9.3 基于边缘的分割
基于边缘的图像分割是一种常用的分割方法,它基于图像中物体边缘的特征来进行分割。边缘是图像中亮度或颜色发生剧烈变化的区域,通常表示不同物体或物体的边界。基于边缘的分割方法通过检测和连接边缘来实现图像分割。基于边缘的图像分割方法在许多应用中都非常有用,特别是对于提取物体边界和形状信息。它们在计算机视觉、图像处理和模式识别等领域得到广泛应用。
9.3.1 Canny边缘检测
Canny边缘检测是一种经典的边缘检测算法,它在图像中寻找强度梯度最大的位置,并将其视为边缘点。实现Canny边缘检测的基本步骤如下:
- 首先,将图像转换为灰度图像。
- 然后,对灰度图像应用高斯滤波来平滑图像,减少噪声。
- 接下来,计算图像中每个像素的梯度幅值和方向。
- 然后,应用非极大值抑制,将非边缘像素抑制为0,保留梯度幅值最大的边缘像素。
- 最后,应用双阈值处理,通过设置高阈值和低阈值来确定强边缘和弱边缘,并将它们连接成完整的边缘。
Canny边缘检测使用了多个步骤来实现边缘检测,包括高斯滤波、梯度计算、非极大值抑制和双阈值处理,例如下面是一个使用OpenCV库实现Canny边缘检测的例子。
实例9-3:使用OpenCV库实现Canny边缘检测
源码路径:daima\9\can.py
import cv2
# 读取图像
image = cv2.imread('image.jpg', 0)
# 应用Canny边缘检测
edges = cv2.Canny(image, 100, 200) # 阈值1为100,阈值2为200
# 显示原始图像和边缘图像
cv2.imshow('Original Image', image)
cv2.imshow('Edges', edges)
cv2.waitKey(0)
cv2.destroyAllWindows()
在上述代码中,首先首先使用cv2.imread()函数读取一幅灰度图像。然后,我们使用cv2.Canny()函数应用Canny边缘检测。函数的参数包括图像、两个阈值,阈值1用于边缘的强度梯度下限,阈值2用于边缘的强度梯度上限。接下来,使用cv2.imshow()函数显示原始图像和边缘图像,然后使用cv2.waitKey()等待按键操作,最后使用cv2.destroyAllWindows()关闭窗口。本实例演示了如何使用Canny边缘检测算法实现图像分割,可以根据需要调整阈值的选择,以获得更好的边缘检测效果。执行效果如图9-2所示。
图9-2 执行效果
9.3.2 边缘连接方法
基于边缘连接的图像分割方法是一种基于边缘像素的相邻性来连接边缘的方法。这种方法旨在将图像中的边缘像素连接成连续的边缘,从而实现图像的分割,形成完整的边缘。这些方法包括:
- 滞后阈值:根据梯度幅值的阈值,将边缘像素标记为强边缘或弱边缘。然后,根据弱边缘像素是否与强边缘像素相连,决定将其保留还是抑制。
- 连接分析:通过在边缘像素之间建立连接关系,将相邻的边缘像素连接起来形成连续的边缘。
- 边缘跟踪:从一个初始边缘像素开始,沿着边缘的方向追踪相邻的边缘像素,直到边缘结束。
例如下面是一个使用库OpenCV实现基于边缘连接方法的图像分割例子。
实例9-4:使用库OpenCV实现基于边缘连接方法的图像分割
源码路径:daima\9\bian.py
# 读取图像并进行边缘检测
image = cv2.imread('image.jpg', 0)
edges = cv2.Canny(image, 100, 200)
# 执行边缘连接方法
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 创建一个黑色背景图像
segmented_image = np.zeros_like(image)
# 在黑色背景上绘制边缘
cv2.drawContours(segmented_image, contours, -1, (255, 255, 255), thickness=cv2.FILLED)
# 显示原始图像和分割后的图像
cv2.imshow('Original Image', image)
cv2.imshow('Segmented Image', segmented_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
对上述代码的具体说明如下:
- 首先使用cv2.imread()函数读取一幅灰度图像。然后,我们使用cv2.Canny()函数对图像进行边缘检测,生成一组离散的边缘像素。
- 接下来,使用cv2.findContours()函数执行边缘连接方法,从边缘图像中找到边缘的连续轮廓。参数cv2.RETR_EXTERNAL表示只检测最外层的边缘,cv2.CHAIN_APPROX_SIMPLE表示仅保留边缘像素的端点。
- 然后,创建一个与原始图像大小相同的黑色背景图像,作为分割后的图像。使用cv2.drawContours()函数在黑色背景上绘制边缘轮廓,将边缘像素连接起来形成连续的边缘。
- 最后,使用cv2.imshow()函数显示原始图像和分割后的图像,然后使用cv2.waitKey()等待按键操作,使用cv2.destroyAllWindows()关闭窗口。