[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

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

【C++ Primer Plus习题】13.4

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "port.h"int main() {Port p1;Port p2("Abc", "Bcc", 30);std::cout <<

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

C++包装器

包装器 在 C++ 中,“包装器”通常指的是一种设计模式或编程技巧,用于封装其他代码或对象,使其更易于使用、管理或扩展。包装器的概念在编程中非常普遍,可以用于函数、类、库等多个方面。下面是几个常见的 “包装器” 类型: 1. 函数包装器 函数包装器用于封装一个或多个函数,使其接口更统一或更便于调用。例如,std::function 是一个通用的函数包装器,它可以存储任意可调用对象(函数、函数

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