Android Camera2 实战:全屏预览与实时帧处理全解析
2025.09.19 11:23浏览量:22简介:本文深入解析Android Camera2 API实现全屏预览与实时获取预览帧进行图像处理的技术要点,涵盖配置优化、帧捕获机制及图像处理流程,助力开发者构建高性能相机应用。
一、Camera2 API 基础与优势
Camera2 API 是 Android 5.0(API 21)引入的全新相机接口,相比已废弃的 Camera1 API,其核心优势在于更精细的控制能力和更低的延迟。Camera2 将相机操作拆解为多个可配置的请求(CaptureRequest),开发者能独立控制对焦、曝光、白平衡等参数,同时支持多摄像头同步和动态分辨率调整。
在全屏预览场景中,Camera2 的输出目标(Surface)配置机制尤为关键。通过将预览 Surface 设置为与屏幕分辨率匹配的 TextureView 或 SurfaceView,可避免画面拉伸或黑边。例如,在配置预览请求时,需明确指定输出尺寸:
// 创建预览用的Surface
TextureView textureView = findViewById(R.id.texture_view);
SurfaceTexture surfaceTexture = textureView.getSurfaceTexture();
surfaceTexture.setDefaultBufferSize(previewWidth, previewHeight);
Surface previewSurface = new Surface(surfaceTexture);
// 配置CaptureRequest.Builder
CaptureRequest.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
方法,动态调整预览方向:
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
int rotation = getWindowManager().getDefaultDisplay().getRotation();
cameraDevice.createCaptureSession(Arrays.asList(previewSurface),
new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
// 根据旋转角度更新预览请求
}
}, backgroundHandler);
}
三、实时获取预览帧的机制
1. ImageReader 的配置与使用
通过 ImageReader
捕获预览帧是实时处理的关键。需配置与预览尺寸相同的 ImageFormat.YUV_420_888
格式,并设置最大图像数:
ImageReader imageReader = ImageReader.newInstance(
previewWidth, previewHeight,
ImageFormat.YUV_420_888,
2 // 缓冲区数量
);
// 添加到CaptureRequest
previewBuilder.addTarget(imageReader.getSurface());
2. 帧到达回调处理
通过 ImageReader.OnImageAvailableListener
接收帧数据,转换为可处理的 Image
对象:
imageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
@Override
public 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-30FPS
previewBuilder.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)持续优化。
发表评论
登录后可评论,请前往 登录 或 注册