
在计算机视觉领域,雾天等恶劣天气会导致图像对比度下降、细节模糊,严重影响后续的目标检测、图像分割等任务。图像去雾算法作为解决这一问题的核心技术,已广泛应用于自动驾驶、监控安防、遥感航拍等场景。本文将从基础原理出发,系统梳理传统去雾算法与深度学习去雾算法的核心思想、实现流程,并附上Python实操代码,帮助大家快速掌握图像去雾技术。
一、图像去雾的核心原理:大气散射模型
雾天图像的退化本质是大气散射导致的光线衰减,所有去雾算法的核心都是基于这一物理模型反向求解。
1. 大气散射模型公式
雾天退化图像的数学表达为:
I(x,y)=J(x,y)⋅t(x,y)+A⋅(1−t(x,y))I(x,y) = J(x,y) \cdot t(x,y) + A \cdot (1 - t(x,y))I(x,y)=J(x,y)⋅t(x,y)+A⋅(1−t(x,y))
- I(x,y)I(x,y)I(x,y):输入的雾天图像(观测值)
- J(x,y)J(x,y)J(x,y):无雾原始图像(待求解目标)
- t(x,y)t(x,y)t(x,y):透射率,反映光线到达相机的衰减程度(t∈[0,1]t \in [0,1]t∈[0,1],t=1t=1t=1 表示无衰减)
- AAA:大气光,雾天环境中的全局光照强度(通常为常数)
2. 去雾的核心目标
通过已知的 I(x,y)I(x,y)I(x,y),估算出 t(x,y)t(x,y)t(x,y) 和 AAA,再代入公式推导得到无雾图像 J(x,y)J(x,y)J(x,y):
J(x,y)=I(x,y)−Amax(t(x,y),t0)+AJ(x,y) = \frac{I(x,y) - A}{max(t(x,y), t_0)} + AJ(x,y)=max(t(x,y),t0)I(x,y)−A+A
其中 t0t_0t0 是最小透射率阈值(通常取 0.1),避免分母过小导致图像失真。
二、经典传统去雾算法:原理与实现
传统去雾算法的核心是通过先验知识 估算透射率 t(x,y)t(x,y)t(x,y) 和大气光 AAA,无需大量数据训练,实时性强。
1. 暗通道先验算法(DCP):最经典的传统方法
1.1 核心先验假设
自然无雾图像中,除了天空等亮区域,绝大多数局部区域(如 15×15 窗口)至少有一个通道(R/G/B)的像素值接近 0,这一区域称为"暗通道"。
1.2 算法步骤
- 计算暗通道 :对雾天图像的每个像素,在局部窗口内取 R/G/B 三通道最小值,再对整个窗口取最小值,得到暗通道图像 dark(x,y)dark(x,y)dark(x,y)。
- 估算大气光 A :在暗通道图像中选取亮度最高的前 0.1% 像素,对应到原始雾天图像中取这些像素的最大值作为 AAA。
- 估算初始透射率 :基于暗通道假设推导初始透射率 tinit(x,y)=1−ω⋅minc(Ic(x,y)Ac)t_{init}(x,y) = 1 - \omega \cdot min_c(\frac{I_c(x,y)}{A_c})tinit(x,y)=1−ω⋅minc(AcIc(x,y))(ω\omegaω 为雾保留系数,通常取 0.95)。
- 透射率优化:用软matting或导向滤波对初始透射率进行平滑处理,避免去雾后图像出现块效应。
- 恢复无雾图像 :代入公式计算 J(x,y)J(x,y)J(x,y)。
1.3 Python 实现(OpenCV)
python
import cv2
import numpy as np
def dark_channel(img, window_size=15):
"""计算暗通道图像"""
min_rgb = cv2.erode(cv2.min(img, axis=2), np.ones((window_size, window_size), np.uint8))
return min_rgb
def estimate_atmospheric_light(img, dark_img):
"""估算大气光 A"""
h, w = img.shape[:2]
# 选取暗通道中前0.1%的亮像素
num_pixels = int(h * w * 0.001)
flat_img = img.reshape(-1, 3)
flat_dark = dark_img.flatten()
# 按暗通道亮度降序排序
indices = np.argsort(-flat_dark)[:num_pixels]
# 取这些像素在原始图像中的最大值作为A
A = np.max(flat_img[indices], axis=0)
return A.astype(np.float64)
def estimate_transmission(img, A, omega=0.95, window_size=15):
"""估算初始透射率"""
normalized_img = img.astype(np.float64) / A
min_norm = cv2.erode(cv2.min(normalized_img, axis=2), np.ones((window_size, window_size), np.float64))
transmission = 1 - omega * min_norm
return transmission
def guided_filter(img, guide, radius=60, eps=1e-3):
"""导向滤波优化透射率"""
return cv2.ximgproc.guidedFilter(guide=guide, src=img, radius=radius, eps=eps)
def dehaze(img, window_size=15, omega=0.95, t0=0.1):
"""暗通道先验去雾主函数"""
# 1. 计算暗通道
dark_img = dark_channel(img, window_size)
# 2. 估算大气光A
A = estimate_atmospheric_light(img, dark_img)
# 3. 估算初始透射率
t_init = estimate_transmission(img, A, omega, window_size)
# 4. 导向滤波优化透射率
t_refined = guided_filter(t_init, img[:, :, 0], radius=60, eps=1e-3)
# 5. 限制最小透射率,避免失真
t_refined = np.maximum(t_refined, t0)
# 6. 恢复无雾图像
img_float = img.astype(np.float64)
J = (img_float - A) / t_refined[..., np.newaxis] + A
# 像素值裁剪到[0,255]
J = np.clip(J, 0, 255).astype(np.uint8)
return J
# 测试代码
if __name__ == "__main__":
# 读取雾天图像
foggy_img = cv2.imread("foggy_image.jpg")
# 去雾处理
dehazed_img = dehaze(foggy_img)
# 保存结果
cv2.imwrite("dehazed_image.jpg", dehazed_img)
# 显示对比
cv2.imshow("Foggy Image", foggy_img)
cv2.imshow("Dehazed Image", dehazed_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
2. 其他传统去雾算法对比
| 算法名称 | 核心思想 | 优点 | 缺点 |
|---|---|---|---|
| 直方图均衡化(HE) | 拉伸图像灰度范围,提升对比度 | 实现简单、实时性强 | 易过度增强噪声,色彩失真 |
| Retinex 算法 | 分离图像的照度和反射分量,修正照度 | 色彩还原好 | 对厚雾效果差,易出现光晕 |
| 基于偏振的去雾 | 利用偏振光分离散射光和目标光 | 物理模型精确 | 需专用偏振相机,场景受限 |
三、深度学习去雾算法:端到端的解决方案
传统算法依赖人工设计的先验,在厚雾、不均匀雾场景下效果有限。深度学习通过数据驱动自动学习去雾规律,实现端到端去雾,性能更优。
1. 深度学习去雾的核心思路
- 把去雾视为图像复原任务 :输入雾天图像 III,输出无雾图像 JJJ,模型直接学习 I→JI \rightarrow JI→J 的映射关系。
- 无需手动估算透射率和大气光,由网络自动学习退化模型的逆过程。
2. 经典深度学习去雾模型
2.1 DehazeNet(2016):首个CNN去雾模型
- 核心结构:5层卷积网络,通过"特征提取→多尺度融合→透射率估计→图像恢复"四步实现去雾。
- 创新点:首次用CNN替代人工先验估算透射率,验证了深度学习在去雾任务中的有效性。
2.2 AOD-Net(2017):轻量级端到端模型
- 核心结构:简化网络设计,仅用3层卷积,直接输出无雾图像。
- 创新点:提出"所有雾都可被表示为 A−A⋅tA - A \cdot tA−A⋅t",简化模型参数,实时性大幅提升(FPS达30+)。
2.3 基于Transformer的去雾模型(2020后)
- 核心优势:CNN擅长提取局部特征,而Transformer的自注意力机制能捕捉全局雾浓度分布,解决不均匀雾去雾难题。
- 代表模型:DehazeFormer、Restormer(通用图像复原模型,去雾效果顶尖)。
3. 深度学习去雾的关键要素
- 数据集:常用公开数据集有 RESIDE(最大去雾数据集,含合成雾和真实雾图像)、HazeRD。
- 损失函数:采用 L1 损失(减少模糊)+ 感知损失(提升视觉质量)+ 对抗损失(GAN-based模型,增强细节)。
- 训练技巧:使用数据增强(随机裁剪、翻转、雾浓度变化)提升模型泛化能力。
四、算法性能评估与对比
1. 客观评价指标
- 峰值信噪比(PSNR):衡量去雾后图像与真实无雾图像的像素误差,值越高越好(通常≥25dB为优秀)。
- 结构相似性(SSIM):衡量图像的结构一致性,值越接近1越好。
- 运行速度(FPS):实时场景(如自动驾驶)需≥30FPS。
2. 不同算法性能对比
| 算法类型 | PSNR(dB) | SSIM | FPS(CPU) | 适用场景 |
|---|---|---|---|---|
| 暗通道先验(DCP) | 22-28 | 0.75-0.85 | 5-10 | 非实时、轻雾场景 |
| AOD-Net | 28-32 | 0.85-0.92 | 30+ | 实时场景、移动端部署 |
| DehazeFormer | 32-38 | 0.92-0.96 | 10-20 | 高精度场景、厚雾去雾 |
五、总结与未来展望
1. 核心总结
- 传统去雾算法(如DCP)依赖物理先验,实现简单、实时性强,但对复杂雾场景适应性差。
- 深度学习去雾通过端到端学习,能处理厚雾、不均匀雾,视觉效果更优,但需大量数据训练,部分模型计算量较大。
- 实际应用中需根据场景选择:实时场景用AOD-Net,高精度场景用DehazeFormer,资源受限场景用DCP。
2. 未来趋势
- 实时高精度去雾:结合轻量化网络(如MobileNet、ShuffleNet)与Transformer,平衡速度和性能。
- 跨场景适配:解决真实雾与合成雾的域差异,提升模型在真实场景的泛化能力。
- 多任务融合:将去雾与目标检测、语义分割等任务联合训练,满足端到端视觉系统需求。