Android Camera2 实战:全屏预览与实时帧处理全解析
2025.09.19 11:23浏览量:203简介:本文深入解析Android Camera2 API实现全屏预览与实时获取预览帧进行图像处理的技术要点,涵盖配置优化、帧捕获机制及图像处理流程,助力开发者构建高性能相机应用。
一、Camera2 API 基础与优势
Camera2 API 是 Android 5.0(API 21)引入的全新相机接口,相比已废弃的 Camera1 API,其核心优势在于更精细的控制能力和更低的延迟。Camera2 将相机操作拆解为多个可配置的请求(CaptureRequest),开发者能独立控制对焦、曝光、白平衡等参数,同时支持多摄像头同步和动态分辨率调整。
在全屏预览场景中,Camera2 的输出目标(Surface)配置机制尤为关键。通过将预览 Surface 设置为与屏幕分辨率匹配的 TextureView 或 SurfaceView,可避免画面拉伸或黑边。例如,在配置预览请求时,需明确指定输出尺寸:
// 创建预览用的SurfaceTextureView textureView = findViewById(R.id.texture_view);SurfaceTexture surfaceTexture = textureView.getSurfaceTexture();surfaceTexture.setDefaultBufferSize(previewWidth, previewHeight);Surface previewSurface = new Surface(surfaceTexture);// 配置CaptureRequest.BuilderCaptureRequest.Builder previewBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);previewBuilder.addTarget(previewSurface); // 绑定预览Surface
二、全屏预览的实现要点
1. 屏幕适配与分辨率匹配
全屏预览的核心是确保相机输出的图像比例与设备屏幕比例一致。需通过 CameraCharacteristics 获取相机支持的分辨率列表,并筛选出与屏幕宽高比最接近的尺寸:
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);Size[] previewSizes = map.getOutputSizes(SurfaceTexture.class);// 根据屏幕宽高比筛选最优尺寸Size optimalSize = findOptimalPreviewSize(previewSizes, screenWidth, screenHeight);
2. 自动对焦与曝光控制
为提升预览体验,需配置持续自动对焦(CONTINUOUS_PICTURE)和自动曝光:
previewBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);previewBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON);
3. 横竖屏切换处理
通过监听 TextureView.SurfaceTextureListener 的 onSurfaceTextureSizeChanged 方法,动态调整预览方向:
@Overridepublic void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {int rotation = getWindowManager().getDefaultDisplay().getRotation();cameraDevice.createCaptureSession(Arrays.asList(previewSurface),new CameraCaptureSession.StateCallback() {@Overridepublic void onConfigured(@NonNull CameraCaptureSession session) {// 根据旋转角度更新预览请求}}, backgroundHandler);}
三、实时获取预览帧的机制
1. ImageReader 的配置与使用
通过 ImageReader 捕获预览帧是实时处理的关键。需配置与预览尺寸相同的 ImageFormat.YUV_420_888 格式,并设置最大图像数:
ImageReader imageReader = ImageReader.newInstance(previewWidth, previewHeight,ImageFormat.YUV_420_888,2 // 缓冲区数量);// 添加到CaptureRequestpreviewBuilder.addTarget(imageReader.getSurface());
2. 帧到达回调处理
通过 ImageReader.OnImageAvailableListener 接收帧数据,转换为可处理的 Image 对象:
imageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {@Overridepublic void onImageAvailable(ImageReader reader) {Image image = reader.acquireLatestImage();if (image != null) {processImage(image); // 自定义处理逻辑image.close();}}}, backgroundHandler);
3. YUV 数据转换与处理
原始 YUV 数据需转换为 RGB 或 Bitmap 进行算法处理。以下示例展示 YUV420 到 RGB 的转换:
private void yuvToRgb(Image image) {Image.Plane[] planes = image.getPlanes();ByteBuffer yBuffer = planes[0].getBuffer();ByteBuffer uBuffer = planes[1].getBuffer();ByteBuffer vBuffer = planes[2].getBuffer();int ySize = yBuffer.remaining();int uSize = uBuffer.remaining();int vSize = vBuffer.remaining();byte[] yData = new byte[ySize];byte[] uData = new byte[uSize];byte[] vData = new byte[vSize];yBuffer.get(yData);uBuffer.get(uData);vBuffer.get(vData);// 使用RenderScript或OpenCV进行YUV到RGB转换// 示例省略具体转换代码}
四、图像处理流水线优化
1. 异步处理架构
为避免阻塞相机线程,需将图像处理放在独立线程:
ExecutorService executor = Executors.newSingleThreadExecutor();private void processImage(Image image) {executor.execute(() -> {// 1. YUV转换// 2. 应用图像处理算法(如美颜、滤镜)// 3. 显示或保存结果});}
2. 性能关键点
- 减少内存拷贝:直接操作
Image的ByteBuffer,避免byte[]转换。 - 降低分辨率:对实时性要求高的场景,可降低处理分辨率。
- 算法优化:使用 RenderScript 或 NDK 加速计算密集型操作。
3. 帧率控制
通过 CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE 限制帧率,平衡性能与功耗:
Range<Integer> fpsRange = new Range<>(15, 30); // 15-30FPSpreviewBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, fpsRange);
五、常见问题与解决方案
1. 预览卡顿
- 原因:UI线程阻塞或处理耗时过长。
- 解决:将所有图像处理移至后台线程,使用
HandlerThread管理。
2. 内存泄漏
- 原因:未关闭
Image或Surface。 - 解决:在
onImageAvailable中确保调用image.close(),并在onPause中释放ImageReader。
3. 权限问题
- 动态权限:Android 6.0+ 需请求
CAMERA和WRITE_EXTERNAL_STORAGE。 - 运行时检查:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)!= PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA);}
六、进阶优化方向
- 多摄像头同步:通过
CameraManager同时打开前后摄像头。 - HEIF 格式支持:使用
ImageFormat.HEIC减少存储占用。 - 机器学习集成:结合 ML Kit 或 TensorFlow Lite 实现实时人脸检测。
通过系统掌握 Camera2 的全屏预览与帧捕获机制,开发者能够构建出流畅、低延迟的相机应用,为图像处理、AR 等场景提供坚实基础。实际开发中需结合设备兼容性测试(如使用 Camera2Compat 库)和性能监控工具(如 Android Profiler)持续优化。

发表评论
登录后可评论,请前往 登录 或 注册