开运算和闭运算_OpenCV计算机视觉学习(5)——形态学处理(腐蚀膨胀,开闭运算,礼帽黑帽,边缘检测)...
在開始學習之前推薦大家可以多在FlyAI競賽服務平臺多參加訓練和競賽,以此來提升自己的能力。FlyAI是為AI開發者提供數據競賽并支持GPU離線訓練的一站式服務平臺。每周免費提供項目開源算法樣例,支持算法能力變現以及快速的迭代算法模型。
如果需要處理的原圖及代碼,請移步小編的GitHub地址
傳送門:請點擊我如果點擊有誤:https://github.com/LeBron-Jian/ComputerVisionPractice
形態學操作簡單來說,就是改變物體的形狀,下面學習一下,首先本文的目錄如下:
- 1,定義結構元素
- 2,腐蝕和膨脹
- 3,開運算和閉運算
- 4,禮帽/頂帽,黑帽算法
- 5,梯度運算
- 6,形態學運算 檢測邊和角點(1,檢測邊緣 ; 2,檢測拐角)
1,定義結構元素
形態學操作的原理:在特殊領域運算形式——結構元素(Structure Element),在每個像素位置上與二值圖像對應的區域進行特定的邏輯運算。運算結構是輸出圖像的相應像素。運算效果取決于結構元素大小內容以及邏輯運算性質。
結構元素:膨脹和腐蝕操作的最基本組成部分,用于測試輸出圖像,通常要比待處理的圖像小很多,二維平面結構元素由一個數值為0或1的矩陣組成。結構元素的原點指定了圖像中需要處理的像素范圍,結構元素中數值為1的點決定結構元素的領域像素進行膨脹或腐蝕操作時是否需要參與計算。
形態學處理的核心就是定義結構元素,在OpenCV-Python中,可以使用其自帶的 getStructuringElement 函數,也可以直接使用 Numpy 的 ndarray 來定義一個結構元素,形象圖如下:
下面代碼為上圖的十字形,代碼如下:
#_*_coding:utf-8_*_import cv2import numpy as npdef show_element():element_cross = cv2.getStructuringElement(cv2.MORPH_CROSS, (5, 5))print(element_cross)element_ellipse = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))print(element_ellipse)element_rect = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))print(element_rect)'''[[0 0 1 0 0][0 0 1 0 0][1 1 1 1 1][0 0 1 0 0][0 0 1 0 0]][[0 0 1 0 0][1 1 1 1 1][1 1 1 1 1][1 1 1 1 1][0 0 1 0 0]][[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]]'''def define_cross_structure():NpKernel = np.uint8(np.zeros((5, 5)))for i in range(5):NpKernel[2, i] = 1NpKernel[i, 2] = 1print("NpKernel", NpKernel)'''NpKernel [[0 0 1 0 0][0 0 1 0 0][1 1 1 1 1][0 0 1 0 0][0 0 1 0 0]]'''上面我們自定義了一個結構元素 kernel,先聲明一個矩陣,然后對其進行賦值,這種方法靈活但是略顯復雜。OpenCV提供了一個函數 也就是上面展示的,可以獲取常用結構元素的性質:矩形(包括線形),橢圓(包括圓形)以及十字形。下面具體學習一下此方法
1.1 定義一些基本符號和關系
1,元素
設有一幅圖像X,若點 a 在 X 的區域以內,則稱 a 為 X 的元素,記做 a 屬于 X,如圖 6.1所示。
2,B包含于X
設有兩幅圖像 B, X。對于 B中所有的元素 ai, 都有 ai 屬于 X,則稱B包含于 (included in)X ,記做 B 屬于 X,如圖6.2所示。
3,B擊中 X
設有兩幅圖像B, X。若存在這一一個點,它即是B的元素,又是 X 的元素,則稱 B 擊中(hit)X,記做 B ↑ X,如圖6.3所示。
4,B不擊中 X
設有兩幅圖像B, X。若不存在任何一個點,它既是B的元素,又是 X的元素,即 B和 X的交集是空,則稱 B 不擊中(miss)X,記做 B ∩ X = Φ;其中 ∩ 是集合運算相交的符號,Φ 表示空集,如圖6.4所示。
5,補集
設有一幅圖像 X,所有 X 區域以外的點構成的集合稱為 X 的補集,記做 Xc,如下圖所示。顯然,如果B ∩ X = Φ,則 B 在 X的補集內,即 B 屬于 Xc。
6,結構元素
設有兩幅圖像B,X。若X是被處理的對象,而B是用來處理X的,則稱B為結構元素(structure element),又被形象的稱作刷子。結構元素通常都是一些比較小的圖像。
7,對稱集
設有一幅圖像B,將B中所有元素的坐標取反,即令(x, y)變為(-x, -y),所有這些點構成的新的集合稱為B的對稱集,記做 Bv,如下圖6.6所示。
8,平移
設有一幅圖像B,有一個點a(x0, y0),將B平移a后的結果是,把B中所有元素的橫坐標加 x0,縱坐標加 y0,即令(x, y)變成(x + x0, y+y0),所有這些點構成新的集合稱為B的平移,記做 Ba,如圖6.7所示。
1.2 getStructuringElement 方法
getStructuringElement 是OpenCV提供的一個函數,getStructuringElement 的內部并沒有什么優化實現,只是封裝了一些功能,其原理同樣是聲明了一個矩陣,然后求形狀,指定矩陣的值。而我們只需要直接調用即可。
函數原型如下:
def getStructuringElement(shape, ksize, anchor=None):參數的意思:
- shape 表示內核的形狀,有三種形狀可以選擇:
——十字形:cv2.getStructuringElement(cv2.MORPH_CROSS,(5,5))
——橢圓:cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))
——矩形:cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))
- ksize 表示內核的尺寸(n, n)
- anchor 錨點的位置
此函數最終會返回指定形狀和尺寸的結構元素。
下面代碼實現一下,這里同時展示一下自己寫的:
kernel1 = np.ones((3, 3), np.uint8)kernel2 = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))print(kernel1)print(kernel2)print(kernel1 == kernel2)'''[[1 1 1][1 1 1][1 1 1]][[1 1 1][1 1 1][1 1 1]][[ True True True][ True True True][ True True True]]'''這里其實再證明一次。
2,腐蝕和膨脹
圖像的膨脹(Dilation)和腐蝕(Erosion)是兩種基本的形態學運算,主要用來尋找圖像中的極大區域和極小區域。其中膨脹類似于“領域擴張”,將圖像中的高亮區域或白色部分進行擴張,其運行結果圖比原圖的高亮區域更大;腐蝕類似于“領域被蠶食”,將圖像中的高亮區域或白色部分進行縮減細化,其運行結果圖比原圖的高亮區域更小。
形態學各種功能實現,都歸結為腐蝕 erode 和 膨脹 dilate 的組合,形象理解一下就是腐蝕等于變瘦,膨脹等于變胖,所以下面學習一下腐蝕和膨脹。
注意:腐蝕和膨脹主要針對二值化圖像的白色部分。
2.1 腐蝕
腐蝕就是把結構元素B平移a后得到Ba,若Ba包含于X,我們記下這個a點,所有滿足上述條件的 a點組成的集合稱為X被B腐蝕(Erosion)的結果。
上圖 X 是被處理的對象,B是結構元素,不難知道,對于任意一個在陰影部分的點 a,Ba包含于X,所以 X被B腐蝕的結果就是那個陰影部分,陰影部分在 X的范圍之內,且比 X小,就像 X 被剝掉了一層似的,這0就是為什么叫腐蝕的原因。
腐蝕的運算符為 “ - ”,其定義如下:
該公式表示圖像A用卷積模板B來進行腐蝕處理,通過模板B與圖像A進行卷積計算,得到B覆蓋區域的像素點最小值,并用這個最小值來替代參考點的像素值。如圖所示,將左邊的原始圖像A腐蝕處理為右邊的效果圖A-B。
腐蝕:腐蝕會把物體的邊界腐蝕掉,卷積核沿著圖像滑動,如果卷積核對應的原圖的所有像素值為1,那么中心元素就保持原來的值,否則變為零。主要應用在去除白噪聲,也可以斷開連在一起的物體。
在原圖的每一個區域中取最小值,由于是二值化圖像,只要有一個點為0,則為0,來達到瘦身的目的。
腐蝕的作用:
- 1,對象大小減少1個像素(3*3)
- 2,平滑對象邊緣
- 3,弱化或者分割圖像之間的半島型連接
2.2 膨脹(Dilate)
膨脹可以看做是腐蝕的對偶運算,其定義是:把結構元素B平移 a 后得到 Ba,若Ba擊中X,我們記下這個 a 點。所有滿足上述條件的 a點組成的集合稱為 X被B膨脹的結果。
膨脹的方法是:拿B的中心點和X上的點及X周圍的點一個一個的對,如果B上有一個點落在X的范圍內,則該點為黑,可以看出X的范圍就像X膨脹一圈似的。
圖像膨脹的運算符是“⊕”,其定義如下:
這個公式表示用B來對圖像A進行膨脹處理,其中B是一個卷積模板或卷積核,其形狀可以為正方形或圓形,通過模板B與圖像A進行卷及計算,掃描圖像中的每一個像素點,用模板元素與二值圖像元素做“與”運算,如果都為0,那么目標像素點為0,否則為1。從而計算B覆蓋區域的像素點最大值,并用該值替換參考點的像素值實現膨脹。下圖是將左邊的原始圖像A膨脹處理為右邊的效果圖 A⊕B。
膨脹:卷積核所對應的原圖像的像素值只要有一個是1,中心像素值就是1.一般在除噪聲,先腐蝕再膨脹,因為腐蝕在去除白噪聲的時候也會使圖像縮小,所以我們之后要進行膨脹。當然也可以用來將兩者物體分開。
膨脹的作用:
- 1,對象大小增加一個像素 (3*3)
- 2,平滑對象邊緣
- 3,減少或者填充對象之間的距離
2.3 代碼展示
代碼如下:
import cv2import numpy as npdef erode_image(img_path):origin_img = cv2.imread(img_path)gray_img = cv2.cvtColor(origin_img, cv2.COLOR_BGR2GRAY)# OpenCV定義的結構元素kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))# 腐蝕圖像eroded = cv2.erode(gray_img, kernel)# 顯示腐蝕后的圖像cv2.imshow('Origin', origin_img)cv2.imshow('Erode', eroded)cv2.waitKey(0)cv2.destroyAllWindows()def dilate_image(img_path):origin_img = cv2.imread(img_path)gray_img = cv2.cvtColor(origin_img, cv2.COLOR_BGR2GRAY)# OpenCV定義的結構元素kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))# 膨脹圖像dilated = cv2.dilate(gray_img, kernel)# 顯示腐蝕后的圖像cv2.imshow('Dilate', dilated)cv2.waitKey(0)cv2.destroyAllWindows()if __name__ == '__main__':img_path = 'origin.jpg'erode_image(img_path)dilate_image(img_path)如上所示,腐蝕和膨脹的處理很簡單,只需設置好結構元素,然后分別調用 cv2.erode() 和 cv2.dilate()函數,其中第一個參數為需要處理的圖像,第二個是結構元素,返回處理好的圖像。
下圖從左到右依次是 原圖,腐蝕,膨脹(我們可以看出腐蝕是將線條變瘦,膨脹是變胖):
2.4 腐蝕和膨脹的知識點補充
1,可以看做膨脹是將白色區域擴大,腐蝕是將黑色區域擴大。
2,可以不進行灰度處理,對彩色圖像進行處理
腐蝕cv2.erode(src, # 輸入圖像kernel, # 卷積核dst=None,anchor=None,iterations=None, # 迭代次數,默認1borderType=None,borderValue=None)膨脹cv2.dilate(src, # 輸入圖像kernel, # 卷積核dst=None,anchor=None,iterations=None, # 迭代次數,默認1borderType=None,borderValue=None)3,開運算和閉運算
開運算和閉運算就是將腐蝕和膨脹按照一定的次序進行處理。但是這兩者并不是可逆的,即先開后閉并不能得到原來的圖像。
為了獲取圖像中的主要對象:對一幅二值圖連續使用閉運算和開運算,或者消除圖像中的噪聲,也可以對圖像先用開運算后用閉運算,不過這樣也會消除一些破碎的對象。
- 開運算:先腐蝕后膨脹,用于移除由圖像噪聲形成的斑點
- 閉運算:先膨脹后腐蝕,用來連接被誤分為許多小塊的對象
3.1 開運算
開運算 = 先腐蝕運算,再膨脹運算(看上去把細微連在一起的兩塊目標分開了)
開運算的效果圖如下圖所示:
開運算總結:
- (1)開運算能夠除去孤立的小點,毛刺和小橋,而總的位置和形狀不變。
- (2)開運算是一個基于幾何運算的濾波器
- (3)結構元素大小的不同將導致濾波效果的不同
- (4)不同的結構元素的選擇導致了不同的分割,即提取出不同的特征。
3.2 閉運算
閉運算=先膨脹運算,再腐蝕運算(看上去將兩個細微連接的圖封閉在一起)
閉運算的效果如下圖所示:
閉運算總結:
- (1)閉運算能夠填平小湖(即小孔),彌合小裂縫,而總的位置和形狀不變。
- (2)閉運算是通過填充圖像的凹角來濾波圖像的。
- (3)結構元素大小的不同將導致濾波效果的不同。
- (4)不同結構元素的選擇導致了不同的分割。
代碼如下:
import cv2import numpy as npdef Open_operation(img_path):origin_img = cv2.imread(img_path)gray_img = cv2.cvtColor(origin_img, cv2.COLOR_BGR2GRAY)# OpenCV定義的結構元素kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))# 開運算open = cv2.morphologyEx(gray_img, cv2.MORPH_OPEN, kernel)# 顯示腐蝕后的圖像cv2.imshow('Open', open)cv2.waitKey(0)cv2.destroyAllWindows()def Closed_operation(img_path):origin_img = cv2.imread(img_path)gray_img = cv2.cvtColor(origin_img, cv2.COLOR_BGR2GRAY)# OpenCV定義的結構元素kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))# 閉運算closed = cv2.morphologyEx(gray_img, cv2.MORPH_CLOSE, kernel)# 顯示腐蝕后的圖像cv2.imshow('Closed', closed)cv2.waitKey(0)cv2.destroyAllWindows()def show_origin(origin_path):# img = cv2.imread(origin_path, )# 灰度化img = cv2.imread(origin_path, 0)cv2.imshow('origin', img)cv2.waitKey(0)cv2.destroyAllWindows()if __name__ == '__main__':# 此圖為加了高斯噪聲的圖片img_path = 'butterfly_Gaussian.jpg'show_origin(img_path)Closed_operation(img_path)Open_operation(img_path)import cv2import numpy as npdef Open_operation(img_path):origin_img = cv2.imread(img_path)gray_img = cv2.cvtColor(origin_img, cv2.COLOR_BGR2GRAY)# OpenCV定義的結構元素kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))# 開運算open = cv2.morphologyEx(gray_img, cv2.MORPH_OPEN, kernel)# 顯示腐蝕后的圖像cv2.imshow('Open', open)cv2.waitKey(0)cv2.destroyAllWindows()def Closed_operation(img_path):origin_img = cv2.imread(img_path)gray_img = cv2.cvtColor(origin_img, cv2.COLOR_BGR2GRAY)# OpenCV定義的結構元素kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))# 閉運算closed = cv2.morphologyEx(gray_img, cv2.MORPH_CLOSE, kernel)# 顯示腐蝕后的圖像cv2.imshow('Closed', closed)cv2.waitKey(0)cv2.destroyAllWindows()def show_origin(origin_path):# img = cv2.imread(origin_path, )# 灰度化img = cv2.imread(origin_path, 0)cv2.imshow('origin', img)cv2.waitKey(0)cv2.destroyAllWindows()if __name__ == '__main__':# 此圖為加了高斯噪聲的圖片img_path = 'butterfly_Gaussian.jpg'show_origin(img_path)Closed_operation(img_path)Open_operation(img_path)效果如下:(分布是原圖,開運算的圖,閉運算的圖)
閉運算用來連接被誤分為許多小塊的對象,而開運算用于移除由圖像噪聲形成的斑點。因此,某些情況下可以連續運用這兩種運算。如對一幅二值圖連續使用閉運算和開運算,將獲得圖像中的主要讀寫。同樣,如果想消除圖像中噪聲(即圖像中的“小點”),也可以對圖像先用開運算后用閉運算,不過這樣也會消除一些破碎的對象。
3.3 開運算和閉運算的知識點補充
這里主要補充函數原型
開運算圖像開運算主要使用的函數morphologyEx,它是形態學擴展的一組函數,其參數cv2.MORPH_OPEN對應開運算。其原型如下:dst = cv2.morphologyEx(src, cv2.MORPH_OPEN, kernel)參數dst表示處理的結果,src表示原圖像,cv2.MORPH_OPEN表示開運算,kernel表示卷積核閉運算圖像閉運算主要使用的函數morphologyEx,其原型如下:dst = cv2.morphologyEx(src, cv2.MORPH_CLOSE, kernel)參數dst表示處理的結果,src表示原圖像, cv2.MORPH_CLOSE表示閉運算,kernel表示卷積核4,禮帽/頂帽,黑帽算法
禮帽 :原始圖像與其進行開運算后的圖像進行一個差
黑帽:原始圖像與其閉運算后的圖像進行一個差
禮帽運算 = 原始圖像 - 開運算
黑帽運算 = 閉運算 - 原始圖像
代碼如下:
import cv2def hat_algorithm(img_path):original_img0 = cv2.imread(img_path)original_img = cv2.imread(img_path, 0)kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) # 定義矩形結構元素TOPHAT_img = cv2.morphologyEx(original_img, cv2.MORPH_TOPHAT, kernel) # 頂帽運算BLACKHAT_img = cv2.morphologyEx(original_img, cv2.MORPH_BLACKHAT, kernel) # 黒帽運算# 顯示圖像cv2.imshow("original_img0", original_img0)cv2.imshow("original_img", original_img)cv2.imshow("TOPHAT_img", TOPHAT_img)cv2.imshow("BLACKHAT_img", BLACKHAT_img)cv2.waitKey(0)cv2.destroyAllWindows()if __name__ == '__main__':img_path = 'butterfly_Gaussian.jpg'hat_algorithm(img_path)效果如下:(依次是原圖,灰度圖圖片(兩個類似,是因為我將原圖做了灰度化高斯處理,所以灰度化之后和原圖類似),頂帽圖片,黑帽圖片)
該算法可以用于圖像識別的預處理,用于圖像二值化后取出孤立點,代碼如下:
import cv2def deal_isolated(img_path):original_img = cv2.imread(img_path, 0)gray_img = cv2.resize(original_img, None, fx=0.8, fy=0.8,interpolation=cv2.INTER_CUBIC) # 圖形太大了縮小一點kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) # 定義矩形結構元素(核大小為3效果好)TOPHAT_img = cv2.morphologyEx(gray_img, cv2.MORPH_TOPHAT, kernel) # 頂帽運算BLACKHAT_img = cv2.morphologyEx(gray_img, cv2.MORPH_BLACKHAT, kernel) # 黒帽運算bitwiseXor_gray = cv2.bitwise_xor(gray_img, TOPHAT_img)# 顯示如下腐蝕后的圖像cv2.imshow("gray_img", gray_img)cv2.imshow("TOPHAT_img", TOPHAT_img)cv2.imshow("BLACKHAT_img", BLACKHAT_img)cv2.imshow("bitwiseXor_gray", bitwiseXor_gray)cv2.waitKey(0)cv2.destroyAllWindows()if __name__ == '__main__':img_path = 'lena.jpg'deal_isolated(img_path)可以看出,最后效果更加明顯了一些:
5,梯度運算
梯度 = 膨脹 - 腐蝕
下面看一個示例:
import cv2import numpy as npimport matplotlib.pyplot as pltimg = cv2.imread('circle.jpg')kernel = np.ones((7, 7), np.uint8)# kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7, 7))erosion = cv2.erode(img, kernel, iterations = 5)dilation = cv2.dilate(img, kernel, iterations = 3)gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)result = [img, erosion, dilation, gradient]titles = ['origin img', 'erosion img', 'dilate img', 'gradient img']for i in range(4):plt.subplot(2, 2, i+1), plt.imshow(result[i])plt.title(titles[i])plt.xticks([]), plt.yticks([])plt.show()效果如下:
6,用形態學運算檢測邊和角點
這里通過一個較復雜的例子學習如何用形態學算子檢測圖像中的邊緣和拐角(這里只做形態學處理例子,實際使用請參考Canny和Harris等算法:請參考博文:深入學習OpenCV中幾種圖像邊緣檢測算子)
6.1 檢測邊緣
形態學檢測邊緣的原理很簡單,在膨脹時,圖像中的物體會向周圍“擴張”;腐蝕時,圖像的額物體會“收縮”。比較兩幅圖像,由于其變化的區域只發生在邊緣。所以這時將這兩幅圖像相減,得到的就是圖像中的邊緣。這里用的依然是參考資料《Opencv2 Computer Vision Application Programming Cookbook》中相關章節的圖片:
代碼如下:
# coding=utf-8import cv2import numpydef detection_edge(img_path):image = cv2.imread(img_path, 0)# 構造一個3×3的結構元素element = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))dilate = cv2.dilate(image, element)erode = cv2.erode(image, element)# 將兩幅圖像相減獲得邊,第一個參數是膨脹后的圖像,第二個參數是腐蝕后的圖像# cv2.absdiff參數:(膨脹后的圖像,腐蝕后的圖像)result = cv2.absdiff(dilate, erode)# 上面得到的結果是灰度圖,將其二值化以便更清楚的觀察結果retval, result = cv2.threshold(result, 40, 255, cv2.THRESH_BINARY)# 反色,即對二值圖每個像素取反result = cv2.bitwise_not(result)# 顯示圖像cv2.imshow("result", result)cv2.waitKey(0)cv2.destroyAllWindows()if __name__ == '__main__':img_path = "building.jpg"detection_edge(img_path)結果如下:
6.2 檢測角點(拐角)
與邊緣檢測不同,拐角的檢測過程稍稍有些復雜。但是原理相同,所不同的是先用十字形的結構元素膨脹像素,這種情況下只會在邊緣處“擴張”,角點不發生變化。接著用菱形的結構元素腐蝕原圖像,導致只有在拐角處才會“收縮”,而直線邊緣都未發生變化。
第二步是用X行膨脹原圖像,焦點膨脹的比邊要多。這樣第二次用方塊腐蝕時,角點恢復原狀,而邊要腐蝕的更多。所以當兩幅圖像相減時,只保留了拐角處,示意圖如下(示意圖來自參考資料《Opencv2 Computer Vision Application Programming Cookbook》):
代碼如下:
# coding=utf-8import cv2import numpydef detection_inflexion(img_path):image = cv2.imread(img_path, 0)origin = cv2.imread(img_path)# 構造5×5的結構元素,分別為十字形、菱形、方形和X型cross = cv2.getStructuringElement(cv2.MORPH_CROSS, (5, 5))# 菱形結構元素的定義稍麻煩一些diamond = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))diamond[0, 0] = 0diamond[0, 1] = 0diamond[1, 0] = 0diamond[4, 4] = 0diamond[4, 3] = 0diamond[3, 4] = 0diamond[4, 0] = 0diamond[4, 1] = 0diamond[3, 0] = 0diamond[0, 3] = 0diamond[0, 4] = 0diamond[1, 4] = 0square = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))x = cv2.getStructuringElement(cv2.MORPH_CROSS, (5, 5))# 使用cross膨脹圖像dilate_cross_img = cv2.dilate(image, cross)# 使用菱形腐蝕圖像erode_diamond_img = cv2.erode(dilate_cross_img, diamond)# 使用X膨脹原圖像dilate_x_img = cv2.dilate(image, x)# 使用方形腐蝕圖像erode_square_img = cv2.erode(dilate_x_img, square)# result = result1.copy()# 將兩幅閉運算的圖像相減獲得角result = cv2.absdiff(erode_square_img, erode_diamond_img)# 使用閾值獲得二值圖retval, result = cv2.threshold(result, 40, 255, cv2.THRESH_BINARY)# 在原圖上用半徑為5的圓圈將點標出。for j in range(result.size):y = int(j / result.shape[0])x = int(j % result.shape[0])if result[x, y] == 255:cv2.circle(image, (y, x), 5, (255, 0, 0))cv2.imshow("Result", image)cv2.waitKey(0)cv2.destroyAllWindows()if __name__ == '__main__':img_path = "building.jpg"detection_inflexion(img_path)通過上面的代碼就能檢測出圖像的拐角并標出來,效果如下:
當然這個只是一個示例,效果不是很好。
參考文獻:https://www.cnblogs.com/ssyfj/p/9276999.htmlhttps://blog.csdn.net/wsp_1138886114/article/details/82917661https://blog.csdn.net/JohinieLi/article/details/81041276https://blog.csdn.net/hanshanbuleng/article/details/806571481、《Opencv2 Computer Vision Application Programming Cookbook》
2、《OpenCV References Manule》
最初的來源: https://blog.csdn.net/sunny2038/article/details/9137759https://blog.csdn.net/gbxvip/article/details/50844007
更多精彩內容請訪問FlyAI-AI競賽服務平臺;為AI開發者提供數據競賽并支持GPU離線訓練的一站式服務平臺;每周免費提供項目開源算法樣例,支持算法能力變現以及快速的迭代算法模型。
挑戰者,都在FlyAI!!!
總結
以上是生活随笔為你收集整理的开运算和闭运算_OpenCV计算机视觉学习(5)——形态学处理(腐蚀膨胀,开闭运算,礼帽黑帽,边缘检测)...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: clickhouse 子查询_TPCDS
- 下一篇: 铁矿怎么来_铁矿期货今日创出新高908.