灰度直方图即将一张图的颜色统计出来,以8位灰度图像为例,每个像素的颜色灰度在0-255之间,现在需要统计出每个颜色在图像中出现的频次,横坐标为0-255,纵坐标为频次,或归一化后为概率(即将每个灰度值出现的次数除以总像素个数)。
以下图为例:
可以发现边缘处的灰度值出现的频次较少。可以用直方图均衡化方法来增强图像
因为直方图均衡化处理之后,原来比较少像素的灰度会被分配到别的灰度去,像素相对集中, 处理后灰度范围变大,对比度变大,清晰度变大,所以能有效增强图像。直方图均衡化是图像处理领域中利用图像直方图对对比度进行调整的方法。这种方法通常用来增加许多图像的局部对比度,尤其是当图像的有用数据的对比度相当接近的时候。通过这种方法,亮度可以更好地在直方图上分布。这样就可以用于增强局部的对比度而不影响整体的对比度,直方图均衡化通过有效地扩展常用的亮度来实现这种功能。
均衡化方法:下面几张图来源于 https://www.cnblogs.com/tianyalu/p/5687782.html
假设有如下图像:
得图像的统计信息如下图所示,并根据统计信息完成灰度值映射:
映射后的图像如下所示:
原图图处理后效果以及处理后图像的灰度直方图如下:
Python 处理代码如下:
from PIL import Image
import matplotlib.pyplot as plt
def norm(L):
"""
将频次归一化转为概率
"""
s = sum(L)
for i in range(len(L)):
L[i] /= s
return L
def getColorDensity(img):
"""
返回图像的颜色概率密度
x为图像灰度,y为密度,且一一对应
"""
if img.mode!="L":
print("需传入灰度图像")
return None,None
x=[]
y=[]
colors = img.getcolors()
#print(colors)
if colors==None:
print("colos out of range")
return None,None
for i in colors:
x.append(i[1])
y.append(i[0])
y = norm(y)
return x,y
def drawGrayBar(img):
"""
绘制灰度直方图
"""
x,y = getColorDensity(img)
if x==None:
return
plt.bar(x,y)
plt.show()
def GrayNorm(img,lRange=0,hRange=255):
"""
灰度均衡化
"""
desImg = Image.new(img.mode,(img.width,img.height))
delta = hRange - lRange
grayNum,prop = getColorDensity(img)
if grayNum == None:
return
colorTab = {}#colorTab是一个字典,key为原图某像素的灰度值,value为此灰度转化后的灰度,
prop_total=0
for i in range(len(prop)):
prop_total += prop[i]
prop[i] = round(prop_total * delta) #将每个像素颜色值使用累积概率密度相乘得到转化后的灰度
colorTab[grayNum[i]] = prop[i]
#遍历图像所有像素,将像素值灰度置位均衡化后的灰度
for x in range(img.width):
for y in range(img.height):
gray_origin = img.getpixel((x,y))
desImg.putpixel((x,y),colorTab[gray_origin])#由于是灰度图,所以后面只需要传一个参数即灰度。若为真彩色,则传一个元组
return desImg
img = Image.open("D:\\lena_gray.jpg")
desImg = GrayNorm(img)
drawGrayBar(desImg)