计算机视觉(opencv)实战十七——图像直方图均衡化
直方图与直方图均衡化原理详解
图像处理领域中,直方图是一种非常重要的工具,它能够反映一幅图像中像素灰度分布的整体情况。而直方图均衡化则是一种常用的图像增强技术,可以有效改善图像的对比度,使暗部更亮、亮部更亮,从而让细节更加清晰。
本文将通过理论讲解和代码示例,帮助理解直方图及均衡化的原理与应用。
一、直方图的概念与作用
直方图是一种统计图,它记录了图像中各个灰度值出现的次数。
假设图像是 8 位灰度图像,那么每个像素灰度范围是 0~255,直方图就有 256 个柱子,每个柱子代表对应灰度值的像素数量。
横轴:灰度值 (0 ~ 255)。
纵轴:该灰度值的像素出现频率或次数。
直方图能够快速反映图像的亮暗分布:
如果直方图集中在左边,说明图像偏暗;
集中在右边,说明图像偏亮;
集中在中间且分布较窄,说明图像对比度较低,灰度层次不明显;
分布较均匀且覆盖整个灰度范围,说明图像对比度较高,细节丰富。
二、直方图均衡化的原理
1. 问题动机
如果图像的灰度分布比较集中,比如大量像素集中在 100 ~ 150 之间,那么整幅图像会显得灰蒙蒙、对比度低。这种情况就需要对像素的分布进行“拉伸”,让灰度值尽可能覆盖整个 0~255 区间。
2. 基本原理
直方图均衡化的核心思想是 重新分配像素灰度值,让直方图分布更加均匀。
具体步骤如下:
统计图像直方图,得到每个灰度值的概率分布;
计算累积分布函数 (CDF);
用 CDF 作为映射函数,把原始灰度值映射到新的灰度值,使得像素分布更均匀;
输出的图像对比度被增强,暗区更亮、亮区更暗,使细节更突出。
这种方法的优点是简单、高效,缺点是可能导致某些图像过度增强,细节丢失或噪声被放大。
三、局部直方图均衡化(CLAHE)
全局直方图均衡化对整幅图像使用同一个映射函数,有时会导致过度增强或亮度不均。为了保留细节,可以使用 自适应直方图均衡化(CLAHE, Contrast Limited Adaptive Histogram Equalization)。
CLAHE 将图像分为小块(tiles),在每个小块上分别做直方图均衡化,再把结果拼接起来,从而在局部区域增强对比度。
此外,CLAHE 有一个 clipLimit 参数,用来限制对比度增强的幅度,防止过度增强产生噪声。
四、代码讲解
下面的代码演示了直方图的绘制、全局直方图均衡化以及局部均衡化的效果。
# 直方图均衡化:直方图均衡化是一种图像增强技术,它可以通过增加图像的对比度和亮度来改善图像的质量。
# 直方图均衡化通过将图像的像素值分布均匀化来实现这一目标。
# 在Python OpenCV中,可以使用cv2.equalizeHist()函数来实现直方图均衡化。
# 该函数将输入图像转换为灰度图像,并将其像素值分布均匀化,从而增强图像的对比度和亮度。
import cv2
import matplotlib.pyplot as plt
import numpy as npwoman = cv2.imread('face.jpg', cv2.IMREAD_GRAYSCALE)
# # # phone_hist = cv2.calcHist([phone], [0], None, [256], [0,256])
plt.hist(woman.ravel(), bins=256)#numpy中的ravel将数组多维度拉成一维数组
plt.show()woman_equalize = cv2.equalizeHist(woman)
plt.hist(woman_equalize.ravel(), bins=256)#numpy中的ravel将数组多维度拉成一维数组
plt.show()res = np.hstack((woman, woman_equalize))#横向拼接,将多个数组按水平方向(列顺序)堆叠成一个新的数组。
cv2.imshow('woman_equalize', res)
cv2.waitKey(0)
# # # 自适应直方图均衡化(局部直方图处理),通过局部调整图像的直方图分布来提升图像的对比度和细节表现力,当需要保存细节特征,需要做局部处理
# # # cv2.createCLAHE([, clipLimit[, tileGridSize]]) → retval
# # # 参数说明:
# # # clipLimit:颜色对比度的阈值,可选项,默认值 8
# # # tileGridSize:局部直方图均衡化的模板(邻域)大小,可选项,默认值 (8,8)
clahe = cv2.createCLAHE(clipLimit=1, tileGridSize=(16, 16))#通过类创建了一个局部均衡化对象
woman_clahe = clahe.apply(woman)
res = np.hstack((woman, woman_equalize, woman_clahe))
cv2.imshow('phone_equalize', res)
cv2.waitKey(0)
代码解析
加载图像:
使用cv2.imread(..., cv2.IMREAD_GRAYSCALE)
将图像读为灰度图,便于后续处理。绘制原始直方图:
plt.hist(woman.ravel(), bins=256)
统计原始图像灰度分布。ravel()
将二维数组展平,便于统计。全局均衡化:
cv2.equalizeHist(woman)
对整幅图像进行直方图均衡化,使直方图分布更均匀。显示对比效果:
np.hstack((woman, woman_equalize))
将原图和均衡化图横向拼接,方便观察效果。局部均衡化(CLAHE):
clipLimit=1
限制对比度增强,防止噪声放大。tileGridSize=(16, 16)
将图像分为 16x16 小块,每块单独均衡化。clahe.apply(woman)
对原图应用局部均衡化。
最终显示三图对比:
左图:原始灰度图
中图:全局均衡化图
右图:局部均衡化图(对比度提升更明显,细节保留更好)
五、应用场景
医学影像:增强 X 光片、CT 图像的细节,使病灶更清晰;
工业检测:增强低对比度图像,提高缺陷检测的准确率;
夜间监控:提高暗光环境下图像可见性;
OCR 识别:提升文档对比度,减少噪声干扰,提高文字识别准确率。
六、总结
直方图是分析图像亮度分布的重要工具,而直方图均衡化能够有效提升图像对比度。
全局均衡化简单高效,但可能会损失局部细节;自适应直方图均衡化(CLAHE)通过分块处理,可以更好地保留局部细节,增强效果更自然。
通过本文及代码演示,可以直观理解直方图均衡化的原理与实际效果,掌握其在图像增强中的应用。
要不要我帮你画一张示意图,展示直方图均衡化前后灰度分布的变化(比如用两张直方图对比)?这样文章会更直观。