9. 照片参数控制:设置照片尺寸、调整ISO与曝光时间、白平衡与对焦模式

各位同学,今天我们来聊聊拍照参数控制。说实话,这部分内容在视频采集课程里经常被忽略——很多人觉得“反正我要的是视频流,拍照参数随便设设就行了”。但我在实际项目中踩过不少坑,比如拍出来的照片要么过曝、要么偏色严重,最后发现是参数没调对。

嗯,咱们今天就把这些参数一个一个说清楚。

9.1 照片尺寸:不是越大越好

照片尺寸,说白了就是分辨率。Android Camera2 API 里用 Size 类来表示。你可能会想:“分辨率越高越好啊,反正我存下来还能裁剪。” 但这里有个坑——高分辨率意味着更大的数据量,处理时间更长,内存占用也更高

我在一个实时拍照+人脸识别的项目里,一开始用了 4000x3000 的分辨率,结果每拍一张照片要卡顿 2 秒。后来降到 1920x1080,流畅多了,识别率也没下降。

核心原则: 照片尺寸 = 够用就好。如果是打印输出,选最大;如果是屏幕展示或上传服务器,选 1080p 或 720p 就够了。

获取支持的尺寸列表:

StreamConfigurationMap map = cameraCharacteristics.get(
    CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
Size[] outputSizes = map.getOutputSizes(ImageFormat.JPEG);
// 遍历 outputSizes,找到最合适的尺寸

设置照片尺寸时,记得通过 CaptureRequest.Builderset 方法:

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);
注意: 不是所有设备都支持手动设置曝光时间和 ISO。你需要先检查 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 知识体系总览

下面这张图总结了照片参数控制的整体逻辑:

照片参数控制 照片尺寸 ImageReader 指定 JPEG 质量/方向 ISO & 曝光时间 SENSOR_EXPOSURE_TIME SENSOR_SENSITIVITY 白平衡 AWB 模式 色温/增益 对焦模式 AF_MODE LENS_FOCUS_DISTANCE 四个参数相互独立,但共同决定最终照片质量 建议:先调曝光时间 → 再调 ISO → 最后调白平衡

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,就老老实实用自动模式。

好了,照片参数控制这部分就讲到这里。记住一个原则:参数是死的,场景是活的。多在实际设备上测试,找到最适合你应用场景的那组参数。


公众号:蓝海资料掘金营,微信deep3321