ArUco

这篇具有很好参考价值的文章主要介绍了ArUco。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、ArUco简介

  姿态估计(Pose estimation)在计算机视觉领域扮演着十分重要的角色:如机器人导航、目标跟踪和相机定标等。所谓姿态估计问题就是要确定某个三维物体的方位指向问题,也就是确定以该物体为中心原点的一个坐标系。这一过程的基础是找到现实世界和图像投影之间的对应点。这通常是困难的,因此我们使用Marker解决这一问题。
  aruco模块基于ArUco库,这是一个检测二进制marker的非常流行的库。
  aruco标记其实就是一种编码,就和我们日常生活中的二维码是相似的,只不过由于编码方式的不同,导致它们存储信息的方式、容量等等有所差异。由于单个aruco标记就可以提供足够的对应关系,例如有四个明显的角点及内部的二进制编码,所以aruco标记被广泛用来增加从二维世界映射到三维世界时的信息量,便于发现二维世界与三维世界之间的投影关系,从而实现姿态估计、相机矫正等等应用。

aruco的函数包含在#include <opencv2/aruco.hpp>,该库主要的类主要有:
aruco::Marker----视觉标志类;
aruco::MarkerDetector----视觉标志检测类;
aruco::MarkerPoseTracker----视觉标志姿态预估类;
aruco::MarkerMap-----视觉标志地图类;
aruco::MarkerMapPoseTracker----视觉标志地图姿态预估类;
aruco::CvDrawingUtils----绘图类;

二、Marker和字典

  ArUco marker是一个由二进制矩阵组成的正方形标记。它由一个宽黑色边框和一个内部的二进制矩阵组成。黑色边框有利于快速检测到图像,内部二进制编码用于识别标记和提供错误检测和纠正。marker的尺寸的大小决定了内部矩阵的大小。例如,一个4x4的marker由16 位二进制数(16bits)组成。
  
一些marker图像示例:
aruco,视觉,opencv,计算机视觉,图像处理,ros

  应当注意到,我们需要检测到一个Marker在空间中发生了旋转,但是,检测的过程需要确定它的初始角度,所以每个角落需要是明确的,不能有歧义,保证上述这点也是靠二进制编码完成的。
  markers的字典是在一个特殊应用中使用到的marker的集合。这仅仅是每个marker的二进制编码的链表。
  字典的主要性质是字典的大小marker的大小:字典的大小是组成字典的marker的数量;marker的大小是这些marker的尺寸(位的个数)。
  aruco模块包含了一些预定义的字典,这些字典涵盖了一系列的字典大小和Marker尺寸。
  一个marker的 id 仅是marker在它所在的字典的下标,由内部的矩阵决定。例如,一个字典里的五个marker的 id 是:0,1,2,3 和 4。

三、步骤

1.创建Marker(Marker Creation)

cv::Mat markerImage; 
cv::aruco::Dictionary dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250); 
cv::aruco::drawMarker(dictionary, 23, 200, markerImage, 1);

getPredefinedDictionary():
  在我们创建aruco标记之前,需要先指定一个字典。这个字典表示的是创建出来的aruco标记具有怎样的尺寸、怎样的编码等等内容。我们使用这个API来声明我们使用的字典。在OpenCV中,提供了多种预定义字典,我们可以通过PREDEFINED_DICTIONARY_NAME来查看有哪些预定义字典。而且字典名称表示了该字典的aruco标记数量和尺寸,例如DICT_6X6_250表示一个包含了250种6x6位标记的字典。
  
drawMarker()
  确定好我们需要的字典后,就可以通过这个API来生成aruco标记,其参数含义如下:
(1)参数dictionary: 之前创建的 Dictionary 对象;
(2)参数id:marker 的 id,表示绘制字典中的哪一个aruco标记。每个字典由不同数量的标记组成,id 有效范围是 [ 0,字典包含的标记数 ),任何超出有效范围的特定 id 都会产生异常;
(3)参数sidepixel: 输出标记图像的尺寸,输出标记图像的尺寸为Size(sidepixel,sidepixel)(此参数应足够大以存储特定字典的位数,至少需要满足(sidepixel - 标记的边长)>= 2;并且为了避免输出标记图像变形,sidepixel应与位数 + 边界大小成比例,或者至少比标记尺寸大得多,以使变形不明显);
(4)参数img:输出的标记图像;
(5)参数borderBist:可选,用于指定标记黑色边框的宽度,例如borderBist=2 表示边框的宽度等于两个内部像素的大小,默认值 borderBist=1。
  
  这样,我们就创建了一个选定字典的aruco标记了,下面我们创建5个不同的aruco标记来对比下,演示代码如下:

	//创建aruco标记
	Mat marker;
	auto dictionary = aruco::getPredefinedDictionary(aruco::PREDEFINED_DICTIONARY_NAME::DICT_6X6_250);
	for (int i = 0;i < 5;i++)
	{
		aruco::drawMarker(dictionary, i, 200, marker, 1);
		string windowName = "marker" + to_string(i);
		imshow(windowName, marker);
		string path ="D:\\"+ windowName + ".jpg";
		imwrite(path, marker);
	}

  效果如下:
