OpenCV Python教程(3)(4)(5): 直方图的计算与显示 形态学处理 初级滤波内
OpenCV Python教程(3、直方圖的計(jì)算與顯示)
本篇文章介紹如何用OpenCV?Python來(lái)計(jì)算直方圖,并簡(jiǎn)略介紹用NumPy和Matplotlib計(jì)算和繪制直方圖
直方圖的背景知識(shí)、用途什么的就直接略過(guò)去了。這里直接介紹方法。
計(jì)算并顯示直方圖
與C++中一樣,在Python中調(diào)用的OpenCV直方圖計(jì)算函數(shù)為cv2.calcHist。
cv2.calcHist的原型為:
[python]?view plaincopy
第二個(gè)參數(shù)是用于計(jì)算直方圖的通道,這里使用灰度圖計(jì)算直方圖,所以就直接使用第一個(gè)通道;
第三個(gè)參數(shù)是Mask,這里沒(méi)有使用,所以用None。
第四個(gè)參數(shù)是histSize,表示這個(gè)直方圖分成多少份(即多少個(gè)直方柱)。第二個(gè)例子將繪出直方圖,到時(shí)候會(huì)清楚一點(diǎn)。
第五個(gè)參數(shù)是表示直方圖中各個(gè)像素的值,[0.0, 256.0]表示直方圖能表示像素值從0.0到256的像素。
最后是兩個(gè)可選參數(shù),由于直方圖作為函數(shù)結(jié)果返回了,所以第六個(gè)hist就沒(méi)有意義了(待確定)
最后一個(gè)accumulate是一個(gè)布爾值,用來(lái)表示直方圖是否疊加。
彩色圖像不同通道的直方圖
彩色圖像不同通道的直方圖
下面來(lái)看下彩色圖像的直方圖處理。以最著名的lena.jpg為例,首先讀取并分離各通道:
[python]?view plaincopy
接著在主函數(shù)中使用:
[python]?view plaincopy
更進(jìn)一步
這樣做有點(diǎn)繁瑣,參考abid rahman的做法,無(wú)需分離通道,用折線來(lái)描繪直方圖的邊界可在一副圖中同時(shí)繪制三個(gè)通道的直方圖。方法如下:
[python]?view plaincopy
代碼說(shuō)明:
這里的for循環(huán)是對(duì)三個(gè)通道遍歷一次,每次繪制相應(yīng)通道的直方圖的折線。for循環(huán)的第一行是計(jì)算對(duì)應(yīng)通道的直方圖,經(jīng)過(guò)上面的介紹,應(yīng)該很容易就能明白。
這里所不同的是沒(méi)有手動(dòng)的計(jì)算直方圖的最大值再乘以一個(gè)系數(shù),而是直接調(diào)用了OpenCV的歸一化函數(shù)。該函數(shù)將直方圖的范圍限定在0-255×0.9之間,與之前的一樣。下面的hist= np.int32(np.around(originHist))先將生成的原始直方圖中的每個(gè)元素四舍六入五湊偶取整(cv2.calcHist函數(shù)得到的是float32類型的數(shù)組),接著將整數(shù)部分轉(zhuǎn)成np.int32類型。即61.123先轉(zhuǎn)成61.0,再轉(zhuǎn)成61。注意,這里必須使用np.int32(...)進(jìn)行轉(zhuǎn)換,numpy的轉(zhuǎn)換函數(shù)可以對(duì)數(shù)組中的每個(gè)元素都進(jìn)行轉(zhuǎn)換,而Python的int(...)只能轉(zhuǎn)換一個(gè)元素,如果使用int(...),將導(dǎo)致only length-1 arrays can be converted to Python scalars錯(cuò)誤。
下面的pts = np.column_stack((bins,hist))是將直方圖中每個(gè)bin的值轉(zhuǎn)成相應(yīng)的坐標(biāo)。比如hist[0] =3,...,hist[126] = 178,...,hist[255] = 5;而bins的值為[[0],[1],[2]...,[255]]。使用np.column_stack將其組合成[0, 3]、[126, 178]、[255, 5]這樣的坐標(biāo)作為元素組成的數(shù)組。
最后使用cv2.polylines函數(shù)根據(jù)這些點(diǎn)繪制出折線,第三個(gè)False參數(shù)指出這個(gè)折線不需要閉合。第四個(gè)參數(shù)指定了折線的顏色。
當(dāng)所有完成后,別忘了用h = np.flipud(h)反轉(zhuǎn)繪制好的直方圖,因?yàn)槔L制時(shí),[0,0]在圖像的左上角。這在直方圖可視化一節(jié)中有說(shuō)明。
NumPy版的直方圖計(jì)算
在查閱abid rahman的資料時(shí),發(fā)現(xiàn)他用NumPy的直方圖計(jì)算函數(shù)np.histogram也實(shí)現(xiàn)了相同的效果。如下:
[python]?view plaincopy
另外,通過(guò)NumPy和matplotlib可以更方便的繪制出直方圖,下面的代碼供大家參考,如果有機(jī)會(huì),再寫的專門介紹matplotlib的文章。
[python]?view plaincopy這里顯示的是綠色通道的直方圖。
OpenCV-Python教程(4、形態(tài)學(xué)處理)
提示:
- 轉(zhuǎn)載請(qǐng)?jiān)敿?xì)注明原作者及出處,謝謝!
- 本文介紹使用OpenCV-Python進(jìn)行形態(tài)學(xué)處理
- 本文不介紹形態(tài)學(xué)處理的基本概念,所以讀者需要預(yù)先對(duì)其有一定的了解。
定義結(jié)構(gòu)元素
形態(tài)學(xué)處理的核心就是定義結(jié)構(gòu)元素,在OpenCV-Python中,可以使用其自帶的getStructuringElement函數(shù),也可以直接使用NumPy的ndarray來(lái)定義一個(gè)結(jié)構(gòu)元素。首先來(lái)看用getStructuringElement函數(shù)定義一個(gè)結(jié)構(gòu)元素:
[python]?view plaincopy
也可以用NumPy來(lái)定義結(jié)構(gòu)元素,如下:
[python]?view plaincopy這里可以看出,用OpenCV-Python內(nèi)置的常量定義橢圓(MORPH_ELLIPSE)和十字形結(jié)構(gòu)(MORPH_CROSS)元素要簡(jiǎn)單一些,如果定義矩形(MORPH_RECT)和自定義結(jié)構(gòu)元素,則兩者差不多。
本篇文章將用參考資料1中的相關(guān)章節(jié)的圖片做測(cè)試:
腐蝕和膨脹
下面先以腐蝕圖像為例子介紹如何使用結(jié)構(gòu)元素:
[python]?view plaincopy如上所示,腐蝕和膨脹的處理很簡(jiǎn)單,只需設(shè)置好結(jié)構(gòu)元素,然后分別調(diào)用cv2.erode(...)和cv2.dilate(...)函數(shù)即可,其中第一個(gè)參數(shù)是需要處理的圖像,第二個(gè)是結(jié)構(gòu)元素。返回處理好的圖像。
結(jié)果如下:
開(kāi)運(yùn)算和閉運(yùn)算
了解形態(tài)學(xué)基本處理的同學(xué)都知道,開(kāi)運(yùn)算和閉運(yùn)算就是將腐蝕和膨脹按照一定的次序進(jìn)行處理。但這兩者并不是可逆的,即先開(kāi)后閉并不能得到原先的圖像。代碼示例如下:
[python]?view plaincopy閉運(yùn)算用來(lái)連接被誤分為許多小塊的對(duì)象,而開(kāi)運(yùn)算用于移除由圖像噪音形成的斑點(diǎn)。因此,某些情況下可以連續(xù)運(yùn)用這兩種運(yùn)算。如對(duì)一副二值圖連續(xù)使用閉運(yùn)算和開(kāi)運(yùn)算,將獲得圖像中的主要對(duì)象。同樣,如果想消除圖像中的噪聲(即圖像中的“小點(diǎn)”),也可以對(duì)圖像先用開(kāi)運(yùn)算后用閉運(yùn)算,不過(guò)這樣也會(huì)消除一些破碎的對(duì)象。
對(duì)原始圖像進(jìn)行開(kāi)運(yùn)算和閉運(yùn)算的結(jié)果如下:
用形態(tài)學(xué)運(yùn)算檢測(cè)邊和角點(diǎn)
這里通過(guò)一個(gè)較復(fù)雜的例子介紹如何用形態(tài)學(xué)算子檢測(cè)圖像中的邊緣和拐角(這里只是作為介紹形態(tài)學(xué)處理例子,實(shí)際使用時(shí)請(qǐng)用Canny或Harris等算法)。
檢測(cè)邊緣
形態(tài)學(xué)檢測(cè)邊緣的原理很簡(jiǎn)單,在膨脹時(shí),圖像中的物體會(huì)想周圍“擴(kuò)張”;腐蝕時(shí),圖像中的物體會(huì)“收縮”。比較這兩幅圖像,由于其變化的區(qū)域只發(fā)生在邊緣。所以這時(shí)將兩幅圖像相減,得到的就是圖像中物體的邊緣。這里用的依然是參考資料1中相關(guān)章節(jié)的圖片:
代碼如下:
[python]?view plaincopy
檢測(cè)拐角
與邊緣檢測(cè)不同,拐角的檢測(cè)的過(guò)程稍稍有些復(fù)雜。但原理相同,所不同的是先用十字形的結(jié)構(gòu)元素膨脹像素,這種情況下只會(huì)在邊緣處“擴(kuò)張”,角點(diǎn)不發(fā)生變化。接著用菱形的結(jié)構(gòu)元素腐蝕原圖像,導(dǎo)致只有在拐角處才會(huì)“收縮”,而直線邊緣都未發(fā)生變化。
第二步是用X形膨脹原圖像,角點(diǎn)膨脹的比邊要多。這樣第二次用方塊腐蝕時(shí),角點(diǎn)恢復(fù)原狀,而邊要腐蝕的更多。所以當(dāng)兩幅圖像相減時(shí),只保留了拐角處。示意圖如下(示意圖來(lái)自參考資料1):
代碼如下:
[python]?view plaincopy
大家可以驗(yàn)證一下,比如在代碼中插入這兩行代碼,就能知道結(jié)果了:
[python]?view plaincopy
當(dāng)然,這只是個(gè)形態(tài)學(xué)處理示例,檢測(cè)結(jié)果并不好。
未完待續(xù)...
在將來(lái)的某一篇文章中將做個(gè)總結(jié),介紹下OpenCV中常用的函數(shù),如threshold、bitwise_xxx,以及繪制函數(shù)等。
參考資料:
1、《Opencv2 Computer Vision Application Programming Cookbook》
2、《OpenCV References Manule》
如果覺(jué)得本文寫的還可以的話,請(qǐng)輕點(diǎn)“頂”,方便讀者、以及您的支持是我寫下去的最大的兩個(gè)動(dòng)力。
OpenCV-Python教程(5、初級(jí)濾波內(nèi)容)
本篇文章介紹如何用OpenCV-Python來(lái)實(shí)現(xiàn)初級(jí)濾波功能。
提示:
- 轉(zhuǎn)載請(qǐng)?jiān)敿?xì)注明原作者及出處,謝謝!
- 本文介紹使用OpenCV-Python實(shí)現(xiàn)基本的濾波處理
- 本文不介紹濾波處理的詳細(xì)概念,所以讀者需要預(yù)先對(duì)其有一定的了解。
簡(jiǎn)介
過(guò)濾是信號(hào)和圖像處理中基本的任務(wù)。其目的是根據(jù)應(yīng)用環(huán)境的不同,選擇性的提取圖像中某些認(rèn)為是重要的信息。過(guò)濾可以移除圖像中的噪音、提取感興趣的可視特征、允許圖像重采樣,等等。其源自于一般的信號(hào)和系統(tǒng)理論,這里將不介紹該理論的細(xì)節(jié)。但本章會(huì)介紹關(guān)于過(guò)濾的基本概念,以及如何在圖像處理程序中使用濾波器。首先,簡(jiǎn)要介紹下頻率域分析的概念。
當(dāng)我們觀察一張圖片時(shí),我們觀察的是圖像中有多少灰度級(jí)(或顏色)及其分布。根據(jù)灰度分布的不同來(lái)區(qū)分不同的圖像。但還有其他方面可以對(duì)圖像進(jìn)行分析。我們可以觀察圖像中灰度的變化。某些圖像中包含大量的強(qiáng)度不變的區(qū)域(如藍(lán)天),而在其他圖像中的灰度變化可能會(huì)非常快(如包含許多小物體的擁擠的圖像)。因此,觀察圖像中這些變化的頻率就構(gòu)成了另一條分類圖像的方法。這個(gè)觀點(diǎn)稱為頻域。而通過(guò)觀察圖像灰度分布來(lái)分類圖像稱為空間域。
頻域分析將圖像分成從低頻到高頻的不同部分。低頻對(duì)應(yīng)圖像強(qiáng)度變化小的區(qū)域,而高頻是圖像強(qiáng)度變化非常大的區(qū)域。目前已存在若干轉(zhuǎn)換方法,如傅立葉變換或余弦變換,可以用來(lái)清晰的顯示圖像的頻率內(nèi)容。注意,由于圖像是一個(gè)二維實(shí)體,所以其由水平頻率(水平方向的變化)和豎直頻率(豎直方向的變化)共同組成。
在頻率分析領(lǐng)域的框架中,濾波器是一個(gè)用來(lái)增強(qiáng)圖像中某個(gè)波段或頻率并阻塞(或降低)其他頻率波段的操作。低通濾波器是消除圖像中高頻部分,但保留低頻部分。高通濾波器消除低頻部分
本篇文章介紹在OpenCV-Python中實(shí)現(xiàn)的初級(jí)的濾波操作,下一篇文章介紹更加復(fù)雜的濾波原理及其實(shí)現(xiàn)。
本篇文章使用傳統(tǒng)的lena作為實(shí)驗(yàn)圖像。
用低通濾波來(lái)平滑圖像
低通濾波器的目標(biāo)是降低圖像的變化率。如將每個(gè)像素替換為該像素周圍像素的均值。這樣就可以平滑并替代那些強(qiáng)度變化明顯的區(qū)域。在OpenCV中,可以通過(guò)blur函數(shù)做到這一點(diǎn):
[python]?view plaincopy其中dst是blur處理后返回的圖像,參數(shù)一是輸入的待處理圖像,參數(shù)2是低通濾波器的大小。其后含有幾個(gè)可選參數(shù),用來(lái)設(shè)置濾波器的細(xì)節(jié),具體可查閱參考資料2。不過(guò)這里,這樣就夠了。下面是一個(gè)簡(jiǎn)單的示例代碼:
[python]?view plaincopy
這種濾波器又稱為boxfilter(注,這與化學(xué)上的箱式過(guò)濾器是兩碼事,所以這里就不翻譯了)。所以也可通過(guò)OpenCV的cv2.bofxfilter(...)函數(shù)來(lái)完成相同的工作。如下:
[python]?view plaincopy
高斯模糊
在某些情況下,需要對(duì)一個(gè)像素的周圍的像素給予更多的重視。因此,可通過(guò)分配權(quán)重來(lái)重新計(jì)算這些周圍點(diǎn)的值。這可通過(guò)高斯函數(shù)(鐘形函數(shù),即喇叭形數(shù))的權(quán)重方案來(lái)解決。cv::GaussianBlur函數(shù)可作為濾波器用下面的方法調(diào)用:
[python]?view plaincopy
區(qū)別
低通濾波與高斯濾波的不同之處在于:低通濾波中,濾波器中每個(gè)像素的權(quán)重是相同的,即濾波器是線性的。而高斯濾波器中像素的權(quán)重與其距中心像素的距離成比例。關(guān)于高斯模糊的詳細(xì)內(nèi)容,抽空將寫一篇獨(dú)立的文章介紹。
使用中值濾波消除噪點(diǎn)
前面介紹的是線性過(guò)濾器,這里介紹非線性過(guò)濾器——中值濾波器。由于中值濾波器對(duì)消除椒鹽現(xiàn)象特別有用。所以我們使用第二篇教程中椒鹽函數(shù)先對(duì)圖像進(jìn)行處理,將處理結(jié)果作為示例圖片。
調(diào)用中值濾波器的方法與調(diào)用其他濾波器的方法類似,如下:
[python]?view plaincopy
如果在某個(gè)像素周圍有白色或黑色的像素,這些白色或黑色的像素不會(huì)選擇作為中值(最大或最小值不用),而是被替換為鄰域值。代碼如下:
[python]?view plaincopy
由于中值濾波不會(huì)處理最大和最小值,所以就不會(huì)受到噪聲的影響。相反,如果直接采用blur進(jìn)行均值濾波,則不會(huì)區(qū)分這些噪聲點(diǎn),濾波后的圖像會(huì)受到噪聲的影響。
中值濾波器在處理邊緣也有優(yōu)勢(shì)。但中值濾波器會(huì)清除掉某些區(qū)域的紋理(如背景中的樹(shù))。
其他
由于方向?yàn)V波器與這里的原理有較大的出入,所以將用獨(dú)立的一篇文章中介紹其原理以及實(shí)現(xiàn)。
參考資料:
1、《Opencv2 Computer Vision Application Programming Cookbook》
2、《OpenCV References Manule》
from: http://blog.csdn.net/sunny2038/article/category/904451
總結(jié)
以上是生活随笔為你收集整理的OpenCV Python教程(3)(4)(5): 直方图的计算与显示 形态学处理 初级滤波内的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: OpenCV之Python学习笔记(1)
- 下一篇: OpenCV-Python教程(6)(7