当前位置: 首页 > news >正文

传统CV算法——边缘检测算法Canny算法实战

Canny 算法

边缘:我的理解是在图像处理的过程中,针对我们图像处理的过程中,梯度变化以较大的地方能够让我们能够快速辨识,针对一个人脸,脸上有一些平滑的地方(没错我针对美颜的),与头发的接壤处,会让我们清楚的意识到这个人脸的大小形状等特征。通过线条我们能够很清晰的辨认一个人的特征,因此,图像边缘是图像处理之中很简单的任务之一。

Canny 边缘检测算法是一种广泛使用的边缘检测技术,由 John F. Canny 在 1986 年提出。它被认为是最优的边缘检测算法之一,因其在检测边缘时具有较好的准确性和低噪声敏感性。Canny 算法的主要目标是识别图像中的边缘,并提供精确的边缘定位。

Canny 算法的步骤

Canny 边缘检测算法是一种多阶段的边缘检测方法,其数学原理主要包括以下几个步骤:

1. 高斯平滑

在进行边缘检测之前,首先需要对图像进行平滑处理,以减少噪声的影响。Canny 算法使用高斯滤波器来实现这一点。高斯滤波器的数学表达式为:

G ( x , y ) = 1 2 π σ 2 e − x 2 + y 2 2 σ 2 G(x, y) = \frac{1}{2\pi\sigma^2} e^{-\frac{x^2 + y^2}{2\sigma^2}} G(x,y)=2πσ21e2σ2x2+y2

其中, σ \sigma σ 是高斯分布的标准差, ( x , y ) (x, y) (x,y) 是相对于滤波器中心的坐标。通过卷积操作,将高斯滤波器应用于输入图像,得到平滑后的图像。

2. 计算梯度

接下来,使用 Sobel 算子或其他梯度算子计算图像中每个像素的梯度强度和方向。Sobel 算子通常有两个方向的卷积核:

  • 水平方向( G x G_x Gx):
    G x = [ − 1 0 1 − 2 0 2 − 1 0 1 ] G_x = \begin{bmatrix} -1 & 0 & 1 \\ -2 & 0 & 2 \\ -1 & 0 & 1 \end{bmatrix} Gx= 121000121

  • 垂直方向( G y G_y Gy):
    G y = [ 1 2 1 0 0 0 − 1 − 2 − 1 ] G_y = \begin{bmatrix} 1 & 2 & 1 \\ 0 & 0 & 0 \\ -1 & -2 & -1 \end{bmatrix} Gy= 101202101

通过卷积操作,计算每个像素的梯度强度 G G G 和方向 θ \theta θ

G = G x 2 + G y 2 G = \sqrt{G_x^2 + G_y^2} G=Gx2+Gy2

θ = arctan ⁡ ( G y G x ) \theta = \arctan\left(\frac{G_y}{G_x}\right) θ=arctan(GxGy)

3. 非极大值抑制

在计算出梯度强度和方向后,Canny 算法会进行非极大值抑制,以细化边缘。对于每个像素,算法会检查其梯度强度是否为局部最大值。具体步骤如下:

  • 根据梯度方向,将像素分为四个方向( 0 ∘ 0^\circ 0 4 5 ∘ 45^\circ 45 9 0 ∘ 90^\circ 90 13 5 ∘ 135^\circ 135)。
  • 对于每个像素,检查其在梯度方向上的前后两个像素的强度值。
  • 如果当前像素的强度值不是局部最大值,则将其强度设为零。

4. 双阈值处理

Canny 算法使用双阈值处理来确定强边缘和弱边缘。设定两个阈值(高阈值和低阈值):

  • 强边缘:梯度强度高于高阈值的像素。
  • 弱边缘:梯度强度介于低阈值和高阈值之间的像素。
  • 非边缘:梯度强度低于低阈值的像素。

5. 边缘连接

最后,Canny 算法通过连接强边缘和弱边缘来形成最终的边缘图。只有与强边缘相连的弱边缘才会被保留,其他的弱边缘将被抑制。这一过程确保了边缘的连续性。

