python+opencv圖像形態學處理詳細解釋(膨脹、腐蝕、開閉運算、禮帽和黑貓)


python+opencv圖像形態學處理

本篇博客主要是關於形態學中的腐蝕、膨脹、開運算、閉運算、禮帽和黑帽的函數用法。

內容會比較,為方便查閱。代碼的解釋會寫在代碼中。

用於測試的圖像原圖:

一、腐蝕

  • 關於腐蝕就是將圖像的邊界腐蝕掉,或者說使得圖像整體上看起來變瘦了。它的操作原理就是卷積核沿着圖像滑動,如果與卷積核對應的原圖像的所有像素值都是1,那么中心元素保持原來的值,否則就變為0。這對於去除白噪聲很有用,也可以用於斷開兩個連載一起的物體。
  • 通俗的講,腐蝕操作就是讓圖像整體看起來瘦一點。
  • 但是老貓發現,這句話並不完全正確,腐蝕操作不一定會讓圖像變瘦,有可能還會讓它變胖。

例如:

 1 #腐蝕
 2 #讀取圖像
 3 img1=cv.imread("oldcat.jpg")
 4 
 5 #將圖像進行反向二值化操作,即將白色部分變為黑色,黑色部分變為白色
 6 #ret,img2=cv.threshold(img1,80,255,cv.THRESH_BINARY_INV) 
 7 
 8 #定義一個3*3的卷積核
 9 kernel=np.ones((3,3),np.uint8)
10 
11 #圖像腐蝕:cv2.erode(輸入圖像,卷積核,iterations=腐蝕的次數)
12 erosion=cv.erode(img1,kernel,iterations=1)
13 
14 #在圖像上添加文本,方便分清每個操作相對應的圖像
15 cv.putText(img1,"original",(150,230),cv.FONT_HERSHEY_COMPLEX,1,(0,0,255),2,8)
16 cv.putText(erosion,"erosion",(150,230),cv.FONT_HERSHEY_COMPLEX,1,(0,0,255),2,8)
17 
18 #將原圖像和腐蝕操作的圖像放在同一個窗口顯示
19 glay=np.hstack((img1,erosion))
20 cv.imshow("glay",glay)
21 cv.waitKey(0)
22 cv.destroyAllWindows()

效果圖:

可以發現:

  相比於原圖,腐蝕並沒有變瘦,反而還“胖”了。

原因:

  形態學處理是一個對二值化灰度圖像的處理,主要是對白色圖像的一個卷積操作。

  由於原圖字體是黑色,底色為白色,所以在進行腐蝕操作的時候,卷積核中只要有一個點為0,卷積核的中心點也會為0。

解決方法:

  對原圖像進行一個反向二值化處理,即將白色部分變為黑色,黑色部分變為白色

  去掉上面代碼ret,img2=cv.threshold(img,80,255,cv.THRESH_BINARY_INV)的注釋,同時將erosion=cv.erode(img1,kernel,iterations=1)改為erosion=cv.erode(img2,kernel,iterations=1)

效果圖:

如圖所示:這樣腐蝕處理的圖像才會變瘦

二、膨脹

膨脹:卷積核所對應的原圖像的像素值只要有一個是1,中心像素值就是1。一般在除噪是,先腐蝕再膨脹,因為腐蝕在去除白噪聲的時候也會使圖像縮小,所以我們之后要進行膨脹。當然也可以用來將兩者物體分開。

例如:

 

 1 import numpy as np
 2 import cv2 as cv
 3 #膨脹
 4 #讀取圖像
 5 img1=cv.imread("oldcat.jpg",0)
 6 
 7 #將圖像進行反向二值化操作,即將白色部分變為黑色,黑色部分變為白色
 8 ret,img2=cv.threshold(img1,80,255,cv.THRESH_BINARY_INV) 
 9 
10 #定義一個3*3的卷積核
11 kernel=np.ones((3,3),np.uint8)
12 
13 #圖像腐蝕:cv2.dilate(輸入圖像,卷積核,iterations=腐蝕的次數)
14 dilation=cv.dilate(img2,kernel,iterations=1)
15 
16 #在圖像上添加文本,方便分清每個操作相對應的圖像
17 cv.putText(img1,"original",(150,230),cv.FONT_HERSHEY_COMPLEX,1,(0,0,255),2,8)
18 
19 #將原圖像和膨脹操作的圖像放在同一個窗口顯示
20 glay=np.hstack((img1,dilation))
21 cv.imshow("glay",glay)
22 cv.waitKey(0)
23 cv.destroyAllWindows()

效果圖:

 腐蝕和膨脹是比較簡單的。

 三、開運算

了解形態學基本處理的同學都知道,開運算和閉運算就是將腐蝕和膨脹按照一定的次序進行處理。但這兩者並不是可逆的,即先開后閉並不能得到原先的圖像。

例如:

 1 import numpy as np
 2 import cv2 as cv
 3 #開運算
 4 #先腐蝕,再膨脹
 5 img1=cv.imread("oldcat.jpg",0)
 6 #反二值化,小於127設為255,即黑變白;大於127的設為 0,即白變黑。
 7 ret,img2=cv.threshold(img1,127,255,cv.THRESH_BINARY_INV)
 8 
 9 #定義一個3*3的卷積核
10 kernel=np.ones((3,3),np.uint8)
11 
12 #開運算
13 opening2=cv.morphologyEx(img2,cv.MORPH_OPEN,kernel)
14 
15 #在圖像上添加文本,方便分清每個操作相對應的圖像
16 cv.putText(img1,"original",(150,230),cv.FONT_HERSHEY_COMPLEX,1,(0,0,255),2,8)
17 
18 #將原圖像和開運算操作的圖像放在同一個窗口顯示
19 glay=np.hstack((img1,opening2))
20 cv.imshow("glay",glay)
21 cv.waitKey(0)
22 cv.destroyAllWindows()

