深入解析 Canny 边缘检测:原理、步骤与实践应用全攻略

摘要:本文全面且深入地探讨了 Canny 边缘检测。详细阐述了其包括去噪(重点分析高斯核选取及不同大小核的影响)、计算梯度、非极大值抑制、双阈值确定边缘等核心步骤,并结合实际案例与代码(如使用 cv2.Canny 对 pig.JPG 图片处理)展示其在不同阈值设置下的效果差异及原因,助力读者深入理解并掌握 Canny 边缘检测技术在图像处理领域的应用要点与原理精髓。

如果你觉得本文对你有帮助,请点赞收藏关注,我会持续创作更多跟OpenCV相关的文章

深入解析 Canny 边缘检测:原理、步骤与实践应用全攻略

Canny边缘检测步骤

第一步:去噪

一般是使用高斯滤波,高斯滤波的特点是靠近中心的权值比较大,远离的权值较小。平滑一些纹理较弱的非轮廓区域,我用画图板给大家画一个例子,使用高斯滤波核对下面这张图的红色像素点进行计算:

高斯卷积核的如下:

两个矩阵乘法/56 = 138.

核越大对于噪声的敏感度就越低,通常来说5x5的核足以满足大多数情况

因为边缘的方向是由切向量来定义的,所以梯度的方向与边缘的方向垂直。

高斯核的选取

小核的局限性:小高斯核(如 3x3)在抑制噪声方面的能力相对较弱。虽然它能够较好地保留图像的细节和边缘的精确位置,但在实际应用中,很多图像都含有一定程度的噪声。如果噪声没有得到有效抑制,就会在边缘检测过程中产生大量的伪边缘。这些伪边缘会干扰真正边缘信息的提取,导致边缘检测结果不准确。

用 5x5 的高斯核可以在一定程度上有效地平滑图像,减少噪声的影响。例如,在一幅含有椒盐噪声(图像上随机出现的黑白像素点)的图像中,5x5 的高斯核能够将这些噪声点周围的像素值进行加权平均,使得噪声引起的像素值突变得到缓解。这样,在后续的边缘检测步骤(如计算梯度幅值和方向)中,就不容易因为噪声的干扰而错误地检测出边缘。

高斯核越大,边缘信息对于噪声的敏感度就越低,核越大定位错误也会增加。

虽然较大的高斯核(如 5x5)可能会导致边缘定位出现一些误差,但在很多实际应用场景中,这种误差是可以接受的。因为边缘检测的主要目的通常是获取物体的大致轮廓,而不是精确到像素级别的边缘位置。例如,在一个工业零件检测的场景中,只需要知道零件的大致边缘位置来判断其形状是否符合标准,少量的边缘定位误差不会对整体的检测结果产生重大影响。

相比于小核可能产生的大量伪边缘,大核导致的边缘定位错误相对来说是次要的。如果使用小核,大量的伪边缘会使得后续的边缘连接、轮廓提取等操作变得非常复杂,甚至无法准确地获取物体的完整轮廓。而使用 5x5 的核可以在减少伪边缘的同时,虽然会有一定的定位错误,但仍然能够提供相对清晰和准确的边缘轮廓。

第二步:计算梯度

G = (Gx^2 +Gy ^2)**(1/2)

方向 = arctan2(Gy,Gx)

梯度的方向与边缘垂直,就近取值为(左右上下、左上 左下 右上右下)八种,因此在计算梯度的时候,我们会得到角度和梯度两个值,请看下图:

第三步:非极大值抑制

获得梯度的幅度和方向以后,遍历所有像素点,去掉所有非边缘的点,判断当前仙姑私单是否式周围中具有相同梯度方向的最大值,如果不是最大值就抑制该点。通过非极大值抑制实现边缘细化的目的

第四步:双阈值确定边缘

第四步又分为两小步;

第一步:设置两个阈值 max min 如果梯度>= max那么标记为强边缘,如果在 max>梯度>min,那么标记为弱边缘,如果梯度<min,那么直接删去

