传统去雾算法优化:从对比度增强论文到工程复现

2023 年 2 月 26 日 星期日(已编辑)
/ , , , ,
3
摘要
从大气散射模型 I=Jt+A(1-t) 出发,复现 Kim et al. 的对比度增强去雾论文。涵盖四叉树大气光估计、透射率代价搜索、引导滤波细化和视频时间一致性问题。

阅读此文章之前,你可能需要首先阅读以下的文章才能更好的理解上下文。

传统去雾算法优化:从对比度增强论文到工程复现

编写时间:2023-02

围绕传统去雾算法的一次学习和复现,核心参考是 《Optimized Contrast Enhancement for Real-time Image and Video Dehazing》(Kim et al., JVCIR 2013, 项目页)这条路线。它不是端到端学习,而是从大气散射模型出发,估计大气光 A 和透射率 t(x),再反推出无雾图 J(x)

查看/下载 PDF 附录:对比度增强去雾复现笔记

雾退化模型

雾图可以写成:

Ic(x)=Jc(x)t(x)+Ac(1t(x)) I_c(x)=J_c(x)t(x)+A_c(1-t(x))

其中 x 是像素坐标,c 是 RGB 通道,I 是观察到的有雾图,J 是待恢复的无雾图,A 是大气光,t(x) 是透射率。物理上常写作:

t(x)=erd(x) t(x)=e^{-r d(x)}

r 是大气散射系数,d(x) 是场景深度。透射率越小,说明雾越浓、距离越远、原始信息保留越少。

如果 At 已知,可以反推:

Jc(x)=Ic(x)Act(x)+Ac J_c(x)=\frac{I_c(x)-A_c}{t(x)}+A_c

这一步本质是线性映射:

Jc(x)=1t(x)Ic(x)+Ac(11t(x)) J_c(x)=\frac{1}{t(x)}I_c(x)+A_c\left(1-\frac{1}{t(x)}\right)

因此 JI 的关系不是随意增强,而是一条斜率为 1/t 的直线。t 越小,斜率越大,对比度越强;但同样也越容易把像素拉到 [0,255] 之外。

大气光 A 的估计

传统暗通道思路常会先找灰度较高、颜色接近白色的像素,再取其中亮度最高的点作为大气光。但真实图像里有白车、白墙、天空、过曝灯牌等干扰;它们很亮,却不一定代表雾层大气光。

论文里使用四叉树递归:雾最厚的区域通常亮度高、区域内部变化小,所以每个区域可以用“亮但均匀”来打分:

Score(R)=μ(R)σ(R) Score(R)=\mu(R)-\sigma(R)

mu(R) 越高,区域越可能接近大气光;sigma(R) 越小,区域越均匀,越不像包含丰富纹理的近景物体。递归过程是:

这个策略不是单纯追求最亮,而是避免把有纹理的白色物体误当成 A。它也为后面的优化埋下一个点:每层递归都需要区域均值和标准差,后续可以用积分图把这类统计加速。

透射率 t 的搜索

t 不能直接从单张图精确解出。论文把它改写成局部搜索问题:对一个局部块 B,尝试一组候选 t_B,把它代入反推公式,得到候选无雾块 J_B,再用代价函数评价。

这个代价由两部分组成:

代价项目标直觉
E_loss避免像素反推后越界t 太小会把暗部拉到 0 以下,把亮部拉到 255 以上
E_contrast增强局部对比度t 越小,1/t 越大,局部方差越大

总目标可以写成:

E(tB)=Econtrast(tB)+λEloss(tB) E(t_B)=E_{contrast}(t_B)+\lambda E_{loss}(t_B)

这里的 lambda 是平衡项:lambda 越大,算法越保守,更怕失真;lambda 越小,算法越激进,更愿意拉对比度。

为什么会越界

反推式的输入输出关系是一条直线。对单个通道:

Jc=IcAct+Ac J_c=\frac{I_c-A_c}{t}+A_c

J_c=0 时,输入阈值为:

αc=Ac(1t) \alpha_c=A_c(1-t)

J_c=255 时,输入阈值为:

βc=Ac+t(255Ac) \beta_c=A_c+t(255-A_c)

所以只有 I_c \in [\alpha_c,\beta_c] 时,反推出的 J_c 才落在 [0,255]。如果 I_c < alpha_c,输出会低于 0;如果 I_c > beta_c,输出会高于 255。

去雾反推的线性映射与截断区间

去雾反推的线性映射与截断区间

越界损失可以写成:

Eloss(tB)=xBc(min(0,Jc(x;tB))2+max(0,Jc(x;tB)255)2) E_{loss}(t_B)=\sum_{x\in B}\sum_c \left( \min(0,J_c(x;t_B))^2+ \max(0,J_c(x;t_B)-255)^2 \right)

这项只惩罚出界部分:落在 [0,255] 内的像素不增加损失。

对比度项

对比度增强可以用局部方差理解。论文讨论过 MSE、Michelson、Weber 等形式,工程上选择更容易处理的 MSE/方差形式:

Econtrast(tB)=c1NBxB(Jc(x;tB)Jˉc)2 E_{contrast}(t_B)= -\sum_c\frac{1}{N_B}\sum_{x\in B} \left(J_c(x;t_B)-\bar J_c\right)^2

