详细解释aruco::markdetection _detectInitialCandidates函数

_detectInitialCandidates 是 OpenCV 的 ArUco 模块中一个非常关键的函数,它负责检测图像中的候选 ArUco 标记。该函数的主要目标是:

  • 使用多个尺度(scale)对输入图像进行自适应阈值处理;
  • 在每个尺度下提取轮廓并筛选出符合要求的四边形角点;
  • 将这些候选标记及其对应的轮廓保存到输出参数中。

📌 函数签名

static void _detectInitialCandidates(const Mat &grey,vector<vector<Point2f> > &candidates,vector<vector<Point> > &contours,const DetectorParameters &params)

参数说明:

参数名类型含义
greyconst Mat &输入的灰度图像
candidatesvector<vector<Point2f> > &输出的候选标记角点(4个点组成的矩形)
contoursvector<vector<Point> > &输出的与候选角点对应的完整轮廓信息
paramsconst DetectorParameters &检测器参数,控制检测过程的行为

🔍 功能详解

1️⃣ 设置自适应阈值窗口大小范围

CV_Assert(params.adaptiveThreshWinSizeMin >= 3 && params.adaptiveThreshWinSizeMax >= 3);
CV_Assert(params.adaptiveThreshWinSizeMax >= params.adaptiveThreshWinSizeMin);
CV_Assert(params.adaptiveThreshWinSizeStep > 0);

确保传入的参数合法:

  • 自适应阈值窗口最小和最大尺寸 ≥ 3(OpenCV 要求)
  • 步长必须大于 0

2️⃣ 计算要使用的窗口大小数量(即图像金字塔层数)

int nScales = (params.adaptiveThreshWinSizeMax - params.adaptiveThreshWinSizeMin) /params.adaptiveThreshWinSizeStep + 1;

根据设定的最小、最大窗口大小和步长,计算需要尝试多少种不同的窗口大小。

例如:min=20max=40step=5 → nScales = 5


3️⃣ 为每种窗口大小准备容器

vector<vector<vector<Point2f> > > candidatesArrays((size_t) nScales);
vector<vector<vector<Point> > > contoursArrays((size_t) nScales);

  • candidatesArrays[i]:第 i 个窗口大小下的所有候选标记角点集合。
  • contoursArrays[i]:对应的所有轮廓。

4️⃣ 多线程处理不同尺度(parallel_for_)

parallel_for_(Range(0, nScales), [&](const Range& range) {for (int i = begin; i < end; i++) {int currScale = params.adaptiveThreshWinSizeMin + i * params.adaptiveThreshWinSizeStep;Mat thresh;_threshold(grey, thresh, currScale, params.adaptiveThreshConstant);_findMarkerContours(thresh, candidatesArrays[i], contoursArrays[i],params.minMarkerPerimeterRate, params.maxMarkerPerimeterRate,params.polygonalApproxAccuracyRate, params.minCornerDistanceRate,params.minSideLengthCanonicalImg);}
});

对于每一个窗口大小:
  1. 调用 _threshold() 进行自适应阈值处理
    • 用于将图像二值化,便于后续提取轮廓。
  2. 调用 _findMarkerContours() 提取轮廓并筛选出可能的 ArUco 标记角点
    • 筛选条件包括:周长范围、是否为凸四边形、角点距离等。

5️⃣ 合并所有尺度的结果

for(int i = 0; i < nScales; i++) {for(unsigned int j = 0; j < candidatesArrays[i].size(); j++) {candidates.push_back(candidatesArrays[i][j]);contours.push_back(contoursArrays[i][j]);}
}

将不同尺度下检测到的候选标记统一合并到最终输出变量 candidates 和 contours 中。


🧠 关键辅助函数说明

✅ _threshold()

static void _threshold(InputArray _in, OutputArray _out, int winSize, double constant)
  • 使用 adaptiveThreshold() 对图像进行自适应二值化。
  • 确保窗口大小为奇数。
  • 采用 ADAPTIVE_THRESH_MEAN_C 方法,反向二值化 (THRESH_BINARY_INV)。

✅ _findMarkerContours()

static void _findMarkerContours(const Mat &in,vector<vector<Point2f> > &candidates,vector<vector<Point> > &contoursOut,double minPerimeterRate,double maxPerimeterRate,double accuracyRate,double minCornerDistanceRate,int minSize)

这个函数负责从二值图像中提取轮廓,并筛选出可能是 ArUco 标记的四边形。

主要步骤:
  1. 查找所有轮廓

    findContours(in, contours, RETR_LIST, CHAIN_APPROX_NONE);
  2. 逐个轮廓筛选

    • 周长在指定范围内;
    • 多边形逼近后为凸四边形;
    • 四个角点之间最小距离满足要求;
    • 如果启用 ArUco3 功能,则额外判断最小边长。
  3. 将符合条件的轮廓加入输出

    • 角点存入 candidates
    • 完整轮廓存入 contoursOut

