数字图像处理——直方图的均衡化
数字图像处理——直方图的均衡化
直方图均衡化是一种常用的图像增强方法,通过调整图像的亮度分布来提高图像的对比度。这种方法在医学影像、消费类电子产品等领域有着广泛的应用。本文将从原理、实现过程和代码示例等多个维度详细介绍直方图均衡化的技术细节。
1. 方法简介
直方图均衡化通常用来增加许多图像的全局对比度,尤其是当图像的有用数据的对比度相当接近的时候。通过这种方法,亮度可以更好地在直方图上分布。这样就可以用于增强局部的对比度而不影响整体的对比度,直方图均衡化通过有效地扩展常用的亮度来实现这种功能。
这种方法对于背景和前景都太亮或者太暗的图像非常有用,这种方法尤其是可以带来X光图像中更好的骨骼结构显示以及曝光过度或者曝光不足照片中更好的细节。这种方法的一个主要优势是它是一个相当直观的技术并且是可逆操作,如果已知均衡化函数,那么就可以恢复原始的直方图,并且计算量也不大。这种方法的一个缺点是它对处理的数据不加选择,它可能会增加背景噪声的对比度并且降低有用信号的对比度。
直方图均衡技术将原始图像的灰度直方图从比较集中的某个灰度区间变成在全部灰度范围内的均匀分布, 由于其算法简单, 无需借助外来因素的参数设置,可以自成系统的运行, 有效地增强图像对比度, 是一种常用的图像增强方法. 一直以来, 直方图均衡技术受到各个领域的重视, 比如在消费类电子产品邻域, 在均衡图像的同时希望保持图像的亮度信息 。
2. 实现过程
我们来看一个灰度图像,让ni表示灰度i出现的次数,这样图像中灰度为i 的像素的出现概率是
L 是图像中所有的灰度数,n 是图像中所有的像素数, p 实际上是图像的直方图,归一化到 0..1。
把 c 作为对应于 p 的累计概率函数, 定义为:
c 是图像的累计归一化直方图。
我们创建一个形式为 y = T(x) 的变化,对于原始图像中的每个值它就产生一个 y,这样 y 的累计概率函数就可以在所有值范围内进行线性化,转换公式定义为:
yi = T(xi) = c(i)
注意 T 将不同的等级映射到 0..1 域,为了将这些值映射回它们最初的域,需要在结果上应用下面的简单变换:
上面描述了灰度图像上使用直方图均衡化的方法,但是通过将这种方法分别用于图像RGB颜色值的红色、绿色和蓝色分量,从而也可以对彩色图像进行处理。
3. 调用系统的均衡化函数
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 读取图像
img = cv2.imread('1.png', 0)
# 对图像进行直方图均衡化
equ = cv2.equalizeHist(img)
# 显示原始图像和均衡化后的图像
plt.subplot(2, 1, 1), plt.imshow(img, cmap='gray')
plt.title('Original Image'), plt.xticks([]), plt.yticks([])
plt.subplot(2, 1, 2), plt.imshow(equ, cmap='gray')
plt.title('Histogram Equalized'), plt.xticks([]), plt.yticks([])
plt.show()
4. 自定义均衡化函数的代码
import cv2
import numpy as np
import matplotlib.pyplot as plt
def def_equalizehist(img, L=256): # 自定义直方图的均衡话
img = cv2.imread(img, flags=0)
h, w = img.shape
hist = cv2.calcHist([img], [0], None, [256], [0, 255])
hist[0:255] = hist[0:255] / (h * w)
sum_hist = np.zeros(hist.shape)
for i in range(256):
sum_hist[i] = sum(hist[0:i+1])
equal_hist = np.zeros(sum_hist.shape)
for i in range(256):
equal_hist[i] = int((L-1) * sum_hist[i])
equal_img = img.copy()
for i in range(h):
for j in range(w):
equal_img[i, j] = equal_hist[img[i, j]]
equal_hist = cv2.calcHist([equal_img], [0], None, [256], [0, 255])
equal_hist[0:255] = equal_hist[0:255] / (h * w)
return [equal_img, equal_hist]
if __name__ == '__main__':
img = "./1.png" # 图片所在路径
def_img, def_hist = def_equalizehist(img)
x = np.linspace(0, 255, 256)
plt.subplot(1, 2, 1), plt.plot(x, def_hist, '-r')
plt.show()
ori_img = cv2.imread(img, 0)
cv2.imshow('ori_img', ori_img)
cv2.imshow('def_img', def_img)
cv2.waitKey()
5. 实现效果
初始图片:
均衡化后的图片:
均衡化后的直方图: