增強現實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大小。

文檔提到的平移分辨率為

旋轉角度分辨率為

我的分辨率與文檔分辨率相差

,