📈 总结流程图

_detectInitialCandidates()
│
├─ 设置参数检查
│
├─ 计算使用多少种窗口大小(nScales)
│
├─ 并行遍历每个窗口大小:
│   ├─ 图像二值化(_threshold)
│   └─ 提取并筛选候选标记(_findMarkerContours)
│       ├─ 查找轮廓
│       ├─ 筛选轮廓(凸四边形、周长、角点距离等)
│       └─ 添加进临时容器
│
└─ 合并所有窗口大小下的结果到输出

🧰 参数影响分析(DetectorParameters)

参数名作用
adaptiveThreshWinSizeMin最小阈值窗口大小,决定最小可检测标记大小
adaptiveThreshWinSizeMax最大阈值窗口大小,决定最大可检测标记大小
adaptiveThreshWinSizeStep窗口大小递增步长
minMarkerPerimeterRate最小周长比例(相对于图像宽度/高度)
maxMarkerPerimeterRate最大周长比例
polygonalApproxAccuracyRate多边形逼近精度比例
minCornerDistanceRate角点间最小距离比例
minSideLengthCanonicalImgArUco3 功能中最小边长限制

📝 示例说明

假设你有如下代码调用:

Mat grey = ...; // 输入灰度图
vector<vector<Point2f>> candidates;
vector<vector<Point>> contours;
DetectorParameters params = DetectorParameters::create();
_detectInitialCandidates(grey, candidates, contours, params);

这段代码会:

  • 使用多个窗口大小对图像进行自适应阈值;
  • 提取轮廓并筛选出潜在的 ArUco 标记;
  • 返回所有候选标记的四个角点坐标及其原始轮廓。

✅ 总结

特性描述
功能检测图像中所有可能的 ArUco 标记候选区域
输入灰度图像、检测参数
输出候选角点列表、对应轮廓列表
关键技术自适应阈值、轮廓检测、多边形逼近、几何筛选
性能优化使用 parallel_for_ 实现多线程加速
后续处理通常交给 _reorderCandidatesCorners() 排序角点顺序

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

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

相关文章

Android 开发中配置 USB 配件模式(Accessory Mode) 配件过滤器的配置

在 Android 开发中配置 USB 配件模式&#xff08;Accessory Mode&#xff09; 的配件过滤器&#xff08;accessory_filter.xml&#xff09;&#xff0c;需要以下步骤&#xff1a; 1. 创建配件过滤器文件 在项目的 res/xml/ 目录下创建 accessory_filter.xml 文件&#xff08;若…

FreeRTOS互斥量

目录 1.使用场合2.函数2.1 创建2.1.1 动态创建2.1.2 静态创建 2.2 删除2.3 释放&#xff08;Give&#xff09;2.4 获取&#xff08;Take&#xff09;2.5 ISR 版本注意事项 3.常规使用流程4.和二进制信号量的对比5.递归锁5.1 死锁5.2 概念5.2.1 问题5.2.2 解决方案&#xff1a;递…

ThinkPad 交换 Ctrl 键和 Fn 键

概述 不知道那个大聪明设计的将fn设置在最左边&#xff0c;xxx&#xff0c;我服了&#xff0c;你这个老六真恶心。 方法 一&#xff1a;BIOS/UEFI 设置&#xff08;推荐&#xff09; 重启 你的 ThinkPad。 在启动时按下 F1&#xff08;或 Enter&#xff0c;再按 F1&#xff0…

`dispatch_source_t` 计时器 vs `NSTimer`:核心差异一览

