7、高动态范围(HDR)基础:HDR原理、线性与非线性传感器、多帧合成与单帧HDR
各位好,今天我们来聊聊车载Camera系统里一个绕不开的话题——HDR。说实话,HDR这个词在消费电子领域已经被说烂了,但在车载领域,它的意义完全不同。你手机拍夜景HDR,拍糊了可以重来。但在车上,前方一个隧道出口,阳光刺眼,如果HDR没做好,那一帧图像可能就直接导致感知系统漏掉一个行人。嗯,责任重大。
7.1 为什么车载摄像头需要HDR?
我们先想一个问题:一个普通的8-bit sensor,动态范围大概在60-70dB左右。这是什么概念?我举个例子,你在一个晴朗的下午开车,隧道入口处的亮度可能只有10 lux,而隧道外的阳光直射区域可能高达100,000 lux。这中间的跨度超过80dB。普通sensor根本hold不住,要么暗部一片死黑,要么亮部过曝成一片白。
我当年在做一个ADAS项目时,第一次拿到路测数据,发现车辆刚出隧道的那几帧,前方几乎全是白茫茫一片。算法团队直接炸了,说这数据没法用。后来我们才意识到,不是算法不行,是图像数据本身就已经丢失了信息。所以,HDR在车载领域不是锦上添花,而是刚需。
7.2 HDR的基本原理
说白了,HDR就是让摄像头能「看」到更亮和更暗的东西。传统sensor的响应是线性的,每个像素的电荷量与入射光强成正比。但线性响应有个问题——它只能在一个有限的亮度范围内保持线性。超出这个范围,就饱和了。
HDR的核心思路其实很简单:用不同的曝光参数去捕捉同一场景,然后把它们合成在一起。短曝光捕捉亮部细节,长曝光捕捉暗部细节,中间曝光负责过渡区域。最后通过融合算法,把三张图里「最好」的部分拼成一张图。
你可能会问:这不就是多帧合成吗?没错,但车载场景下,多帧合成面临一个巨大的挑战——运动。车辆在高速行驶,场景中的物体也在快速移动。如果帧与帧之间有运动,合成出来的图像就会出现鬼影(ghosting)。所以,车载HDR的难点不在于「怎么合成」,而在于「怎么在运动场景下合成得又快又好」。
7.3 线性传感器 vs 非线性传感器
这里我要讲一个很多初学者容易混淆的概念。我们常说的「线性传感器」,指的是光电转换特性是线性的——入射光强增加一倍,输出电压也增加一倍。这种传感器在低动态范围场景下表现很好,但遇到高对比度场景就捉襟见肘了。
那非线性传感器呢?它的响应曲线不是一条直线,而是一条对数曲线或者分段线性曲线。什么意思?就是它对暗部区域的增益高,对亮部区域的增益低。这样一来,同样的8-bit数据,它能覆盖更宽的亮度范围。
我个人的习惯是,在选型时先看sensor的响应曲线。如果是线性sensor,那基本只能靠多帧合成来做HDR。如果是非线性sensor(比如LFM、Split Pixel这类),那单帧就能实现不错的HDR效果。
| 特性 | 线性传感器 | 非线性传感器 |
|---|---|---|
| 响应曲线 | 直线(光强 vs 电压) | 对数/分段线性 |
| 动态范围 | 60-70 dB(典型) | 100-140 dB(典型) |
| HDR实现方式 | 多帧合成(DOL、SME) | 单帧HDR(LFM、Split Pixel) |
| 运动伪影 | 容易产生鬼影 | 基本无鬼影 |
| 成本 | 较低 | 较高 |
| 车载适用场景 | 低速/停车场景 | 高速/全场景 |
7.4 多帧合成HDR
多帧合成HDR,也叫DOL(Digital Overlap)模式。它的工作流程是这样的:sensor在同一个曝光周期内,连续输出多帧不同曝光时间的图像。比如一帧短曝光(1ms)、一帧中曝光(4ms)、一帧长曝光(16ms)。然后ISP把这些帧对齐、融合,输出一张HDR图像。
这里有个关键参数——帧间间隔。如果三帧之间的时间差太大,运动物体就会在帧间发生位移,导致合成后出现鬼影。所以,DOL模式要求帧间间隔尽可能短,最好在1ms以内。
我记得有一次调试一个DOL方案,发现鬼影总是消不掉。查了半天,发现是sensor的帧间间隔配置错了,实际间隔是3ms而不是我们以为的0.5ms。改回来之后,效果立竿见影。所以,做多帧HDR,一定要确认sensor的时序配置。
// DOL模式下的曝光时序配置示例(伪代码)
// 假设使用三帧合成:T1=1ms, T2=4ms, T3=16ms
// 帧间间隔要求 < 1ms
sensor_config_t cfg;
cfg.hdr_mode = HDR_MODE_DOL;
cfg.num_exposures = 3;
cfg.exposure_times[0] = 1000; // 1ms (短曝光)
cfg.exposure_times[1] = 4000; // 4ms (中曝光)
cfg.exposure_times[2] = 16000; // 16ms (长曝光)
cfg.frame_interval = 500; // 0.5ms 帧间间隔
// 注意:不同sensor的寄存器配置方式不同
// 务必参考datasheet中的时序图
sensor_apply_config(&cfg);
7.5 单帧HDR
单帧HDR,顾名思义,就是只用一帧曝光就实现高动态范围。这听起来有点反直觉——一帧怎么能同时覆盖亮部和暗部呢?答案是:利用sensor像素本身的设计。
目前主流的单帧HDR技术有两种:
- LFM(Large Full Well):每个像素有两个电荷存储节点,一个容量大(用于亮部),一个容量小(用于暗部)。曝光结束后,两个节点的电荷分别读出,然后合成。
- Split Pixel:每个像素被分成两个子像素,一个子像素的感光面积大(灵敏度高,用于暗部),另一个感光面积小(灵敏度低,用于亮部)。两个子像素的信号合并,得到HDR图像。
这两种方案的好处是:没有帧间间隔,所以没有鬼影。你想想看,车辆在高速上跑,前方突然出现一个逆光的行人,单帧HDR能在一帧内同时保留行人的轮廓和背景的细节。而多帧HDR如果帧间间隔没控制好,可能就出现鬼影了。
不过,单帧HDR也有代价。LFM方案需要更大的像素面积,所以分辨率会受限。Split Pixel方案则对工艺要求高,成本也更高。我个人的建议是:前视、环视这类对运动伪影敏感的场景,优先考虑单帧HDR;倒车、侧视这类低速场景,多帧HDR也够用。
7.6 知识体系总览
下面这张图是我自己整理的HDR知识体系,涵盖了从原理到实现的完整链路。你可以把它当作一个快速索引,遇到具体问题时回来对照着看。
7.7 小结
好了,这一章的内容就到这里。我们聊了HDR的基本原理,对比了线性传感器和非线性传感器的差异,也深入分析了多帧合成和单帧HDR各自的优缺点。说实话,HDR这个领域水很深,不同场景、不同成本约束下,选择完全不一样。但有一点是确定的:在车载领域,HDR不是可选项,而是必选项。没有HDR,你的感知系统在强光、逆光、隧道出入口这些场景下,基本就是瞎子。
下一章我们会深入HDR的工程实现细节,包括ISP pipeline中的HDR融合算法、鬼影消除技术,以及如何在Android HAL层配置HDR模式。到时候我会分享一些我在项目中踩过的坑,希望能帮你少走弯路。
一句话总结: HDR的本质是用「多信息」换「宽范围」。线性传感器靠多帧,非线性传感器靠像素设计。选型时,先看场景,再看成本,最后看性能。
公众号:蓝海资料掘金营,微信deep3321