1. 程式人生 > >Python OpenCV _3形態學處理(腐蝕膨脹,開閉運算,以及利用形態學進行邊緣角點檢測)

Python OpenCV _3形態學處理(腐蝕膨脹,開閉運算,以及利用形態學進行邊緣角點檢測)

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)程式碼結果(請忽略準確性,咱先了解一下原理, ̄□ ̄||)

 

歡迎掃碼關注微信公眾號