维度GCD 计时器 (dispatch_source_t)NSTimer依赖机制直接挂在 GCD 队列;底层走 Mach 内核定时源挂在 RunLoop,必须指定 RunLoop & mode线程上下文哪个队列就在哪条线程回调(例中用 dispatch_get_main_queue())总在定时器所在的 RunLoop 线程(默认主线程 & NSDefau…

ubuntu22.04系统安装部署docker和docker compose全过程!

更新系统包 首先&#xff0c;确保系统包是最新的&#xff1a; sudo apt updatesudo apt upgrade -y安装依赖 安装 Docker 所需的依赖包&#xff1a; sudo apt install -y apt-transport-https ca-certificates curl software-properties-common添加 Docker 官方 GPG 密钥 添加…

企业如何增强终端安全?

在数字化转型加速的今天&#xff0c;企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机&#xff0c;到工厂里的物联网设备、智能传感器&#xff0c;这些终端构成了企业与外部世界连接的 “神经末梢”。然而&#xff0c;随着远程办公的常态化和设备接入的爆炸式…

VS2017----打开ui文件几秒后闪退

问题描述 在vs2017中双击ui文件能够打开,但是几秒后就闪退了,提示报错 问题解决 QT VS tools ----Options,把这个设置为True保存即可

深入解析Docker网桥模式:从docker0到容器网络的完整通信链路

1. 简介docker 网桥模式 Docker 启动时默认创建 docker0 虚拟网桥&#xff08;Linux bridge&#xff09;&#xff0c;并分配私有 IP 地址范围&#xff08;如 172.17.42.1/16&#xff09;&#xff0c;它的作用相当于一个虚拟交换机&#xff0c;让宿主机和多个容器之间可以通信。…

Proof of Talk专访CertiK联创顾荣辉:全周期安全方案护航Web3生态

6月10日&#xff0c;CertiK联合创始人兼CEO顾荣辉在Proof of Talk 2025举办期间&#xff0c;接受大会官方专访&#xff0c;分享了他对Web3安全现状的观察以及CertiK的安全战略布局。 顾荣辉指出&#xff0c;虽然安全的重要性被广泛认可&#xff0c;但许多创业者和开发者仍存在…

再说一说LangChain Runnable接口

之前我们介绍过LangChain通过Runnable和LCEL来实现各个组件的快捷拼装&#xff0c;整个过程就像拼积木一样。 今天我们深入剖析Runnable接口的底层实现逻辑。 往期文章推荐: 16.Docker实战&#xff1a;5分钟搞定MySQL容器化部署与最佳实践15.Ollama模板全解析&#xff1a;从基…

LLaMA-Factory微调Qwen3模型完了,怎么直接用vllm推理模型?

环境&#xff1a; LLaMA-Factory vllm0.8.5 Qwen3-8b 问题描述&#xff1a; LLaMA-Factory微调Qwen3模型完了,怎么直接用vllm推理模型&#xff1f; 解决方案&#xff1a; 一、合并 LoRA 权重与基础模型 vLLM 需要完整的模型文件&#xff08;含合并后的权重&#xff09;…

C#AES加密

一、AES 加密概念 定义 &#xff1a;AES&#xff08;Advanced Encryption Standard&#xff0c;高级加密标准&#xff09;是一种对称加密算法&#xff0c;由美国国家标准与技术研究院&#xff08;NIST&#xff09;于 2001 年发布&#xff0c;用于替代之前的 DES&#xff08;数据…

搞了两天的win7批处理脚本问题

目录 问题 原因&#xff1a; 经过各种对比 解决方法 问题 比如 echo "yes" | find /c /v "" 这个统计非空串的行数&#xff0c;在其它系统都是 1&#xff1b;但在win7里非正常的反应&#xff0c;为空。 原因&#xff1a; 在wvpCheckStart.bat 首…

手阳明大肠经之温溜穴

个人主页&#xff1a;云纳星辰怀自在 座右铭&#xff1a;“所谓坚持&#xff0c;就是觉得还有希望&#xff01;” 温溜又名&#xff1a; 1.《针灸甲乙经》&#xff1a;逆注、蛇头。 2.《资生》&#xff1a;池头。 所属经络&#xff1a;手阳明大肠经 定位 屈肘&#xff0c;在前臂…

传统Web应用和RESTful API模式

传统Web应用和RESTful API 传统模式 传统模式没有实现前后端分离&#xff0c;服务器处理完业务后直接返回完整的HTML页面&#xff0c;每次操作都要刷新整个页面。类似下面的情况&#xff1a; Controller public class UserController {RequestMapping("/addUser")…

JS开发node包并发布流程

开发一个可发布到 npm 的 JavaScript 插件&#xff0c;需要遵循标准的开发、测试、打包和发布流程。以下是详细步骤指南&#xff1a; 1. 初始化项目 创建项目目录并初始化 package.json mkdir my-js-plugin cd my-js-plugin npm init -y手动修改 package.json&#xff0c;确保…

对比学习(Contrastive Learning)方法详解

对比学习&#xff08;Contrastive Learning&#xff09;方法详解 对比学习&#xff08;Contrastive Learning&#xff09;是一种强大的自监督或弱监督表示学习方法&#xff0c;其核心思想是学习一个嵌入空间&#xff0c;在这个空间中&#xff0c;相似的样本&#xff08;“正样…

1.6 http模块nodejs 对比 go

我们以go语言 原生实现 和浏览器交互.到现在学习 nodejs http模块. nodejs 对于请求分发,也需要我们自己处理. 我们应该也对 http 服务是建立在 tcp协议基础上.有更深入的体会了吧. 对于我们之后 学习 java web容器. 能有更深入的认知. 请求分发 请求分发是指 Web 框架或服务器…

护照阅读器在景区的应用

护照阅读器在景区的应用可以显著提升游客管理效率、增强安全性并优化游客体验。以下是其主要应用场景、优势及实施建议&#xff1a; 一、核心应用场景 快速入园核验 自动身份识别&#xff1a;通过扫描护照芯片&#xff08;MRZ码或NFC读取&#xff09;&#xff0c;1-3秒完成身份…

Prompt Tuning、P-Tuning、Prefix Tuning的区别

一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…