这篇博客将介绍Aruco标记是什么,以及如何使用Python,OpenCV生成Aruco标记。本文提供俩种生成方式:在线生成和代码生成;

使用OpenCV处理ArUco标签非常简单,因为OpenCV库中内置的子模块cv2.aruco(即不需要任何额外的Python包或依赖项来检测ArUco标记)。生成了Aruco标签,下一篇博客将介绍如何获取生成的标签,并在图像和实时视频流中实际检测它们。

1. 效果图

DICT_5X5_100_id88.png 生成DICT_5X5_100类型的唯一id88的Aruco标记
使用Python,OpenCV生成Aruco标记-编程知识网
多个DICT_5X5_100类型标记的概览效果图
使用Python,OpenCV生成Aruco标记-编程知识网

2. 原理

2.1 ArUco标记是什么,为什么使用它?

与AprilTags类似,ArUco标记是计算机视觉算法可以轻易检测到的二进制图案。主要使用场景有:相机校准、物体大小估计、测量相机和物体之间的距离、三维位置估计、物体方向、机器人学和自主导航。

与AprilTags相比,使用ArUco标记的主要好处包括:

  • ArUco标记内嵌于cv2.ruco子模块;
  • OpenCV库本身可以通过cv2.aluco.drawMarker函数生成ArUco标记;
  • 有一些在线的ArUco生成器,而AprilTags的在线生成器不好找到;
  • 有ROS(Robot Operating System机器人操作系统)对ArUco标记的实现;
  • ArUco标记的检测更准确

2.2 cv2.ruco.drawMarker函数

OpenCV库有一个内置的ArUco标记生成器(cv2.ruco.drawMarker)。这个函数的参数包括

  • arucoDict: 指定所使用的ArUco标记类型的字典
  • id: 要画的标记的ID(必须是ArUco字典中的有效ID)
  • sidePixels: 将绘制ArUco标记的(方形)图像的像素大小
  • borderBits: 边框的宽度和高度(像素),表示生成标记外边框便于检测;
    drawMarker函数返回画有ArUco标记的输出图像。

ArUco字典指定了正在生成和检测的ArUco标记的类型。如果没有字典将无法生成和检测这些标记。

2.3 ArUco字典的种类及命名规则

ARUCO_DICT = {
“DICT_4X4_50”: cv2.aruco.DICT_4X4_50,
“DICT_4X4_100”: cv2.aruco.DICT_4X4_100,
“DICT_4X4_250”: cv2.aruco.DICT_4X4_250,
“DICT_4X4_1000”: cv2.aruco.DICT_4X4_1000,
“DICT_5X5_50”: cv2.aruco.DICT_5X5_50,
“DICT_5X5_100”: cv2.aruco.DICT_5X5_100,
“DICT_5X5_250”: cv2.aruco.DICT_5X5_250,
“DICT_5X5_1000”: cv2.aruco.DICT_5X5_1000,
“DICT_6X6_50”: cv2.aruco.DICT_6X6_50,
“DICT_6X6_100”: cv2.aruco.DICT_6X6_100,
“DICT_6X6_250”: cv2.aruco.DICT_6X6_250,
“DICT_6X6_1000”: cv2.aruco.DICT_6X6_1000,
“DICT_7X7_50”: cv2.aruco.DICT_7X7_50,
“DICT_7X7_100”: cv2.aruco.DICT_7X7_100,
“DICT_7X7_250”: cv2.aruco.DICT_7X7_250,
“DICT_7X7_1000”: cv2.aruco.DICT_7X7_1000,
“DICT_ARUCO_ORIGINAL”: cv2.aruco.DICT_ARUCO_ORIGINAL,
“DICT_APRILTAG_16h5”: cv2.aruco.DICT_APRILTAG_16h5,
“DICT_APRILTAG_25h9”: cv2.aruco.DICT_APRILTAG_25h9,
“DICT_APRILTAG_36h10”: cv2.aruco.DICT_APRILTAG_36h10,
“DICT_APRILTAG_36h11”: cv2.aruco.DICT_APRILTAG_36h11
}

cv2.aruco.DICT_NxN_M,NxN值是ArUco标记的2D位大小。例如,对于6×6标记总共有36位,网格大小后面的整数M指定了可以使用该字典生成的唯一ArUco ID的总数。
如:cv2.aruco.DICT_4X4_50 表示要生成一个二进制的4×4平方阿鲁科标记。使用这个字典能生成50个独特的阿鲁科标记ID。

2.4 如何决定要使用哪种阿鲁科标记词典呢?

首先查看需要的字典中有多少个唯一值;然后查看输入的图像/视频分辨率大小。
OpenCV的ArUco检测实现利用错误校正来提高标记检测的准确性和鲁棒性。 纠错取决于标记间距离。
较小的字典大小和较大的NxN标记大小会增加标记间的距离,从而降低错误读数的可能性。

