第一章 坏点校正(DPC)实战:静态与动态坏点检测、校正算法选择、调试中的常见陷阱

坏点校正,圈里人常叫DPC(Defect Pixel Correction)。

这活儿看着不起眼,但要是没做好,整张照片就像白米饭里掺了沙子——怎么吃怎么别扭。我做了十年ISP调试,可以负责任地告诉你:DPC是图像质量的第一道防线。

1.1 什么是坏点?先搞清楚敌人长什么样

坏点说白了就是传感器上那些「不听话」的像素点。正常像素在暗场下输出应该接近0,亮场下输出应该线性增长。但坏点不按套路出牌。

我习惯把坏点分成两类:

  • 静态坏点:出厂就有的,或者随着时间老化出现的。位置固定,打死不变。
  • 动态坏点:受温度、增益、曝光时间影响。今天有明天没,这帧有下帧没。

你想想看,动态坏点是不是更头疼?静态的咱可以提前标定,动态的就得靠算法实时抓了。

核心观点:静态坏点靠「记性」,动态坏点靠「眼力」。两者缺一不可。

1.2 静态坏点检测:一张暗场图就够了?

静态坏点检测,业内标准做法是拍暗场。盖上镜头盖,拍一张全黑图。正常像素输出值应该在1-2个LSB左右,坏点可能飙到几百甚至上千。

但这里有个坑——温度。我记得有一次项目,常温下标定得好好的,结果客户在夏天户外一用,满屏亮点。后来才发现,高温下暗电流暴涨,原来没问题的像素全变成了「准坏点」。

所以我现在的做法是:

  1. 常温下标定一次,阈值设严一点
  2. 高温箱里(60°C)再标一次,记录新增的坏点
  3. 取两次的并集,写入OTP

代码示例(简化版):

// 静态坏点检测伪代码
for each pixel (x, y) in dark_frame:
    if pixel_value > static_threshold:
        mark_as_static_defect(x, y)
        
// 高温补偿
if temperature > 50°C:
    static_threshold = static_threshold * 0.7  // 阈值收紧

我的习惯:静态坏点表一定要留余量。宁可多标100个假坏点,也别漏掉1个真坏点。假坏点可以用校正算法补回来,漏掉的坏点就是照片上的永久污点。

1.3 动态坏点检测:实时抓现行

动态坏点检测,说白了就是在图像流里「抓现行」。算法得判断:这个像素是真实细节,还是坏点?

常用的方法有三种:

方法 原理 优缺点
邻域比较法 比较当前像素与周围8邻域的差值 简单快速,但容易误判边缘
中值滤波法 用邻域中值替代,看差异是否过大 抗噪性好,但计算量大
梯度分析法 分析水平和垂直方向的梯度一致性 准确率高,适合纹理区域

我个人偏爱梯度分析法。为什么?因为邻域比较法在遇到细线条时,经常把正常像素当坏点给修了。你想想看,一根头发丝被当成坏点抹掉,那画面多尴尬。

动态检测的阈值设置是个技术活:

// 动态坏点检测 - 梯度分析法
// 计算水平梯度
grad_h = abs(pixel(x,y) - pixel(x-1,y)) + abs(pixel(x,y) - pixel(x+1,y))
// 计算垂直梯度  
grad_v = abs(pixel(x,y) - pixel(x,y-1)) + abs(pixel(x,y) - pixel(x,y+1))

// 判断是否为坏点
if (grad_h > dynamic_threshold && grad_v > dynamic_threshold):
    // 两个方向梯度都大,可能是坏点
    // 进一步用中值验证
    median_val = get_median_of_neighbors(x, y)
    if abs(pixel(x,y) - median_val) > median_threshold:
        mark_as_dynamic_defect(x, y)

注意:动态阈值不能是固定值。增益越高,噪声越大,阈值就得跟着往上调。我曾经见过一个团队,ISO 3200下还用ISO 100的阈值,结果满屏误检,照片修得跟油画似的。

1.4 校正算法怎么选?三种主流方案

检测到坏点之后,怎么补?我常用的有三种方案:

  • 邻域均值法:取周围4个或8个像素的平均值。简单,但会模糊细节。
  • 中值法:取邻域中值。抗噪性好,适合孤立坏点。
  • 自适应插值法:根据边缘方向选择插值权重。效果最好,但最耗资源。

怎么选?我的经验是:

  • 静态坏点用中值法,因为位置已知,可以提前算好权重
  • 动态坏点用自适应插值法,因为要兼顾实时性和画质
  • 低端平台用邻域均值法,省资源

避坑指南:我曾经在Bayer域做DPC,直接用G通道的值去补R通道的坏点。结果颜色全乱了。后来才意识到,Bayer域校正必须考虑通道一致性——R通道的坏点只能用R通道的邻域来补,跨通道校正会引入颜色伪影。

1.5 调试中的常见陷阱

这些年踩过的坑,我列几个典型的:

  1. 陷阱一:暗场标定不严谨
    暗场曝光时间太短,暗电流没充分激发,标出来的坏点表不全。我建议暗场曝光时间至少1秒。
  2. 陷阱二:动态阈值一刀切
    不同区域的纹理复杂度不同,阈值应该自适应。平坦区域阈值要严,纹理区域阈值要松。
  3. 陷阱三:校正后不检查
    校正算法本身可能引入新的问题。比如中值法在密集坏点区域会失效,形成「补丁效应」。
  4. 陷阱四:忽略温度补偿
    温度每升高10°C,暗电流翻倍。没有温度补偿的DPC,在高温下基本等于没开。

我的调试流程:先做静态标定,再调动态检测,最后验证校正效果。每一步都要用客观指标(如坏点残留率、误检率)来量化评估。别凭感觉调,数据不会骗人。

1.6 本章知识体系

下面这张图是我自己整理的DPC知识框架,帮你理清思路:

坏点校正(DPC)知识体系 坏点分类 坏点分类 静态坏点(位置固定) 动态坏点(时有时无) 暗场标定法 邻域比较法 梯度分析法 邻域均值法 中值法 自适应插值法 常见陷阱:标定不严谨 | 阈值一刀切 | 忽略温度补偿 | 校正后不检查

这张图从坏点分类开始,到检测方法、校正算法,再到常见陷阱,把DPC的完整链路串起来了。你调试的时候,可以对照着这张图一步步排查问题。


好了,第一章就聊到这儿。DPC这东西,说难不难,说简单也不简单。关键是要理解每个参数背后的物理意义,别光顾着调数值。

下一章我们聊聊去噪(Denoise)——又是一个让人又爱又恨的模块。

专注资料整理