Python常用圖像形態(tài)學(xué)操作詳解
腐蝕
在一些圖像中,會有一些異常的部分,比如這樣的毛刺:
對于這樣的情況,我們就可以應(yīng)用復(fù)式操作了。需要注意的是,腐蝕操作只能處理二值圖像,即像素矩陣的值只有0(黑色)和255(白色)。我們先看看代碼和效果:
import cv2 import numpy as np img = cv2.imread('dagongren.png') # 腐蝕的代碼 kernel = np.ones((3,3),np.uint8) erosion = cv2.erode(img,kernel,iterations = 1) cv2.imshow('erosion', erosion) cv2.waitKey(0) cv2.destroyAllWindows()
這張圖片已經(jīng)幾乎看不到毛刺了,但與此同時,三個文字也小了一點,這就是腐蝕操作。所謂腐蝕操作,就是我們設(shè)置一個n×n的矩陣,這個矩陣可以視為一個卷積核,在原圖上進(jìn)移動。矩陣覆蓋住的像素點中,如果有0(黑色),那么該卷積核的中心位置置零,反之,如果該卷積核內(nèi)全都是255,則不做操作:
注意:我們可以理解成腐蝕操作是完全根據(jù)原圖生成的新圖,而不是在原土上的修改。
接下來我們再看看腐蝕的代碼:
kernel = np.ones((3,3),np.uint8) erosion = cv2.erode(img,kernel,iterations = 1)
首先,我們要利用numpy庫生成一個n×n大小的全1矩陣kernel作為卷積核,并且需要指定數(shù)據(jù)類型為無符號8位整數(shù)。然后使用erode()函數(shù),其接收的參數(shù)分別為圖像矩陣,kernel矩陣,以及迭代次數(shù)。迭代次數(shù)就是腐蝕操作的次數(shù)。下面我們用一個圓來查看一下不同迭代次數(shù)的腐蝕效果:
import cv2 import numpy as np kernel = np.ones((30,30),np.uint8) pie = cv2.imread('pie.png') # 觀察不同的迭代次數(shù) erosion_1 = cv2.erode(pie,kernel,iterations = 1) erosion_2 = cv2.erode(pie,kernel,iterations = 2) erosion_3 = cv2.erode(pie,kernel,iterations = 3) res = np.hstack((erosion_1,erosion_2,erosion_3)) cv2.imshow('res', res) cv2.waitKey(0) cv2.destroyAllWindows()
膨脹
腐蝕操作可以腐蝕掉二值圖像的邊緣,因此可以消除掉一些圖片上的毛刺,但是損失一些原圖相中有效的部分也是在所難免的。膨脹其實就是腐蝕操作的反面。“卷積核”包裹住的像素中有255,則這個卷積核中心位置會置為255,否則不變。因此,膨脹操作會把原本的圖像范圍進(jìn)行擴(kuò)大:
import cv2 import numpy as np img = cv2.imread('dagongren.png') kernel = np.ones((3,3),np.uint8) # 膨脹操作 dige_dilate = cv2.dilate(img,kernel,iterations = 1) cv2.imshow('dilate', dige_dilate) cv2.waitKey(0) cv2.destroyAllWindows()
可以看到,膨脹操作后,圖像的范圍變大了一圈,就連毛刺也都擴(kuò)大了。膨脹操作通常會配合腐蝕操作一起使用的,先腐蝕在膨脹,可以在保持圖片中有效內(nèi)容大小大體不變的情況下去除掉毛刺:
import cv2 import numpy as np img = cv2.imread('dagongren.png') kernel = np.ones((3,3),np.uint8) # 腐蝕 erosion = cv2.erode(img,kernel,iterations = 1) # 對原圖像進(jìn)行腐蝕 # 膨脹 dige_dilate = cv2.dilate(erosion,kernel,iterations = 1) # 對腐蝕后圖像進(jìn)行膨脹 cv2.imshow('dilate', dige_dilate) cv2.waitKey(0) cv2.destroyAllWindows()
其原理和參數(shù)意義與腐蝕操作類似,在此不做過多講解。
開運算與閉運算
開運算與閉運算都是應(yīng)用腐蝕與膨脹操作來處理原圖像的。區(qū)別在于開運算是先腐蝕在膨脹,閉運算是先膨脹再腐蝕。這兩個操作需要用到的函數(shù)都是morphologyEx(),只需要調(diào)整參數(shù)即可完成兩種不同的操作。
開運算
執(zhí)行開運算的函數(shù)是:
cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
kernel依然是n×n的矩陣,cv2.MORPH_OPEN指定了執(zhí)行運算為開運算:
import cv2 import numpy as np img = cv2.imread('dagongren.png') kernel = np.ones((3,3),np.uint8) opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel) cv2.imshow('opening', opening) cv2.waitKey(0) cv2.destroyAllWindows()
結(jié)果為:
閉運算
和開運算基本相同,只需要把morphologyEx()函數(shù)的第二個參數(shù)改為cv2.MORPH_CLOSE即可:
import cv2 import numpy as np img = cv2.imread('dagongren.png') kernel = np.ones((3,3),np.uint8) closing = cv2.morphologyEx(img,cv2.MORPH_CLOSE,kernel) cv2.imshow('closing', closing) cv2.waitKey(0) cv2.destroyAllWindows()
很明顯,先膨脹再腐蝕和原圖并沒有什么區(qū)別,僅僅是比原圖大了一圈,因此閉運算也沒有開運算應(yīng)用廣泛。
梯度運算
梯度運算本質(zhì)是膨脹-腐蝕。從這個定義中不難發(fā)現(xiàn),梯度就是原圖的邊緣部分。獲取梯度依然要用到morphologyEx()函數(shù),將第二個參數(shù)改為cv2.MORPH_GRADIENT即可:
import cv2 import numpy as np img = cv2.imread('dagongren.png') kernel = np.ones((3,3),np.uint8) # 先用開運算把毛刺去掉: img = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel) gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel) cv2.imshow('gradient', gradient) cv2.waitKey(0) cv2.destroyAllWindows()
得到的結(jié)果就是下面這樣:
禮帽與黑帽
禮帽和黑帽都是翻譯的結(jié)果,因此我們不能望文生義。禮貌操作就是原始圖像-開運算結(jié)果,黑帽操作是閉運算-原始輸入。依然是用morphologyEx()函數(shù),通過修改第二個參數(shù)完成。
禮帽
禮帽操作需要用到的參數(shù)是cv2.MORPH_TOPHAT。由禮帽操作的定義可以直到,禮帽操作可以得到圖片中的“毛刺”部分:
import cv2 import numpy as np img = cv2.imread('dagongren.png') kernel = np.ones((3,3),np.uint8) # 禮帽操作 tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel) cv2.imshow('tophat', tophat) cv2.waitKey(0) cv2.destroyAllWindows()
得到的結(jié)果為:
黑帽
黑帽操作需要用到的參數(shù)是cv2.MORPH_BLACKHAT,黑帽運算會輸出執(zhí)行閉運算后的圖像比原圖大出的一小圈輪廓:
import cv2 import numpy as np img = cv2.imread('dagongren.png') kernel = np.ones((5,5),np.uint8) # kernel矩陣維度大一些會讓黑帽操作的結(jié)果更明顯 # 黑帽操作 tophat = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel) cv2.imshow('tophat', tophat) cv2.waitKey(0) cv2.destroyAllWindows()
到此這篇關(guān)于Python常用圖像形態(tài)學(xué)操作詳解的文章就介紹到這了,更多相關(guān)Python圖像形態(tài)學(xué)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python TK庫簡單應(yīng)用(實時顯示子進(jìn)程輸出)
這篇文章主要介紹了python TK庫簡單應(yīng)用(實時顯示子進(jìn)程輸出),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10Numpy中的數(shù)組搜索中np.where方法詳細(xì)介紹
這篇文章主要介紹了Numpy中的數(shù)組搜索中np.where方法詳細(xì)介紹,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01Python使用tkinter模塊實現(xiàn)推箱子游戲
這篇文章主要介紹了Python使用tkinter模塊實現(xiàn)推箱子游戲,主要分享兩點,第一就是這個程序的實現(xiàn)過程,第二點就是我在編寫過程中的一些思考。本文通過實例代碼給大家介紹的非常詳細(xì),需要的朋友參看下吧2019-10-10pycharm中導(dǎo)入模塊錯誤時提示Try to run this command from the system ter
這篇文章主要介紹了pycharm中導(dǎo)入模塊錯誤時提示Try to run this command from the system terminal問題,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-03-03Python實現(xiàn)獲取網(wǎng)站PR及百度權(quán)重
這篇文章主要介紹了Python實現(xiàn)獲取網(wǎng)站PR及百度權(quán)重,本文使用傳參的方式請求站長工具和谷歌工具獲取PR值和百度權(quán)重,需要的朋友可以參考下2015-01-01