3. 传统增强方法(一):直方图均衡化(HE)、自适应直方图均衡化(AHE)、限制对比度自适应直方图均衡化(CLAHE)
聊到低照度图像增强,很多人第一反应就是上深度学习。但说实话,在我十几年的ISP调试生涯里,真正在产线上用得最多、最稳的,反而是今天要讲的这三个传统方法。它们就像工具箱里的螺丝刀——不花哨,但关键时刻真能解决问题。
直方图均衡化(HE)、自适应直方图均衡化(AHE)、限制对比度自适应直方图均衡化(CLAHE),这三兄弟是递进关系。咱们一个一个拆开看。
3.1 直方图均衡化(HE)——最朴素的亮度拉伸
HE的原理其实特别简单。你想想看,一张暗图,它的像素大多挤在低灰度区。HE要做的,就是把这种“挤在一起”的分布,强行拉开,让整个灰度范围都利用起来。
数学上,它用的是累积分布函数(CDF)做映射。我直接给你看代码,比讲公式直观得多:
import cv2
import numpy as np
# 读取低照度图像(灰度)
img = cv2.imread('dark_scene.png', 0)
# 直方图均衡化
equ = cv2.equalizeHist(img)
# 拼接对比
result = np.hstack((img, equ))
cv2.imwrite('he_result.png', result)
就一行 cv2.equalizeHist(),效果立竿见影。但——嗯,这里要注意,HE有个致命伤:它是对整张图做全局映射。如果图像里既有亮区又有暗区,HE会把亮区拉得更亮,暗区压得更暗。我在项目中遇到过,用HE处理夜间监控画面,结果路灯区域过曝成一片白,完全没法看。
3.2 自适应直方图均衡化(AHE)——局部救星
HE的全局问题怎么解决?我当时的想法是:既然全局不行,那就分块做。AHE就是这么干的——把图像分成若干个小窗口,在每个窗口内独立做HE。
这样做的好处很明显:每个局部都能得到最适合自己的拉伸。暗区不会被亮区拖累,亮区也不会被暗区影响。
但AHE也有新问题。我直接说痛点:
- 计算量大:每个窗口都要算一次CDF,实时性堪忧
- 块效应严重:窗口边界处会出现明显的拼接痕迹
- 噪声放大更猛:在均匀区域(比如天空、墙壁),AHE会把微小的噪声差异放大成明显的颗粒
我记得有一次调试车载夜视系统,用AHE处理路面图像,结果柏油路面的纹理被过度增强,看起来像龟裂一样。客户直接问:“你们这摄像头是不是坏了?”
3.3 限制对比度自适应直方图均衡化(CLAHE)——工程最优解
CLAHE就是在AHE基础上打了两个补丁:
- 限制对比度:在计算直方图时,设定一个阈值,把超过阈值的部分裁剪掉,再均匀分布到整个灰度区间。说白了,就是不让任何一个灰度级“太突出”。
- 双线性插值:消除块效应。每个像素的映射值,由它周围四个窗口的映射结果插值得到。
这两个改进,直接让CLAHE成了工程界的宠儿。我直接给你看OpenCV的实现参数:
import cv2
# 创建CLAHE对象
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
# 应用CLAHE
img = cv2.imread('dark_scene.png', 0)
clahe_img = clahe.apply(img)
# 保存结果
cv2.imwrite('clahe_result.png', clahe_img)
参数就两个,但调起来门道很多:
| 参数 | 作用 | 我的调参建议 |
|---|---|---|
clipLimit |
对比度限制阈值,越大增强越强 | 低照度场景建议2.0~4.0,过曝场景建议1.0~2.0 |
tileGridSize |
分块大小,影响局部自适应程度 | 默认8×8,细节丰富场景可降到4×4,平滑场景可升到16×16 |
3.4 三者的核心差异对比
我习惯用一张表来总结它们的区别,这样你在选型时一眼就能看明白:
| 方法 | 作用域 | 噪声控制 | 计算开销 | 适用场景 |
|---|---|---|---|---|
| HE | 全局 | 差 | 低 | 光照均匀的图像(文档、X光) |
| AHE | 局部(分块) | 极差 | 高 | 需要局部增强但不介意噪声(科研实验) |
| CLAHE | 局部(分块+插值) | 好 | 中 | 工程落地首选(监控、车载、手机拍照) |
3.5 知识体系结构图
下面这张图,把三者的演进关系、核心机制和工程权衡画清楚了。你保存下来,以后做方案选型时直接对照:
3.6 实战中的选择建议
最后,我结合自己的项目经验,给你几条实在的建议:
- 做预处理:如果你只是想把图像提亮一点做后续分析,CLAHE是首选。clipLimit设2.0,tileGridSize设8×8,基本不会翻车。
- 做实时系统:如果算力有限(比如嵌入式设备),可以考虑HE或者降低CLAHE的分块数。我曾在海思3516上跑CLAHE,tileGridSize设16×16,帧率能稳定在30fps。
- 做3A联动:CLAHE的结果可以用来指导AE的目标亮度调整。比如,CLAHE增强后如果暗区仍然偏暗,说明当前曝光不足,需要提高AE target。
- 做对比实验:别只盯着PSNR/SSIM。我建议你同时看增强后的局部对比度和噪声水平,这两个指标往往比全局指标更能反映实际效果。