直方图均衡化就是把一已知灰度概率分布的图像经过一种变换使之演变成一幅具有均匀灰度概率分布的新图像
它是以累积分布函数变换法为基础的直方图修正法
我们来看看直方图的含义
还是以上次我们讲的例子为例
我们看到R通道的直方图主要集中在亮部,所以R通道灰度图看起来较白
而B通道的直方图主要集中在暗部,而对应的B通道灰度图看起来很暗
G通道分布比较均匀,但有点偏暗
好了,这就是直观的理解
而清晰柔和的图像的直方图灰度分布比较均匀
什么是累积分布函数呢,我们先看看直方图的画法,每一个横坐标上纵坐标的高度对应于灰度值为该值的像素点的个数
若我们定义一个横坐标对应纵坐标高度是所有小于该灰度值的像素点的个数
这就是我们说的累积分布
灰度值为1处对应灰度值为1的点
灰度值为2处对应灰度值为1和2的点
灰度值为3处对应灰度值为1、2、3的点
·······
灰度值为255处对应所有的点
好啦
我们来看看累积分布直方图的效果吧
直方图均衡化的方法如下:
红色部分是原图累积分布函数轮廓线
而理想的均衡化累积分布函数轮廓线应该是一条斜线
对于原图中灰度值为80的点,按图中的方法我们把它转换为灰度值为60
对每个灰度值,我们建立一个转换表,再对原图进行转换,就可以得到均衡化后的图了
我们来看看具体程序
importcvdefHist(image,color=cv.RGB(102,204,204)):
a=[0]*256w=image.width
h=image.height
iHist=cv.CreateImage((256,256),8,3)foriinrange(h):forjinrange(w):
iGray=int(image[i,j])
a[iGray]=a[iGray]+1S=max(a)forkinrange(256):
a[k]=a[k]*255/S
x=(k,255)
y=(k,255-a[k])
cv.Line(iHist,x,y,color)returniHistdefLHist(image,color=cv.RGB(102,204,204)):
a=[0]*256w=image.width
h=image.height
iLHist=cv.CreateImage((256,256),8,3)foriinrange(h):forjinrange(w):
iGray=int(image[i,j])
a[iGray]=a[iGray]+1foriinrange(1,256):
a[i]=a[i]+a[i-1]
S=max(a)forkinrange(256):
a[k]=a[k]*255/S
x=(k,255)
y=(k,255-a[k])
cv.Line(iLHist,x,y,color)returniLHistdefEqualize(image):
a=[0]*256w=image.width
h=image.height
size=(w,h)
iEqualize=cv.CreateImage(size,image.depth,1)foriinrange(h):forjinrange(w):
iGray=int(image[i,j])
a[iGray]=a[iGray]+1foriinrange(1,256):
a[i]=a[i]+a[i-1]
S=max(a)forkinrange(256):
a[k]=a[k]*255/Sforiinrange(h):forjinrange(w):
iEqualize[i,j]=a[int(image[i,j])]returniEqualize
image=cv.LoadImage('lena.jpg',0)
iHist=Hist(image)
iLHist=LHist(image)
iEqualize=Equalize(image)
iEHist=Hist(iEqualize,cv.RGB(153,204,54))
iELHist=LHist(iEqualize,cv.RGB(153,204,54))
cv.ShowImage('image',image)
cv.ShowImage('iHist',iHist)
cv.ShowImage('iLHist',iLHist)
cv.ShowImage('iEqualize',iEqualize)
cv.ShowImage('iEHist',iEHist)
cv.ShowImage('iELHist',iELHist)
cv.WaitKey(0)
看看运行效果
现在图像的直方图分布比较均匀了
但很难得到完全均衡的结果,另外,变换后的灰度级减少了。
这种现象叫做“简并”现象。由于简并现象的存在,处理后的灰度级总是要减少的
直观反映就是均衡后直方图在垂直方向上有很多黑线
好啦,直方图均衡化就讲到这里啦