图像均衡化本质是灰度变换。通过重新分配图像的灰度级分布,使得像素更均匀地分布在灰度范围内。可以增强图像对比度,使图像细节更加明显。本代码只考虑应用于灰度图像
使用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根据均衡化定义,使用代码进行直方图均衡化处理
http://t.csdn.cn/4kWM7http://t.csdn.cn/4kWM7根据此篇文章,对其进行代码实现:
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)之比,即链接里所提到的映射方法:http://t.csdn.cn/4kWM7http://t.csdn.cn/4kWM7
代码实现:
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]
经该代码生成的图像:
其灰度不如上面skimage函数生成的图片均匀