使用opencv的Canny算子实现图像边缘检测

 

1 边缘检测介绍

图像边缘检测技术是图像处理和计算机视觉等领域最基本的问题,也是经典的技术难题之一。如何快速、精确地提取图像边缘信息,一直是国内外的研究热点,同时边缘的检测也是图像处理中的一个难题。早期的经典算法包括边缘算子方法、曲面拟合的方法、模板匹配方法、阈值法等。

近年来,随着数学理论与人工智能技术的发展,出现了许多新的边缘检测方法,如Roberts、Laplacan、Canny等图像的边缘检测方法。这些方法的应用对于高水平的特征提取、特征描述、目标识别和图像理解有重大的影响。然而,在成像处理的过程中投影、混合、失真和噪声等会导致图像模糊和变形,这使得人们一直致力于构造具有良好特性的边缘检测算子。

1.1 什么是边缘检测

边缘检测是图像处理和计算机视觉中的基本问题,边缘检测的目的是标识数字图像中亮度变化明显的点。图像属性中的显著变化通常反映了属性的重要事件和变化,包括深度不连续、表面方向不连续、物质属性变化和场景照明变化。边缘检测特征是提取中的一个研究领域。图像边缘检测大幅度地减少了数据量,并且剔除了可以认为不相关的信息,保留了图像重要的结构属性。

ba30c8c30a4f4769b79dce231980dfc9.png

1.2 边缘检测的方法

人类视觉系统认识目标的过程分为两步:首先,把图像边缘与背景分离出来;然后,到图像的细节,辨认出图像的轮廓。计算机视觉正是模仿人类视觉的过程。

因此,在检测物体边缘时先对轮廓点进行粗略检测,然后通过链接规则把原来检测到的轮廓点连接起来,同时检测和连接遗漏的边界点及去除虚假的边界点。图像的边缘是图像的重要特征,是计算机视觉、模式识别等的基础,因此边缘检测是图像处理中一个重要的环节。然而,边缘检测是图像处理中的一个难题,因为实际景物图像的边缘往往是各种类型的边缘及它们模糊化后结果的组合,且实际图像信号存在噪声。噪声和边缘都属于高频信号,很难用频带做取舍。

边缘是指图像周围像素灰度有阶跃变化或屋顶状变化的像素集合,存在于目标与背景、目标与目标、区域与区域、基元与基元之间。边缘具有方向和幅度两个特征,沿边缘走向,像素值变化比较平缓;垂直于边缘走向,像素值变化比较剧烈,可能呈现阶跃状,也可能呈现斜坡状。因此,边缘可以分为两种:

  • 一种为阶跃性边缘,两边的像素灰度值有着明显的不同;

  • 另一种为屋顶状边缘,位于灰度值从增加到减少的变化转折点。

对于阶跃性边缘,二阶方向导数在边缘处呈零交叉;对于屋顶状边缘,二阶方向导数在边缘处取极值。有许多方法可以用于边缘检测,绝大部分可以划分为两类:基于搜索的一类和基于零穿越的一类。

  • 基于搜索:通过寻找图像一阶导数中的最大值来检测边界,然后利用计算结果估计边缘的局部方向,通常采用梯度的方向,并利用此方向找到局部梯度模的最大值,代表算法是Sobel算子和Scharr算子。

ee342b69286545f89d6153c9d55bde58.png

  • 基于零穿越:通过寻找图像二阶导数零穿越来寻找边界,代表算法是Laplacian算子。

91276000e2b84fd49624342fac4045ee.png

1.3 典型算子比较

算子优缺点
Roberts对具有陡峭的低噪声的图像处理效果较好,但利用Roberts算子提取边缘的结果是边缘比较粗,因此边缘定位不是很准确
Sobel对灰度渐变和噪声较多的图像处理效果比较好,Sobel算子对边缘定位比较准确
Kirsch对灰度渐变和噪声较多的图像处理效果较好
Prewitt 对灰度渐变和噪声较多的图像处理效果较好
Laplacian对图像中的阶跃性边缘点定位准确,对噪声非常敏感,丢失一部分边缘的方向信息,造成一些不连续的检测边缘
LoGLoG算子经常出现双边缘像素边界,而且该检测算法对噪声比较敏感,所以很少用LoG算子检测边缘,而是用来判断边缘像素是位于图像的明区还是暗区
Canny此方法不容易受噪声的干扰,能够检测到真正的弱边缘。在edge函数中,最有效的边缘检测方法是Canny方法。该方法的优点在于使用两种不同的阈值分别检测强边缘和弱边缘,并且仅当弱边缘和强边缘相连时,才将弱边缘包含在输出图像中。因此,这种方法不容易被噪声”填充“,更容易检测出真正的弱边缘。

