边缘检测算子Canny原理概述并利用OpenCV的库函数Canny()对图像进行边缘检测[通俗易懂]

边缘检测算子Canny原理概述并利用OpenCV的库函数Canny()对图像进行边缘检测[通俗易懂]图像边缘检测的概念和大概原理可以参考我的另一篇博文,链接如下:https://blog.csdn.net/wenhao_ir/article/details/51743382本篇博文介绍边缘检测算子Canny,并利用OpenCV的库函数Canny()对图像进行边缘检测。Canny算子是JohnCanny在1986年发表的论文中首次提出的边缘检测算子,该算子检测性能比较好,应用广泛。Canny算法被推崇为当今最优的边缘检测的算法。Canny算子进行边缘检测的原理和步骤如下:⑴消除噪声。边缘

大家好,又见面了,我是你们的朋友全栈君。

图像边缘检测的概念和大概原理可以参考我的另一篇博文,链接如下:
https://blog.csdn.net/wenhao_ir/article/details/51743382

本篇博文介绍边缘检测算子Canny,并利用OpenCV的库函数Canny()对图像进行边缘检测。

Canny算子是John Canny在1986年发表的论文中首次提出的边缘检测算子,该算子检测性能比较好,应用广泛。Canny 算法被推崇为当今最优的边缘检测的算法。

Canny算子进行边缘检测的原理和步骤如下

⑴消除噪声。边缘检测的算法主要是基于图像强度的一阶和二阶微分操作,但导数通常对噪声很敏感,边缘检测算法常常需要根据图像源的数据进行预处理操作,因此采用滤波器来改善与噪声有关的边缘检测性能,比如在进行边缘检测前,可以对原始数据先作高斯滤波处理。如果不做滤波平滑处理,不仅是噪声,原图片中不是边缘但是灰度变化频率较高的部分也容易被认为是边缘,这样会导致边缘检测性能的下降。

⑵找到图片的强度梯度。在对图像进行平滑处理后,Canny边缘算法的第二步是找到图片的强度梯度。尽管“强度梯度”这个名词可能听起来很复杂,其实很简单,它是指边缘的方向。一条边实际上可以指向任何方向,但该算法只查看四个方向以简化事情。方向是水平、垂直和两个对角线方向。在数学中,我们将其写为 [0 ° , 90 ° , 45 ° , 135 ° ]。
OpenCV中的函数Canny()使用3×3 Sobel内核来确定水平方向的导数,然后将其转置以确定垂直方向的导数,这些导数可用于在所需的四个方向上找到我们的边缘。

⑶非极大值抑制。非极大值抑制的目的是剔除第⑵部中计算出来的结果中的大部分非边缘点。其原理是通过像素的八邻域来判断要不要将这个像素置为边缘点,如果不置为边缘点,那么就置为背景色。判断的方法如下:

①判断范围是像素的八邻域,所以是局部最优判断法;

②判断的标准是如果某个像素在其八邻域内,既是最大值,梯度值也最大,那么可判断该点为像素边缘点,否则就不是。具体判断的方法如下:

首先,梯度值的判断是很好判断的,用边缘检测微分算子得到的结果直接比较就可以了,但是最大值的判断可不是只比较其旁边的八个点哦,还要比较另外两个点,详情如下:

边缘检测算子Canny原理概述并利用OpenCV的库函数Canny()对图像进行边缘检测[通俗易懂]

如果已经判断出上图中的C点比其旁边的8个点的像素值都大,那么接下来判断上图中dTmp1和dTmp2的值是否也小于C点的值,那么dTmp1和dTmp2的值怎么求呢?上图中蓝色的线条方向为C点的梯度方向,由于是梯度方向,所以可以确定其局部的最大值肯定分布在这条线上,也即除了C点外,梯度方向的交点dTmp1和dTmp2这两个点的值也可能会是局部最大值。因此,判断C点灰度与这两个点灰度大小即可判断C点是否为其邻域内的局部最大灰度点。如果经过判断,C点灰度值小于这两个点中的任一个,那就说明C点不是局部极大值,那么则可以排除C点为边缘。

⑷用滞后阈值算法求解图像边缘。上一步对边缘检测算子的结果进行了非极大值抑制,接下来我们用二值化的方法来求解图像边缘。单阈值处理边缘效果不好,所以Cannny算法中采用滞后阈值法求解。滞后阈值法需要设置一个高阈值和一个低阈值,解后按如下法则进行:

第一,如果某一像素位置的梯度幅值超过高阈值,则像素被保留为边缘像素;

第二,如果某一像素位置的梯度幅值小于低阈值,则像素被排除;

第三,如果某一像素位置的幅值在两个阈值之间,该像素仅仅在连接到一个高于高阈值的像素时被保留。

在以上的法则中,推荐的高阈值与低阈值比在2:1到3:1之间。

通过消除噪声、计算梯度幅度与方向、非极大值抑制及用滞后阈值算法求解图像边缘四个步骤就可实现Canny边缘检测。

OpenCV提供了函数Canny()实现Canny算子,其原型如下:

void Canny( InputArray image, 
			OutputArray edges, 
			double threshold1, 
			double threshold2, 
			int apertureSize=3, 
			bool L2gradient=false 
		  )

Image—输入图像,要求是数据深度为8bit的图像,官方文档中并没有说输入图像必须为单通道,但很多资料上都说要求是单通道的图像。

edges—输出图像,单通道8bit的图像,尺寸与输入图像相同。

 threshold1—滞后阈值算法的低阈值;

 threshold2—滞后阈值算法的高阈值;

apertureSize—Sobel算子的大小,为什么是Sobel算子,请看上面对Canny算子描述的第二点。

