[OpenCV] 数字图像处理 C++ 学习——13Canny边缘检测 附完整代码

本文主要是介绍[OpenCV] 数字图像处理 C++ 学习——13Canny边缘检测 附完整代码,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 前言
  • 1.理论基础
    • (1)高斯模糊平滑图像(GaussianBlur)
    • (2)计算图像梯度(Sobel/Scharr)
    • (3)非极大值抑制 (Non-maximum Suppression)
    • (4)双阈值检测 (Double Threshold)
    • (5)边缘跟踪(通过滞后处理)
  • 2.代码实现
  • 3.完整代码

前言

Canny 边缘检测(高斯滤波、梯度计算、非极大值抑制、双阈值检测、边缘跟踪)是经典的边缘检测算法之一,本文将详细介绍 Canny 边缘检测的理论基础、实现方法,并提供完整的 C++ 代码示例。

1.理论基础

Canny 边缘检测算法是由 John F. Canny 于 1986 年提出的。Canny 算法提取图像的边缘时表现出了很高的性能。Canny 算法的主要步骤如下:

①使用高斯滤波器,平滑图像,滤除噪声。
②计算图像中每个像素点的梯度。
③非极大值(Non-Maximum Suppression)抑制,去除非边缘的像素点,减少边缘检测中的噪声响应。
④双阈值(Double-Threshold)检测来确定真实的和潜在的边缘。
⑤通过连接强边缘像素点和与之相邻的弱边缘像素点,得到完整的边缘图像。

(1)高斯模糊平滑图像(GaussianBlur)

高斯模糊是通过模糊图像来减少噪声和细节,防止这些无关信息在后续的边缘检测中被误检为边缘。

[OpenCV] 数字图像处理 C++ 学习——07图像模糊 附完整代码(小白入门篇)有讲到,有需要可以去看一下

(2)计算图像梯度(Sobel/Scharr)

使用 Sobel 算子计算图像在水平方向(x 方向)和垂直方向(y 方向)的梯度。梯度的大小和方向可以通过以下公式计算:

在这里插入图片描述

(3)非极大值抑制 (Non-maximum Suppression)

在图像梯度幅值图上,抑制非边缘的像素,即抑制不是局部最大值的像素。这一步骤是为了减少不必要的边缘响应,只保留真正的边缘像素。

在这里插入图片描述

图中将梯度方向划分为了 4 个主要区域,每个区域对应一定的角度范围。这些区域分别是:

  • 黄色区域 (0° 和 180°):梯度方向接近水平方向,具体来说,角度在(0° ,22.5° ) 或(157.5° ,180°) 之间。这个方向对应着水平边缘。
  • 绿色区域 (45°):梯度方向介于水平和垂直之间,对应的角度范围是(22.5° , 67.5°) 。这个方向通常表示斜向的边缘。
  • 蓝色区域 (90°):梯度方向接近垂直方向,角度在(67.5° ,112.5°) 之间。这个方向对应着垂直边缘。
  • 红色区域 (135°):梯度方向介于垂直和水平之间,对应的角度范围是 (112.5° , 157.5°)。这个方向也是斜向的,方向与绿色区域的方向相反。

非极大值抑制的处理步骤

  • 选择方向:根据每个像素点的梯度方向,将该方向归类到上述的四个主要方向之一。然后沿着这个主要方向进行非极大值抑制。
  • 比较相邻像素:对于每个像素点,沿着该点的梯度方向,比较其梯度幅值是否是局部最大值。如果当前像素的梯度幅值大于沿着梯度方向的前一个和后一个像素的梯度幅值,则保留该点为边缘点;否则,将该点的梯度幅值设为零,表示非边缘。

例如:

  • 如果梯度方向是接近水平的(黄色区域),则比较当前像素与左侧和右侧像素的梯度幅值。
  • 如果梯度方向是接近垂直的(蓝色区域),则比较当前像素与上方和下方像素的梯度幅值。

通过非极大值抑制,梯度幅值图像中的噪声点和不明确的边缘点会被抑制,只保留那些可能真实存在的边缘。

(4)双阈值检测 (Double Threshold)

应用两个阈值对检测到的边缘进行分类:强边缘(强于高阈值)、弱边缘(介于高阈值和低阈值之间)和非边缘(低于低阈值)。强边缘直接被保留,弱边缘如果连接到强边缘则保留,否则舍弃。

在这里插入图片描述

  • A 点的梯度值值大于 maxVal,因此 A 是强边缘。
  • B 和 C 点的梯度值介于 maxVal 和 minVal 之间,因此 B、C 是虚边缘。
    • B 点的梯度值介于 maxVal 和 minVal 之间,是虚边缘,但该点与强边缘不相连,故将其抛弃。
    • C 点的梯度值介于 maxVal 和 minVal 之间,是虚边缘,但该点与强边缘 A 相连,故将其保留。
  • D 点的梯度值小于 minVal,因此 D 被抑制(抛弃)。

(5)边缘跟踪(通过滞后处理)

通过连接强边缘像素点和与之相邻的弱边缘像素点,得到完整的边缘图像。

2.代码实现

