OpenCV与图像处理学习六——图像形态学操作:腐蚀、膨胀、开、闭运算、形态学梯度、顶帽和黑帽
OpenCV與圖像處理學習六——圖像形態(tài)學操作:腐蝕、膨脹、開、閉運算、形態(tài)學梯度、頂帽和黑帽
- 四、圖像形態(tài)學操作
- 4.1 腐蝕和膨脹
- 4.1.1 圖像腐蝕
- 4.1.2 圖像膨脹
- 4.2 開運算與閉運算
- 4.2.1 開運算
- 4.2.2 閉運算
- 4.3 形態(tài)學梯度(Gradient)
- 4.4頂帽和黑帽
有關(guān)圖像處理前三次的筆記:
OpenCV與圖像處理學習三——圖像基本操作(1)
OpenCV與圖像處理學習四——圖像基本操作(2)
OpenCV與圖像處理學習五——圖像基本操作(3)
這是有關(guān)圖像基本操作的最后一次筆記,有關(guān)圖像形態(tài)學操作。
四、圖像形態(tài)學操作
形態(tài)學,是圖像處理中應用最為廣泛的技術(shù)之一,主要用于從圖像中提取對表達和描繪區(qū)域形狀有意義的圖像分量,使后續(xù)的識別工作能夠抓住目標對象最為本質(zhì)的形狀特征,如邊界和連通區(qū)域等。
下面會經(jīng)常用到一個概念,這里先進行說明:
結(jié)構(gòu)元素:設有兩幅圖像B,X,若X是被處理的對象,而B是用來處理X的,則B稱為結(jié)構(gòu)元素(structure element),又被形象地稱作刷子。結(jié)構(gòu)元素通常都是一些比較小的圖像。
下面將介紹形態(tài)學的幾種常用操作:腐蝕、膨脹、開運算和閉運算等。
4.1 腐蝕和膨脹
圖像的膨脹(Dilation)和腐蝕(Erosion)是兩種基本的形態(tài)學運算,其中膨脹類似于“領(lǐng)域擴張”,將圖像中的白色部分進行擴張,其運行結(jié)果圖比原圖的白色區(qū)域更大;而腐蝕類似于“領(lǐng)域被蠶食”,將圖像中白色的部分進行縮減細化,其運行結(jié)果圖比原圖的白色區(qū)域更小。
4.1.1 圖像腐蝕
把結(jié)構(gòu)元素B平移a后得到Ba,若Ba包含于X,我們記下這個a點,所有滿足上述條件的a點組成的集合稱作X被B腐蝕(Erosion)的結(jié)果。如下圖所示:
其中X是被處理的對象,B是結(jié)構(gòu)元素。對于任意一個在陰影部分的點a,Ba包含于X,所以X被B腐蝕的結(jié)果就是那個陰影部分。陰影部分在X的范圍之內(nèi),且比X小,就像X被剝掉了一層似的。
腐蝕后的結(jié)果如下圖黑色部分所示:
相較于原來的灰色部分,仿佛變瘦了。
OpenCV中的函數(shù)為:
dst = cv2.erode( src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]] )參數(shù)為:
下面看個例子:
import cv2 import numpy as np import matplotlib.pyplot as plt img = cv2.imread('./image/morphology.png') img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) kernel = np.ones((3, 3), np.uint8) erosion = cv2.erode(img, kernel, iterations = 1) plt.subplot(121), plt.imshow(img), plt.title('Original') plt.xticks([]), plt.yticks([]) plt.subplot(122), plt.imshow(erosion), plt.title('erosion') plt.xticks([]), plt.yticks([]) plt.show()結(jié)果如下所示:
若將結(jié)構(gòu)元素的尺寸擴大到7,結(jié)果為:
ps:在構(gòu)造結(jié)構(gòu)元素的時候,可以使用numpy,也可以使用OpenCV提供的函數(shù)cv2.getStructuringElement()
函數(shù):
retval = cv2.getStructuringElement( shape, ksize[, anchor] )參數(shù):
看一下例子:
import numpy as np import cv2kernel = np.ones((5, 5), np.uint8) print(kernel) [[1 1 1 1 1][1 1 1 1 1][1 1 1 1 1][1 1 1 1 1][1 1 1 1 1]] kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (7,7)) print(kernel) [[0 0 0 1 0 0 0][0 0 0 1 0 0 0][0 0 0 1 0 0 0][1 1 1 1 1 1 1][0 0 0 1 0 0 0][0 0 0 1 0 0 0][0 0 0 1 0 0 0]] kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (7,7)) print(kernel) [[0 0 0 1 0 0 0][0 1 1 1 1 1 0][1 1 1 1 1 1 1][1 1 1 1 1 1 1][1 1 1 1 1 1 1][0 1 1 1 1 1 0][0 0 0 1 0 0 0]] kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7,7)) print(kernel) [[1 1 1 1 1 1 1][1 1 1 1 1 1 1][1 1 1 1 1 1 1][1 1 1 1 1 1 1][1 1 1 1 1 1 1][1 1 1 1 1 1 1][1 1 1 1 1 1 1]]我們可以用非矩形的結(jié)構(gòu)元素來進行腐蝕操作:
#!/usr/bin/env python3 import cv2image = cv2.imread("./image/morphology.png") gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) cv2.imshow("Gray Image", gray)kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (7, 7)) eroded = cv2.erode(gray.copy(), kernel, 10) # eroded = cv2.erode(gray.copy(), None, 10)cv2.imshow("Eroded Image", eroded) cv2.waitKey(0) cv2.destroyAllWindows()
也是可以達到一定效果的,但是比矩形的那種腐蝕程度低一些些,因為畢竟結(jié)構(gòu)元素里多了一些0。
4.1.2 圖像膨脹
膨脹(dilation)可以看做是腐蝕的對偶運算,其定義是:把結(jié)構(gòu)元素B平移后得到Ba,若Ba與X有交集,我們記下這個a點。所有滿足上述條件的a點組成的集合稱作X被B膨脹后的結(jié)果,如下圖所示:
其中X是被處理的對象,B是結(jié)構(gòu)元素,對于任意一個在陰影部分的點a,Ba與X有交集,所以X被B膨脹后的結(jié)果就是那個陰影部分,陰影部分包括X所有范圍,就像是X膨脹了一圈似的。
膨脹后的圖像,其中綠色是膨脹多出來的部分:
在OpenCV中的函數(shù)為:
參數(shù):
看個例子:
import cv2 import numpy as np import matplotlib.pyplot as plt img = cv2.imread('./image/morphology.png') img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) #kernel = np.ones((3,),np.uint8) kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7,7))dilation = cv2.dilate(img,kernel,iterations = 1) plt.subplot(121),plt.imshow(img),plt.title('origin') plt.xticks([]), plt.yticks([]) plt.subplot(122),plt.imshow(dilation),plt.title('dilation') plt.xticks([]), plt.yticks([]) plt.show()結(jié)果為:
若將運算元素尺寸擴大一點,擴大為11:
原本斷開的地方或小孔都被填上了。
4.2 開運算與閉運算
4.2.1 開運算
開運算 = 先腐蝕運算,再膨脹運算,看上去把細微連在一起的兩塊目標分開了,開運算的效果圖如下所示:
開運算對一些細微的小點,小塊,細條等部分是可以消去的,因為先腐蝕消去它們,導致它們消失了無法再通過膨脹變回來,而一些比較大的塊通過腐蝕操作只是會變瘦一點,不會被完全抹去,所以可以通過膨脹運算變回來,那么總的效果就是開運算去除了這些孤立的小點,細長的小條。
開運算總結(jié):
開運算和閉運算都用如下函數(shù)來表示,這個函數(shù)是OpenCV中圖像形態(tài)學變化的通用函數(shù):
dst = cv2.morphologyEx( src, op, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]] )參數(shù)如下所示:
下面看個例子:
import cv2 import numpy as np import matplotlib.pyplot as plt img = cv2.imread('./image/open.png') img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) #kernel = np.ones((5,5),np.uint8) kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel) plt.subplot(121), plt.imshow(img), plt.title('Original') plt.xticks([]), plt.yticks([]) plt.subplot(122), plt.imshow(opening), plt.title('opening') plt.xticks([]), plt.yticks([]) plt.show()結(jié)果如下所示:
一些細小的點被去除了很多,但是開運算的結(jié)構(gòu)元素的尺寸很重要,太小可能去除效果不好,太大可能會得到不想要的結(jié)果,如將3改為9,結(jié)果將變?yōu)?#xff1a;
所以調(diào)節(jié)這個參數(shù)還是很關(guān)鍵的。
4.2.2 閉運算
閉運算 = 先膨脹運算,再腐蝕運算,看上去將兩個細微連接的圖塊封閉在一起,閉運算的效果圖如下圖所示:
閉運算總結(jié):
看個例子:
import cv2 as cv import numpy as np import matplotlib.pyplot as plt img = cv.imread('./image/close.png') img = cv.cvtColor(img,cv.COLOR_BGR2RGB) # kernel = np.ones((5,5),np.uint8) kernel = np.ones((7, 7), np.uint8) closing = cv.morphologyEx(img, cv.MORPH_CLOSE, kernel) plt.subplot(121), plt.imshow(img), plt.title('Original') plt.xticks([]), plt.yticks([]) plt.subplot(122), plt.imshow(closing), plt.title('closing') plt.xticks([]), plt.yticks([]) plt.show()結(jié)果如下所示:
一些小孔被填滿了。若把尺寸從7改為21,結(jié)果為:
就有點過了,把不需要連接和填補的地方也給連接、填補了,所以要合理選擇參數(shù)。
4.3 形態(tài)學梯度(Gradient)
用cv2.morphologyEx函數(shù)可以實現(xiàn)基礎(chǔ)梯度操作,看下面這個例子:
import cv2 as cv import numpy as np import matplotlib.pyplot as plt img = cv.imread('./image/morphology.png') img = cv.cvtColor(img, cv.COLOR_BGR2RGB) kernel = np.ones((3, 3), np.uint8) gradient = cv.morphologyEx(img, cv.MORPH_GRADIENT, kernel) plt.subplot(121), plt.imshow(img), plt.title('Original') plt.xticks([]), plt.yticks([]) plt.subplot(122), plt.imshow(gradient), plt.title('gradient') plt.xticks([]), plt.yticks([]) plt.show()結(jié)果如下所示:
4.4頂帽和黑帽
- 頂帽(Top Hat):原圖像與開運算圖的差值,突出原圖像中比周圍亮的區(qū)域。
- 黑帽(Black Hat):閉運算圖與原圖的差值,突出原圖中比周圍暗的區(qū)域。
看兩個例子:
頂帽:
import cv2 as cv import numpy as np import matplotlib.pyplot as plt img = cv.imread('./image/morphology.png') img = cv.cvtColor(img, cv.COLOR_BGR2RGB) kernel = np.ones((9, 9), np.uint8) tophat = cv.morphologyEx(img, cv.MORPH_TOPHAT, kernel) plt.subplot(121), plt.imshow(img), plt.title('Original') plt.xticks([]), plt.yticks([]) plt.subplot(122), plt.imshow(tophat), plt.title('tophat') plt.xticks([]), plt.yticks([]) plt.show()結(jié)果為:
黑帽:
圖像處理之圖像基本操作的筆記就暫時到這里,后面將學習傳統(tǒng)方法進行圖像分割,包括閾值分割、邊緣檢測算法、連通域分析以及一些其他區(qū)域生長算法。
總結(jié)
以上是生活随笔為你收集整理的OpenCV与图像处理学习六——图像形态学操作:腐蚀、膨胀、开、闭运算、形态学梯度、顶帽和黑帽的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JavaSE——Java基础语法(二进制
- 下一篇: UG/Open API基础知识-语法1