坏点校正(DPC):静态坏点与动态坏点

坏点校正,英文叫 Defective Pixel Correction,简称 DPC。

说白了,就是 sensor 上有些像素点坏了,拍出来的图像上会有固定的亮点或暗点。你想想看,一张照片上突然冒出来几个白点或者黑点,多碍眼。

我刚开始做 ISP 的时候,遇到过一台设备,拍出来的夜景照片上全是星星点点的白斑。客户以为是 sensor 坏了,折腾了好久。后来一查,是 DPC 没开,动态坏点检测阈值设得太保守了。

嗯,这节课我们就来聊聊 DPC 的那些事。

静态坏点 vs 动态坏点

坏点分两种:静态坏点和动态坏点。

  • 静态坏点:出厂就有的,位置固定。比如 sensor 生产时某个像素短路了,永远输出全白或全黑。这种坏点,厂家会提供一个坏点列表(Defective Pixel List),我们直接查表校正就行。
  • 动态坏点:用着用着才出现的。温度变化、电压波动、长时间曝光,都可能导致某些像素突然“抽风”。这种坏点位置不固定,得靠算法实时检测。

我在项目中遇到过一种情况:某款 sensor 在低温环境下,动态坏点数量暴增。一开始以为是 sensor 批次问题,后来发现是 DPC 算法对低温噪声的鲁棒性不够。调了阈值之后,问题就解决了。

核心区别一句话总结:静态坏点是“已知的敌人”,动态坏点是“潜伏的间谍”。

DPC 算法原理

DPC 算法其实不复杂。核心就三步:

  1. 检测:判断当前像素是不是坏点。
  2. 校正:如果是坏点,用周围像素的值把它替换掉。
  3. 平滑:避免校正后出现突兀的像素块。

检测方法有很多种,我常用的有两种:

  • 阈值法:当前像素值与周围像素的平均值做差,如果差值超过某个阈值,就判定为坏点。简单粗暴,但阈值不好设。设小了容易误检,设大了漏检。
  • 梯度法:计算像素在水平和垂直方向上的梯度。如果某个方向的梯度异常大,说明这个像素可能是坏点。这种方法对边缘区域更友好,不容易把边缘误判为坏点。

校正方法就更直接了:

  • 中值滤波:取周围 3x3 或 5x5 窗口的中值来替换。效果不错,但计算量大。
  • 均值滤波:取周围像素的平均值。速度快,但容易模糊细节。
  • 方向插值:沿着边缘方向做插值。效果最好,但实现复杂。

我个人习惯用梯度法检测 + 中值滤波校正。为什么?因为梯度法能更好地保护边缘,中值滤波对孤立坏点效果极佳。两者搭配,干活不累。

小技巧:实际项目中,我通常会把静态坏点列表和动态检测结合起来。先查表,再检测。这样既能保证已知坏点被校正,又能应对突发情况。

驱动寄存器配置实战

好了,理论说完了,我们来点实际的。

以某款常见的 ISP 芯片为例,DPC 相关的寄存器主要有这几个:

寄存器名称 地址 功能描述
DPC_EN 0x3000 DPC 功能使能,bit0=1 开启
DPC_THRESHOLD 0x3004 动态坏点检测阈值,范围 0-255
DPC_STATIC_LIST_ADDR 0x3008 静态坏点列表起始地址
DPC_STATIC_LIST_LEN 0x300C 静态坏点列表长度
DPC_MODE 0x3010 校正模式选择:0=中值,1=均值,2=方向插值

配置流程大概是这样的:

// 1. 使能 DPC
write_reg(0x3000, 0x01);

// 2. 设置动态检测阈值
// 这个值需要根据 sensor 的噪声水平来调
// 我一般从 40 开始试,然后看效果微调
write_reg(0x3004, 40);

// 3. 加载静态坏点列表
// 假设坏点列表在内存地址 0x8000 处,共 100 个坏点
write_reg(0x3008, 0x8000);
write_reg(0x300C, 100);

// 4. 选择校正模式
// 我推荐用中值滤波,效果最稳定
write_reg(0x3010, 0x00);

注意:阈值设得太小,会把正常像素误判为坏点,导致图像模糊。设得太大,坏点漏检,图像上会有斑点。我曾经在一个项目中,因为阈值设小了,导致整张图看起来像磨了皮,客户投诉说“细节都没了”。后来把阈值从 20 调到 50,问题就解决了。

嗯,这里还要提一下动态坏点检测的时机。我建议在每一帧的开始做检测,而不是每一帧都做。为什么?因为动态坏点不会频繁变化,每帧都检测浪费算力。一般每 10 帧检测一次就够了。

另外,静态坏点列表的维护也很重要。sensor 出厂时厂家会给一个列表,但 sensor 用久了,坏点会增多。我建议在设备每次启动时,先跑一遍坏点检测,把新出现的坏点加到列表里。这样能保证校正效果始终在线。

SVG 流程图:DPC 处理流程

DPC 处理流程 输入像素 静态坏点 列表? 是 执行校正 否 动态坏点 检测? 是 执行校正 否 输出像素

这个流程图很直观。像素进来,先查静态坏点列表。如果在列表里,直接校正。如果不在,再走动态检测。动态检测通过了,就输出原值。没通过,就校正。

为什么要先查静态列表?因为静态坏点检测快,查表就行。动态检测要算梯度、做比较,慢一些。先快后慢,效率最高。

好了,DPC 的内容就讲到这里。记住,坏点校正不是一劳永逸的事。sensor 会老化,环境会变化,阈值和模式都需要根据实际情况调整。多试、多调、多观察,才能把 DPC 调好。