《opencv实用探索·十三》opencv之canny边缘检测

1、canny边缘检测应用场景

目标检测:
Canny边缘检测可以用于检测图像中的目标边缘,从而帮助识别和定位物体。在目标检测的流程中,边缘通常是检测的第一步。
图像分割:
Canny边缘检测可用于图像分割,即将图像划分为具有相似属性的区域。图像分割是许多计算机视觉任务的基础,如图像分析、物体识别等。
图像增强:
Canny边缘检测可以突出图像中的边缘特征,从而增强图像的结构信息。这对于图像处理任务,如图像重建和特征提取,非常有帮助。
边缘跟踪:
Canny边缘检测是一种强边缘跟踪器,可以用于跟踪图像中的曲线和边缘。
机器视觉和自动驾驶: 在机器视觉和自动驾驶系统中,Canny边缘检测可用于检测道路边缘、车辆和行人等物体。
医学图像处理:
在医学图像中,Canny边缘检测用于检测器官的边缘,从而协助医生进行诊断和手术规划。
光学字符识别(OCR):
在文字识别领域,Canny边缘检测可用于提取文本的边缘,以帮助进行光学字符识别。
图像分析:
Canny边缘检测在图像分析中是一种常见的工具,用于提取图像的重要特征。

2、canny边缘检测步骤
(1)噪声抑制:
在进行边缘检测之前,通常会对图像进行平滑以抑制噪声。这通常使用高斯滤波器来实现,可以通过cv::GaussianBlur函数完成。
(2)计算图像梯度:
使用Sobel算子计算图像在水平和垂直方向上的梯度。这个过程可以通过cv::Sobel函数实现。
(3)计算梯度的幅值和方向:
根据梯度的水平和垂直分量,计算梯度的幅值和方向。这可以通过cv::magnitude和cv::phase实现。
(4)非极大值抑制:
对梯度幅值图进行非极大值抑制,保留梯度方向上的局部最大值。这一步骤有助于细化边缘,使其更接近实际的边界。
(5)双阈值边缘跟踪:
根据设定的两个阈值(高阈值和低阈值),对非极大值抑制后的图像进行阈值处理,得到二值图像。高阈值用于确定强边缘,低阈值用于确定可能的边缘。通常,高阈值选取的较高,低阈值选取的较低。
(6)边缘连接:
对低阈值下的边缘像素进行连接,使其连接到高阈值下的边缘。这一步骤可以使用递归或迭代方法实现。

对于高斯滤波和梯度计算在之前的章节已经阐述过,请点击高斯滤波和梯度计算进行回顾。

这里解释下什么是梯度幅值和方向:
边缘检测算子返回水平方向的Gx和垂直方向的Gy。梯度的幅度𝐺和方向𝛩(用角度值表示)为:
在这里插入图片描述
式中,atan2(•)表示具有两个参数的 arctan 函数。

梯度幅值是梯度矢量的长度,表示图像在某一点的强度变化的大小,梯度的方向总是与边缘垂直的,通常就近取值为水平(左、右)、垂直(上、下)、对角线(右上、左上、左下、右下)等 8 个不同的方向。

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

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

非极大值像素梯度抑制:
在具体实现时,逐一遍历像素点,判断当前像素点是否是周围像素点中具有相同梯度方向的最大值,并根据判断结果决定是否抑制该点。如果当前像素点是周围像素点中最大值,我们保留该像素值,否则将其抑制为零。

例如A、B、C 三点具有相同的方向(梯度方向垂直于边缘)如下图。判断这三个点是否为各自的局部最大值:如果是,则保留该点;否则,抑制该点(归零)。
在这里插入图片描述
从图中可以看到A点在图像边缘,所以A 点具有最大的局部值,所以保留 A 点(称为边缘),其余两点(B和 C)被抑制(归零)。

再比如下图中,黑色背景的点都是向上方向梯度(边缘处于水平)的局部最大值。因此,这些点会被保留;其余点被抑制(处理为 0)。这意味着,这些黑色背景的点最终会被处理为边缘点,而其他点都被处理为非边缘点。
在这里插入图片描述
经过上述处理后,对于同一个方向的若干个边缘点,基本上仅保留了一个,使得检测到的边缘更狭窄,更接近实际的边界。