阿鲁科词典的理想设置包括:

  • 需要生成和读取的唯一ArUco ID数量较少
  • 包含将被检测到的阿鲁科标记的高质量图像输入
  • 更大的NxN网格大小,与少量独特的ArUco ID相平衡,以便标记间距离可用于纠正误读标记

3. 源码

在线生成Aruco标记
在线svg转png

# 三部曲——使用Python,Opencv生成Aruco标记,检测图像和视频流中的Aruco标记,检测标记的类型# 使用Python,Opencv生成Aruco标记
# 与AprilTags类似,ArUco标记是计算机视觉算法可以轻易检测到的二进制图案。主要使用场景有:相机校准、物体大小估计、测量相机和物体之间的距离、三维位置估计、物体方向、机器人学和自主导航
# 与AprilTags相比,使用ArUco标记的主要好处包括:ArUco标记内嵌于cv2.ruco子模块;OpenCV库可以通过cv2.aluco.drawMarker函数生成ArUco标记;有在线的ArUco生成器,而AprilTags的在线生成器不好找到;有ROS(Robot Operating System机器人操作系统)对ArUco标记的实现;ArUco标记的检测更准确;
# 生成ArUco标记的步骤:1. 选择ArUco字典;2. 定义要绘制的ArUcoID; 3. 定义像素级别的ArUco图像大小; 4. 调用drawMarker函数绘制ArUco标志;# python opencv_generate_aruco.py --id 24 --type DICT_5X5_100 --output tags/DICT_5X5_100_id24.png
# 导入必要的包
import numpy as np  # 定义空数组保存生成好的Aruco标记
import argparse
import cv2
import sys# 构建命令行参数及解析
# -o 输出保存Aruco标记的图片路径
# -i ArUco标签的唯一标识符--该ID必须是用于生成标签的ArUco字典中的有效ID
# -t 用于生成标签的ArUco字典的名称;默认情况下将使用原始的ArUco字典
ap = argparse.ArgumentParser()
ap.add_argument("-o", "--output", required=True,help="path to output image containing ArUCo tag")
ap.add_argument("-i", "--id", type=int, required=True,help="ID of ArUCo tag to generate")
ap.add_argument("-t", "--type", type=str,default="DICT_ARUCO_ORIGINAL",help="type of ArUCo tag to generate")
args = vars(ap.parse_args())# 定义opencv支持的Aruco标记名称映射字典
ARUCO_DICT = {"DICT_4X4_50": cv2.aruco.DICT_4X4_50,"DICT_4X4_100": cv2.aruco.DICT_4X4_100,"DICT_4X4_250": cv2.aruco.DICT_4X4_250,"DICT_4X4_1000": cv2.aruco.DICT_4X4_1000,"DICT_5X5_50": cv2.aruco.DICT_5X5_50,"DICT_5X5_100": cv2.aruco.DICT_5X5_100,"DICT_5X5_250": cv2.aruco.DICT_5X5_250,"DICT_5X5_1000": cv2.aruco.DICT_5X5_1000,"DICT_6X6_50": cv2.aruco.DICT_6X6_50,"DICT_6X6_100": cv2.aruco.DICT_6X6_100,"DICT_6X6_250": cv2.aruco.DICT_6X6_250,"DICT_6X6_1000": cv2.aruco.DICT_6X6_1000,"DICT_7X7_50": cv2.aruco.DICT_7X7_50,"DICT_7X7_100": cv2.aruco.DICT_7X7_100,"DICT_7X7_250": cv2.aruco.DICT_7X7_250,"DICT_7X7_1000": cv2.aruco.DICT_7X7_1000,"DICT_ARUCO_ORIGINAL": cv2.aruco.DICT_ARUCO_ORIGINAL,"DICT_APRILTAG_16h5": cv2.aruco.DICT_APRILTAG_16h5,"DICT_APRILTAG_25h9": cv2.aruco.DICT_APRILTAG_25h9,"DICT_APRILTAG_36h10": cv2.aruco.DICT_APRILTAG_36h10,"DICT_APRILTAG_36h11": cv2.aruco.DICT_APRILTAG_36h11
}# 验证Aruco标签存在且opencv支持
if ARUCO_DICT.get(args["type"], None) is None:print("[INFO] ArUCo tag of '{}' is not supported".format(args["type"]))sys.exit(0)# 加载ArUCo字典
arucoDict = cv2.aruco.Dictionary_get(ARUCO_DICT[args["type"]])# 定义内存数组以存储绘制了Aruco标记的图片
print("[INFO] generating ArUCo tag type '{}' with ID '{}'".format(args["type"], args["id"]))
tag = np.zeros((300, 300, 1), dtype="uint8")
cv2.aruco.drawMarker(arucoDict, args["id"], 300, tag, 1)# 保存生成的Aruco标签图片到磁盘并显示
cv2.imwrite(args["output"], tag)
cv2.imshow("ArUCo Tag", tag)
cv2.waitKey(0)

参考

  • https://pyimagesearch.com/2020/12/14/generating-aruco-markers-with-opencv-and-python/