【图像处理】——图像增强Python实现直⽅图均衡化
⽬录
⼀、相关概念
1、灰度直⽅图概念(hist)
对图像中不同灰度级别出现的次数进⾏统计,统计后进⾏绘制直⽅图,横坐标表⽰灰度级别0-255,纵坐标表⽰每个灰度级别在图像中出现的次数,⼀般会对次数进⾏归⼀化,⽤每个灰度级出现的次数除以图像的像素总个数
2、灰度概率累积函数(cdf)
灰度级由0到255出现频率次数不断进⾏累加得到的直⽅图
3、灰度直⽅图均衡化(equalizehist)
简单来说就是使得灰度在不同灰度级别出现的概率更加的均匀均衡的意思就是使得每⼀个灰度级别的像素点个数是⼀样或者相近的,这时候灰度累积直⽅图是⼀条直线,这时候出现的频率相近则灰度级别类别也就多了,出现的次数也差不多,能够增加图像的对⽐度,均衡化常⽤于偏暗和偏亮的图像处理
4、均衡化适⽤范围
当直⽅图中的数据集中在某⼀个灰度值范围内时,直⽅图均衡化很有⽤。但是如果像素的变化很⼤,⽽且占据的灰度范围⾮常⼴时,例如:既有很亮的像素点⼜有很暗的像素点时。请查看更多资源中的 SOF 链接。
⼆、均衡化的⽬的以及求解步骤
1、⽬的
这种⽅法通常⽤来增加许多图像的全局对⽐度,尤其是当图像的有⽤数据的对⽐度相当接近的时候。通过这种⽅法,亮度可以更好地在直⽅图上分布,这样就可以⽤于增强局部的对⽐度⽽不影响整体的对⽐度。
这种⽅法对于背景和前景都太亮或者太暗的图像⾮常有⽤,这种⽅法尤其是可以带来X光图像中更好的⾻骼结构显⽰以及曝光过度或者曝光不⾜照⽚中更好的细节。
这种⽅法的⼀个主要优势是它是⼀个相当直观的技术并且是可逆操作,如果已知均衡化函数,那么就可以恢复原始的直⽅图,并且计算量也不⼤。这种⽅法的⼀个缺点是它对处理的数据不加选择,它可能会增加背景噪声的对⽐度并且降低有⽤信号的对⽐度。
2、求解步骤
以图像为3位,共2**3-1 = 8个灰度级 ,0-7,求解过程如表中数据
(1)原图灰度直⽅图求解
⽤⾃带函数cv2.calcHist()也可以求解,表⽰每个灰度级的频率,即该灰度级出现的个数占总像素点的⽐例
img = cv2.imread(img,0)
#第⼀步获取图像的直⽅图
h,w = img.shape
hist = cv2.calcHist([img],[0],None,[256],[0,255])#这⾥返回的是次数
hist[0:255] = hist[0:255]/(h*w)#将直⽅图归⼀化,化为概率的形式
(2)计算累积直⽅图
也就是统计每⼀个灰度在整个图像中像素个数的占⽐,总和为1。记第i个灰度的直⽅图分布概率为p(i)。利⽤cumsum()函数直⽅图.cumsum(),返回累积直⽅图数据
def cdf(img):
img = cv2.imread(img,0)
#flatten() 将数组变成⼀维
hist,bins = np.histogram(img.flatten(),256,[0,256])#计算直⽅图
#bins:每个区间的起始点和终点,(257,1)
#hist:直⽅图(256.1)
# 计算累积分布图
print(hist)
cdf = hist.cumsum()
cdf_normalized = cdf * hist.max()/ cdf.max()#
plt.plot(cdf_normalized, color = 'b')#绘制累积灰度级别曲线
plt.hist(img.flatten(),256,[0,256], color = 'r')#绘制原始图像的直⽅图
plt.xlim([0,256])
plt.legend(('cdf','histogram'), loc = 'upper left')
plt.show()
⾃定义
#第⼆步得到灰度级概率累积直⽅图
sum_hist = np.zeros(hist.shape)#⽤于存放灰度级别概率的累和
for i in range(256):
sum_hist[i] = sum(hist[0:i+1])#将前i+1个灰度级别的出现概率总和赋值给sum_hist[i]
(3)取整扩展确定映射关系
每个Pk经过映射后的灰度级值
L表⽰图像处理的灰度级个数,因为此表处理的图像为3位,所以灰度级共2的3次⽅,8个灰度级,所以L=8 ,⼀般L=256
L-1 表⽰最⼤灰度级
0 表⽰最⼩灰度级
例 S(0) = int[((8-1)-0)*0.02+0.5] = 0
#第三步通过映射函数获得原图像灰度级与均衡后图像的灰度级的映射关系,这⾥创建映射后的灰度级别排序
equal_hist = np.zeros(sum_hist.shape)
for i in range(256):
equal_hist[i] = int(((L-1)-0)*sum_hist[i]+0.5)
(4)根据映射关系计算均衡化直⽅图以及图像(这⼀步是关键)
计算后的灰度级替换掉计算前的灰度级,得到均衡化后的直⽅图
#第四步根据第三步的映射关系将灰度图每个像素点的灰度级别替换为映射后的灰度级别,这⾥是这样换的,equal_hist的索引号相当于原先的灰度级别排序,元素值 equal_img = py()#⽤于存放均衡化后图像的灰度值
for i in range(h):
for j in range(w):
equal_img[i,j] = equal_hist[img[i,j]]
#计算得到均衡化后的直⽅图
equal_hist = cv2.calcHist([equal_img],[0],None,[256],[0,255])
equal_hist[0:255] = equal_hist[0:255] / (h * w) # 将直⽅图归⼀化,化为概率的形式
3、绘制未均衡和均衡后对应像素点像素值的改变
import cv2
import numpy as np
from matplotlib import pyplot as plt
def sys_equalizehist(img):
'''
利⽤系统⾃带的函数进⾏直⽅图均衡化
:param img: 待处理图像
:return: [equ_img,equ_hist],返回⼀个列表,第⼀个元素是均衡化后的图像,第⼆个是均衡了的直⽅图 '''
img = cv2.imread(img,0)
h,w = img.shape
equ_img = cv2.equalizeHist(img)#得到直⽅图均衡化后的图像
equ_hist = cv2.calcHist([equ_img],[0],None,[256],[0,255])#得到均衡化后的图像的灰度直⽅图
equ_hist[0:255] = equ_hist[0:255] / (h * w) # 将直⽅图归⼀化,化为概率的形式
# res = np.hstack((img,equ)) #stacking images side-by-side#这⼀⾏是将两个图像进⾏了⾏⽅向的叠加 return [img,equ_img,equ_hist]
#创建绘制原图像和均衡化后图像的对应灰度值变化曲线
def equalWithOrignImg(gray_img,sys_img):
'''
:param gray_img: 未均衡图
:param sys_img: 均衡图
:return:⽆返回值
'''
#将图像像素变成⼀维的
gray_img = gray_img.ravel()
sys_img = sys_img.ravel()
#返回gray_img像素值从⼩到⼤的索引号,对其进⾏排序
argOfGrayImg = np.argsort(gray_img)局部直方图均衡化
gray_img = sorted(gray_img)
#根据索引号来取sys_img中的元素
sys_img_sorted = []
for i in argOfGrayImg:
sys_img_sorted.append(sys_img[i])
plt.plot(gray_img,sys_img_sorted)
plt.show()
if __name__ == '__main__':
img = "E:\PYTHON\Image_Processing\colorful_lena.jpg"
gray_img,sys_img,sys_hist = sys_equalizehist(img)
equalWithOrignImg(gray_img,sys_img)
三、全局均衡化直⽅图
OpenCV 中的直⽅图均衡化函数为 cv2.equalizeHist()。这个函数的输⼊图⽚仅仅是⼀副灰度图像,输出结果是直⽅图均衡化之后的图像。对全局进⾏均衡化
1、系统⾃带函数
import cv2
import numpy as np
from matplotlib import pyplot as plt
def sys_equalizehist(img):
'''
利⽤系统⾃带的函数进⾏直⽅图均衡化
:param img: 待处理图像
:return: [equ_img,equ_hist],返回⼀个列表,第⼀个元素是均衡化后的图像,第⼆个是均衡了的直⽅图
'''
img = cv2.imread(img,0)
h,w = img.shape
equ_img = cv2.equalizeHist(img)#得到直⽅图均衡化后的图像
equ_hist = cv2.calcHist([equ_img],[0],None,[256],[0,255])#得到均衡化后的图像的灰度直⽅图
equ_hist[0:255] = equ_hist[0:255] / (h * w) # 将直⽅图归⼀化,化为概率的形式
# res = np.hstack((img,equ)) #stacking images side-by-side#这⼀⾏是将两个图像进⾏了⾏⽅向的叠加
return [equ_img,equ_hist]
2、⾃定义函数
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论