opencv中ArUco模块实践(1)
論文閱讀模塊將分享點云處理,SLAM,三維視覺,高精地圖相關的文章。公眾號致力于理解三維視覺領域相關內容的干貨分享,歡迎各位加入我,我們一起每天一篇文章閱讀,開啟分享之旅,有興趣的可聯系微信dianyunpcl@163.com。
aruco標記板的檢測與識別
在上一節中我們介紹了aruco單個的標記 板的檢測和識別這里我們將介紹aruco標記板的檢測和識別的過程。
ArUco的生成與檢測
ArUco與AprilTag簡介
ArUco標定板是一組標記板的組合,其作用類似于單個標記,因為它為相機提供了單個姿勢。最流行的標記板是在同一平面上有所有標記的標定板,因為它很容易打印:
然而,標定板是不限于此情況的,并且可以在任何2d或3d物體上進行布局。
標定板和一組獨立標記之間的區別在于,標定板中的標記物中的相對位置是先驗的。這使得所有標記的角點可以用于估計相機相對于整個板子的姿勢,使用一組獨立的標記時,可以單獨估計每個標記的姿勢,因為您不知道標記物在環境中的相對位置。
使用標定板的主要好處是:
姿態估計更為通用,只需要一些標記就可以進行姿態估計,因此,即使存在遮擋或局部視圖,也可以計算姿勢。
由于采用了更多的點對應(標記角點),因此獲得的姿勢通常更精確。
ArUco模塊允許使用標定板。主類是cv::aruco::Board類,它定義了標定板布局的函數:
class Board {
public:
std::vector<std::vector<cv::Point3f> > objPoints;
cv::aruco::Dictionary dictionary;
std::vector<int> ids;};
Board類型的對象有三個參數:
objPoints結構是三維板參考系統中的角點位置列表,即其布局。對于每個標記,其四個角按標準順序存儲,即順時針順序并從左上角開始。
dictionary參數指示板標記屬于哪個標記字典。
最后,ids結構指示objPoints中每個標記相對于指定字典的標識符。
標定板的檢測
標記板檢測與標準標記檢測類似。唯一的區別在于姿勢估計步驟。事實上,要使用標記板,在估計板姿勢之前,應該先進行標準的標記檢測。
aruco模塊提供了一個特定的函數estimatePoseBoard(),用于對標記板執行姿勢估計:
cv::Mat inputImage;
// camera parameters are read from somewhere
cv::Mat cameraMatrix, distCoeffs;
readCameraParameters(cameraMatrix, distCoeffs);
// assume we have a function to create the board objectcv::aruco::Board board = createBoard();...vector< int > markerIds;
vector< vector<Point2f> > markerCorners;
cv::aruco::detectMarkers(inputImage, board.dictionary, markerCorners, markerIds);
// if at least one marker detectedif(markerIds.size() > 0) {cv::Vec3d rvec, tvec;int valid = cv::aruco::estimatePoseBoard(markerCorners, markerIds, board, cameraMatrix, distCoeffs, rvec, tvec);}
estimatePoseBoard的參數為:
markerCorners和markerIds:detectMarkers()函數中檢測到的標記的結構。
board:定義board布局及其id的board對象
cameraMatrix和distcoefs:姿態估計所需的攝像機校準參數。
rvec和tvec:董事會的估計姿勢。如果不為空,則視為初始猜測。
函數返回用于估計棋盤姿勢的標記總數。注意,不應該使用markerCorners和markerIds中提供的所有標記,因為只考慮Board::ids結構中列出了其id的標記。
drawAxis() 函數的作用是:檢查獲得的姿勢。
標記板帶有坐標系可視化的結果
被遮擋的標記物的檢測并帶有坐標系的可視化的結果
柵格標記板
創建柵格的標記板對象需要指定環境中每個標記的角位置。然而,在許多情況下,柵格標記板將只是同一平面和網格布局中的一組標記,因此可以輕松打印和使用,幸運的是,aruco模塊提供了創建和打印這些類型標記的基本功能。
GridBoard類是一個專門的類,它繼承了Board類,它表示一個板,其中包含同一平面和網格布局中的所有標記,如下圖所示:
可以使用以下參數定義GridBoard對象:
X方向上的標記數。
Y方向上的標記數。
標記側的長度。
標記物分隔的長度。
標記物詞典。
所有標記的ID(X*Y標記)。
可以使用cv::aruco::GridBoard::create()靜態函數從這些參數輕松創建此對象:
cv::aruco::GridBoard board = cv::aruco::GridBoard::create(5, 7, 0.04, 0.01, dictionary);
第一和第二參數分別是X和Y方向上的標記物的個數。
第三和第四個參數分別是標記長度和標記間距。它們可以以任何單位提供,記住該板的估計姿勢將以相同單位測量(通常使用米)。
最后給出了標記的字典。
因此,該板將由5x7=35個標記組成。默認情況下,從0開始按升序分配每個標記的ID,因此它們將是0、1、2、…、。這可以通過board.ids訪問ids向量來輕松定制,就像在board父類中一樣。
創建網格板之后,我們可能要打印并使用它。
cv::aruco::GridBoard::draw()
中提供了生成網格板圖像的函數。例如
cv::aruco::GridBoard board = cv::aruco::GridBoard::create(5, 7, 0.04, 0.01, dictionary);
cv::Mat boardImage;
board.draw( cv::Size(600, 500), boardImage, 10, 1 );
第一個參數是輸出圖像的像素大小。在這種情況下,600x500像素。如果這與標記板尺寸不成比例,則將以圖像為中心。
boardImage:帶板的輸出圖像。
第三個參數是像素的(可選)邊距,因此沒有任何標記觸及圖像邊界。
最后,標記邊框的大小,類似于drawMarker()函數,默認值為1。
輸出圖像如下所示:
創建標定板的完整工作示例包含在module samples文件夾中的create_board.cpp中。
標記檢測的細化
如果我們檢測到屬于標定板的標記的子集,我們可以使用這些標記和標記板布局信息來嘗試查找以前未檢測到的標記。這可以使用refinedDetectedMarkers()函數來完成,該函數應該在調用detectMarkers()之后調用。此函數的主要參數是檢測標記的原始圖像、板對象、檢測到的標記角點、檢測到的標記ID和拒絕的標記角點。拒絕的角點可以從detectMarkers()函數獲得,也被稱為候選標記。這些候選者是在原始圖像中發現的方形,但未能通過識別步驟(即其內部編碼呈現太多錯誤),因此未被識別為標記。
然而,這些候選標記有時是由于圖像中的高噪聲、非常低的分辨率或其他影響二進制代碼提取的相關問題而未被正確識別的實際標記。函數的作用是:
查找這些候選標記與標記板上丟失的標記之間的對應關系。此搜索基于兩個參數:
候選標記與缺失標記的投影之間的距離:要獲得這些投影,必須檢測到標定板的至少一個標記,投影是使用相機參數(相機矩陣和失真系數)獲得的,如果提供的話,如果不是,則從局部單應獲得投影,并且只允許平面標記板(即所有標記角的Z坐標應相同),refinedDetectedMarkers()中的minRepDistance參數確定候選角點和投影標記角點之間的最小歐氏距離(默認值10)。
二進制編碼:如果候選標記超過最小距離條件,則再次分析其內部位以確定它是否實際是投影標記,然而,在這種情況下,條件不是那么強,并且允許的錯誤比特的數目可以更高,這在errorCorrectionRate參數(默認值3.0)中表示,如果提供負值,則根本不分析內部位,只計算角距離。
這是使用finitedetectedmarkers()函數的示例:
cv::aruco::Dictionary?dictionary?=?cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250);cv::aruco::GridBoard board = cv::aruco::GridBoard::create(5, 7, 0.04, 0.01, dictionary);vector< int > markerIds;vector< vector<Point2f> > markerCorners, rejectedCandidates;cv::aruco::detectMarkers(inputImage, dictionary, markerCorners, markerIds, cv::aruco::DetectorParameters(), rejectedCandidates);cv::aruco::refineDetectedMarkersinputImage, board, markerCorners, markerIds, rejectedCandidates);// After calling this function, if any new marker has been detected it will be removed from rejectedCandidates and included// at the end of markerCorners and markerIds
還必須注意的是,在某些情況下,如果首先檢測到的標記數量太少(例如只有1或2個標記),丟失標記的投影質量可能很差,從而產生錯誤的對應。
資源
三維點云論文及相關應用分享
【點云論文速讀】基于激光雷達的里程計及3D點云地圖中的定位方法
3D目標檢測:MV3D-Net
三維點云分割綜述(上)
3D-MiniNet: 從點云中學習2D表示以實現快速有效的3D LIDAR語義分割(2020)
win下使用QT添加VTK插件實現點云可視化GUI
JSNet:3D點云的聯合實例和語義分割
大場景三維點云的語義分割綜述
PCL中outofcore模塊---基于核外八叉樹的大規模點云的顯示
基于局部凹凸性進行目標分割
基于三維卷積神經網絡的點云標記
點云的超體素(SuperVoxel)
基于超點圖的大規模點云分割
更多文章可查看:點云學習歷史文章大匯總
SLAM及AR相關分享
【開源方案共享】ORB-SLAM3開源啦!
【論文速讀】AVP-SLAM:自動泊車系統中的語義SLAM
【點云論文速讀】StructSLAM:結構化線特征SLAM
SLAM和AR綜述
常用的3D深度相機
AR設備單目視覺慣導SLAM算法綜述與評價
SLAM綜述(4)激光與視覺融合SLAM
Kimera實時重建的語義SLAM系統
SLAM綜述(3)-視覺與慣導,視覺與深度學習SLAM
易擴展的SLAM框架-OpenVSLAM
高翔:非結構化道路激光SLAM中的挑戰
SLAM綜述之Lidar SLAM
基于魚眼相機的SLAM方法介紹
往期線上分享錄播匯總
第一期B站錄播之三維模型檢索技術
第二期B站錄播之深度學習在3D場景中的應用
第三期B站錄播之CMake進階學習
第四期B站錄播之點云物體及六自由度姿態估計
第五期B站錄播之點云深度學習語義分割拓展
第六期B站錄播之Pointnetlk解讀
[線上分享錄播]點云配準概述及其在激光SLAM中的應用
[線上分享錄播]cloudcompare插件開發
[線上分享錄播]基于點云數據的?Mesh重建與處理
[線上分享錄播]機器人力反饋遙操作技術及機器人視覺分享
[線上分享錄播]地面點云配準與機載點云航帶平差
如果你對本文感興趣,請點擊“原文閱讀”獲取知識星球二維碼,務必按照“姓名+學校/公司+研究方向”備注加入免費知識星球,免費下載pdf文檔,和更多熱愛分享的小伙伴一起交流吧!
以上內容如有錯誤請留言評論,歡迎指正交流。如有侵權,請聯系刪除
掃描二維碼
? ? ? ? ? ? ? ? ? ?關注我們
讓我們一起分享一起學習吧!期待有想法,樂于分享的小伙伴加入免費星球注入愛分享的新鮮活力。分享的主題包含但不限于三維視覺,點云,高精地圖,自動駕駛,以及機器人等相關的領域。
分享及合作:群主微信“920177957”(需要按要求備注) 聯系郵箱:dianyunpcl@163.com,歡迎企業來聯系公眾號展開合作。
點一下“在看”你會更好看耶
總結
以上是生活随笔為你收集整理的opencv中ArUco模块实践(1)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SC-A-LOAM:在A-LOAM中加入
- 下一篇: OpenCV中检测ChArUco的角点(