3、Camera2高级特性:曝光控制、对焦模式、白平衡、HDR模式、多摄像头切换
各位同学,咱们今天聊点硬核的。Camera2 的高级特性,说白了就是让你真正「控制」摄像头,而不是被摄像头控制。我刚开始接触 Camera2 时,也被那一堆参数搞得头大,但后来发现,只要你理解了核心逻辑,其实就那么几件事:曝光、对焦、色彩、动态范围,以及——选哪个镜头干活。
嗯,咱们一个一个来拆。
3.1 曝光控制:让画面亮暗由你说了算
曝光控制,说白了就是控制进光量。Camera2 里,曝光由三个参数决定:曝光时间、感光度(ISO)、光圈。不过大多数手机光圈是固定的,所以我们主要折腾前两个。
核心 API:
CaptureRequest.CONTROL_AE_MODE—— 自动曝光模式CaptureRequest.SENSOR_EXPOSURE_TIME—— 曝光时间(纳秒)CaptureRequest.SENSOR_SENSITIVITY—— ISO 值
我个人习惯,在需要手动控制曝光时,先把 AE 模式设为 AE_MODE_OFF,然后自己设置曝光时间和 ISO。举个例子,拍夜景时,我会把曝光时间拉到 1/30 秒,ISO 控制在 800 以内,这样画面干净又不至于糊掉。
// 关闭自动曝光,手动控制
captureRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE,
CaptureRequest.CONTROL_AE_MODE_OFF);
captureRequestBuilder.set(CaptureRequest.SENSOR_EXPOSURE_TIME,
TimeUnit.SECONDS.toNanos(1L / 30)); // 1/30 秒
captureRequestBuilder.set(CaptureRequest.SENSOR_SENSITIVITY,
800); // ISO 800
小技巧:曝光时间单位是纳秒,别直接写 30000000 这种数字,用 TimeUnit 转换,代码可读性高很多。
我在项目中遇到过一个问题:手动设置曝光后,画面闪烁。后来发现是没关掉 AE 的防闪烁模式。嗯,这里要注意,手动模式下,最好把 CONTROL_AE_ANTIBANDING_MODE 也设成 OFF,否则系统会偷偷干预你的曝光参数。
3.2 对焦模式:从「拍清楚」到「拍你想拍的」
对焦这件事,Camera2 给了你三种选择:自动对焦、连续自动对焦、手动对焦。你想想看,拍静态场景用连续对焦,反而会来回拉风箱,浪费性能。
| 模式 | 适用场景 | API 常量 |
|---|---|---|
| 自动对焦(单次) | 拍照、扫码 | CONTROL_AF_MODE_AUTO |
| 连续自动对焦 | 视频录制、运动物体 | CONTROL_AF_MODE_CONTINUOUS_VIDEO |
| 手动对焦 | 微距、特殊效果 | CONTROL_AF_MODE_OFF + LENS_FOCUS_DISTANCE |
我曾经在做一个扫码项目时,发现二维码总是对不上焦。排查了半天,原来是默认用了连续对焦模式,扫码时镜头一直在微调。改成单次自动对焦后,问题立刻解决。所以,选对模式比调参数更重要。
// 设置连续自动对焦(适合视频)
captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_VIDEO);
// 手动对焦:先关掉自动对焦,再设置距离
captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_OFF);
captureRequestBuilder.set(CaptureRequest.LENS_FOCUS_DISTANCE,
0.0f); // 0.0 表示无限远,数值越大对焦越近
注意:手动对焦时,LENS_FOCUS_DISTANCE 的单位是「屈光度」(1/米),不是厘米。0.0 是无限远,10.0 大约是 10 厘米。别设成负数,会 crash。
3.3 白平衡:别让画面「偏色」
白平衡,说白了就是告诉相机「什么是白色」。Camera2 提供了预设模式,也支持手动调节色温。我个人建议,室内灯光下用 WHITE_BALANCE_INCANDESCENT,日光下用 WHITE_BALANCE_DAYLIGHT,省心。
但如果你追求极致,可以手动设置色温值。色温的单位是开尔文(K),日光大约是 5500K,白炽灯大约是 3000K。
// 使用预设模式
captureRequestBuilder.set(CaptureRequest.CONTROL_AWB_MODE,
CaptureRequest.CONTROL_AWB_MODE_DAYLIGHT);
// 手动色温(需要先关掉自动白平衡)
captureRequestBuilder.set(CaptureRequest.CONTROL_AWB_MODE,
CaptureRequest.CONTROL_AWB_MODE_OFF);
captureRequestBuilder.set(CaptureRequest.COLOR_CORRECTION_MODE,
CaptureRequest.COLOR_CORRECTION_MODE_TRANSFORM_MATRIX);
captureRequestBuilder.set(CaptureRequest.COLOR_CORRECTION_GAINS,
new RggbChannelVector(1.5f, 1.0f, 1.0f, 1.8f)); // RGGB 增益
避坑指南:我曾经在录视频时,发现画面颜色突然跳变。原因是自动白平衡在场景切换时重新计算了色温。解决方案很简单:录制前锁定白平衡模式,用 AWB_MODE_DAYLIGHT 或手动设置,别用 AWB_MODE_AUTO。
3.4 HDR模式:高动态范围的「魔法」
HDR 模式,就是拍多张不同曝光的照片,然后合成一张亮部和暗部都清晰的图片。Camera2 里,HDR 通常通过 CONTROL_SCENE_MODE_HDR 或 CONTROL_EFFECT_MODE 来开启。
但说实话,我很少用系统自带的 HDR 模式。为什么?因为它的处理流程是黑盒,你没法控制合成参数。我更推荐自己实现多帧合成:拍三张(欠曝、正常、过曝),然后用 OpenGL 或 RenderScript 合成。这样灵活度更高。
// 开启系统 HDR(如果设备支持)
if (isHdrSupported(characteristics)) {
captureRequestBuilder.set(CaptureRequest.CONTROL_SCENE_MODE,
CaptureRequest.CONTROL_SCENE_MODE_HDR);
}
重要:不是所有设备都支持 HDR 模式。一定要先通过 CameraCharacteristics.SCENE_MODE_AVAILABLE 检查,否则会抛出异常。我在项目里吃过这个亏,上线后一堆 crash 报告。
3.5 多摄像头切换:选对镜头,事半功倍
现在的手机,少则两个摄像头,多则四五个。Camera2 通过 CameraManager.getCameraIdList() 获取所有摄像头 ID,然后根据 CameraCharacteristics.LENS_FACING 区分前后置,根据 CameraCharacteristics.FOCAL_LENGTH 区分广角、长焦。
我建议你在应用启动时,先枚举所有摄像头,建立一张「摄像头能力表」。这样用户切换时,你就能快速找到合适的镜头。
// 枚举所有摄像头
CameraManager manager = (CameraManager) getSystemService(CAMERA_SERVICE);
for (String cameraId : manager.getCameraIdList()) {
CameraCharacteristics chars = manager.getCameraCharacteristics(cameraId);
Integer facing = chars.get(CameraCharacteristics.LENS_FACING);
float[] focalLengths = chars.get(CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS);
// 根据 facing 和 focalLengths 判断是广角还是长焦
}
注意:切换摄像头时,必须先关闭当前 CameraCaptureSession,再打开新的。直接复用 session 会导致崩溃。我曾经在直播项目里踩过这个坑,画面卡死,用户骂声一片。
3.6 知识体系总览
说了这么多,咱们用一张图把核心逻辑串起来。你想想看,Camera2 的高级特性,其实就围绕三个维度:曝光(亮暗)、对焦(清晰度)、色彩(白平衡 + HDR),再加上硬件选择(多摄像头)。
这张图把咱们今天讲的内容都串起来了。你想想看,曝光、对焦、白平衡、HDR、多摄像头,这五个点其实互相关联。比如你切换了摄像头,曝光参数可能需要重新调整;你开了 HDR,对焦模式最好用单次自动对焦,避免合成时画面模糊。
好了,这一章的内容就到这里。记住,Camera2 的高级特性不是让你炫技的,而是让你在真实场景中解决问题。多动手,多踩坑,你才能真正掌握它。