效果
- 左下角为原图片,右上为原图灰度化后的直方图均衡化后的图片,右下为原图的直方图均衡化后的图片。
- 左上角图片中,蓝色部分表示原图的直方图,橙色部分表示均衡化后的直方图
原理
直方图
-
在图像处理中,经常用到直方图,如颜色直方图、灰度直方图等。
-
图像的灰度直方图就描述了图像中灰度分布情况,能够很直观的展示出图像中各个灰度级所
占的多少。 -
图像的灰度直方图是灰度级的函数,描述的是图像中具有该灰度级的像素的个数:其中,横
坐标是灰度级,纵坐标是该灰度级出现的频率。
-
直方图反映了图像中的灰度分布规律。它描述每个灰度级具有的像素个数,但不包含这些像素在图像中的位置信息。图像直方图不关心像素所处的空间位置,因此不受图像旋转和平移变化的影响,可以作为图像的特征。
-
任何一幅特定的图像都有唯一的直方图与之对应,但不同的图像可以有相同的直方图。
-
如果一幅图像有两个不相连的区域组成,并且每个区域的直方图已知,则整幅图像的直方图是两个区域的直方图之和
直方图的应用
直方图均衡化
- 直方图均衡化是将原图像的直方图通过变换函数变为均匀的直方图,然后按均匀的直方图修改原图像,从而获得一幅灰度均匀分布的信徒想。直方图的均衡化就是用一定的算法使直方图大致平和的方法
- 直方图均衡化的作用是图像增强
为了将原图像的亮度范围进行扩展,需要一个映射函数,将原图像的像素值均衡映射到新直
方图中,这个映射函数有两个条件:
- 为了不打乱原有的顺序,映射后亮、暗的大小关系不能改变,
- 映射后必须在原有的范围内,比如(0-255)
步骤:
- 依次扫描原始灰度图像的每一个像素,计算出图像的灰度直方图H
- 计算灰度直方图的累加直方图
- 根据累加直方图和直方图均衡化原理得到输入与输出之间的映射关系。
- 最后根据映射关系得到结果:dst(x,y) = H’(src(x,y))进行图像变换
详细步骤
- 对于输入图像的任意一个像素p, p∈[0,255], 总能在输出图像里有对应的像素q, q∈[0,255] 使得下面等式成
立(输入和输出的像素总量相等):
2. 其中,输出图像每个灰度级的个数:
3.带入累加直方图公式
!! 实例 !!
假设这是一张5*5的图片,每个像素的值代表着像素的亮暗程度(灰度值),下面,我们把相同的灰度值的所有像素点归为一个梯度,则原图像表示为
接下来,我们要计算每个梯度对应的均衡化后的灰度值,即计算0~9的梯度所对应的灰度值
- pix:通道值相同的像素(每个梯度)
- Ni:相同通道值的像素个数(每个梯度的像素个数)
- Pi = Ni/image:某个通道值对应的像素在整幅图的比例
- sumPi:Pi的累加
- sumPi*256-1:即q,表示均衡化后每个梯度对应的灰度值(或是某个通道的值)
- 四舍五入取整
代码部分
"""
@author: Hanley-Yang
equalizeHist—直方图均衡化
函数原型: equalizeHist(src, dst=None)
src:图像矩阵(单通道图像)
dst:默认即可
"""
import cv2
from matplotlib import pyplot as plt
# 获取灰度图像
img = cv2.imread('Euphonium.png')
grayImg = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 灰度图像的直方图均衡化
dst = cv2.equalizeHist(grayImg)
# 获取直方图
hist = cv2.calcHist([dst],[0],None,[256],[0,256])
#输出原灰度图和均衡化后的灰度图的直方图,进行对比
plt.figure()
plt.subplot(221)
plt.hist(grayImg.ravel(),256)
plt.hist(dst.ravel(),256)
plt.subplot(222)
plt.imshow(dst,cmap="gray")
# cv2.imshow("Histogram Equalization",np.hstack([grayImg,dst]))
# cv2.waitKey(0)
# # 彩色图像直方图均衡化
# img = cv2.imread("Euphonium.png",1)
# cv2.imshow("src",img)
# 彩色图像均衡化,需要分解通道,对每一个通道均衡化
(b, g, r) = cv2.split(img)
bH = cv2.equalizeHist(b)
gH = cv2.equalizeHist(g)
rH = cv2.equalizeHist(r)
# 合并每一个通道
result = cv2.merge((bH, gH, rH))
# 将图像从BGR转换为RGB
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.subplot(223)
plt.imshow(img_rgb)
result_rgb = cv2.cvtColor(result, cv2.COLOR_BGR2RGB)
plt.subplot(224)
plt.imshow(result_rgb)
plt.show()