2 使用opencv的Canny算子实现边缘检测

Canny边缘检测是一种经典的边缘检测算法,由John F.在1986年提出。它被广泛应用于计算机视觉和图像处理领域,是一种多阶段的边缘检测算法,能够有效地检测图像中的边缘并抑制噪声,得到清晰准确的边缘信息,并且对噪声具有一定的鲁棒性。Canny被认为是最优的边缘检测算法。

2.1 检测原理

2.1.1 应用高斯滤波去除图像噪声

由于图像边缘非常容易受到噪声的干扰,因此为了避免检测到错误的边缘信息,通常需要对图像进行滤波以去除噪声。滤波的目的是平滑一些纹理较弱的非边缘区域,以便得到更准确的边缘。在实际处理过程中,通常采用高斯滤波去除图像中的噪声。

图 10-1 演示了使用高斯滤波器 T 对原始图像 O 中像素值为 226 的像素点进行滤波,得到该点在滤波结果图像 D 内的值的过程。

3e8861d555544853a5a73a01e90689e9.png

在滤波过程中,我们通过滤波器对像素点周围的像素计算加权平均值,获取最终滤波结果。对于高斯滤波器 T,越临近中心的点,权值越大。在图 10-1 中,对图像 O 中像素值为 226 的像素点,使用滤波器 T 进行滤波的计算过程及结果为:

结果 = 156×(197×1+25×1+106×2+156×1+159×1+149×1+40×3+107×4+5×3+71×1+163×2+198×4+226×8+223×4+156×2+222×1+37×3+68×4+193×3+157×1+42×1+72×1+250×2+41×1+75×1)= 138

 当然,高斯滤波器(高斯核)并不是固定的,例如它还可以是:

0a6f73bb537a44faa86dd5b806c58934.png
滤波器的大小也是可变的,高斯核的大小对于边缘检测的效果具有很重要的作用。滤波器的核越大,边缘信息对于噪声的敏感度就越低。不过,核越大,边缘检测的定位错误也会随之增加。通常来说,一个 5×5 的核能够满足大多数的情况。

2.1.2 计算梯度幅值和方向

前面一节讲了如何计算图像梯度的幅度。在这里,我们关注梯度的方向,梯度的方向与边缘的方向是垂直的。

边缘检测算子返回水平方向的Gx和垂直方向的Gy。梯度的幅度𝐺和方向𝛩(用角度值表示)为:

4727f5e6240a40dd94fe5ec6c59d2ce0.png

e672aca992c243778bd6af160e74e330.png

如果某个像素点是边缘,则其梯度方向总是垂直与边缘垂直。梯度方向被归为四类:垂直,水平,和两个对角线方向。

因此,在计算梯度时,我们会得到梯度的幅度和角度(代表梯度的方向)两个值。

图 10-2 展示了梯度的表示法。其中,每一个梯度包含幅度和角度两个不同的值。为了方便观察,这里使用了可视化表示方法。例如,左上角顶点的值“2↑”实际上表示的是一个二元数对“(2, 90)”,表示梯度的幅度为 2,角度为 90°。
493b6d6998914dd2a5a5e0a1042f127b.png

2.1.3 非极大值抑制

在获得了梯度的幅度和方向后,遍历图像中的像素点,去除所有非边缘的点。

在具体实现时,逐一遍历像素点,判断当前像素点是否是周围像素点中具有相同梯度方向的最大值,并根据判断结果决定是否抑制该点。

通过以上描述可知,该步骤是边缘细化的过程。针对每一个像素点:

  • 如果该点是正/负梯度方向上的局部最大值,则保留该点。

  • 如果不是,则抑制该点(归零)。

在图 10-3 中,A、B、C 三点具有相同的方向(梯度方向垂直于边缘)。判断这三个点是否为各自的局部最大值:如果是,则保留该点;否则,抑制该点(归零)。
1a5248863af24cbd97938b0d2478a9d7.png

经过比较判断可知,A 点具有最大的局部值,所以保留 A 点(称为边缘),其余两点(B和 C)被抑制(归零)。