因为 JI 的线性变换:

Var(Jc)=1tB2Var(Ic) Var(J_c)=\frac{1}{t_B^2}Var(I_c)

所以 t_B 越小,局部方差越大,E_contrast 越小。也就是说,对比度项天然倾向于选择更小的 t,而损失项会阻止 t 小到造成大量截断。

选择对比度越界风险视觉结果
t 较大去雾不足、残雾
t 较小过曝、色块、黑白截断
E_contrast + lambda E_loss平衡可控尽量增强但不大量失真

候选 t_B 还可以先给一个下界,避免明显必然越界的取值。由 J_c \in [0,255] 可得到类似约束:

tBmax(maxx,cAcIc(x)Ac,maxx,cIc(x)Ac255Ac) t_B \ge \max\left( \max_{x,c}\frac{A_c-I_c(x)}{A_c}, \max_{x,c}\frac{I_c(x)-A_c}{255-A_c} \right)

实际实现时只需要把不合理的候选 t_B 排除,再在 [t_{min},1] 内寻找代价最小值。

块级 t 的问题

块级搜索的优点是快。假设一个块内的 t 相同,就不用为每个像素单独求解;但这个假设也很脆弱。t(x)=e^{-rd(x)} 里真正变化的是深度 d(x),一个固定块里可能同时有近处栏杆、远处建筑和天空,单个 t_B 无法同时照顾它们。

为了减轻固定网格带来的块效应,可以让窗口围绕每个像素滑动:对像素 x,在所有覆盖它的候选块中选择代价更合适的块,而不是只用固定分块的结果。直觉上相当于让每个像素从周围局部块里取一个更稳的 t

这里也能看出后续工程优化的方向:如果对每个像素都枚举覆盖它的块,计算量会上去;区域统计、局部方差和代价搜索都需要更高效的实现。

Guided Filter 细化透射图

块级 t 只是一张粗透射图,还需要细化到边缘。Guided Filter 的假设是,在局部窗口 omega_k 内,输出透射率可以表示成引导图 I 的线性组合:

t^(q)=skTI(q)+ϕk,qωk \hat t(q)=s_k^T I(q)+\phi_k,\quad q\in \omega_k

s_k 是向量,phi_k 是偏移量,在同一个窗口内保持不变。通过最小二乘求:

(sk,ϕk)=argminsk,ϕkqωk(t(q)t^(q))2 (s_k^*,\phi_k^*)= \arg\min_{s_k,\phi_k} \sum_{q\in\omega_k}\left(t(q)-\hat t(q)\right)^2

这样做的意义是:用原图边缘引导透射图边缘。平坦区域继续平滑,物体边界处尽量保留深度突变。

视频去雾的时间一致性

单帧去雾直接逐帧应用到视频上,会遇到时间一致性问题:每帧单独估计 At,输出就可能闪。为了降低复杂度,可以把 RGB 转到 YUV,先用 Y 通道估计透射率,U/V 通道不参与核心估计。

一个简化假设是:相邻帧同一场景点的原始辐射值在短时间内近似不变:

JYk(p)JYk+1(p) J_Y^k(p)\approx J_Y^{k+1}(p)

如果大气光 A_Y 在短片段内也近似稳定,则有:

tk(p)=γk(p)tk+1(p) t_k(p)=\gamma_k(p)t_{k+1}(p)

其中:

γk(p)=IYk(p)AYIYk+1(p)AY \gamma_k(p)= \frac{I_Y^k(p)-A_Y}{I_Y^{k+1}(p)-A_Y}

这个关系只在“同一场景点”上成立。真实视频里有运动、遮挡、相机抖动和压缩噪声,所以不能硬约束每个像素。更稳的做法是用相邻帧差异构造一个权重:

wk(p)=exp((IYk(p)IYk+1(p))2σ2) w_k(p)=\exp\left( -\frac{(I_Y^k(p)-I_Y^{k+1}(p))^2}{\sigma^2} \right)

差异越小,权重越大,说明这个位置更可能可以使用时间一致性;差异越大,权重越小,减少错误约束。块级权重可写成:

wˉB=1NBpBwk(p) \bar w_B=\frac{1}{N_B}\sum_{p\in B}w_k(p)

于是可以把时间一致性写成额外代价:

Etemporal=wˉB(tB,kγBtB,k1)2 E_{temporal}=\bar w_B\left(t_{B,k}-\gamma_B t_{B,k-1}\right)^2

总目标变成:

E=Econtrast+λlEloss+λtEtemporal E=E_{contrast}+\lambda_l E_{loss}+\lambda_t E_{temporal}

这条视频扩展思路的价值在于提醒:视频去雾不能只看单帧对比度。大气光稳定性、透射率连续性、运动区域的错误约束,都需要被单独考虑。

可落地的算法链路

这条路线的优点是可解释、可控、能做实时优化;缺点是对 At 的估计都很敏感。优化基本围绕两个点:一是别把 A 当作简单的全局最亮点,二是别让递归区域统计和局部代价搜索重复计算。

使用社交账号登录

  • Loading...
  • Loading...
  • Loading...
  • Loading...
  • Loading...