视觉标记定位aruco使用

转载自:https://lightsail.blog.csdn.net/article/details/102752780

视觉标记定位aruco使用

沧海飞帆 2019-10-26 11:05:51 2657 收藏 14

分类专栏: SLAM 文章标签: opencv aruco定位

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/ktigerhero3/article/details/102752780

版权

本文的目的是实现生成一张marker broad图片,告诉标记检测程序tag在真实世界中的实际大小。
检测成功后得到marker的id,四个角点坐标,marker到相机的平移和旋转。

1.下载安装参考

opencv 中的aruco源码下载要到下面地址
opencv 中的aruco源码下载
https://github.com/opencv/opencv_contrib/tree/master/modules/aruco
https://github.com/opencv/opencv_contrib/releases/tag/3.3.0

2.生成单个marker图片

程序如下

#include <opencv2/opencv.hpp>
#include <opencv2/aruco.hpp>
#include <opencv2/calib3d/calib3d.hpp>
#include "opencv2/core/core.hpp"
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>

using namespace std;
using namespace cv;

int main()
{
    cv::Mat markerImage;
    cv::Ptr<cv::aruco::Dictionary> dictionary = 	cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250);
    cv::aruco::drawMarker(dictionary, 23, 200, markerImage, 1);
    imwrite("./aruco_tag.png",markerImage);
    imshow("test", markerImage);//显示marker
    waitKey();
    return 0;
}

cv::aruco::drawMarker
第一个参数是之前创建的Dictionary对象。
第二个参数是marker的id,在这个例子中选择的是字典DICT_6X6_250 的第23个marker。注意到每个字典是由不同数目的Marker组成的,在这个例子中的字典中,有效的Id数字范围是0到249。不在有效区间的特定id将会产生异常。
三个参数,200,是输出Marker图像的大小。在这个例子中,输出的图像将是200x200像素大小。注意到这一参数需要满足能够存储特定字典 的所有位。举例来说,你不能为6x6大小的marker生成一个5x5图像(这还没有考虑到Marker的边界)。除此之外,为了避免变形,这一参数最好和位数+边界的大小成正比,或者至少要比marker的大小大得多(如这个例子中的200),这样变形就不显著了
第四个参数是输出的图像。
最终,最后一个参数是一个可选的参数,它指定了Marer黑色边界的大小。这一大小与位数数目成正比。例如,值为2意味着边界的宽度将会是2的倍数。默认的值为1。

3 . 打印并标定相机内参

注意,打印的时候如果用像素为200200的图像打印,实际打印大小为20cm20cm,那么一个像素对应1毫米。
内参标定就不介绍了,此实验使用内参为

intrinsic_matrix: !!opencv-matrix
   rows: 3
   cols: 3
   dt: d
   data: [ 420.019, 0., 330.8676, 0.,
       419.6044, 217.8731, 0., 0., 1. ]
distortion_vector: !!opencv-matrix
   rows: 1
   cols: 4
   dt: d
   data: [ -0.3549, 0.1151, -0.0035, -0.0029 ]

的相机拍出来的图像如下
在这里插入图片描述

4.检测marker并得到id和相对位移

确定好实际打印出来的marker的边长和内参就可以检测并计算了。
其中markerlength表示marker的实际物理长度。
使用上面的图像和内参程序如下

#include <opencv2/opencv.hpp>
#include <opencv2/aruco.hpp>
#include <opencv2/calib3d/calib3d.hpp>
#include "opencv2/core/core.hpp"
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <eigen3/Eigen/Core>
#include <eigen3/Eigen/Geometry>
#include <opencv2/core/eigen.hpp>

using namespace std;
using namespace cv;

