失蹤人口回歸~~~上一次更新部落格已經是十天前的事情,害(。・∀・)最近挺忙的,蠻多事情要做,同時還在學習新的東西,是以就把整理OpenCV筆記這件事暫且先放一放了。
言歸正傳,今天要整理的内容依然是有關于OpenCV的拓展子產品ArUco,那就是aruco标記闆的建立和标記檢測,同時使用到增強型标記檢測,最後利用檢測出的标記對aruco标記闆進行姿态估計。
在之前我們已經整理過什麼是aruco标記了,那麼aruco标記闆又是何物???其實很簡單,aruco标記闆就是一系列來自相同字典的aruco标記的集合,我們可以将其列印在平面上以供檢測使用。但是要注意的是,aruco标記闆其實并不局限于二維平面,如果你樂意,完全可以列印在一張紙上然後折成立體的,例如XYZ坐标軸那種形狀(牆角。。?)。
aruco标記闆的優點呢很明顯,就是精确度肯定會比單個aruco标記要更高,而且即使其中有部分标記未被檢測出來,同樣可以識别出這是一個标記闆。總而言之,就是aruco标記闆相對于單個aruco标記來說,其準确度、魯棒性都會更好,然而使用便捷性顯然會有下降,畢竟人家隻是一小個标記你卻足足一面闆。。。當然了使用起來便捷性不足,同樣也就限制了它的應用場景。
那麼在OpenCV中,如何利用ArUco子產品建立aruco标記闆呢?首先,我們依然需要指定字典,也就是告訴程式說,那個誰,我要用這個字典裡面的标記!!!
接着我們就可以使用
aruco::GridBoard::create()
來建立aruco标記闆了,注意這裡需要引入
GridBoard
這個子子產品,直接用aruco來尋找的話是不可以的。
aruco::GridBoard::create()
的參數含義如下:
(1)參數markersX:在 X 軸方向上的标記數;
(2)參數markersY:在Y 軸方向上的标記數;
(3)參數markerLength:标記邊長,機關通常為米;
(4)參數markerSaparation:标記間隔,機關通常為米;
(5)參數dictionary:生成标記的字典。
示範代碼如下:
vector<vector<Point3f>>objPoints;
auto dictionary = aruco::getPredefinedDictionary(DICT_6X6_250);
auto board = aruco::GridBoard::create(5, 7, 0.04, 0.01, dictionary);
是以非常簡單的,我們就建立好了一個aruco标記闆,但是我們看不到它長啥樣啊,是以為了一睹芳容,我們對它進行可視化,也就是
show()
出來,當然了你要是不想看可以不看它。我們使用建立的aruco标記闆指針去調用
board->draw()
,其參數含義如下:
(1)參數outsize:輸出圖像的尺寸;
(2)參數img:輸出的包含标記闆的圖像;
(3)參數marginSize:标記闆的邊框大小(不是每個标記!);
(4)參數borderBits:标記闆中包含的每個标記的邊框大小。
代碼示範如下:
Mat boardImg;
board->draw(Size(600, 800), boardImg, 10, 1);
imshow("boardImg", boardImg);
我們來看一下建立出來的aruco标記闆的芳容:
好的,那接下來我們就要來對建立出的aruco标記闆進行檢測了,因為我沒有列印出來,是以就直接拍照啦,如下圖:
接下來又是熟悉的一步:加載相機内參矩陣和畸變系數,這裡我是已經标定好了的,是以直接輸入值(話說一直想整理下相機标定的内容,然而,沒啥空。。。)
cv::Mat cameraMatrix, distCoeffs;
vector<double> camera = { 657.1548323619423, 0, 291.8582472145741,0, 647.384819351103, 391.254810476919,0, 0, 1 };
cameraMatrix = Mat(camera);
cameraMatrix = cameraMatrix.reshape(1, 3);
vector<double> dist = { 0.1961793476399528, -1.38146317350581, -0.002301820186177369, -0.001054637905895881, 2.458286937422959 };
distCoeffs = Mat(dist);
distCoeffs = distCoeffs.reshape(1, 1);
接下來我們進行标記檢測,這一步的檢測和對于單個aruco标記檢測所用代碼是一樣的,就不做介紹了
vector<vector<Point2f>>corners, rejectedCorners;
vector<int>ids;
auto parameters = aruco::DetectorParameters::create();
aruco::detectMarkers(board_image, dictionary, corners, ids, parameters, rejectedCorners, cameraMatrix, distCoeffs);
接着我們進行增強型标記檢測,這一步是針對于标記闆而言的,可以将上面檢測步驟中沒有檢出的aruco标記進行增強檢測,提高檢測的正确率。增強标記檢測是對上一步中得到的候選标記角點,利用相機參數進行投影,并通過投影角點和候選角點的距離或者錯誤位比率來判斷某候選角點是否為标記角點。
進行增強标記檢測的API是
aruco::refineDetectedMarkers()
,其參數含義如下:
(1)參數image:檢測到标記的圖像;
(2)參數board:标記闆;
(3)參數detectedCorners:已經檢測到的标記角點,如果檢測到新的标記角點則更新該參數;
(4)參數detecterIDs:已經檢測到的标記的ID,如果檢測到新的标記角點則更新該參數;
(5)參數rejectedCorners:候選角點,由
detectMarkers()
獲得;如果檢測到新的标記角點,則将該角點從候選角點中删除;
(6)和(7)參數:相機内外參數;
(8)參數 minRepDistance:候選角點和投影角點的最小距離,如果距離小于該值則可以認為該候選角點也是标記角點;
(9)參數errorCorrectionRate:與所用字典的糾錯能力相同的允許錯誤位的比率。errorCorrectionRate = -1 表示忽略錯誤更正步驟;
通過這個API我們能夠都aruco标記闆進行二次增強檢測,找到初步檢測漏檢的aruco标記,由于我們拍的圖像還算完好,裡面的标記都能夠被檢測出來,是以這個API的效果就不做示範了。
下面來看下對aruco标記闆進行姿态估計的内容。
我們之前對aruco标記進行姿态估計時使用了一個API
estimatePose()
,那麼這裡要對aruco标記闆進行姿态估計,也是一個很類似的API:
estimatePoseBoard()
,其參數含義與上面那個API是很相似的,隻是多了一個輸入參數
board
,并且傳回值是檢測到的aruco标記闆的數量。代碼示範如下:
//如果至少檢測到一個标記,繪制标記、檢測标記闆并對标記闆進行姿态估計
Vec3d rvec, tvec;
if (corners.size() > 0)
{
aruco::drawDetectedMarkers(board_image, corners, ids, Scalar(0, 255, 0));
int boardNum = aruco::estimatePoseBoard(corners, ids, board, cameraMatrix, distCoeffs, rvec, tvec);
//如果至少檢測到一個标記闆
if (boardNum > 0)
{
aruco::drawAxis(board_image, cameraMatrix, distCoeffs, rvec, tvec, 0.04);
}
}
imshow("board", board_image);
下面看下對aruco标記闆進行姿态估計的效果(注意這裡檢測出來的都是标記闆内部的aruco标記):
好的,那今天就整理了ArUco子產品中對于aruco标記闆的建立、檢測、增強标記檢測和姿态估計這些内容,本次筆記到此結束啦,下次有空再來~
PS:本人的注釋比較雜,既有自己的心得體會也有網上查閱資料時摘抄下的知識内容,是以如有雷同,純屬我向前輩學習的緻敬,如果有前輩覺得我的筆記内容侵犯了您的知識産權,請和我聯系,我會将涉及到的博文内容删除,謝謝!