opencv4 c++ 提取图片中的白色区域_【从零学习OpenCV 4】形态学应用
本文首發(fā)于“小白學(xué)視覺”微信公眾號(hào),歡迎關(guān)注公眾號(hào)
本文作者為小白,版權(quán)歸人民郵電出版社發(fā)行所有,禁止轉(zhuǎn)載,侵權(quán)必究!
經(jīng)過幾個(gè)月的努力,小白終于完成了市面上第一本OpenCV 4入門書籍《OpenCV 4開發(fā)詳解》。為了更讓小伙伴更早的了解最新版的OpenCV 4,小白與出版社溝通,提前在公眾號(hào)上連載部分內(nèi)容,請(qǐng)持續(xù)關(guān)注小白。
圖像形態(tài)學(xué)腐蝕可以將細(xì)小的噪聲區(qū)域去除,但是會(huì)將圖像主要區(qū)域的面積縮小,造成主要區(qū)域的形狀發(fā)生改變;圖像形態(tài)學(xué)膨脹可以擴(kuò)充每一個(gè)區(qū)域的面積,填充較小的空洞,但是同樣會(huì)增加噪聲的面積。根據(jù)兩者的特性將圖像腐蝕和膨脹適當(dāng)?shù)慕Y(jié)合,便可以既去除圖像中的噪聲,又不縮小圖像中主要區(qū)域的面積;既填充了較小的空洞,又不增加噪聲所占的面積。因此,本節(jié)中將介紹如何利用不同順序的圖像腐蝕和膨脹實(shí)現(xiàn)圖像的開運(yùn)算、閉運(yùn)算、形態(tài)學(xué)梯度、頂帽運(yùn)算、黑帽運(yùn)算以及擊中擊不中變換等操作。
開運(yùn)算
圖像開運(yùn)算可以去除圖像中的噪聲,消除較小連通域,保留較大連通域,同時(shí)能夠在兩個(gè)物體纖細(xì)的連接處將兩個(gè)物體分離,并且在不明顯改變較大連通域的面積的同時(shí)能夠平滑連通域的邊界。開運(yùn)算是圖像腐蝕和膨脹操作的結(jié)合,首先對(duì)圖像進(jìn)行腐蝕,消除圖像中的噪聲和較小的連通域,之后通過膨脹運(yùn)算彌補(bǔ)較大連通域因腐蝕而造成的面積減小。圖6-22給出了圖像開運(yùn)算的三個(gè)階段,圖6-22中左側(cè)圖像是待開運(yùn)算的原圖像,中間的圖像是利用3×3矩形結(jié)構(gòu)元素對(duì)原圖像進(jìn)行腐蝕后的圖像,通過結(jié)果可以看到較小的連通域已經(jīng)被去除,但是較大的連通域也在邊界區(qū)域產(chǎn)生了較大的面積縮減,之后對(duì)腐蝕后的圖像進(jìn)行膨脹運(yùn)算,得到圖6-22中右側(cè)圖像。通過結(jié)果可以看出,膨脹運(yùn)算彌補(bǔ)了腐蝕運(yùn)算造成的邊界面積縮減,使得開運(yùn)算的結(jié)果只去除了較小的連通域,保留了較大的連通域。
圖6-22 圖像開運(yùn)算三個(gè)階段開運(yùn)算是對(duì)圖像腐蝕和膨脹的組合,OpenCV 4沒有提供只用于圖像開運(yùn)算的函數(shù),而是提供了圖像腐蝕和膨脹運(yùn)算不同組合形式的morphologyEx()函數(shù),以實(shí)現(xiàn)圖像的開運(yùn)算、閉運(yùn)算、形態(tài)學(xué)提取、頂帽運(yùn)算、黑帽運(yùn)算以及擊中擊不中變換,該函數(shù)的函數(shù)原型在代碼清單6-15中給出。
代碼清單6-15 morphologyEx()函數(shù)原型 1. void cv::morphologyEx(InputArray src, 2. OutputArray dst, 3. int op, 4. InputArray kernel, 5. Point anchor = Point(-1,-1), 6. int iterations = 1, 7. int borderType = BORDER_CONSTANT, 8. const Scalar & borderValue = morphologyDefaultBorderValue() 9. )- src:輸入圖像,圖像的通道數(shù)可以是任意的,但是圖像的數(shù)據(jù)類型必須是CV_8U,CV_16U,CV_16S,CV_32F或CV_64F之一。
- dst:形態(tài)學(xué)操作后的輸出圖像,與輸入圖像具有相同的尺寸和數(shù)據(jù)類型。
- op:形態(tài)學(xué)操作類型的標(biāo)志,可以選擇的標(biāo)志及含義在表6-6中給出。
- kernel:結(jié)構(gòu)元素,可以自己生成,也可以用getStructuringElement()函數(shù)生成。
- anchor:中心點(diǎn)在結(jié)構(gòu)元素中的位置,默認(rèn)參數(shù)為結(jié)構(gòu)元素的幾何中心點(diǎn)
- iterations:處理的次數(shù)
- borderType:像素外推法選擇標(biāo)志,取值范圍在表3-5中給出。默認(rèn)參數(shù)為BORDER_DEFAULT,表示不包含邊界值倒序填充。
- borderValue:使用邊界不變外推法時(shí)的邊界值。
該函數(shù)根據(jù)結(jié)構(gòu)元素對(duì)輸入圖像進(jìn)行多種形態(tài)學(xué)操作,在處理多通道圖像時(shí)每個(gè)通道獨(dú)立進(jìn)行處理。函數(shù)的第一個(gè)參數(shù)為待形態(tài)學(xué)處理的圖像,圖像通道數(shù)可以是任意的,但是圖像的數(shù)據(jù)類型必須是CV_8U,CV_16U,CV_16S,CV_32F或CV_64F之一。函數(shù)第二個(gè)參數(shù)為形態(tài)學(xué)處理后的輸出圖像,與輸入圖像具有相同的尺寸和數(shù)據(jù)類型。函數(shù)第三個(gè)參數(shù)是形態(tài)學(xué)操作類型的選擇標(biāo)志,可以選擇的形態(tài)學(xué)操作類型有開運(yùn)算、閉運(yùn)算、形態(tài)學(xué)梯度、頂帽運(yùn)算、黑帽運(yùn)算以及擊中擊不中變換,詳細(xì)的參數(shù)在表6-6給出。函數(shù)第四個(gè)和第五個(gè)參數(shù)都是與結(jié)構(gòu)元素相關(guān)的參數(shù),第四個(gè)參數(shù)為結(jié)構(gòu)元素,使用的結(jié)構(gòu)元素尺寸越大效果越明顯,第四個(gè)參數(shù)為結(jié)構(gòu)元素的中心位置,第五個(gè)參數(shù)的默認(rèn)值為Point(-1,-1),表示結(jié)構(gòu)元素的幾何中心處為結(jié)構(gòu)元素的中心點(diǎn)。函數(shù)第六個(gè)參數(shù)是使用結(jié)構(gòu)元素處理的次數(shù),處理次數(shù)越多效果越明顯。函數(shù)第七個(gè)參數(shù)是圖像像素外推法的選擇標(biāo)志,第八個(gè)參數(shù)為使用邊界不變外推法時(shí)的邊界值,這兩個(gè)參數(shù)對(duì)圖像中主要部分的形態(tài)學(xué)操作沒有影響,因此在多數(shù)情況下使用默認(rèn)值即可。
表6-6 morphologyEX()函數(shù)中形態(tài)學(xué)操作類型標(biāo)志可選參數(shù)及含義
該函數(shù)實(shí)現(xiàn)了多種形態(tài)學(xué)操作,對(duì)于函數(shù)的使用方法將在介紹該函數(shù)涉及到的所有形態(tài)學(xué)操作相關(guān)概念后在代碼清單6-16中給出。
閉運(yùn)算
圖像閉運(yùn)算可以去除連通域內(nèi)的小型空洞,平滑物體輪廓,連接兩個(gè)臨近的連通域。開運(yùn)算是圖像腐蝕和膨脹操作的結(jié)合,首先對(duì)圖像進(jìn)行膨脹,填充連通域內(nèi)的小型空洞,擴(kuò)大連通域的邊界,將臨近的兩個(gè)連通域連接,之后通過腐蝕運(yùn)算減少由膨脹運(yùn)算引起的連通域邊界的擴(kuò)大以及面積的增加。圖6-23給出了圖像閉運(yùn)算的三個(gè)階段,圖6-23中左側(cè)圖像是待閉運(yùn)算的原圖像,中間的圖像是利用3×3矩形結(jié)構(gòu)元素對(duì)原圖像進(jìn)行膨脹后的圖像,通過結(jié)果可以看到較大連通域內(nèi)的小型空洞已經(jīng)被填充,同時(shí)臨近的兩個(gè)連通域也連接了在一起,但是連通域的邊界明顯擴(kuò)張,整體的面積增加,之后對(duì)膨脹后的圖像進(jìn)行腐蝕運(yùn)算,得到圖6-22中右側(cè)圖像。通過結(jié)果可以看出,腐蝕運(yùn)算能夠消除連通域因膨脹運(yùn)算帶來的面積增長(zhǎng),但是圖像中依然存在較大的面積增長(zhǎng),主要是因?yàn)檫B通域膨脹后,有較大區(qū)域在圖像的邊緣區(qū)域,而圖像邊緣區(qū)域的形態(tài)學(xué)操作結(jié)果與圖像的邊緣外推方法有著密切的關(guān)系,因此采用默認(rèn)外推方法時(shí),邊緣的連通域不會(huì)被腐蝕掉,從而產(chǎn)生圖6-23右側(cè)的結(jié)果。
圖6-23 圖像閉運(yùn)算三個(gè)階段閉運(yùn)算是對(duì)圖像膨脹和腐蝕的組合,OpenCV 4提供的morphologyEx()函數(shù)可以選擇閉運(yùn)算參數(shù)MORPH_CLOSE實(shí)現(xiàn)圖像的閉運(yùn)算,該函數(shù)的函數(shù)原型已經(jīng)在代碼清單6-15中給出,函數(shù)的使用方式將在介紹該函數(shù)涉及到的所有形態(tài)學(xué)操作相關(guān)概念后在代碼清單6-16中給出。
形態(tài)學(xué)梯度
形態(tài)學(xué)梯度能夠描述目標(biāo)的邊界,根據(jù)圖像腐蝕和膨脹與原圖之間的關(guān)系計(jì)算得到,形態(tài)學(xué)梯度可以分為基本梯度、內(nèi)部梯度和外部梯度。基本梯度是原圖像膨脹后圖像和腐蝕后圖像間的差值圖像,內(nèi)部梯度圖像是原圖像和腐蝕后圖像間的差值圖像,外部梯度是膨脹后圖像和原圖像間的差值圖像。圖6-24給出了計(jì)算形態(tài)學(xué)基本梯度的三個(gè)階段,圖6-24中左側(cè)圖像是原圖像利用3×3矩形結(jié)構(gòu)元素進(jìn)行膨脹后的圖像,中間的圖像是原圖像利用3×3矩形結(jié)構(gòu)元素進(jìn)行腐蝕后的圖像,右側(cè)圖像是左側(cè)圖像和中間圖像的差值。
圖6-24 形態(tài)學(xué)梯度計(jì)算的三個(gè)階段OpenCV 4提供的morphologyEx()函數(shù)可以選擇閉運(yùn)算參數(shù)MORPH_GRADIENT實(shí)現(xiàn)圖像的基本梯度,如果需要計(jì)算圖像的內(nèi)部梯度或者外部梯度,需要自己通過程序?qū)崿F(xiàn)。morphologyEx()函數(shù)的函數(shù)原型已經(jīng)在代碼清單6-15中給出,函數(shù)的使用方式將在介紹該函數(shù)涉及到的所有形態(tài)學(xué)操作相關(guān)概念后在代碼清單6-16中給出。
頂帽運(yùn)算
圖像頂帽運(yùn)算是原圖像與開運(yùn)算結(jié)果之間的差值,往往用來分離比鄰近點(diǎn)亮一些的斑塊,因?yàn)殚_運(yùn)算帶來的結(jié)果是放大了裂縫或者局部低亮度的區(qū)域,因此,從原圖中減去開運(yùn)算后的圖,得到的效果圖突出了比原圖輪廓周圍的區(qū)域更明亮的區(qū)域。頂帽運(yùn)算先對(duì)圖像進(jìn)行開運(yùn)算,之后從原圖像中減去開運(yùn)算計(jì)算的結(jié)果,在圖6-25中給出了計(jì)算頂帽運(yùn)算的三個(gè)階段,圖6-25中左側(cè)圖像是原圖像,中間的圖像是利用3×3矩形結(jié)構(gòu)元素對(duì)原圖像進(jìn)行開運(yùn)算后的圖像,右側(cè)圖像是左側(cè)原與中間開運(yùn)算結(jié)果圖像之間的差值,即為原圖像頂帽運(yùn)算的結(jié)果。
圖6-25 圖像頂帽運(yùn)算的三個(gè)階段OpenCV 4提供的morphologyEx()函數(shù)可以選擇頂帽運(yùn)算的參數(shù)MORPH_TOPHAT實(shí)現(xiàn)圖像的閉運(yùn)算,該函數(shù)的函數(shù)原型已經(jīng)在代碼清單6-15中給出,函數(shù)的使用方式將在介紹該函數(shù)涉及到的所有形態(tài)學(xué)操作相關(guān)概念后在代碼清單6-16中給出。
黑帽運(yùn)算
圖像黑帽運(yùn)算是與圖像頂帽運(yùn)算相對(duì)應(yīng)的形態(tài)學(xué)操作,與頂帽運(yùn)算相反,黑帽運(yùn)算是原圖像與閉運(yùn)算結(jié)果之間的差值,往往用來分離比鄰近點(diǎn)暗一些的斑塊。頂帽運(yùn)算先對(duì)圖像進(jìn)行開運(yùn)算,之后從原圖像中減去開運(yùn)算計(jì)算的結(jié)果,在圖6-26中給出了計(jì)算頂帽運(yùn)算的三個(gè)階段,圖6-26中左側(cè)圖像是利用3×3矩形結(jié)構(gòu)元素對(duì)原圖像進(jìn)行閉運(yùn)算后的圖像,中間的圖像是原圖像,右側(cè)圖像是左側(cè)閉運(yùn)算結(jié)果圖像與中間原圖像之間的差值,即為原圖像黑帽運(yùn)算的結(jié)果。
圖6-26 圖像黑帽運(yùn)算的三個(gè)階段OpenCV 4提供的morphologyEx()函數(shù)可以選擇黑帽運(yùn)算的參數(shù)MORPH_BLACKHAT實(shí)現(xiàn)圖像的閉運(yùn)算,該函數(shù)的函數(shù)原型已經(jīng)在代碼清單6-15中給出,函數(shù)的使用方式將在介紹該函數(shù)涉及到的所有形態(tài)學(xué)操作相關(guān)概念后在代碼清單6-16中給出。
擊中擊不中變換
擊中擊不中變換是比圖像腐蝕要求更加苛刻的一種形態(tài)學(xué)操作,圖像腐蝕只需要圖像能夠?qū)⒔Y(jié)構(gòu)元素中所有非0元素包含即可,但是擊中擊不中變換要求原圖像中需要存在與結(jié)構(gòu)元素一模一樣的結(jié)構(gòu),即結(jié)構(gòu)元素中非0元素也需要同時(shí)被考慮。如圖6-27中所示,如果用中間的結(jié)構(gòu)元素對(duì)左側(cè)圖像進(jìn)行腐蝕,那么將會(huì)得到圖6-24中所示的腐蝕計(jì)算結(jié)果,而用中間結(jié)構(gòu)元素對(duì)左側(cè)圖像進(jìn)行擊中擊不中變換結(jié)果為圖6-27右側(cè)所示,因?yàn)榻Y(jié)構(gòu)元素的中心位置為0,而在原圖像中符合這種結(jié)構(gòu)的位置只在圖像中的中心處,因此擊中擊不中變換的結(jié)果與圖像腐蝕結(jié)果具有極大的差異。但是在使用矩形結(jié)構(gòu)元素時(shí),擊中擊不中變換與圖像的腐蝕結(jié)果相同。
圖6-27 圖像擊中擊不中變換結(jié)果OpenCV 4提供的morphologyEx()函數(shù)可以選擇擊中擊不中變換參數(shù)MORPH_HITMISS實(shí)現(xiàn)圖像的擊中擊不中變換,該函數(shù)的函數(shù)原型已經(jīng)在代碼清單6-15中給出,函數(shù)的使用方式在介紹該函數(shù)涉及到的所有形態(tài)學(xué)操作相關(guān)概念后在代碼清單6-16中給出。程序中構(gòu)建了用于介紹形態(tài)學(xué)多種操作原理的原圖像,之后用3×3矩形結(jié)構(gòu)元素分別對(duì)原圖像進(jìn)行開運(yùn)算、閉運(yùn)算、形態(tài)學(xué)梯度、頂帽運(yùn)算、黑帽運(yùn)算以及擊中擊不中變換等操作,驗(yàn)證morphologyEx()函數(shù)處理結(jié)果與理論處理結(jié)果是否相同,處理結(jié)果在圖6-28給出。其中需要注意的是由于進(jìn)行擊中擊不中變換使用的結(jié)構(gòu)元素與原理介紹時(shí)不同,因此程序中的擊中擊不中變換結(jié)果與圖6-27不同。此外,為了驗(yàn)證多種形態(tài)學(xué)操作處理圖像的效果,程序中讀取一張灰度圖像,對(duì)圖像進(jìn)行二值化后分別進(jìn)行多種形態(tài)學(xué)操作,灰度圖像和二值化后的圖像如圖6-29所示,形態(tài)學(xué)操作處理后的圖像在圖6-30給出。
代碼清單6-16 myMorphologyApp.cpp形態(tài)學(xué)操作應(yīng)用 1. #include <opencv2opencv.hpp> 2. #include <iostream> 3. #include <vector> 4. 5. using namespace cv; 6. using namespace std; 7. 8. int main() 9. { 10. //用于驗(yàn)證形態(tài)學(xué)應(yīng)用的二值化矩陣 11. Mat src = (Mat_<uchar>(9, 12) << 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12. 0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 255, 0, 13. 0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 14. 0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 15. 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 16. 0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 17. 0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 255, 0, 18. 0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 19. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 20. namedWindow("src", WINDOW_NORMAL); //可以自由調(diào)節(jié)顯示圖像的尺寸 21. imshow("src", src); 22. //3×3矩形結(jié)構(gòu)元素 23. Mat kernel = getStructuringElement(0, Size(3, 3)); 24. 25. //對(duì)二值化矩陣進(jìn)行形態(tài)學(xué)操作 26. Mat open, close,gradient,tophat,blackhat,hitmiss; 27. 28. //對(duì)二值化矩陣進(jìn)行開運(yùn)算 29. morphologyEx(src, open, MORPH_OPEN, kernel); 30. namedWindow("open", WINDOW_NORMAL); //可以自由調(diào)節(jié)顯示圖像的尺寸 31. imshow("open", open); 32. 33. //對(duì)二值化矩陣進(jìn)行閉運(yùn)算 34. morphologyEx(src, close, MORPH_CLOSE, kernel); 35. namedWindow("close", WINDOW_NORMAL); //可以自由調(diào)節(jié)顯示圖像的尺寸 36. imshow("close", close); 37. 38. //對(duì)二值化矩陣進(jìn)行梯度運(yùn)算 39. morphologyEx(src, gradient, MORPH_GRADIENT, kernel); 40. namedWindow("gradient", WINDOW_NORMAL); //可以自由調(diào)節(jié)顯示圖像的尺寸 41. imshow("gradient", gradient); 42. 43. //對(duì)二值化矩陣進(jìn)行頂帽運(yùn)算 44. morphologyEx(src, tophat, MORPH_TOPHAT, kernel); 45. namedWindow("tophat", WINDOW_NORMAL); //可以自由調(diào)節(jié)顯示圖像的尺寸 46. imshow("tophat", tophat); 47. 48. //對(duì)二值化矩陣進(jìn)行黑帽運(yùn)算 49. morphologyEx(src, blackhat, MORPH_BLACKHAT, kernel); 50. namedWindow("blackhat", WINDOW_NORMAL); //可以自由調(diào)節(jié)顯示圖像的尺寸 51. imshow("blackhat", blackhat); 52. 53. //對(duì)二值化矩陣進(jìn)行擊中擊不中變換 54. morphologyEx(src, hitmiss, MORPH_HITMISS, kernel); 55. namedWindow("hitmiss", WINDOW_NORMAL); //可以自由調(diào)節(jié)顯示圖像的尺寸 56. imshow("hitmiss", hitmiss); 57. 58. //用圖像驗(yàn)證形態(tài)學(xué)操作效果 59. Mat coin = imread("coin.png",IMREAD_GRAYSCALE); 60. imshow("coin", coin); 61. threshold(coin, coin, 130, 255, THRESH_BINARY); 62. imshow("二值化后的coin", coin); 63. 64. //5×5矩形結(jié)構(gòu)元素 65. Mat kernel_coin = getStructuringElement(0, Size(5, 5)); 66. Mat open_coin, close_coin, gradient_coin; 67. Mat tophat_coin, blackhat_coin, hitmiss_coin; 68. 69. //對(duì)圖像進(jìn)行開運(yùn)算 70. morphologyEx(coin, open_coin, MORPH_OPEN, kernel_coin); 71. imshow("open_coin", open_coin); 72. 73. //對(duì)圖像進(jìn)行閉運(yùn)算 74. morphologyEx(coin, close_coin, MORPH_CLOSE, kernel_coin); 75. imshow("close_coin", close_coin); 76. 77. //對(duì)圖像進(jìn)行梯度運(yùn)算 78. morphologyEx(coin, gradient_coin, MORPH_GRADIENT, kernel_coin); 79. imshow("gradient_coin", gradient_coin); 80. 81. //對(duì)圖像進(jìn)行頂帽運(yùn)算 82. morphologyEx(coin, tophat_coin, MORPH_TOPHAT, kernel_coin); 83. imshow("tophat_coin", tophat_coin); 84. 85. //對(duì)圖像進(jìn)行黑帽運(yùn)算 86. morphologyEx(coin, blackhat_coin, MORPH_BLACKHAT, kernel_coin); 87. imshow("blackhat_coin", blackhat_coin); 88. 89. //對(duì)圖像進(jìn)行擊中擊不中變換 90. morphologyEx(coin, hitmiss_coin, MORPH_HITMISS, kernel_coin); 91. imshow("hitmiss_coin", hitmiss_coin); 92. 93. waitKey(0); 94. return 0; 95. } 圖6-28 myMorphologyApp.cpp程序中驗(yàn)證形態(tài)學(xué)操作的處理結(jié)果圖6-29 myMorphologyApp.cpp程序中灰度圖像及二值化后的圖像圖6-30 myMorphologyApp.cpp程序中圖像形態(tài)學(xué)操作后的結(jié)果經(jīng)過幾個(gè)月的努力,市面上第一本OpenCV 4入門書籍《OpenCV 4開發(fā)詳解》將春節(jié)后由人民郵電出版社發(fā)行。如果小伙伴覺得內(nèi)容有幫助,希望到時(shí)候多多支持!
關(guān)注小白的小伙伴可以提前看到書中的內(nèi)容,我們創(chuàng)建了學(xué)習(xí)交流群,歡迎各位小伙伴添加小白微信加入交流群,添加小白時(shí)請(qǐng)備注“學(xué)習(xí)OpenCV 4”。
https://u.wechat.com/MJ-57nVtXgxUyL3dTwWd014 (二維碼自動(dòng)識(shí)別)
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的opencv4 c++ 提取图片中的白色区域_【从零学习OpenCV 4】形态学应用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python3.8安装pygame_Py
- 下一篇: mybatisplus or查询_Myb