当完成非极大值抑制后,只保留了效果明显的边缘,然而,对于这些边缘,有些确实是图像的边缘,而有些却是由噪声产生的。之前用高斯滤波只是降噪,并不能消除噪声。而这些噪声造成的边缘被称为虚边缘,我们需要通过双值域将其消除。

双阈值设置:
首先设置两个阈值:高阈值(highThreshold)和低阈值(lowThreshold),高阈值用于确定强边缘,低阈值用于确定可能的边缘。对于所有的像素点,逐一遍历,如果当前边缘像素的梯度值 大于高阈值定为强边缘, 低于高阈值但是高于低阈值被定为虚边缘, 低于低阈值的像素点(抑制)置零。
所有的强边缘保留,而对于虚边缘,我们要做个判断。如果这些虚边缘是连接着强边缘的,那么保留,如果不是,那么抑制(置零)。

下面以一个示例图来说明。
图中Max和Min表示高低阈值,A在Max上面为强边缘直接保留,B在Max和Min之间为虚边缘,但B连着B,故也认定为边缘,保留。C也处于Max和Min之间,但C和A没有连接,故认定C不是边缘,被抑制。D之间小于低阈值,之间被抑制为0。

最后进行边缘连接,其过程如下:
(1)遍历经过非极大值抑制后的梯度幅值图像(图像经过非极大值抑制后只有边缘上的像素点的梯度幅值被保留,其他像素点的梯度幅值为零。)
(2)将大于高阈值的像素点标记为强边缘,高低阈值之间的像素值标记为弱边缘。
(3)从弱边缘像素出发,沿着其梯度方向前进,如果相邻像素中有强边缘像素(梯度幅值大于高阈值),则将其标记为强边缘,并继续追踪。追踪过程中,可能的边缘像素逐渐被标记为强边缘,形成一个连接的边缘。
(4)重复以上步骤,直到没有新的像素被添加到连接的边缘。最终,连接的边缘像素集合就是Canny边缘检测算法的输出。

3、opencv之canny接口调用

void cv::Canny(InputArray image,         // 输入图像(单通道8位灰度图像)OutputArray edges,         // 输出边缘图像double threshold1,        // 低阈值double threshold2,        // 高阈值int apertureSize = 3,      // Sobel算子核的大小,默认为3bool L2gradient = false    // 是否使用更精确的L2范数梯度计算,默认为false
);

双阈值怎么设定?

通常建议高阈值与低阈值的比例在2:1到3:1之间。
例如,如果设置高阈值为100,则低阈值可以设置为50或33。
根据图像特性:
可以根据图像的特性来调整阈值。如果图像中的边缘比较弱,可以适当降低阈值;如果图像中的边缘比较强,可以适当提高阈值。

参考代码:

int main() 
{  // 读取灰度图像cv::Mat image = cv::imread("1.jpg", cv::IMREAD_GRAYSCALE);// 检查图像是否成功读取if (image.empty()) {std::cerr << "Error: Could not read the image." << std::endl;return -1;}// 应用Canny边缘检测cv::Mat edges;double lowThreshold = 50;  // 低阈值double highThreshold = 150;  // 高阈值//高斯滤波去噪后检测图像边缘GaussianBlur(image, image, Size(3, 3), 0);cv::Canny(image, edges, lowThreshold, highThreshold);// 显示原始图像和Canny边缘检测的输出cv::imshow("Original Image", image);cv::imshow("Canny Edges", edges);// 等待用户按键cv::waitKey(0);return 0;
}

效果图如下:
左边是之间通过canny检测的边缘,右边是先通过高斯滤波去噪后再使用canny检测的边缘,可以明显的发现先去噪再检测边缘效果会更好。
在这里插入图片描述

参考文章:opencv基础44- Canny边缘检测详解-cv.Canny()

在这里插入图片描述

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

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

相关文章

数据分析基础之《matplotlib(4)—柱状图》

