Marker类型
以下是找到的marker的种类,进行了统计如下,并对能找到源码或测试代码的marker进行了调试说明,若有遗漏,欢迎建议补充
ArUco Marker
1.简介
ArUco标记最初由S.Garrido-Jurado等人在2014年发表的论文Automatic generation and detection of highly reliable fiducial markers under occlusion中提出。ArUco的全称是Augmented Reality University of Cordoba,下面给出ArUco标记的一些示例。
ArUco标记是可用于摄像机姿态估计的二进制方形基准标记。它的主要优点是检测简单、快速,并且具有很强的鲁棒性。ArUco 标记是由宽黑边框和确定其标识符(id)的内部二进制矩阵组成的正方形标记。ArUco标记的黑色边框有助于其在图像中的快速检测,内部二进制编码用于识别标记和提供错误检测和纠正。ArUco标记尺寸的大小决定内部矩阵的大小,例如尺寸为 4x4 的标记由 16 位二进制数组成。 ArUco标记的尺寸可以任意的更改,为了成功检测可根据对象大小和场景选择合适的尺寸。在实际使用中,如果标记的尺寸太小,可能无法检测到它,这时可以选择更换较大尺寸的标记,或者将相机离标记更近一些。
在机器人应用中,可以将这些标记沿着仓库机器人的路径放置。当安装在机器人上的摄像头检测到这些标记时,由于每个标记都有唯一的ID,并且标记在仓库中的放置位置已知,因此就可以知道机器人在仓库中的精确位置。
通俗地说,Aruco标记其实就是一种编码,就和我们日常生活中的二维码是相似的,只不过由于编码方式的不同,导致它们存储信息的方式、容量等等有所差异,所以在应用层次上也会有所不同。由于单个ArUco标记就可以提供足够的对应关系,例如有四个明显的角点及内部的二进制编码,所以ArUco标记被广泛用来增加从二维世界映射到三维世界时的信息量,便于发现二维世界与三维世界之间的投影关系,从而实现姿态估计、相机矫正等等应用。
2. Marker和字典
一个ArUco marker是一个二进制方形标记,它由一个宽的黑边和一个内部的二进制矩阵组成,内部的矩阵决定了它们的id。黑色的边界有利于快速检测到图像,二进制编码可以验证id,并且允许错误检测和矫正技术的应用。marker的大小决定了内部矩阵的大小。
3.通过使用OpenCV生成ArUco标记图
使用OpenCV可轻松生成这些标记。OpenCV中的Aruco模块总共有25个预定义的标记词典。每个词典中所有的Aruco标记均包含相同数量的块或位(例如4×4、5×5、6×6或7×7),且每个词典中Aruco标记的数量固定(例如50、100、250或1000)。接下来将展示如何使用Python中生成和检测各种aruco标记。
调用getPredefinedDictionary()
函数加载包含250个标记的字典,其中每个标记都是6×6位二进制模式。具体代码在下面给出。
import cv2 as cv
import numpy as np
# 创建
dictionary = cv.aruco.getPredefinedDictionary(dict=cv.aruco.DICT_6X6_250)
img = cv.aruco.drawMarker(dictionary, id=33, sidePixels=200, borderBits=1)
# id 指定该Marker在字典中的索引ID,该例中合法的ID为[0, 249]
# sidePixels 指定输出的Marker图像的尺寸,单位是像素,该例中为(200,200)
# 如果使用DICT_6X6_250,则编码区域被划分为6X6个等大小的模块
# 参数borderBits=1,所以整个标志块区域被划分为8X8个等大小的模块
# 模块的尺寸必须大于一个像素。因此该例中,此参数最小值为8
# borderBits 指定编码区域到标志块区域的距离。单位是编码模块。取值必须大于等于1
print(img.shape)
cv.imshow("Aruco Marker", img)
cv.waitKey()
代码中drawMarker函数可以从由250个aruco标记组成的集合中选择给定id(第二个参数– 33)的标记,这250个标记的id由0~249表示。drawMarker函数的sidePixels决定生成的标记的大小,在上面的示例中,它将生成200×200像素的图像。borderBits是边界宽度参数,它决定应将多少位(块)作为边界添加到生成的二进制图案中。
在上面的代码中,将在6×6生成的图形周围添加1位的边界,以在200×200像素的图像中生成8×8位的图像。上述代码生成的aruco标记如下图所示。 在实际应用时,我们可能需要生成多个标记。之后我们只需要将这些标记打印出来就可以直接使用了。
3.检测Aruco标记
3.1 创建检测图像
# 创建图像
img_detected = np.ones((800, 600), dtype=np.uint8) * 255
img_detected[50:100, 50:100] = cv.aruco.drawMarker(dictionary, id=23, sidePixels=50, borderBits=1)
img_detected[350:400, 350:400] = cv.aruco.drawMarker(dictionary, id=18, sidePixels=50, borderBits=1)
img_detected[450:500, 450:500] = cv.aruco.drawMarker(dictionary, id=33, sidePixels=50, borderBits=1)
cv.imshow("img_detected", img_detected)
cv.waitKey()
3.2 检测
# 检测
corners, ids, rejectedImgPoints = cv.aruco.detectMarkers(image=img_detected,
dictionary=dictionary,
parameters=None)
img_color = cv.cvtColor(img_detected, cv.COLOR_GRAY2BGR)
cv.aruco.drawDetectedMarkers(img_color, corners, ids)
cv.imshow("DectectedMarker", img_color)
cv.waitKey()
4.一些API的介绍
姿态估计问题就是要确定某个三维物体的方位指向问题,也就是确定以该物体为中心原点的一个坐标系。
getPredefinedDictionary()
dictionary = cv.aruco.getPredefinedDictionary(dict=cv.aruco.DICT_6X6_250)
-
关于DICT_4X4_50含义 DICT是dictionary的缩写,6×6表示去掉一个宽的黑边后的网格大小,如下图所示是6×6的,蓝色的矩形框所示。 50表示每个字典中的Marker数目,有效的id数字范围是0到49。不在有效区间的特定id将会产生异常。 上图为一个典型的ArUco marker,去除黑色边框后为6X6的格子(黑色表示0,白色表示1),6X6的格子的外边缘为黑色。
id的计算方法: 1 0 0 1 1 0 1 0 0 0 1 1 0 0 0 0 0 1 0 0 0 1 1 1 1 1 0 0 1 1 0 1 1 1 1 0 每行组成一个二进制数,将这6个二进制数进行相加转换为十进制,就是id。 enum PREDEFINED_DICTIONARY_NAME { DICT_4X4_50 = 0, DICT_4X4_100, DICT_4X4_250, DICT_4X4_1000, DICT_5X5_50, DICT_5X5_100, DICT_5X5_250, DICT_5X5_1000, DICT_6X6_50, DICT_6X6_100, DICT_6X6_250, DICT_6X6_1000, DICT_7X7_50, DICT_7X7_100, DICT_7X7_250, DICT_7X7_1000, DICT_ARUCO_ORIGINAL, DICT_APRILTAG_16h5, ///< 4x4 bits, minimum hamming distance between any two codes = 5, 30 codes DICT_APRILTAG_25h9, ///< 5x5 bits, minimum hamming distance between any two codes = 9, 35 codes DICT_APRILTAG_36h10, ///< 6x6 bits, minimum hamming distance between any two codes = 10, 2320 codes DICT_APRILTAG_36h11 ///< 6x6 bits, minimum hamming distance between any two codes = 11, 587 codes };
注: marker corner的顺序是起点为左上角, 顺时针 注: DICT_ARUCO_ORIGINAL: 为DICT_5X5_1024
drawMarker()
-
函数作用:detectMarkers函数用于检测和确定标记角点的位置。
dictionary = cv.aruco.getPredefinedDictionary(dict=cv.aruco.DICT_6X6_250) img = cv.aruco.drawMarker(dictionary, id=33, sidePixels=200, borderBits=1)
首先,我们通过选择aruco模块中一个预定义的字典来创建一个字典对象,具体而言,这个字典是由250个marker组成的,每个marker的大小为6x6bits(DICT_6X6_250)
drawMarker的参数如下:
-
第一个参数是之前创建的字典对象(带有标记的场景图像)。
-
第二个参数是marker的id(用于生成标记的字典),成功检测到的标记将存储在markerCorners中,在这个例子中选择的是字典DICT_6X6_250第23个marker。注意到每个字典是由不同数目的Marker组成的,在这个例子中,有效的Id数字范围是0到249。不在有效区间的特定id将会产生异常。
-
第三个参数,200,是输出Marker图像的大小。在这个例子中,输出的图像将是200x200像素大小。注意到这一参数需要满足能够存储特定字典 的所有位。所以,举例而言,你不能为6x6大小的marker生成一个5x5图像(这还没有考虑到Marker的边界)。除此之外,为了避免变形,这一参数最好和位数+边界的大小成正比,至少要比marker的大小大得多(如这个例子中的200),这样变形就不显著了。。
-
最后一个参数是一个可选的参数,它指定了Marker黑色边界的大小。这一大小与位数数目成正比。例如,值为2意味着边界的宽度将会是2的倍数。默认的值为1。 生成的图像如下:
estimatePoseSingleMarkers()
cv.aruco.estimatePoseSingleMarkers(v_marker_corner, marker_size, cameraMatrix, distCoeffs, rvecs, tvecs)
-
函数作用:估计marker在相机坐标系中的3D位姿。 参数:
-
第一个参数:已检测marker角点的的向量
-
第二个参数:marker的尺寸
-
第三个参数:相机的内参矩阵
-
第四个参数:相机的畸变系数
-
第五个参数:输出marker坐标系到相机坐标系的旋转变换矩阵R
-
第六个参数:输出marker坐标系到相机坐标系的旋转变换矩阵T 注: marker坐标系用marker的位置有关, z轴向外。
6.对aruco标记进行姿态估计的可视化显示
camera_matrix = np.array([[532.79536562, 0, 342.4582516],
[0, 532.91928338, 233.90060514],
[0, 0, 1.]])
dist_coefs = np.array([-2.81086258e-01, 2.72581018e-02, 1.21665908e-03, -1.34204275e-04, 1.58514022e-01])
rvecs, tvecs, _objPoints = cv.aruco.estimatePoseSingleMarkers(corners, 0.05, camera_matrix, dist_coefs)
for i in range(len(rvecs)):
cv.aruco.drawAxis(img_color, camera_matrix, dist_coefs, rvecs[i], tvecs[i], 0.05)
cv.imshow("Pose Estimation", img_color)
cv.waitKey()
效果:
Diamond Markers
1.简介
Chessboard
具有高的交点精度,但是交点提取比较困难。ArUco
能够快速检测,但即使使用亚像素精度提取,提取的交点精度也不甚理想。ChArUco
集成了Chessboard
的高精度与ArUco
易用性的优点。
ChArUco菱形标记(或简称菱形标记)是一个由3x3个方格和4个在白色方格内的ArUco标记组成的棋盘。它在外观上与ChArUco板相似,但在概念上有所不同。
ChArUco board和Diamond marker的检测都基于先前检测到的ArUco标记。Charuco使用的标记是通过直接查找其标识符选择的。这意味着,如果在图像上找到一个标记(包含在板中),它将自动假定属于板。此外,如果一个标记在图像中被发现不止一次,它将产生歧义,因为系统无法知道哪一个应该用于该板;Diamond marker的检测不是基于标识符。相反,它们的检测是基于标记的相对位置。因此,标记标识符可以在同一个菱形中或在不同的菱形之间重复,并且可以同时检测到,而不会产生歧义。然而,由于基于其相对位置查找标记的复杂性,钻石标记的大小限制为3x3正方形和4个标记。
与单个ArUco标记一样,每个Diamond marker由4个角和一个标识符组成。四个角对应于标记中的四个棋盘角,标识符实际上是一个由4个数字组成的数组,这些数字是菱形内部四个ArUco标记的标识符。
2. 创建ChArUco Diamond
# 创建 marker_ids = np.array([45, 68, 28, 74]) squareLength = 200 markerLength = 120 dictionary = cv2.aruco.getPredefinedDictionary(dict=cv2.aruco.DICT_6X6_250) img = cv2.aruco.drawCharucoDiamond(dictionary, ids=marker_ids, squareLength=squareLength, markerLength=markerLength) print(img.shape) cv2.imshow("ChArUco Diamond", img) cv2.waitKey()
参数示意图
3.ChArUco Diamond检测
corners, ids, rejectedImgPoints = cv2.aruco.detectMarkers(image=img, dictionary=dictionary) diamond_corners, diamond_ids = cv2.aruco.detectCharucoDiamond(img, markerCorners=corners, markerIds=marker_ids, squareMarkerLengthRate=squareLength / markerLength) img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR) img = cv2.aruco.drawDetectedDiamonds(img, diamond_corners, diamond_ids) print(img.shape) cv2.imshow("ChArUco Diamond", img) cv2.waitKey()
4. 位姿估计
camera_matrix = np.array([[532.79536562, 0, 342.4582516], [0, 532.91928338, 233.90060514], [0, 0, 1.]]) dist_coefs = np.array([-2.81086258e-01, 2.72581018e-02, 1.21665908e-03, -1.34204275e-04, 1.58514022e-01]) rvecs, tvecs, _objPoints = cv2.aruco.estimatePoseSingleMarkers(diamond_corners, markerLength, cameraMatrix=camera_matrix, distCoeffs=dist_coefs) for i in range(len(rvecs)): cv2.drawFrameAxes(img_color, camera_matrix, dist_coefs, rvecs[i], tvecs[i], length=50, thickness=2) cv2.imshow("Pose Estimation", img_color) cv2.waitKey()
Apriltag
1.简介
AprilTag 是一个视觉基准系统,可用于多种任务,包括增强现实,机器人和相机校准。通过特定的标志(与二维码相似,但是降低了复杂度以满足实时性要求),可以快速地检测标志,并计算相对位置。它可以从普通打印机创建目标,AprilTag检测软件可以计算标签相对于相机的精确3D位置,方向和ID。AprilTag库在C中实现,没有任何外部依赖关系。它被设计为易于包含在其他应用程序中,并且可移植到嵌入式设备中。即使在手机级处理器上也可以实现实时性能。
2. Apriltag图像生成
2.1 通过OpenMV生成
下载openmv软件
-
中国官网地址:OpenMV | 星瞳科技 (点击 软件下载)
-
美国官网下载地址:Download | OpenMV
安装后打开,依次按照图示进行,选择相应文件夹生成即可
2.2 官网下载
实际上,在网络上所有的Apriltag的图片已经被生成存储,可以直接下使用:
-
mirrors / AprilRobotics / apriltag-imgs
请注意,所有序列的Apriiltag图片个数非常多,所以下载使用在解压缩的时候花费很多的时间和磁盘存储空间。
2.3 网页图片
如果只是使用少量的Apriltag做实验,可以直接在一些网页上提取,鼠标右键存储。
2.4 程序生成
sudo apt install python-pyx rosrun tagslam make_tag.py --nx 1 --ny 1 --marginx 0.00 --marginy 0.00 --tsize 0.16 --tspace 0.0 --startid 4 --tfam t36h11 --borderbits 1
3. 检测
检测代码仓库: https://github.com/swatbotics/apriltag 可以通过以下指令安装其python接口,但需要注意,提供pypi库的并非该仓库的作者
pip3 install apriltag
import apriltag import cv2 img = cv2.imread('/home/rvbust/Pictures/1111.png', cv2.IMREAD_GRAYSCALE)
detector = apriltag.Detector() result = detector.detect(img) print(result)
输出结果为:
[Detection(tag_family=b'tag36h11', tag_id=20, hamming=0, goodness=0.0, decision_margin=126.08333587646484, homography=array([[ 1.73373238e-16, 7.06417257e-01, -1.36868344e+00], [-7.06417257e-01, 3.16654215e-16, -1.10377696e+00], [-5.31125879e-29, 1.65748568e-17, -4.41510786e-02]]), center=array([31., 25.]), corners=array([[47., 9.], [47., 41.], [15., 41.], [15., 9.]]))]
使用下面的脚本可进行位姿估计 python apriltag.py -c -k '(765.00, 764.18, 393.72, 304.66)' -s .127 ../images/mapping_feb_2014/*JPG
TopoTag
1.简介
TopoTag是一种鲁棒且可扩展的拓扑基准标记系统,它支持从单个图像进行可靠和准确的姿态估计。TopoTag在标记检测中使用拓扑和几何信息,以实现更高的鲁棒性。拓扑信息被广泛用于2D标记检测,并且进一步用于ID解码的相应几何信息。通过利用所有TopoTag顶点实现稳健的3D姿态估计。TopoTag不必像以前的系统那样牺牲比特来获得更高的召回率和精度,它可以使用完整的比特来进行ID编码。TopoTag支持数万个唯一ID,并可轻松扩展到数百万个唯一标签,从而实现巨大的可扩展性。
2.论文地址
3.检测源码
暂未找到开源的代码,官方提供了测试的exe及数据
ChromaTag
1.简介
ChromaTag是一种彩色基准标记和快速检测算法。它最初发表于ICCV 2017(见下文引文)。该方法通过使用颜色信息来快速剔除错误检测,并最终在灰度图下提升定位精度。
2.marker的下载地址
3.代码仓库
源代码仓库:https://github.com/CogChameleon/ChromaTag 原仓库代码存在一些bug及不兼容opencv4.X,我已经修复,仓库地址:https://github.com/ancy397031272/ChromaTag
4.检测效果
RUNETag
1.简介
2.代码仓库
CCTag
1.简介
检测由同心圆组成的CCTag标记
2.代码仓库
该仓库代码实现论文. Detection and Accurate Localization of Circular Fiducials Under Highly Challenging Conditions,支持CPU和GPU
3.maker下载地址
4.源码编译
# 下载源码 git clone git@github.com:alicevision/CCTag.git # 下载最新的TBB https://github.com/oneapi-src/oneTBB/releases/tag/v2021.7.0 # 修改CmakeList.txt, 设置TBB路径 set(TBB_DIR /home/rvbust/Downloads/oneapi-tbb-2021.7.0/lib/cmake/tbb/) # 路径设置 find_package(TBB 2021.5.0 CONFIG REQUIRED) # 编译 mkdir build && cd build make -j7
5.检测结果
./build/Linux-x86_64/detection -n 3 -i sample/01.png
STag
1.简介
这是一种稳定的基准标记系统,从作者的展示来看,其稳定性高于ARToolKit+, ArUcon, RUNE-Tag
2.代码下载地址
3.marker下载地址
Pi-Tag
1. 简介
2.论文地址
3.代码下载地址
4.marker生成代码
5.检测效果
ARToolkit
1.简介
2.代码地址
reacTIVision
1.简介
2.代码地址
Chilitags
1.简介
chilttags演示视频地址
2.制作marker
1)可以从以下地址中下载
https://github.com/chili-epfl/chilitags/releases/download/2.0.0/tags.zip
2)使用仓库中的脚本生成
/tools/creator