aruco,视觉,opencv,计算机视觉,图像处理,ros

2.检测Marker(Marker Detection)

cv::Mat inputImage; 
vector< int > markerIds;
vector< vector<Point2f> > markerCorners, rejectedCandidates;
cv::aruco::DetectorParameters parameters; 
cv::aruco::Dictionary dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250); 
cv::aruco::detectMarkers(inputImage, dictionary, markerCorners, markerIds, parameters, rejectedCandidates);

detectMarkers()
  当我们把aruco标记打印出来后贴在任意其它地方后,再进行拍摄,就可以对aruco标记进行检测。这个API用于检测aruco标记,其参数含义如下:
(1)参数image:输入的需要检测标记的图像;
(2)参数dictionary:进行检测的字典对象,这里的字典就是我们创建aruco标记时所使用的字典,检测什么类型的aruco标记就使用什么类型的字典;
(3)参数corners:检测到的aruco标记的角点列表,对于每个标记,其四个角点均按其原始顺序返回(从右上角开始顺时针旋转),第一个角是右上角,然后是右下角,左下角和左上角;

注意这里的返回角点顺序,在OpenCV官方文档中记录的是从左上角开始进行旋转,而经过测试,发现是以右上角为起点的。
(4)检测到的每个标记的 id,需要注意的是第三个参数和第四个参数具有相同的大小;
(5)参数parameters: DetectionParameters 类的对象,该对象包括在检测过程中可以自定义的所有参数;
(6)参数rejectedImgPoints:抛弃的候选标记列表,即检测到的、但未提供有效编码的正方形。每个候选标记也由其四个角定义,其格式与第三个参数相同,该参数若无特殊要求可以省略。
  
drawDetectedMarkers():
  当我们进行aruco标记检测后,为了方便我们观察,通常需要进行可视化操作,也就是把检测到的aruco标记绘制出来,我们使用这个API来绘制检测到的aruco标记,其参数含义如下:
(1)参数image: 是将绘制标记的输入 / 输出图像(通常就是检测到标记的图像);
(2)参数corners:检测到的aruco标记的角点列表;
(3)参数ids:检测到的每个标记对应到其所属字典中的id;
(4)参数borderColor:绘制标记外框的颜色。
  
  对aruco标记进行检测并绘制的演示代码如下:

auto dictionary = aruco::getPredefinedDictionary(aruco::PREDEFINED_DICTIONARY_NAME::DICT_6X6_250);
vector<vector<Point2f>>corners, rejectedImgPoints;
vector<int>ids;
auto parameters = aruco::DetectorParameters::create();
aruco::detectMarkers(test_image, dictionary, corners, ids, parameters, rejectedImgPoints);
aruco::drawDetectedMarkers(test_image, corners, ids, Scalar(0, 255, 0));

  效果如下:
aruco,视觉,opencv,计算机视觉,图像处理,ros
aruco,视觉,opencv,计算机视觉,图像处理,ros
aruco,视觉,opencv,计算机视觉,图像处理,ros
  可以看到每个aruco标记的边框上,都有一个绿色矩形框,而在标记的中心,有一个 id 值,这个 id 就是该标记在其所属字典中的 id。
  到这里,就完成了对aruco标记的创建和检测。后续的姿态估计、相机标定等等操作都是建立在此基础之上的。

3.姿态估计(Pose Estimation)

Mat cameraMatrix, distCoeffs;  
vector< Vec3d > rvecs, tvecs; 
cv::aruco::estimatePoseSingleMarkers(corners, 0.05, cameraMatrix, distCoeffs, rvecs, tvecs);

  接下来要通过Marker检测来获取相机pose。
  为了获取相机pose,需要知道相机的校准(Calibration)参数,即相机矩阵和畸变系数。
  注:当用ArUco marker来检测相机Pose时,可以单独地检测每个Marker的pose。如果想要从一堆Marker里检测出一个pose,需要的是aruco板。(参见ArUco板教程)
  涉及到marker的相机pose是一个从marker坐标系统到相机坐标系统的三维变换。这是由一个旋转和一个平移向量确定的(参见 solvePnP() 函数)。

  当我们每检测到一个aruco标记,vector<vector<Point2f>>corners中就会获得一个检测到标记的角点列表,我们接下来就通过这个角点列表来对该标记进行姿态估计。
  
estimatePoseSingleMarkers()
  OpenCV中提供了这个API来实现对这种简单标记的姿态估计,其参数含义如下:
