数字图像处理的python实践(3)——直方图均衡化

        直方图均衡化又称为灰度均衡化,指的是通过某种灰度映射规律,来将输入图像转换成灰度直方图中每个范围内的像素点数目都基本一致的输出图像。这种情况下的输出图像,由于图中的不同数值的灰度数量分布是均匀的,图像也会拥有较高的对比度和较大的动态范围,不会出现直方图中集中在低值区域或者是集中在高值区域,对我们后续其他操作也有一定的帮助。

       虽然现实中的图像都是离散的,均衡化的对象也是直方图,但是为了理论分析的方便,我们先考虑灰度范围在0-1内且是连续的情形。我们得到的输入图像,用一个概率密度函数来描述其中的灰度数值分布情况。

p(x),0\leq x\leq 1

       更加具有现实意义的是概率分布函数,描述的是在图像中像素点的灰度值介于0到x之间的比率。之所以使用y作为积分变量是为了将x作为积分上限,所以看起来有点奇怪,实际上p(x)、p(y)是相同的概率密度函数。

P(x) =\int_{0}^{x}p(y)dy   

   p(x) =\frac{\partial P(x)}{\partial x}

        那么更仔细一些,以p_{r}(x)表示转化前的灰度概率密度函数,用p_{s}(y)表示转换后的灰度概率密度函数,这里的x和y都是灰度值。如果,我们建立起一个y和x的映射关系如下

y=f(x), x=f^{-1}(y)

       那么根据概率论中的知识,这就是随机变量函数的概率分布。简单一些说,就是已知一个变量X的分布情况(概率密度函数),然后我们要求这个变量代入某个函数f后得到的新的变量的分布情况。

P_{s}(y) = P\{Y<y\}=P\{X<f^{-1}(y)\}=P_{r}\{f^{-1}(y)\}

p_{s}(y)=\frac{\mathrm{d}P_{s}(y) }{\mathrm{d} y}=\frac{\mathrm{d}P_{r}(f^{-1}(y)) }{\mathrm{d} y}=p_{r}(f^{-1}(y))*\frac{\mathrm{d}(f^{-1}(y)) }{\mathrm{d} y}=p_{r}(x)*\frac{\mathrm{d}x }{\mathrm{d} y}

      如果我们要使得转换后的图像的概率密度函数:p_{s}(y)=1,0\leq y\leq1,那么最重要的映射关系为

p_{r}(x)=\frac{\mathrm{d} y}{\mathrm{d} x}

y=f(x)=\int_{0}^{x}p_{r}(r)dr

这恰好也是p_{r}的累积分布函数。

       以上讨论的,是灰度取值在0-1的范围,实际上我们面对的都是0-255的情况,需要乘上最大灰度值D_{max}。此时的灰度均衡转换公式为

D_{B}=f(D_{A})=D_{max}*\int_{0}^{D_{A}}p_{D_{A}}(\mu )d\mu

        而对于离散的灰度级,相应的转换公式为

D_{B}=f(D_{A})=\frac{D_{max}}{A_{0}}*\sum_{i=0}^{D_{A}}H_{i}

A_{0}为图像的面积,也就是像素的总数。H_{i}为第i个灰度级的像素个数,在最最理想的情况上就是分割成256个区间,为了计算或者是没有那么高的均衡要求,可以减少为128或者64,因为最后的目标都是为了实现一个均衡的直方图。实现的python代码为

from PIL import Image
import numpy as np
import matplotlib.pyplot as plt

gray_girl = "C:/Users/60214/Desktop/python_work/DigitalExecution/gray_girl.jpg"

new_path = "C:/Users/60214/Desktop/python_work/DigitalExecution/Histeq.jpg"

def Histeq(src, target, bins = 256):
	'''
	bins = 256
	'''
	dmax = 255
	im = Image.open(src)
	imarray = np.array(im)
	height, width = imarray.shape

	tran_func = dict(zip([i for i in range(bins)],[0 for i in range(bins)]))
	hist = 	dict(zip([i for i in range(bins)],[0 for i in range(bins)]))

	for i in range(height):
		for j in range(width):
			hist[imarray[i, j]] += 1
	
	total = 0
	for i in range(bins):
		total += hist[i]
		tran_func[i] = round(dmax*total/height/width)

	for i in range(height):
		for j in range(width):
			imarray[i, j] = tran_func[imarray[i, j]]
	new_im = Image.fromarray(imarray)
	new_im.save(target)

GrayHist(gray_girl, 256)
Histeq(gray_girl, new_path)
GrayHist(new_path, 256)

        处理前后的图片对比,以及灰度直方图对比如下。显然可以看到处理之后的图像的灰度直方图分布更加均匀,虽然在高灰度值区域仍存在部分峰值,这是因为我们所采用的转换函数造成的,累加的形式必然难以达到连续情况下积分所得到的p_{s}(y)=1这种效果。但图像已经显示的更加清晰,已经到达到了直方均衡的目的。

数字图像处理的python实践(3)——直方图均衡化_第1张图片

数字图像处理的python实践(3)——直方图均衡化_第2张图片数字图像处理的python实践(3)——直方图均衡化_第3张图片

 

 

 

 

 

 

你可能感兴趣的:(数字图像处理的python实践)