增強現實ArUco二維碼庫的測試與應用
- 2019 年 10 月 8 日
- 筆記
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()。這個函數需要真實環境的點(三維)和其在攝像機平面的投影(二維)。通常我們使用標定板來獲取這種三維點和二維點的對應關係,可以再看OpenCV的calibrateCamera()函數的詳細文檔。
使用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的腳本語言獲取每個視點的 t 和 r 。

求取了平移和旋轉的平均誤差

平均一幀處理時間約為

。
我們使用Maya的數據來測試ROI條件下的識別精度,以及完整圖片中識別Marker的效率。比如我們使用如下序列的圖片集來測試識別Marker的效率。

我們使用如下序列的圖片來測試ROI條件下的識別精度。

我們2倍的比例不斷縮小Marker Map在視頻幀的大小。直到識別到相鄰的不同狀態(失敗、成功)的兩幀,然後取兩幀中Marker Map的大小差,以1個像素為遞減值,直到識別到相鄰的不同狀態的兩幀。取最後也即最小的像素大小的Marker Map作為我們的ROI測試精度。
識別單個Marker的速度為

。
ROI識別精度為

單一Marker大小。
文檔提到的平移分辨率為

旋轉角度分辨率為

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

,

。