圖像形態學主要從圖像內提取分量信息,該分量信息通常對表達圖像的特征具有重要意義。例如,在車牌號碼識別中,能夠使用形態學計算其重要特征信息,在進行識別時,只需對這些特征信息運算即可。圖像形態學在目標視覺檢測、醫學圖像處理、信息壓縮提取等領域都有重要的應用。接下來,這篇隨筆介紹使用OpenCV進行圖像處理的第七章 圖像形態學操作。
7 圖像形態學操作
形態學操作主要包括:腐蝕、膨脹、開運算、閉運算、形態學梯度運算、頂帽運算(禮帽運算)、黑帽運算等操作。其中,腐蝕和膨脹是形態學中最基本的運算,其他方法都是基於這兩種運算組合而成的。
7.1 腐蝕
腐蝕是最基本的形態學操作之一,能夠消除圖像中的邊界,使圖像沿邊界向內收縮。
腐蝕時,有一個結構元逐個像素掃描原圖像,根據結構元中心與原圖像的關系來進行腐蝕。該結構元也被成為核。
核能夠自定義生成,也可以使用函數cv2.getStructuringElement()構造不同結構的核,該核函數的shape參數有多種,能夠生成不同的核,但相比於自定義核就稍有局限,所以本章內容全部默認基於自定義核,當然朋友們也可以嘗試使用cv2.getStructuringElement()核函數來構造特定結構的核。
在OpenCV中,使用cv2.erode()函數進行腐蝕操作,舉例程序如下:
1 #使用函數cv.erode()完成圖像腐蝕 2 import cv2 3 import numpy as np 4 o=cv2.imread('E:\python_opencv/fushi.jpg',cv2.IMREAD_UNCHANGED) 5 kernel=np.ones((5,5),np.uint8) #核大小為5×5 6 erosion=cv2.erode(o,kernel) #使用kernel對原圖像腐蝕 7 cv2.imshow('orriginal',o) 8 cv2.imshow('erosion',erosion) 9 cv2.waitKey() 10 cv2.destroyAllWindows()
在上面程序中,讀取圖片后先生成kernel結構元,是一個5×5大小且元素均為1的矩陣,再使用cv2.erode()函數進行腐蝕操作,運行結果如圖所示:
左圖是原始圖像,右圖是腐蝕圖像。可以看到,腐蝕操作能將圖片中的毛刺等腐蝕消掉。下面我們調節cv2.erode()函數的迭代次數,觀察不同kernel核對圖像的腐蝕效果。程序如下所示:
1 #調節函數cv2.erode()的參數,觀察不同參數控制下的圖像腐蝕效果 2 import cv2 3 import numpy as np 4 o=cv2.imread('E:\python_opencv/fushi.jpg',cv2.IMREAD_UNCHANGED) 5 kernel=np.ones((9,9),np.uint8) #核大小為9×9 6 #參數iteration等於5,是對cv2.erode()的迭代次數進行控制,讓其迭代5次 7 erosion=cv2.erode(o,kernel,iterations=5) 8 cv2.imshow('orriginal',o) 9 cv2.imshow('erosion',erosion) 10 cv2.waitKey() 11 cv2.destroyAllWindows()
運行結果如下圖,左為原圖像,右為迭代5次后的腐蝕處理結果,圖像已明顯向內收縮。
在這段代碼中,使用了更大的核、更多的迭代次數,所以圖像被腐蝕的更嚴重了。
7.2 膨脹
膨脹操作是腐蝕的逆運算,能對圖像從邊界處向外擴張。如果圖片中的兩個目標相距較近,膨脹后兩個目標可能會連通。膨脹操作經常應用在圖像分割后的填充任務中。
圖像膨脹也是使用一個kernel核,逐一對原圖像素進行掃描,判斷它們的位置關系來實現的。
在OpenCV中,使用cv2.dilate()函數進行膨脹操作,舉例程序如下:
1 #使用函數cv2.dilate()完成圖像膨脹操作 2 import cv2 3 import numpy as np 4 o=cv2.imread('E:\python_opencv/pengzhang.jpg',cv2.IMREAD_UNCHANGED) 5 kernel=np.ones((9,9),np.uint8) #核大小為9×9 6 dilation=cv2.dilate(o,kernel) #使用kernel對原圖像膨脹 7 cv2.imshow('orriginal',o) 8 cv2.imshow('dilation',dilation) 9 cv2.waitKey() 10 cv2.destroyAllWindows()
運行結果如下圖,左為原圖像,右為圖像膨脹處理結果,圖像已由邊界處向外擴張。
下面我們調節cv2.dilate()函數的迭代次數,觀察不同kernel核對圖像的腐蝕效果。代碼如下:
1 #調節函數cv2.dilate()的參數,觀察不同參數控制下的圖像膨脹效果 2 import cv2 3 import numpy as np 4 o=cv2.imread('E:\python_opencv/pengzhang.jpg',cv2.IMREAD_UNCHANGED) 5 kernel=np.ones((5,5),np.uint8) #核大小為5×5 6 #參數iteration等於9,是對cv2.dilate()的迭代次數進行控制,迭代9次 7 dilation=cv2.dilate(o,kernel,iterations=9) 8 cv2.imshow('orriginal',o) 9 cv2.imshow('dilation',dilation) 10 cv2.waitKey() 11 cv2.destroyAllWindows()
運行結果如下圖,左為原圖像,右為迭代9次后的膨脹處理結果,圖像已明顯由邊界處向外擴張。
7.3 開運算
開運算是先將圖像腐蝕,再對腐蝕后的結果進行膨脹。開運算常應用於圖像去噪等。
OpenCV提供了形態學函數cv2.morphologyEx()來實現各種形態學運算,內部op參數如下:
所以,使用函數cv2.morphologyEx()實現開運算舉例代碼如下:
1 #使用函數cv2.morphologyEx()實現開運算 2 import cv2 3 import numpy as np 4 img=cv2.imread('E:\python_opencv/kaiyunsuan.jpg') 5 kernel=np.ones((20,20),np.uint8) 6 #cv2.morphologyEx()函數的op參數設置為cv2.MORPH_OPEN 7 rst=cv2.morphologyEx(img,cv2.MORPH_OPEN,kernel) 8 cv2.imshow('img',img) 9 cv2.imshow('rst',rst) 10 cv2.waitKey() 11 cv2.destroyAllWindows()
運行結果如下圖,左為原圖像,右為開運算處理結果,圖像兩個目標已斷開連接。
7.4 閉運算
閉運算是先將圖像膨脹,再對膨脹后的結果進行腐蝕。閉運算常應用於去除圖像上的小黑點、或者連接圖中多個相距較近的目標等。
使用函數cv2.morphologyEx()實現閉運算,舉例代碼如下:
1 #使用函數cv2.morphologyEx()實現閉運算 2 import cv2 3 import numpy as np 4 img=cv2.imread('E:\python_opencv/biyunsuan.jpg') 5 kernel=np.ones((10,10),np.uint8) 6 #cv2.morphologyEx()函數的op參數設置為cv2.MORPH_CLOSE 7 rst=cv2.morphologyEx(img,cv2.MORPH_CLOSE,kernel,iterations=3) 8 cv2.imshow('img',img) 9 cv2.imshow('rst',rst) 10 cv2.waitKey() 11 cv2.destroyAllWindows()
運行結果如下圖,左為原圖像,右為閉運算處理結果,圖像兩個目標經過運算后連接在一起。
7.5 形態學梯度運算
形態學梯度運算是用圖像的膨脹圖像減去腐蝕圖像的操作。形態學梯度運算經常用於獲取前景圖像的邊緣信息。
使用函數cv2.morphologyEx()實現形態學梯度運算,舉例代碼如下:
1 #使用函數cv2.morphologyEx()實現形態學梯度運算 2 import cv2 3 import numpy as np 4 img=cv2.imread('E:\python_opencv/biyunsuan.jpg',cv2.IMREAD_UNCHANGED) 5 kernel=np.ones((5,5),np.uint8) 6 #cv2.morphologyEx()函數的op參數設置為cv2.MORPH_GRADIENT 7 rst=cv2.morphologyEx(img,cv2.MORPH_GRADIENT,kernel) 8 cv2.imshow('img',img) 9 cv2.imshow('rst',rst) 10 cv2.waitKey() 11 cv2.destroyAllWindows()
運行結果如下圖,左為原圖像,右為形態學梯度運算處理結果,獲得了前景圖像的邊緣輪廓。
7.6 禮帽運算
禮帽運算是用原始圖像減去其開運算圖像的操作。禮帽運算經常用於獲取圖像的噪聲信息和比原圖像更亮的局部邊緣信息。
使用函數cv2.morphologyEx()實現禮帽運算,舉例代碼如下:
1 #使用函數cv2.morphologyEx()實現禮帽運算 2 import cv2 3 import numpy as np 4 img=cv2.imread('E:\python_opencv/lena.jpg',cv2.IMREAD_UNCHANGED) 5 kernel=np.ones((5,5),np.uint8) 6 #cv2.morphologyEx()函數的op參數設置為cv2.MORPH_TOPHAT 7 rst=cv2.morphologyEx(img,cv2.MORPH_TOPHAT,kernel) 8 cv2.imshow('img',img) 9 cv2.imshow('rst',rst) 10 cv2.waitKey() 11 cv2.destroyAllWindows()
運行結果如下圖,左為原圖像,右為禮帽運算處理結果。
7.7 黑帽運算
黑帽運算是用閉運算圖像減去原始圖像的操作。黑帽運算能夠獲取圖像內部的小黑點或小孔,得到比原圖像更暗的邊緣信息。
使用函數cv2.morphologyEx()實現黑帽運算,舉例代碼如下:
1 #使用函數cv2.morphologyEx()實現黑帽運算 2 import cv2 3 import numpy as np 4 img=cv2.imread('E:\python_opencv/lena.jpg',cv2.IMREAD_UNCHANGED) 5 kernel=np.ones((5,5),np.uint8) 6 #cv2.morphologyEx()函數的op參數設置為cv2.MORPH_BLACKHAT 7 rst=cv2.morphologyEx(img,cv2.MORPH_BLACKHAT,kernel) 8 cv2.imshow('img',img) 9 cv2.imshow('rst',rst) 10 cv2.waitKey() 11 cv2.destroyAllWindows()
運行結果如下圖,左為原圖像,右為黑帽運算處理結果。
可以看到,黑帽運算得到了比禮帽運算更暗的邊緣信息。
這次內容就分享到這里了,下次繼續更新第8章 圖像梯度與Canny邊緣檢測,希望與各位老師和小伙伴們交流學習~