(1)参数corners: detectMarkers()返回的检测到标记的角点列表,是一个vector<vector<Point2f>>类型的元素;
(2)参数markerLength:aruco标记的实际物理尺寸,也就是我们打印出来的aruco标记的实际尺寸,一般以米为单位;
(3)参数cameraMatrix:相机的内参矩阵;
(4)参数distCoeffs:相机的畸变参数;
(5)参数rvecs:vector<cv::Vec3d>类型的向量,其中每个元素为每个标记相对于相机的旋转向量;
(6)参数tvecs:vector<cv::Vec3d>类型的向量,其中每个元素为每个标记相对于相机的平移向量。
(7)参数_objPoints:每个标记角点的对应点数组。
  
  接收 detectMarkers()检测到的aruco标记(以输出角点列表的方式表示),并分别对每个标记进行姿态估计。因此,每个aruco标记都将返回一个相对于相机的旋转向量和平移矢量,返回的点数组是将标记角点从每个标记坐标系转换到相机坐标系下的表示。
  标记坐标系原点位于标记的中心,Z轴垂直于标记平面,每个标记的四个角点在其坐标系中的坐标为:(-markerLength / 2,markerLength / 2,0)(markerLength / 2,markerLength / 2,0)(markerLength / 2,-markerLength / 2 ,0)(-markerLength / 2,-markerLength / 2,0),其中,markerLength是aruco标记的边长。
  
  通过这个API,我们就能实现对简单aruco标记的姿态估计了,但是我们还需要把它进行可视化来便于我们查看,所以我们可以绘制出每个aruco标记的坐标轴,从而查看姿态估计的结果。
  
drawAxis()
  我们使用这个API来绘制坐标轴,其参数含义为:
(1)参数image:绘制坐标轴的输入、输出图像(通常是进行检测标记的图像);
(2)参数cameraMatrix:相机的内参矩阵;
(3)参数distCoeffs:相机的畸变参数;
(4)~(5)参数rvec和参数tvec:当前要绘制坐标轴的物体的姿态参数,分别是旋转向量和平移向量;
(6)参数length:绘制坐标轴的长度,单位通常为米。

  我们需要加载相机的内参矩阵和畸变系数,这里是默认标定好了的,直接获取的参数,演示代码如下:

cv::Mat cameraMatrix, distCoeffs;
vector<double> camera = { 657.1548323619423, 0, 291.8582472145741,0, 647.384819351103, 391.254810476919,0, 0, 1 };
cameraMatrix = Mat(camera);
cameraMatrix = cameraMatrix.reshape(1,3);
vector<double> dist = { 0.1961793476399528, -1.38146317350581, -0.002301820186177369, -0.001054637905895881, 2.458286937422959 };
distCoeffs = Mat(dist);
distCoeffs = distCoeffs.reshape(1, 1);

  然后,调用摄像头

VideoCapture capture;
capture.open(0);
if (!capture.isOpened())
{
	cout << "can't open camera" << endl;
	exit(-1);
}

  接着在每一帧图像中都进行aruco标记的检测以及姿态估计,并绘制出每一帧中检测到的aruco标记的坐标轴

Mat frame;
while (capture.read(frame))
{
	Mat test_image;
	resize(frame, test_image, Size(800, 800));
	imshow("test_image", test_image);
	auto dictionary = aruco::getPredefinedDictionary(aruco::PREDEFINED_DICTIONARY_NAME::DICT_6X6_250);
	vector<vector<Point2f>>corners, rejectedImgPoints;
	vector<int>ids;
	auto parameters = aruco::DetectorParameters::create();
	aruco::detectMarkers(test_image, dictionary, corners, ids, parameters, rejectedImgPoints);
	aruco::drawDetectedMarkers(test_image, corners, ids, Scalar(0, 255, 0));
	//namedWindow("dectect", WINDOW_FREERATIO);
	//imshow("dectect", test_image);

	std::vector<cv::Vec3d> rvecs;
	std::vector<cv::Vec3d> tvecs;
	cv::aruco::estimatePoseSingleMarkers(corners, 0.053, cameraMatrix, distCoeffs, rvecs, tvecs);
	for (int i = 0;i < rvecs.size();i++)
	{
		//绘制坐标轴,检查姿态估计结果
		cv::aruco::drawAxis(test_image, cameraMatrix, distCoeffs, rvecs[i], tvecs[i], 0.02);
	}
	//namedWindow("pose", WINDOW_FREERATIO);
	imshow("pose", test_image);

	char ch = cv::waitKey(1);
	if (27 == ch)
	{
		break;
	}
}


  下面是效果演示:
aruco,视觉,opencv,计算机视觉,图像处理,ros
aruco,视觉,opencv,计算机视觉,图像处理,ros
aruco,视觉,opencv,计算机视觉,图像处理,ros文章来源地址https://www.toymoban.com/news/detail-576073.html

