OpenCV学习——ArUco模块

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/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球