第二步:遍历弱边缘,若与强边缘有连接,那么确定为边缘,没连接删去

语法与案例

语法

edges = cv2.Canny(待处理8位输入图像image ,阈值1 threshold1,阈值2 threshold2,图像梯度幅度L2gradient 默认为False计算速度快,他的图像梯度是二者绝对值之和,而设置为True就是G = (Gx^2 +Gy ^2)**(1/2),这样计算的更为准确)

我使用的是jupyter notebook,我项目的文件结构是这样的,我将对pig.JPG图片进行处理,如果你使用的是pycharm,将图片和代码放在同一个文件夹下就好了:

我把我的pig.JPG图片放在文章中,大家可以下载然后重命名:

案例是为了论证一个知识点,请先看代码和运行结果,我再讲这个知识点:

python 复制代码
import numpy as np
import cv2
pig = cv2.imread("pig.JPG")
img1 = cv2.Canny(pig,128,200)
img2 = cv2.Canny(pig,32,128)
cv2.imshow("original",pig)
cv2.imshow("128-200",img1)
cv2.imshow("32-128",img2)
cv2.waitKey()
cv2.destroyAllWindows()

在上面这个运行结果可以看出,阈值低的部分可以选择出更多边缘细节。

原因如下:当低阈值较小时,更多的像素梯度幅值能够大于低阈值,这就使得更多的像素有机会被标记为弱边缘像素或者强边缘像素。

例如,在一个包含一些微弱边缘的图像中,较低的低阈值可以让这些微弱边缘对应的像素梯度幅值超过低阈值,从而被考虑进入边缘检测的后续流程。

对于后续的边缘连接等操作,这些被标记为弱边缘的像素有机会与强边缘像素连接起来,最终形成完整的边缘。因为在边缘连接阶段,一些弱边缘像素如果与强边缘像素相邻或者在一定的连接规则下,它们会被判定为边缘的一部分,从而增加了边缘的完整性,捕获到更多的边缘信息。

致谢

本文参考了一些博主的文章,博取了他们的长处,也结合了我的一些经验,对他们表达诚挚的感谢,使我对 Canny边缘检测 有更深入的了解,也推荐大家去阅读一下他们的文章。纸上学来终觉浅,明知此事要躬行:
opencv基础44- Canny边缘检测详解-cv.Canny()
图像处理算法 | 高斯滤波

相关推荐
一只小灿灿2 小时前
前端计算机视觉:使用 OpenCV.js 在浏览器中实现图像处理
前端·opencv·计算机视觉
一起搞IT吧4 小时前
相机Camera日志实例分析之五:相机Camx【萌拍闪光灯后置拍照】单帧流程日志详解
android·图像处理·数码相机
看到我,请让我去学习17 小时前
OpenCV编程- (图像基础处理:噪声、滤波、直方图与边缘检测)
c语言·c++·人工智能·opencv·计算机视觉
蹦蹦跳跳真可爱5891 天前
Python----OpenCV(图像増强——高通滤波(索贝尔算子、沙尔算子、拉普拉斯算子),图像浮雕与特效处理)
人工智能·python·opencv·计算机视觉
PyAIExplorer2 天前
图像处理中的插值方法:原理与实践
图像处理·人工智能
彭祥.2 天前
Jetson边缘计算主板:Ubuntu 环境配置 CUDA 与 cudNN 推理环境 + OpenCV 与 C++ 进行目标分类
c++·opencv·分类
超龄超能程序猿2 天前
(三)PS识别:基于噪声分析PS识别的技术实现
图像处理·人工智能·计算机视觉
Tony沈哲2 天前
macOS 上为 Compose Desktop 构建跨架构图像处理 dylib:OpenCV + libraw + libheif 实践指南
opencv·算法
加油吧zkf2 天前
AI大模型如何重塑软件开发流程?——结合目标检测的深度实践与代码示例
开发语言·图像处理·人工智能·python·yolo
视觉人机器视觉3 天前
Visual Studio2022和C++opencv的配置保姆级教程
c++·opencv·visual studio