【opencv】示例-detect_blob.cpp

05e10ae22e0f10301f0f1ace0e13a56f.png

764203c69015800b0c0d6f58223f1868.png

6e2add132197607c548e86e92aae02c3.png

e197626577d5b4ba5e91c4bf366be8d0.png

ecc63488fee20b0fde586c7bd1f65959.png

0814de97e6dd604f81da14ff860a379f.png

d77827d8c37e379862cca7ac8b890bd5.png

e3efe6ee0ef4fd6b7b0039269e4dc7bf.png

// 导入所需的OpenCV头文件
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/features2d.hpp>
// 导入向量和映射容器
#include <vector>
#include <map>
// 导入输入输出流库
#include <iostream>// 使用标准命名空间和OpenCV命名空间,避免在使用这些命名空间下的类型和函数时反复输入std::和cv::
using namespace std;
using namespace cv;// 帮助函数,用于提供程序的使用说明
static void help(char** argv)
{cout << "\n This program demonstrates how to use BLOB to detect and filter region \n"<< "Usage: \n"<< argv[0]<< " <image1(detect_blob.png as default)>\n"<< "Press a key when image window is active to change descriptor";
}// 函数Legende用于根据SimpleBlobDetector的参数pAct生成不同Blob检测条件的文字描述
static String Legende(SimpleBlobDetector::Params &pAct)
{// 创建一个空字符串s,用于存放最终生成的描述文字String s = "";// 如果启用了面积过滤器filterByAreaif (pAct.filterByArea){// 将最小面积minArea和最大面积maxArea转换成字符串表示,并追加到s中String inf = static_cast<const ostringstream&>(ostringstream() << pAct.minArea).str();String sup = static_cast<const ostringstream&>(ostringstream() << pAct.maxArea).str();s = " Area range [" + inf + " to  " + sup + "]";}// 如果启用了圆度过滤器filterByCircularityif (pAct.filterByCircularity){// 将最小圆度minCircularity和最大圆度maxCircularity转换成字符串表示,并追加到s中String inf = static_cast<const ostringstream&>(ostringstream() << pAct.minCircularity).str();String sup = static_cast<const ostringstream&>(ostringstream() << pAct.maxCircularity).str();// 判断之前的描述文字s是否为空,如果为空则直接赋值,不为空则添加"AND"进行连接if (s.length() == 0)s = " Circularity range [" + inf + " to  " + sup + "]";elses += " AND Circularity range [" + inf + " to  " + sup + "]";}// 如果启用了颜色过滤器filterByColorif (pAct.filterByColor){// 将Blob的颜色blobColor转换为整数并转换成字符串表示,然后追加到s中String inf = static_cast<const ostringstream&>(ostringstream() << (int)pAct.blobColor).str();// 判断之前的描述文字s是否为空,如果为空则直接赋值,不为空则添加"AND"进行连接if (s.length() == 0)s = " Blob color " + inf;elses += " AND Blob color " + inf;}// 如果启用了凸度过滤器filterByConvexityif (pAct.filterByConvexity){// 将最小凸度minConvexity和最大凸度maxConvexity转换成字符串表示,并追加到s中String inf = static_cast<const ostringstream&>(ostringstream() << pAct.minConvexity).str();String sup = static_cast<const ostringstream&>(ostringstream() << pAct.maxConvexity).str();// 判断之前的描述文字s是否为空,如果为空则直接赋值,不为空则添加"AND"进行连接if (s.length() == 0)s = " Convexity range[" + inf + " to  " + sup + "]";elses += " AND  Convexity range[" + inf + " to  " + sup + "]";}// 如果启用了惯性比过滤器filterByInertiaif (pAct.filterByInertia){// 将最小惯性比minInertiaRatio和最大惯性比maxInertiaRatio转换成字符串表示,并追加到s中String inf = static_cast<const ostringstream&>(ostringstream() << pAct.minInertiaRatio).str();String sup = static_cast<const ostringstream&>(ostringstream() << pAct.maxInertiaRatio).str();// 判断之前的描述文字s是否为空,如果为空则直接赋值,不为空则添加"AND"进行连接if (s.length() == 0)s = " Inertia ratio range [" + inf + " to  " + sup + "]";elses += " AND  Inertia ratio range [" + inf + " to  " + sup + "]";}// 返回最终生成的Blob检测条件描述文字return s;
}// 主函数
int main(int argc, char *argv[])
{// 用于存储读取的文件名String fileName;// 创建命令行解析器,用于处理通过命令行传入的参数cv::CommandLineParser parser(argc, argv, "{@input |detect_blob.png| }{h help | | }");// 如果有"-h"或"--help"参数,显示帮助信息后结束程序if (parser.has("h")){help(argv);return 0;}// 如果没有提供输入文件名参数,则使用默认的"detect_blob.png"fileName = parser.get<string>("@input");// 读取并存储图像Mat img = imread(samples::findFile(fileName), IMREAD_COLOR);// 如果读取失败或图像为空,则输出错误信息并结束程序if (img.empty()){cout << "Image " << fileName << " is empty or cannot be found\n";return 1;}// 初始化SimpleBlobDetector的默认参数SimpleBlobDetector::Params pDefaultBLOB;// 设置默认的BLOB检测器的参数// 设置SimpleBlobDetector的阈值步长pDefaultBLOB.thresholdStep = 10;// 设置SimpleBlobDetector的最小阈值pDefaultBLOB.minThreshold = 10;// 设置SimpleBlobDetector的最大阈值pDefaultBLOB.maxThreshold = 220;// 设置SimpleBlobDetector的最小重复性pDefaultBLOB.minRepeatability = 2;// 设置SimpleBlobDetector的BLOB之间的最小距离pDefaultBLOB.minDistBetweenBlobs = 10;pDefaultBLOB.filterByColor = false; // 不按颜色过滤pDefaultBLOB.blobColor = 0; // BLOB的默认颜色pDefaultBLOB.filterByArea = false; // 不按区域大小过滤pDefaultBLOB.minArea = 25; // 最小区域大小pDefaultBLOB.maxArea = 5000; // 最大区域大小pDefaultBLOB.filterByCircularity = false; // 不按圆度过滤pDefaultBLOB.minCircularity = 0.9f; // 最小圆度pDefaultBLOB.maxCircularity = (float)1e37; // 设置一个非常大的数,代表无上限pDefaultBLOB.filterByInertia = false; // 不按惯性比过滤pDefaultBLOB.minInertiaRatio = 0.1f; // 最小惯性比pDefaultBLOB.maxInertiaRatio = (float)1e37; // 设置一个非常大的数,代表无上限pDefaultBLOB.filterByConvexity = false; // 不按凸度过滤pDefaultBLOB.minConvexity = 0.95f; // 最小凸度pDefaultBLOB.maxConvexity = (float)1e37; // 设置一个非常大的数,代表无上限// 存储BLOB类型描述符的字符串向量vector<String> typeDesc;// 存储不同BLOB参数的向量vector<SimpleBlobDetector::Params> pBLOB;// BLOB参数向量的迭代器vector<SimpleBlobDetector::Params>::iterator itBLOB;// 初始化一个颜色调色板,用于给不同的BLOB着色vector< Vec3b >  palette;// 随机生成调色板中的颜色for (int i = 0; i<65536; i++){uchar c1 = (uchar)rand();uchar c2 = (uchar)rand();uchar c3 = (uchar)rand();palette.push_back(Vec3b(c1, c2, c3));}// 调用help函数显示帮助信息help(argv);// 下面代码将创建不同参数的BLOB检测器,并显示它们的结果// 配置六种不同参数的BLOB检测器// 例如,第一个检测器我们要检测所有BLOB// 对每种类型描述符进行初始化,然后按不同的过滤条件修改参数// 将"BLOB"类型推入描述符类型向量typeDesc.push_back("BLOB");    // 参见OpenCV官方文档SimpleBlobDetector类的描述pBLOB.push_back(pDefaultBLOB); // 将默认BLOB参数推入参数向量pBLOB.back().filterByArea = true; // 启用面积过滤pBLOB.back().minArea = 1; // 设置筛选的最小面积pBLOB.back().maxArea = float(img.rows * img.cols); // 设置筛选的最大面积为图像的总面积// 第二个BLOB检测器的参数设置:要求检测面积在500到2900像素之间的区域typeDesc.push_back("BLOB"); // 类型描述符追加"BLOB"pBLOB.push_back(pDefaultBLOB); // 使用默认参数作为基础pBLOB.back().filterByArea = true; // 启用面积过滤pBLOB.back().minArea = 500; // 设置最小面积为500像素pBLOB.back().maxArea = 2900; // 设置最大面积为2900像素// 第三个BLOB检测器的参数设置:仅检测圆形物体typeDesc.push_back("BLOB"); // 类型描述符追加"BLOB"pBLOB.push_back(pDefaultBLOB); // 使用默认参数作为基础pBLOB.back().filterByCircularity = true; // 启用圆度过滤// 第四个BLOB检测器的参数设置:根据惯性比进行筛选typeDesc.push_back("BLOB"); // 类型描述符追加"BLOB"pBLOB.push_back(pDefaultBLOB); // 使用默认参数作为基础pBLOB.back().filterByInertia = true; // 启用惯性比过滤pBLOB.back().minInertiaRatio = 0; // 设置最小惯性比为0pBLOB.back().maxInertiaRatio = (float)0.2; // 设置最大惯性比为0.2// 第五个BLOB检测器的参数设置:根据凸度进行筛选typeDesc.push_back("BLOB"); // 类型描述符追加"BLOB"pBLOB.push_back(pDefaultBLOB); // 使用默认参数作为基础pBLOB.back().filterByConvexity = true; // 启用凸度过滤pBLOB.back().minConvexity = 0.; // 设置最小凸度为0pBLOB.back().maxConvexity = (float)0.9; // 设置最大凸度为0.9// 第六个BLOB检测器的参数设置:检测重心颜色为0的BLOBtypeDesc.push_back("BLOB"); // 类型描述符追加"BLOB"pBLOB.push_back(pDefaultBLOB); // 使用默认参数作为基础pBLOB.back().filterByColor = true; // 启用颜色过滤pBLOB.back().blobColor = 0; // 设置筛选的BLOB颜色为0// 迭代器指向BLOB参数向量的起始位置itBLOB = pBLOB.begin();// 存储比较结果的向量vector<double> desMethCmp;// 创建Feature2D的智能指针,用于后续的特征检测Ptr<Feature2D> b;// 用于存储文本标签String label;// 循环遍历所有类型描述符vector<String>::iterator itDesc;for (itDesc = typeDesc.begin(); itDesc != typeDesc.end(); ++itDesc){// 存储检测到的关键点vector<KeyPoint> keyImg1;// 对于BLOB类型描述符if (*itDesc == "BLOB"){b = SimpleBlobDetector::create(*itBLOB); // 创建BLOB检测器label = Legende(*itBLOB); // 生成描述字符串++itBLOB; // 移动到下一个参数集}// 错误处理try{// 存储检测到的关键点vector<KeyPoint>  keyImg;vector<Rect>  zone;vector<vector <Point> >  region;// 创建用于描述的矩阵和结果显示的图像Mat     desc, result(img.rows, img.cols, CV_8UC3);// 如果是SimpleBlobDetectorif (b.dynamicCast<SimpleBlobDetector>().get()){// 动态转换为SimpleBlobDetectorPtr<SimpleBlobDetector> sbd = b.dynamicCast<SimpleBlobDetector>();// 使用SimpleBlobDetector检测关键点sbd->detect(img, keyImg, Mat());// 绘制检测到的关键点drawKeypoints(img, keyImg, result);// 遍历关键点,并在结果图中用圆圈表示int i = 0;for (vector<KeyPoint>::iterator k = keyImg.begin(); k != keyImg.end(); ++k, ++i)circle(result, k->pt, (int)k->size, palette[i % 65536]);}// 创建窗口显示结果namedWindow(*itDesc + label, WINDOW_AUTOSIZE);imshow(*itDesc + label, result);// 显示原始图像imshow("Original", img);// 等待用户响应waitKey();}catch (const Exception& e){// 如果发生错误,则打印错误信息cout << "Feature : " << *itDesc << "\n";cout << e.msg << endl;}}// 程序正常退出return 0;
}

