杂记7--opencv的ar码模块学习
背景:项目需要用到marker知识,所以到官网上临时补一些知识。
概要:主要介绍marker一些接口的含义,纯属个人理解,有误则希望大佬不吝赐教
1、
涉及ar码操作学习,其头文件为:
#include <opencv2/aruco.hpp>
1)创建marker
cv::Mat markerImage;
cv::Ptr<cv::aruco::Dictionary> dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250);
cv::aruco::drawMarker(dictionary, 23, 200, markerImage, 1);
cv::imwrite("marker23.png", markerImage);
参数1: dictionary :表示marker字典类型为DICT_6X6_250,使用构造函数进行创建
参数2: 23 表示准备绘制的ar码在该字典里面的编号id为23
参数3: 200 表示输出ar码图片像素为200x200
参数4: markerImage 保存的是输出ar图片dictionary表示的是marker数据集
可以参考:
const char* keys ="{@outfile |<none> | Output image }""{d | | dictionary: DICT_4X4_50=0, DICT_4X4_100=1, DICT_4X4_250=2,""DICT_4X4_1000=3, DICT_5X5_50=4, DICT_5X5_100=5, DICT_5X5_250=6, DICT_5X5_1000=7, ""DICT_6X6_50=8, DICT_6X6_100=9, DICT_6X6_250=10, DICT_6X6_1000=11, DICT_7X7_50=12,""DICT_7X7_100=13, DICT_7X7_250=14, DICT_7X7_1000=15, DICT_ARUCO_ORIGINAL = 16}""{cd | | Input file with custom dictionary }""{id | | Marker id in the dictionary }""{ms | 200 | Marker size in pixels }""{bb | 1 | Number of bits in marker borders }""{si | false | show generated image }";
}
2)marker检测函数detectMarkers()解析:
cv::Mat inputImage;
...
std::vector<int> markerIds;
std::vector<std::vector<cv::Point2f>> markerCorners, rejectedCandidates;
cv::Ptr<cv::aruco::DetectorParameters> parameters = cv::aruco::DetectorParameters::create();
cv::Ptr<cv::aruco::Dictionary> dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250);
cv::aruco::detectMarkers(inputImage, dictionary, markerCorners, markerIds, parameters, rejectedCandidates);
参数1 inputImage : 表示包含 ar码marker的图片=
参数2: dictionary : 表示ar码来自哪个字典类型
参数3: markerCorners : 该容器作用是保存的是检测出来的ar码参数4: markerIds : 作用记录检测出来的ar码存储在markerCorners在字典中的编号
参数5: parameters : DetectorParameters类的实例化对象,其包含了检测ar码过程所涉及的所有自定义的参数
参数6: rejectedCandidates : 保存没有检测出来有效的ar码 marker
参考:https://docs.opencv.org/4.x/d5/dae/tutorial_aruco_detection.html
3)绘制marker框框 drawDetectedMarkers()
在上一步骤检出ar码后,下一步检测是否真的检查正确,这时候需要使用绘制marker框框来验证,此时可使用函数drawDetectedMarkers():
cv::Mat outputImage = inputImage.clone();
cv::aruco::drawDetectedMarkers(outputImage, markerCorners, markerIds);
参数1 : outputImage 表示输入的图片
参数2 : markerCorners 来自detectMarkers()函数获取得到保存了ar码容器
参数3 : markerIds 来自detectMarkers()函数获取的,记录检测出来的ar码存储在markerCorners的ar码在字典中的编号
参考:https://docs.opencv.org/4.x/d5/dae/tutorial_aruco_detection.html
4)姿态信息函数estimatePoseSingleMarkers()
在检测校验检测出来的ar码之后,我们需要做的是从ar码里面获取对应的姿态信息,姿态信息函数estimatePoseSingleMarkers():
cv::Mat cameraMatrix, distCoeffs;
// You can read camera parameters from tutorial_camera_params.yml
readCameraParameters(filename, cameraMatrix, distCoeffs); // This function is located in detect_markers.cpp
std::vector<cv::Vec3d> rvecs, tvecs;
cv::aruco::estimatePoseSingleMarkers(markerCorners, 0.05, cameraMatrix, distCoeffs, rvecs, tvecs);
参数1: markerCorners 来自detectMarkers()函数,意义为存储检测出来的ar码
参数2: 0.05 ar码的尺寸,单位一般为米(也可以为其他单位,如mm),注意尺寸单位和姿态估计变换矩阵单位一致
参数3: cameraMatrix 相机内参
参数4: distCoeffs 相机畸变参数
参数5: rvecs 该容器保存的是markerCorners里面每个ar的旋转信息
参数6: tvecs 该容器保存的是markerCorners里面每个ar的平移信息
相机内参和畸变参数可以查看:https://blog.csdn.net/weixin_43206570/article/details/84797361
5)打印姿态信息cv::drawFrameAxes()
姿态信息获取后,可以打印出检验出来的姿态信息进行校验,参考函数cv::drawFrameAxes()
inputImage.copyTo(outputImage);
for (int i = 0; i < rvecs.size(); ++i) {
auto rvec = rvecs[i];
auto tvec = tvecs[i];
cv::drawFrameAxes(outputImage, cameraMatrix, distCoeffs, rvec, tvec, 0.1);
}
参数1: outputImage 绘制ar码的图片
参数2: cameraMatrix 相机内参
参数3: distCoeffs 相机畸变参数
参数4: rvec 该容器保存的是markerCorners里面每个ar的旋转信息
参数5: tvecs 该容器保存的是markerCorners里面每个ar的平移信息
参数6: 0.1 轴线长度,单位同rvec、tvecs,一般为米
以下为一个简单ar码,从检测到姿态估计的完整过程:
cv::VideoCapture inputVideo;
inputVideo.open(0);
cv::Mat cameraMatrix, distCoeffs;
// You can read camera parameters from tutorial_camera_params.yml读取相机参数
readCameraParameters(filename, cameraMatrix, distCoeffs); // This function is located in detect_markers.cpp
cv::Ptr<cv::aruco::Dictionary> dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250);
while (inputVideo.grab()) {
cv::Mat image, imageCopy;
inputVideo.retrieve(image);
image.copyTo(imageCopy);
std::vector<int> ids;
std::vector<std::vector<cv::Point2f>> corners;
//检测
cv::aruco::detectMarkers(image, dictionary, corners, ids);
// if at least one marker detected
if (ids.size() > 0) {
cv::aruco::drawDetectedMarkers(imageCopy, corners, ids);//绘制检测框
std::vector<cv::Vec3d> rvecs, tvecs;
cv::aruco::estimatePoseSingleMarkers(corners, 0.05, cameraMatrix, distCoeffs, rvecs, tvecs);//姿态估计
// draw axis for each marker
for(int i=0; i<ids.size(); i++)
cv::drawFrameAxes(imageCopy, cameraMatrix, distCoeffs, rvecs[i], tvecs[i], 0.1);//绘制姿态
}
cv::imshow("out", imageCopy);//显示图片
char key = (char) cv::waitKey(waitTime);
if (key == 27)
break;
}
其他内容为解析一些自定义检测过程参数事情,后续想要学习,可以打开链接加以学习
参考:https://docs.opencv.org/4.x/d5/dae/tutorial_aruco_detection.html
2、利用ar 码集(注意跟上一节的单个ar码检测到姿态估计区别)进行姿态估计
单独检测一个ar码和 board 码检测的区别,board码可以知道各个ar码之间的相对位置而单独ar码不知,也就是有一个先验值。
boards好处:
姿态估计更加丰富;获取的姿态更加准确
1)头文件
#include <opencv2/aruco.hpp>
2)Board类
class Board {
public:
std::vector<std::vector<cv::Point3f> > objPoints;
cv::Ptr<cv::aruco::Dictionary> dictionary;
std::vector<int> ids;
};
参数1: objPoints 角点位置列表,就是存储所有ar码四个角点位置信息
参数2: dictionary 表示board上面使用的ar码归属字典
参数3: ids 存储的是objPoints 里面的ar码对应在字典里面的编号
参考:https://docs.opencv.org/4.x/d5/dae/tutorial_aruco_detection.html
3)Board detection
板检测和marker检测类似,唯一差别在于姿态估计上。板在board姿态估计之前,务必进行一次marker检测
cv::Mat inputImage;
// camera parameters are read from somewhere
cv::Mat cameraMatrix, distCoeffs; //相机的内参、相机畸变参数
// You can read camera parameters from tutorial_camera_params.yml
readCameraParameters(filename, cameraMatrix, distCoeffs); // This function is located in detect_board.cpp
// assume we have a function to create the board object
cv::Ptr<cv::aruco::Board> board = cv::aruco::Board::create();
...
std::vector<int> markerIds;//ar码在字典中的编号,对应markerCorners中ar码
std::vector<std::vector<cv::Point2f>> markerCorners;// 所有ar码
cv::aruco::detectMarkers(inputImage, board.dictionary, markerCorners, markerIds);
// if at least one marker detected
if(markerIds.size() > 0) {
cv::Vec3d rvec, tvec;
int valid = cv::aruco::estimatePoseBoard(markerCorners, markerIds, board, cameraMatrix, distCoeffs, rvec, tvec);
}
参数1: markerCorners 存储的是板上的ar码
参数2: markerIds 存储的是存储ar码在字典中的编号
参数3: board 记录板的布局和ar码的id(?)
参数4: cameraMatrix 相机内参
参数5: distCoeffs 相机畸变参数
参数6: rvec 板的旋转姿态估计
参数7: tvec 板的平移姿态估计
注意一个点,markerCorners
和markerIds
存储的并非所有检测到的ar信息,而是在存储在Board::ids里面给到的ar编号所属信息。
参考:https://docs.opencv.org/4.x/db/da9/tutorial_aruco_board_detection.html
3、延伸
marker可以提供一些姿态信息,比如我想直到图像里面的某个平面的姿态信息,那么,我们可以给平面贴上一些marker,构造board,调用opencv接口可以返回变换矩阵信息,那么我们根据预设的board信息就可以直到某个平面的姿态信息。
#####################
不积硅步,无以至千里
好记性不如烂笔头
觉得nice,记得点赞收藏
相关文章:
杂记7--opencv的ar码模块学习
背景:项目需要用到marker知识,所以到官网上临时补一些知识。 概要:主要介绍marker一些接口的含义,纯属个人理解,有误则希望大佬不吝赐教 1、 涉及ar码操作学习,其头文件为: #include <op…...
[项目设计]高并发内存池
目录 1、项目介绍 2、高并发内存池整体框架设计 3、thread cache <1>thread cache 哈希桶对齐规则 <2>Thread Cache类设计 4、Central Cache <1>Central Cache类设计 5、page cache <1>Page Cache类设计 6、性能分析 <1>定长内存池实现…...
28岁才转行软件测试,目前32了,我的一些经历跟感受
我是92年的,算是最早的90后,现在跟你介绍的时候还恬不知耻的说我是90后,哈哈,计算机专业普通本科毕业。在一个二线城市,毕业后因为自身能力问题、认知水平问题,再加上运气不好,换过多份工作&…...
Python导入模块的3种方式
很多初学者经常遇到这样的问题,即自定义 Python 模板后,在其它文件中用 import(或 from...import) 语句引入该文件时,Python 解释器同时如下错误:ModuleNotFoundError: No module named 模块名意思是 Pytho…...
select 与 where、order by、limit 子句执行优先级比较
当 select 和 其他三种语句的一者或者多者同时出现时,他们之间是存在执行先后顺序的。 他们的优先级顺序是:where > select > order by > limit 目录 1、select 与 where 2、select 与 order by 3、order by 与 limit 4、优先级证明 1、s…...
Linux内核并发与竞争-原子操作
一.原子操作的概念首先看一下原子操作,原子操作就是指不能再进一步分割的操作,一般原子操作用于变量或者位操作。假如现在要对无符号整形变量 a 赋值,值为 3,对于 C 语言来讲很简单,直接就是: a3但是 C 语言…...
Java笔记-泛型的使用
参考: Java 泛型,你了解类型擦除吗? 泛型的使用 1、泛型的定义 可以广泛使用的类型,一种较为准确的说法就是为了参数化类型,或者说可以将类型当作参数传递给一个类或者是方法。 2、泛型的使用 2.1泛型类 public c…...
特斯拉无人驾驶解读
来源于Tesla AI Day Tesla无人驾驶算法的核心任务就是如何理解我们所看到的一切呢?也就是说,不使用高端的设备,比如激光雷达,仅仅使用摄像头就能够将任务做得很好。Tesla使用环绕型的8个摄像头获得输入。 第一步是特征提取模块Backbone,无论什么任务都离不开特征…...
生物素-琥珀酰亚胺酯Biotin-NHS;CAS号:35013-72-0;可对溶液中的抗体,蛋白质和任何其他含伯胺的大分子进行简单有效的生物素标记。
结构式: 生物素-琥珀酰亚胺酯Biotin NHS CAS号:35013-72-0 英文名称:Biotin-NHS 中文名称:D-生物素 N-羟基琥珀酰亚胺酯;生物素-琥珀酰亚胺酯 CAS号:35013-72-0 密度:1.50.1 …...
Maven_第五章 核心概念
目录第五章 其他核心概念1、生命周期①作用②三个生命周期③特点2、插件和目标①插件②目标3、仓库第五章 其他核心概念 1、生命周期 ①作用 为了让构建过程自动化完成,Maven 设定了三个生命周期,生命周期中的每一个环节对应构建过程中的一个操作。 …...
【深度学习】人脸识别工程化落地
文章目录前言1、facenet2、使用2.1.其它blog2.2 实践总结前言 老早以前就希望能写一篇关于人脸识别的工程化落地的案例,一年前做疲劳驾驶时使用的dlib插件,它封装好了,人脸检测、对齐、相似度计算三个部分,就是插件比较难装,但同时也少了很多…...
AOP面向切面编程思想。
目录 一、AOP工作流程 1、基本概念 2、AOP工作流程 二、AOP核心配置 1、AOP切入点表达式 2、AOP通知类型 三、AOP通知获取数据 1、获取参数 2、获取返回值 3、获取异常 四、AOP事务管理 1、Spring事务简介 2、Spring事务角色 3、事务属性 一、AOP工作流程 1、…...
实验7-变治技术及动态规划初步
目录 1.统计个数 2.数塔dp -A 3.Horspool算法 4.计数排序 5.找零问题1-最少硬币 1.统计个数 【问题描述】有n个数、每个元素取值在1到9之间,试统计每个数的个数 【输入形式】第一行,n的值;第二行...
JVM垃圾回收机制GC理解
目录JVM垃圾回收分代收集如何识别垃圾引用计数法可达性分析法引用关系四种类型: 强、软、弱、虚强引用软引用 SoftReference弱引用 WeakReferenceWeakHashMap软引用与虚引用的使用场景虚引用与引用队列引用队列虚引用 PhantomReference垃圾回收算法引用计数复制 Cop…...
C++中的容器
1.1 线性容器1)std::array看到这个容器的时候肯定会出现这样的问题:为什么要引入 std::array 而不是直接使用 std::vector?已经有了传统数组,为什么要用 std::array?先回答第一个问题,与 std::vector 不同,…...
2023备战金三银四,Python自动化软件测试面试宝典合集(五)
接上篇八、抓包与网络协议8.1 抓包工具怎么用 我原来的公司对于抓包这块,在 App 的测试用得比较多。我们会使用 fiddler 抓取数据检查结果,定位问题,测试安全,制造弱网环境;如:抓取数据通过查看请求数据,请…...
SpringDI自动装配BeanSpring注解配置和Java配置类
依赖注入 上篇博客已经提到了DI注入方式的构造器注入,下面采用set方式进行注入 基于set方法注入 public class User {private String name;private Address address;private String[] books;private List<String> hobbys;private Map<String,String>…...
2月面经:真可惜...拿了小米的offer,字节却惨挂在三面
我是2月份参加字节跳动和华为的面试的,虽然我只拿下了小米的offer,但是我自己也满足了,想把经验分享出来,进而帮助更多跟我一样想进大厂的同行朋友们,希望大家可以拿到理想offer。 自我介绍 我是16年从南京工业大学毕…...
磐云PY-B8 网页注入
文章目录1.使用渗透机场景windows7中火狐浏览器访问服务器场景中的get.php,根据页面回显获取Flag并提交;2.使用渗透机场景windows7中火狐浏览器访问服务器场景中的post.php,根据页面回显获取Flag并提交;3.使用渗透机场景windows7中…...
多传感器融合定位十-基于滤波的融合方法Ⅰ其二
多传感器融合定位十-基于滤波的融合方法Ⅰ其二3. 滤波器基本原理3.1 状态估计模型3.2 贝叶斯滤波3.3 卡尔曼滤波(KF)推导3.4 扩展卡尔曼滤波(EKF)推导3.5 迭代扩展卡尔曼滤波(IEKF)推导4. 基于滤波器的融合4.1 状态方程4.2 观测方程4.3 构建滤波器4.4 Kalman 滤波实际使用流程4…...
Java集合面试题:HashMap源码分析
文章目录一、HashMap源码二、HashMap数据结构模型图三、HashMap中如何确定元素位置四、关于equals与hashCode函数的重写五、阅读源码基本属性参考文章:史上最详细的 JDK 1.8 HashMap 源码解析参考文章:Hash详解参考文章:hashCode源码分析参考…...
华为OD机试 - 数组合并(Python),真题含思路
数组合并 题目 现在有多组整数数组, 需要将他们合并成一个新的数组。 合并规则, 从每个数组里按顺序取出固定长度的内容合并到新的数组中, 取完的内容会删除掉, 如果该行不足固定长度或者已经为空, 则直接取出剩余部分的内容放到新的数组中, 继续下一行。 如样例 1, 获得长度…...
Vue2创建移动端项目
一、Vscode Vscode 下载安装以及常用的插件 1、Vscode 下载 下载地址:Vscode 中文语言插件 搜索 chinese 主题 Atom 主题 文件图标主题 搜索 icon 源代码管理插件GitLens 搜索 GitLens Live Server _本地服务器 搜索 Live Server Prettier - Code formatt…...
PorterDuffXfermode与圆角图片
版权声明 本文原创作者:谷哥的小弟作者博客地址:http://blog.csdn.net/lfdfhl 圆角图片 在项目开发中,我们常用到这样的功能:显示圆角图片。 这个是咋做的呢?我们来瞅瞅其中一种实现方式 /*** param bitmap 原图* p…...
如何准备大学生电子设计竞赛
大学生电子设计竞赛难度中上,一般有好几个类型题目可以选择,参赛者可以根据自己团队的能力、优势去选择合适自己的题目,灵活自主空间较大。参赛的同学们可以在暑假好好学习相关内容,把往年的题目拿来练练手。这个比赛含金量还是有…...
【Java容器(jdk17)】ArrayList深入源码,就是这么简单
ArrayList深入源码一、ArrayList源码解析1. MIXIN 的混入2. 属性说明3. 构造方法4. 其他方法(核心)iterator 和 listIterator 方法add方法remove 方法sort方法其他二、ArrayList 为什么是线程不安全的?体现哪些方面呢?三、ArrayLi…...
【Java 面试合集】简述下Java的三个特性 以及项目中的应用
简述下Java的特征 以及项目中的应用 1. 概述 上述截图中就是Java的三大特性,以及特性的实现方案。接下来就每个点展开来说说 2. 封装 满足:隐藏实现细节,公开使用方法 的都可以理解为是封装 而实现封装的有利手段就是权限修饰符了。可以根据…...
git基本概念图示【学习】
基本概念工作区(Working Directory)就是你在电脑里能看到的目录,比如名字为 gafish.github.com 的文件夹就是一个工作区本地版本库(Local Repository)工作区有一个隐藏目录 .git,这个不算工作区,…...
微前端qiankun架构 (基于vue2实现)使用教程
工具使用版本 node --> 16vue/cli --> 5 创建文件 创建文件夹qiankun-test。 使用vue脚手架创建主应用main和子应用dev 主应用 安装 qiankun: yarn add qiankun 或者 npm i qiankun -S 使用qiankun: 在 utils 内创建 微应用文件夹 microApp,在该文件夹…...
记录robosense RS-LIDAR-16使用过程3
一、wireshark抓包保存pcap文件并解析ubuntu18安装wireshark,参考下面csdn教程,官网教程我看的一脸蒙(可能英语太差)https://blog.csdn.net/weixin_46048542/article/details/121730448?spm1001.2101.3001.6650.2&utm_medium…...
宝鸡网站建设天伟网络/百度推广登录入口下载
Rsync文件同步的核心算法 文章出处:http://coolshell.cn/articles/7425.html#more-7425 rsync是unix/linux下同步文件的一个高效算法,它能同步更新两处计算机的文件与目录,并适当利用查找文件中的不同块以减少数据传输。rsync中一项与其他大部分类似程序…...
做视频搬运哪个网站最赚钱/2023上海又出现疫情了
本人正在吹着空调,喝着茶水,然后qq头像抖了两下,业务开发同学给我打了个招呼,“忙么?帮个忙可以不?” 这很明显了,要忙了呀!来活了。本着爱岗敬业的精神回复“您说”。 然后很含蓄的…...
做DJ网站违法吗/优化外包服务公司
无论哪一个牌子的手机都会有很多自带的软件,不过很多人都觉得手机自带的软件没什么用,很鸡肋,有些人甚至把一些自带软件都删掉了,不过小编今天要说的是苹果手机里两个超好用的自带软件,就是用到手机报废我都不会把它们…...
益阳市 网站建设/企业营销策略分析论文
那是我处理GD东西的第一个方法.我正在尝试使用jcrop jquery插件实现调整大小和裁剪的功能.我仍然不知道如何保存裁剪后的图像.在jcrop网站上没有太多关于它的内容.这是我的代码:if ($_SERVER[REQUEST_METHOD] POST) {$targ_w $targ_h 150;$jpeg_quality 90;$src…...
青岛制作企业网站/长春seo顾问
1.配置httpd.conf 监听多个端口 #Listen 12.34.56.78:80 Listen 8081 Listen 8082 Listen 8083 可以通过netstat -n -a查看端口是否开启 2.开启虚拟站点 # Virtual hosts #Include conf/extra/httpd-vhosts.conf #修改为 # Virtual hosts Include conf/extra/httpd-vhosts.con…...
推荐定制型网站建设/短视频seo
1.C语言结构体的定义和使用 在实际问题中,一组数据往往具有不同的数据类型;例如在学生信息登记表中,姓名为字符型,学号为整型或字符型,年龄为整型,性别为字符型,成绩为整型或实型。因为数据类型不同,显然不能用一个数组来存放。在C语言中,可以使用结构体(Struct)来…...