Camera2高级特性:手动对焦、手动曝光、ISO控制、白平衡调节、AE/AWB Lock

各位同学,欢迎来到Camera2的高级特性章节。

说实话,前面我们讲的那些基础操作,比如打开摄像头、预览画面、拍照,其实只是热身。真正让Camera2变得强大的,是它给了你一把“手术刀”——你可以像专业摄影师一样,精细控制相机的每一个参数。

我个人习惯把这一章叫做“手动模式实战”。因为从这章开始,你不再是那个只会按快门的程序员,而是真正开始理解“光”和“影”的工程师。

核心知识点一览:

手动对焦、手动曝光、ISO控制、白平衡调节、AE/AWB Lock。这五个能力,是Camera2区别于Camera1的最大卖点。

Camera2 高级控制 手动对焦 AF_MODE_OFF + 焦距值 手动曝光 曝光时间 + 感光度 ISO控制 SENSOR_SENSITIVITY 白平衡调节 CONTROL_AWB_MODE AE/AWB Lock 锁定曝光/白平衡 💡 核心逻辑:CaptureRequest 是一切控制的入口 通过 CaptureRequest.Builder 设置不同 Key 每个 Key 对应一个硬件控制单元 设置完成后提交到 CameraCaptureSession ⚠️ 注意:并非所有设备都支持全部手动控制

1. 手动对焦:让画面按你的意思来

自动对焦很方便,但有时候它很“自作聪明”。

比如拍微距的时候,镜头老是对着背景跑。或者拍视频时,焦点忽远忽近地抽风。这时候,手动对焦就是你的救星。

我的经验:有一次做扫码项目,自动对焦总是对不准条码的细纹。我干脆把对焦锁死在一个固定距离,识别率反而从70%飙到了95%。

手动对焦的核心就两步:

  1. 把对焦模式设为 AF_MODE_OFF
  2. 设置 LENS_FOCUS_DISTANCE 的值

看代码:

// 关闭自动对焦
captureRequestBuilder.set(
    CaptureRequest.CONTROL_AF_MODE,
    CaptureRequest.CONTROL_AF_MODE_OFF
);

// 设置对焦距离,单位是屈光度(1/米)
// 比如 0.5 表示对焦在 2 米处
captureRequestBuilder.set(
    CaptureRequest.LENS_FOCUS_DISTANCE,
    0.5f
);

嗯,这里要注意:LENS_FOCUS_DISTANCE 的值范围是 0 到最大焦距。0 代表无穷远,数值越大对焦越近。你可以通过 LENS_INFO_MINIMUM_FOCUS_DISTANCE 拿到设备支持的最小对焦距离。

避坑指南:我曾经在一台低端平板上测试,发现设置手动对焦后画面反而模糊了。查了半天,原来是那台设备的 AF_MODE_OFF 不支持手动设置焦距。所以,记得先检查 LENS_INFO_AVAILABLE_FOCUS_DISTANCES 这个参数。

2. 手动曝光:掌控光线的艺术

曝光控制说白了就是两件事:快门速度和感光度(ISO)。

自动曝光在大多数场景下够用,但遇到高反差场景——比如拍窗户外的风景时,自动曝光要么让窗外过曝,要么让室内一片漆黑。

手动曝光的核心参数:

参数 Key 说明
曝光时间 SENSOR_EXPOSURE_TIME 单位纳秒,1秒 = 1_000_000_000 ns
感光度 SENSOR_SENSITIVITY ISO值,如100、200、400

代码示例:

// 先关闭自动曝光
captureRequestBuilder.set(
    CaptureRequest.CONTROL_AE_MODE,
    CaptureRequest.CONTROL_AE_MODE_OFF
);

// 设置曝光时间:1/30秒 ≈ 33毫秒
captureRequestBuilder.set(
    CaptureRequest.SENSOR_EXPOSURE_TIME,
    33_000_000L  // 纳秒
);

// 设置ISO:400
captureRequestBuilder.set(
    CaptureRequest.SENSOR_SENSITIVITY,
    400
);

你想想看,为什么夜景模式能拍得那么亮?其实就是把曝光时间拉长到几秒钟,同时压低ISO来减少噪点。当然,代价就是必须用三脚架,不然手抖一下画面就糊了。

个人建议:手动曝光时,先固定ISO,再调曝光时间。比如拍夜景,ISO先定在100,然后慢慢加曝光时间,直到画面亮度满意为止。这样噪点最少。

3. ISO控制:噪点与亮度的博弈

ISO其实就是传感器对光的敏感度。ISO越高,画面越亮,但噪点也越多。

我记得有一次帮客户做安防摄像头,他们要求在极暗环境下也能看清人脸。自动模式下一团黑,后来我手动把ISO拉到3200,虽然噪点像雪花一样,但至少能认出人脸了。

ISO的可用范围因设备而异:

// 获取ISO范围
Range<Integer> isoRange = characteristics.get(
    CameraCharacteristics.SENSOR_INFO_SENSITIVITY_RANGE
);
// isoRange.getLower() 最小值,通常是100
// isoRange.getUpper() 最大值,可能是3200或6400

