【图像处理】——图像增强Python实现直方图均衡化
目錄
一、相關概念
1、灰度直方圖概念(hist)
2、灰度概率累積函數(cdf)
3、灰度直方圖均衡化(equalizehist)
4、均衡化適用范圍
二、均衡化的目的以及求解步驟
1、目的
2、求解步驟
(1)原圖灰度直方圖求解
(2)計算累積直方圖
直方圖.cumsum(),返回累積直方圖數據
(3)取整擴展確定映射關系
(4)根據映射關系計算均衡化直方圖以及圖像(這一步是關鍵)
3、繪制未均衡和均衡后對應像素點像素值的改變
三、全局均衡化直方圖
1、系統自帶函數
2、自定義函數
3、結果展示
四、限制對比度自適應直方圖均衡(Contrast Limited?Adaptive histgram equalization/CLAHE)
1、限制對比度自適應直方圖均衡的概念
2、適用場景與優勢
3、原理及代碼
?
一、相關概念
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.shapehist = 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
(4)根據映射關系計算均衡化直方圖以及圖像(這一步是關鍵)
計算后的灰度級替換掉計算前的灰度級,得到均衡化后的直方圖
#第四步根據第三步的映射關系將灰度圖每個像素點的灰度級別替換為映射后的灰度級別,這里是這樣換的,equal_hist的索引號相當于原先的灰度級別排序,元素值則是映射后的灰度級別equal_img = img.copy()#用于存放均衡化后圖像的灰度值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 pltdef sys_equalizehist(img):'''利用系統自帶的函數進行直方圖均衡化:param img: 待處理圖像:return: [equ_img,equ_hist],返回一個列表,第一個元素是均衡化后的圖像,第二個是均衡了的直方圖'''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#這一行是將兩個圖像進行了行方向的疊加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 pltdef sys_equalizehist(img):'''利用系統自帶的函數進行直方圖均衡化:param img: 待處理圖像:return: [equ_img,equ_hist],返回一個列表,第一個元素是均衡化后的圖像,第二個是均衡了的直方圖'''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#這一行是將兩個圖像進行了行方向的疊加return [equ_img,equ_hist]2、自定義函數
def def_equalizehist(img,L=256):'''根據均衡化原理自定義函數:param img: 待處理圖像:param L: 灰度級別的個數:return: [equal_img,equal_hist]返回一個列表,第一個元素是均衡化后的圖像,第二個是均衡了的直方圖'''img = cv2.imread(img,0)#第一步獲取圖像的直方圖h,w = img.shapehist = cv2.calcHist([img],[0],None,[256],[0,255])#這里返回的是次數hist[0:255] = hist[0:255]/(h*w)#將直方圖歸一化,化為概率的形式#第二步得到灰度級概率累積直方圖sum_hist = np.zeros(hist.shape)#用于存放灰度級別概率的累和for i in range(256):sum_hist[i] = sum(hist[0:i+1])#將前i+1個灰度級別的出現概率總和賦值給sum_hist[i]#第三步通過映射函數獲得原圖像灰度級與均衡后圖像的灰度級的映射關系,這里創建映射后的灰度級別排序equal_hist = np.zeros(sum_hist.shape)for i in range(256):equal_hist[i] = int(((L-1)-0)*sum_hist[i]+0.5)#第四步根據第三步的映射關系將灰度圖每個像素點的灰度級別替換為映射后的灰度級別,這里是這樣換的,equal_hist的索引號相當于原先的灰度級別排序,元素值則是映射后的灰度級別equal_img = img.copy()#用于存放均衡化后圖像的灰度值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) # 將直方圖歸一化,化為概率的形式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、結果展示
均衡化以前
均衡化以后
可見均衡化后的直方圖比較密集了,且比較均勻,說明各個灰度級別出現的概率比較相近 ,且均衡化的圖像比均衡化前的對比度大,亮的更亮,暗的更暗,色差大
四、限制對比度自適應直方圖均衡(Contrast Limited?Adaptive histgram equalization/CLAHE)
1、限制對比度自適應直方圖均衡的概念
有限對比適應性直方圖均衡化我們在上邊做的直方圖均衡化會改變整個圖像的對比度,但是在很多情況下,這樣做的效果并不好。如下圖:
?????? 的確在進行完直方圖均衡化之后,圖片背景的對比度被改變了。但是你再對比一下兩幅圖像中雕像的面圖,由于太亮我們丟失了很多信息。造成這種結果的根本原因在于這幅圖像的直方圖并不是集中在某一個區域(試著畫出它的直方圖,你就明白了)。
????????? 為了解決這個問題,我們需要使用自適應的直方圖均衡化。這種情況下,整幅圖像會被分成很多小塊,這些小塊被稱為“tiles”(在 OpenCV 中 tiles 的大小默認是 8x8),然后再對每一個小塊分別進行直方圖均衡化(跟前面類似)。
所以在每一個的區域中,直方圖會集中在某一個小的區域中(除非有噪聲干擾)。如果有噪聲的話,噪聲會被放大。為了避免這種情況的出現要使用對比度限制。對于每個小塊來說,如果直方圖中的 也就是灰度級別 超過對比度的上限的話,就把其中的像素點均勻分散到其他 bins 中,然后在進行直方圖均衡化。最后,為了去除每一個小塊之間“人造的”(由于算法造成)邊界,再使用雙線性差值,對小塊進行縫合。
?
2、適用場景與優勢
自適應直方圖均衡化(AHE)用來提升圖像的對比度的一種計算機圖像處理技術。和普通的直方圖均衡算法不同,AHE算法通過計算圖像的局部直方圖,然后重新分布亮度來來改變圖像對比度。因此,該算法更適合于改進圖像的局部對比度以及獲得更多的圖像細節。
3、原理及代碼
原理比較復雜,可參考:https://blog.csdn.net/huangli19870217/article/details/45534397
def clahe(img,tileGridSize=8):'''限制對比度自適應直方圖均衡:param img: 待測圖像:param tileGridSize: 劃分小區域的大小一般為8:return: 返回的是直方圖均衡化后的圖像'''img = cv2.imread(img, 0)clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(tileGridSize, tileGridSize))#先設置區域塊tile的大小以及裁剪的限制cl1 = clahe.apply(img)#對圖片進行自適應均衡化return cl1這時候的圖像對比度高,且不會模糊細節
總結
以上是生活随笔為你收集整理的【图像处理】——图像增强Python实现直方图均衡化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 全国计算机OFFICE二级考试大纲,全国
- 下一篇: Access数据库多表联合查询