效果圖:

四、閉運算

閉運算:就是先膨脹,后腐蝕,也是不可逆的。

 1 import numpy as np
 2 import cv2 as cv
 3 #閉運算
 4 #先膨脹,后腐蝕
 5 img1=cv.imread("oldcat.jpg",0)
 6 #反二值化,小於127設為255,即黑變白;大於127的設為 0,即白變黑。
 7 ret,img2=cv.threshold(img1,127,255,cv.THRESH_BINARY_INV)
 8 
 9 #定義一個3*3的卷積核
10 kernel=np.ones((3,3),np.uint8)
11 
12 #閉運算
13 closing=cv.morphologyEx(img2,cv.MORPH_CLOSE,kernel)
14 
15 #在圖像上添加文本,方便分清每個操作相對應的圖像
16 cv.putText(img1,"original",(150,230),cv.FONT_HERSHEY_COMPLEX,1,(0,0,255),2,8)
17 
18 #將原圖像和閉運算操作的圖像放在同一個窗口顯示
19 glay=np.hstack((img1,closing))
20 cv.imshow("glay",glay)
21 cv.waitKey(0)
22 cv.destroyAllWindows()

效果圖:

 五、梯度運算

梯度運算,類似於提取輪廓。梯度=膨脹-腐蝕

例如:

 

 1 import numpy as np
 2 import cv2 as cv
 3 #梯度運算,類似於提取輪廓
 4 #梯度=膨脹-腐蝕
 5 img1=cv.imread("oldcat.jpg",0)
 6 
 7 #反二值化,小於127設為255,即黑變白;大於127的設為 0,即白變黑。
 8 ret,img2=cv.threshold(img1,127,255,cv.THRESH_BINARY_INV)
 9 
10 #定義一個3*3的卷積核
11 kernel=np.ones((3,3),np.uint8)
12 
13 #梯度運算
14 gradient=cv.morphologyEx(img2,cv.MORPH_GRADIENT,kernel)
15 
16 #在圖像上添加文本,方便分清每個操作相對應的圖像
17 cv.putText(img1,"original",(150,230),cv.FONT_HERSHEY_COMPLEX,1,(0,0,255),2,8)
18 
19 #將原圖像和梯度運算操作的圖像放在同一個窗口顯示
20 glay=np.hstack((img1,gradient))
21 cv.imshow("glay",glay)
22 cv.waitKey(0)
23 cv.destroyAllWindows()

 

效果圖:

 

六、禮帽

禮帽就是原始初入減去開運算結果

例如:

 1 import numpy as np
 2 import cv2 as cv
 3 #禮帽,小線條
 4 #禮帽=原始輸入-運算結果
 5 img1=cv.imread("oldcat.jpg",0)
 6 ret,img2=cv.threshold(img1,127,255,cv.THRESH_BINARY_INV)
 7 kernel=np.ones((3,3),np.uint8)
 8 
 9 #禮帽
10 tophat=cv.morphologyEx(img2,cv.MORPH_TOPHAT,kernel)
11 
12 #在圖像上添加文本,方便分清每個操作相對應的圖像
13 cv.putText(img1,"original",(150,230),cv.FONT_HERSHEY_COMPLEX,1,(0,0,255),2,8)
14 
15 #將原圖像和禮帽運算操作的圖像放在同一個窗口顯示
16 glay=np.hstack((img1,tophat))
17 cv.imshow("glay",glay)
18 cv.waitKey(0)
19 cv.destroyAllWindows()

效果圖:

 

 七、黑帽

黑帽=閉運算-原始輸入

例如:

 1 import numpy as np
 2 import cv2 as cv
 3 #黑帽。只能看見大概輪廓
 4 #黑帽=閉運算-原始輸入
 5 img1=cv.imread("oldcat.jpg",0)
 6 ret,img2=cv.threshold(img1,127,255,cv.THRESH_BINARY_INV)
 7 kernel=np.ones((3,3),np.uint8)
 8 
 9 #黑帽
10 blackhat=cv.morphologyEx(img2,cv.MORPH_BLACKHAT,kernel)
11 
12 #在圖像上添加文本,方便分清每個操作相對應的圖像
13 cv.putText(img1,"original",(150,230),cv.FONT_HERSHEY_COMPLEX,1,(0,0,255),2,8)
14 
15 #將原圖像和開運算操作的圖像放在同一個窗口顯示
16 glay=np.hstack((img1,blackhat))
17 cv.imshow("glay",glay)
18 cv.waitKey(0)
19 cv.destroyAllWindows()

效果圖:

 八、總結

  • 本篇博客主要是關於圖像形態學處理,文字描述雖然不多,但是每一行代碼都有解釋,並且每一個運算處理的效果圖都有原圖和處理后的圖像對比。
  • 圖像形態學處理是針對灰度圖的,所以在讀取原圖的過程中,直接關閉了顏色通道,雖然方便但也有不足,就是圖像上,添加的文字信息也會失去顏色。具體可以觀察腐蝕處理和膨脹處理再讀取代碼上的區別。
  • 為了方便更容易理解,我是將原圖進行了一個二值化反色處理,再進行相應的形態學處理。若不進行二值化反色處理,結果是跟我的效果圖是不一樣的。具體就是將代碼中的二值化處理代碼去掉,大家可以試一試,對比觀察,更深的理解形態學處理是什么實現的。

實踐出真知,博客的代碼很完整,但還需要自己實際寫一遍才能更加理解。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM