《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算子核的大小,默认为3
    bool 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.niftyadmin.cn/n/5261293.html

相关文章

k8s debug 浅谈

一 k8s debug 浅谈 说明&#xff1a; 本文只是基于对kubectl debug浅显认识总结的知识点,后续实际使用再补充案例 Kubernetes 官方出品调试工具上手指南(无需安装&#xff0c;开箱即用) debug-application 简化 Pod 故障诊断: kubectl-debug 介绍 1.18 版本之前需要自己…

人工智能中的顺序学习:概念、应用和未来方向

一、介绍 人工智能 &#xff08;AI&#xff09; 中的顺序学习是一个关键研究领域&#xff0c;近年来引起了人们的极大兴趣。它指的是人工智能系统从数据序列中学习的能力&#xff0c;其中数据点的顺序至关重要。本文将探讨人工智能中顺序学习的概念、其重要性、应用、方法、挑战…

常见动物经济手术3d模拟交互演示教学实现了教育资源的共享

动物常见病防治是兽医必备的技能&#xff0c;为了让实习兽医在上岗作业前拥有丰富的常见病防治经验。借助动物常见病防治VR虚拟仿真技术开展动物常见病防治VR模拟实操培训&#xff0c;能极大方便院校实训。 提高教学质量 传统的动物医学教学往往依赖于理论知识和实验室实践&…

富时中国a50指数期货论文

富时中国A50指数期货概述 富时中国A50指数期货是中国境内市场上的一种衡量蓝筹股表现的期货合约&#xff0c;其跟踪富时中国A50指数的表现。富时中国A50指数是由富时罗素指数有限公司编制的一种反映中国大陆A股市场50只流动性好、市值大的股票的指数。 市场背景与意义 富时中…

2023 前端实战面试题

题目&#xff1a;JSON.stringify深拷贝的缺陷与递归实现的深拷贝函数 引言&#xff1a; 在前端开发中&#xff0c;数据的深拷贝是一个不可忽视的问题。常见的深拷贝方式之一是使用JSON.stringify&#xff0c;但这种方式并非完美无缺。本文将深入探讨使用JSON.stringify的缺陷&…

DevOps的发展史了解

DevOps的历史发展史可以追溯到2000年代初期&#xff0c;当时软件开发行业开始意识到&#xff0c;软件开发和IT运维之间的问题已经成为阻碍软件开发速度和效率的重要因素。在此之前&#xff0c;软件开发和IT运维是两个相对独立的过程&#xff0c;开发人员开发软件并将其交付给运…

文章解读与仿真程序复现思路——电网技术EI\CSCD\北大核心《基于最优经济运行区域的主动配电网日前-日内协同调度方法》

这个标题涉及到主动配电网的日前-日内协同调度方法&#xff0c;其关键要素包括“最优经济运行区域”和“日前-日内协同调度”。 主动配电网&#xff1a; 这指的是一种能够主动响应和参与调度的配电网系统。传统的配电网通常是被动的&#xff0c;即电力从电源到终端用户的传输是…

MCU平台下一种简单的文件系统设计构想

本文介绍MCU平台下一种简单的文件系统设计构想。 在使用MCU的项目中&#xff0c;经常会涉及到一些数据的存储&#xff0c;受限于硬件&#xff0c;又不太可能直接上文件系统&#xff08;如FAT文件系统&#xff09;&#xff0c;直接指定存储地址&#xff0c;数据长度对数据进行读…