【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.rhkb.cn/news/306025.html

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

相关文章

【RV1106的ISP使用记录之二】设备树的构建

基于MIPI接口的两种摄像头接入方式&#xff0c;理清楚各链路关系&#xff0c;方便后续的开发调试工作&#xff0c;先上一张图&#xff0c;后面再补充解释。

Parameter-Efficient Fine-Tuning for Large Models: A Comprehensive Survey

Parameter-Efficient Fine-Tuning for Large Models: A Comprehensive Survey PDF: https://arxiv.org/pdf/2403.14608.pdf 1 概述 大型模型在多个领域取得了显著进展&#xff0c;但它们的大规模参数带来了高昂的计算成本。这些模型需要大量资源来执行&#xff0c;尤其是在针…

强化学习基础概念入门

文章目录 1. 什么是强化学习&#xff1f;2. 强化学习的基本元素3. 相关衍生元素3.1 策略(Policy)3.2 状态转移(State Transition)3.3 回报(Return)3.4 价值函数(Value Function) 4. 算法分类4.1 按环境是否已知划分4.2 按学习方式划分4.3 按学习目标划分 参考资料 1. 什么是强化…

农业小型气象站解析

TH-NQ12农业小型气象站&#xff0c;作为现代智慧农业体系的重要组成部分&#xff0c;以其独特的优势在农业生产中发挥着不可或缺的作用。这种专为农业领域设计的小型气象站&#xff0c;不仅具备高度自动化和智能化的特点&#xff0c;而且能够实时监测和记录农田环境中的多种气象…

QT:QMainWindow、ui界面、资源文件的添加、信号和槽

1.练习&#xff1a;使用手动连接&#xff0c;将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中&#xff0c;在自定义的槽函数中调用关闭函数 #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(…

[python] Numpy库用法(持续更新)

先导入一下 import numpy as np 一、np.random用法 生成随机整数&#xff1a;np.random.randint(low, high, size) low: 最小值high: 最大值size: 生成的数组大小&#xff08;可以是多维&#xff0c;下面同理&#xff09; 生成随机浮点数&#xff1a;np.random.uniform(low, …

Ubuntu 22.04进行远程桌面连接

文心一言 Ubuntu 22.04进行远程桌面连接&#xff0c;无论是连接到Windows 10还是另一个Ubuntu 22.04&#xff0c;都可以通过不同的方式实现。以下是具体的步骤&#xff1a; 连接到Windows 10 在Windows 10上开启远程桌面功能&#xff1a;首先&#xff0c;需要在Windows 10上…

ViT:拉开Trasnformer在图像领域正式挑战CNN的序幕 | ICLR 2021

论文直接将纯Trasnformer应用于图像识别&#xff0c;是Trasnformer在图像领域正式挑战CNN的开山之作。这种简单的可扩展结构在与大型数据集的预训练相结合时&#xff0c;效果出奇的好。在许多图像分类数据集上都符合或超过了SOTA&#xff0c;同时预训练的成本也相对较低   来源…

深入理解MD5算法:原理、应用与安全

title: 深入理解MD5算法&#xff1a;原理、应用与安全 date: 2024/4/11 20:55:57 updated: 2024/4/11 20:55:57 tags: MD5算法数据安全哈希函数摘要算法安全漏洞SHA算法密码学 第一章&#xff1a;引言 导言 在当今数字化时代&#xff0c;数据安全和完整性变得至关重要。消息…

【学习路径】AI入门路线分享

近期整理飞书文档&#xff0c;一些权限被关掉了。看好多人在申请访问这个飞书文档&#xff0c;于是把它单独拿出来放在CSDN上&#xff0c;供大家参考~ 原视频地址&#xff1a;AI&#xff1a;从小白到入门&#xff0c;超详细人工智能成长路径分享_哔哩哔哩_bilibili 文章目录 1.…

HarmonyOS实战开发-证书管理、如何实现对签名数据进行校验功能。

