­

增强现实ArUco二维码库的测试与应用

  • 2019 年 10 月 8 日
  • 筆記
Introduction

ArUco标记是一种二维码强标记物,在机器人导航,增强现实等应用中作为摄像机姿态估计工具。相比于其他弱标记物,比如自然图片,自然物体,ArUco标记的检测是鲁棒的,快速的,简单的。

OpenCV中的ArUco模块包括标记物的生成,检测,求取摄像机姿态等功能。标记物有两类:ArUco,ChArUco,其中 ChArUco=ArUco + Chessboard 构成的。如下图所示。

ArUco Markers

ChArUco Definition

ChArUco标记物功能性得整合了ArUco标记以及传统的用于摄像机标定的棋盘格,这样我们更容易得到更准确的角点检测结果,所以即使整个ChArUco标记物有部分遮挡,该标记物也可被识别。而且ArUco作者也推荐使用这种标记物。

一个典型的ArUco应用案例包括:模版的生成,摄像头的标定,摄像机姿态的估计。下面我以ChArUco模块的应用为例。

模版的生成

功能

由于二维码的快速检测和他们的易用性,ArUco标记物或者标记板非常的有用。然而,ArUco标记物的问题之一就是它的角点检测的精度不高,甚至使用亚像素精度来优化,精度也不高。相反,常用于摄像机标定的棋盘格的角点检测精度非常高,因为棋盘格是由黑白方块交替摆放形成的标定板,每个角点的色彩变化非常突出,因此棋盘格的角点检测精度高而且快。然而,必须要把棋盘格完全暴露没有任何遮挡的情况下,才能检测到棋盘格。

所以,以ArUco + Chessboard为构成的标记物可以兼顾高精度和高效率以及鲁棒性。

流程

ArUco模块提供 cv::aruco::CharucoBoard 类来表达一个 CharucoBoard 版,该类继承自 Board 类。

导入aruco的charuco模块

#include <opencv2/aruco/charuco.hpp>

设定标记物参数

CharUco标记板的平面局部坐标系以左上角为原点,从左上角至右上角的方向为 X 正方向,从左上角至左下角的方向为 Y 正方向。

a) X方向的棋盘格方块的数目。

Eg: 5

b) Y方向的棋盘格方块的数目。

Eg: 7

c) 棋盘格方块的边长(像素)

Eg: 500

d) ArUco标记的边长(像素)

Eg: 400

e) 所有的ArUco模块内置的标记物的ids。

    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_ORIGINAsL = 16;      Eg: DICT_6X6_250

该常量的意思是这种类型的DICT可以提供250种不同的标记物,每一个标记物在内存中的大小为 6*6 bits。

函数

(1)

Ptr<Dictionary> getPredefinedDictionary()

定义一个

aruco::Dictionary

(2)

Ptr<CharucoBoard> CharucoBoard::create()

定义一个

aruco::CharucoBoard

示例

摄像头的标定

功能

ArUco模块也可用来标定摄像头。摄像头标定结果包括得到摄像机内参和扭曲系数。这些参数基本是固定的,除非摄像机的光学设备发生明显变化,摄像机标定只需要在应用前做一次即可。

通常我们使用OpenCV的标定函数calibrateCamera()。这个函数需要真实环境的点(三维)和其在摄像机平面的投影(二维)。通常我们使用标定板来获取这种三维点和二维点的对应关系,可以再看OpenCVcalibrateCamera()函数的详细文档。

使用ArUco模块,标定过程可以使用ArUco标记物和棋盘格的混合。实验证明,使用ArUco模块辅助的标定板更加鲁棒,精确。

流程

打印真实大小的ChArUco标定板。

a) X方向的棋盘格方块的数目

Eg: 5

b) Y方向的棋盘格方块的数目

Eg: 7

c) 棋盘格方块的边长(m)

Eg: 0.05

d) ArUco标记的边长(m)

Eg: 0.04

e) 所有的ArUco模块内置的标记物的ids

Eg: DICT_6X6_250

读取detector参数,这些参数为ArUco模块提供的参数,我们不用管。

把标定板放在某个位置,使用摄像头拍摄多张不同角度的照片,10~20张即可。如下图所示。

生成标定系数。这里我们假设我们使用的摄像头分辨率为

函数

aruco::DetectorParameters::create()

建立一个Detector的参数指针,包括一系列默认参数,详见文档。

aruco::detectMarkers()

在输入图片中找到marker,只有预先定义过的 dictionary type (eg: DICT_6X6_250)才可以被检测到。

aruco::refineDetectedMarkers()

优化检测到的marker。

aruco::interpolateCornersCharuco()

得到每一个marker上的角点集。

aruco::drawDetectedCornersCharuco()

在输入图片上画出检测到的角点集。

aruco::calibrateCameraCharuco()

标定摄像机。

示例

摄像机姿态的估计

功能

当我们从视频帧中检测一个ChArUco标定板,实际上检测的是标定板内部的每一个角点。每一个角点都被分配一个唯一的id。这些id从0到角点数目。在ChArUco标定板检测到后,因为ChArUco模块支持遮挡检测,所以未被遮挡的id也能检测到。如下图所示。

检测到标记点的ChArUco标定板

有部分遮挡的ChArUco标定板

如果提供了标定后的参数,我们可以求得每一个ArUco标定物的姿态,并重投影回ChArUco标定板上标记出每一个ArUco的位置。

流程

设定要检测的标定板参数,详见上一节。

输入摄像机标定参数。详见上一节。

读取detector参数。详见上一节。

检测每一帧的markers。

估计ChArUco版相对于摄像机的姿态。如图所示。

如图中,每一个id表示找到的ChArUco内部的角点。每一个绿色的方框表示ArUco标记物。把求取得标定板姿态用局部坐标系的形式画到标定板上。

函数

aruco::estimatePoseCharucoBoard(charucoCorners, charucoIds, charucoboard,camMatrix, distCoeffs, rvec, tvec);

检测CharucoBoard的姿态。

示例

精度以及性能

在这里我使用单独的ArUco标记物做精度以及性能测试。

流程

Maya虚拟测试环境

制作真实尺度的图片,并模拟一个摄像机路径。然后批渲染一秒共 24 帧图片。如下图所示。

使用Maya的脚本语言获取每个视点的 tr

求取了平移和旋转的平均误差

平均一帧处理时间约为

我们使用Maya的数据来测试ROI条件下的识别精度,以及完整图片中识别Marker的效率。比如我们使用如下序列的图片集来测试识别Marker的效率。

我们使用如下序列的图片来测试ROI条件下的识别精度。

我们2倍的比例不断缩小Marker Map在视频帧的大小。直到识别到相邻的不同状态(失败、成功)的两帧,然后取两帧中Marker Map的大小差,以1个像素为递减值,直到识别到相邻的不同状态的两帧。取最后也即最小的像素大小的Marker Map作为我们的ROI测试精度。

识别单个Marker的速度为

ROI识别精度为

单一Marker大小。

文档提到的平移分辨率为

旋转角度分辨率为

我的分辨率与文档分辨率相差

,