这段代码是使用OpenCV库编写的C++源码,用于演示如何通过SimpleBlobDetector类检测图像中的BLOB(Binary Large Object,二进制大对象),并根据不同参数过滤和显示检测到的区域。BLOB主要用于分割图像中具有不同特性(如面积、颜色、凸性等)的连续区域。代码中包括Blob检测参数的配置、随机颜色调色板的生成、关键点检测、过滤条件的文字描述生成、图像的显示以及异常处理。通过更改SimpleBlobDetector的参数,用户可以筛选满足特定条件的图像区域,比如特定大小、形状或颜色的物体。

b.dynamicCast<SimpleBlobDetector>().get()

0b3d47b0f59195b7de388f2629a8a3f1.png

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

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

相关文章

微软卡内基梅隆大学:无外部干预,GPT4等大语言模型难以自主探索

目录 引言&#xff1a;LLMs在强化学习中的探索能力探究 研究背景&#xff1a;LLMs的在情境中学习能力及其重要性 实验设计&#xff1a;多臂老虎机环境中的LLMs探索行为 实验结果概览&#xff1a;LLMs在探索任务中的普遍失败 成功案例分析&#xff1a;Gpt-4在特定配置下的探…

【QT入门】Qt自定义控件与样式设计之qss的加载方式

往期回顾 【QT入门】 Qt自定义控件与样式设计之QPushButton点击按钮弹出菜单-CSDN博客 【QT入门】Qt自定义控件与样式设计之QProgressBar用法及qss-CSDN博客 【QT入门】 Qt自定义控件与样式设计之QSlider用法及qss-CSDN博客 【QT入门】Qt自定义控件与样式设计之qss的加载方式 …

JDBC看这一篇就够了

JDBC核心技术 第1章&#xff1a;JDBC概述 1.1 数据的持久化 持久化(persistence)&#xff1a;把数据保存到可掉电式存储设备中以供之后使用。大多数情况下&#xff0c;特别是企业级应用&#xff0c;数据持久化意味着将内存中的数据保存到硬盘上加以”固化”&#xff0c;而持久…

centos7上docker搭建vulhub靶场

1 vulhub靶场概述 VulHub是一个在线靶场平台&#xff0c;提供了丰富的漏洞环境供安全爱好者学习和实践。 该平台主要面向网络安全初学者和进阶者&#xff0c;通过模拟真实的漏洞环境&#xff0c;帮助用户深入了解漏洞的成因、利用方式以及防范措施。 此外&#xff0c;VulHub还…

Kubernetes学习笔记7

使用kubeadm部署Kubernetes集群方法 使用kubernetes部署单节点Master节点K8s集群。 在实际生产环境中&#xff0c;是不允许单master节点的&#xff0c;如果单master节点不可用的话&#xff0c;当导致我们的K8s集群无法访问。 可以使用kubeadm将单master节点升级为多master节点…

