相机标定
姿态估计在许多计算机视觉的应用中都是十分重要的环节,在机器人导航、增强现实等场景中广泛运用。这个过程主要基于找到点在真实3d环境中的坐标和2d图像中的对应坐标。这通常是一个比较困难的步骤,因此运用通用的标记物或者标准标号来使这个问题简单一点。
使用二维码记号通常是一个常用的途径之一。这标记的主要优势是单个记号就提供了获取相机姿态的足够对应信息。同时,记号的内部二进制编码使得标记在错误检查和修正等方面保持一定的稳定性。
Aruco模块主要基于 ArUco library,是一个二维码识别中被广泛使用的库。
Markers and Dirctionaries
一个ArUco标记外围都有一组黑色边框,同时内部有着确定该标记ID的二维矩阵组合而成。黑色的边框能加速标记在图像中的检测速度,内部的二维编码能唯一识别该标记,同时进行错误检测和错误修复。标记的大小确定了内部矩阵的大小,例如4x4大小的标记有16个bit(5x5就有25bits?)。
Some examples of ArUco markers:
尤其需要注意到的是,标志在环境中通常存在旋转,然而,检测的过程需要确定旋转的初始方向,因此,每一个角点在二维编码的过程中就会被唯一确定。
标记字典是一组被用来进行特殊应用的标记,它大大简化了每个marker二维码列表。字典的主要属性就是字典的大小和标志的大小:
- 字典大小:合成字典的marker的数量 (50 100 250 1000)
- 标志大小:marker的大小(bits 16 25 49 ...)
aruco模块中包含了一些已经预先定义好不同大小和数量的字典集
有些人可能会想到,一个marker的id是从二维码中获取得到并转换成一个10进制的数值。然而,这对于高位marker由于有着太高的bits来实现这种管理是不实际的,因此marker的id简化在了所属的字典序列中。
Marker Creation
在检测之前,往往我们需要打印一些marker放到我们的环境中。Marker图案我们能通过drawMarker函数产生:
c++ cv::Mat markerImage; cv::aruco::Dictionary dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250);
cv::aruco::drawMarker(dictionary, 23, 200, markerImage, 1);
以上代码产生的Marker图片:
Marker Detection
在包含ArUco标志的图片中,检测过程通常能返回被检测到的marker序列。每一个检测的Marker结果包括:
- marker四个角点在图片中的位置
- marker的id
Marker检测过程主要有两个步骤:
- 检测Marker的候选区域。
- 通过分析二维码确定marker
在opencv的ArUco模块中,主要通过detectMarkers()函数来完成,这个函数是整个模块中最重要的函数了,因为后续的函数处理几乎都依赖于该函数的检测结果。
c++ cv::Mat inputImage; ... vector< int > markerIds; vector< vector<Point2f> > markerCorners, rejectedCandidates;
cv::aruco::DetectorParametersparameters; cv::aruco::Dictionary dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250); cv::aruco::detectMarkers(inputImage, dictionary, markerCorners, markerIds, parameters, rejectedCandidates);
Pose Estiimation
当获取得到Marker的识别结果之后,就是确定相机姿态了。
为了确定相机姿态,首先得知道相机的标定参数,内参和畸变。
在估计每个ArUco标记的时候,我们能单独估计每个marker。如果你希望能从一系列的marker中估计一个pose,你需要了解ArUco Boards.
相机相对于marker的姿态是一个3d的旋转,从marker坐标系到camera坐标系。这个通过一个旋转和一个平移向量和描述。
c++ Mat cameraMatrix, distCoeffs; ... vector< Vec3d > rvecs, tvecs;
cv::aruco::estimatePoseSingleMarkers(corners, 0.05, cameraMatrix, distCoeffs, rvecs, tvecs);
- The corners parameter is the vector of marker corners returned by the detectMarkers() function.
- The second parameter is the size of the marker side in meters or in any other unit. Note that the translation vectors of the estimated poses will be in the same unit
- cameraMatrix and distCoeffs are the camera calibration parameters that need to be known a priori.
-
rvecs and tvecs are the rotation and translation vectors respectively, for each of the markers in corners.
标记坐标系统是假设z轴是朝外的,x是朝右边,y朝前进方向。标志角点在左上角点。
如图所示: