4. 坏点校正(DPC):静态与动态坏点检测、校正算法选择、参数调优
坏点校正,简称 DPC。说白了,就是处理 sensor 上那些「不听话」的像素点。
我刚开始调 ISP 时,觉得 DPC 不就是个中值滤波嘛,有啥好调的?直到有一次,一个项目在夜视模式下满屏都是白点,客户直接退货。嗯,从那以后,我再也不敢小看 DPC 了。
坏点分两种:静态坏点和动态坏点。静态坏点出厂就固定了,动态坏点会随温度、增益变化而出现。处理方式完全不同。
核心观点: DPC 不是简单的滤波,而是 sensor 健康度的「体检医生」。调好了,画面干净;调不好,要么坏点漏检,要么好点被误伤。
4.1 静态坏点检测
静态坏点,就是 sensor 出厂时就带有的死点、亮点。这些点位置固定,不随环境变化。
检测方法主要有两种:
- 出厂坏点表: sensor 厂商会提供一个坏点坐标列表。直接加载就行,省事。但我遇到过,有些厂商给的列表不全,漏了不少点。
- 在线标定: 盖上镜头盖,拍一张全黑图,再拍一张均匀光照图。通过对比,找出异常点。我建议项目量产前,至少做一次在线标定,跟出厂表做交叉验证。
我的习惯: 静态坏点表我会保留两份——一份是厂商提供的原始表,一份是产线标定后生成的补充表。两份合并使用,漏检率基本能降到 0.1% 以下。
4.2 动态坏点检测
动态坏点就麻烦多了。它们平时好好的,温度一高、增益一拉,就冒出来了。你想想看,晚上监控画面突然出现一堆闪烁的白点,多吓人。
常用的检测算法:
| 算法 | 原理 | 优点 | 缺点 |
|---|---|---|---|
| 亮度梯度法 | 计算像素与邻域的梯度差,超过阈值判为坏点 | 计算快,硬件友好 | 对纹理边缘敏感,容易误检 |
| 邻域统计法 | 统计 5x5 或 7x7 窗口内的均值、方差,偏离过大判为坏点 | 鲁棒性好,抗噪能力强 | 计算量大,需要软件优化 |
| 自适应阈值法 | 根据局部亮度动态调整检测阈值 | 适应性强,暗场亮场都能用 | 参数多,调起来费劲 |
我个人比较喜欢用邻域统计法。虽然慢一点,但准确率高。我曾经在一个项目中,用亮度梯度法死活调不好,换成邻域统计法后,问题迎刃而解。
4.3 校正算法选择
检测到坏点后,怎么修?常见的有三种:
- 中值滤波: 用邻域像素的中值替换坏点。简单粗暴,但对边缘有损伤。
- 线性插值: 根据坏点周围的好点,做双线性或双三次插值。效果细腻,但计算量大。
- 自适应加权: 结合中值和插值的优点,根据局部纹理复杂度动态选择权重。我目前的主力方案。
注意: 校正算法不是越复杂越好。在低算力平台上,中值滤波+小窗口往往比复杂的自适应算法更稳定。我曾经在某个海思方案上,因为用了太复杂的插值,导致帧率直接掉了一半。
4.4 参数调优实战
参数调优,是 DPC 最磨人的部分。我总结了一套「三步走」策略:
- 第一步:定阈值。 先拍一张均匀灰卡图,统计像素分布,确定正常范围。阈值设得太严,好点被误杀;设得太松,坏点漏网。我一般取均值 ± 3σ 作为初始值。
- 第二步:选窗口。 3x3 窗口最快,但检测能力有限;5x5 窗口是主流;7x7 窗口更准,但边缘细节容易模糊。我建议从 5x5 开始调。
- 第三步:增益补偿。 动态坏点在高增益下更明显。需要根据 ISP 的增益值,动态调整检测阈值。增益每增加 6dB,阈值可以放宽 10%-15%。
下面是一个简单的参数配置示例:
// DPC 参数结构体示例
typedef struct {
uint8_t enable; // 0:关闭, 1:开启
uint8_t static_table_en; // 静态坏点表使能
uint8_t dynamic_detect_en;// 动态检测使能
uint16_t static_threshold; // 静态检测阈值, 默认 40
uint16_t dynamic_threshold;// 动态检测阈值, 默认 60
uint8_t window_size; // 检测窗口: 3,5,7
uint8_t correction_mode; // 0:中值, 1:插值, 2:自适应
uint16_t gain_compensation;// 增益补偿系数, 默认 100
} dpc_params_t;
// 初始化推荐值
dpc_params_t dpc_cfg = {
.enable = 1,
.static_table_en = 1,
.dynamic_detect_en = 1,
.static_threshold = 40,
.dynamic_threshold = 60,
.window_size = 5,
.correction_mode = 2,
.gain_compensation = 100
};
避坑指南: 我曾经在一个项目中,把动态阈值设得太低,结果把正常的星空画面里的星星全当坏点给抹掉了。后来我加了一个「亮度保护」逻辑——如果像素亮度超过某个上限,就不做 DPC 处理。这样星星保住了,坏点也没漏。
4.5 调优效果评估
调得好不好,不能光靠眼睛看。我一般用三个指标来衡量:
| 指标 | 定义 | 合格标准 |
|---|---|---|
| 坏点漏检率 | 未被检测到的坏点 / 总坏点数 | < 0.5% |
| 好点误检率 | 被误判为坏点的好点 / 总好点数 | < 0.1% |
| PSNR 损失 | DPC 处理前后的峰值信噪比变化 | < 0.5dB |
嗯,这三个指标都达标了,DPC 才算调到位。记住,坏点校正不是越强越好,而是在「去坏点」和「保细节」之间找到平衡点。