【youcans 的 OpenCV 例程200篇】145. 形态学之边缘和角点检测
5.7 形态学之边缘和角点检测
边缘和角点不仅保留了图像的重要特征,而且极大地减少了信息的数据量,因而具有很大的信息熵,在场景重建、运动估计、目标跟踪与识别、图像的配准与匹配等计算机视觉领域具有重要作用。角点检测的方法主要是基于图像边缘或基于图像灰度,后者的应用更加广泛,如 Harris算子、Moravec 算子和 Susan 算子。
本节介绍一种基于形态学的边缘检测和角点检测方法。角点在水平和竖直方向的变化都很大,即 x,y 方向的梯度都很大;边缘在 x,y 中的一个方向上梯度很大;而平坦区域在水平竖直两个方向上的梯度都较小。
形态学边缘检测的原理是,图像中的物体在膨胀时向周围扩张,在腐蚀时会发生收缩,变化的区域都只发生在物体的边缘。图像的形态学梯度运算,是膨胀图像与腐蚀图像之差 ,可以得到图像的轮廓,通常用于提取物体边缘。
形态学角点检测的原理是,通过十字形、菱形、方形、X 型等不同形状结构元的膨胀腐蚀,使原图像的边缘不发生变化,仅有焦点被腐蚀。
需要说明的是,本案例只是为了示范形态学方法的功能,并不是高效、精准的角点检测方法。
例程 10.36:基于灰度形态学的边缘检测和角点检测
形态学检测边缘的原理是,图像中的物体在膨胀时向周围扩张,在腐蚀时会发生收缩,变化的区域都只发生在物体的边缘。图像的形态学梯度运算,是膨胀图像与腐蚀图像之差 ,可以得到图像的轮廓,通常用于提取物体边缘。
(1)先用十字形结构元膨胀,图像在水平和垂直方向膨胀,而在 45度、135度的斜向没有膨胀;再用菱形核对膨胀结果进行腐蚀,使得膨胀结果在水平和垂直方向被腐蚀,而在45度、135度的斜向也有腐蚀。
(2)先用 X 形结构元膨胀,图像在水平、垂直方向、45度、135度斜向都发生膨胀;再用正方形核对膨胀结果进行腐蚀,使原图的角点被恢复,而水平、垂直方向的边缘被腐蚀。
(3) 二者相减,得到角点检测结果。
# 10.36: 基于灰度形态学的拐角检测
# 基于灰度形态学的复杂背景图像重建
img = cv2.imread("../images/imgBuilding1.png", flags=1)
imgSign = img.copy()
imgGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 图片格式转换:BGR(OpenCV) -> Gray
# ret, imgBin = cv2.threshold(imgGray, 127, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU) # 二值化处理
# 边缘检测
element = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
imgEdge = cv2.morphologyEx(imgGray, cv2.MORPH_GRADIENT, element) # 形态学梯度
# 构造 5×5 结构元素,十字形、菱形、方形、X 型
cross = cv2.getStructuringElement(cv2.MORPH_CROSS, (5, 5)) # 十字型结构元
square = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5)) # 矩形结构元
xShape = cv2.getStructuringElement(cv2.MORPH_CROSS, (5, 5)) # X 形结构元
diamond = cv2.getStructuringElement(cv2.MORPH_CROSS, (5, 5)) # 构造菱形结构元
diamond[1, 1] = diamond[3, 3] = 1
diamond[1, 3] = diamond[3, 1] = 1
print(diamond)
imgDilate1 = cv2.dilate(imgGray, cross) # 用十字型结构元膨胀原图像
imgErode1 = cv2.erode(imgDilate1, diamond) # 用菱形结构元腐蚀图像
imgDilate2 = cv2.dilate(imgGray, xShape) # 使用 X 形结构元膨胀原图像
imgErode2 = cv2.erode(imgDilate2, square) # 使用方形结构元腐蚀图像
imgDiff = cv2.absdiff(imgErode2, imgErode1) # 将两幅闭运算的图像相减获得角点
retval, thresh = cv2.threshold(imgDiff, 40, 255, cv2.THRESH_BINARY) # # 二值化处理
# 在原图上用半径为 5 的圆圈标记角点
for j in range(thresh.size):
y = int(j / thresh.shape[0])
x = int(j % thresh.shape[0])
if (thresh[x, y] == 255):
cv2.circle(imgSign, (y, x), 5, (255, 0, 255))
plt.figure(figsize=(9, 6))
plt.subplot(131), plt.title("Origin"), plt.axis('off')
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.subplot(132), plt.title("Edge"), plt.axis('off')
plt.imshow(imgEdge, cmap='gray', vmin=0, vmax=255)
plt.subplot(133), plt.title("Corner"), plt.axis('off')
plt.imshow(cv2.cvtColor(imgSign, cv2.COLOR_BGR2RGB))
plt.tight_layout()
plt.show()
(本节完)
版权声明:
youcans@xupt 原创作品,转载必须标注原文链接:(https://blog.csdn.net/youcans/article/details/123786155)
Copyright 2022 youcans, XUPT
Crated:2022-3-30