小技巧:如果你想让画面干净,ISO尽量控制在800以下。超过1600,大部分手机都会出现明显噪点。当然,旗舰机除外——它们的算法确实牛。

4. 白平衡调节:还原真实色彩

白平衡是什么?说白了就是让白色物体在各种光线下看起来都是白色的。

日光灯下偏蓝,白炽灯下偏黄。自动白平衡(AWB)大多数时候能搞定,但遇到混合光源——比如室内既有日光灯又有窗户光——它就懵了。

Camera2提供了预设的白平衡模式:

模式 常量 适用场景
自动 CONTROL_AWB_MODE_AUTO 日常拍摄
日光 CONTROL_AWB_MODE_DAYLIGHT 户外晴天
阴天 CONTROL_AWB_MODE_CLOUDY_DAYLIGHT 阴天或黄昏
白炽灯 CONTROL_AWB_MODE_INCANDESCENT 室内暖光
荧光灯 CONTROL_AWB_MODE_FLUORESCENT 办公室冷光

设置方式很简单:

captureRequestBuilder.set(
    CaptureRequest.CONTROL_AWB_MODE,
    CaptureRequest.CONTROL_AWB_MODE_DAYLIGHT
);

曾经踩过的坑:有一次我在室内拍产品照片,用了自动白平衡,结果拍出来的产品颜色偏蓝。客户说“这颜色不对啊”。后来我手动设为白炽灯模式,颜色就准了。所以,做电商拍照类App,一定要给用户手动白平衡的选项。

5. AE/AWB Lock:锁定,别乱动

这个功能特别实用。想象一下这个场景:你在拍视频,镜头从暗处移到亮处。自动曝光会突然变亮,画面闪一下。自动白平衡也会跟着变,颜色突然偏一下。

这种“闪烁”在视频里非常明显,很影响观感。

AE Lock 和 AWB Lock 就是用来解决这个问题的。它们分别锁定曝光和白平衡,不让系统自动调整。

// 锁定自动曝光
captureRequestBuilder.set(
    CaptureRequest.CONTROL_AE_LOCK,
    true
);

// 锁定自动白平衡
captureRequestBuilder.set(
    CaptureRequest.CONTROL_AWB_LOCK,
    true
);

什么时候用?我个人习惯是:

  • 拍视频时:先让相机自动对好焦和曝光,然后锁定。这样画面就不会忽明忽暗。
  • 拍全景图时:锁定曝光和白平衡,保证每张照片的亮度和颜色一致,拼接起来才自然。
  • 做扫码或OCR时:锁定参数,保证每帧画面的处理条件一致。

核心要点:AE Lock 和 AWB Lock 是独立的。你可以只锁曝光不锁白平衡,也可以两个都锁。但要注意,如果 AE 模式是 OFF(手动曝光),那 AE Lock 就没意义了。

实战组合:一个完整的手动控制示例

说了这么多,我们来写一个完整的手动控制流程。假设我们要拍一张夜景照片:

// 1. 创建请求
CaptureRequest.Builder builder = cameraDevice.createCaptureRequest(
    CameraDevice.TEMPLATE_STILL_CAPTURE
);

// 2. 关闭自动对焦,手动对焦到无穷远
builder.set(CaptureRequest.CONTROL_AF_MODE,
    CaptureRequest.CONTROL_AF_MODE_OFF);
builder.set(CaptureRequest.LENS_FOCUS_DISTANCE, 0f);

// 3. 关闭自动曝光,手动设置
builder.set(CaptureRequest.CONTROL_AE_MODE,
    CaptureRequest.CONTROL_AE_MODE_OFF);
builder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, 500_000_000L); // 0.5秒
builder.set(CaptureRequest.SENSOR_SENSITIVITY, 200); // ISO 200

// 4. 设置白平衡为日光模式
builder.set(CaptureRequest.CONTROL_AWB_MODE,
    CaptureRequest.CONTROL_AWB_MODE_DAYLIGHT);

// 5. 锁定曝光和白平衡(虽然手动模式下锁不锁都一样)
builder.set(CaptureRequest.CONTROL_AE_LOCK, true);
builder.set(CaptureRequest.CONTROL_AWB_LOCK, true);

// 6. 提交请求
session.capture(builder.build(), callback, handler);

你看,整个流程其实很清晰。先关自动,再设手动,最后提交。Camera2的设计哲学就是这样——给你最大的控制权,但也要求你负起全部责任。

最后说一句:这些高级特性不是所有设备都支持。发布App前,一定要用 CameraCharacteristics 检查一下可用性。不然用户打开你的App,发现手动对焦没反应,那体验就糟糕了。

好了,这一章的内容就到这里。手动控制是Camera2的精髓,掌握了这些,你就能做出真正有“专业感”的相机应用。下一章我们会聊更进阶的话题,但先把今天这些代码跑通,你会发现自己对相机的理解又上了一个台阶。


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