直方圖是什么?
直方圖是一種圖形表示方法,用于顯示數(shù)據(jù)中各個數(shù)值或數(shù)值范圍的分布情況。它將數(shù)據(jù)劃分為一系列的區(qū)間(也稱為“箱子”或“bin”),然后統(tǒng)計每個區(qū)間中數(shù)據(jù)出現(xiàn)的頻次(或頻率)。直方圖可以幫助我們更好地理解數(shù)據(jù)的分布特征,包括集中趨勢、離散程度等。
直方圖的主要特點包括:
1. 橫軸(X 軸): 橫軸表示數(shù)據(jù)的數(shù)值范圍或區(qū)間。每個區(qū)間通常由兩個數(shù)值來表示,例如,0-10、10-20 等。
2. 縱軸(Y 軸): 縱軸表示每個區(qū)間中數(shù)據(jù)的頻次(或頻率),也就是該區(qū)間內(nèi)數(shù)據(jù)出現(xiàn)的次數(shù)。
3. 條形圖: 直方圖的圖形由一系列的矩形條組成,每個矩形條的寬度表示區(qū)間的寬度,高度表示該區(qū)間內(nèi)數(shù)據(jù)的頻次。
4. 連續(xù)數(shù)據(jù): 直方圖適用于連續(xù)型數(shù)據(jù)
,例如測量數(shù)據(jù)、時間數(shù)據(jù)等。對于離散型數(shù)據(jù),柱狀圖可能更為適合
。
直方圖在許多領(lǐng)域有重要的應(yīng)用,包括統(tǒng)計學(xué)、圖像處理、數(shù)據(jù)分析等。在圖像處理中,直方圖可以用來分析圖像的像素值分布,從而進(jìn)行圖像增強、對比度調(diào)整、圖像分割等操作。在統(tǒng)計學(xué)中,直方圖可以幫助我們了解數(shù)據(jù)的分布情況,如正態(tài)分布、偏態(tài)分布等。通過觀察直方圖,我們可以對數(shù)據(jù)的特征有更深入的了解,從而做出更準(zhǔn)確的決策和分析
直方圖在圖像中的含義
從統(tǒng)計的角度講,直方圖是圖像內(nèi)灰度值的統(tǒng)計特性與圖像灰度值之間的函數(shù),直方圖統(tǒng)計圖像內(nèi)各個灰度級出現(xiàn)的次數(shù)。從直方圖的圖形上觀察,橫坐標(biāo)是圖像中各像素點的灰度級,縱坐標(biāo)是具有該灰度級(像素值)的像素個數(shù)。
例如,有一幅圖像如圖 13-1 所示。該圖中只有 9 個像素點,存在 1、2、3、4、5,共 5 個灰度級。
統(tǒng)計各個灰度級出現(xiàn)的次數(shù),如表 13-1 所示
在繪制直方圖時,將灰度級作為 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)系,可以繪制出如圖 13-2 所示的折線圖(左圖)和直方圖(右圖)。一般情況下,我們把左側(cè)的直線圖和右側(cè)直方圖都稱為直方圖。
在實際處理中,圖像直方圖的 x 軸區(qū)間一般是[0, 255],對應(yīng)的是 8 位位圖的 256 個灰度級;y 軸對應(yīng)的是具有相應(yīng)灰度級的像素點的個數(shù)。
例如在圖 13-3 中,上圖是一張圖像,下圖則是其對應(yīng)的直方圖。圖中圓點表示這些像素點會被統(tǒng)計到對應(yīng)的灰度級上。
雖然 8 位的圖像都具有 256 個灰度級(每一個像素可以有 256 個灰度值),但是屬于不同灰度級的像素數(shù)量是很不一樣的。
例如圖 13-4,從圖中可以看出,圖像的不同部分直方圖是不一樣的。
有時為了便于表示,也會采用歸一化直方圖。在歸一化直方圖中,x 軸仍然表示灰度級;y軸不再表示灰度級出現(xiàn)的次數(shù),而是灰度級出現(xiàn)的頻率。
例如,針對圖 13-1,統(tǒng)計各個灰度級出現(xiàn)的頻率:
灰度級出現(xiàn)的頻率 = 灰度級出現(xiàn)的次數(shù)/總像素數(shù)
在圖 13-1 中共有 9 個像素,所以統(tǒng)計結(jié)果如表 13-2 所示。
在歸一化直方圖中,各個灰度級出現(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]
根據(jù)上述關(guān)系,可以繪制出如圖 13-5 所示的歸一化直方圖。對比圖 13-4 與圖 13-5,可以看到,歸一化直方圖與直方圖在外觀上是一致的,只是 y 軸的標(biāo)簽不同而已。
本例中,在直方圖內(nèi),y 軸顯示的標(biāo)簽是 1、2、3;在歸一化直方圖中,y 軸顯示的標(biāo)簽是 1/9、2/9、3/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ù)據(jù)的過程中,有時需要將眾多的數(shù)據(jù)劃分為若干個組,再進(jìn)行分析。
例如,針對圖 13-1 中的灰度級,你可能希望將兩個像素值作為一組討論。這樣,整個灰度級被劃分為三組,具體為{ {1,2} , {3,4} , {5} }。圖 13-6 所示的是劃分前后的直方圖情況。
也可以按照上述方式對灰度圖像進(jìn)行劃分。例如,在灰度圖像中,將[0, 255]區(qū)間內(nèi)的 256個灰度級,按照每 16 個像素一組劃分為子集:
[0, 255] = [0, 15] ∪ [16, 31] ∪…∪[240, 255]
按照上述方式,整個灰度級范圍可以劃分為 16 個子集,具體為:
整個灰度級范圍 = bin1 ∪ bin2 ∪…∪ bin16
子集劃分完以后,某灰度圖像生成的直方圖如圖 13-7 所示(圖中的 b1 代表 bin1,b2 代表bin2,以此類推)。
下面討論 BINS 的值:
- 針對圖 13-1,在原始圖像中,共有 5 個灰度級,其 BINS 值為 5。在以 2 個灰度級為一個小組劃分子集后,得到 3 個子集,其 BINS 值為 3。
- 針對灰度圖像,灰度級區(qū)間為[0, 255],共有 256 個灰度級,其 BINS 值為 256;在以 16個灰度級為一個小組劃分子集后,其 BINS 值為 16。
說白了就是柱子的數(shù)量
繪制直方圖
Python 的模塊 matplotlib.pyplot 中的 hist()
函數(shù)能夠方便地繪制直方圖,我們通常采用該函數(shù)直接繪制直方圖(機器學(xué)習(xí)也用的這個)。除此以外,OpenCV 中的cv2.calcHist()函數(shù)
能夠計算統(tǒng)計直方圖,還可以
在此基礎(chǔ)上繪制圖像的直方圖。下面分別討論這兩種方式。
使用Numpy繪制直方圖
模塊 matplotlib.pyplot 提供了一個類似于 MATLAB 繪圖方式的框架,可以使用其中的matplotlib.pyplot.hist()函數(shù)
(以下簡稱為 hist()函數(shù))來繪制直方圖。
此函數(shù)的作用是根據(jù)數(shù)據(jù)源和灰度級分組繪制直方圖。其基本語法格式為:
matplotlib.pyplot.hist(X,BINS)
其中兩個參數(shù)的含義如下:
-
X:數(shù)據(jù)源,必須是一維的。圖像通常是二維的,需要使用 ravel()函數(shù)將圖像處理為一維數(shù)據(jù)源以后,再作為參數(shù)使用。
-
BINS:BINS 的具體值,表示灰度級的分組情況。
函數(shù) ravel()的作用是將二維數(shù)組降維成一維數(shù)組。例如,有圖像 a,其值為:
使用函數(shù) ravel()對 a 進(jìn)行處理:
b = a.ravel()
可以得到 b 為:
示例:使用 hist()函數(shù)繪制一幅圖像的直方圖。
代碼如下:
import cv2
import matplotlib.pyplot as plt
o=cv2.imread("boat.jpg")
plt.hist(o.ravel(),256)
plt.show()
運行結(jié)果:
示例:使用函數(shù) hist()將一幅圖像的灰度級劃分為 16 組后,繪制該圖像的直方圖。
將上面的255改成了16
import cv2
import matplotlib.pyplot as plt
o=cv2.imread("boat.jpg")
plt.hist(o.ravel(),16)
plt.show()
使用OpenCV繪制直方圖
OpenCV 提供了函數(shù) cv2.calcHist()用來計算圖像的統(tǒng)計直方圖,該函數(shù)能統(tǒng)計各個灰度級的像素點個數(shù)。利用matplotlib.pyplot 模塊中的 plot()函數(shù),可以將函數(shù) cv2.calcHist()的統(tǒng)計結(jié)果繪制成直方圖
1.用cv2.calcHist()函數(shù)統(tǒng)計圖像直方圖信息
函數(shù) cv2.calcHist()用于統(tǒng)計圖像直方圖信息,其語法格式為:
hist = cv2.calcHist( images, channels, mask, histSize, ranges, accumulate )
函數(shù)中返回值及參數(shù)的含義為:
-
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è)置。
示例:使用 cv2.calcHist()函數(shù)計算一幅圖像的統(tǒng)計直方圖結(jié)果,并觀察得到的統(tǒng)計直方圖信息。
代碼如下:
import cv2
img=cv2.imread("boat.jpg")
hist = cv2.calcHist([img],[0],None,[16],[0,255])
print(type(hist))
print(hist.shape)
print(hist.size)
print(hist)
運行結(jié)果如下:
需要注意,在本例的 cv2.calcHist()函數(shù)中:
- 第 1 個參數(shù)“[img]”表示要繪制直方圖的原始圖像,是使用“[ ]”括起來的。
- 第 2 個參數(shù)表示要統(tǒng)計哪個通道的直方圖信息。本例中讀取的 img 是灰度圖像,所以使
用“[0]”來表示。 - 第 3 個參數(shù)是掩模圖像,在本例中的值為“None”,表示計算整幅圖像的直方圖。
- 第 4 個參數(shù)“[16]”表示 BINS 的值是 16,也就是分了16組
- 第 5 個參數(shù)“[0, 255]”表示灰度級的范圍是[0, 255]。
<class 'numpy.ndarray'>
(16, 1)
16
[[ 12575.]
[ 39591.]
[ 56651.]
[ 38932.]
[ 29997.]
[ 33472.]
[ 46033.]
[ 74555.]
[199718.]
[288966.]
[136663.]
[ 44440.]
[ 20355.]
[ 20691.]
[ 5578.]
[ 344.]]
示例:繪制統(tǒng)計直方圖
import cv2
from matplotlib import pyplot as plt
img=cv2.imread("boat.jpg")
hist = cv2.calcHist([img],[0],None,[16],[0,255])
plt.plot(hist,color='b')
plt.show()
運行結(jié)果:
以上都是將圖像進(jìn)行直方圖展示函數(shù),下面來講下直方圖在圖像處理中的應(yīng)用函數(shù)。
直方圖均衡化
如果一幅圖像擁有全部可能的灰度級,并且像素值的灰度均勻分布,那么這幅圖像就具有高對比度和多變的灰度色調(diào),灰度級豐富且覆蓋范圍較大。在外觀上,這樣的圖像具有更豐富的色彩,不會過暗或過亮。
圖 13-22 展示了對一幅圖像進(jìn)行直方圖均衡化前后的對比,左圖是原始圖像,比較暗;右圖是均衡化后的圖像,色彩比較均衡。
在 OpenCV 的官網(wǎng)上,對圖像均衡化(即直方圖均衡化)前后的直方圖進(jìn)行了對比,如圖13-23 所示。其中,左圖是原始圖像的直方圖,可以看到灰度級集中在中間,圖像中沒有較暗和較亮的像素點;右圖是對原圖均衡化后的直方圖,像素分布更均衡。
直方圖均衡化的主要目的是將原始圖像的灰度級均勻地映射到整個灰度級范圍內(nèi),得到一個灰度級分布均勻的圖像。這種均衡化,既實現(xiàn)了灰度值統(tǒng)計上的概率均衡,也實現(xiàn)了人類視覺系統(tǒng)(Human Visual System,HVS)上的視覺均衡。
直方圖均衡化函數(shù)
OpenCV 使用函數(shù) cv2.equalizeHist()實現(xiàn)直方圖均衡化
。該函數(shù)的語法格式為:
dst = cv2.equalizeHist( src )
式中:
- dst 是直方圖均衡化處理的結(jié)果。
- src 是 8 位單通道原始圖像。
示例:使用函數(shù) cv2.equalizeHist()實現(xiàn)直方圖均衡化。
原圖:
代碼如下:
#-----------導(dǎo)入使用的模塊---------------
import cv2
import matplotlib.pyplot as plt
#-----------讀取原始圖像---------------
img = cv2.imread('equ.bmp',cv2.IMREAD_GRAYSCALE)
#-----------直方圖均衡化處理---------------
equ = cv2.equalizeHist(img)
#-----------顯示均衡化前后的圖像---------------
cv2.imshow("original",img)
cv2.imshow("result",equ)
#-----------顯示均衡化前后的直方圖---------------
plt.figure("原始圖像直方圖") #構(gòu)建窗口
plt.hist(img.ravel(),256)
plt.figure("均衡化結(jié)果直方圖") #構(gòu)建新窗口
plt.hist(equ.ravel(),256)
plt.show()
#----------等待釋放窗口---------------------
cv2.waitKey()
cv2.destroyAllWindows()
結(jié)果中可以看到對比很明顯:在直方圖均衡化之前,圖像整體比較
亮;均衡化以后,圖像的亮度變得比較均衡。而兩幅圖像的直方圖的對比,則不太明顯。這實際上體現(xiàn)了,均衡化是指綜合考慮了統(tǒng)計概率和 HVS 的結(jié)果。
下面做簡單的說明:
-
原始圖像的直方圖,大部分的像素值集中在右側(cè)(線條密集)。這說明圖像中位于[200,255]區(qū)間的像素點很多,圖像比較亮。文章來源:http://www.zghlxwxcb.cn/news/detail-641801.html
-
在均衡化后的直方圖中,左側(cè)的像素點比較密集而右側(cè)的相對比較稀疏。但是,實際上人眼并不能明顯感受到像素值的細(xì)微差別,所以我們可以將相近的像素值看成同一個像素值,這樣就會得到類似于圖 13-29 的直方圖。此時,直方圖內(nèi)灰度級的分布就比較均衡了,是均衡一致的直方圖。文章來源地址http://www.zghlxwxcb.cn/news/detail-641801.html
到了這里,關(guān)于opencv進(jìn)階01-直方圖的應(yīng)用及示例cv2.calcHist()的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!