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

news/2024/11/30 0:47:03/

在这里插入图片描述

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

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

  • 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图片放在文章中,大家可以下载然后重命名:
在这里插入图片描述
案例是为了论证一个知识点,请先看代码和运行结果,我再讲这个知识点:

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()
图像处理算法 | 高斯滤波


http://www.ppmy.cn/news/1551049.html

相关文章

docker搭建socks5代理

准备工作 VPS安全组/策略放行相应端口如启用了防火墙&#xff0c;放行相应端口 实际操作 我们选用“历史悠久”的Dante socks5 代理服务器&#xff0c;轻量、稳定。Github也有对dante进行进一步精简的镜像&#xff0c;更为适宜。github项目地址如下&#xff1a; https://gi…

中科亿海微SoM模组——波控处理软硬一体解决方案

本文介绍的波控处理软硬一体解决方案主要是面向相控阵天线控制领域&#xff0c;波控处理通过控制不同天线组件的幅相来调整天线波束的方向和增益&#xff0c;实现高精度角度控制和高增益。本方案由波控处理板、波控处理控制软件算法和上位机软件共同构成。波控处理SoM模组原型样…

mongodb文档字符串批量替换

【mongodb文档字符串批量替换脚本语句】 前言&#xff1a; 1、本方式对于数据量大的情况不适用&#xff0c;执行可能比较慢&#xff1b; 2、数据量大的情况&#xff0c;个人推荐代码层面解决&#xff0c;多线程替换更快&#xff1a; &#xff08;1&#xff09;写实体类的方式…

追加docker已运行容器添加或修改端口映射方法

docker run可以指定端口映射 【】docker run -d -p 80:80 --name name 但是容器一旦生成&#xff0c;就没有一个命令可以直接修改。通常间接的办法是&#xff0c;保存镜像&#xff0c;再创建一个新的容器&#xff0c;在创建时指定新的端口映射。 【】 docker stop A 【】 doc…

docker镜像、容器、仓库介绍

docker docker介绍docker镜像命令docker容器命令docker仓库 docker介绍 官网 Docker 是一种开源的容器化平台&#xff0c;用于开发、部署和运行应用。它通过将应用程序及其依赖项打包到称为“容器”的单一包中&#xff0c;使得应用能够在任何环境下运行&#xff0c;不受底层系…

量化交易系统开发-实时行情自动化交易-4.5.1.机器学习策略实现

19年创业做过一年的量化交易但没有成功&#xff0c;作为交易系统的开发人员积累了一些经验&#xff0c;最近想重新研究交易系统&#xff0c;一边整理一边写出来一些思考供大家参考&#xff0c;也希望跟做量化的朋友有更多的交流和合作。 接下来继续说说机器学习策略实现。 机…

[js] 函数柯里化

面试题&#xff1a;实现一个add方法&#xff0c;使计算结果能够满足如下预期&#xff1a; add(1)(2)(3) 6; add(1, 2, 3)(4) 10; add(1)(2)(3)(4)(5) 15; // 保存不定长参数 let nums []; function add(...args) { // 往数组中插入不定长参数nums.push(...args)// 判断参数…

Hive 函数(实例操作版2)

数据脱敏函数 -- 演示数据脱敏函数 -- mask_hash: 返回指定字符串的hash编码 select mask_hash(binzi);-- 拓展 --将查询回的数据&#xff0c;大写字母转换为X&#xff0c;小写字母转换为x&#xff0c;数字转换为n。 select mask("abc123DEF"); -- xxxnnnXXX--自定…