053、坏点校正(DPC)进阶:静态坏点标定与动态坏点检测算法对比 📅 2026/7/16 15:49:52 053、坏点校正DPC进阶静态坏点标定与动态坏点检测算法对比一、一个让我熬夜三天的坏点问题2019年某款旗舰机项目量产前两周产线突然反馈暗光下预览画面出现大量“星星点灯”——白点、黑点、彩点密密麻麻像撒了一把胡椒面。产线急得跳脚说Sensor批次换了坏点率从千分之三飙到百分之五。我第一反应是Sensor厂又偷工减料了但拿到原始RAW图一看傻眼了——坏点分布完全随机而且只在增益大于12dB时才冒出来。静态标定表里根本没有这些点。这说明什么说明我们之前依赖的“出厂坏点标定”在暗光高增益场景下完全失效了。那次之后我花了整整三天把DPCDefect Pixel Correction从静态标定到动态检测从硬件实现到软件补偿从头到尾捋了一遍。今天这篇笔记就是那次踩坑的总结。二、坏点到底是什么别被“坏”字骗了很多新人以为坏点就是Sensor物理损坏了像素永远不工作。实际上坏点分三种1. 静态坏点Static Defect出厂就有的位置固定。比如某个像素的光电二极管短路了输出永远是全白白点或全黑黑点。这类坏点用一张暗场图和一张亮场图就能标定出来属于“明牌”。2. 动态坏点Dynamic Defect这才是坑爹的地方。它平时表现正常但在特定条件下才“发病”——比如高增益、高温、长曝光。原因可能是像素复位噪声异常、暗电流不均匀、或者读出电路时序抖动。这类坏点位置不固定今天测在这里明天可能换地方。3. 闪烁坏点Flicker Defect更诡异输出值在正常和异常之间来回跳频率可能几帧一次。常见于老化的Sensor或供电不稳的场景。静态坏点好办出厂标定一次烧进OTPOne Time Programmable或者存成校准表ISP直接替换就行。动态坏点才是DPC算法的核心战场。四、静态坏点标定工厂里的“体检报告”静态标定通常分两步走第一步暗场标定Dark Frame盖上镜头盖或者用快门挡住光拍一张全黑图。理论上所有像素输出应该接近0考虑暗电流的话有个底噪。如果某个像素输出明显高于周围邻居比如超过均值3个标准差那就是白点Hot Pixel。这里有个坑暗电流随温度变化所以标定环境温度必须控制在25±2℃否则标出来的坏点表到了冬天就失效。我们之前有个项目在深圳标定冬天发到哈尔滨用户投诉暗光下全是噪点——其实就是温度变了暗电流漂了静态表不准了。第二步亮场标定Bright Frame用均匀光源积分球或灯箱打亮Sensor拍一张50%灰或90%灰的图。如果某个像素输出明显低于周围比如低于均值50%那就是黑点Dead Pixel。这里有个经验值亮场标定通常用增益0dB曝光时间控制在使输出值在满阱的60%-80%之间。太低了信噪比不够太高了容易饱和都会误判。标定完成后生成一张坏点位置图Defect Map每个像素一个bit0表示正常1表示坏点。这张图可以烧进Sensor的OTP或者存在系统校准分区里。ISP在pipeline的早期阶段通常在黑电平校正之后、去马赛克之前查表替换。静态标定的致命缺陷它只能解决“出厂时就坏”的点。对于使用过程中新产生的坏点比如跌落、老化、温度冲击导致的或者动态坏点完全无能为力。这就是为什么我们那个项目在高增益下炸了——出厂标定时增益0dB坏点表里根本没有高增益下才冒出来的点。五、动态坏点检测实时“巡逻”算法动态坏点检测不依赖出厂标定表而是在每一帧图像里实时判断每个像素是否异常。核心思想很简单坏点一定是“孤立”的——它和周围邻居的差异远大于正常像素之间的差异。主流算法基于邻域统计的阈值法以最常见的5x5窗口为例实际工程中常用3x3或5x5取决于算力// 伪代码别直接复制这是思路 for each pixel (i,j): // 取3x3邻域排除中心点 neighbors [p(i-1,j-1), p(i-1,j), p(i-1,j1), p(i,j-1), p(i,j1), p(i1,j-1), p(i1,j), p(i1,j1)] // 计算邻域中值Median别用均值均值会被坏点污染 median_val median(neighbors) // 计算中心点与中值的绝对差 diff abs(p(i,j) - median_val) // 阈值判断阈值需要随增益和亮度自适应 // 这里踩过坑固定阈值在高增益下会漏检在低增益下会误检 threshold base_threshold * gain_factor * (1 luminance_factor) if diff threshold: mark_as_defect(i,j)关键参数调优经验阈值怎么定别用固定值。我一般用“中值绝对偏差MAD”作为动态阈值的基准。MAD median(|neighbors - median_val|)然后threshold k * MAD。k值通常在3-5之间。这个方法的优点是阈值自动适应局部纹理——在平坦区域MAD小阈值小容易检出坏点在纹理区域MAD大阈值大避免误检。增益补偿增益每增加一倍噪声标准差增加√2倍。所以threshold需要乘以sqrt(gain)。别问我为什么是平方根问就是光子散粒噪声的泊松分布特性。这里有个工程技巧增益值可以从ISP的AE模块直接拿或者从Sensor的寄存器读。亮度补偿暗区噪声大亮区噪声小。我习惯把像素值归一化到0-1然后threshold乘以(1 0.5 * (1 - normalized_value))。这样暗区阈值放宽亮区阈值收紧。动态检测的坑边缘误检在物体的边缘像素值突变是正常的。如果算法只看邻域差异会把边缘误判为坏点。解决方案先做边缘检测比如Sobel算子在边缘区域降低检测灵敏度或者直接跳过。纹理误检高频纹理比如草地、布料里相邻像素差异本来就大。我的做法是计算邻域方差方差大的区域纹理区提高阈值方差小的区域平坦区降低阈值。连续坏点簇如果坏点连成一片比如3x3区域全是坏的邻域中值也被污染了算法会失效。这种情况需要更大窗口比如7x7做二次检测或者结合静态标定表。六、静态 vs 动态什么时候用哪个维度静态标定动态检测检测对象出厂永久坏点使用中产生的坏点、动态坏点实现复杂度低查表即可高每帧计算硬件开销只需存储Defect Map需要行缓冲和计算单元误检率极低标定准确的话较高容易误检边缘和纹理漏检率高无法检测新坏点低只要阈值合理适用场景量产一致性要求高的场景可靠性要求高、环境变化大的场景实际工程中的组合策略我做过的最稳定的方案是“静态为主、动态为辅”出厂时做一次高精度静态标定生成Defect Map作为第一道防线。ISP先查静态表替换已知坏点。对静态表替换后的图像再做动态检测捕捉新产生的坏点。动态检测的结果可以反馈给系统如果某个位置连续多帧被标记为坏点就把它加入动态坏点表后续帧直接查表替换不用再算。这个方案的好处是静态表处理了90%的坏点动态检测只处理剩下的10%算力开销小而且动态检测的误检可以被静态表覆盖因为静态表里的点已经被替换了动态检测不会再处理。七、一个真实案例为什么动态检测在暗光下失效了回到开头那个项目。我们当时用的是某供应商的DPC IP默认配置是静态标定固定阈值动态检测。在实验室25℃、增益0dB下效果完美。但到了产线暗房测试增益24dB画面全是坏点。排查过程先看RAW图坏点分布均匀不是Sensor局部问题。关掉动态检测只留静态标定坏点消失。说明动态检测误检了。分析误检原因增益24dB下噪声标准差是0dB时的√24≈4.9倍。但动态检测的阈值只乘了增益因子24倍没有乘平方根。阈值设得太宽正常像素也被判为坏点。修正把阈值公式改为threshold base * sqrt(gain) * (1 luminance_factor)。重新测试误检率从30%降到0.5%。另一个发现暗光下Sensor的暗电流非均匀性DSNU会放大导致某些像素即使没有坏输出也明显偏离邻居。这不是坏点是DSNU。解决方案在做动态检测之前先做DSNU校正用暗场标定的偏移量减去每个像素的暗电流。这个步骤通常放在黑电平校正之后、DPC之前。八、个人经验性建议别迷信Sensor厂的坏点标定。他们标定的条件温度、增益、曝光时间和你的实际使用场景可能完全不同。我见过太多项目Sensor厂给的Defect Map在用户手里完全没用——因为用户是在30℃、增益16dB下用的而Sensor厂是在25℃、增益0dB下标定的。动态检测的阈值一定要自适应。固定阈值是万恶之源。至少要做到随增益和亮度自适应。如果算力允许最好加上温度补偿从Sensor的温度寄存器读。坏点替换别用均值。均值会被坏点污染。用中值Median或者加权中值。我习惯用5x5窗口的中值如果算力紧张3x3中值也够用。别用双边滤波那是给去噪用的DPC不需要那么复杂。注意坏点替换后的图像质量。替换后的像素值可能和周围不连续产生“补丁”效应。我的做法替换后做一次局部平滑比如3x3均值让过渡更自然。但别平滑太多否则会损失细节。动态坏点表要定期更新。如果某个像素连续100帧被标记为坏点就把它加入永久坏点表后续帧直接查表替换。这样可以减少动态检测的算力开销同时提高稳定性。最后一条也是最重要的一条DPC不是万能的。如果坏点率超过1%或者坏点连成片cluster任何算法都救不了。这时候应该找Sensor厂换货而不是在算法上死磕。我见过有人花两个月优化DPC算法结果发现是Sensor的FPC排线接触不良——换了排线坏点全没了。九、写在后面DPC这个模块在ISP pipeline里看起来不起眼但它是图像质量的“守门员”。守门员漏一个球前锋进十个都补不回来。静态标定是“预防”动态检测是“补救”两者缺一不可。下次遇到坏点问题别急着调算法参数。先问三个问题坏点是静态的还是动态的坏点出现的条件是什么增益、温度、曝光时间坏点率是多少这三个问题搞清楚了解决方案自然就有了。这篇笔记写于某次出差回程的飞机上旁边坐了个打呼噜的大叔。想到哪写到哪可能有点跳跃但都是实战中淌过的浑水。希望对你有用。