智能制造六大核心发展方向,驱动企业数字化转型

在制造过程中&#xff0c;智能制造展现出非凡的活力&#xff0c;它使人与智能机器的协同工作成为可能。这不仅将制造自动化的概念提升至一个新的层次&#xff0c;更将其扩展至柔性化、智能化和高度集成化的领域。通过这样的革新&#xff0c;我们得以实现数字化智能工厂的落地生…

Linux的学习之路:5、粘滞位与vim

摘要 这里主要是把上章没说完的权限的粘滞位说一下&#xff0c;然后就是vim的一些操作。 目录 摘要 一、粘滞位 二、权限总结 三、vim的基本概念 四、vim的基本操作 五、vim正常模式命令集 1、插入模式 2、从插入模式切换为命令模式 3、移动光标 4、删除文字 5、复…

Spring MVC体系结构和处理请求控制器(一)

一、MVC模式 MVC模式是指Model-View-Controller&#xff08;模型-视图-控制器&#xff09;模式&#xff0c;是开发Web应用程序时常用的一种代码分层模式MVC模式是软件工程中的一种架构模式&#xff0c;会强制行的把系统的输入、处理和输出分开&#xff0c;是系统从功能上形成M…

我的小程序接口被刷爆了

自然流量的惊喜 书接上文&#xff0c;凭着短视频的好奇&#xff0c;搭了个小程序&#xff0c;做了文案提取&#xff0c;配音等功能&#xff0c;也顺带写了两篇口水文章&#xff0c;不曾想居然收获历史最高的点赞与收藏。有兴趣的朋友可以点这里一看究尽&#xff1a;《短视频配音…

B02、GC日志分析-案例演示-6.4

1、案例一&#xff1a;堆溢出演示 1.1、简单springboot项目创建 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:s…

环形队列的简单理解

