直方图均衡化( Histogram Equalization )
直方图均衡化是使直方图变得平坦的操作,是不需要计算上面的问题中的平均值、标准差等数据使直方图的值变得均衡的操作。
直方图均衡化保证在图像像素映射过程中原来的大小关系保持不变,即较亮的区域依旧较亮,较暗的依旧较暗,只是对比度增加,不能明暗颠倒;保证像素映射函数的值域在0和255之间。
按照以下步骤对像素值进行处理:
- 对图像中的像素点进行统计,统计每个像素值对应的个数和占比
- 进行函数映射,zmax是映射范围,一般为255。
h
(
i
)
h(i)
h(i)的累加是灰度值的累计像素个数。S是像素点个数。
Z ′ = Z m a x S ∑ i = 0 z h ( i ) Z' = \frac{Z_{max}}{S} \ \sum\limits_{i=0}^z\ h(i) Z′=SZmax i=0∑z h(i)
计算方法就是用当前灰度值的累计像素个数乘上要分布映射的范围(255)
- 比如100个像素点,其中像素值最小为3,个数为5个,(sum(3) = 5)
- 那么就把像素值为3的像素点值改为 255 × ( 5 100 ) = 12.75 255 \times\left(\frac{5}{100}\right)=12.75 255×(1005)=12.75 -> 取整 -> 13
- 下一个像素值为4,个数有8个,那么 s u m ( 4 ) = 5 + 8 = 12 sum(4) = 5+8 = 12 sum(4)=5+8=12
- 把像素值为4的像素点值改为 255 × ( 12 100 ) = 30.6 255 \times\left(\frac{12}{100}\right)=30.6 255×(10012)=30.6 ----> 取整 ----> 31
依次累加计算像素值。
代码实现
def equalHist(img):
result = np.zeros_like(img)
#像素总数
imgsize = img.size
#统计0~255的值的个数
count = np.bincount(img.reshape(-1))
for i in range(count.size):
#如果这个像素值的个数不为0(就是存在该像素值的点)
if count[i]:
#计算累计个数
sum = count[:i+1].sum()
x = 255*(sum/imgsize)
#四舍五入后转为uint8类型
x = np.around(x).astype(np.uint8)
#修改原本的像素值,改动放到新的图片上,以免打乱后面的像素值运算
result[img == i] = x
return result
# 读取图片
path = 'C:/Users/86187/Desktop/image/'
file_in = path + 'cake.jpg'
img = imread(file_in)
img3 = img.copy()
img3 = equalHist(img3)
imgshow = plt.imshow(img3)
plt.show()
hist1 = plt.hist(img3.reshape(-1),bins=255,rwidth=0.85,range=(0,255))