cv::Canny() 使用了上述的步骤,自动进行图像平滑、梯度计算、非极大值抑制、双阈值检测和边缘跟踪。

	cv::Mat edges;double lowThreshold = 50;double highThreshold = 150;cv::Canny(blurredImage, edges, lowThreshold, highThreshold);cv::imshow("Canny Edges", edges);

lowThreshold = 50和highThreshold = 150结果

在这里插入图片描述

lowThreshold = 50和highThreshold = 100结果
在这里插入图片描述

具体的结果需要根据实际图像的特性来调节双阈值,以达到最佳边缘检测效果。

3.完整代码

#include<opencv2/opencv.hpp>
#include<highgui.hpp>
#include<iostream>
#include<math.h>using namespace cv;
using namespace std;void Canny_edge_detection()
{cv::Mat image;image = imread("lena.png", IMREAD_GRAYSCALE);if (image.empty()) {printf("could not find the image...\n");return;}namedWindow("input image", cv::WINDOW_AUTOSIZE);cv::imshow("input image", image);// 使用高斯滤波器平滑图像cv::Mat blurredImage;GaussianBlur(image, blurredImage, Size(5, 5), 1.5);// 执行 Canny 边缘检测cv::Mat edges;double lowThreshold = 50;double highThreshold = 100;cv::Canny(blurredImage, edges, lowThreshold, highThreshold);cv::imshow("Canny Edges", edges);waitKey(0);}
int main() 
{Canny_edge_detection();return 0;
}

这篇关于[OpenCV] 数字图像处理 C++ 学习——13Canny边缘检测 附完整代码的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1135074

相关文章

Spring Boot 3.4.3 基于 Spring WebFlux 实现 SSE 功能(代码示例)

《SpringBoot3.4.3基于SpringWebFlux实现SSE功能(代码示例)》SpringBoot3.4.3结合SpringWebFlux实现SSE功能,为实时数据推送提供... 目录1. SSE 简介1.1 什么是 SSE?1.2 SSE 的优点1.3 适用场景2. Spring WebFlu

java之Objects.nonNull用法代码解读

《java之Objects.nonNull用法代码解读》:本文主要介绍java之Objects.nonNull用法代码,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录Java之Objects.nonwww.chinasem.cnNull用法代码Objects.nonN

SpringBoot实现MD5加盐算法的示例代码

《SpringBoot实现MD5加盐算法的示例代码》加盐算法是一种用于增强密码安全性的技术,本文主要介绍了SpringBoot实现MD5加盐算法的示例代码,文中通过示例代码介绍的非常详细,对大家的学习... 目录一、什么是加盐算法二、如何实现加盐算法2.1 加盐算法代码实现2.2 注册页面中进行密码加盐2.

python+opencv处理颜色之将目标颜色转换实例代码

《python+opencv处理颜色之将目标颜色转换实例代码》OpenCV是一个的跨平台计算机视觉库,可以运行在Linux、Windows和MacOS操作系统上,:本文主要介绍python+ope... 目录下面是代码+ 效果 + 解释转HSV: 关于颜色总是要转HSV的掩膜再标注总结 目标:将红色的部分滤

在C#中调用Python代码的两种实现方式

《在C#中调用Python代码的两种实现方式》:本文主要介绍在C#中调用Python代码的两种实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C#调用python代码的方式1. 使用 Python.NET2. 使用外部进程调用 Python 脚本总结C#调

C++ 中的 if-constexpr语法和作用

《C++中的if-constexpr语法和作用》if-constexpr语法是C++17引入的新语法特性,也被称为常量if表达式或静态if(staticif),:本文主要介绍C++中的if-c... 目录1 if-constexpr 语法1.1 基本语法1.2 扩展说明1.2.1 条件表达式1.2.2 fa

Java时间轮调度算法的代码实现

《Java时间轮调度算法的代码实现》时间轮是一种高效的定时调度算法,主要用于管理延时任务或周期性任务,它通过一个环形数组(时间轮)和指针来实现,将大量定时任务分摊到固定的时间槽中,极大地降低了时间复杂... 目录1、简述2、时间轮的原理3. 时间轮的实现步骤3.1 定义时间槽3.2 定义时间轮3.3 使用时

Java中&和&&以及|和||的区别、应用场景和代码示例

《Java中&和&&以及|和||的区别、应用场景和代码示例》:本文主要介绍Java中的逻辑运算符&、&&、|和||的区别,包括它们在布尔和整数类型上的应用,文中通过代码介绍的非常详细,需要的朋友可... 目录前言1. & 和 &&代码示例2. | 和 ||代码示例3. 为什么要使用 & 和 | 而不是总是使

Java强制转化示例代码详解

《Java强制转化示例代码详解》:本文主要介绍Java编程语言中的类型转换,包括基本类型之间的强制类型转换和引用类型的强制类型转换,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录引入基本类型强制转换1.数字之间2.数字字符之间引入引用类型的强制转换总结引入在Java编程语言中,类型转换(无论

MySQL中慢SQL优化方法的完整指南

《MySQL中慢SQL优化方法的完整指南》当数据库响应时间超过500ms时,系统将面临三大灾难链式反应,所以本文将为大家介绍一下MySQL中慢SQL优化的常用方法,有需要的小伙伴可以了解下... 目录一、慢SQL的致命影响二、精准定位问题SQL1. 启用慢查询日志2. 诊断黄金三件套三、六大核心优化方案方案