[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

相关文章

python使用Akshare与Streamlit实现股票估值分析教程(图文代码)

《python使用Akshare与Streamlit实现股票估值分析教程(图文代码)》入职测试中的一道题,要求:从Akshare下载某一个股票近十年的财务报表包括,资产负债表,利润表,现金流量表,保存... 目录一、前言二、核心知识点梳理1、Akshare数据获取2、Pandas数据处理3、Matplotl

Django开发时如何避免频繁发送短信验证码(python图文代码)

《Django开发时如何避免频繁发送短信验证码(python图文代码)》Django开发时,为防止频繁发送验证码,后端需用Redis限制请求频率,结合管道技术提升效率,通过生产者消费者模式解耦业务逻辑... 目录避免频繁发送 验证码1. www.chinasem.cn避免频繁发送 验证码逻辑分析2. 避免频繁

精选20个好玩又实用的的Python实战项目(有图文代码)

《精选20个好玩又实用的的Python实战项目(有图文代码)》文章介绍了20个实用Python项目,涵盖游戏开发、工具应用、图像处理、机器学习等,使用Tkinter、PIL、OpenCV、Kivy等库... 目录① 猜字游戏② 闹钟③ 骰子模拟器④ 二维码⑤ 语言检测⑥ 加密和解密⑦ URL缩短⑧ 音乐播放

Python使用Tenacity一行代码实现自动重试详解

《Python使用Tenacity一行代码实现自动重试详解》tenacity是一个专为Python设计的通用重试库,它的核心理念就是用简单、清晰的方式,为任何可能失败的操作添加重试能力,下面我们就来看... 目录一切始于一个简单的 API 调用Tenacity 入门:一行代码实现优雅重试精细控制:让重试按我

Python极速搭建局域网文件共享服务器完整指南

《Python极速搭建局域网文件共享服务器完整指南》在办公室或家庭局域网中快速共享文件时,许多人会选择第三方工具或云存储服务,但这些方案往往存在隐私泄露风险或需要复杂配置,下面我们就来看看如何使用Py... 目录一、android基础版:HTTP文件共享的魔法命令1. 一行代码启动HTTP服务器2. 关键参

C++11范围for初始化列表auto decltype详解

《C++11范围for初始化列表autodecltype详解》C++11引入auto类型推导、decltype类型推断、统一列表初始化、范围for循环及智能指针,提升代码简洁性、类型安全与资源管理效... 目录C++11新特性1. 自动类型推导auto1.1 基本语法2. decltype3. 列表初始化3

C++11右值引用与Lambda表达式的使用

《C++11右值引用与Lambda表达式的使用》C++11引入右值引用,实现移动语义提升性能,支持资源转移与完美转发;同时引入Lambda表达式,简化匿名函数定义,通过捕获列表和参数列表灵活处理变量... 目录C++11新特性右值引用和移动语义左值 / 右值常见的左值和右值移动语义移动构造函数移动复制运算符

OpenCV在Java中的完整集成指南分享

《OpenCV在Java中的完整集成指南分享》本文详解了在Java中集成OpenCV的方法,涵盖jar包导入、dll配置、JNI路径设置及跨平台兼容性处理,提供了图像处理、特征检测、实时视频分析等应用... 目录1. OpenCV简介与应用领域1.1 OpenCV的诞生与发展1.2 OpenCV的应用领域2

在Java中使用OpenCV实践

《在Java中使用OpenCV实践》用户分享了在Java项目中集成OpenCV4.10.0的实践经验,涵盖库简介、Windows安装、依赖配置及灰度图测试,强调其在图像处理领域的多功能性,并计划后续探... 目录前言一 、OpenCV1.简介2.下载与安装3.目录说明二、在Java项目中使用三 、测试1.测

C++中detach的作用、使用场景及注意事项

《C++中detach的作用、使用场景及注意事项》关于C++中的detach,它主要涉及多线程编程中的线程管理,理解detach的作用、使用场景以及注意事项,对于写出高效、安全的多线程程序至关重要,下... 目录一、什么是join()?它的作用是什么?类比一下:二、join()的作用总结三、join()怎么