在图 10-4 中,黑色背景的点都是向上方向梯度(水平边缘)的局部最大值。因此,这些点会被保留;其余点被抑制(处理为 0)。这意味着,这些黑色背景的点最终会被处理为边缘点,而其他点都被处理为非边缘点。
e34279f0fb5c444b8b1e98b73897c8d0.png

“正/负梯度方向上”是指相反方向的梯度方向。例如,在图 10-5 中,黑色背景的像素点都是垂直方向梯度(向上、向下)方向上(即水平边缘)的局部最大值。这些点最终会被处理为边缘点。

9e0057f6f0624bb692869bd66de87c3e.png

经过上述处理后,对于同一个方向的若干个边缘点,基本上仅保留了一个,因此实现了边缘细化的目的。

2.1.4 应用双阈值确定边缘

完成上述步骤后,图像内的强边缘已经在当前获取的边缘图像内。但是,一些虚边缘可能也在边缘图像内。这些虚边缘可能是真实图像产生的,也可能是由于噪声所产生的。对于后者,必须将其剔除。

设置两个阈值,其中一个为高阈值 maxVal,另一个为低阈值 minVal。根据当前边缘像素的梯度值(指的是梯度幅度,下同)与这两个阈值之间的关系,判断边缘的属性。具体步骤为:

  • 如果当前边缘像素的梯度值大于或等于 maxVal,则将当前边缘像素标记为强边缘。

  • 如果当前边缘像素的梯度值介于 maxVal 与 minVal 之间,则将当前边缘像素标记为虚边缘(需要保留)。

  • 如果当前边缘像素的梯度值小于或等于 minVal,则抑制当前边缘像素。

在上述过程中,我们得到了虚边缘,需要对其做进一步处理。一般通过判断虚边缘与强边
缘是否连接,来确定虚边缘到底属于哪种情况。通常情况下,如果一个虚边缘:

  • 与强边缘连接,则将该边缘处理为边缘。

  • 与强边缘无连接,则该边缘为弱边缘,将其抑制。

在图 10-6 中,左图显示的是三个边缘信息,右图是对边缘信息进行分类的示意图,具体划分如下:

  • A 点的梯度值值大于 maxVal,因此 A 是强边缘。

  • B 和 C 点的梯度值介于 maxVal 和 minVal 之间,因此 B、C 是虚边缘。

  • D 点的梯度值小于 minVal,因此 D 被抑制(抛弃)。

d784430883c84d0d81fcca9a179a9907.png

图 10-7 显示了对图 10-6 中的虚边缘 B 和 C 的处理结果。其中:

  • B 点的梯度值介于 maxVal 和 minVal 之间,是虚边缘,但该点与强边缘不相连,故将其抛弃。

  • C 点的梯度值介于 maxVal 和 minVal 之间,是虚边缘,但该点与强边缘 A 相连,故将其保留。

c4dd17db3da14d95a43dbd9912396eaa.png

注意,高阈值 maxVal 和低阈值 minVal 不是固定的,需要针对不同的图像进行定义。

10-8 给出了一个 Canny 边缘检测的效果图。

697ae07add454ada9b8dc6ed0bc88140.png

2.1.5 检测边缘连接

Canny边缘检测的边缘连接是指将非极大值抑制得到的边缘点连接成连续的边缘线。这个过程是Canny边缘检测算法中的最后一步,它的目的是去除由于非极大值抑制产生的间断的边缘点,从而得到更加准确和连续的边缘检测结果。

Canny边缘检测的边缘连接过程:

  • 遍历梯度幅值图像:首先,遍历经过非极大值抑制后的梯度幅值图像,即只有边缘上的像素点的梯度幅值被保留,其他像素点的梯度幅值为零。

  • 标记边缘点:对于每个强边缘像素点(梯度幅值大于高阈值),将其标记为边缘点。强边缘像素点是图像中梯度值较大的像素点,它们代表了图像中明显的边缘。

  • 边缘连接:对于每个边缘点的相邻像素点,如果其梯度幅值大于低阈值,并且没有被标记为边缘点,则将其标记为弱边缘点,并递归地进行边缘连接。这一步的目的是将与强边缘像素点相邻的弱边缘像素点连接到边缘线上。

  • 递归连接:在边缘连接过程中,如果某个弱边缘像素点被标记为边缘点,则会继续检查该像素点的相邻像素点,以便将所有与强边缘像素点相邻的弱边缘像素点连接到边缘线上。

  • 结束条件:边缘连接的递归过程会一直进行,直到所有与强边缘像素点相邻的弱边缘像素点都被标记为边缘点,没有更多的像素点可以连接。

  • 非边缘点处理:经过边缘连接后,所有未被标记为边缘点的像素点视为非边缘点,并抑制其梯度幅值为零,从而得到最终的边缘图像。

