图像均衡化本质是灰度变换。通过重新分配图像的灰度级分布,使得像素更均匀地分布在灰度范围内。可以增强图像对比度,使图像细节更加明显。本代码只考虑应用于灰度图像


使用skimage库进行简单计算:

from matplotlib import pyplot as plt
from skimage import io, color, exposure

img = io.imread('846f089b1733d5227094e5cc68f1ffb1_.png', as_gray=True)
equalized_image = exposure.equalize_hist(img)  # 使用exposure进行直方图均衡化

plt.subplot(221)
plt.imshow(img, cmap='gray')  # 为什么要重新定义下灰度?
plt.title('original img')

plt.subplot(2, 2, 2)
plt.hist(img.flatten(), 256, color='gray', alpha=0.7)
plt.title('hist of original image')

plt.subplot(2, 2, 3)
plt.imshow(equalized_image, cmap='gray')
plt.title('equalized img')

plt.subplot(2, 2, 4)
plt.hist(equalized_image.flatten(), 256, color='gray', alpha=0.7)
plt.title('hist of ei')
plt.tight_layout()
plt.show()

需要注意的是,经过exposure函数处理之后,生成的equalized_img的像素值可能会出现某些变化导致生成的图像灰度不在[0, 255]之间,这样带来的问题会在下一有关图片量化的文章中有显著体现。

以下是生成的图片及其直方图,经exposure均衡化处理后的图像灰度分布更加均匀。

直方图均衡化程序_人工智能

 使用numpy根据均衡化定义,使用代码进行直方图均衡化处理

对其进行代码实现:

import numpy as np
from matplotlib import pyplot as plt
from skimage import io, color, exposure

first_img = io.imread('846f089b1733d5227094e5cc68f1ffb1_.png', as_gray=True)
img = first_img / first_img.max()
hist, bin_edges = np.histogram(img.flatten(), bins=256)
cdf = hist.cumsum()  # 累计分布函数,hist.cumsum用于计算数组元素的累计和,得出来的cdf也是一个数组,表示某个灰度以及之前灰度的像素和
cdf_normalized = cdf / cdf.max()  # 归一化处理,cdf.max即所有像素累积和,cdf_normalized是一个元素都小于1的数组
mapping = (cdf_normalized * 255).astype('uint8')  # 映射表,将cdf_normalized * 255得出正常范围的灰度级别,astype将数据转化为无符号整数类
equalized_image = mapping[(img * 255).astype('uint8')]  # 数组映射,将img经过mapping进行映射处理,img的累积分布函数就是映射关系
plt.subplot(221)
plt.imshow(img, cmap='gray')  # 为什么要重新定义下灰度?
plt.title('original img')

plt.subplot(2, 2, 2)
plt.hist(img.flatten(), 256, color='gray', alpha=0.7)
plt.title('hist of original image')

plt.subplot(2, 2, 3)
plt.imshow(equalized_image, cmap='gray')
plt.title('equalized img')

plt.subplot(2, 2, 4)
plt.hist(equalized_image.flatten(), 256, color='gray', alpha=0.7)
plt.title('hist of ei')
plt.tight_layout()
plt.show()

其中:

cdf = hist.cumsum()  # 累计分布函数,hist.cumsum用于计算数组元素的累计和,得出来的cdf也是一个数组,表示某个灰度以及之前灰度的像素和

含义是计算出一个数组,数组内第n个数代表前n个像素值包含的像素数量之和(cdf)。进而的,可以计算出前n个像素值像素数量和与总像素值(cdf.max)之比

直方图均衡化程序_直方图均衡化程序_02

 代码实现:

cdf = hist.cumsum()  # 累计分布函数,hist.cumsum用于计算数组元素的累计和,得出来的cdf也是一个数组,表示某个灰度以及之前灰度的像素和
cdf_normalized = cdf / cdf.max()  # 归一化处理,cdf.max即所有像素累积和,cdf_normalized是一个元素都小于1的数组
mapping = (cdf_normalized * 255).astype('uint8')  # 映射表,将cdf_normalized * 255得出正常范围的灰度级别,astype将数据转化为无符号整数类
equalized_image = mapping[(img * 255).astype('uint8')]  # 数组映射,将img经过mapping进行映射处理,img的累积分布函数就是映射关系

该方法生成图片灰度无问题,如有后续使用,不需要进一步转换至[0, 255]

经该代码生成的图像:

直方图均衡化程序_计算机视觉_03

 其灰度不如上面skimage函数生成的图片均匀