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

news2024/12/26 11:16:12

 

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.coloradmin.cn/o/1314796.html

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

相关文章

代码随想录-刷题第二十八天

93. 复原 IP 地址 题目链接:93. 复原 IP 地址 思路:切割问题,原理上还是抽象成树形结构,然后使用回溯法。 131 题的要求是:让你把字符串 s 切分成若干个合法的回文串,返回所有的切分方法。 本题的要求是…

知识|基于混合模式的多余度飞控全数字仿真系统研究

*余度(Redundancy):一种确保安全的设计手段,使得出现两个及以上故障时,才会引起既定不希望发生的工作状态。 飞行控制软件主要完成飞行传感器数据处理、飞行姿态控制和余度管理任务,对保证飞机安全性和可靠…

GroupMixFormer:基于Group-Mix注意力的视觉Transformer

文章目录 摘要1、简介2、相关工作2.1、视觉转换器2.2、全面的自注意力建模 3、组混合注意力和GroupMixFormer3.1. 动机:从个体到群体3.2. GMA: 混合组以获得更好的注意力3.3. 架构配置 4、实验4.1、实现细节4.2. 与最先进模型的比较4.3. 消融实验 5、结论 摘要 htt…

[论文笔记] chatgpt系列 SparseMOE—GPT4的MOE结构

SparseMOE: 稀疏激活的MOE Swtich MOE,所有token要在K个专家网络中,选择一个专家网络。 显存增加。 Experts Choice:路由MOE:​​​​​​​ 由专家选择token。这样不同的专家都选择到某个token,也可以不选择该token。 由于FFN层的时间复杂度和attention层不同,FFN层的时…

[Vulnhub靶机] DC-1

[Vulnhub靶机] DC-1靶机渗透思路及方法(个人分享) 靶机下载地址: https://download.vulnhub.com/dc/DC-1.zip 靶机地址:192.168.67.25 攻击机地址:192.168.67.3 一、信息收集 1.使用 arp-scan 命令扫描网段内存活的…

代码随想录刷题题Day14

刷题的第十四天,希望自己能够不断坚持下去,迎来蜕变。😀😀😀 刷题语言:C Day14 任务 ● 110.平衡二叉树 ● 257. 二叉树的所有路径 ● 404.左叶子之和 1 平衡二叉树 二叉树节点的深度:指从根节…

数据库系列之简要对比下GaussDB和OpenGauss数据库

GaussDB作为一款企业级的数据库产品,和开源数据库OpenGauss之间又是什么样的关系,刚开始接触的时候是一头雾水,因此本文简要对比下二者的区别,以加深了解。 1、GaussDB和OpenGauss数据库简要对比 GaussDB是华为基于PostgreSQL数据…

用Python快速从深层嵌套 JSON 中找到特定的 Value

有时候,我们拿到一个JSON数据的时候,会难以看出其逻辑层次结构。 这时候就需要我们进行代码解析了。 代码: import jsondef find_json_value(data_json, value, path""):if isinstance(data_json, dict):for k, v in data_json.…

学生用的台灯选什么比较好?热门考研护眼台灯推荐

是不是在台灯下用眼时间长了就觉得眼睛干涩难受,这说明是时候该换掉你的普通台灯换一盏护眼台灯了,用了才知道有多香。小台灯也有大学问,如果还不知道该怎么挑台灯的话也没关系,我已经总结了一份护眼台灯的科普和攻略,…

vmware安装Linux虚拟机设置固定IP地址

Linux虚拟机设置固定IP 近期工作需要,本地用VMware安装了三台Linux-centos虚拟机,来搭建rocketmq集群。但是IP地址每天关机重启之后就会比变化,很是恼火。找到了一个修改的教程,亲测有效!!!&am…

MySQL数据存储、索引记录

行格式(每行记录) 行格式(每行记录): 以记录为单位来向表中插入数据的,这些记录在磁盘上的存放方式也被称为 行格式 或者 记录格式。 InnoDB 存储引擎4种不同类型的 行格式 ,分别是 Compact 、 Redundant 、Dynamic 和 Compressed 行格式。组…

电机的开环控制和闭环控制

目录 开环电机控制 闭环电机控制 开环到闭环转换 开环电机控制 开环控制(也称为标量控制或伏特/赫兹控制)是一种常见的电机控制方法,可用于运行任何交流电机。这是一种简单的方法,不需要来自电机的任何反馈。为了保持定子磁通恒…

软考、PMP 区别

软考 考试时间:一年两次,报名3月,8月;对应考试:5月最后一个周末,11月第一个周末 报名费:50-200元,每个城市不同北京57每科 报名网站:中国计算机技术职业资格网 考试等…

LangChain学习三:链-实战

文章目录 上一节内容:LangChain学习二:提示-实战(下半部分)学习目标:明白链是什么?有哪些?怎么用?学习内容一:介绍学习内容二:有那些学习内容三:实…

【Flink-cdc-Mysql-To-Kafka】使用 Flinksql 利用集成的 connector 实现 Mysql 数据写入 Kafka

【Flink-cdc-Mysql-To-Kafka】使用 Flinksql 利用集成的 connector 实现 Mysql 数据写入 Kafka 1)环境准备2)准备相关 jar 包3)实现场景4)准备工作4.1.Mysql4.2.Kafka 5)Flink-Sql6)验证 1)环境…

EAM系统在地铁设备管理中的应用

在现代城市的交通系统中,地铁作为一种高效、快速、可靠的公共交通工具,扮演着至关重要的角色。为了确保地铁系统的正常运行和可靠性,地铁管理部门需要有效地管理大量的设备和设施。在这个过程中,企业资产管理(EAM&…

虚幻学习笔记13—C++静态和动态加载

一、前言 我们在蓝图中可以很方便的添加各种需要的组件,那么在C代码中要如何实现呢。在代码中分静态和动态加载,而无论静态和动态,加载的内容有资源和资源类,资源类通常为带资源的蓝图类。 二、实现 在实现静态或动态加载时&…

mybatis-plus雪花算法自动生成ID到前端后精度丢失问题

问题发生 前端接收到后端的数据出现异常,异常如下: 如图这是后端正常返回的数据, 但是点击预览时发现这个id的数据被改变了 这就导致了我通过id去修改相关数据时无法成功 问题原因 id的长度过长(19位),前…

针对网页html中插入动图gif不能循环播放只播放一次的解决方案

针对网页html中插入动图gif不能循环播放只播放一次的解决方案 原因分析解决方案 原因分析 使用图片编辑软件制作的过程中未启用“循环播放”功能,这里以Photoshop为例,演示设置GIF图片循环播放的操作流程:所需材料:PS。第一步&am…

云仓酒庄为您挑选意大利葡萄酒

作为世界产酒大国之一,意大利葡萄酒种类也是纷繁多样,赢得了众多葡萄酒爱好者的喜爱。说意大利葡萄酒地位仅次法国也不为过。那么,云仓酒庄的品牌雷盛红酒分享有没有一些挑选意大利葡萄酒的方法和技巧呢? 意大利的酒也有几千万种…