Python OpenCV _3形態學處理(腐蝕膨脹,開閉運算,以及利用形態學進行邊緣角點檢測)
阿新 • • 發佈:2018-11-23
Python OpenCV這個初級影象處理系列是參考他人的文章寫的,有些地方做了一些改動,沒有太多理論,側重程式碼實現,主要目的是將這些基本操作程式碼系統地梳理一遍,也是為了以後能快速查詢。
此係列原始碼在我的GitHub裡:https://github.com/yeyujujishou19/Python-OpenCV
一,原圖
二,腐蝕和膨脹
# coding=utf-8 import cv2 import numpy as np # opencv裡所說的腐蝕,膨脹是針對白色區域,腐蝕是縮小白色區域,膨脹是擴大白色區域 img = cv2.imread('D:/2.jpg', 0) # OpenCV定義的結構元素 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) # 腐蝕影象 eroded = cv2.erode(img, kernel) # 顯示腐蝕後的影象 cv2.imshow("Eroded Image", eroded); # 膨脹影象 dilated = cv2.dilate(img, kernel) # 顯示膨脹後的影象 cv2.imshow("Dilated Image", dilated); # 原影象 cv2.imshow("Origin", img) # NumPy定義的結構元素 NpKernel = np.uint8(np.ones((3, 3))) Nperoded = cv2.erode(img, NpKernel) # 顯示腐蝕後的影象 cv2.imshow("Eroded by NumPy kernel", Nperoded); cv2.waitKey(0) cv2.destroyAllWindows()
程式碼結果:
三,開運算和閉運算
# coding=utf-8 import cv2 import numpy as np #開運算和閉運算就是將腐蝕和膨脹按照一定的次序進行處理。 # 但這兩者並不是可逆的,即先開後閉並不能得到原先的影象。 img = cv2.imread('D:/2.jpg', 0) # 定義結構元素 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (29, 29)) # 閉運算 closed = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel) # 顯示腐蝕後的影象 cv2.imshow("Close", closed); # 開運算 opened = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel) # 顯示腐蝕後的影象 cv2.imshow("Open", opened); cv2.waitKey(0) cv2.destroyAllWindows()
程式碼結果:
(對不起了,路飛,O(∩_∩)O哈哈~)
四,用形態學運算檢測邊和角點
1)檢測邊緣
A)原圖
B)程式碼
# coding=utf-8 import cv2 import numpy image = cv2.imread("D:/test/3_1.jpg", 0); # 構造一個3×3的結構元素 element = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) dilate = cv2.dilate(image, element) erode = cv2.erode(image, element) # 將兩幅影象相減獲得邊,第一個引數是膨脹後的影象,第二個引數是腐蝕後的影象 result = cv2.absdiff(dilate, erode); # 上面得到的結果是灰度圖,將其二值化以便更清楚的觀察結果 retval, result = cv2.threshold(result, 40, 255, cv2.THRESH_BINARY); # 反色,即對二值圖每個畫素取反 result = cv2.bitwise_not(result); # 顯示影象 cv2.imwrite("D:/21.jpg",result) # cv2.imshow("result", result); # cv2.waitKey(0) # cv2.destroyAllWindows()
C)程式碼結果
2)檢測拐角
A)與邊緣檢測不同,拐角的檢測的過程稍稍有些複雜,但原理相同。
a)先用十字形的結構元素膨脹畫素,這種情況下只會在邊緣處“擴張”,角點不發生變化。
# 使用cross膨脹影象
result1 = cv2.dilate(image, cross)
b)接著用菱形的結構元素腐蝕原影象,導致只有在拐角處才會“收縮”,而直線邊緣都未發生變化。
# 使用菱形腐蝕影象
result1 = cv2.erode(result1, diamond)
c)第三步是用X形膨脹原影象,角點膨脹的比邊要多。
# 使用X膨脹原影象
result2 = cv2.dilate(image, x)
d)這樣第二次用方塊腐蝕時,角點恢復原狀,而邊要腐蝕的更多。
# 使用方形腐蝕影象
result2 = cv2.erode(result2, square)
e)所以當兩幅影象相減時,只保留了拐角處。
# 將兩幅閉運算的影象相減獲得角
result = cv2.absdiff(result2, result1)
B)整體程式碼:
# coding=utf-8
import cv2
image = cv2.imread("D:/test/3_1.jpg", 0)
origin = cv2.imread("D:/test/3_1.jpg")
# 構造5×5的結構元素,分別為十字形、菱形、方形和X型
cross = cv2.getStructuringElement(cv2.MORPH_CROSS, (5, 5))
# 菱形結構元素的定義稍麻煩一些
diamond = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
diamond[0, 0] = 0
diamond[0, 1] = 0
diamond[1, 0] = 0
diamond[4, 4] = 0
diamond[4, 3] = 0
diamond[3, 4] = 0
diamond[4, 0] = 0
diamond[4, 1] = 0
diamond[3, 0] = 0
diamond[0, 3] = 0
diamond[0, 4] = 0
diamond[1, 4] = 0
square = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
x = cv2.getStructuringElement(cv2.MORPH_CROSS, (5, 5))
# 使用cross膨脹影象
result1 = cv2.dilate(image, cross)
# 使用菱形腐蝕影象
result1 = cv2.erode(result1, diamond)
# 使用X膨脹原影象
result2 = cv2.dilate(image, x)
# 使用方形腐蝕影象
result2 = cv2.erode(result2, square)
# result = result1.copy()
# 將兩幅閉運算的影象相減獲得角
result = cv2.absdiff(result2, result1)
# 使用閾值獲得二值圖
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(origin, (y, x), 5, (0, 0, 255))
cv2.imshow("Result", origin)
cv2.waitKey(0)
cv2.destroyAllWindows()
C)程式碼結果(請忽略準確性,咱先了解一下原理, ̄□ ̄||)