坏点校正(DPC):静态与动态坏点检测及校正强度调节

坏点校正,英文叫 Defect Pixel Correction,简称 DPC。说白了,就是处理 sensor 上那些「不听话」的像素点。有的永远亮着,有的永远暗着,还有的时好时坏。嗯,这节我们就来聊聊怎么搞定它们。

核心观点:坏点校正不是越强越好。校正过度,细节就没了;校正不足,画质就花了。关键在于「找得准、调得稳」。

3.1 坏点的两种类型

我在项目中遇到过不少 sensor,坏点问题千奇百怪。但归纳起来,就两类:

类型 定义 典型表现 处理难度
静态坏点 固定位置、固定亮度偏差 同一位置始终偏亮(白点)或偏暗(黑点) 低(可离线标定)
动态坏点 随温度、增益、曝光时间变化 高增益下突然冒出的亮点,低增益下消失 高(需实时检测)

你想想看,静态坏点就像 sensor 出厂时的「胎记」,位置固定。动态坏点就麻烦多了,它像幽灵一样,温度一高、增益一拉就冒出来。我调过一款 1/2.3 英寸的 sensor,常温下好好的,一进 60°C 烘箱,满屏亮点。嗯,那就是典型的动态坏点。

3.2 静态坏点检测算法

静态坏点检测,我个人习惯用「离线标定 + 查表」的方式。流程很简单:

  1. 采集全黑帧:盖上镜头盖,拍 10~20 帧全黑图像。
  2. 采集全白帧:用均匀光源拍 10~20 帧过曝图像(接近饱和)。
  3. 统计偏差:对每个像素,计算全黑帧的均值与全白帧的均值。
  4. 标记坏点:全黑帧中亮度超过阈值(如 10 DN)的标记为亮点;全白帧中亮度低于阈值(如 1020 DN)的标记为暗点。
  5. 生成坏点表:将坐标写入 OTP 或校准文件。

我的经验:全黑帧建议多拍几帧做平均,避免随机噪声干扰。全白帧的亮度控制在饱和值的 80%~90% 比较稳妥,太接近饱和反而容易误判。

3.3 动态坏点检测算法

动态坏点没法提前标定,必须实时检测。我常用的方法是「邻域比较法」。核心思路:

  • 对每个像素,取它周围 3x3 或 5x5 邻域的像素值。
  • 计算邻域的中值或均值。
  • 如果当前像素与邻域中值的偏差超过阈值,就判定为坏点。

举个例子,一个 3x3 的窗口:

原始像素值(假设中心像素是候选坏点):
[100, 102, 101]
[103, 250, 99 ]
[101, 100, 102]

邻域中值 = 101
中心像素 = 250
偏差 = 250 - 101 = 149

如果阈值设为 50,则判定为坏点。

为什么会这样?因为正常像素在局部区域内变化平缓,坏点则会出现「突兀」的跳变。阈值怎么设?我建议根据 sensor 的噪声水平动态调整。低增益下阈值可以设小一点,高增益下要适当放大。

注意:动态坏点检测最怕误判。图像边缘、纹理丰富区域,像素值本身变化就大,容易把正常细节当成坏点。我踩过这个坑——有一次把一条细电线上的高光点全当坏点给抹了,结果画面里电线断了。嗯,后来加了边缘保护逻辑才解决。

3.4 校正强度调节

找到坏点后,怎么修?常见方法有三种:

方法 原理 优点 缺点
邻域均值替换 用周围像素的平均值替代坏点 实现简单,速度快 容易模糊细节
邻域中值替换 用周围像素的中值替代坏点 抗噪性好,不易受异常值影响 计算量稍大
自适应插值 根据边缘方向选择插值权重 保留边缘细节,效果最好 实现复杂,耗时

我个人习惯用「中值替换 + 自适应权重」的混合方案。具体来说:

  • 先判断坏点是否在边缘区域(通过梯度检测)。
  • 如果在平坦区域,直接用中值替换。
  • 如果在边缘区域,沿边缘方向做加权插值。

这样既能去掉坏点,又能保住边缘。校正强度可以通过一个系数 α 来控制:

最终像素值 = (1 - α) × 原始值 + α × 校正值

α 的范围是 0~1。α=0 时不校正,α=1 时完全替换。我一般设 α=0.8~0.9,留一点原始值,避免校正痕迹太明显。

3.5 避免校正过度导致细节损失

这是 DPC 调试里最头疼的问题。校正过度,画面会变得「塑料感」——细节模糊,纹理丢失。怎么避免?

第一,加边缘保护。 检测到坏点后,先算一下它周围的梯度。如果梯度大(说明在边缘),就降低校正强度,甚至不校正。

第二,设置信度。 不是所有「疑似坏点」都要修。我习惯给每个候选坏点算一个置信度分数:

  • 偏差越大,置信度越高。
  • 邻域方差越小,置信度越高(平坦区域的可信度更高)。
  • 只有置信度超过阈值,才执行校正。

第三,做多帧验证。 动态坏点检测时,不要单帧就下结论。连续 3~5 帧都在同一位置出现异常,再判定为坏点。这样可以避免把随机噪声当成坏点。

避坑指南:我曾经在一个项目中,把 sensor 的固定模式噪声(FPN)当成了坏点。结果校正算法把整行整列的像素都修了一遍,画面出现了明显的「网格感」。后来我加了空域滤波预处理,先把 FPN 去掉,再跑 DPC,问题就解决了。

3.6 DPC 调试流程总结

下面这张图是我自己整理的 DPC 调试流程,你可以参考:

DPC 调试流程图 DPC 调试流程 输入 RAW 图像 静态坏点检测(查表) 动态坏点检测(邻域比较) 置信度判断 + 边缘保护 校正输出 关键参数 静态阈值:10 DN 动态阈值:50 DN(可调) 避坑提醒 避免误判边缘 多帧验证防噪声

3.7 调试中的常见问题与对策

问题 现象 可能原因 对策
坏点没修掉 画面仍有固定亮点/暗点 静态坏点表未更新,或动态阈值过高 重新标定坏点表,降低动态阈值
细节模糊 纹理区域被抹平 校正强度过大,或边缘保护不足 降低 α 值,增强边缘梯度检测
出现网格感 画面有规律性条纹 误将 FPN 当坏点处理 先做 FPN 校正,再跑 DPC
动态坏点漏检 高增益下出现零星亮点 动态阈值未随增益调整 建立增益-阈值映射表

嗯,以上就是 DPC 调试的核心内容。坏点校正看似简单,但要做好、做稳,需要反复调参和验证。我建议你在调试时,多准备几组不同场景的测试图——暗场、亮场、纹理丰富的场景、边缘场景,都跑一遍,才能发现潜在问题。