3、HDR合成流程概览:从多帧输入到最终输出
好,咱们进入正题。HDR合成,说白了就是把几张不同曝光的照片,合成一张亮部不过曝、暗部有细节的“完美”照片。我刚开始接触这个领域时,觉得不就是“亮图取暗部,暗图取亮部”嘛,简单。结果第一次自己写流程,出来的图全是鬼影和断层,惨不忍睹。
后来才明白,一个工业级的HDR合成流程,远不止“融合”这一步。它是一条完整的流水线,每一步都有坑。今天我就带你走一遍这条流水线,把每个环节的作用和我的个人经验都交代清楚。
3.1 输入多帧图像:素材是基础
一切从输入开始。通常我们会拍摄3到5帧,甚至7帧不同曝光的图像。曝光策略上,我习惯用“包围曝光”,也就是固定光圈ISO,只改变快门速度。这样能保证景深和噪点水平一致。
这里有个坑:输入帧的位深。很多手机拍出来是8-bit JPEG,动态范围本身就有限。我建议至少用10-bit RAW或者16-bit TIFF作为输入。你想想看,如果源数据就丢了细节,后面再怎么合成也是白搭。
| 输入格式 | 位深 | 动态范围 | 我的建议 |
|---|---|---|---|
| JPEG | 8-bit | 低 | 不推荐,后期断层明显 |
| TIFF (16-bit) | 16-bit | 高 | 推荐,保留足够细节 |
| RAW (DNG/CR2) | 12/14-bit | 极高 | 最佳选择,后期空间最大 |
3.2 对齐:消除“手抖”的痕迹
手持拍摄,帧与帧之间肯定有位移。如果不做对齐,融合后的图像边缘会有重影,像没对上焦一样。
对齐算法我分两类:
- 全局对齐(仿射变换):适合相机纯平移或旋转。速度快,但遇到视差大的场景就露馅。
- 局部对齐(光流法):逐像素匹配。精度高,但计算量大。我在项目中遇到过,光流法对运动物体反而会引入错误匹配,需要配合后面的去鬼影一起用。
3.3 去鬼影:干掉“幽灵”
这是整个流程里最头疼的一步。什么是鬼影?就是场景中的运动物体(比如行人、汽车、树叶),在不同帧里位置不一样。直接融合,就会出现半透明的“幽灵”。
去鬼影的核心思路是:检测运动区域,然后只从某一帧里取那个区域的内容。我常用的方法有:
- 基于中值/均值偏差检测:简单,但对大运动不敏感。
- 基于光流一致性检测:精度高,但容易把高光区域误判为运动。
- 基于深度学习(如CNN):效果好,但需要大量标注数据。我曾经用U-Net做过一个去鬼影网络,效果确实比传统方法好一截,但部署到手机上时,模型压缩花了不少功夫。
3.4 融合:把“底片”叠在一起
对齐和去鬼影做完,终于到了融合这一步。融合的本质是:对每个像素,根据其在不同帧中的曝光质量和运动置信度,赋予一个权重,然后加权平均。
常见的融合策略:
- 简单平均:所有帧等权重。效果最差,动态范围几乎没有扩展。
- 基于曝光质量的权重:中间曝光的像素权重高,过曝或欠曝的权重低。这是最常用的方法。
- 拉普拉斯金字塔融合:多尺度融合,能保留更多细节。我个人的项目里,90%的情况都用这个方法。
// 伪代码:基于曝光质量的权重融合
for each pixel (x, y):
weight_sum = 0
hdr_pixel = 0
for each frame i:
// 计算权重:像素值越接近中间灰度,权重越高
weight_i = 1.0 - abs(pixel_i - 0.5) * 2.0
// 应用去鬼影置信度
weight_i *= confidence_i(x, y)
hdr_pixel += pixel_i * weight_i
weight_sum += weight_i
hdr_pixel /= weight_sum
3.5 色调映射:把“大象”塞进“冰箱”
融合后的图像是32位浮点的HDR数据,动态范围可能达到10^6:1。但我们的显示器只能显示0-255的8位数据。色调映射就是做这个“压缩”的。
色调映射算法分两类:
- 全局映射:对整个图像用同一个映射曲线。简单,但容易丢失局部对比度。
- 局部映射:根据像素周围的亮度自适应调整。效果好,但容易出现光晕(halo)伪影。
我常用的一个技巧是:先用全局映射把整体亮度压下来,再用局部映射恢复细节。这样既能避免光晕,又能保留暗部层次。
3.6 输出HDR图像:最后的交付
最后一步,输出。输出格式取决于你的应用场景:
- 显示用:输出8-bit JPEG或PNG,经过色调映射后的标准图像。
- 后期用:输出16-bit TIFF或OpenEXR,保留HDR数据,方便在Photoshop或达芬奇里进一步调整。
- 移动端展示:输出10-bit HEIF,兼顾画质和文件大小。
嗯,到这里,整个HDR合成流程就走完了。你看,从输入到输出,每一步都有讲究。对齐和去鬼影决定了“能不能用”,融合决定了“底子好不好”,色调映射决定了“好不好看”。