2.2 Canny函数原型

edges = cv.Canny( image, threshold1, threshold2[, apertureSize[, L2gradient]])

参数:

  • edges 为计算得到的边缘图像。

  • image 为 8 位输入图像。

  • threshold1 表示处理过程中的第一个阈值。

  • threshold2 表示处理过程中的第二个阈值。

  • apertureSize 表示 Sobel 算子的孔径大小。

  • L2gradient 为计算图像梯度幅度(gradient magnitude)的标识。其默认值为 False。如果为 True,则使用更精确的 L2 范数进行计算(即两个方向的导数的平方和再开方),否则使用 L1 范数(直接将两个方向导数的绝对值相加)。

 

2.3 检测代码

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt# 1 读取图像
img = cv.imread('../data/cat_dog.jpg')# 2 将图片由BGR转为RGB
img = cv.cvtColor(img, cv.COLOR_BGR2RGB)# 2 边缘检测,canny算子,阈值128-200,低于128的像素点认为是边缘,
# 高于200的像素点认为是边缘,中间值的像素点如果与边缘点相连则认为是边缘
edge = cv.Canny(img, 128, 200)# 3 图像显示
plt.figure(figsize=(10, 8), dpi=100)
plt.subplot(121), plt.imshow(img), plt.title('original')
plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(edge, cmap=plt.cm.gray), plt.title('Canny')
plt.xticks([]), plt.yticks([])
plt.show()

运行代码显示:

5009fa7d451d4101abdc43c6a4d50c70.png

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/225291.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【论文阅读】Uncertainty-aware Self-training for Text Classification with Few Label

