第13章:直方图处理
第13章:直方圖處理
- 一、直方圖的含義:
- 1. 普通直方圖:
- 2. 歸一化直方圖:
- 二、繪制直方圖:
- 1. 使用Numpy繪制直方圖:
- 2. 使用OpenCV繪制直方圖:
- 3. 使用掩碼繪制直方圖:
- 三、直方圖均衡化:
- 1. 直方圖均衡化的原理:
- (1) 在原有范圍內(nèi)實現(xiàn)均衡化:
- (2) 在更廣泛的范圍內(nèi)實現(xiàn)均衡化:
- 2. 直方圖均衡化處理:
- 直方圖是圖像處理過程中一種重要的分析工具。
- 直方圖是從圖像內(nèi)部灰度級的角度對圖像進(jìn)行表述,包含豐富重要的信息。
- 從直方圖的角度對圖像進(jìn)行處理,可以達(dá)到增強(qiáng)圖像顯示效果的目的。
一、直方圖的含義:
1. 普通直方圖:
從統(tǒng)計的角度講,直方圖統(tǒng)計的是圖像內(nèi)各個灰度級出現(xiàn)的次數(shù)。從直方圖的圖形上觀察,橫坐標(biāo)是圖像中各像素點的灰度級,縱坐標(biāo)是具有該灰度級(像素值)的像素個數(shù)。
例如,有一幅圖像。該圖中只有9個像素點,存在1、2、3、4、5,共5個灰度級。
統(tǒng)計各個灰度級出現(xiàn)的次數(shù):
在繪制直方圖時,將灰度級作為x軸處理,該灰度級出現(xiàn)的次數(shù)作為y軸處理,則可知:
- x軸的數(shù)據(jù)為x=[1 2 3 4 5]。
- y軸的數(shù)據(jù)為y=[3 1 2 1 2]。
根據(jù)上述關(guān)系,可以繪制出如圖所示的折線圖(左圖)和直方圖(右圖)。一般情況下,我們把左側(cè)的直線圖和右側(cè)直方圖都稱為直方圖。
在實際處理中,圖像直方圖的x軸區(qū)間一般是[0,255],對應(yīng)的是8位位圖的256個灰度級;y軸對應(yīng)的是具有相應(yīng)灰度級的像素點的個數(shù)。
2. 歸一化直方圖:
歸一化直方圖中,x軸仍然表示灰度級;y軸不再表示灰度級出現(xiàn)的次數(shù),而是灰度級出現(xiàn)的頻率。
- 灰度級出現(xiàn)的頻率 = 灰度級出現(xiàn)的次數(shù)/總像素數(shù)
例如,統(tǒng)計各個灰度級出現(xiàn)的頻率:
在歸一化直方圖中,各個灰度級出現(xiàn)的頻率之和為1。例如,本例中:
在繪制直方圖時,將灰度級作為x軸數(shù)據(jù)處理,將其出現(xiàn)的頻率作為y軸數(shù)據(jù)處理,則可知:
- x軸的數(shù)據(jù)為x=[1 2 3 4 5]
- y軸的數(shù)據(jù)為y=[3/9 1/9 2/9 1/9 2/9]
注意:在OpenCV的官網(wǎng)上,特別提出了要注意三個概念:DIMS、BINS、RANGE。
- DIMS:表示在繪制直方圖時,收集的參數(shù)的數(shù)量。一般情況下,直方圖中收集的數(shù)據(jù)只有一種,就是灰度級。因此,該值為1。
- RANGE:表示要統(tǒng)計的灰度級范圍,一般為[0,255]。0對應(yīng)的是黑色,255對應(yīng)的是白色。
- BINS:參數(shù)子集的數(shù)目,即參數(shù)分的組的數(shù)量。在處理數(shù)據(jù)的過程中,有時需要將眾多的數(shù)據(jù)劃分為若干個組,再進(jìn)行分析。
例如,在灰度圖像中,將[0,255]區(qū)間內(nèi)的256個灰度級,按照每16個像素一組劃分為子集:
[0,255]=[0,15]∪[16,31]∪…∪[240,255]
按照上述方式,整個灰度級范圍可以劃分為16個子集,具體為:
整個灰度級范圍=bin1 ∪ bin2 ∪…∪ bin16
子集劃分完以后,某灰度圖像生成的直方圖如圖所示
討論BINS的值:
- 在原始圖像中,如果,共有5個灰度級,其BINS值為5。在以2個灰度級為一個小組劃分子集后,得到3個子集,其BINS值為3。
- 針對灰度圖像,灰度級區(qū)間為[0,255],共有256個灰度級,其BINS值為256;在以16個灰度級為一個小組劃分子集后,其BINS值為16。
二、繪制直方圖:
繪制直方圖的方式有兩種:
1. 使用Numpy繪制直方圖:
Python模塊matplotlib.pyplot 提供了一個類似于 MATLAB 繪圖方式的框架,可以使用其中的matplotlib.pyplot.hist() 函數(shù)(以下簡稱為hist()函數(shù))來繪制直方圖。
此函數(shù)的作用是根據(jù)數(shù)據(jù)源和灰度級分組繪制直方圖。其基本語法格式為:
- matplotlib.pyplot.hist(X,BINS)
- X:數(shù)據(jù)源,必須是一維的。圖像通常是二維的,需要使用ravel()函數(shù)將圖像處理為一維數(shù)據(jù)源以后,再作為參數(shù)使用。
- BINS:BINS的具體值,表示灰度級的分組情況。
示例:
import cv2 import matplotlib.pyplot as pltimg = cv2.imread('../boat.512.tiff', 0) # 將二維數(shù)組轉(zhuǎn)換為一維的 data = img.ravel() print(data) plt.hist(data, 256) plt.show() cv2.imshow('img', img)cv2.waitKey() cv2.destroyAllWindows()# 輸出結(jié)果 [127 123 125 ... 102 95 97]2. 使用OpenCV繪制直方圖:
在OpenCV提供了函數(shù)cv2.calcHist()用來計算圖像的統(tǒng)計直方圖,該函數(shù)能夠統(tǒng)計圖像內(nèi)各個灰度級的像素點個數(shù)。然后,利用matplotlib.pyplot模塊中的plot()函數(shù),可以將函數(shù)cv2.calcHist()的統(tǒng)計結(jié)果繪制成直方圖。
- hist=cv2.calcHist(images,channels,mask,histSize,ranges,accumulate)
- hist:返回的統(tǒng)計直方圖,是一個一維數(shù)組,數(shù)組內(nèi)的元素是各個灰度級的像素個數(shù)。
- images:原始圖像,該圖像需要使用“[]”括起來。
- channels:指定通道編號。通道編號需要用“[]”括起來,如果輸入圖像是單通道灰度圖像,該參數(shù)的值就是[0]。對于彩色圖像,它的值可以是[0]、[1]、[2],分別對應(yīng)通道B、G、R。
- mask:掩模圖像。當(dāng)統(tǒng)計整幅圖像的直方圖時,將這個值設(shè)為None。當(dāng)統(tǒng)計圖像某一部分的直方圖時,需要用到掩模圖像。
- histSize:BINS的值,該值需要用“[]”括起來。例如,BINS的值是256,需要使用“[256]”作為此參數(shù)值。
- ranges:即像素值范圍。例如,8位灰度圖像的像素值范圍是[0,255]。
- accumulate:累計(累積、疊加)標(biāo)識,默認(rèn)值為False。如果被設(shè)置為True,則直方圖在開始計算時不會被清零,計算的是多個直方圖的累積結(jié)果,用于對一組圖像計算直方圖。該參數(shù)允許從多個對象中計算單個直方圖,或者實時更新直方圖。該參數(shù)是可選的,一般情況下不需要設(shè)置。
使用matplotlib.pyplot模塊內(nèi)的plot()函數(shù),將函數(shù)cv2.calcHist()的返回值繪制為圖像直方圖
import cv2 import matplotlib.pyplot as pltimg = cv2.imread('../boat.512.tiff', 0) hist = cv2.calcHist([img], [0], None, [256],[0, 255])plt.plot(hist,color='b') plt.show() cv2.imshow('img', img) cv2.waitKey() cv2.destroyAllWindows()補(bǔ)充: 學(xué)習(xí)plot()函數(shù)的其他用法:
示例1: 將給定的x=[0,1,2,3,4,5,6],y=[0.3,0.4,2,5,3,4.5,4],使用plot()函數(shù)繪制出來。
import matplotlib.pyplot as pltx = [0, 1, 2, 3, 4, 5, 6] y = [0.3, 0.4, 2, 5, 3, 4.5, 4] plt.plot(x, y) plt.show()圖中x軸由x=[0,1,2,3,4,5,6]指定,y軸由y=[0.3,0.4,2,5,3,4.5,4]指定。
示例2: 給定y=[0.3,0.4,2,5,3,4.5,4],使用plot()函數(shù)將其繪制出來,觀察繪制結(jié)果。
import matplotlib.pyplot as plty = [0.3, 0.4, 2, 5, 3, 4.5, 4] plt.plot(y) plt.show()從圖中可以看出,在使用plot()函數(shù)時,如果僅僅指定一個參數(shù),則其對應(yīng)x軸的值默認(rèn)是一個自然數(shù)序列x=[0,1,… ,n?1,n]。自然序列x的長度與y的長度保持一致。
示例3: 使用plot()函數(shù)將兩組不同的值a=[0.3,0.4,2,5,3,4.5,4], b=[3,5,1,2,1,5,3]以不同的顏色繪制出來。
import matplotlib.pyplot as plta = [0.3, 0.4, 2, 5, 3, 4.5, 4] b = [3, 5, 1, 2, 1, 5, 3] plt.plot(a, color='b') plt.plot(b, color='g')plt.show()示例4: 使用函數(shù)plot()和函數(shù)cv2.calcHist(),將彩色圖像各個通道的直方圖繪制在一個窗口內(nèi)。
import cv2 import matplotlib.pyplot as pltimg = cv2.imread('../lena512color.tiff') hist_b = cv2.calcHist([img], [0], None, [256], [0, 255]) hist_g = cv2.calcHist([img], [1], None, [256], [0, 255]) hist_r = cv2.calcHist([img], [2], None, [256], [0, 255])plt.plot(hist_b, 'b') plt.plot(hist_g, 'g') plt.plot(hist_r, 'r') plt.show()cv2.imshow('img', img) cv2.waitKey() cv2.destroyAllWindows()3. 使用掩碼繪制直方圖:
import cv2 import matplotlib.pyplot as plt import numpy as npimg = cv2.imread('../lena512color.tiff')mask = np.zeros(img.shape[:2], np.uint8) mask[200: 400, 200: 400] = 255hist_b = cv2.calcHist([img], [0], mask, [256], [0, 255]) hist_g = cv2.calcHist([img], [1], mask, [256], [0, 255]) hist_r = cv2.calcHist([img], [2], mask, [256], [0, 255])plt.plot(hist_b, 'b') plt.plot(hist_g, 'g') plt.plot(hist_r, 'r') plt.show()rst = cv2.bitwise_and(img, img, mask=mask) cv2.imshow('img', img) cv2.imshow('rst', rst) cv2.waitKey() cv2.destroyAllWindows()三、直方圖均衡化:
為什么要直方圖均衡化?
如果一幅圖像擁有全部可能的灰度級,并且像素值的灰度均勻分布,那么這幅圖像就具有高對比度和多變的灰度色調(diào),灰度級豐富且覆蓋范圍較大。在外觀上,這樣的圖像具有更豐富的色彩,不會過暗或過亮。
如上圖直方圖均衡化前后的對比
? 在OpenCV的官網(wǎng)上,對圖像均衡化前后的直方圖進(jìn)行了對比,如圖所示。其中,左圖是原始圖像的直方圖,可以看到灰度級集中在中間,圖像中沒有較暗和較亮的像素點;右圖是對原圖均衡化后的直方圖,像素分布更均衡。
什么是直方圖均衡化?
? 直方圖均衡化的主要目的是將原始圖像的灰度級均勻地映射到整個灰度級范圍內(nèi),得到一個灰度級分布均勻的圖像。這種均衡化,既實現(xiàn)了灰度值統(tǒng)計上的概率均衡,也實現(xiàn)了人類視覺系統(tǒng)(Human Visual System,HVS)上的視覺均衡。
例如:在某幅圖像內(nèi)僅僅出現(xiàn)了1、2、3、101、102、103等6個像素值,其分布分別如表中的情況A和情況B所示。
下面分別討論這兩種情況下像素值均衡的情況。
- 情況A:每一個灰度級在圖像內(nèi)出現(xiàn)的次數(shù)都是1,灰度級均勻地映射到當(dāng)前的灰度級范圍內(nèi),所以可以理解為其直方圖是均衡的。
- 情況B:灰度級1、2、3出現(xiàn)的次數(shù)都是1次,灰度級103出現(xiàn)的次數(shù)是3次,灰度級101、102出現(xiàn)的次數(shù)是0次。從表面上看,灰度級是不均衡的。但是,從HVS的角度來說,人眼的敏感度不足以區(qū)分1個像素值的差異,即人眼會將灰度級1、2和3看作是相同的,會將灰度級101、102和103看作是相同的。也就是說,HVS會自動地將灰度級劃分為兩組,灰度級[1,3]為一組,灰度級[101,103]為另一組。在整幅圖像內(nèi),這兩組的灰度級出現(xiàn)的次數(shù)都是3次,概率是相等的。在均衡化處理中,綜合考慮了統(tǒng)計概率和HVS的均衡。
1. 直方圖均衡化的原理:
直方圖均衡化的算法主要包括兩個步驟:
(1)計算累計直方圖。
(2)對累計直方圖進(jìn)行區(qū)間轉(zhuǎn)換
在此基礎(chǔ)上,再利用人眼視覺達(dá)到直方圖均衡化的目的。
下面我們通過一個例子進(jìn)行講解。例如,圖像A,它是一幅3位的位圖,即共有8(23)個灰度級,有49個像素。
圖像A共有8個灰度級,范圍為[0,7],計算其統(tǒng)計直方圖如表所示:
在此基礎(chǔ)上,計算歸一化統(tǒng)計直方圖,計算方式是計算每個像素在圖像內(nèi)出現(xiàn)的概率。出現(xiàn)概率=出現(xiàn)次數(shù)/像素總數(shù),用每個灰度級的像素個數(shù)除以總的像素個數(shù)(49),就得到歸一化統(tǒng)計直方圖。
接下來,計算累計統(tǒng)計直方圖,即計算所有灰度級的累計概率。
在累計直方圖的基礎(chǔ)上,對原有灰度級空間進(jìn)行轉(zhuǎn)換。可以在原有范圍內(nèi)對灰度級實現(xiàn)均衡化,也可以在更廣泛的灰度空間范圍內(nèi)對灰度級實現(xiàn)均衡化。下面分別介紹這兩種形式。
(1) 在原有范圍內(nèi)實現(xiàn)均衡化:
在原有范圍內(nèi)實現(xiàn)直方圖均衡化時,用當(dāng)前灰度級的累計概率乘以當(dāng)前灰度級的最大值7,得到新的灰度級,并作為均衡化的結(jié)果。
- 原始圖像A中的灰度級0,經(jīng)直方圖均衡化后調(diào)整為新的灰度級1(即均衡化值1)。在原始圖像A中,灰度級0共有9個像素點,所以在均衡化后的圖像中,灰度級1共有9個像素點。
- 原始圖像A中的灰度級1和2經(jīng)直方圖均衡化后調(diào)整為灰度級3。在原始圖像A中,灰度級1共有9個像素點,灰度級2共有6個像素點,所以在均衡化后的圖像中,灰度級3共有9+6=15個像素點。
- 原始圖像A中的灰度級3經(jīng)直方圖均衡化后調(diào)整為灰度級4。在原始圖像A中,灰度級3共有5個像素點,所以在均衡化后的圖像中,灰度級4共有5個像素點。
- 原始圖像A中的灰度級4和5經(jīng)直方圖均衡化后調(diào)整為灰度級5。在原始圖像A中,灰度級4共有6個像素點,灰度級5共有3個像素點,所以在均衡化后的圖像中,灰度級5共有6+3=9個像素點。
- 原始圖像A中的灰度級6經(jīng)直方圖均衡化后調(diào)整為灰度級6。在原始圖像A中,灰度級6共有3個像素點,所以在均衡化后的圖像中,灰度級6共有3個像素點。
- 原始圖像A中的灰度級7經(jīng)直方圖均衡化后調(diào)整為灰度級7。在原始圖像A中,灰度級7共有8個像素點,所以在均衡化后的圖像中,灰度級7共有8個像素點。
經(jīng)過均衡化處理后,灰度級在整個灰度空間內(nèi)的分布會更均衡。
直方圖均衡化前后的對比圖。其中,左圖是均衡化之前的直方圖,右圖是均衡化之后的直方圖。
這里的均衡化是綜合考慮了統(tǒng)計概率和HVS的結(jié)果。
- 在圖像A中,未進(jìn)行直方圖均衡化之前:灰度級0 ~ 3之間的像素個數(shù)為29個,灰度級4 ~ 7之間的像素個數(shù)為20個。
- 對圖像A進(jìn)行直方圖均衡化之后:灰度級0 ~ 3之間的像素個數(shù)為24個,灰度級4 ~ 7之間的像素個數(shù)為25個。
通過上述比較,可以看出,直方圖均衡化之后圖像的灰度級分布更均衡了。
(2) 在更廣泛的范圍內(nèi)實現(xiàn)均衡化:
? 在更廣泛的范圍內(nèi)實現(xiàn)直方圖均衡化時,用當(dāng)前灰度級的累計概率乘以更廣泛范圍灰度級的最大值,得到新的灰度級,并作為均衡化的結(jié)果。
? 例如,要將灰度級空間擴(kuò)展為[0,255]共256個灰度級,就必須將原灰度級的累計概率乘以255,得到新的灰度級。如表所示的是圖像A在新的灰度級空間[0,255]內(nèi)的新的灰度級。
經(jīng)過均衡化處理后,圖像A的灰度級在新灰度空間[0,255]內(nèi)保持均衡。
通過上述分析可知,通過如下兩個步驟, 可以讓直方圖達(dá)到均衡化的效果。
-
計算累計直方圖。
-
將累計直方圖進(jìn)行區(qū)間轉(zhuǎn)換。
下面我們用數(shù)學(xué)表達(dá)式描述以上的直方圖均衡化過程。假設(shè)圖像中像素的總數(shù)是N,圖像的灰度級數(shù)是L,灰度級空間是[0,L-1],用nkn_knk?表示第k級灰度(第k個灰度級,灰度值為k)在圖像內(nèi)的像素點個數(shù),那么該圖像中灰度級為rkr_krk?(第k個灰度級)出現(xiàn)的概率為:
根據(jù)灰度級概率,對其進(jìn)行均衡化處理的計算公式為:
式中,表示累計概率,將該值與灰度級的最大值L-1相乘即得到均衡化后的新灰度級(像素值)。
? 直方圖均衡化使圖像色彩更均衡、外觀更清晰,也使圖像更便于處理,它被廣泛地應(yīng)用在醫(yī)學(xué)圖像處理、車牌識別、人臉識別等領(lǐng)域。
2. 直方圖均衡化處理:
在OpenCV中通過函數(shù)cv2.equalizeHist()來實現(xiàn)直方圖均衡化。該函數(shù)的具體語法格式為:
- dst = cv2.equalizeHist(src)
- src:8位單通道原始圖像
- dst:直方圖均衡化處理的結(jié)果。
在直方圖均衡化之前,圖像整體比較亮;均衡化以后,圖像的亮度變得比較均衡。而兩幅圖像的直方圖的對比,則不太明顯。這實際上體現(xiàn)了,均衡化是指綜合考慮了統(tǒng)計概率和HVS的結(jié)果。
總結(jié)
以上是生活随笔為你收集整理的第13章:直方图处理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 字节和字符串
- 下一篇: Debian安装metasploit