多次遇到环形队列的情况&#xff0c;记不住什么情况是队列满&#xff0c;什么情况是队列空。一直也没有理解透彻。 仔细研究了一下&#xff0c;掌握了一些原理&#xff0c;记录一下。 1. 环形队列有一个头指针head&#xff0c;一个为指针tail。有一个疑问&#xff1a;head和ta…

更换淘宝镜像地址,旧的已经失效(https://registry.npm.taobao.org )

旧的镜像地址&#xff1a;npm install --registryhttps://registry.npm.taobao.org 新的镜像地址&#xff1a;npm install --registryhttps://registry.npmmirror.com

【2024最新博客美化教程重置版】今天教你如何使用SimpleMemory美化你的博客,体会一下大神是如何装逼的!

&#x1f680; 个人主页 极客小俊 ✍&#x1f3fb; 作者简介&#xff1a;程序猿、设计师、技术分享 &#x1f40b; 希望大家多多支持, 我们一起学习和进步&#xff01; &#x1f3c5; 欢迎评论 ❤️点赞&#x1f4ac;评论 &#x1f4c2;收藏 &#x1f4c2;加关注 SimpleMemory …

【算法基础】插入排序与二分查找、升级二分查找

文章目录 1. 插入排序1.1 插入排序的思想1.2 插入排序的实现 2. 普通二分查找2.1 普通二分查找的思想2.2 普通二分查找的实现 3. 升级二分查找3.1 升级二分查找思想3.2 升级二分查找实现 1. 插入排序 1.1 插入排序的思想 插入排序很类似于已有一副有序的扑克牌&#xff0c;不断…

【话题】AI技术创业有那些机会,简单探讨下

大家好&#xff0c;我是全栈小5&#xff0c;欢迎阅读小5的系列文章&#xff0c;这是《话题》系列文章 目录 背景机会一、引言二、AI技术的创业机遇1.智能服务行业的兴起2.数据驱动的业务模式创新3.AI与产业融合的创新发展 三、AI技术创业的挑战1.技术门槛高2.法规政策的不确定性…

P1712 [NOI2016] 区间(线段树 + 贪心 + 双指针)

题目描述 在数轴上有 n 个闭区间从 1 至 n 编号&#xff0c;第 i 个闭区间为 [li​,ri​] 。 现在要从中选出 m 个区间&#xff0c;使得这 m 个区间共同包含至少一个位置。换句话说&#xff0c;就是使得存在一个 x &#xff0c;使得对于每一个被选中的区间 [li​,ri​]&#…

关于Ansible模块 ⑥

转载说明&#xff1a;如果您喜欢这篇文章并打算转载它&#xff0c;请私信作者取得授权。感谢您喜爱本文&#xff0c;请文明转载&#xff0c;谢谢。 内容在继《关于Ansible的模块 ①》、《关于Ansible的模块 ②》、《关于Ansible的模块 ③》、《关于Ansible的模块 ④》与《关于a…

YOLOv8草莓生长状态(灰叶病缺钙需要肥料)检测系统(python开发,带有训练模型,可以重新训练,并有Pyqt5界面可视化)

本次检测系统&#xff0c;不仅可以检测图片、视频或摄像头当中出现的草莓叶子是否有灰叶病&#xff0c;还可以检测出草莓叶是否缺钙、是否需要施肥等状态。基于最新的YOLO-v8训练的草莓生长状态检测模型和完整的python代码以及草莓的训练数据&#xff0c;下载后即可运行&#x…

C语言——字符函数和字符串函数

Hello&#xff0c;大家好&#xff0c;今天和大家分享C语言中的几个字符函数和字符串函数&#xff0c;记得三连支持一下哦&#xff01; 在编程的过程中&#xff0c;我们经常要处理字符和字符串&#xff0c;为了⽅便操作字符和字符串&#xff0c;C语⾔标准库中提供了⼀系列库函数…

积分短信群发平台:精准营销新利器,助力企业高效触达目标用户

在当今数字化营销时代&#xff0c;精准营销已成为企业获取竞争优势的关键手段。积分短信群发平台作为一种高效、精准的营销工具&#xff0c;正逐渐受到越来越多企业的青睐。通过该平台&#xff0c;企业可以针对目标用户进行个性化的积分活动推广&#xff0c;实现精准营销&#…