第一章 坏点校正(DPC)实战:静态与动态坏点检测、校正算法选择、调试中的常见陷阱
坏点校正,圈里人常叫DPC(Defect Pixel Correction)。
这活儿看着不起眼,但要是没做好,整张照片就像白米饭里掺了沙子——怎么吃怎么别扭。我做了十年ISP调试,可以负责任地告诉你:DPC是图像质量的第一道防线。
1.1 什么是坏点?先搞清楚敌人长什么样
坏点说白了就是传感器上那些「不听话」的像素点。正常像素在暗场下输出应该接近0,亮场下输出应该线性增长。但坏点不按套路出牌。
我习惯把坏点分成两类:
- 静态坏点:出厂就有的,或者随着时间老化出现的。位置固定,打死不变。
- 动态坏点:受温度、增益、曝光时间影响。今天有明天没,这帧有下帧没。
你想想看,动态坏点是不是更头疼?静态的咱可以提前标定,动态的就得靠算法实时抓了。
核心观点:静态坏点靠「记性」,动态坏点靠「眼力」。两者缺一不可。
1.2 静态坏点检测:一张暗场图就够了?
静态坏点检测,业内标准做法是拍暗场。盖上镜头盖,拍一张全黑图。正常像素输出值应该在1-2个LSB左右,坏点可能飙到几百甚至上千。
但这里有个坑——温度。我记得有一次项目,常温下标定得好好的,结果客户在夏天户外一用,满屏亮点。后来才发现,高温下暗电流暴涨,原来没问题的像素全变成了「准坏点」。
所以我现在的做法是:
- 常温下标定一次,阈值设严一点
- 高温箱里(60°C)再标一次,记录新增的坏点
- 取两次的并集,写入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秒。 - 陷阱二:动态阈值一刀切
不同区域的纹理复杂度不同,阈值应该自适应。平坦区域阈值要严,纹理区域阈值要松。 - 陷阱三:校正后不检查
校正算法本身可能引入新的问题。比如中值法在密集坏点区域会失效,形成「补丁效应」。 - 陷阱四:忽略温度补偿
温度每升高10°C,暗电流翻倍。没有温度补偿的DPC,在高温下基本等于没开。
我的调试流程:先做静态标定,再调动态检测,最后验证校正效果。每一步都要用客观指标(如坏点残留率、误检率)来量化评估。别凭感觉调,数据不会骗人。
1.6 本章知识体系
下面这张图是我自己整理的DPC知识框架,帮你理清思路:
这张图从坏点分类开始,到检测方法、校正算法,再到常见陷阱,把DPC的完整链路串起来了。你调试的时候,可以对照着这张图一步步排查问题。
好了,第一章就聊到这儿。DPC这东西,说难不难,说简单也不简单。关键是要理解每个参数背后的物理意义,别光顾着调数值。
下一章我们聊聊去噪(Denoise)——又是一个让人又爱又恨的模块。