2. 直方图均衡化原理
直方图均衡化,说白了就是让图像的灰度分布更均匀。你想想看,一张曝光不足的照片,像素都挤在暗区;一张过曝的照片,像素都堆在亮区。这两种情况,图像的细节都看不清楚。
我刚开始接触图像增强时,总觉得调亮度、拉对比度就够了。直到有一次处理医学X光片,怎么调都看不清病灶边缘。后来用了直方图均衡化,效果立竿见影。嗯,从那以后我就把这招当成了图像预处理的标配。
2.1 核心思想:把灰度分布“拉平”
直方图均衡化的目标很简单:让输出图像的直方图尽可能平坦。也就是说,每个灰度级上的像素数量大致相等。
为什么这样做能增强图像?因为人眼对对比度敏感。当像素均匀分布在各个灰度级上时,图像的动态范围被充分利用,暗部细节和亮部细节都能看清楚。
核心公式:对于输入灰度 r,输出灰度 s 的映射关系为:
s = T(r) = (L-1) × ∫₀ʳ p_r(w) dw
其中 L 是灰度级数(通常为256),p_r(r) 是输入图像的概率密度函数。
2.2 累积分布函数:从概率到映射
这里的关键是累积分布函数(CDF)。我习惯把它理解成“小于等于某个灰度值的像素占比”。
对于离散图像,我们处理的是直方图而不是概率密度函数。假设图像有 N 个像素,灰度级 r_k 的像素数为 n_k,那么:
p_r(r_k) = n_k / N // 概率密度
cdf(r_k) = Σⱼ₌₀ᵏ p_r(r_j) // 累积分布
映射关系就变成了:
s_k = T(r_k) = (L-1) × cdf(r_k)
为什么会这样?因为 CDF 天然是一个从0到1的单调递增函数,乘以 (L-1) 后正好映射到 [0, L-1] 的灰度范围。
我的经验:实际计算时,CDF 的最小值可能不是0。我习惯先计算 CDF,然后做归一化:
s_k = (L-1) × (cdf(r_k) - cdf_min) / (1 - cdf_min)
这样能保证输出图像的最小灰度是0,最大灰度是 L-1。
2.3 映射关系推导:一步步来
我们用一个具体例子走一遍流程。假设一张3×3的灰度图像,灰度范围0-7(L=8):
| 灰度级 r_k | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|---|---|---|---|---|---|---|---|---|
| 像素数 n_k | 2 | 1 | 0 | 3 | 1 | 0 | 1 | 1 |
| 概率 p_r | 2/9 | 1/9 | 0 | 3/9 | 1/9 | 0 | 1/9 | 1/9 |
| CDF | 2/9 | 3/9 | 3/9 | 6/9 | 7/9 | 7/9 | 8/9 | 1 |
| 映射 s_k | 1.56 | 2.33 | 2.33 | 4.67 | 5.44 | 5.44 | 6.22 | 7 |
| 取整 | 2 | 2 | 2 | 5 | 5 | 5 | 6 | 7 |
你看,原来灰度0的像素(2个)被映射到灰度2;灰度3的像素(3个)被映射到灰度5。输出图像的直方图明显比输入更均匀了。
注意:取整操作会导致多个输入灰度映射到同一个输出灰度。这是信息损失,但通常不影响视觉效果。我曾经在遥感图像处理中遇到过因为取整导致条带效应的问题,后来改用插值映射解决了。
2.4 数学证明:为什么CDF映射能均衡化
你可能想问:为什么用CDF做映射就能让直方图变平?我们来简单证明一下。
假设输入 r 的概率密度函数是 p_r(r),映射函数 s = T(r) 单调递增。那么输出 s 的概率密度函数为:
p_s(s) = p_r(r) × |dr/ds|
当 T(r) = (L-1) × ∫₀ʳ p_r(w) dw 时:
ds/dr = (L-1) × p_r(r)
p_s(s) = p_r(r) × 1/[(L-1) × p_r(r)] = 1/(L-1)
看到了吗?输出概率密度函数变成了常数 1/(L-1)。这就是完美的均匀分布!
当然,这是连续情况下的理想结果。离散情况下,由于取整和采样问题,只能做到近似均匀。
2.5 直方图均衡化流程总结
- 计算直方图:统计每个灰度级的像素数 n_k
- 计算概率密度:p_r(r_k) = n_k / N
- 计算累积分布:cdf(r_k) = Σⱼ₌₀ᵏ p_r(r_j)
- 计算映射:s_k = round((L-1) × cdf(r_k))
- 应用映射:将输入图像每个像素的灰度替换为映射后的灰度
我的建议:实际编码时,第4步可以用查表法加速。先建一个256长度的映射表,然后直接查表替换像素值。OpenCV的 cv2.equalizeHist() 就是这么干的。
2.6 知识结构图
下面这张图展示了直方图均衡化的完整知识体系:
2.7 直方图均衡化的特点
| 优点 | 缺点 |
|---|---|
| 自动增强,无需手动参数 | 可能过度增强噪声 |
| 计算简单,速度快 | 输出灰度级可能减少(取整合并) |
| 对曝光不足/过度有效 | 对自然图像可能不自然 |
| 可逆操作(理论上) | 对平坦区域效果差 |
避坑指南:我曾经在处理医学CT图像时,直接对整个图像做直方图均衡化,结果把背景噪声也增强了,病灶反而看不清。后来我改用自适应直方图均衡化(AHE),只对局部区域做均衡化,效果就好多了。这个我们后面章节会详细讲。