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)代码结果(请忽略准确性,咱先了解一下原理, ̄□ ̄||)

 

欢迎扫码关注微信公众号

猜你喜欢

转载自blog.csdn.net/sxlsxl119/article/details/84256308