int main()
{
    cv::Mat m_image=imread("./mark.jpg");
    if(m_image.empty())
    {
        cout<<"m_image  is empty"<<endl;
        return 0;
    }
    //read para
   double markerlength=0.105;
   cv::Mat intrinsics = (Mat_<double>(3, 3) <<
                         420.019, 0.0, 330.8676,
                         0.0,419.6044, 217.8731,
                         0.0, 0.0, 1.0);

    cv::Mat distCoeffs=(cv::Mat_<double>(4, 1) <<  -0.3549, 0.1151, -0.0035, -0.0029);
    cv::Mat  imageCopy;
    m_image.copyTo(imageCopy);
    cv::Ptr<cv::aruco::Dictionary> dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250);

    std::vector<int> ids;
    std::vector<std::vector<cv::Point2f>> corners;
    cv::aruco::detectMarkers(m_image, dictionary, corners, ids);//检测靶标
    // if at least one marker detected
    if (ids.size() > 0) {
        cv::aruco::drawDetectedMarkers(imageCopy, corners, ids);//绘制检测到的靶标的框
        for(unsigned int i=0; i<ids.size(); i++)
        {
           std::vector<cv::Vec3d> rvecs, tvecs;
          cv::aruco::estimatePoseSingleMarkers(corners[i], markerlength, intrinsics, distCoeffs, rvecs, tvecs);//求解旋转矩阵rvecs和平移矩阵tvecs
            cv::aruco::drawAxis(imageCopy,intrinsics,distCoeffs, rvecs[i], tvecs[i], 0.1);
            //3.rotaion vector to eulerAngles
            cv::Mat rmat;
            Rodrigues(rvecs[i], rmat);
            Eigen::Matrix3d rotation_matrix3d;
            cv2eigen(rmat,rotation_matrix3d);
            Eigen::Vector3d eulerAngle = rotation_matrix3d.eulerAngles(0,1,2);//(0,1,2)表示分别绕XYZ轴顺序,即 顺序,逆时针为正
            cout<<"pitch "<<eulerAngle.x()<<"yaw "<<eulerAngle.y()<<"roll"<<eulerAngle.z()<<endl;
            cout<<"x= "<<tvecs[i][0]<<"y="<<tvecs[i][1]<<"z="<<tvecs[i][2]<<endl;
        }
    }
    cv::imshow("out", imageCopy);
    cv::waitKey();

    return 0;
}

其中
The parameters of detectMarkers are:
The first parameter is the image where the markers are going to be detected.
The second parameter is the dictionary object, in this case one of the predefined dictionaries (DICT_6X6_250).
The detected markers are stored in the markerCorners and markerIds structures:
markerCorners is the list of corners of the detected markers. For each marker, its four corners are returned in their original order (which is clockwise starting with top left). So, the first corner is the top left corner, followed by the top right, bottom right and bottom left.
markerIds is the list of ids of each of the detected markers in markerCorners. Note that the returned markerCorners and markerIds vectors have the same sizes.
The fourth parameter is the object of type DetectionParameters. This object includes all the parameters that can be customized during the detection process. This parameters are commented in detail in the next section.
The final parameter, rejectedCandidates, is a returned list of marker candidates, i.e. those squares that have been found but they do not present a valid codification. Each candidate is also defined by its four corners, and its format is the same than the markerCorners parameter. This parameter can be omitted and is only useful for debugging purposes and for ‘refind’ strategies (see refineDetectedMarkers() ).

5实验效果

输出

pitch 3.12894yaw -0.0187251roll-1.5281
x= -0.011554y=-0.0038433z=0.17224

在这里插入图片描述

6.生成多个marker组成的board

参考http://www.pianshen.com/article/2639341324/

#include <opencv2/opencv.hpp>
#include <opencv2/aruco.hpp>
#include <opencv2/calib3d/calib3d.hpp>
#include "opencv2/core/core.hpp"
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>

using namespace std;
using namespace cv;

