3、自动曝光算法(AE):18%灰板原理、平均测光、中央重点测光、点测光
自动曝光,说白了就是让相机自己决定「拍多亮」。你按下快门,它帮你算光圈、快门、ISO。但这里有个灵魂拷问:相机怎么知道「正常亮度」是什么?
答案就是——18%灰板。搞懂这个,AE算法才算入门。
3.1 18%灰板原理:相机眼中的「标准灰」
先讲个故事。我早年做手机相机调试时,发现一个怪现象:拍雪景,画面总是灰蒙蒙的;拍黑煤堆,画面又亮得发白。后来才明白,相机默认把整个世界都当成「18%灰」来曝光。
18%灰板,就是一块反射率恰好为18%的灰色卡纸。在摄影界,它被当作「中间灰」的标准。相机测光系统以它为基准:
- 场景亮度 = 18%灰 → 曝光正确
- 场景亮度 > 18%灰 → 相机认为「太亮」,自动压暗
- 场景亮度 < 18%灰 → 相机认为「太暗」,自动提亮
核心结论:所有自动曝光算法,本质上都是在「把场景平均亮度映射到18%灰」。这是AE的底层逻辑。
你想想看,如果场景里全是白墙,相机硬把它压成18%灰,白墙就变灰墙了。这就是「曝光补偿」存在的意义——告诉相机:「喂,这场景不是18%灰,你得加一档!」
3.2 平均测光:最朴素的「全局平均」
平均测光,就是把整个画面所有像素的亮度加起来,取个平均值。然后拿这个平均值去跟18%灰比。
公式很简单:
L_avg = (1/N) * Σ L(i, j)
target_exposure = L_18 / L_avg * current_exposure
其中 L_18 是18%灰对应的亮度值。
我做过一个实验:用平均测光拍一张「半边亮半边暗」的场景。结果呢?亮部过曝,暗部欠曝。因为平均测光不会区分「哪里重要」。
| 测光模式 | 权重策略 | 适用场景 | 我的评价 |
|---|---|---|---|
| 平均测光 | 全图等权 | 光照均匀的场景 | 简单但容易翻车 |
| 中央重点 | 中心权重高 | 人像、主体居中 | 比较实用 |
| 点测光 | 单点权重100% | 逆光、高反差 | 精准但需要技巧 |
避坑指南:我曾经在夜景模式下用平均测光,结果画面整体偏亮,噪点爆炸。后来改成点测光对焦暗部,才压住曝光。平均测光对「大面积亮区」特别敏感,拍夜景时慎用。
3.3 中央重点测光:给画面中心「开小灶」
平均测光的问题在于:它不知道你关注哪里。大部分时候,主体都在画面中央。所以中央重点测光就出现了——给中心区域更高的权重。
权重分布通常是这样的:
L_weighted = (W_center * L_center + W_surround * L_surround) / (W_center + W_surround)
常见的权重比例:中心60%~80%,边缘20%~40%。具体比例各家厂商不一样,但思路一致:中心说了算,边缘做参考。
我个人习惯在拍人像时用中央重点测光。人脸通常在画面中央,这样肤色曝光比较准。但要注意:如果主体不在中心,比如三分法构图,中央重点反而会出错。
小技巧:很多相机支持「对焦联动测光」——对焦点在哪,中央重点的中心就移到哪。这比固定中心灵活得多。我在项目中经常用这个模式,省去重新构图的麻烦。
3.4 点测光:指哪打哪的「狙击手」
点测光就狠了。它只取画面中一个极小区域(通常1%~5%的面积)来计算曝光。其他区域?不管。
为什么需要这么极端的模式?因为有些场景反差太大,平均或中央重点都搞不定。比如:
- 逆光人像:人脸暗、背景亮
- 舞台灯光:主体亮、周围黑
- 夜景灯牌:局部高亮、整体黑暗
点测光的核心用法:对你想正确曝光的位置测光。比如逆光时,对人脸点测光,人脸就正常了,背景过曝就过曝吧——总比人脸死黑强。
我记得有一次做车载摄像头AE调试,遇到一个极端场景:隧道出口。洞口亮到爆,洞内暗到死。平均测光直接废了,中央重点也不行。最后用点测光锁定洞口边缘区域,才拿到可用的曝光参数。
3.5 三种测光模式的对比与选择
直接上对比表,方便你快速决策:
| 场景类型 | 推荐模式 | 原因 |
|---|---|---|
| 风景、光照均匀 | 平均测光 | 简单高效,不容易出错 |
| 人像、主体居中 | 中央重点 | 中心权重高,肤色准 |
| 逆光、高反差 | 点测光 | 精准控制关键区域 |
| 运动、快速抓拍 | 中央重点 | 平衡速度与精度 |
| 夜景、灯光复杂 | 点测光 | 避免大面积暗区干扰 |
我的建议:新手先从中央重点测光开始。它比平均测光聪明,又比点测光宽容。等你能预判「这个场景哪里最重要」了,再上点测光。
3.6 从理论到代码:一个简单的AE实现
说了这么多,来点实际的。下面是一个简化版的AE算法实现,支持三种测光模式:
def auto_exposure(image, mode='center_weighted', target_luminance=0.18):
"""
自动曝光算法
:param image: 输入图像 (H, W, 3)
:param mode: 'average', 'center_weighted', 'spot'
:param target_luminance: 目标亮度(18%灰)
:return: 曝光补偿系数
"""
# 转灰度
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
h, w = gray.shape
if mode == 'average':
# 平均测光:全图等权
current_luminance = np.mean(gray)
elif mode == 'center_weighted':
# 中央重点:中心区域权重0.7,边缘0.3
center_h, center_w = h // 2, w // 2
center_region = gray[center_h-50:center_h+50, center_w-50:center_w+50]
center_lum = np.mean(center_region)
edge_lum = (np.sum(gray) - np.sum(center_region)) / (h*w - 100*100)
current_luminance = 0.7 * center_lum + 0.3 * edge_lum
elif mode == 'spot':
# 点测光:只取中心1%区域
spot_size = int(np.sqrt(0.01 * h * w))
center_h, center_w = h // 2, w // 2
spot_region = gray[center_h-spot_size//2:center_h+spot_size//2,
center_w-spot_size//2:center_w+spot_size//2]
current_luminance = np.mean(spot_region)
# 计算曝光补偿系数
exposure_gain = target_luminance / (current_luminance + 1e-6)
return exposure_gain
这段代码虽然简单,但核心逻辑跟专业ISP里的AE模块是一样的。你可以在自己的项目里跑跑看,换几张不同场景的图,观察三种模式的差异。
扩展思考:实际产品中的AE比这复杂得多——还要考虑帧率、ISO噪声、运动模糊、闪烁抑制等。但底层逻辑不变:测光 → 算增益 → 调参数。把基础搞扎实,后面加花活就简单了。
3.7 本章知识体系
下面这张图帮你理清三种测光模式的关系和适用边界:
三种模式没有的好坏,只有合不合适。关键是你得知道:当前场景里,哪部分亮度最能代表「正确曝光」。选对了,AE就成功了一半。