问题描述
图像分割是将数字图像细分为多个子区域的过程,在计算机视觉/机器视觉领域被广泛应用。它的目的是简化或改变图像的表示形式,以便更容易理解和分析。常见的图像分割方法包括阈值处理、聚类法、边缘检测和区域生长等。解决图像分割问题通常需要结合领域知识,以提高解决效果。
边缘检测是一种常用的图像分割方法,通过提取图像中不连续部分的特征来实现。目前,常见的边缘检测算子包括差分算子、Roberts算子、Sobel算子、Prewitt算子、Log算子和Canny算子。Canny算子是由John F. Canny于1986年提出的一种边缘检测算子,被认为是目前最完善的边缘检测算法之一。许多常用的图像处理工具(如MATLAB、OpenCV)都内置了Canny算子的API。
Canny边缘检测
Canny边缘检测是一种经典的边缘检测算法,于1986年由John F. Canny提出。它被广泛应用于计算机视觉和图像处理领域,用于检测图像中的边缘信息。
论文信息:
标题:A Computational Approach to Edge Detection
作者:John F. Canny
出版年份:1986年
Canny边缘检测算法的步骤
Canny边缘检测算法的目标是找到图像中的强边缘,并尽量消除噪声和弱边缘。该算法的步骤如下:
-
噪声抑制:首先,使用高斯滤波器对图像进行平滑处理,以减少噪声的影响。
-
计算梯度:然后,计算图像中每个像素点的梯度强度和方向。这可以通过应用Sobel等滤波器来实现。
-
非极大值抑制:接下来,对梯度强度图像进行非极大值抑制,以细化边缘并消除边缘响应。
-
双阈值处理:然后,使用双阈值处理来确定边缘的强度。根据设定的阈值,将边缘像素分为强边缘、弱边缘和非边缘像素。
-
边缘连接:最后,通过边缘连接算法来连接强边缘像素和与之相邻的弱边缘像素,以形成完整的边缘。
Canny边缘检测算法在图像处理领域广受赞誉,它能够检测到细微的边缘,并且对噪声具有较好的鲁棒性。
1.应用高斯滤波去除图像噪声
高斯滤波器是一种平滑滤波器,通过对图像进行卷积操作,降低像素值之间的差异,从而减少噪声的影响。
高斯滤波器的核(或模板)是一个二维的权重矩阵,其中权重值由高斯函数计算得出。该权重矩阵的大小和标准差(σ)是高斯滤波器的两个关键参数,决定了滤波器的平滑程度。
二维高斯函数可以表示为:
其中,G(x, y)表示二维高斯函数在点(x, y)处的值,σ表示标准差。
对于图像中的每个像素,应用高斯滤波器可以通过以下卷积操作实现:
I' = G * I
其中,I'表示滤波后的图像,G表示高斯滤波器核,I表示原始图像。
具体而言,对于每个像素点,将高斯滤波器核与以该像素为中心的邻域进行卷积操作,计算邻域内像素值的加权平均值,作为该像素在滤波后图像中的值。通过这种方式,高斯滤波器可以模糊图像并减少噪声的影响。
需要注意的是,高斯滤波器的大小和标准差需要根据具体的应用场景进行选择。较大的滤波器大小和较小的标准差可以提供更强的平滑效果,但可能会导致边缘信息的模糊。相反,较小的滤波器大小和较大的标准差可以保留更多细节,但可能无法有效抑制噪声。
二维高斯滤波器的标准差σ在水平和垂直方向上是相等的,以保持滤波器的各向同性。选择合适的标准差取决于噪声水平和图像特性,较大的标准差可以提供更强的平滑效果,但可能会模糊边缘和细节。
2. 使用Sobel算子计算像素梯度
Sobel算子是一种常用的离散微分算子,它可以计算图像中每个像素点的梯度强度和方向。在Canny边缘检测中,通常使用Sobel算子来计算图像在水平和垂直方向上的梯度。
对于灰度图像,我们可以通过以下Sobel算子来计算像素的梯度:
水平方向的梯度(Gx):
-1 0 1
Gx = -2 0 2
-1 0 1
垂直方向的梯度(Gy):
-1 -2 -1
Gy = 0 0 0
1 2 1
下面是使用Sobel算子计算像素梯度的具体步骤:
-
将图像转换为灰度图像(如果不是灰度图像)。
-
对图像应用水平方向的Sobel算子(Gx)和垂直方向的Sobel算子(Gy)。
-
计算每个像素的梯度强度和方向:
G = sqrt(Gx^2 + Gy^2) (梯度强度) θ = arctan(Gy / Gx) (梯度方向)
其中,G表示梯度强度,θ表示梯度方向。
这样,我们就可以得到图像中每个像素的梯度强度和方向。这些梯度信息将在Canny边缘检测算法的后续步骤中使用,以检测和连接边缘。
3. 非极大值像素梯度抑制
在该步骤中,我们需要检查每个像素点的梯度方向上的相邻像素,并保留梯度强度最大的像素,将其他像素抑制为零。
为了更好地描述非极大值抑制的过程,我们将假设图像的梯度方向离散化为四个主要方向:0°(水平方向)、45°(对角线方向)、90°(垂直方向)和135°(对角线方向)。对于每个像素点,我们比较其梯度强度与沿着梯度方向的两个相邻像素的梯度强度。
如果像素点的梯度方向是0°(水平方向),我们比较其梯度强度与其左右两个相邻像素的梯度强度。
假设当前像素点为(x,y),其梯度方向为0°,梯度强度为G(x, y)。我们比较G(x, y)与两个相邻像素的梯度强度:G(x-1, y)和G(x+1, y)。
- 如果G(x, y)是三个值中最大的,我们保留该像素值,否则将其抑制为零。
具体而言,我们使用线性插值来判断是否保留像素值。如果G(x, y)介于G(x-1, y)和G(x+1, y)之间,那么我们通过线性插值计算相应的权重w:
最终,我们保留像素值的条件是:
根据具体的图像数据和梯度方向,上述过程将分别应用于其他方向(45°、90°和135°)。
4. 阈值滞后处理
完成上述步骤后,图像内的强边缘已经在当前获取的边缘图像内。但是,一些虚边缘可能也在边缘图像内。这些虚边缘可能是真实图像产生的,也可能是由于噪声所产生的。对于后者,必须将其剔除。
在这一步骤中,我们使用双阈值处理来确定边缘的强度。
- 首先,根据设定的高阈值和低阈值,将梯度强度图像的像素分为三类:强边缘、弱边缘和非边缘。
- 强边缘像素的梯度强度高于高阈值,
- 非边缘像素的梯度强度低于低阈值,
- 弱边缘像素的梯度强度在两个阈值之间。
5. 边缘连接
在最后一步中,通过边缘连接算法来连接强边缘像素和与之相邻的弱边缘像素,以形成完整的边缘。通常,如果一个弱边缘像素与至少一个强边缘像素相邻,那么它将被认为是边缘的一部分。这个过程可以通过递归或迭代实现。
程序流程图
图片链接: https://pic4.zhimg.com/80/v2-7400b8669ef4c750aeff27ed699ba7c7_720w.webp
Canny 函数及使用
OpenCV 提供了函数 cv2.Canny()来实现 Canny 边缘检测,其语法形式如下:
edges = cv.Canny( image, threshold1, threshold2[, apertureSize[, L2gradient]])
其中:
- edges 为计算得到的边缘图像。
- image 为 8 位输入图像。
- threshold1 表示处理过程中的第一个阈值。
- threshold2 表示处理过程中的第二个阈值。
- apertureSize 表示 Sobel 算子的孔径大小。
- L2gradient 为计算图像梯度幅度(gradient magnitude)的标识。其默认值为 False。如果为 True,则使用更精确的 L2 范数进行计算(即两个方向的导数的平方和再开方),否则使用 L1 范数(直接将两个方向导数的绝对值相加)。
示例:
使用函数 cv2.Canny()获取图像的边缘,并尝试使用不同大小的 threshold1 和threshold2。
import cv2
o=cv2.imread("lena.bmp",cv2.IMREAD_GRAYSCALE)
r1=cv2.Canny(o,128,200)
r2=cv2.Canny(o,32,128)
cv2.imshow("original",o)
cv2.imshow("result1",r1)
cv2.imshow("result2",r2)
cv2.waitKey()
cv2.destroyAllWindows()
运行结果: 文章来源:https://www.toymoban.com/news/detail-854513.html
从程序运行结果可知,当函数 cv2.Canny()的参数 threshold1 和 threshold2 的值较小时,能够捕获更多的边缘信息。 文章来源地址https://www.toymoban.com/news/detail-854513.html
到了这里,关于OpenCV——Canny边缘检测算法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!