一、柱状图绘制 1、柱状图要素 有类别 2、需求&#xff1a;对比每部电影的票房收入 电影数据如下图所示&#xff1a; 3、matplotlib.pyplot.bar(x, height, width0.8, bottomNone, *, aligncenter, dataNone, **kwargs) 说明&#xff1a; x&#xff1a;有几个类别 height&am…

基于JavaSE+JDBC使用控制台操作的简易购物系统【源码+数据库】

1、项目简介 本项目是一套基于JavaSEJDBC使用控制台操作的简易购物系统&#xff0c;主要针对计算机相关专业的正在做bishe的学生和需要项目实战练习的Java学习者。 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目可以直接作为bishe使用。 项目都经过严格调试&…

html刷题笔记

1 em 12 pt 16 px 100% source元素为audio、video、picture元素指定多个媒体文件 margin是用来隔开元素与元素的间距&#xff1b;padding是用来隔开元素与内容的间隔。 margin用于布局分开元素使元素与元素互不相干&#xff1b;padding用于元素与内容之间的间隔&#xff0c;…

实话!卷运维不如卷网络安全

最近发现很多从事运维的选择了辞职&#xff0c;重新规划自己的职业发展方向。运维工程师这个岗位在IT行业里面确实是处于最底层的&#xff0c;不管什么环节出现问题&#xff0c;基本都是运维背锅。背锅也就罢了&#xff0c;薪资水平也比不上别的岗位。 一般运维的薪资水平大多数…

3DMAX UV贴图修改插件安装卸载方法

3DMAX UV贴图修改插件安装卸载方法 3dMax贴图修改插件PolyUnwrapper是为纹理艺术家设计的一整套专业工具&#xff0c;尤其适用于建筑和游戏行业。 它包含许多功能&#xff0c;将大大帮助您改进UV展开的工作流程。 【主要功能特点】 -多重缝合。一次缝合多个壳 -自定义打包算…

种下一棵栀子花

女孩说自己是男孩当年伸手就可触及的栀子花.男孩沉默了,明白了当初失去了什么. 时光倒流,13年前的一个夏天夜晚,男孩与女孩同在沪城,女孩分享了自己的照片给男孩.男孩站在窗前,那晚的夜空很美丽,仿佛托着那个白衣裳女孩的纯真的梦,来到了自己的身边. 女孩说彼此间只是少了一个深…

js vue 输入正确手机号/邮箱后,激活“发送验证码”按钮

按钮禁止点击状态&#xff1a; 按钮能够点击状态&#xff1a; 我采用的方式是监听手机号/邮箱输入框的输入事件&#xff0c;即实判断用户输入的数据是否满足规则&#xff0c;如果满足手机号/邮箱规则&#xff0c;则激活“获取验证码”按钮。 话不多说&#xff0c;上代码 样式…

二叉树题目:翻转二叉树以匹配前序遍历

文章目录 题目标题和出处难度题目描述要求示例数据范围 解法思路和算法代码复杂度分析 题目 标题和出处 标题&#xff1a;翻转二叉树以匹配前序遍历 出处&#xff1a;971. 翻转二叉树以匹配前序遍历 难度 5 级 题目描述 要求 给定一个二叉树的根结点 root \texttt{roo…

安装python第三方库后,在pycharm中不能正常导入

python小白学习opencv&#xff0c;使用pip安装完opencv库后import cv2报错&#xff0c;按照如下设置解决&#xff1a; 需要正确设置python解释器路径

⭐Unity 搭建UDP服务端(02)接收客户端消息

客户端在上一篇 由于服务器逻辑写的较为简单 所以直接上代码了~ using System; using System.Net; using System.Net.Sockets; using System.Text; using UnityEngine;public class UdpServer : MonoBehaviour {public static UdpServer instance;private void Awake(){if (…

如何选择靠谱的软件测试外包公司?CMA、CNAS软件测试报告获取

作为信息科技产业的代表之一&#xff0c;软件公司受到了越来越多的关注&#xff0c;它们的发展为我国的科技创新提供了强大的战略支撑。软件测试作为提升软件产品质量的后盾&#xff0c;日益成为一个专业化、标准化和规范化的行业&#xff0c;软件测试外包公司就是这种背景下成…

基于LSTM和N-gram序列的英文文本生成(文末送书)

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…