请注意:笔记内容片面粗浅,请读者批判着阅读!
一、直方图处理的核心理论
1. 直方图均衡化(Histogram Equalization)
直方图均衡化的目标是将图像的灰度分布调整为近似均匀分布,从而增强对比度。其核心步骤如下:
1.计算灰度直方图 :统计每个灰度级出现的频数。
2.计算累积分布函数(CDF) :将直方图归一化为概率分布,并计算累积概率。
3.映射到新灰度级 :根据CDF将原灰度级映射到新的灰度级范围(例如0-255)。
数学公式:
s k = T ( r k ) = ( L − 1 ) ∑ j = 0 k n j N s_k = T(r_k) = (L - 1) \sum_{j=0}^{k} \frac{n_j}{N} sk=T(rk)=(L−1)j=0∑kNnj
其中,
L
为最大灰度级n_j
为灰度级r_j
的像素数N
为总像素数
理论局限性:- 离散灰度级会导致均衡化后的直方图不完全均匀(灰度级归并现象)。
- 可能过度增强噪声或背景 .
2. 直方图规定化(Histogram Matching)
直方图规定化将输入图像的直方图映射到指定目标直方图分布,适用于需要特定对比度调整的场景。核心步骤:
1.分别对输入图像和目标图像进行均衡化,得到各自的CDF。
2.建立输入图像CDF到目标CDF的映射关系。
3.通过反向映射函数重构像素值 。
二、Python代码实现
1. 直方图均衡化
python
import cv2
import matplotlib.pyplot as plt
from pylab import mpl
# 设置显示中文字体
mpl.rcParams["font.sans-serif"] = ["SimHei"]
# 设置正常显示符号
mpl.rcParams["axes.unicode_minus"] = False
# 读取灰度图像
img = cv2.imread('f.png', 0)
# 直方图均衡化
equ = cv2.equalizeHist(img)
# 显示结果
plt.figure(figsize=(12, 6))
plt.subplot(221), plt.imshow(img, cmap='gray'), plt.title('原始图像')
plt.subplot(222), plt.imshow(equ, cmap='gray'), plt.title('均衡化图像')
plt.subplot(223), plt.hist(img.ravel(), 256, [0,256], color='r')
plt.subplot(224), plt.hist(equ.ravel(), 256, [0,256], color='b')
plt.show()
代码解析 :
cv2.equalizeHist()直接完成均衡化,适用于灰度图像。
直方图对比显示均衡后灰度分布更均匀。
2. 直方图规定化
直方图规定化是指通过灰度映射函数,将灰度直方图改造成所希望的直方图,从而有选择地增强某个灰度值范围内的对比度,使图像灰度值的分布满足特定的要求。
python
from scipy.interpolate import interp1d
import numpy as np
import cv2
import matplotlib.pyplot as plt
from pylab import mpl
# 设置显示中文字体
mpl.rcParams["font.sans-serif"] = ["SimHei"]
# 设置正常显示符号
mpl.rcParams["axes.unicode_minus"] = False
def histogram_matching(src, target):
# 计算输入图像和目标图像的CDF
src_hist, _ = np.histogram(src.flatten(), 256, [0, 256])
target_hist, _ = np.histogram(target.flatten(), 256, [0, 256])
# 归一化并计算累积分布
src_cdf = (src_hist.cumsum() / src.size).clip(0, 1)
target_cdf = (target_hist.cumsum() / target.size).clip(0, 1)
# 解决CDF平顶问题:添加微小梯度
src_cdf += np.linspace(0, 1e-6, 256)
target_cdf += np.linspace(0, 1e-6, 256)
# 构建反向映射函数(允许外推)
inverse_func = interp1d(target_cdf, np.arange(256),
bounds_error=False,
fill_value=(0, 255),
assume_sorted=True)
# 生成映射表并应用
lookup_table = inverse_func(src_cdf).astype(np.uint8)
return np.clip(lookup_table[src], 0, 255)
if __name__ == "__main__":
# 读取图像
try:
src_img = cv2.imread(r"D:\software\opencv\opencv\sources\samples\data\basketball1.png", 0) # 输入图像
target_img = cv2.imread(r"D:\software\opencv\opencv\sources\samples\data\butterfly.jpg", 0) # 目标图像
# 执行直方图匹配
matched_img = histogram_matching(src_img, target_img)
# 可视化对比
plt.figure(figsize=(15, 5))
plt.subplot(131), plt.imshow(src_img, cmap='gray')
plt.title('原始图像'), plt.axis('off')
plt.subplot(132), plt.imshow(target_img, cmap='gray')
plt.title('目标图像'), plt.axis('off')
plt.subplot(133), plt.imshow(matched_img, cmap='gray')
plt.title('匹配结果'), plt.axis('off')
plt.tight_layout()
plt.show()
except Exception as e:
print(f"错误: {e}")
print("提示:请检查图像路径是否存在")
关键点 :
使用插值函数interp1d建立输入CDF到目标CDF的映射关系。
映射表需处理离散值的近似问题。
三、实验结果分析
1. 均衡化效果
原始图像 :灰度集中在中低亮度区域,对比度低。
均衡化后 :灰度分布扩展到全范围,暗部细节增强(如实验图pout.tif)。
直方图对比:均衡化后直方图呈现"平台状",但非完全平坦(离散灰度级导致)。
2. 规定化效果
若目标直方图为高斯分布,则输出图像具有自然过渡的对比度。
实际应用中需注意目标直方图的合理性,避免引入噪声。
四、总结
直方图处理是数字图像增强的基础技术,均衡化与规定化分别适用于全局和特定对比度调整需求。Python实现中需注意离散灰度级的影响及插值方法的选择。实际应用中可结合CLAHE或分通道处理优化结果,同时需权衡增强效果与噪声控制。