Canny 边缘检测算法的数学原理结合了高斯平滑、梯度计算、非极大值抑制、双阈值处理和边缘连接等多个步骤。通过这些步骤,Canny 算法能够有效地检测图像中的边缘,并提供较高的准确性和鲁棒性。

Canny 算法的优点

  • 高精度:Canny 算法能够准确地检测到边缘,并且对噪声具有较强的鲁棒性。
  • 多级阈值:通过双阈值处理,可以有效地分离强边缘和弱边缘,增强边缘的连通性。
  • 细化边缘:非极大值抑制步骤使得边缘更加细化,减少了边缘的宽度。

Canny 算法的缺点

  • 计算复杂度:相较于其他简单的边缘检测算法(如 Roberts、Sobel),Canny 算法的计算复杂度较高,处理速度较慢。
  • 参数选择:高斯滤波器的标准差和双阈值的选择对结果有较大影响,可能需要根据具体应用进行调整。

应用场景

Canny 边缘检测算法广泛应用于计算机视觉和图像处理领域,包括但不限于:

  • 物体检测与识别
  • 图像分割
  • 特征提取
  • 机器人视觉
  • 医学图像分析

总之,Canny 边缘检测算法因其高效性和准确性,成为了边缘检测领域的经典算法之一。

Canny算法步骤

  • 去燥(常用高斯滤波)

任何边缘检测算法都不可能在未经处理的原始数据上很好地工作,使用高斯滤波可以去除常见的噪声。

g σ ( m , n ) = 1 2 π σ 2 e − m 2 + n 2 2 σ 2 ⋅ f ( m , n ) g_\sigma(m, n)=\frac{1}{\sqrt{2 \pi \sigma^2}} e^{-\frac{m^2+n^2}{2 \sigma^2}} \cdot f(m, n) gσ(m,n)=2πσ2 1e2σ2m2+n2f(m,n)

・计算梯度大小和方向
梯度的大小和方向往往可以反应图像灰度值的变化和方向, 可以通过点乘一个sobel或其它算子得到不同方向的梯度值。
常见的梯度算子:canny算子,sobel算子,拉普拉斯算子
・沿着梯度方向进行非极大值抑制

  • 双边阈值处理
  • 低于低阈值的舍弃, 高于阈值的确定为边缘, 在中间的如果与边缘相连接保留,否则舍去。

cv2.Canny 是 OpenCV 中用于执行 Canny 边缘检测的函数。该函数的主要作用是检测图像中的边缘,并返回一个二值图像,其中边缘像素为白色(255),非边缘像素为黑色(0)。

函数原型

edges = cv2.Canny(image, threshold1, threshold2, apertureSize=3, L2gradient=False)

参数说明

  1. image (numpy.ndarray):

    • 描述:输入图像,通常是一个灰度图像。Canny 边缘检测算法通常在灰度图像上运行,因此如果输入是彩色图像,需要先将其转换为灰度图像。
  2. threshold1 (int):

    • 描述:低阈值,用于边缘连接的第一阈值。该值用于确定强边缘和弱边缘的分界。梯度强度低于此值的像素被认为是非边缘。
  3. threshold2 (int):

    • 描述:高阈值,用于边缘连接的第二阈值。该值用于确定强边缘的分界。梯度强度高于此值的像素被认为是强边缘。
  4. apertureSize (int, 可选):

    • 描述:Sobel 算子的大小,默认为 3。该参数决定了用于计算图像梯度的 Sobel 算子的大小。可以设置为 1、3、5 或 7。较大的值会导致更平滑的边缘,但可能会丢失一些细节。
  5. L2gradient (bool, 可选):

    • 描述:是否使用更精确的 L2 范数来计算梯度。默认为 False,表示使用 L1 范数。如果设置为 True,则使用 L2 范数,这样可以获得更精确的边缘检测结果。

返回值

  • edges (numpy.ndarray):
    • 返回一个二值图像,其中边缘像素为白色(255),非边缘像素为黑色(0)。