论文下载 GitHub bib: INPROCEEDINGS{mukherjee-awadallah-2020-ust,title "Uncertainty-aware Self-training for Few-shot Text Classification",author "Subhabrata Mukherjee and Ahmed Hassan Awadallah",booktitle "NeurIPS",yea…

关于嵌入式开发的一些信息汇总:C标准、芯片架构、编译器、MISRA-C

关于嵌入式开发的一些信息汇总:C标准、芯片架构、编译器、MISRA-C 关于C标准芯片架构是什么?架构对芯片有什么作用?arm架构X86架构mips架构小结 编译器LLVM是什么?前端在干什么?后端在干什么? MISRA C的诞生…

​LeetCode解法汇总1631. 最小体力消耗路径

目录链接: 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目: https://github.com/September26/java-algorithms 原题链接: 力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 描述: 你准备参…

【Linux】使用官方脚本自动安装 Docker(Ubuntu 22.04)

前言 Docker是一种开源平台,用于开发、交付和运行应用程序。它利用了容器化技术,使开发人员能够将应用程序及其依赖项打包到一个称为Docker容器的可移植容器中。这些容器可以在任何运行Docker的机器上快速、一致地运行,无论是开发环境、测试…

make没有更新最新的uImage

在 LCD 驱动的时候发现,linux logo一直弄不出来,猜想可能是因为uImage的问题,就看了一眼 uImage 时间: ​ 我现在的时间是 ,那可能就是没有更新make的时候没有更新,就上网搜了一下用下面的命令输出 uImage&…

数据结构(七):树介绍及面试常考算法

一、树介绍 1、定义 树形结构是一种层级式的数据结构,由顶点(节点)和连接它们的边组成。 树类似于图,但区分树和图的重要特征是树中不存在环路。树有以下特点: (1)每个节点有零个或多个子节点…

为什么 GAN 不好训练

为什么 GAN 不好训练?先看 GAN 的损失: 当生成器固定时,堆D(x)求导,推理得到(加号右边先对log求导,再对负项求导) 然后在面对最优Discriminator时,Generator的优化目标就变成了&…

微积分-三角函数2

三角函数 在上一节中,讨论了如何在直角三角形中定义三角函数,限制让我们扩展三角函数的定义域。 事实上我们可以取任意角的正弦和余弦,而不只是局限于 0 0 0~ π 2 \frac{\pi}{2} 2π​当中。 当然需要注意的是,正切函数对不是对…

指数分布的随机变量

如果连续型随机变量的概率密度满足如下条件: 其中为常数,那么就称服从参数为的指数分布。 指数分布的重要性质---无记忆性:

数据结构(7.5)-- 树扩展之字典树

一、字典树 1、字典树介绍 字典树,也称为“前缀树”,是一种特殊的树状数据结构,对于解决字符串相关问题非常有效。典型 用于统计、排序、和保存大量字符串。所以经常被搜索引擎系统用于文本词频统计。它的优点是: 利用字符串的…

(1)(1.8) MSP(MultiWii 串行协议)(4.1 版)

文章目录 前言 1 协议概述 2 配置 3 参数说明 前言 ArduPilot 支持 MSP 协议,可通过任何串行端口进行遥测和传感器。这允许 ArduPilot 将其遥测数据发送到 MSP 兼容设备(如大疆护目镜),用于屏幕显示(OSD&#xff…

VR智慧眼:为各行业打造3D数字化业务协同平台

自改革开放以来,城镇化建设一直在不断推进实施,如今各城市化速度虽然在不断加快,但随之而来的部分城市开始出现资源短缺、环境污染、交通拥堵、安全隐患等问题,因此为了满足智慧城市大型区域场景数字化升级需求,助力区…

【深入浅出SpringCloud源码探究】「Netflix系列之Ribbon+Fegin」微服务化的负载均衡组件源码剖析与实战开发全流程(Ribbon篇)

微服务化的负载均衡组件源码剖析与实战开发全流程 什么是负载均衡负载均衡的种类服务器端负载均衡(S-LB)客户端负载均衡(C-LB)注解LoadBalancedLoadBalancerAutoConfiguration类LoadBalancerClient类源码分析 ServiceInstanceChoo…

ToolLLM model 以及LangChain AutoGPT Xagent在调用外部工具Tools的表现对比浅析

文章主要谈及主流ToolLLM 以及高口碑Agent 在调用Tools上的一些对比,框架先上,内容会不断丰富与更新。 第一部分,ToolLLM model 先来说主打Function Call 的大模型们 OpenAI GPT 宇宙第一LLM,它的functionCall都知道&#xff0…

python 小程序学生选课系统源码

开发工具: PyCharm,mysql5.7,微信开发者工具 技术说明: python django html 小程序 功能介绍: 学生: 登录,选课(查看课程及选择),我的成绩,…

Axure中动态面板使用及轮播图多种登录方式左侧导航栏之案列

🎬 艳艳耶✌️:个人主页 🔥 个人专栏 :《产品经理如何画泳道图&流程图》 ⛺️ 越努力 ,越幸运 目录 一、轮播图简介 1、什么是轮播图 2、轮播图有什么作用 3、轮播图有什么特点 4、轮播图适应范围 5、…

解决Chrome同一账号在不同设备无法自动同步书签的问题

文章目录 一、问题与原因?2. 解决办法 一、问题与原因? 1.问题 使用谷歌Chrome浏览器比较头疼的问题就是:使用同一个Google账号,办公电脑与家用电脑的数据无法同步。比如:办公电脑中的书签、浏览记录等数据&#xff0…

C语言----文件操作(二)

在上一篇文章中我们简单介绍了在C语言中文件是什么以及文件的打开和关闭操作,在实际工作中,我们不仅仅是要打开和关闭文件,二是需要对文件进行增删改写。本文将详细介绍如果对文件进行安全读写。 一,以字符形式读写文件&#xff…

Nessus漏洞扫描报错:42873 - SSL Medium Strength Cipher Suites Supported (SWEET32)

个人搭建的windows server 2019服务器,被Nessus工具扫描出现三个漏洞,修复比较过程比较坎坷,特记录下 首先:报错信息: 42873 - SSL Medium Strength Cipher Suites Supported (SWEET32) 104743 - TLS Version 1.0 Protocol Detection 157288 - TLS Version 1.1 Protocol …

uni-app微信小程序隐藏左上角返回按钮

官方文档链接:uni.setNavigationBarTitle(OBJECT) | uni-app官网 (dcloud.net.cn) 首先要明确的是页面间的跳转方式有几种、每一种默认的作用是什么。 uniapp五种跳转方式 第一:wx.navigatorTo 【新页面打开,默认会有返回按钮】第二&#x…