Opencv之Aruco码的检测和姿态估计

1.介绍

Aruco码是由宽黑色边框和确定其标识符(id)的内部二进制矩阵组成的正方形标记。它的黑色边框有助于其在图像中的快速检测,内部二进制编码用于识别标记和提供错误检测和纠正。单个aruco 标记就可以提供足够的对应关系,例如有四个明显的角点及内部的二进制编码,所以aruco 标记被广泛用来增加从二维世界映射到三维世界时的信息量,便于发现二维世界与三维世界之间的投影关系,从而实现姿态估计、增强现实等应用。

2.码的创建

首先我们要指定一个字典,这个字典表示的是创建出来的aruco 标记具有怎样的尺寸、怎样的编码等我们使用:APlgetPredefined Dictionary ()来声明我们使用的字典。 些预定义字典。而且字典名称表示了该字典的aruco 标记数量和尺寸,例如DICT_7X7_50表示一个包含了50种7x7位标记的字典。
在OpenCv中提供了多种预定义字典,我们可以通过PREDEFINED_DICTIONARY_NAME来查看:

auto dictionary = aruco::getPredefinedDictionary(aruco::DICT_6X6_250);
可使用的字典:
        DICT_4X4_50=0,             
        DICT_4X4_100=1, 
        DICT_4X4_250=2,
        DICT_4X4_1000=3, 
        DICT_5X5_50=4, 
        DICT_5X5_100=5, 
        DICT_5X5_250=6, 
        DICT_5X5_1000=7, 
        DICT_6X6_50=8, 
        DICT_6X6_100=9,
        DICT_6X6_250=10, 
        DICT_6X6_1000=11, 
        DICT_7X7_50=12,
        DICT_7X7_100=13, 
        DICT_7X7_250=14, 
        DICT_7X7_1000=15, 
        DICT_ARUCO_ORIGINAL = 16

Aruco码和Aruco码板的创建:

#include <opencv2/highgui.hpp>
#include <opencv2/aruco.hpp>

using namespace cv;

namespace {
const char* about = "Create an ArUco grid board image main -w=2 -h=2 -l=10 -s=5 -d=16 -si=true ";
const char* keys  =
"{@outfile |<none> | Output image }"
"{w        |       | Number of markers in X direction }"
"{h        |       | Number of markers in Y direction }"
"{l        |       | Marker side length (in pixels) }"
"{s        |       | Separation between two consecutive markers in the grid (in pixels)}"
"{d        |       | dictionary: DICT_4X4_50=0, DICT_4X4_100=1, DICT_4X4_250=2,"
"DICT_4X4_1000=3, DICT_5X5_50=4, DICT_5X5_100=5, DICT_5X5_250=6, DICT_5X5_1000=7, "
"DICT_6X6_50=8, DICT_6X6_100=9, DICT_6X6_250=10, DICT_6X6_1000=11, DICT_7X7_50=12,"
"DICT_7X7_100=13, DICT_7X7_250=14, DICT_7X7_1000=15, DICT_ARUCO_ORIGINAL = 16}"
"{mid        | 0      | markerboard start id}"
"{m        |       | Margins size (in pixels). Default is marker separation (-s) }"
"{bb       | 1     | Number of bits in marker borders }"
"{si       | false | show generated image }";
}

int main(int argc, char *argv[]) {
    CommandLineParser parser(argc, argv, keys);
    parser.about(about);

    if(argc < 7) {
        parser.printMessage();
        return 0;
    }

    int markersX = parser.get<int>("w");
    int markersY = parser.get<int>("h");
    int markerLength = parser.get<int>("l");
    int markerSeparation = parser.get<int>("s");
    int dictionaryId = parser.get<int>("d");
    int margins = markerSeparation;
    if(parser.has("m")) {
        margins = parser.get<int>("m");
    }

    int borderBits = parser.get<int>("bb");
    bool showImage = parser.get<bool>("si");
    int marker_st_id = parser.get<int>("mid");
    String out = parser.get<String>(0);

    if(!parser.check()) {
        parser.printErrors();
        return 0;
    }

    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, marker_st_id);

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

    if(showImage) {
        imshow("board", boardImage);
        waitKey(0);
    }

    imwrite(out, boardImage);

    return 0;
}

3.检测和姿态估计

3.1 Aruco标记的检测

cv::aruco::detectMarkers()

cv::aruco::detectMarkers(image_, dictionary_, corners, ids, detectorParams_, rejected);
参数:
(1)image :输入的需要检测标记的图像。 
(2)dictionary :进行检测的字典对象指针,这里的字典就是我们创建aruco 标记时所使用的字典,检测什么类型的aruco 标记就使用什么类型的字典。 
(3)corners :检测到的aruco 标记的角点列表,其四个角点均按其原始顺序返回 (从左上角开始顺时针旋转)(4)ids:检测到的每个标记的id,需要注意的是第三个参数和第四个参数具有相同的大小。 
(5)parameters:Detection parameters 类的对象,该对象包括在检测过程中可以自定义的所有参数。
(6)参数rejectedImgPoints 

3.2 单个Aruco码的姿态估计

2023-02-22 16-22-15 的屏幕截图.png
cv::aruco::estimatePosesingleMarkers()

cv::aruco::estimatePoseSingleMarkers(corners, markerLength, intrinsic_matrix_, distortion_matrix_, rvecs, tvecs, _objPoints);
参数:
(1)corners :detectMarkers ()返回的检测到标记的角点列表; 
(2)markerLength :aruco 标记的实际物理尺寸,也就是打印出来的aruco标记的实际尺寸,以m为单位; 
(3)intrinsic_matrix_ :相机的内参矩阵;
(4)distortion_matrix_ :相机的畸变参数;
(5)rvecs : 标记相对于相机的旋转向量。 
(6)tvecs : 标记相对于相机的平移向量。 
(7)_objPoints :每个标记角点的对应点数组。 

通过检测到的corners,并分别对每个标记进行姿态估计。 因此,每个aruco 标记都将返回一个相对于相机的旋转向量和平移矢量,返回的点数组是将标记角点从每个标记坐标系转换到相机坐标系下的表示。 标记坐标系原点位于标记的中心,Z轴垂直于标记平面,每个标记的四个角点在其坐标系中的坐标为:(-markerLength/ 2, markerLength/2,0) (markerLength/ 2, markerLength/ 2, 0) (markerLength/2,-markerLength/2,0) (-markerLength /2,-markerLength /2,0),其中,markerLength 是aruco 标记的实际边长。

3.3 单个Aruco码板的姿态估计

2023-02-22 16-23-41 的屏幕截图.png
1.创建aruco码板
cv::aruco::GridBoard::create()

// create board object
cv::Ptr<cv::aruco::GridBoard> gridboard =
cv::aruco::GridBoard::create(markersX, markersY, markerlength, markerseparation, dictionary_, ids[0]);
board.markerboard_ptr = gridboard.staticCast<cv::aruco::Board>();
参数:
(1)markersX: 码板的横向码的个数;
(2)markersY: 码板的纵向码的个数;
(3)markerlength: 每一个码的边长,单位m;
(4)markerseparation: 两个码之间的间隔宽度,单位m;
(5)dictionary_:字典;
(6)ids[0]:码板的第一个码的id值;

2.姿态估计
cv::aruco::estimatePoseBoard()

cv::aruco::estimatePoseBoard(corners, ids, markerboard_ptr, intrinsic_matrix_, distortion_matrix_, rvec, tvec);

码板识别的坐标系是以码板的左下角为坐标原点建立的坐标系,如图所示。

3.4 Aruco码可视化

1.坐标轴的可视化
cv::aruco::drawAxis()

cv::aruco::drawAxis(image_, intrinsic_matrix_, distortion_matrix_, rvecs[i], tvecs[i], markerLength * 2.5f);
参数:
(1)image_ :绘制坐标轴的图像;
(2)intrinsic_matrix_ :相机的内参矩阵;
(3)distortion_matrix_ :相机的畸变参数; 
(4)rvecs:旋转向量;
(5)tvecs:平移向量;
(6)markerLength :绘制坐标轴的长度,单位为m。

2.标记的可视化
cv::aruco::drawDetectedMarkers()

cv::aruco::drawDetectedMarkers(image_, board.match_corners, board.match_ids);
参数:
(1)image :绘制标记的图像;
(2)corners :检测到的aruco 标记的角点列表;
(3)ids:检测到的每个标记对应到其所属字典中的id ;
(4)borderColor :绘制标记外框的颜色;

4.应用

1.增强现实
2023-02-22 16-32-34 的屏幕截图.png
2.激光雷达和相机的联合标定
在这里插入图片描述
还有很多其他的应用,这里就不举例了。

  • 6
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: 红绿灯检测图片数据xml文件是用于存储红绿灯位置和属性信息的一种文件格式。它通常由计算机视觉算法生成,用于训练和测试红绿灯检测模型。 在xml文件中,首先会包含图片的基本信息,比如图片的宽度、高度和通道数等。然后,每个红绿灯实例都会被描述为一个矩形框,用四个值表示矩形框的左上角和右下角的坐标。这些矩形框将围绕着红绿灯的位置。 除了矩形框,xml文件中还包括其他与红绿灯相关的属性信息。例如,每个红绿灯可能具有一个类别标签,用于表示该红绿灯是红灯还是绿灯。此外,还可以添加一些其他属性,如红绿灯的形状、大小、颜色等。 通过使用这些xml文件,我们可以训练红绿灯检测模型。在训练过程中,模型将根据xml文件中提供的红绿灯位置和属性信息来学习如何准确地检测红绿灯。而在测试过程中,我们可以使用xml文件中的矩形框来标识红绿灯的位置,并对其进行分类。 总的来说,红绿灯检测图片数据xml文件是一种用于存储红绿灯位置和属性信息的文件格式,它是进行红绿灯检测训练和测试的重要数据源。通过使用这个xml文件,我们能够有效地训练和测试红绿灯检测模型,从而提高交通安全性能。 ### 回答2: 红绿灯检测是指通过处理红绿灯图片数据,并对其进行分析和处理,以确定其中是否存在红绿灯的位置及状态。XML文件是一种标记语言,用于存储和描述数据,以便在不同平台和程序之间进行数据交换和共享。 对于红绿灯检测图片数据,XML文件通常用于存储多个图像的相关信息。在XML文件中,可以将每个图像的路径、大小、位置和标签等信息存储起来。这些信息对于训练红绿灯检测模型和评估检测算法的性能非常重要。 XML文件中的每个图像通常包含一系列的标注框(bounding box),用于表示红绿灯的位置。每个标注框由四个坐标值组成,分别表示框的左上角和右下角的坐标。此外,还可以在每个标注框中添加一些属性,如红绿灯的颜色、信号状态(红灯、绿灯、黄灯)等。 红绿灯检测图片数据的XML文件还可以包含其他信息,如图像的拍摄时间、相机参数、光照条件等。这些信息可以帮助研究人员或开发者更好地理解红绿灯检测数据集的特征和条件,从而提高算法的鲁棒性和泛化能力。 总之,红绿灯检测图片数据的XML文件对于提供图像的标注信息、辅助算法的训练和评估具有重要作用,是实现红绿灯检测算法的必要数据之一。通过分析和处理XML文件中的信息,可以更好地进行红绿灯检测算法的研究和应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

黑马水牛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值