介绍 本示例使用了ohos.security.certManager相关接口实现了对签名数据进行校验的功能。 实现场景如下&#xff1a; 1&#xff09;使用正确的原始数据和签名数据进行签名校验场景&#xff1a;模拟服务端对签名数据进行校验&#xff0c;验证客户端身份和原始数据完整性。 2&…

【安装部署】国产数据库OpenGauss的安装部署以及问题排查解决(全网唯一一个解决的!含源码分析)

国产数据库OpenGauss的安装部署以及问题排查解决(含源码分析) 💖点赞超100,将取消VIP文章,免费公开 前面都是一些排除得方式,如果想知道最终的问题,可以直接切换到3.3章节 💖如果您需要这篇文章可以扫描下方的公众号二维码,私信我们,我们将帮您解答 目录 国产数…

CentOS7安装MySQL8.0教程

环境介绍 操作系统&#xff1a;Centos7.6 MySQL版本&#xff1a; 8.0.27 只要是8.0.*版本&#xff0c;那就可以按照本文说明安装 一、安装前准备 1、卸载MariaDB 安装MySQL的话会和MariaDB的文件冲突&#xff0c;所以需要先卸载掉MariaDB。 1.1、查看是否安装mariadb rpm -…

AI大模型探索之路-应用篇10:Langchain框架-架构核心洞察

目录 前言 一、LangChain设计目标 二、LangChain设计之道 三、LangChain典型应用 1、简单的问答Q&A over SQL CSV: 2、聊天机器人Chatbots: 3、总结摘要Summarization: 4、网页爬虫Web scraping: 5、本地知识库&#xff08;Q&A with RAG): 三、LangChain架构…

blender安装mmd并导入pmx,pmd文件

点击链接GitHub上下载这个&#xff0c;值得注意的是blender4.0以上版本暂时不支持&#xff0c;这里使用的是blender3.6版本GitHub - powroupi/blender_mmd_tools: mmd_tools is a blender addon for importing Models and Motions of MikuMikuDance. 复制当前内容 粘贴到当前…

组合数学<1>——组合数学基础

今天我们聊聊组合数学。(本期是给刚刚学习组合数学的同学看的&#xff0c;dalao们可以自行忽略) 建议:不会求逆元的出门左转数论<2>&#xff0c;不会数论的出门右转数论<1>。 加乘原理 加乘原理小学奥数就有。 总的来说:加法原理:分类;乘法原理:分步 比如说&a…

中国网站数量竟然比2022年多了10000个

关注卢松松&#xff0c;会经常给你分享一些我的经验和观点。 CNNIC发布了最新中国互联网报告&#xff0c;报告显示&#xff1a; 2018年中国有523万个网站&#xff0c;2023年13月下降到388万个&#xff0c;5年时间网站数量下降30%&#xff0c;但相比于2022年12月&#xff0c;竟…

ThinkPHP审计(1) 不安全的SQL注入PHP反序列化链子phar利用简单的CMS审计实例

ThinkPHP代码审计(1) 不安全的SQL注入&PHP反序列化链子phar利用&简单的CMS审计实例 文章目录 ThinkPHP代码审计(1) 不安全的SQL注入&PHP反序列化链子phar利用&简单的CMS审计实例一.Thinkphp5不安全的SQL写法二.Thinkphp3 SQL注入三.Thinkphp链5.1.x结合phar实现…

第6章 6.3.1 正则表达式的语法(MATLAB入门课程)

讲解视频&#xff1a;可以在bilibili搜索《MATLAB教程新手入门篇——数学建模清风主讲》。​ MATLAB教程新手入门篇&#xff08;数学建模清风主讲&#xff0c;适合零基础同学观看&#xff09;_哔哩哔哩_bilibili 正则表达式可以由一般的字符、转义字符、元字符、限定符等元素组…

普通函数和箭头函数的区别

普通函数和箭头函数在JavaScript中主要有以下区别&#xff1a; 语法形式。箭头函数使用简洁的箭头语法>定义&#xff0c;不需要像普通函数那样使用function关键字。匿名性。箭头函数只能是匿名的&#xff0c;而普通函数可以是匿名的&#xff0c;也可以具有具体的名称。this…