python中opencv?直方圖處理
直方圖處理
直方圖從圖像內(nèi)部灰度級的角度對圖像進(jìn)行表述從直方圖的角度對圖像進(jìn)行處理,可以達(dá)到增強(qiáng)圖像顯示效果的目的。
直方圖的含義
直方圖是圖像內(nèi)灰度值的統(tǒng)計特性與圖像灰度值之間的函數(shù),直方圖統(tǒng)計圖像內(nèi)各個灰度級出現(xiàn)的次數(shù)。從直方圖的圖形上觀察,橫坐標(biāo)是圖像中各像素點(diǎn)的灰度級,縱坐標(biāo)是具有該灰度級(像素值)的像素個數(shù)。在繪制直方圖時,將灰度級作為x軸處理,該灰度級出現(xiàn)的次數(shù)作為y軸處理
把左側(cè)的直線圖和右側(cè)直方圖都稱為直方圖
在實(shí)際處理中,圖像直方圖的x軸區(qū)間一般是[0, 255],對應(yīng)的是8位位圖的256個灰度級;y軸對應(yīng)的是具有相應(yīng)灰度級的像素點(diǎn)的個數(shù)。
歸一化直方圖: 在歸一化直方圖中,x軸仍然表示灰度級;y軸不再表示灰度級出現(xiàn)的次數(shù),而是灰度級出現(xiàn)的頻率。
灰度級出現(xiàn)的頻率=灰度級出現(xiàn)的次數(shù)/總像素數(shù)在歸一化直方圖中,各個灰度級出現(xiàn)的頻率之和為1。歸一化直方圖與直方圖在外觀上是一致的,只是y軸的標(biāo)簽不同而已。
在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)行分析。
例如: 希望將兩個像素值作為一組討論
繪制直方圖
Python的模塊matplotlib.pyplot中的hist()函數(shù)能夠方便地繪制直方圖,通常采用該函數(shù)直接繪制直方圖。除此以外,OpenCV中的cv2.calcHist()函數(shù)能夠計算統(tǒng)計直方圖,還可以在此基礎(chǔ)上繪制圖像的直方圖。
使用Numpy繪制直方圖
模塊matplotlib.pyplot提供了一個類似于MATLAB繪圖方式的框架,可以使用其中的matplotlib.pyplot.hist()函數(shù)來繪制直方圖。此函數(shù)的作用是根據(jù)數(shù)據(jù)源和灰度級分組繪制直方圖。
其基本語法格式為:
matplotlib.pyplot.hist(X, BINS)
- X:數(shù)據(jù)源,必須是一維的。圖像通常是二維的,需要使用ravel()函數(shù)將圖像處理為一維數(shù)據(jù)源以后,再作為參數(shù)使用。
- BINS:BINS的具體值,表示灰度級的分組情況。
函數(shù)ravel()的作用是將二維數(shù)組降維成一維數(shù)組。
例如:數(shù)組a
使用函數(shù)ravel()對a進(jìn)行處理:
b = a.ravel()
使用hist()函數(shù)繪制一幅圖像的直方圖
import cv2 import matplotlib.pyplot as plt o=cv2.imread("./img/hand1.png") cv2.imshow("original", o) plt.hist(o.ravel(),256) plt.show() cv2.waitKey() cv2.destroyAllWindows()
使用函數(shù)hist()將一幅圖像的灰度級劃分為16組后,繪制該圖像的直方圖。
將灰度級劃分為16組,即將灰度級劃分為16個子集,對應(yīng)的BINS值為16。
import cv2 import matplotlib.pyplot as plt o=cv2.imread("./img/hand1.png") plt.hist(o.ravel(),16) plt.show()
使用OpenCV繪制直方圖
OpenCV提供了函數(shù)cv2.calcHist()用來計算圖像的統(tǒng)計直方圖,該函數(shù)能統(tǒng)計各個灰度級的像素點(diǎn)個數(shù)。利用matplotlib.pyplot模塊中的plot()函數(shù),可以將函數(shù)cv2.calcHist()的統(tǒng)計結(jié)果繪制成直方圖。
- 用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)計圖像某一部分的直方圖時,需要用到掩模圖像。
僅計算掩膜區(qū)域
- histSize:BINS的值,該值需要用“[ ]”括起來。例如,BINS的值是256,需要使用“[256]”作為此參數(shù)值。
- ranges:即像素值范圍。例如,8位灰度圖像的像素值范圍是[0, 255]。
- accumulate:累計(累積、疊加)標(biāo)識,默認(rèn)值為False。如果被設(shè)置為True,則直方圖在開始計算時不會被清零,計算的是多個直方圖的累積結(jié)果,用于對一組圖像計算直方圖。該參數(shù)允許從多個對象中計算單個直方圖,或者實(shí)時更新直方圖。該參數(shù)是可選的,一般情況下不需要設(shè)置。
**例子:**使用cv2.calcHist()函數(shù)計算一幅圖像的統(tǒng)計直方圖結(jié)果,并觀察得到的統(tǒng)計直方圖信息。
import cv2 import numpy as np img=cv2.imread("./img/hand1.png") hist = cv2.calcHist([img], [0], None, [256], [0,255]) print(type(hist)) print(hist.shape) print(hist.size) print(hist) ###### <class 'numpy.ndarray'> (256, 1) 256 [[ 88.] [ 31.] [ 48.] [ 66.] ...
函數(shù)cv2.calcHist()返回值的數(shù)據(jù)類型為“ndarray”。該數(shù)據(jù)的shape為(256,1),說明其有256行1列。
該數(shù)據(jù)的size為256,說明有256個元素,分別對應(yīng)著256個灰度級在圖像內(nèi)出現(xiàn)的次數(shù)。
plot()函數(shù)的使用:
使用matplotlib.pyplot模塊內(nèi)的plot()函數(shù),可以將函數(shù)cv2.calcHist()的返回值繪制為圖像直方圖。
繪制統(tǒng)計直方圖:
使用函數(shù)plot()將函數(shù)cv2.calcHist()的返回值繪制為直方圖。
import cv2 import matplotlib.pyplot as plt o=cv2.imread("./img/hand1.png") histb = cv2.calcHist([o], [0], None, [256], [0,255]) plt.plot(histb, color='b') plt.show()
使用函數(shù)plot()和函數(shù)cv2.calcHist(),將彩色圖像各個通道的直方圖繪制在一個窗口內(nèi)。
import cv2 import matplotlib.pyplot as plt o=cv2.imread("./img/hand1.png") histb = cv2.calcHist([o], [0], None, [256], [0,255]) histg = cv2.calcHist([o], [1], None, [256], [0,255]) histr = cv2.calcHist([o], [2], None, [256], [0,255]) plt.plot(histb, color='b') plt.plot(histg, color='g') plt.plot(histr, color='r') plt.show()
使用掩模繪制直方圖
在函數(shù)cv2.calcHist()中,參數(shù)mask用于標(biāo)識是否使用掩模圖像。
當(dāng)使用掩模圖像獲取直方圖時,僅獲取掩模參數(shù)mask指定區(qū)域的直方圖。
- 掩模處理的概念
通常將掩模圖像白色區(qū)域的值設(shè)置為255,然后讓掩模圖像與原始圖像進(jìn)行按位與運(yùn)算
OpenCV提供了bitwise_and函數(shù),用于兩個像素值之間的按位與運(yùn)算。
掩模圖像的白色背景部分設(shè)置為255,黑色背景部分設(shè)置為0
當(dāng)在一個函數(shù)F中使用了掩模時,就意味著要先將參與運(yùn)算的圖像與掩模圖像進(jìn)行按位與運(yùn)算,得到掩模運(yùn)算結(jié)果。然后,再將掩模運(yùn)算結(jié)果,作為函數(shù)F的參數(shù)完成函數(shù)F所指定的運(yùn)算。 - 構(gòu)造掩模圖像
在構(gòu)造掩模圖像時,通常先構(gòu)造一個像素值都是0的二維數(shù)組,再將數(shù)組中指定區(qū)域的像素值設(shè)定為255,就得到了掩模圖像。
首先使用函數(shù)np.zeros()構(gòu)造一個像素值都是0的二維數(shù)組,然后將其中間部分的值設(shè)置為255
import cv2 import numpy as np mask=np.zeros([600,600], np.uint8) mask[200:400,200:400]=255 cv2.imshow('mask',?mask) cv2.waitKey() cv2.destroyAllWindows()
使用掩模繪制直方圖:
繪制掩模圖像時,首先將函數(shù)cv2.calcHist()的mask參數(shù)設(shè)置為掩模圖像,得到掩模處理的直方圖信息,再使用plot()函數(shù)完成直方圖的繪制。
函數(shù)cv2.calcHist()的語法格式:
hist = cv2.calcHist( images, channels, mask, histSize, ranges, accumulate )
其中,mask參數(shù)就是掩模圖像。
繪制掩模結(jié)果圖像的直方圖
首先構(gòu)造一個掩模圖像,然后使用函數(shù)cv2.calcHist()計算掩模結(jié)果圖像的統(tǒng)計直方圖信息,最后使用函數(shù)plot()繪制掩模圖像的直方圖。
掩模圖像要保持與原始圖像相等的大小, 使用參數(shù)image.shape表示構(gòu)造與原始圖像等大小的掩模圖像。
import cv2 import numpy as np import matplotlib.pyplot as plt image=cv2.imread("./img/hand1.png", cv2.IMREAD_GRAYSCALE) mask=np.zeros(image.shape, np.uint8) mask[200:400,200:400]=255 histImage=cv2.calcHist([image], [0], None, [256], [0,255]) histMI=cv2.calcHist([image], [0], mask, [256], [0,255]) plt.plot(histImage,color="b") plt.plot(histMI,color="g") plt.show()
直方圖均衡化
如果一幅圖像擁有全部可能的灰度級,并且像素值的灰度均勻分布,那么這幅圖像就具有高對比度和多變的灰度色調(diào),灰度級豐富且覆蓋范圍較大。
在外觀上,這樣的圖像具有更豐富的色彩,不會過暗或過亮。直方圖均衡化的主要目的是將原始圖像的灰度級均勻地映射到整個灰度級范圍內(nèi),得到一個灰度級分布均勻的圖像。這種均衡化,既實(shí)現(xiàn)了灰度值統(tǒng)計上的概率均衡,也實(shí)現(xiàn)了人類視覺系統(tǒng)(Human Visual System, HVS)上的視覺均衡。
直方圖均衡化原理
直方圖均衡化的算法主要包括兩個步驟:
- 計算累計直方圖。
- 對累計直方圖進(jìn)行區(qū)間轉(zhuǎn)換
在此基礎(chǔ)上,再利用人眼視覺達(dá)到直方圖均衡化的目的。
在累計直方圖的基礎(chǔ)上,對原有灰度級空間進(jìn)行轉(zhuǎn)換??梢栽谠蟹秶鷥?nèi)對灰度級實(shí)現(xiàn)均衡化,也可以在更廣泛的灰度空間范圍內(nèi)對灰度級實(shí)現(xiàn)均衡化。
在原有范圍內(nèi)實(shí)現(xiàn)均衡化
用當(dāng)前灰度級的累計概率乘以當(dāng)前灰度級的最大值,得到新的灰度級,并作為均衡化的結(jié)果。
在更廣泛的范圍內(nèi)實(shí)現(xiàn)均衡化
用當(dāng)前灰度級的累計概率乘以更廣泛范圍灰度級的最大值,得到新的灰度級,并作為均衡化的結(jié)果。
通過如下兩個步驟,可以讓直方圖達(dá)到均衡化的效果。
- 計算累計直方圖。
- 將累計直方圖進(jìn)行區(qū)間轉(zhuǎn)換。
直方圖均衡化使圖像色彩更均衡、外觀更清晰,也使圖像更便于處理,它被廣泛地應(yīng)用在醫(yī)學(xué)圖像處理、車牌識別、人臉識別等領(lǐng)域。
直方圖均衡化處理
OpenCV使用函數(shù)cv2.equalizeHist()實(shí)現(xiàn)直方圖均衡化。
該函數(shù)的語法格式為:
dst = cv2.equalizeHist( src )
- src是8位單通道原始圖像
- dst是直方圖均衡化處理的結(jié)果
例子: 使用函數(shù)cv2.equalizeHist()實(shí)現(xiàn)直方圖均衡化
#-----------導(dǎo)入使用的模塊---------------? import cv2 import matplotlib.pyplot as plt #-----------讀取原始圖像---------------? img = cv2.imread('./img/hand1.png',?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()
語句“plt.figure("原始圖像直方圖")”用于構(gòu)造名為“原始圖像直方圖”的新窗口。
均衡化是指綜合考慮了統(tǒng)計概率和HVS的均衡化結(jié)果。
pyplot 模塊介紹
matplotlib.pyplot模塊提供了一個類似于MATLAB繪圖方式的框架,可以使用其中的函數(shù)方便地繪制圖形。
subplot 函數(shù)
模塊matplotlib.pyplot提供了函數(shù)matplotlib.pyplot.subplot()用來向當(dāng)前窗口內(nèi)添加一個子窗口對象。該函數(shù)的語法格式為:
matplotlib.pyplot.subplot(nrows, ncols, index)
- nrows為行數(shù)。
- ncols為列數(shù)。
- index為窗口序號。
序號是從“1”開始而不是從“0”開始的。
如果所有參數(shù)都小于10,可以省略彼此之間的逗號,直接寫三個數(shù)字。例如,subplot(2, 3, 4)可以直接表示為subplot(234)。
import cv2 import matplotlib.pyplot as plt img = cv2.imread('./img/hand1.png',?cv2.IMREAD_GRAYSCALE) equ = cv2.equalizeHist(img) plt.figure("subplot示例") plt.subplot(121), plt.hist(img.ravel(),256) plt.subplot(122), plt.hist(equ.ravel(),256) plt.show()
imshow函數(shù)
模塊matplotlib.pyplot提供了函數(shù)matplotlib.pyplot.imshow()用來顯示圖像。
其語法格式為:
matplotlib.pyplot.imshow(X, cmap=None)
- X為圖像信息,可以是各種形式的數(shù)值。
- cmap表示色彩空間。該值是可選項(xiàng),默認(rèn)值為null,默認(rèn)使用RGB(A)色彩空間。
使用函數(shù)matplotlib.pyplot.imshow()顯示彩色圖像
import cv2 import matplotlib.pyplot as plt img = cv2.imread('./img/hand1.png') imgRGB=cv2.cvtColor(img, cv2.COLOR_BGR2RGB) plt.figure("顯示結(jié)果") plt.subplot(121) plt.imshow(img), plt.axis('off') plt.subplot(122) plt.imshow(imgRGB), plt.axis('off') plt.show()
- 語句“plt.axis('off')”表示關(guān)閉坐標(biāo)軸的顯示
使用函數(shù)matplotlib.pyplot.imshow()顯示灰度圖像。
嘗試使用不同的形式顯示灰度圖像
import cv2 import matplotlib.pyplot as plt o = cv2.imread('./img/hand1.png') g=cv2.cvtColor(o, cv2.COLOR_BGR2GRAY) plt.figure("灰度圖像顯示演示") plt.subplot(221) plt.imshow(o), plt.axis('off') plt.subplot(222) plt.imshow(o, cmap=plt.cm.gray), plt.axis('off') plt.subplot(223) plt.imshow(g), plt.axis('off') plt.subplot(224) plt.imshow(g, cmap=plt.cm.gray), plt.axis('off') plt.show()
只有使用灰度圖像作為參數(shù),并且將色彩空間參數(shù)值設(shè)置為“cmap=plt.cm.gray”,灰度圖像才被正常顯示。
使用函數(shù)matplotlib.pyplot.imshow()以不同的參數(shù)形式顯示灰度圖像。
import cv2 import matplotlib.pyplot as plt o = cv2.imread('./img/hand1.png') g=cv2.cvtColor(o, cv2.COLOR_BGR2GRAY) plt.figure("灰度圖像顯示演示") plt.subplot(221); plt.imshow(g, cmap=plt.cm.gray) plt.subplot(222); plt.imshow(g, cmap=plt.cm.gray_r) plt.subplot(223); plt.imshow(g, cmap='gray') plt.subplot(224); plt.imshow(g, cmap='gray_r') plt.show()
色彩空間參數(shù)cmap的參數(shù)值“plt.cm.gray_r”及“gray_r”中的“r”是英文“reverse”的縮寫,表示逆轉(zhuǎn)的意思。
到此這篇關(guān)于python中opencv 直方圖處理的文章就介紹到這了,更多相關(guān)python opencv 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python在Matplotlib圖中顯示中文字體的操作方法
這篇文章主要介紹了Python在Matplotlib圖中顯示中文字體的方法,本篇主要針對在Ubuntu系統(tǒng)中,matplotlib顯示不了中文的問題,尤其是在無法安裝系統(tǒng)字體的情況下,解決Python繪圖時中文顯示的問題。需要的朋友可以參考下2019-07-07用python生成(動態(tài)彩色)二維碼的方法(使用myqr庫實(shí)現(xiàn))
今天小編就為大家分享一篇用python生成(動態(tài)彩色)二維碼的方法(使用myqr庫實(shí)現(xiàn)),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-06-06Python使用logging結(jié)合decorator模式實(shí)現(xiàn)優(yōu)化日志輸出的方法
這篇文章主要介紹了Python使用logging結(jié)合decorator模式實(shí)現(xiàn)優(yōu)化日志輸出的方法,實(shí)例分析了Python使用logging模塊操作日志的相關(guān)技巧,需要的朋友可以參考下2016-04-04使用python 將圖片復(fù)制到系統(tǒng)剪貼中
今天小編就為大家分享一篇使用python 將圖片復(fù)制到系統(tǒng)剪貼中,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-12-12Python實(shí)現(xiàn)簡單的用戶交互方法詳解
這篇文章給大家分享了關(guān)于Python實(shí)現(xiàn)簡單的用戶交互的相關(guān)知識點(diǎn)內(nèi)容,有需要的朋友們可以學(xué)習(xí)下。2018-09-09python練習(xí)之曾經(jīng)很火的小人畫愛心表白代碼
小編有個好兄弟最近在追妹子,跟妹子打得火熱!就差臨門一腳了,這一jio我?guī)兔ρa(bǔ)上去了!他問有沒有什么酷炫的表白方式,可以給人心動的趕jio,表白的方式有許多種今天小編來教大家一個之前很火的小人畫愛心表白代碼2021-09-09