当前位置: 首页 > news >正文

OpenCV中使用Canny算法在图像中查找边缘

  • 操作系统:ubuntu22.04
  • OpenCV版本:OpenCV4.9
  • IDE:Visual Studio Code
  • 编程语言:C++11

算法描述

        Canny算法是一种广泛应用于计算机视觉和图像处理领域中的边缘检测算法。它由John F. Canny在1986年提出,旨在寻找给定噪声条件下的最佳边缘检测算法。Canny算法的主要特点和步骤包括:

  1. 应用高斯滤波:首先,使用高斯滤波器平滑图像,以去除噪声并减少细节,这有助于后续步骤中的边缘检测。
  2. 计算梯度强度和方向:接下来,通过对平滑后的图像应用Sobel算子,计算每个像素的梯度强度和方向。梯度强度指示了边缘的强度,而方向指示了边缘的方向。
  3. 非极大值抑制:在计算了梯度之后,执行非极大值抑制(Non-maximum suppression)。这一步骤涉及检查每个像素的梯度强度是否是局部最大值。如果不是,则认为该像素不是边缘的一部分,因此将其强度设置为零。
  4. 双阈值检测和边缘连接:最后,应用两个阈值:低阈值和高阈值。高于高阈值的边缘被确认为真正的边缘,而低于低阈值的边缘则被抛弃。介于两阈值之间的边缘仅在与高于高阈值的边缘相连时才被保留,这是为了防止断断续续的边缘。

        Canny算法因其在检测真实边缘的同时最大限度地减少错误检测和响应重复性方面的良好性能而受到推崇。在OpenCV中,可以通过调用Canny函数来应用Canny算法进行边缘检测

Canny函数

        该函数使用Canny算法在输入图像中查找边缘,并在输出映射edges中标记它们。在threshold1和threshold2之间,较小的值用于边缘连接,而较大的值用于寻找初始的强边缘段。更多信息请参考Canny边缘检测器的维基百科页面:http://en.wikipedia.org/wiki/Canny_edge_detector

函数原型1

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

参数1

  • 参数image 8位输入图像.通常应该是灰度图像
  • 参数 edges 输出的边缘图;单通道8位图像,其尺寸与image相同.这个输出图像将标记出检测到的边缘
  • 参数threshold1 滞后阈值程序的第一阈值,这是一个较低的阈值,用于确定哪些边缘应被进一步考虑。低于此阈值的像素会被视为非边缘
  • 参数threshold2 滞后阈值程序的第二阈值。这是一个较高的阈值,用于确定哪些边缘是强边缘。高于此阈值的像素将被确定为边缘
  • 参数apertureSize Sobel算子的孔径大小。Sobel算子用于计算图像中每个像素的梯度,孔径大小决定了Sobel算子的大小,这会影响边缘检测的精细程度。
  • 参数L2gradient 一个标志,指示是否应该使用更精确的 L 2 L_2 L2 n o r m = ( d I / d x ) 2 + ( d I / d y ) 2 norm=\sqrt{(dI/dx)^2 + (dI/dy)^2} norm=(dI/dx)2+(dI/dy)2 范数来计算图像的梯度大小(L2gradient=true),或者是否默认的 L 1 L_1 L1 n o r m = ∣ d I / d x ∣ + ∣ d I / d y ∣ norm=|dI/dx|+|dI/dy| norm=dI/dx+dI/dy 范数就足够(L2gradient=false)。L2范数是梯度向量的欧几里得长度,而L1范数是梯度分量的绝对值之和。

函数原型2

        这是一个重载成员函数,为了方便而提供。它与上述函数的不同之处仅在于它接受的参数。使用带有自定义图像梯度的Canny算法在图像中查找边缘

void cv::Canny	
(InputArray 	dx,InputArray 	dy,OutputArray 	edges,double 	threshold1,double 	threshold2,bool 	L2gradient = false 
)		

参数2

  • 参数dx 输入图像的16位x方向导数(类型为CV_16SC1或CV_16SC3)。这表示沿着x轴方向的图像梯度。
  • 参数dy 输入图像的16位y方向导数(与dx同类型)。这表示沿着y轴方向的图像梯度。
  • 参数 edges 输出的边缘图;单通道8位图像,其尺寸与image相同.这个输出图像将标记出检测到的边缘
  • 参数threshold1 滞后阈值程序的第一阈值,这是一个较低的阈值,用于确定哪些边缘应被进一步考虑。低于此阈值的像素会被视为非边缘
  • 参数threshold2 滞后阈值程序的第二阈值。这是一个较高的阈值,用于确定哪些边缘是强边缘。高于此阈值的像素将被确定为边缘
  • 参数apertureSize Sobel算子的孔径大小。Sobel算子用于计算图像中每个像素的梯度,孔径大小决定了Sobel算子的大小,这会影响边缘检测的精细程度。
  • 参数L2gradient 一个标志,指示是否应该使用更精确的 L 2 L_2 L2 n o r m = ( d I / d x ) 2 + ( d I / d y ) 2 norm=\sqrt{(dI/dx)^2 + (dI/dy)^2} norm=(dI/dx)2+(dI/dy)2 范数来计算图像的梯度大小(L2gradient=true),或者是否默认的 L 1 L_1 L1 n o r m = ∣ d I / d x ∣ + ∣ d I / d y ∣ norm=|dI/dx|+|dI/dy| norm=dI/dx+dI/dy 范数就足够(L2gradient=false)。L2范数是梯度向量的欧几里得长度,而L1范数是梯度分量的绝对值之和。

