OpenCV 为轮廓创建边界框和圆(62)

 返回:OpenCV系列文章目录(持续更新中......)

上一篇:OpenCV检测凸包(61)
下一篇 :OpenCV如何为等值线创建边界旋转框和椭圆(62)

目标

在本教程中,您将学习如何:

  • 使用 OpenCV 函数 cv::boundingRect
  • 使用 OpenCV 函数 cv::minEnclosingCircle

cv::boundingRect 和 cv::minEnclosingCircle 都是 OpenCV 库中常用的图像处理函数,主要用于轮廓绘制和弧形分析等操作。

cv::boundingRect 是一个用于计算轮廓边界的函数,它可以计算由轮廓点定义的矩形边框。该函数的主要思路是,在轮廓点坐标系中寻找最小的水平矩形(或垂直矩形),然后返回该矩形的左上角坐标和宽度、高度等信息。通过 boundingRect 函数,我们可以实现轮廓的外边框计算和绘制操作,使得轮廓分析更加精确和直观。

cv::minEnclosingCircle 则是一个用于计算轮廓最小外接圆的函数,它可以计算由轮廓点定义的最小圆形。该函数的主要思路是,在轮廓点中寻找最小的能包含所有点的圆形,然后返回该圆的圆心和半径信息。通过 minEnclosingCircle 函数,我们可以实现轮廓的最小外接圆计算和绘制,同时也可以实现对弧形、角度等特征的计算和分析。

cv::boundingRect 和 cv::minEnclosingCircle 通常会一起使用。它们可以用于轮廓分析、目标跟踪、形状检测等操作。通过 boundingRect 函数计算轮廓的边框,我们可以确定轮廓的矩形区域,从而实现轮廓的定位和绘制操作;通过 minEnclosingCircle 函数计算轮廓的最小圆形,我们可以确定轮廓的圆形区域,并计算出圆形的特征,从而实现更加精确的轮廓分析和检测。

C++代码

本教程代码如下所示。您也可以从这里下载

#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>using namespace cv;
using namespace std;Mat src_gray;
int thresh = 100;
RNG rng(12345);void thresh_callback(int, void* );int main( int argc, char** argv )
{CommandLineParser parser( argc, argv, "{@input | stuff.jpg | input image}" );Mat src = imread( samples::findFile( parser.get<String>( "@input" ) ) );if( src.empty() ){cout << "Could not open or find the image!\n" << endl;cout << "usage: " << argv[0] << " <Input image>" << endl;return -1;}cvtColor( src, src_gray, COLOR_BGR2GRAY );blur( src_gray, src_gray, Size(3,3) );const char* source_window = "Source";namedWindow( source_window );imshow( source_window, src );const int max_thresh = 255;createTrackbar( "Canny thresh:", source_window, &thresh, max_thresh, thresh_callback );thresh_callback( 0, 0 );waitKey();return 0;
}void thresh_callback(int, void* )
{Mat canny_output;Canny( src_gray, canny_output, thresh, thresh*2 );vector<vector<Point> > contours;findContours( canny_output, contours, RETR_TREE, CHAIN_APPROX_SIMPLE );vector<vector<Point> > contours_poly( contours.size() );vector<Rect> boundRect( contours.size() );vector<Point2f>centers( contours.size() );vector<float>radius( contours.size() );for( size_t i = 0; i < contours.size(); i++ ){approxPolyDP( contours[i], contours_poly[i], 3, true );boundRect[i] = boundingRect( contours_poly[i] );minEnclosingCircle( contours_poly[i], centers[i], radius[i] );}Mat drawing = Mat::zeros( canny_output.size(), CV_8UC3 );for( size_t i = 0; i< contours.size(); i++ ){Scalar color = Scalar( rng.uniform(0, 256), rng.uniform(0,256), rng.uniform(0,256) );drawContours( drawing, contours_poly, (int)i, color );rectangle( drawing, boundRect[i].tl(), boundRect[i].br(), color, 2 );circle( drawing, centers[i], (int)radius[i], color, 2 );}imshow( "Contours", drawing );
}

解释

主要功能相当简单,从注释中我们执行以下操作:

  • 打开图像,将其转换为灰度并模糊以消除噪点。
 CommandLineParser parser( argc, argv, "{@input | stuff.jpg | input image}" );Mat src = imread( samples::findFile( parser.get<String>( "@input" ) ) );if( src.empty() ){cout << "Could not open or find the image!\n" << endl;cout << "usage: " << argv[0] << " <Input image>" << endl;return -1;}cvtColor( src, src_gray, COLOR_BGR2GRAY );blur( src_gray, src_gray, Size(3,3) );

  • 创建一个标题为“Source”的窗口,并在其中显示源文件。
 const char* source_window = "Source";namedWindow( source_window );imshow( source_window, src );
  • 在 “Source”的窗口上创建一个跟踪栏,并为其分配回调函数。通常,回调函数用于对某种信号做出反应,在我们的例子中,它是跟踪栏的状态变化。需要显式一次性调用thresh_callback才能同时显示“轮廓”窗口和“源”窗口。
 const int max_thresh = 255;createTrackbar( "Canny thresh:", source_window, &thresh, max_thresh, thresh_callback );thresh_callback( 0, 0 );

