ArUco模块是OpenCV的contrib拓展库中一个模块,需要安装OpenCV的contrib拓展库才能正常使用。
ArUco 标记是由宽黑色边框和确定其标识符(id)的内部二进制矩阵组成的正方形标记,如图1所示。通俗地说,ArUco标记其实就是一种编码,就和我们日常生活中的二维码是相似的,只不过由于编码方式的不同,导致它们存储信息的方式、容量等等有所差异,所以在应用层次上也会有所不同——单个ArUco标记就可以提供足够的对应关系,例如有四个明显的角点及内部的二进制编码,所以ArUco标记被广泛用来增加从二维世界映射到三维世界时的信息量,便于发现二维世界与三维世界之间的投影关系,从而实现姿态估计、相机矫正等应用。
ArUco标记的黑色边框有助于其在图像中的快速检测,内部二进制编码用于识别标记和提供错误检测和纠正。ArUco标记尺寸的大小决定内部矩阵的大小,例如尺寸为4×4的标记由16位二进制数组成。
图1 id=0,字典为DICT_4X4_250的ArUco标记
ArUco标记是一种基于二进制方形基准编码的标记,可用于摄像机姿态估计、相机矫正等。它的主要优点是检测简单、快速,并且具有很强的鲁棒性。
创建ArUco标记时,首先需要指定一个字典,这个字典表示的是创建出来的ArUco标记具有怎样的尺寸、怎样的编码等内容。
使用 getPredefinedDictionary()函数来声明使用的字典。在OpenCV中,提供了多种预定义字典,可以通过 PREDEFINED_DICTIONARY_NAME来查看有哪些预定义字典。而且字典名称表示了该字典的ArUco标记数量和尺寸,例如DICT_7X7_50表示一个包含了50种7×7位标记的字典。
指定好需要的字典后,就可以通过 drawMarker()函数来绘制出ArUco标记。
函数解析:
dictionary = getPredefinedDictionary(Dictionary)
drawMarker(dictionary,id,sidepixel,img,borderBist)
示例代码:
cv::Mat marker;
cv::aruco::Dictionary dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250);
cv::aruco::drawMarker(dictionary, 0, 200, marker, 1);
检测ArUco标记的是 detectMarkers()函数。方便观察检测结果,通常需要进行可视化操作,也就是将检测到的ArUco标记绘制出来,此过程使用的是 drawDetectedMarkers()函数 。
函数解析:
detectMarkers(img,dictionary,corners,ids,parameters,rejectedImgPoints)
drawDetectedMarkers(img,corners,ids,borderColor)
示例代码:
auto dictionary = aruco::getPredefinedDictionary(aruco::PREDEFINED_DICTIONARY_NAME::DICT_4X4_250);
vector>corners, rejectedImgPoints;
vectorids;
auto parameters = aruco::DetectorParameters::create();
aruco::detectMarkers(test_image, dictionary, corners, ids, parameters, rejectedImgPoints);
aruco::drawDetectedMarkers(test_image, corners, ids, Scalar(0, 255, 0));
通过ArUco标记的检测来获取相机pose,需要知道相机的校准(Calibration)参数,即相机矩阵和畸变系数。(当用ArUco标记来检测相机pose时,可以单独地检测每个标记的pose。如果想要从一堆标记里检测出一个pose,需要的是ArUco板)。
涉及到ArUco标记的相机pose是一个从标记坐标系到相机坐标系的三维变换。这是由一个旋转和一个平移向量确定的。
每当我们每检测到一个aruco标记时,vector
为了方便结果的可视化,可以使用 drawAxis()函数来绘制坐标轴。
函数解析:
estimatePoseSingleMarkers(corners,markerLength,cameraMatrix,distCoeffs,rvecs,tvecs,_objPoints)
drawAxis(img,cameraMatrix,distCoeffs,rvec,tvec,length)
示例代码:
cv::Mat cameraMatrix, distCoeffs;
vector camera = { 657.1548323619423, 0, 291.8582472145741,0, 647.384819351103, 391.254810476919,0, 0, 1 };
cameraMatrix = Mat(camera);
cameraMatrix = cameraMatrix.reshape(1,3);
vector dist = { 0.1961793476399528, -1.38146317350581, -0.002301820186177369, -0.001054637905895881, 2.458286937422959 };
distCoeffs = Mat(dist);
distCoeffs = distCoeffs.reshape(1, 1);
VideoCapture capture;
capture.open(0);
if (!capture.isOpened())
{
cout << "can't open camera" << endl;
exit(-1);
}
Mat frame;
while (capture.read(frame))
{
Mat test_image;
resize(frame, test_image, Size(800, 800));
imshow("test_image", test_image);
auto dictionary = aruco::getPredefinedDictionary(aruco::PREDEFINED_DICTIONARY_NAME::DICT_6X6_250);
vector>corners, rejectedImgPoints;
vectorids;
auto parameters = aruco::DetectorParameters::create();
aruco::detectMarkers(test_image, dictionary, corners, ids, parameters, rejectedImgPoints);
aruco::drawDetectedMarkers(test_image, corners, ids, Scalar(0, 255, 0));
std::vector rvecs;
std::vector tvecs;
cv::aruco::estimatePoseSingleMarkers(corners, 0.053, cameraMatrix, distCoeffs, rvecs, tvecs);
for (int i = 0;i < rvecs.size();i++)
{
//绘制坐标轴,检查姿态估计结果
cv::aruco::drawAxis(test_image, cameraMatrix, distCoeffs, rvecs[i], tvecs[i], 0.02);
}
imshow("pose", test_image);
char ch = cv::waitKey(1);
if (27 == ch)
{
break;
}
}
Original: https://blog.csdn.net/qq_53457019/article/details/125811861
Author: 遮云壑
Title: OpenCV学习——ArUco模块
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/520338/
转载文章受原作者版权保护。转载请注明原作者出处!