3、相机响应函数:CRF 的定义、测量与 HDR 应用
相机响应函数,英文叫 Camera Response Function,简称 CRF。这东西说白了,就是描述「场景中的真实亮度」和「相机像素值」之间映射关系的一条曲线。
你可能会想,这不就是一条 gamma 曲线吗?还真不是。Gamma 只是 CRF 的一个简化近似。真实的 CRF 包含了传感器光电转换、模拟增益、ADC 量化、去马赛克、色调映射等一系列非线性操作。我刚开始做 HDR 时,直接用 gamma 2.2 去反推辐照度,结果合成出来的图像亮部一片死白,暗部全是噪声。后来才明白,不标定 CRF,多帧融合就是空中楼阁。
3.1 CRF 的定义
数学上,CRF 可以写成:
Z = f(E · Δt)
其中:
- Z:像素输出值(0~255 或 0~4095)
- E:场景辐照度(Irradiance)
- Δt:曝光时间
- f(·):相机响应函数,单调递增且非线性
注意,f 是单调递增的,否则会出现亮度反转——亮的变暗,暗的变亮,这在实际相机中不可能发生。但 f 不一定是光滑的,有些相机在低亮区有死区,在高亮区有饱和区。
关键理解:CRF 的逆函数 f⁻¹ 可以把像素值 Z 映射回相对辐照度 E·Δt。这就是 HDR 合成的数学基础。
3.2 CRF 的测量方法
测量 CRF 有两种主流思路:
- 使用均匀光源 + 中性密度滤光片:改变 ND 值,记录像素变化。精度高,但需要专业设备。
- 使用多曝光图像序列:固定场景,改变曝光时间,从多帧中恢复 CRF。这就是 Debevec 和 Robertson 方法的思路。
我个人更推荐第二种,因为它不需要额外硬件,用你手头的相机就能做。我在项目中曾经用一台工业相机,拍了 12 帧不同曝光的灰阶卡,然后用 Debevec 方法标定 CRF,效果相当不错。
3.2.1 多曝光标定流程
| 步骤 | 操作 | 注意事项 |
|---|---|---|
| 1 | 固定相机,拍摄静态场景 | 场景必须完全静止,三脚架固定 |
| 2 | 改变曝光时间,拍摄 N 帧 | 曝光时间覆盖 1/1000s ~ 30s,至少 6 帧 |
| 3 | 选取 P 个采样点 | 选在纹理丰富区域,避开过曝/欠曝 |
| 4 | 构建超定方程组 | 用最小二乘法求解 CRF 和辐照度 |
| 5 | 平滑与插值 | 得到完整的 CRF 曲线 |
小技巧:采样点不要选在纯色区域,否则方程会退化。我习惯选在边缘或纹理密集的地方,这样约束更强,求解更稳定。
3.3 CRF 在 HDR 中的作用
CRF 在 HDR 合成中扮演着「翻译官」的角色。没有它,不同曝光帧的像素值无法直接比较。举个例子:
- 短曝光帧中,像素值 128 可能对应场景中很亮的部分
- 长曝光帧中,像素值 128 可能对应场景中较暗的部分
- 如果不做 CRF 逆映射,直接平均这两个 128,结果毫无意义
CRF 逆映射后,我们把所有帧的像素值统一到「辐照度 × 曝光时间」空间,然后才能进行加权融合。这就是 HDR 合成的核心步骤。
避坑指南:我曾经遇到过一个项目,用手机拍摄的多帧 HDR,直接套用标准 CRF 曲线,结果合成图像偏色严重。后来发现,手机 ISP 在拍照时自动做了白平衡和色调映射,改变了 CRF 形状。所以,每台相机的 CRF 都必须单独标定,不能通用。
3.4 Debevec 与 Robertson 方法
这两种方法都是通过多曝光图像序列来恢复 CRF,但思路略有不同。
3.4.1 Debevec 方法(1997)
Debevec 的方法基于一个假设:CRF 是光滑且单调的。他把问题转化为一个最小二乘优化:
目标函数:O = Σ Σ [w(Z_ij) · (g(Z_ij) - ln(E_i) - ln(Δt_j))]² + λ · Σ [w(Z) · g''(Z)]²
其中:
- g = ln(f⁻¹):逆 CRF 的对数形式
- w(Z):权重函数,中间像素权重大,两端权重小
- λ:光滑性约束系数
- g'':二阶导数,强制曲线光滑
这个优化可以分解为两个交替步骤:
- 固定 CRF,求解每个采样点的辐照度 E_i
- 固定辐照度,更新 CRF 曲线 g
迭代直到收敛。Debevec 方法对噪声比较敏感,但结果很稳定。我最早实现 HDR 时用的就是 Debevec 的代码,虽然慢,但效果扎实。
3.4.2 Robertson 方法(2003)
Robertson 的方法引入了概率模型。他认为,像素值 Z 的观测噪声服从高斯分布,CRF 的求解可以转化为最大似然估计:
最大化:P(Z | E, f) = Π Π (1/√(2πσ²)) · exp(-(Z_ij - f(E_i · Δt_j))² / (2σ²))
取对数后,等价于最小化加权平方误差。Robertson 方法的特点是:
- 对噪声更鲁棒:因为显式建模了噪声分布
- 收敛更快:通常 5~10 次迭代即可
- 可以处理欠曝和过曝区域:通过调整权重函数
对比总结:Debevec 方法适合高质量、低噪声的场景;Robertson 方法适合噪声较大或曝光范围极端的场景。我个人在工程中更常用 Robertson,因为它对硬件不完美的容忍度更高。
3.4.3 两种方法的对比表格
| 维度 | Debevec 方法 | Robertson 方法 |
|---|---|---|
| 数学基础 | 最小二乘 + 光滑约束 | 最大似然估计 |
| 噪声处理 | 通过权重函数抑制 | 显式建模噪声分布 |
| 收敛速度 | 较慢,需 20~50 次迭代 | 较快,5~10 次迭代 |
| 实现复杂度 | 中等 | 稍高(需估计噪声方差) |
| 适用场景 | 实验室标定、高质量合成 | 移动端、实时系统、噪声环境 |
3.5 CRF 恢复的完整流程(SVG 图)
下面这张图展示了从多曝光图像到 CRF 曲线的完整流程:
3.6 实战建议
如果你要在项目中实现 CRF 标定,我有几点建议:
- 曝光时间要覆盖足够范围:至少 6 帧,最好 12 帧以上。曝光比建议 2 倍或 4 倍递增。
- 场景选择很重要:用灰阶卡或自然场景都行,但一定要有丰富的亮度变化。纯白墙不行。
- 注意 RAW 和 JPEG 的区别:RAW 的 CRF 更接近线性,JPEG 已经做了 gamma 和色调映射,CRF 更弯曲。我建议用 RAW 做标定,精度更高。
- 权重函数要合理:Debevec 的权重函数是三角形状,中间权重大,两端权重小。Robertson 的权重函数基于噪声模型,更科学。
经验之谈:如果你只是做算法验证,可以用 Debevec 的经典代码,网上有开源实现。但如果是产品化,我建议用 Robertson 方法,因为它对工程中的各种「脏数据」更宽容。我曾经在一个项目中,相机曝光时间有 5% 的误差,Debevec 方法直接发散,Robertson 方法还能收敛出可用的 CRF。
好了,CRF 的内容就讲到这里。记住,CRF 是 HDR 合成的基石,花时间把 CRF 标定做好,后面的融合工作会顺利很多。