L2gradient—是否使用L2范数来计算图像梯度幅值。

以下是使用函数Canny()实现图像边缘检测的示例代码:

代码中用

//博主微信/QQ 2487872782
//有问题可以联系博主交流
//有图像处理需求也可联系博主
//图像处理技术交流QQ群 271891601

//OpenCV版本:3.0
//VS版本:2012

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include<opencv2/imgcodecs/imgcodecs.hpp>
#include <opencv2/imgproc/imgproc.hpp>
 
using namespace cv;
 
int main()
{
        //载入原始图    
        Mat src = imread("F:/material/images/P0042-building_edge_detection.jpg");  
        Mat src_1 = imread("F:/material/images/P0042-building_edge_detection.jpg", 0);
        Mat gray = imread("F:/material/images/P0042-building_edge_detection.jpg", 0);
 
        imshow("原图", src);
 
        //----------------------------------------------------------------------------------  
        //  一、最简单的canny用法,拿到原图的灰度图后直接用。  
        //----------------------------------------------------------------------------------  
        Canny(src_1, src_1, 100, 150, 3);
        imshow("简单用法的Canny边缘检测结果", src_1);
 
        //----------------------------------------------------------------------------------  
        //  二、高级的canny用法,转成灰度图,降噪,用canny,最后将得到的边缘作为掩码,拷贝原图到效果图上,得到彩色的边缘图  
        //----------------------------------------------------------------------------------  
        Mat dst, edge;
 
        // 【1】创建与src同类型和大小的矩阵(dst)  
        dst.create(gray.size(), gray.type());
 
        // 【2】先用使用 3x3内核来降噪  
        blur(gray, edge, Size(3, 3));
 
        // 【3】运行Canny算子  
        Canny(edge, edge, 100, 150, 3);
 
        imshow("高级用法的Canny边缘检测结果", edge);
 
        //【4】将g_dstImage内的所有元素设置为0   
        dst = Scalar::all(0);
 
        //【5】使用Canny算子输出的边缘图g_cannyDetectedEdges作为掩码,来将原图g_srcImage拷到目标图g_dstImage中  
        src.copyTo(dst, edge);
 
        //【6】显示效果图   
        imshow("高级用法的合成图", dst);
 
        waitKey(0);
 
        return 0;
}

运行结果如下图所示:

边缘检测算子Canny原理概述并利用OpenCV的库函数Canny()对图像进行边缘检测[通俗易懂]

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/139370.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Redis配置文件详解(Redis 4.0.8)

    Redis配置文件详解(Redis 4.0.8)目录INCLUDES(引入其他配置):MODULES(模块):NETWORK(网络设置):GENERAL(普通设置):SNAPSHOTTING(快照):REPLICATION(复制):SECURITY(安全):CLIENTS(客户端):MEMORYMANAGEMENT(内存管理):LAZYFREEI…

    2022年6月4日
    50
  • mqttnet 详解_mqttnet3.0用法

    mqttnet 详解_mqttnet3.0用法1///开源库地址:https://github.com/chkr1011/MQTTnet2///对应文档:https://github.com/chkr1011/MQTTnet/wiki/Client34usingMQTTnet;5usingMQTTnet.Client;6usingMQTTnet.Client.Options;7usingSystem;8usingSystem.T…

    2022年6月25日
    51
  • Spring Cloud版本与Spring Boot版本之间匹配关系「建议收藏」

    Spring Cloud版本与Spring Boot版本之间匹配关系「建议收藏」很多人在使用springboot和springcloud,但是对于这两者之间的版本关系不是很清楚,特别是在面临升级的时候不知道该如何操作。本文简要摘录的官方文档的部分内容作为依据,供广大同行参考。问题的提出,我现在使用的是1.5.1版本的springboot和Edgware.RELEASE版本的springcloud,我想升级到springboot到2.0.0,springcloud需要升…

    2022年4月30日
    70
  • Java中System.setProperty()用法

    Java中System.setProperty()用法/* *设置指定键对值的系统属性 *setProperty(Stringprop,Stringvalue); *  *参数: *prop-系统属性的名称。 *value-系统属性的值。   *  *返回: *系统属性以前的值,如果没有以前的值,则返回null。 *  *抛出:   *SecurityExceptio

    2022年7月12日
    76
  • C++滑动窗口算法_最短连续包含子串

    C++滑动窗口算法_最短连续包含子串滑动窗口算法在一个特定大小的字符串或数组上进行操作,而不在整个字符串和数组上操作,这样就降低了问题的复杂度,从而也达到降低了循环的嵌套深度。如下题给你两个长度相同的字符串,s和t。将s中的第i个字符变到t中的第i个字符需要|s[i]-t[i]|的开销(开销可能为0),也就是两个字符的ASCII码值的差的绝对值。用于变更字符串的最大预算是maxCost。在转化字符串时,总开销应当小于等于该预算,这也意味着字符串的转化可能是不完全的。如果你可以将s的子字符串转

    2025年7月10日
    4
  • stm32的语音识别_基于STM32的嵌入式语音识别模块设计

    stm32的语音识别_基于STM32的嵌入式语音识别模块设计引言服务机器人以服务为目的,因此人们需要一种更方便、更自然、更加人性化的方式与机器人交互,而不再满足于复杂的键盘和按钮操作。基于听觉的人机交互是该领域的一个重要发展方向。目前主流的语音识别技术是基于统计模式。然而,由于统计模型训练算法复杂,运算量大,一般由工控机、PC机或笔记本来完成,这无疑限制了它的运用。嵌入式语音交互已成为目前研究的热门课题。嵌入式语音识别系统和PC机的语音识别系统相比,虽然其…

    2022年6月26日
    32

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号