杂记7--opencv的ar码模块学习

2023-05-16

背景:项目需要用到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
参数3200		表示输出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码
参数20.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的平移信息
参数60.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			板的平移姿态估计

注意一个点,markerCornersmarkerIds存储的并非所有检测到的ar信息,而是在存储在Board::ids里面给到的ar编号所属信息。

参考:https://docs.opencv.org/4.x/db/da9/tutorial_aruco_board_detection.html

3、延伸

marker可以提供一些姿态信息,比如我想直到图像里面的某个平面的姿态信息,那么,我们可以给平面贴上一些marker,构造board,调用opencv接口可以返回变换矩阵信息,那么我们根据预设的board信息就可以直到某个平面的姿态信息。

#####################
不积硅步,无以至千里
好记性不如烂笔头
觉得nice,记得点赞收藏

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

杂记7--opencv的ar码模块学习 的相关文章

随机推荐

  • vs2022调用python脚本(亲测可用)

    一 新建一个控制台项目 二制作python环境文件夹 以上是安装好的python环境 此时在新建的控制台项目下新建一个python37文件夹 将一下这个几个文件和文件夹拷贝过去 如图 修改vs工程属性
  • freertos内核--任务调度剖析

    前言 在使用freertos的时候 xff0c 我们都知道在创建了一系列任务之后 xff0c 启用调度器 xff0c 系统就可以帮我们管理任务 xff0c 分配资源 本文主要对调度器的原理进行剖析 xff0c 从vTaskStartSche
  • 二进制信号量

    二进制信号量能够满足任务间的互斥和同步 xff0c 需要的系统开销最小 xff0c 因此也称快速信号量 二进制信号量可以看成一个标志 xff0c 对应资源是可用还是不可用 本小节就来认识二进制信号量的创建等过程 首先要添加一个头文件free
  • STM32自学之SPI的DMA操作(寄存器级)

    STM32自学之SPI的DMA操作 xff08 寄存器级 xff09 一 实验目标 学会配置STM32的SPI寄存器和DMA寄存器 xff0c 实现STM32的SPI1与SPI2通信功能 xff0c 每次发送一字节数据 xff0c 并可多次
  • win11无法设置移动热点

    win11无法设置移动热点 WIN10电脑热点打不开 win11电脑热点打不开 xff0c 都可以参照操作 xff0c 费力九牛二虎之力 xff0c 终于搞定 xff0c 分享给遇见同类问题的同学 xff0c 希望能帮助解决你的烦恼 具体操
  • 【node】升级 Node 版本教程

    文章目录 Window 系统Mac 或 Linux系统 Window 系统 window系统升级node只能到node官网下载window安装包来覆盖之前的node node 安装教程附下载地址 xff1a https blog csdn
  • 惠普关闭 secure boot

    一般新买的win10电脑 xff0c 是无法安装ubuntu的 xff0c 需要关闭 secure boot 开机f1进bios xff0c 改成英文 advanced secure boot configuration config le
  • ubuntu22.04运行qq音乐

    把启动图标参数改为 Exec 61 opt qqmusic qqmusic no sandbox U
  • Ubuntu环境下仿真gazebo的出现的错误的解决方法

    在运行gazebo的会出现几个错误 xff0c 下面几个总结是我在用Ubuntu的gazebo仿真时候出现的几个错误 xff0c 希望对大家在仿真的时候会有所帮助 1 xff1a ros update出错 解决方法 xff1a curl s
  • ros功能包的创建(详细版)

    这个ros功能包的创建流程 xff0c 适合初学的小白 1 xff1a 找一个合适的目录创建一个文件夹 xff0c 本文目录选择了一个名字是ac的文件夹来创建功能包 xff0c 新创建文件夹的名字可以随便起 xff0c 建议最好用英文 xf
  • 如何下载Windows11原版程序光盘映像文件(iso)

    此处采用官网下载 以win11为例 1 进入windows官网 xff0c 链接 xff1a Download Windows11 2 找到 下载win11磁盘映像iso 模块 xff0c 点击 选择下载项 3 下载项目有两个 xff0c
  • 解决The repository ‘http://security.ubuntu.com/ubuntu impish-security Release

    将 etc apt下的sources list的内容全都注释掉 xff0c 然后换成下面的内容 xff1a deb http old releases ubuntu com ubuntu impish main restricted uni
  • if判断的时候,程序不报错,但输出结果不对

    if判断的时候 xff0c 程序不报错 xff0c 但输出结果不对 其中的一个可能的原因是 xff1a 判断语句中少加了等号 如 xff1a if a 61 b 这样不报错 xff0c 但结果不对 应该是两个等号 xff0c 因为一个等号是
  • 学习笔记26-- 在solidwork里面绘制世界环境,制作成gazebo的.world世界文件基本方法

    环境 ubuntu16 04 ros kinetic gazebo7 16 基础要求 基础的urdf文件launch文件内容 能够理解并可以参考编写 问题来源 仿真时候 机器人可能需要各种形式的世界环境 虽然gazebo里面有创建世界建模工
  • 最新嵌入式学习交流群

    老铁们 大家可以帮忙顶顶帖子 帮助更多的伙伴 可以加咱们的学习交 流 裙 611386401 嵌入式物联网创客3 大家手动添加下 更多学习资料 和行业资讯 每天我都会更新的 你可以在咱们裙 免费结识行业精英 有什么不懂得随时问我和裙友 每天
  • 绝对路径! 报错:[gazebo-2] process has died [pid 2382, exit code 134

    当执行 roslaunch turtlebot gazebo turtlebot world launch world file 61 PATH时 xff0c 报错如下信息 xff1a 注 xff1a PATH 是你要打开的world对应的
  • 学习笔记30--ros-gazebo仿真的一些插件学习推荐以及一些urdf关节理解分享

    环境 ubuntu16 04 ros kinectic gazebo7 16 lt 一 gt gazebo支持以下几种插件类型 并且所有插件类型都可以链接到ros 但只能通过urdf文件引用 ModelPlugins xff0c 提供对Ph
  • 学习笔记32--仿真使用的urdf的物理属性定义解析

    环境 ubuntu16 04 ros kinetic gazebo7 16 导入 搞项目不一定要等到实际机器人结构出来 才能测试代码的 很多时候需要根据需要手动编写urdf来仿真测试的 那么 仿真时候 机器人的一些摩擦系数转动惯量是怎么定义
  • 学习笔记35-- 仿真时用到的d435以及16线雷达在urdf中定义以及launch注意点

    环境 ubuntu16 04 ros kinetics gazebo7 16 来源 仿真有d435以及16线雷达的urdf编写 注意 urdf采用的是 xacro编写的 d435 16vel urdf xacro span class to
  • 杂记7--opencv的ar码模块学习

    背景 xff1a 项目需要用到marker知识 xff0c 所以到官网上临时补一些知识 概要 xff1a 主要介绍marker一些接口的含义 xff0c 纯属个人理解 xff0c 有误则希望大佬不吝赐教 1 涉及ar码操作学习 xff0c