一,原图
二,腐蚀和膨胀
# 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)代码结果(请忽略准确性,咱先了解一下原理, ̄□ ̄||)