2. 直方图均衡化去雾(HE)

直方图均衡化,说白了就是把图像的灰度分布「拉平」。有雾的图像通常对比度低,灰度集中在中间区域。均衡化就是把这些像素重新分配,让亮的地方更亮,暗的地方更暗。效果嘛——视觉上确实「通透」了。

但我得先泼盆冷水。这个方法简单,但用在去雾上,问题不少。我早期做项目时也踩过坑,后面会细说。

2.1 全局直方图均衡化原理

先看数学本质。对于一张灰度图,灰度级 r 的概率密度函数是:

p(r) = n_r / N

其中 n_r 是灰度 r 的像素数,N 是总像素数。均衡化就是找一个变换 s = T(r),让输出灰度 s 的分布接近均匀。这个变换就是累积分布函数(CDF):

s_k = T(r_k) = ∑_{j=0}^{k} p(r_j) = ∑_{j=0}^{k} n_j / N

然后映射到 [0, L-1] 区间:

s_k' = round( s_k × (L-1) )

就这么简单。但简单不等于好用。

核心理解: 直方图均衡化不是「去雾算法」,而是「对比度增强算法」。它不建模雾的物理过程,只是把像素重新排列。

2.2 MATLAB 实现与效果分析

MATLAB 里实现全局直方图均衡化,核心就一个函数:histeq。但我建议你手写一遍,理解内部机制。

2.2.1 灰度图均衡化

% 读取有雾图像
I = imread('foggy_scene.jpg');
if size(I, 3) == 3
    I_gray = rgb2gray(I);
else
    I_gray = I;
end

% 方法一:直接调用 histeq
I_eq = histeq(I_gray);

% 方法二:手写均衡化(理解原理)
[counts, bins] = imhist(I_gray);
cdf = cumsum(counts) / numel(I_gray);
cdf_scaled = uint8(cdf * 255);
I_eq_manual = cdf_scaled(I_gray + 1);

% 显示对比
figure;
subplot(2,2,1); imshow(I_gray); title('原始有雾灰度图');
subplot(2,2,2); imhist(I_gray); title('原始直方图');
subplot(2,2,3); imshow(I_eq);   title('均衡化结果');
subplot(2,2,4); imhist(I_eq);   title('均衡化后直方图');

运行这段代码,你会看到直方图被「拉平」了。但图像质量呢?嗯,这里就有问题了。

2.2.2 彩色图均衡化

彩色图不能直接对 RGB 三个通道分别做均衡化。为什么?因为 RGB 通道的亮度信息是耦合的,分开处理会导致颜色失真。我见过不少新手犯这个错。

正确的做法是转换到 HSV 或 Lab 色彩空间,只对亮度通道做均衡化:

% 正确做法:HSV 空间,只处理 V 通道
I = imread('foggy_scene.jpg');
I_hsv = rgb2hsv(I);
V = I_hsv(:,:,3);
V_eq = histeq(V);
I_hsv(:,:,3) = V_eq;
I_result = hsv2rgb(I_hsv);

% 错误做法(别学这个)
% I_r = histeq(I(:,:,1));
% I_g = histeq(I(:,:,2));
% I_b = histeq(I(:,:,3));
% I_wrong = cat(3, I_r, I_g, I_b);  % 颜色完全偏掉
我的习惯: 做彩色图像增强时,优先用 Lab 色彩空间。Lab 的 L 通道与颜色解耦更彻底,处理完再转回 RGB,色彩保真度比 HSV 好。

2.2.3 效果分析

我们来看一组典型结果。用一张浓雾图像测试:

指标 原始有雾图像 HE 处理后 变化
平均亮度 85.3 127.5 ↑ 提升
对比度(标准差) 32.1 74.8 ↑ 显著提升
信息熵 5.87 7.92 ↑ 提升
颜色自然度 较自然(偏灰) 过饱和、偏色 ↓ 下降
天空区域 均匀灰色 出现块状伪影 ↓ 下降

看到了吗?对比度和信息熵确实提升了,但代价是颜色失真和伪影。尤其是天空区域,原本均匀的灰度被拉伸成一块一块的,这就是「过度增强」的典型表现。

2.3 局限性讨论

直方图均衡化去雾的局限性,我总结为三点。这些坑,我在项目中都遇到过。

2.3.1 颜色失真问题

这是最明显的问题。均衡化不考虑色彩的自然分布,只是机械地拉伸灰度。结果就是:天空变蓝得发紫,树叶绿得不自然,人脸变成「阿凡达」。

我曾经做一个安防监控的去雾项目,用 HE 处理后,原本灰色的水泥路面变成了紫色。客户直接问:「你们这是给路面刷漆了吗?」——嗯,从那以后我再也不敢对监控图像直接用 HE 了。

2.3.2 过度增强与伪影

均衡化对像素密集的区域拉伸幅度大。有雾图像中,远景区域(天空、远山)的灰度分布本来就窄,均衡化后会被过度拉伸,产生块状伪影。

你想想看,原本天空的灰度范围是 [180, 200],只有 21 个灰度级。均衡化后要扩展到 [0, 255],中间必然出现断层。这就是伪影的来源。

2.3.3 噪声放大

均衡化对暗区域的拉伸特别厉害。有雾图像的暗部往往包含噪声,均衡化后噪声也被放大了。结果是:雾是去掉了,但图像变得「脏兮兮」的。

避坑指南: 如果图像本身信噪比低(比如手机拍的夜景有雾图),千万不要直接用 HE。噪声放大后,去雾效果还不如原图。我曾经吃过这个亏,后来养成了先做噪声评估的习惯。

2.3.4 局限性总结

我把 HE 的适用场景和不适用场景整理成一张表:

场景 HE 效果 说明
薄雾、轻度雾霾 ⭐⭐⭐ 可用 对比度提升明显,颜色失真可接受
浓雾、大雾 ⭐⭐ 勉强 伪影严重,颜色偏色明显
夜景有雾 ⭐ 不推荐 噪声放大严重,暗部细节丢失
航拍图像 ⭐⭐ 勉强 地物颜色失真,影响判读
监控视频 ⭐ 不推荐 帧间闪烁,颜色不稳定
医学内窥镜 ⭐⭐⭐ 可用 组织对比度提升,辅助诊断

说白了,HE 适合「锦上添花」,不适合「雪中送炭」。如果雾很轻,用 HE 提一下对比度还行。如果雾很浓,还是老老实实用后面章节的物理模型方法吧。

2.4 知识体系图

下面这张图总结了本章的核心逻辑。从原理到实现,再到局限性,一条线串起来。

直方图均衡化去雾(HE)知识体系 核心原理:CDF 映射拉伸 MATLAB 实现方式 灰度图:histeq() 或手写 CDF 彩色图:HSV/Lab → 仅处理亮度通道 效果分析(双刃剑) ✅ 对比度↑ 信息熵↑ 视觉通透 ❌ 颜色失真 伪影 噪声放大 三大局限性 ① 颜色失真 ② 过度增强/伪影 ③ 噪声放大 结论:薄雾可用,浓雾不推荐,需结合物理模型

这张图把 HE 的「从原理到落地」讲清楚了。你记住一句话:HE 是增强工具,不是去雾模型。用它做预处理可以,但别指望它能解决真正的去雾问题。