9. 照片参数控制:设置照片尺寸、调整ISO与曝光时间、白平衡与对焦模式
各位同学,今天我们来聊聊拍照参数控制。说实话,这部分内容在视频采集课程里经常被忽略——很多人觉得“反正我要的是视频流,拍照参数随便设设就行了”。但我在实际项目中踩过不少坑,比如拍出来的照片要么过曝、要么偏色严重,最后发现是参数没调对。
嗯,咱们今天就把这些参数一个一个说清楚。
9.1 照片尺寸:不是越大越好
照片尺寸,说白了就是分辨率。Android Camera2 API 里用 Size 类来表示。你可能会想:“分辨率越高越好啊,反正我存下来还能裁剪。” 但这里有个坑——高分辨率意味着更大的数据量,处理时间更长,内存占用也更高。
我在一个实时拍照+人脸识别的项目里,一开始用了 4000x3000 的分辨率,结果每拍一张照片要卡顿 2 秒。后来降到 1920x1080,流畅多了,识别率也没下降。
获取支持的尺寸列表:
StreamConfigurationMap map = cameraCharacteristics.get(
CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
Size[] outputSizes = map.getOutputSizes(ImageFormat.JPEG);
// 遍历 outputSizes,找到最合适的尺寸
设置照片尺寸时,记得通过 CaptureRequest.Builder 的 set 方法:
captureRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION, orientation);
captureRequestBuilder.set(CaptureRequest.JPEG_QUALITY, (byte) 95);
// 尺寸在创建 CaptureRequest 时通过 Surface 决定,不是直接 set 的
这里有个容易混淆的地方:照片尺寸其实是在创建 ImageReader 时指定的,而不是在 CaptureRequest 里设。CaptureRequest 里只能设 JPEG 质量和方向。
9.2 ISO 与曝光时间:光线的平衡术
ISO 和曝光时间,这两个参数是“相爱相杀”的关系。ISO 越高,画面越亮但噪点越多;曝光时间越长,画面越亮但容易手抖模糊。
我个人习惯的调参顺序是:先固定曝光时间,再调 ISO。为什么?因为曝光时间直接影响画面是否“糊掉”,而 ISO 的噪点后期还能降一降。
| 场景 | 推荐曝光时间 | 推荐 ISO |
|---|---|---|
| 白天户外 | 1/1000s ~ 1/500s | 100 ~ 200 |
| 室内灯光 | 1/60s ~ 1/30s | 400 ~ 800 |
| 暗光环境 | 1/15s ~ 1/4s | 1600 ~ 3200 |
设置代码:
// 设置曝光时间(单位:纳秒)
captureRequestBuilder.set(CaptureRequest.SENSOR_EXPOSURE_TIME,
TimeUnit.MILLISECONDS.toNanos(30)); // 30ms
// 设置 ISO
captureRequestBuilder.set(CaptureRequest.SENSOR_SENSITIVITY, 400);
CONTROL_AE_MODE 是否支持 OFF 模式。如果不支持,你只能通过 AE 补偿来间接控制。
我曾经在一个低端平板上做项目,发现设置曝光时间后完全没效果。查了半天文档,才发现那个设备的传感器根本不支持手动曝光——白忙活一场。
9.3 白平衡:让白色真正是白色
白平衡,说白了就是让相机知道“什么是白色”。不同光源下,白色物体的颜色会偏蓝或偏黄。白平衡就是纠正这个偏差。
Android Camera2 提供了几种预设模式:
WHITE_BALANCE_AUTO:自动模式,大多数场景够用WHITE_BALANCE_INCANDESCENT:白炽灯(偏黄)WHITE_BALANCE_FLUORESCENT:荧光灯(偏绿)WHITE_BALANCE_DAYLIGHT:日光(偏蓝)WHITE_BALANCE_CLOUDY_DAYLIGHT:阴天
设置代码:
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.0f, 1.0f, 1.0f, 1.0f));
9.4 对焦模式:快准稳
对焦模式决定了相机如何找到焦点。Android Camera2 支持多种对焦模式:
CONTROL_AF_MODE_AUTO:单次自动对焦,拍完就锁定CONTROL_AF_MODE_CONTINUOUS_PICTURE:连续自动对焦,适合拍照CONTROL_AF_MODE_CONTINUOUS_VIDEO:连续自动对焦,适合视频CONTROL_AF_MODE_MACRO:微距模式CONTROL_AF_MODE_OFF:手动对焦
我个人最常用的是 CONTINUOUS_PICTURE 模式。它在拍照前会持续调整焦点,按下快门时基本已经对好了。
captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
如果你需要手动对焦(比如拍微距),可以这样:
// 关闭自动对焦
captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_OFF);
// 设置对焦距离(0.0f 到 1.0f,0 是最近,1 是最远)
captureRequestBuilder.set(CaptureRequest.LENS_FOCUS_DISTANCE, 0.5f);
LENS_FOCUS_DISTANCE。有些廉价设备压根不支持手动对焦,你设了也没用。
9.5 知识体系总览
下面这张图总结了照片参数控制的整体逻辑:
9.6 综合示例:手动模式拍照
最后,咱们把上面所有参数串起来,写一个完整的手动模式拍照示例:
private void setupManualCapture(CaptureRequest.Builder builder) {
// 1. 关闭自动曝光
builder.set(CaptureRequest.CONTROL_AE_MODE,
CaptureRequest.CONTROL_AE_MODE_OFF);
// 2. 设置曝光时间 30ms
builder.set(CaptureRequest.SENSOR_EXPOSURE_TIME,
TimeUnit.MILLISECONDS.toNanos(30));
// 3. 设置 ISO 400
builder.set(CaptureRequest.SENSOR_SENSITIVITY, 400);
// 4. 关闭自动白平衡,设为日光模式
builder.set(CaptureRequest.CONTROL_AWB_MODE,
CaptureRequest.CONTROL_AWB_MODE_DAYLIGHT);
// 5. 设置连续对焦
builder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
// 6. JPEG 质量 95%
builder.set(CaptureRequest.JPEG_QUALITY, (byte) 95);
}
AE_MODE_OFF。结果在部分设备上直接崩溃。后来我加了一段检查代码:int[] aeModes = characteristics.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES);如果列表里没有
OFF,就老老实实用自动模式。
好了,照片参数控制这部分就讲到这里。记住一个原则:参数是死的,场景是活的。多在实际设备上测试,找到最适合你应用场景的那组参数。