【图像处理】——图像增强Python实现直方图均衡化
目錄
一、相關(guān)概念
1、灰度直方圖概念(hist)
2、灰度概率累積函數(shù)(cdf)
3、灰度直方圖均衡化(equalizehist)
4、均衡化適用范圍
二、均衡化的目的以及求解步驟
1、目的
2、求解步驟
(1)原圖灰度直方圖求解
(2)計(jì)算累積直方圖
直方圖.cumsum(),返回累積直方圖數(shù)據(jù)
(3)取整擴(kuò)展確定映射關(guān)系
(4)根據(jù)映射關(guān)系計(jì)算均衡化直方圖以及圖像(這一步是關(guān)鍵)
3、繪制未均衡和均衡后對(duì)應(yīng)像素點(diǎn)像素值的改變
三、全局均衡化直方圖
1、系統(tǒng)自帶函數(shù)
2、自定義函數(shù)
3、結(jié)果展示
四、限制對(duì)比度自適應(yīng)直方圖均衡(Contrast Limited?Adaptive histgram equalization/CLAHE)
1、限制對(duì)比度自適應(yīng)直方圖均衡的概念
2、適用場(chǎng)景與優(yōu)勢(shì)
3、原理及代碼
?
一、相關(guān)概念
1、灰度直方圖概念(hist)
對(duì)圖像中不同灰度級(jí)別出現(xiàn)的次數(shù)進(jìn)行統(tǒng)計(jì),統(tǒng)計(jì)后進(jìn)行繪制直方圖,橫坐標(biāo)表示灰度級(jí)別0-255,縱坐標(biāo)表示每個(gè)灰度級(jí)別在圖像中出現(xiàn)的次數(shù),一般會(huì)對(duì)次數(shù)進(jìn)行歸一化,用每個(gè)灰度級(jí)出現(xiàn)的次數(shù)除以圖像的像素總個(gè)數(shù)
2、灰度概率累積函數(shù)(cdf)
灰度級(jí)由0到255出現(xiàn)頻率次數(shù)不斷進(jìn)行累加得到的直方圖
3、灰度直方圖均衡化(equalizehist)
簡(jiǎn)單來(lái)說(shuō)就是使得灰度在不同灰度級(jí)別出現(xiàn)的概率更加的均勻均衡的意思就是使得每一個(gè)灰度級(jí)別的像素點(diǎn)個(gè)數(shù)是一樣或者相近的,這時(shí)候灰度累積直方圖是一條直線,這時(shí)候出現(xiàn)的頻率相近則灰度級(jí)別類(lèi)別也就多了,出現(xiàn)的次數(shù)也差不多,能夠增加圖像的對(duì)比度,均衡化常用于偏暗和偏亮的圖像處理
4、均衡化適用范圍
當(dāng)直方圖中的數(shù)據(jù)集中在某一個(gè)灰度值范圍內(nèi)時(shí),直方圖均衡化很有用。但是如果像素的變化很大,而且占據(jù)的灰度范圍非常廣時(shí),例如:既有很亮的像素點(diǎn)又有很暗的像素點(diǎn)時(shí)。請(qǐng)查看更多資源中的 SOF 鏈接。
二、均衡化的目的以及求解步驟
1、目的
這種方法通常用來(lái)增加許多圖像的全局對(duì)比度,尤其是當(dāng)圖像的有用數(shù)據(jù)的對(duì)比度相當(dāng)接近的時(shí)候。通過(guò)這種方法,亮度可以更好地在直方圖上分布,這樣就可以用于增強(qiáng)局部的對(duì)比度而不影響整體的對(duì)比度。
?????? 這種方法對(duì)于背景和前景都太亮或者太暗的圖像非常有用,這種方法尤其是可以帶來(lái)X光圖像中更好的骨骼結(jié)構(gòu)顯示以及曝光過(guò)度或者曝光不足照片中更好的細(xì)節(jié)。
?????? 這種方法的一個(gè)主要優(yōu)勢(shì)是它是一個(gè)相當(dāng)直觀的技術(shù)并且是可逆操作,如果已知均衡化函數(shù),那么就可以恢復(fù)原始的直方圖,并且計(jì)算量也不大。這種方法的一個(gè)缺點(diǎn)是它對(duì)處理的數(shù)據(jù)不加選擇,它可能會(huì)增加背景噪聲的對(duì)比度并且降低有用信號(hào)的對(duì)比度。
2、求解步驟
以圖像為3位,共2**3-1 = 8個(gè)灰度級(jí) ,0-7,求解過(guò)程如表中數(shù)據(jù)
(1)原圖灰度直方圖求解
用自帶函數(shù)cv2.calcHist()也可以求解,表示每個(gè)灰度級(jí)的頻率,即該灰度級(jí)出現(xiàn)的個(gè)數(shù)占總像素點(diǎn)的比例
img = cv2.imread(img,0)#第一步獲取圖像的直方圖h,w = img.shapehist = cv2.calcHist([img],[0],None,[256],[0,255])#這里返回的是次數(shù)hist[0:255] = hist[0:255]/(h*w)#將直方圖歸一化,化為概率的形式(2)計(jì)算累積直方圖
也就是統(tǒng)計(jì)每一個(gè)灰度在整個(gè)圖像中像素個(gè)數(shù)的占比,總和為1。記第i個(gè)灰度的直方圖分布概率為p(i)。利用cumsum()函數(shù)
直方圖.cumsum(),返回累積直方圖數(shù)據(jù)
def cdf(img):img = cv2.imread(img,0)#flatten() 將數(shù)組變成一維hist,bins = np.histogram(img.flatten(),256,[0,256])#計(jì)算直方圖#bins:每個(gè)區(qū)間的起始點(diǎn)和終點(diǎn),(257,1)#hist:直方圖(256.1)# 計(jì)算累積分布圖print(hist)cdf = hist.cumsum()cdf_normalized = cdf * hist.max()/ cdf.max()#plt.plot(cdf_normalized, color = 'b')#繪制累積灰度級(jí)別曲線plt.hist(img.flatten(),256,[0,256], color = 'r')#繪制原始圖像的直方圖plt.xlim([0,256])plt.legend(('cdf','histogram'), loc = 'upper left')plt.show()自定義
#第二步得到灰度級(jí)概率累積直方圖sum_hist = np.zeros(hist.shape)#用于存放灰度級(jí)別概率的累和for i in range(256):sum_hist[i] = sum(hist[0:i+1])#將前i+1個(gè)灰度級(jí)別的出現(xiàn)概率總和賦值給sum_hist[i](3)取整擴(kuò)展確定映射關(guān)系
每個(gè)Pk經(jīng)過(guò)映射后的灰度級(jí)值
L表示圖像處理的灰度級(jí)個(gè)數(shù),因?yàn)榇吮硖幚淼膱D像為3位,所以灰度級(jí)共2的3次方,8個(gè)灰度級(jí),所以L=8 ,一般L=256
L-1 表示最大灰度級(jí)
0 表示最小灰度級(jí)
- 例 S(0) = int[((8-1)-0)*0.02+0.5] = 0
(4)根據(jù)映射關(guān)系計(jì)算均衡化直方圖以及圖像(這一步是關(guān)鍵)
計(jì)算后的灰度級(jí)替換掉計(jì)算前的灰度級(jí),得到均衡化后的直方圖
#第四步根據(jù)第三步的映射關(guān)系將灰度圖每個(gè)像素點(diǎn)的灰度級(jí)別替換為映射后的灰度級(jí)別,這里是這樣換的,equal_hist的索引號(hào)相當(dāng)于原先的灰度級(jí)別排序,元素值則是映射后的灰度級(jí)別equal_img = img.copy()#用于存放均衡化后圖像的灰度值for i in range(h):for j in range(w):equal_img[i,j] = equal_hist[img[i,j]]#計(jì)算得到均衡化后的直方圖equal_hist = cv2.calcHist([equal_img],[0],None,[256],[0,255])equal_hist[0:255] = equal_hist[0:255] / (h * w) # 將直方圖歸一化,化為概率的形式3、繪制未均衡和均衡后對(duì)應(yīng)像素點(diǎn)像素值的改變
import cv2 import numpy as np from matplotlib import pyplot as pltdef sys_equalizehist(img):'''利用系統(tǒng)自帶的函數(shù)進(jìn)行直方圖均衡化:param img: 待處理圖像:return: [equ_img,equ_hist],返回一個(gè)列表,第一個(gè)元素是均衡化后的圖像,第二個(gè)是均衡了的直方圖'''img = cv2.imread(img,0)h,w = img.shapeequ_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#這一行是將兩個(gè)圖像進(jìn)行了行方向的疊加return [img,equ_img,equ_hist]#創(chuàng)建繪制原圖像和均衡化后圖像的對(duì)應(yīng)灰度值變化曲線 def equalWithOrignImg(gray_img,sys_img):''':param gray_img: 未均衡圖:param sys_img: 均衡圖:return:無(wú)返回值'''#將圖像像素變成一維的gray_img = gray_img.ravel()sys_img = sys_img.ravel()#返回gray_img像素值從小到大的索引號(hào),對(duì)其進(jìn)行排序argOfGrayImg = np.argsort(gray_img)gray_img = sorted(gray_img)#根據(jù)索引號(hào)來(lái)取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 中的直方圖均衡化函數(shù)為 cv2.equalizeHist()。這個(gè)函數(shù)的輸入圖片僅僅是一副灰度圖像,輸出結(jié)果是直方圖均衡化之后的圖像。對(duì)全局進(jìn)行均衡化
1、系統(tǒng)自帶函數(shù)
import cv2 import numpy as np from matplotlib import pyplot as pltdef sys_equalizehist(img):'''利用系統(tǒng)自帶的函數(shù)進(jìn)行直方圖均衡化:param img: 待處理圖像:return: [equ_img,equ_hist],返回一個(gè)列表,第一個(gè)元素是均衡化后的圖像,第二個(gè)是均衡了的直方圖'''img = cv2.imread(img,0)h,w = img.shapeequ_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#這一行是將兩個(gè)圖像進(jìn)行了行方向的疊加return [equ_img,equ_hist]2、自定義函數(shù)
def def_equalizehist(img,L=256):'''根據(jù)均衡化原理自定義函數(shù):param img: 待處理圖像:param L: 灰度級(jí)別的個(gè)數(shù):return: [equal_img,equal_hist]返回一個(gè)列表,第一個(gè)元素是均衡化后的圖像,第二個(gè)是均衡了的直方圖'''img = cv2.imread(img,0)#第一步獲取圖像的直方圖h,w = img.shapehist = cv2.calcHist([img],[0],None,[256],[0,255])#這里返回的是次數(shù)hist[0:255] = hist[0:255]/(h*w)#將直方圖歸一化,化為概率的形式#第二步得到灰度級(jí)概率累積直方圖sum_hist = np.zeros(hist.shape)#用于存放灰度級(jí)別概率的累和for i in range(256):sum_hist[i] = sum(hist[0:i+1])#將前i+1個(gè)灰度級(jí)別的出現(xiàn)概率總和賦值給sum_hist[i]#第三步通過(guò)映射函數(shù)獲得原圖像灰度級(jí)與均衡后圖像的灰度級(jí)的映射關(guān)系,這里創(chuàng)建映射后的灰度級(jí)別排序equal_hist = np.zeros(sum_hist.shape)for i in range(256):equal_hist[i] = int(((L-1)-0)*sum_hist[i]+0.5)#第四步根據(jù)第三步的映射關(guān)系將灰度圖每個(gè)像素點(diǎn)的灰度級(jí)別替換為映射后的灰度級(jí)別,這里是這樣換的,equal_hist的索引號(hào)相當(dāng)于原先的灰度級(jí)別排序,元素值則是映射后的灰度級(jí)別equal_img = img.copy()#用于存放均衡化后圖像的灰度值for i in range(h):for j in range(w):equal_img[i,j] = equal_hist[img[i,j]]#計(jì)算得到均衡化后的直方圖equal_hist = cv2.calcHist([equal_img],[0],None,[256],[0,255])equal_hist[0:255] = equal_hist[0:255] / (h * w) # 將直方圖歸一化,化為概率的形式return [equal_img,equal_hist]if __name__ == '__main__':img = "colorful_lena.jpg"sys_img,sys_hist = sys_equalizehist(img)def_img,def_hist = def_equalizehist(img)x = np.linspace(0,255,256)plt.subplot(1,2,1),plt.plot(x,sys_hist,'-b')plt.subplot(1,2,2),plt.plot(x,def_hist,'-r')plt.show()3、結(jié)果展示
均衡化以前
均衡化以后
可見(jiàn)均衡化后的直方圖比較密集了,且比較均勻,說(shuō)明各個(gè)灰度級(jí)別出現(xiàn)的概率比較相近 ,且均衡化的圖像比均衡化前的對(duì)比度大,亮的更亮,暗的更暗,色差大
四、限制對(duì)比度自適應(yīng)直方圖均衡(Contrast Limited?Adaptive histgram equalization/CLAHE)
1、限制對(duì)比度自適應(yīng)直方圖均衡的概念
有限對(duì)比適應(yīng)性直方圖均衡化我們?cè)?strong>上邊做的直方圖均衡化會(huì)改變整個(gè)圖像的對(duì)比度,但是在很多情況下,這樣做的效果并不好。如下圖:
?????? 的確在進(jìn)行完直方圖均衡化之后,圖片背景的對(duì)比度被改變了。但是你再對(duì)比一下兩幅圖像中雕像的面圖,由于太亮我們丟失了很多信息。造成這種結(jié)果的根本原因在于這幅圖像的直方圖并不是集中在某一個(gè)區(qū)域(試著畫(huà)出它的直方圖,你就明白了)。
????????? 為了解決這個(gè)問(wèn)題,我們需要使用自適應(yīng)的直方圖均衡化。這種情況下,整幅圖像會(huì)被分成很多小塊,這些小塊被稱(chēng)為“tiles”(在 OpenCV 中 tiles 的大小默認(rèn)是 8x8),然后再對(duì)每一個(gè)小塊分別進(jìn)行直方圖均衡化(跟前面類(lèi)似)。
所以在每一個(gè)的區(qū)域中,直方圖會(huì)集中在某一個(gè)小的區(qū)域中(除非有噪聲干擾)。如果有噪聲的話,噪聲會(huì)被放大。為了避免這種情況的出現(xiàn)要使用對(duì)比度限制。對(duì)于每個(gè)小塊來(lái)說(shuō),如果直方圖中的 也就是灰度級(jí)別 超過(guò)對(duì)比度的上限的話,就把其中的像素點(diǎn)均勻分散到其他 bins 中,然后在進(jìn)行直方圖均衡化。最后,為了去除每一個(gè)小塊之間“人造的”(由于算法造成)邊界,再使用雙線性差值,對(duì)小塊進(jìn)行縫合。
?
2、適用場(chǎng)景與優(yōu)勢(shì)
自適應(yīng)直方圖均衡化(AHE)用來(lái)提升圖像的對(duì)比度的一種計(jì)算機(jī)圖像處理技術(shù)。和普通的直方圖均衡算法不同,AHE算法通過(guò)計(jì)算圖像的局部直方圖,然后重新分布亮度來(lái)來(lái)改變圖像對(duì)比度。因此,該算法更適合于改進(jìn)圖像的局部對(duì)比度以及獲得更多的圖像細(xì)節(jié)。
3、原理及代碼
原理比較復(fù)雜,可參考:https://blog.csdn.net/huangli19870217/article/details/45534397
def clahe(img,tileGridSize=8):'''限制對(duì)比度自適應(yīng)直方圖均衡:param img: 待測(cè)圖像:param tileGridSize: 劃分小區(qū)域的大小一般為8:return: 返回的是直方圖均衡化后的圖像'''img = cv2.imread(img, 0)clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(tileGridSize, tileGridSize))#先設(shè)置區(qū)域塊tile的大小以及裁剪的限制cl1 = clahe.apply(img)#對(duì)圖片進(jìn)行自適應(yīng)均衡化return cl1這時(shí)候的圖像對(duì)比度高,且不會(huì)模糊細(xì)節(jié)
總結(jié)
以上是生活随笔為你收集整理的【图像处理】——图像增强Python实现直方图均衡化的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 全国计算机OFFICE二级考试大纲,全国
- 下一篇: 【图像处理】——Python图像分割边缘