到了这里,关于ArUco的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【计算机视觉】数字图像处理(四)—— 图像增强

    图像增强是采用一系列技术去改善图像的视觉效果,或将图像转换成一种更适合于人或机器进行分析和处理的形式。例如采用一系列技术有选择地突出某些感兴趣的信息,同时抑制一些不需要的信息,提高图像的使用价值。 图像增强方法 图像增强方法从增强的作用域出发,可

    2023年04月16日
    浏览(79)
  • 【计算机视觉】数字图像处理(六)—— 图像压缩

    (一)、图像编码技术的研究背景 1. 信息信息传输方式发生了很大的改变 通信方式的改变 文字+语音 图像+文字+语音 通信对象的改变 人与人 人与机器,机器与机器 2. 图像传输与存储需要的信息量空间 (1)彩色视频信息 对于电视画面的分辨率640 480的彩色图像,每秒30帧,

    2024年02月05日
    浏览(53)
  • 目标检测 图像处理 计算机视觉 工业视觉

    从事ai视觉算法有几年了,本帖是对以往做过的计算机视觉项目的一些总结,硬件部署的大多是基于nvidia的开发板和GPU服务器上,如jetson nano,还有地平线J3J5和瑞芯微以及星辰的开发板,另外就是对实时性要求不高的部署在cpu上。有相关项目需求可以一起交流和学习。(+v 3

    2024年02月06日
    浏览(30)
  • 计算机视觉——图像处理基础

    随着计算机视觉的不断发展,图像的预处理成为分析图像的必然前提,本文就介绍图像处理的基础内容。 图像中,高频部分是图像中像素值落差很大的部分,如图像边缘,该部分的有用信息经常被噪声淹没。降低高频段的噪声是设计图像滤波器的关键。 图像滤波器就是一个

    2024年01月19日
    浏览(43)
  • 图像处理与计算机视觉算法

    图像处理与计算机视觉算法是实现对图像和视频内容分析、理解和操作的一系列技术。这些算法可以分为多个类别,包括但不限于以下几个主要方面: 预处理 : 像素操作:灰度化、二值化、直方图均衡化等,用于改善图像的对比度和亮度分布。 去噪:高斯滤波、中值滤波、

    2024年02月22日
    浏览(36)
  • 机器视觉、图像处理和计算机视觉:概念和区别

    机器视觉、图像处理和计算机视觉:概念和区别nbsp; 机器视觉、图像处理和计算机视觉是相关但有区别的概念。 机器视觉主要应用于工业领域,涉及图像感知、图像处理、控制理论和软硬件的结合,旨在实现高效的运动控制或实时操作。 图像处理是指利用计算机对图像进行

    2024年02月06日
    浏览(28)
  • 计算机视觉图像处理常用方法汇总

    光线进入眼睛:当光线从一个物体反射或散射出来,进入人的眼睛时,它们通过角膜和晶状体进入眼球内部。 聚焦光线:角膜和晶状体将光线聚焦在视网膜上。晶状体可以通过调整其形状来调节聚焦距离,使物体的图像清晰地映射在视网膜上。 光敏细胞感受光线:视网膜是

    2024年02月07日
    浏览(32)
  • 图像处理/计算机视觉期刊投稿经验

    我不配,以后有机会再说吧。 我也不配,以后有机会再说吧。 2022年投过,一个月之后被编辑immediate reject, 原因是“the scope not aligning well with the theme interest and/or desired genres of TSP”。在邮件的末尾,编辑表示manuscript的选题“well motivated”并且“interesting”,主要担忧是所用到的

    2024年02月08日
    浏览(38)
  • 计算机视觉(2)——图像预处理

    二、图像预处理 2.1 介绍  2.2 特征提取方法 2.2.1 直方图 2.2.2 CLAHE 2.2.3 形态学运算 2.2.4 空间域处理及其变换 2.2.5 空间域分析及变换  (1) 均值滤波 (2)中值滤波 (3)高斯滤波 (4) 梯度Prewitt滤波 (5) 梯度Sobel滤波 (6) 梯度Laplacian滤波 (7) 其他滤波  2.2.6 频域分

    2024年02月03日
    浏览(47)
  • 计算机视觉实验:图像处理综合-路沿检测

    目录 实验步骤与过程 1. 路沿检测方法设计 2. 路沿检测方法实现 2.1 视频图像提取 2.2 图像预处理 2.3 兴趣区域提取 2.4 边缘检测 ​​​​​​​2.5 Hough变换 ​​​​​​​2.6 线条过滤与图像输出 3. 路沿检测结果展示 4. 其他路沿检测方法 实验结论或体会 实验内容: 针对

    2024年02月14日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包