回调函数完成了所有需要的工作。

  • 使用 cv::Canny 检测图像中的边缘。
 Mat canny_output;Canny( src_gray, canny_output, thresh, thresh*2 );

  • 查找等值线并将它们保存到向量 contour和hierarchy中
 vector<vector<Point> > contours;findContours( canny_output, contours, RETR_TREE, CHAIN_APPROX_SIMPLE );
  • 对于每个找到的等值线,我们现在以 +-3 的精度对多边形应用近似值,并指出曲线必须闭合。之后,我们为每个多边形找到一个边界矩形并将其保存到boundRect 。最后,我们为每个多边形找到一个最小封闭圆,并将其保存到center 和 radius向量。
 vector<vector<Point> > contours_poly( contours.size() );vector<Rect> boundRect( contours.size() );vector<Point2f>centers( contours.size() );vector<float>radius( contours.size() );for( size_t i = 0; i < contours.size(); i++ ){approxPolyDP( contours[i], contours_poly[i], 3, true );boundRect[i] = boundingRect( contours_poly[i] );minEnclosingCircle( contours_poly[i], centers[i], radius[i] );}

我们找到了我们需要的一切,我们所要做的就是画画。

  • 创建新的无符号 8 位字符垫,填充零。它将包含我们将要制作的所有图纸(矩形和圆形)。
Mat drawing = Mat::zeros( canny_output.size(), CV_8UC3 );

  • 对于每个等值线:选择一种随机颜色,用它绘制轮廓、边界矩形和最小封闭圆。
 for( size_t i = 0; i< contours.size(); i++ ){Scalar color = Scalar( rng.uniform(0, 256), rng.uniform(0,256), rng.uniform(0,256) );drawContours( drawing, contours_poly, (int)i, color );rectangle( drawing, boundRect[i].tl(), boundRect[i].br(), color, 2 );circle( drawing, centers[i], (int)radius[i], color, 2 );}
  • 显示结果:创建一个新窗口“轮廓”,并在其上显示我们添加到图纸中的所有内容。
 imshow( "Contours", drawing );

结果

在这里:


参考文献:

1、《Creating Bounding boxes and circles for contours》------ Ana Huamán

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/6579.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据库(MySQL)—— 事务

数据库&#xff08;MySQL&#xff09;—— 事务 什么是事务事务操作未控制事务测试异常情况 控制事务一查看/设置事务提交方式&#xff1a;提交事务回滚事务 控制事务二开启事务提交事务回滚事务 并发事务问题脏读&#xff08;Dirty Read&#xff09;不可重复读&#xff08;Non…

python在Django中,模板加载器(Template Loaders)是负责查找和加载模板文件的组件

在Django中&#xff0c;模板加载器&#xff08;Template Loaders&#xff09;是负责查找和加载模板文件的组件。Django默认使用django.template.loaders.filesystem.Loader和django.template.loaders.app_directories.Loader这两个加载器&#xff0c;它们分别用于从文件系统和D…

数据结构练习题---环形链表详解

链表成环&#xff0c;在力扣中有这样的两道题目 https://leetcode.cn/problems/linked-list-cycle/ https://leetcode.cn/problems/linked-list-cycle-ii/description/ 这道题的经典解法是利用快慢指针&#xff0c;如果链表是一个环形链表&#xff0c;那么快指针(fast)和慢指…

关于MS-DOS时代的回忆

目录 一、MS-DOS是什么&#xff1f; 二、MS-DOS的主要功能有哪些&#xff1f; 三、MS-DOS的怎么运行的&#xff1f; 四、微软开源MS-DOS源代码 五、高手与漂亮女同学 一、MS-DOS是什么&#xff1f; MS-DOS&#xff08;Microsoft Disk Operating System&#xff09;是微软公…

最基本的c++代码

#include <iostream> #include <string> using namespace std; void james_kobe(); std::string bas() {string name;cout << "请输入您的目的地" << endl;cin >> name;cin.get(); // 消耗掉输入的换行符return name; }std::string ca…

在Nacos中,如何注册和发现服务实例?

在Nacos中注册与发现服务实例 在微服务架构中&#xff0c;服务注册与发现是一个核心组件&#xff0c;它使得服务提供者能够注册自己的服务信息&#xff0c;服务消费者能够发现并调用所需的服务。Nacos&#xff0c;作为阿里巴巴开源的一个更易于构建云原生应用的动态服务发现、…

【SHADER】Shader实例学习2:Loading Wheel

简介 shader代码来自github上一个项目&#xff0c;compose libraries&#xff0c;但是链接找不到了。。。&#xff0c;代码很简洁&#xff0c;但是里面的技巧适合我这种初学者领会。 Shader代码 const float PI 3.14159265359;// 按角度旋转。&#xff08;安卓的坐标由于从…

工作问题记录React(持续更新中)

