【opencv】OpenCV 图像增强实战:直方图均衡化与 CLAHE 原理及代码详解

文章目录


前言

我们在处理图像时,经常遇到 对比度太低、画面灰蒙蒙 的问题,比如夜晚拍摄的照片、医学 X 光片、昏暗环境下的监控画面。这些图像的像素灰度值往往集中在某个狭窄区间,导致细节难以辨认。

直方图均衡化(Histogram Equalization) 就是解决这类问题的经典方法,它通过重新分布像素灰度值,让图像的对比度显著提升。而 CLAHE(限制对比度自适应直方图均衡化) 则是它的进阶版,能避免全局均衡化带来的过度增强和噪声放大,尤其适合处理光照不均的复杂场景。

通过完整代码,理解原始图 → 全局均衡化 → CLAHE 三者的效果差异。


完整代码一览

代码可直接运行,图片路径请替换为自己的灰度图

样图:

c 复制代码
import matplotlib.pyplot as plt
import cv2
import numpy as np

black = cv2.imread('black.jpg', cv2.IMREAD_GRAYSCALE)

plt.hist(black.ravel(), bins=256)
plt.show()

black_equalize = cv2.equalizeHist(black)
plt.hist(black_equalize.ravel(), bins=256)
plt.show()

res = np.hstack((black, black_equalize))
cv2.imshow('black_equalize', res)
cv2.waitKey(0)

clahe = cv2.createCLAHE(clipLimit=10, tileGridSize=(8,8))
black_clahe = clahe.apply(black)
res = np.hstack((black, black_equalize, black_clahe))
cv2.imshow('black_equalize', res)
cv2.waitKey(0)

一、导入工具库与读取灰度图像

c 复制代码
import matplotlib.pyplot as plt
import cv2
import numpy as np

black = cv2.imread('black.jpg', cv2.IMREAD_GRAYSCALE)
  • import matplotlib.pyplot as plt:我们用它来绘制图像的灰度直方图,直观展示像素值分布。

  • import cv2:OpenCV 库,负责图像读写、均衡化、CLAHE 等所有图像处理操作。

  • import numpy as np:NumPy 提供高效的数组操作,我们后面会用 np.hstack 水平拼接图像,方便对比展示。

cv2.imread('black.jpg', cv2.IMREAD_GRAYSCALE):以灰度模式读取名为 black.jpg 的图片。cv2.IMREAD_GRAYSCALE 表示直接转为单通道灰度图,忽略颜色信息。如果你的图片是彩色的,这一步会自动将其灰度化,方便后续处理。

二、绘制原始图像的灰度直方图

c 复制代码
plt.hist(black.ravel(), bins=256)
plt.show()
  • black.ravel():将二维灰度图像展平为一维数组(所有像素值排成一行),因为 plt.hist 需要一维数据作为输入。

  • bins=256:灰度值范围是 0~255,共 256 个灰度级,设置 bins=256 就能统计每个灰度值上有多少个像素。

    处理之前的直方图:

原始图像的像素分布,如果图像偏暗,直方图会集中在左侧(低灰度区域);如果偏亮,则集中在右侧。如果图像对比度低,直方图会呈现"瘦高"形态,聚集在中间一小段。

三、全局直方图均衡化

c 复制代码
black_equalize = cv2.equalizeHist(black)
plt.hist(black_equalize.ravel(), bins=256)
plt.show()

cv2.equalizeHist(black):对原始灰度图执行全局直方图均衡化。它的核心思想是:把原始图像的灰度分布"拉伸"到整个 0~255 区间,让每个灰度级上的像素数量尽可能均匀,从而提升整体对比度。

均衡后的直方图:

四、水平拼接原图与均衡图,直观对比效果

c 复制代码
res = np.hstack((black, black_equalize))
cv2.imshow('black_equalize', res)
cv2.waitKey(0)

np.hstack((图像1, 图像2)):将两幅图像水平拼接(左右并排)。注意它们的高度必须一致,这里都是同一张图,尺寸相同,所以可以拼接。

生成结果:

五、CLAHE ------ 限制对比度的自适应均衡化

全局均衡化虽然强大,但也有缺点:它会过度放大噪声,并且在光照不均匀的区域(比如半边亮半边暗)效果不理想。为此,OpenCV 提供了 CLAHE(限制对比度自适应直方图均衡化) 作为改进方案。

c 复制代码
clahe = cv2.createCLAHE(clipLimit=10, tileGridSize=(8,8))
black_clahe = clahe.apply(black)
res = np.hstack((black, black_equalize, black_clahe))
cv2.imshow('black_equalize', res)
cv2.waitKey(0)

第一行代码有两个关键参数

  1. clipLimit:对比度限制阈值。直方图均衡化时,如果某个灰度级的像素数超过此阈值,会被"裁剪"并均匀分配到其他灰度级,从而防止局部对比度过大,抑制噪声放大。数值越大,增强力度越强;一般设置 2~10 之间,这里取 10 为演示。
  2. tileGridSize:将图像划分为若干小块(tile),每个小块独立进行直方图均衡化。(8,8) 表示将图像分成 8×8 = 64 个小块,每个小块分别处理,最后再通过双线性插值拼接起来,这样能适应局部光照变化。小块尺寸越小,自适应能力越强,但计算量也越大。

生成结果:

六、总结

方法 优点 缺点
全局直方图均衡化 代码简单,整体对比度提升明显 易放大噪声,无法适应局部光照变化
CLAHE 自适应局部增强,噪声抑制好,效果自然 参数需调优,计算量稍大