代码示例


#include <opencv2/opencv.hpp>
#include <iostream>int main(int argc, char** argv)
{// 读取图像cv::Mat image = cv::imread("/media/dingxin/data/study/OpenCV/sources/images/fruit_small.jpg", cv::IMREAD_COLOR);if (!image.data){std::cout << "Error: Could not open or find the image." << std::endl;return -1;}// 转换为灰度图像cv::Mat grayImage;cv::cvtColor(image, grayImage, cv::COLOR_BGR2GRAY);// 使用Canny算法检测边缘cv::Mat edges;int lowThreshold = 50;int highThreshold = 150;cv::Canny(grayImage, edges, lowThreshold, highThreshold);// 显示原始图像和边缘图像cv::namedWindow("Original Image", cv::WINDOW_NORMAL);cv::imshow("Original Image", image);cv::namedWindow("Edges", cv::WINDOW_NORMAL);cv::imshow("Edges", edges);// 等待按键后关闭窗口cv::waitKey(0);return 0;
}

运行结果

原图:
在这里插入图片描述
边缘计算之后的图:
在这里插入图片描述
你可以调整lowThreshold和highThreshold的值再运行后观察边缘图像的变化,便于理解函数的使用。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • C++中的多重继承和虚继承:横向继承、纵向继承和联合继承;虚继承
  • 后端工作之一:CrapApi —— API接口管理系统部署
  • 【服务器】在Linux查看运行的Python程序,并找到特定的Python程序
  • HW期间——应急响应
  • 什么是边缘计算?创造一个更快、更智慧、更互联的世界
  • Selenium 等待
  • 图像类别生成数字标签
  • C++基础篇(1)
  • 在ROS (Robot Operating System) 中,查看话题(topics)
  • 从0构建一款appium-inspector工具
  • aop的几种动态代理以及简单案例(1)
  • nginx配置ssl证书
  • JavaWeb__正则表达式
  • 27. 738.单调递增的数字,968.监控二叉树,贪心算法总结
  • 访问控制列表
  • 【编码】-360实习笔试编程题(二)-2016.03.29
  • ComponentOne 2017 V2版本正式发布
  • Git 使用集
  • hadoop集群管理系统搭建规划说明
  • MySQL数据库运维之数据恢复
  • nginx 配置多 域名 + 多 https
  • PHP变量
  • SpingCloudBus整合RabbitMQ
  • Yeoman_Bower_Grunt
  • 阿里中间件开源组件:Sentinel 0.2.0正式发布
  • 闭包,sync使用细节
  • 程序员该如何有效的找工作?
  • - 概述 - 《设计模式(极简c++版)》
  • 开源中国专访:Chameleon原理首发,其它跨多端统一框架都是假的?
  • 使用agvtool更改app version/build
  • 微服务框架lagom
  • 智能合约开发环境搭建及Hello World合约
  • mysql 慢查询分析工具:pt-query-digest 在mac 上的安装使用 ...
  • 积累各种好的链接
  • # Spring Cloud Alibaba Nacos_配置中心与服务发现(四)
  • $.each()与$(selector).each()
  • (1)SpringCloud 整合Python
  • (3)llvm ir转换过程
  • (八十八)VFL语言初步 - 实现布局
  • (第8天)保姆级 PL/SQL Developer 安装与配置
  • (附源码)springboot家庭装修管理系统 毕业设计 613205
  • (免费领源码)Java#Springboot#mysql农产品销售管理系统47627-计算机毕业设计项目选题推荐
  • (七)c52学习之旅-中断
  • (四)activit5.23.0修复跟踪高亮显示BUG
  • (一)Thymeleaf用法——Thymeleaf简介
  • (状压dp)uva 10817 Headmaster's Headache
  • ./mysql.server: 没有那个文件或目录_Linux下安装MySQL出现“ls: /var/lib/mysql/*.pid: 没有那个文件或目录”...
  • .Net Attribute详解(上)-Attribute本质以及一个简单示例
  • .NET Core实战项目之CMS 第一章 入门篇-开篇及总体规划
  • .NET 使用 JustAssembly 比较两个不同版本程序集的 API 变化
  • .NET(C#) Internals: as a developer, .net framework in my eyes
  • .NET6实现破解Modbus poll点表配置文件
  • .考试倒计时43天!来提分啦!
  • 。Net下Windows服务程序开发疑惑
  • @JsonSerialize注解的使用