直方图均衡化是图像算法中利用图像的直方图来调整原图像对比度的一种方法。
首先还是介绍下算法的基本原理:
直方图是对数据分布状态的描述。而图像的数据就是一个个像素值。因此所谓的图像直方图就是像素值的分布情况。直方图的横轴代表像素值,而纵轴代表着该像素值的出现的频数。
而直方图均衡化的目的是要将一个图像像素值的分布情况变得尽量均匀。而从概率论和高数等相应理论我们可以知道,一个随机变量的pdf的积分为cdf函数。cdf的最大值为1。所以当我们把图像的像素看成随机变量时,通过图像的 cdf * 像素值最大值(像素值为非负的)来映射得到新的像素值,能够使得最后的随机变量分布是一个均匀分布(逆/反变换方法)。也就是基于这样的理论,我们得到了我们的映射函数。对于像素值为0-255的图像而言,我们的映射函数就是该图片的 cdf * 255 来映射得到我们映射后的图片。这也就是直方图均衡化的原理。说白了,也就是一个映射函数,而这个映射是通过直方图来得到的(因为要计算 cdf)。
因为图像时数字离散的,所以只能是估计得到我们的 pdf 和 cdf。其实,图像的直方图就是该图片中随机变量(像素)的 pdf。因此 cdf 就是直方图上依次累和。
说了这么多原理,我们上代码看看。下面是我自己写的一段直方图均衡化的 python 代码。写得匆忙,只是实现了算法的思想。大家能明白意思就行:
def histogramEqualization(src_data):
# 输入的src_data是灰度图像
gray_num_pixel = np.zeros((256))
height, width = src_data.shape
total_pixel = height * width
# 计算得到直方图
for i in range(height):
for j in range(width):
gray_num_pixel[src_data[i, j]] += 1
# 计算得到pdf
pdf = gray_num_pixel / total_pixel
cdf = np.zeros((256))
# 计算得到cdf
cdf[0] = pdf[0]
for i in range(1, 256):
cdf[i] = pdf[i] + cdf[i - 1]
dst_data = np.zeros((height, width), dtype=np.uint8)
for i in range(height):
for j in range(width):
dst_data[i, j] = np.uint8(255 * cdf[src_data[i, j]])
return dst_data
# 彩色图片的直方图均衡化
def colorHistogramEqualization(src_data):
height, width, channel = src_data.shape
gray1 = src_data[:,:,0]
gray2 = src_data[:,:,1]
gray3 = src_data[:,:,2]
gray1 = histogramEqualization(gray1)
gray2 = histogramEqualization(gray2)
gray3 = histogramEqualization(gray3)
dst_data = np.zeros((height, width, channel), dtype=np.uint8)
dst_data[:,:,0] = gray1
dst_data[:,:,1] = gray2
dst_data[:,:,2] = gray3
return dst_data
# 测试代码
def histogram_testing():
im = "/Users/linyuhuan/Desktop/测试.jpg"
src_data = io.imread(im)
dst_data = colorHistogramEqualization(src_data).astype(np.uint8)
plt.subplot(1, 2, 1)
plt.imshow(src_data)
plt.subplot(1, 2, 2)
plt.imshow(dst_data)
plt.show()
下面是结果图:
彩色图像结果图:
网友评论