一、backdrop-filter:blur(20px); 毛玻璃效果&#xff0c;在安卓机上有兼容问题&#xff0c;添加兼容前缀也无效&#xff1b; 解决方案&#xff1a;让设计师调整渐变&#xff0c;不要使用该属性! 复制代码 background: radial-gradient(33% 33% at 100% 5%, #e9e5e5 0%, rgba…

C++类定义时成员变量初始化

在C11中允许在类定义时对成员变量初始化。 class A { public:A() { }void show(){cout << "m_a " << m_a << endl;cout << "m_b " << m_b << endl;} private:int m_a 10;//类定义时初始化int m_b; //没有初始化…

Microsoft 365 for Mac(Office 365)v16.84正式激活版

office 365 for mac包括Word、Excel、PowerPoint、Outlook、OneNote、OneDrive和Teams的更新。Office提供了跨应用程序的功能&#xff0c;帮助用户在更短的时间内创建令人惊叹的内容&#xff0c;您可以在这里创作、沟通、协作并完成重要工作。 Microsoft 365 for Mac(Office 36…

Delta lake with Java--liquid clustering

网上说liquid clustering还是实验阶段&#xff0c;python和scala有对应的函数&#xff0c;java没有&#xff0c;只能用sql语句来建表&#xff0c;尝试了两天&#xff0c;遇到很奇怪的情况&#xff0c;先上代码&#xff1a; import io.delta.tables.DeltaTable; import org.apa…

Debian系统的开机启动和进程看护

1.推荐的做法 - systemctl systemctl&#xff0c;这种做法需要事先编辑一个.service的脚本放在/etc/systemd/system&#xff0c;这里有一个例子&#xff1a; [Unit] DescriptionGuide Rtsp Server - using mediamtx Afternetwork.target[Service] Typesimple WorkingDirecto…

HTML_CSS学习:浮动

一、浮动简介 相关代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>浮动_简介</title><style>div{width: 600px;height: 400px;background-color: #1c80d9;}img{float:…

Rust入门篇:你好,世界

文章目录 前言编写程序编译运行最后 前言 你好&#xff0c;我是醉墨居士&#xff0c;欢迎回来 对于我们大多数人接触一门新的编程语言时&#xff0c;第一个任务一般是编写一个控制台输出hello world的程序 我们这篇博客也是如此&#xff0c;让我们一起使用rust去和世界打个招…

智慧旅游引领旅游行业创新发展:借助智能科技的力量,实现旅游资源的优化配置和高效利用,推动旅游行业的转型升级和可持续发展

目录 一、引言 二、智慧旅游的定义与特点 1、信息化程度高 2、智能化服务丰富 3、互动性强 4、个性化服务突出 5、可持续性发展 三、智慧旅游在旅游行业创新发展中的作用 &#xff08;一&#xff09;优化旅游资源配置 &#xff08;二&#xff09;提升旅游服务质量 &…

VMware虚拟机下载安装教程【超详细】

推荐大佬文章&#xff1a;VMware下载安装教程(超详细)-CSDN博客 目录 一、VMware下载 二、VMware安装 一、VMware下载 1、进入VMware官网 2、点击“Products”&#xff0c;向下滑动 --> 选择“Workstation Pro” 3、向下滑动&#xff0c;找到并选择“Download VMware Wo…

智慧文旅展现文化新风貌,科技助力旅行品质升级:借助智慧技术,文旅产业焕发新生机,为旅行者带来更高品质的文化体验之旅

一、引言 在数字化、智能化的浪潮下&#xff0c;文旅产业正迎来前所未有的发展机遇。智慧文旅作为文旅产业与信息技术深度融合的产物&#xff0c;不仅为旅行者带来了全新的文化体验&#xff0c;也为文旅产业注入了新的活力。本文旨在探讨智慧文旅如何借助智慧技术展现文化新风…

pyinstaller打包pytorch和transformers程序

记录使用pyinstaller打包含有pytorch和transformers库的程序时遇到的问题和解决方法。 环境和版本信息 操作系统&#xff1a;Windows 11 Python&#xff1a;3.10.12 pyinstaller&#xff1a;5.13.0 torch&#xff1a;2.2.2 transformers&#xff1a;4.40.1 打包过程和问…

LLaMA详细解读

LLaMA 是目前为止&#xff0c;效果最好的开源 LLM 之一。精读 LLaMA 的论文及代码&#xff0c;可以很好的了解 LLM 的内部原理。本文对 LLaMA 论文进行了介绍&#xff0c;同时附上了关键部分的代码&#xff0c;并对代码做了注释。 摘要 LLaMA是一个系列模型&#xff0c;模型参…

深入理解 Java 并发:AbstractQueuedSynchronizer 源码分析

序言 在多线程编程中&#xff0c;同步机制是保障线程安全和协调线程之间操作顺序的重要手段。AQS 作为 Java 中同步机制的基础框架&#xff0c;为开发者提供了一个灵活且高效的同步工具。本文将通过对 AQS 源码的分析&#xff0c;解读 AQS 的核心实现原理&#xff0c;并深入探…