049、3D降噪的联合调优——空域+时域+频域联合降噪的工程实现——从3DNR的帧缓存管理到运动补偿的精度要求——低照度视频的实战调参

📅 2026/8/13 15:00:57
049、3D降噪的联合调优——空域+时域+频域联合降噪的工程实现——从3DNR的帧缓存管理到运动补偿的精度要求——低照度视频的实战调参
049、3D降噪的联合调优——空域时域频域联合降噪的工程实现——从3DNR的帧缓存管理到运动补偿的精度要求——低照度视频的实战调参昨晚在实验室盯着一块IMX585的RAW图盯到凌晨两点客户报了个case——楼道监控在0.1lux下噪点像雪花一样3DNR开了跟没开似的反而把运动的人拖出了鬼影。我盯着示波器上那根跳动的Y通道曲线突然意识到问题不在降噪算法本身而在我们根本没搞清楚空域、时域、频域这三兄弟在低照度下到底谁该让谁。先说说那个让人抓狂的现场。楼道里只有一盏声控灯人走过去灯亮人走了灯灭。灯亮的时候画面还行灯一灭整个画面就像撒了一把盐。我们当时用的方案是典型的“先空域后时域”串联结构——2DNR在前3DNR在后最后再挂一个频域的小维纳滤波。理论上这个架构没毛病但实际跑起来2DNR把细节磨平了3DNR拿到的输入已经是“糊了的底片”运动补偿的块匹配在低纹理区域直接失效频域滤波又把这个错误进一步放大。最后输出的画面静态区域噪点压住了但动态区域全是撕裂感。这个case让我重新审视了3DNR的帧缓存管理。很多工程师觉得帧缓存不就是开三块DDR存三帧嘛但低照度下帧缓存的管理直接决定了运动补偿的精度。我们当时用的是双帧缓存一帧参考一帧当前运动矢量搜索范围是±8像素。在0.1lux下噪点的幅度已经超过了真实物体的边缘梯度块匹配算法会把噪点当成特征点来追踪结果就是运动矢量全是乱的。后来我把帧缓存改成三帧中间帧做双向运动估计搜索范围缩到±4像素但增加了子像素精度——用1/4像素插值。这个改动让运动矢量的准确率提升了将近40%但代价是DDR带宽涨了30%而且子像素插值本身会引入轻微的模糊。这里踩过一个坑——三帧缓存不是简单地把三帧按时间顺序排开而是要做一个环形缓冲并且要区分“参考帧”和“去噪帧”。参考帧是原始RAW去噪帧是经过空域预滤波后的结果。如果你直接用去噪帧做运动估计那等于把2DNR的误差也带进了时域鬼影会加倍。正确做法是运动估计用原始帧运动补偿用去噪帧最后融合的时候再根据运动矢量的置信度做自适应权重。这个“双轨制”设计是我在调试车载夜视系统时总结出来的搬到安防场景同样适用。再说运动补偿的精度要求。低照度下运动补偿的精度要求不是“像素级”而是“亚像素级置信度门限”。我们当时犯的错误是对所有的运动矢量一视同仁不管置信度高低都做同样的时域滤波强度。结果就是低置信度的区域比如纯色墙壁、黑暗角落被强行做了时域叠加噪点反而被“积累”了。后来我加了一个置信度图用SAD绝对差值和和纹理梯度联合计算置信度低于阈值的区域时域滤波强度直接降到接近零完全靠空域撑着。这个改动让暗部区域的噪点反而比之前更干净了因为空域滤波在低纹理区域的表现其实比时域好。频域这块我们用的是DCT域的维纳滤波但一开始挂在最后面效果很差。后来我把频域滤波挪到了空域和时域之间并且只对高频系数做衰减低频系数保持原样。为什么因为空域滤波已经去掉了大部分高斯噪声时域滤波去掉了时间维度的随机噪声剩下的频域噪声主要是“残留的块效应”和“运动补偿的振铃”。这时候再用维纳滤波只需要针对高频段做轻量级的收缩强度系数控制在0.3到0.5之间千万别超过0.7否则画面会像塑料一样假。实战调参的时候我习惯用“三档递进”策略。第一档先关掉时域只调空域和频域把静态场景的噪点压到可接受范围记录下空域的强度系数和频域的截止频率。第二档打开时域但把时域强度设成空域的一半重点观察运动区域的鬼影和拖尾。如果鬼影明显优先调运动矢量的置信度门限而不是降时域强度——因为降强度是治标调门限是治本。第三档把三者的强度系数做成一个联动曲线随着ISO的升高空域强度线性增加时域强度先增后减因为高ISO下运动估计更容易出错频域强度保持恒定。这个曲线不是拍脑袋定的是从几十组实验数据里拟合出来的。还有一个容易被忽略的细节——帧率。低照度下很多方案会把帧率降到15fps甚至10fps来延长曝光但这对3DNR是致命的。帧率越低相邻帧之间的时间间隔越大运动物体的位移就越大运动补偿的搜索范围根本跟不上。我做过一个对比实验同样0.1lux下30fps的3DNR效果比15fps好一个档次因为运动矢量更小置信度更高。所以如果条件允许宁可提高增益把帧率保住也不要为了降噪而降帧率。这个反直觉的结论让不少同事一开始都以为我疯了。最后说说那个楼道case的结局。我们把帧缓存改成三帧环形缓冲运动估计用原始帧、补偿用去噪帧加了一个基于SAD和纹理梯度的置信度图频域滤波挪到中间位置强度系数调到0.4帧率从15fps拉回30fps增益提高了3dB。最终画面静态区域的噪点比之前降了大概6dB运动区域几乎没有鬼影暗部细节保留得比预期好。客户很满意但我心里清楚这只是一次针对特定场景的调优换一个场景比如雨夜的车载摄像头参数又得重新来一遍。经验这东西说白了就是踩坑踩出来的。3DNR的联合调优核心不是算法多先进而是你要清楚每个模块在什么条件下会“帮倒忙”。空域在低纹理区域会磨皮时域在运动区域会拖影频域在边缘会振铃——你要做的就是让它们在各自擅长的区域干活在彼此冲突的区域学会“闭嘴”。这个“闭嘴”的机制就是置信度门限和自适应权重。别指望一套参数打天下每个场景都得单独调但调参的思路是通用的——先分模块验证再联合调试最后做联动曲线。如果你也在调3DNR我建议你从帧缓存入手先确认你的运动估计是不是在“用脏数据算运动”。这个坑最隐蔽也最致命。