cv2.Canny 函数是实现 Canny 边缘检测的主要工具,通过合理设置阈值和其他参数,可以有效地检测图像中的边缘特征。选择合适的阈值和参数对于获得最佳的边缘检测效果至关重要。

import cv2img = cv2.imread("./images/25.jpg",cv2.IMREAD_COLOR)cv2.imshow("canny",img)img = cv2.convertScaleAbs(img,alpha=6,beta=0)cv2.imshow("abs",img)
# 高斯滤波
img = cv2.GaussianBlur(img,(5,5),1)canny = cv2.Canny(img,100,150)canny = cv2.resize(canny,(500,500))
cv2.imshow("Canny",canny)
cv2.waitKey(0)

在这里插入图片描述

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 艾体宝洞察丨透过语义缓存,实现更快、更智能的LLM应用程序
  • ESD防静电监控系统助力电子制造行业转型升级
  • cesium加载在线3dtiles
  • PS插件DR5至臻高级版下载安装教程Photoshop美颜美白牙齿磨皮使用插件百度网盘分享
  • 2024Java基础总结+【Java数据结构】(1)
  • 【python】—— Python爬虫实战:爬取珠海市2011-2023年天气数据并保存为CSV文件
  • 初始MYSQL数据库(2)——创建、查询、更新、删除数据表的相关操作
  • Django + websocket 连不上
  • 深度学习(一)-感知机+神经网络+激活函数
  • 解锁京东商品详情宝库:开发者必备API利器与实战应用指南
  • C#自定义控件的放置与拖动
  • 使用Unity的准备
  • CSP-S 2022 提高级 第一轮 阅读程序(3)
  • webCppCluster
  • Matlab实现MPC算法
  • IDEA 插件开发入门教程
  • JAVA 学习IO流
  • JavaScript 无符号位移运算符 三个大于号 的使用方法
  • JS笔记四:作用域、变量(函数)提升
  • react 代码优化(一) ——事件处理
  • SpiderData 2019年2月23日 DApp数据排行榜
  • SQLServer之创建数据库快照
  • vue从创建到完整的饿了么(18)购物车详细信息的展示与删除
  • Vue组件定义
  • 创建一种深思熟虑的文化
  • 浮现式设计
  • 技术:超级实用的电脑小技巧
  • 模仿 Go Sort 排序接口实现的自定义排序
  • 微信小程序上拉加载:onReachBottom详解+设置触发距离
  • 我的面试准备过程--容器(更新中)
  • 一份游戏开发学习路线
  • 正则表达式小结
  • 好程序员web前端教程分享CSS不同元素margin的计算 ...
  • 好程序员大数据教程Hadoop全分布安装(非HA)
  • # 利刃出鞘_Tomcat 核心原理解析(八)-- Tomcat 集群
  • #HarmonyOS:软件安装window和mac预览Hello World
  • #宝哥教你#查看jquery绑定的事件函数
  • (1)(1.8) MSP(MultiWii 串行协议)(4.1 版)
  • (1)(1.9) MSP (version 4.2)
  • (52)只出现一次的数字III
  • (6) 深入探索Python-Pandas库的核心数据结构:DataFrame全面解析
  • (Arcgis)Python编程批量将HDF5文件转换为TIFF格式并应用地理转换和投影信息
  • (二)什么是Vite——Vite 和 Webpack 区别(冷启动)
  • (附源码)springboot家庭装修管理系统 毕业设计 613205
  • (算法二)滑动窗口
  • (小白学Java)Java简介和基本配置
  • (学习总结16)C++模版2
  • (一)使用Mybatis实现在student数据库中插入一个学生信息
  • .NET CORE 3.1 集成JWT鉴权和授权2
  • .net core docker部署教程和细节问题
  • .Net Core与存储过程(一)
  • .NET 将多个程序集合并成单一程序集的 4+3 种方法
  • .net 怎么循环得到数组里的值_关于js数组
  • .net 中viewstate的原理和使用
  • .NetCore实践篇:分布式监控Zipkin持久化之殇