int main()
{
    int markersX = 5;//X轴上标记的数量
    int markersY = 5;//Y轴上标记的数量   本例生成5x5的棋盘
    int markerLength = 100;//标记的长度,单位是像素
    int markerSeparation = 20;//每个标记之间的间隔,单位像素
    int dictionaryId = cv::aruco::DICT_4X4_50;//生成标记的字典ID
    int margins = markerSeparation;//标记与边界之间的间隔

    int borderBits = 1;//标记的边界所占的bit位数
    bool showImage = true;

    Size imageSize;
    imageSize.width = markersX * (markerLength + markerSeparation) - markerSeparation + 2 * margins;
    imageSize.height =
        markersY * (markerLength + markerSeparation) - markerSeparation + 2 * margins;

    Ptr<aruco::Dictionary> dictionary =
        aruco::getPredefinedDictionary(aruco::PREDEFINED_DICTIONARY_NAME(dictionaryId));

    Ptr<aruco::GridBoard> board = aruco::GridBoard::create(markersX, markersY, float(markerLength),
        float(markerSeparation), dictionary);

    // show created board
    Mat boardImage;
    board->draw(imageSize, boardImage, margins, borderBits);

    if (showImage) {
        imwrite("./aruco_tag_board.png",boardImage);
        imshow("board", boardImage);
        waitKey(0);
    }

    return 0;
}

参考文献
https://blog.csdn.net/A_L_A_N/article/details/83657878

### 回答1: Aruco是一个基于OpenCV的开源视觉标识系统,可以用于相机姿态估计、相机标定、三维重建等应用。下面是使用Python进行Aruco视觉定位的一些步骤: 1. 安装OpenCV和Aruco库 ``` pip install opencv-python pip install opencv-contrib-python pip install aruco ``` 2. 准备Aruco标识 使用Aruco库提供的函数生成Aruco标识图像,并打印出来。标识图像可以用于相机姿态估计。 3. 相机标定 使用Aruco标识图像进行相机标定,得到相机内参和畸变参数。可以使用OpenCV提供的calibrateCamera函数进行相机标定。 4. 检测Aruco标识 使用OpenCV提供的aruco库中的detectMarkers函数,可以检测到图像中的Aruco标识,并返回标识的位置和姿态信息。 5. 估计相机姿态 使用OpenCV提供的aruco库中的estimatePoseSingleMarkers函数,可以估计相机相对于Aruco标识的姿态。 6. 绘制姿态信息 使用OpenCV提供的drawAxis函数,可以在标识图像上绘制出相机的姿态信息。 以上是使用Python进行Aruco视觉定位的一些基本步骤,具体实现可以参考OpenCV和Aruco库提供的文档和示例代码。 ### 回答2: Aruco视觉定位是一种基于二维码的视觉定位算法,可以用于在图像或视频中定位和识别二维码标记。在Python中,可以使用OpenCV库的Aruco模块来实现Aruco视觉定位。 首先,需要使用pip或conda安装OpenCV库。然后,可以导入Aruco模块并调用其中的函数来进行视觉定位。 在使用Aruco定位之前,我们需要准备一个已知的二维码标记字典,该字典包括一组已知标记的ID和对应的二维码图像。可以使用Aruco模块中的函数来生成字典,或者使用已有的标记字典。 接下来,我们可以读取图像或者视频流,并使用Aruco模块中的函数来检测和识别二维码标记。函数会返回每个检测到的标记的ID和位置信息。 最后,我们可以根据标记的位置信息对图像或视频进行定位。可以通过计算标记的位置和姿态矩阵,来获取标记在世界坐标系中的位置。这样,我们就可以实现对图像或视频中物体的三维定位。 需要注意的是,Aruco视觉定位的准确性受到环境光照、标记图像质量和摄像机参数等多个因素的影响。为了提高定位的准确性,可以对摄像机进行校准,调整环境光照,以及使用更多的标记来增加定位的稳定性。 总结来说,Aruco视觉定位是一种基于二维码的视觉定位算法,可以利用Python中的OpenCV库来实现。通过识别和定位二维码标记,可以在图像或视频中实现物体的三维定位
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值