【AR】使用OpenCV中的aruco模块实现增强现实

2023-05-16

1 ArUco marker

ArUco marker是由S.Garrido-Jurado等人在2014年提出的,全称是Augmented Reality University of Cordoba,详见他们的论文《Automatic generation and detection of highly reliable fiducial markers under occlusion》。

在这里插入图片描述

它类似于二维码,通过预先标定的相机参数和捕获到的aruco标记图像,就可以求解出marker与相机的相对坐标关系。实现增强现实大致包括以下几个步骤:

  • 相机标定,包括相机的内参、畸变系数等;
  • 利用相机参数和预先设定好的marker参数(包括边长、角点等)求解相机3D坐标系到marker所在3D坐标系(z=0)的空间变换关系T;
  • 将T作用于虚拟物体计算其在相机成像平面的投影。

2 Opencv中实现一个简单的AR应用

2.1 编译aruco模块

aruco在opencv的extra_moduls(opencv_contrib)里,需要额外编译才能使用。

  • (不推荐)编译全部opencv_contrib并引用,参考链接;
  • (推荐)只编译某些模块,把这些模块从“opencv_contrib-x.x.x/modules”拷贝到“opencv/modules”,然后执行opencv编译即可。

注意一定要下载与opencv版本相对应的opencv_contrib,可从国内镜像(链接)快速下载。

2.2 生成aruco marker

aruco字典中定义了不同大小的marker(4x4、5x5、6x6、7x7),每个词典中包含了固定数量的标记(50、100、250、1000),详细可以参考opencv里面的定义:

/**
 * @brief Predefined markers dictionaries/sets
 * Each dictionary indicates the number of bits and the number of markers contained
 * - DICT_ARUCO_ORIGINAL: standard ArUco Library Markers. 1024 markers, 5x5 bits, 0 minimum
                          distance
 */
enum CV_EXPORTS_W_SIMPLE PREDEFINED_DICTIONARY_NAME {
    DICT_4X4_50 = 0,
    DICT_4X4_100,
    DICT_4X4_250,
    DICT_4X4_1000,
    DICT_5X5_50,
    DICT_5X5_100,
    DICT_5X5_250,
    DICT_5X5_1000,
    DICT_6X6_50,
    DICT_6X6_100,
    DICT_6X6_250,
    DICT_6X6_1000,
    DICT_7X7_50,
    DICT_7X7_100,
    DICT_7X7_250,
    DICT_7X7_1000,
    DICT_ARUCO_ORIGINAL
};

通过以下C++代码可以创建一个marker图像,生成的图像大小为固定的200x200像素:

// 获取大小为6x6、包含1000个marker的字典
cv::Ptr<cv::aruco::Dictionary> dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_1000);
// 绘制marker图像到markerImage,且在边缘添加1格黑色边界
cv::Mat markerImage;
cv::aruco::drawMarker(dictionary, 23, 200, markerImage, 1);

在这里插入图片描述

2.3 检测aruco marker

将打印出来的marker放置在环境中,我们就可以通过相机和以下代码对其进行实时检测:

// 检测到的marker的id
std::vector<int> ids;
// 检测到的marker的角点列表
std::vector<std::vector<cv::Point2f>> corners;
// 执行检测
cv::aruco::detectMarkers(image, dictionary, corners, ids, params);

为了提高检测精度,我们可以通过detectMarkers的cv::aruco::DetectorParameters参数(即上一段代码中的params)来设置一些参数。首先让我们先看一下可以设置的参数列表:

/**
 * @brief Parameters for the detectMarker process:
 * - adaptiveThreshWinSizeMin: minimum window size for adaptive thresholding before finding
 *   contours (default 3).
 * - adaptiveThreshWinSizeMax: maximum window size for adaptive thresholding before finding
 *   contours (default 23).
 * - adaptiveThreshWinSizeStep: increments from adaptiveThreshWinSizeMin to adaptiveThreshWinSizeMax
 *   during the thresholding (default 10).
 * - adaptiveThreshConstant: constant for adaptive thresholding before finding contours (default 7)
 * - minMarkerPerimeterRate: determine minimum perimeter for marker contour to be detected. This
 *   is defined as a rate respect to the maximum dimension of the input image (default 0.03).
 * - maxMarkerPerimeterRate:  determine maximum perimeter for marker contour to be detected. This
 *   is defined as a rate respect to the maximum dimension of the input image (default 4.0).
 * - polygonalApproxAccuracyRate: minimum accuracy during the polygonal approximation process to
 *   determine which contours are squares.
 * - minCornerDistanceRate: minimum distance between corners for detected markers relative to its
 *   perimeter (default 0.05)
 * - minDistanceToBorder: minimum distance of any corner to the image border for detected markers
 *   (in pixels) (default 3)
 * - minMarkerDistanceRate: minimum mean distance beetween two marker corners to be considered
 *   similar, so that the smaller one is removed. The rate is relative to the smaller perimeter
 *   of the two markers (default 0.05).
 * - cornerRefinementMethod: corner refinement method. (CORNER_REFINE_NONE, no refinement.
 *   CORNER_REFINE_SUBPIX, do subpixel refinement. CORNER_REFINE_CONTOUR use contour-Points)
 * - cornerRefinementWinSize: window size for the corner refinement process (in pixels) (default 5).
 * - cornerRefinementMaxIterations: maximum number of iterations for stop criteria of the corner
 *   refinement process (default 30).
 * - cornerRefinementMinAccuracy: minimum error for the stop cristeria of the corner refinement
 *   process (default: 0.1)
 * - markerBorderBits: number of bits of the marker border, i.e. marker border width (default 1).
 * - perpectiveRemovePixelPerCell: number of bits (per dimension) for each cell of the marker
 *   when removing the perspective (default 8).
 * - perspectiveRemoveIgnoredMarginPerCell: width of the margin of pixels on each cell not
 *   considered for the determination of the cell bit. Represents the rate respect to the total
 *   size of the cell, i.e. perpectiveRemovePixelPerCell (default 0.13)
 * - maxErroneousBitsInBorderRate: maximum number of accepted erroneous bits in the border (i.e.
 *   number of allowed white bits in the border). Represented as a rate respect to the total
 *   number of bits per marker (default 0.35).
 * - minOtsuStdDev: minimun standard deviation in pixels values during the decodification step to
 *   apply Otsu thresholding (otherwise, all the bits are set to 0 or 1 depending on mean higher
 *   than 128 or not) (default 5.0)
 * - errorCorrectionRate error correction rate respect to the maximun error correction capability
 *   for each dictionary. (default 0.6).
 */
struct CV_EXPORTS_W DetectorParameters {

    DetectorParameters();

    CV_WRAP static Ptr<DetectorParameters> create();

    CV_PROP_RW int adaptiveThreshWinSizeMin;
    CV_PROP_RW int adaptiveThreshWinSizeMax;
    CV_PROP_RW int adaptiveThreshWinSizeStep;
    CV_PROP_RW double adaptiveThreshConstant;
    CV_PROP_RW double minMarkerPerimeterRate;
    CV_PROP_RW double maxMarkerPerimeterRate;
    CV_PROP_RW double polygonalApproxAccuracyRate;
    CV_PROP_RW double minCornerDistanceRate;
    CV_PROP_RW int minDistanceToBorder;
    CV_PROP_RW double minMarkerDistanceRate;
    CV_PROP_RW int cornerRefinementMethod;
    CV_PROP_RW int cornerRefinementWinSize;
    CV_PROP_RW int cornerRefinementMaxIterations;
    CV_PROP_RW double cornerRefinementMinAccuracy;
    CV_PROP_RW int markerBorderBits;
    CV_PROP_RW int perspectiveRemovePixelPerCell;
    CV_PROP_RW double perspectiveRemoveIgnoredMarginPerCell;
    CV_PROP_RW double maxErroneousBitsInBorderRate;
    CV_PROP_RW double minOtsuStdDev;
    CV_PROP_RW double errorCorrectionRate;
};

这里设置挑几个参数进行设置,其他参数可根据应用场景自行添加:

cv::Ptr<cv::aruco::DetectorParameters> params = cv::aruco::DetectorParameters::create();
params->adaptiveThreshWinSizeMin = 7;
params->cornerRefinementWinSize = 5;
params->cornerRefinementMaxIterations = 100;
params->cornerRefinementMinAccuracy = 0.1;
params->cornerRefinementMethod = cv::aruco::CORNER_REFINE_CONTOUR;

2.4 绘制检测结果及AR显示

利用下面的代码可将检测到的marker边界及角点绘制在图像上:

// 绘制检测到的marker的框
cv::aruco::drawDetectedMarkers(image, corners, ids);

在这里插入图片描述

利用检测到的角点(corners)以及下面代码中出现的相机参数(cameraMatrix、distCoeffs)、marker尺寸(markerLength)来计算marker与相机坐标系之间的三维空间变换关系,分别得到旋转分量rvecs和平移分量tvecs。其中rvecs可以通过罗德里格斯变换计算对应的旋转矩阵,tvecs的单位与markerLength的单位一致。

// 估计第一个marker的位姿矩阵
double markerLength = 50;
std::vector<cv::Vec3d> rvecs, tvecs;
cv::aruco::estimatePoseSingleMarkers(corners, markerLength, cameraMatrix, distCoeffs, rvecs, tvecs);
cv::aruco::drawAxis(image, cameraMatrix, distCoeffs, rvecs, tvecs, 0.1);

在这里插入图片描述

如果想绘制其他的虚拟物体,将前面得到的rvecs和tvecs应用到该虚拟物体的变换中即可。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【AR】使用OpenCV中的aruco模块实现增强现实 的相关文章

  • 从单应性估计 R/T

    我一直在尝试计算 2 个图像中的特征 然后将这些特征传递回CameraParams R没有运气 特征已成功计算并匹配 但是问题是将它们传递回R t 我明白你必须分解Homography为了使这一点成为可能 我已经使用如下方法完成了 http
  • 从索贝尔确定图像梯度方向?

    我正在尝试使用 openCV 的 Sobel 方法的结果来确定图像梯度方向 我知道这应该是一个非常简单的任务 我从此处复制了许多资源和答案中的方法 但无论我做什么 所得方向始终在 0 57 度之间 我希望范围为 0 360 我相信所有的深度
  • 跟踪白色背景中的白球(Python/OpenCV)

    我在 Python 3 中使用 OpenCV 来检测白场上的白 黑球 并给出它的精确 x y 半径 和颜色 我使用函数 cv2 Canny 和 cv2 findContours 来找到它 但问题是 cv2 Canny 并不总是检测到圆的完整
  • 从视频/图像中提取元数据

    我从 IP 摄像机获取 MJPEG 流 我正在查看该流并将其保存在计算机上 可以找到我的操作代码here https stackoverflow com questions 21702477 how to parse mjpeg http
  • OpenCV:视频录制太快

    我有一个简单的录像机 录制来自网络摄像头的视频 theVideoWriter open filename countAsString ext CV FOURCC X V I D 30 Size 1920 1080 true while re
  • 如何使用 SimpleBlobDetector 获取 blob 的额外信息?

    robot sherrick 回答了我这个问题 https stackoverflow com a 13534094 1705967 这是他回答的后续问题 cv SimpleBlobDetectorOpencv 2 4 中的 看起来非常令人
  • 如何获得垂直线穿过的完整内轴线?

    我有一个图像 我想获取穿过其中轴的像素 我尝试使用骨架化 and 中轴方法来获取它们 但这两种方法都返回比相应对象短的一维线 这是带有示例图像的代码 gt gt gt import skimage filter gt gt gt impor
  • 如何将图像从 np.uint16 转换为 np.uint8?

    我正在创建一个图像 image np empty shape height width 1 dtype np uint16 之后我将图像转换为 BGR 模型 image cv2 cvtColor image cv2 COLOR GRAY2B
  • OpenCV:如何使用图像计算相机和物体之间的距离?

    我是 OpenCV 的新手 我正在使用以下公式来计算距离 distance to object mm focal length mm real height of the object mm image height pixels obje
  • 如何在 OpenCV 中将 Float Mat 写入文件

    我有一个矩阵 Mat B 480 640 CV 32FC1 包含浮点值 我想将此矩阵写入一个可以打开的文件Notepad https en wikipedia org wiki Windows Notepad or 微软Word https
  • opencv如何使用鼠标事件不规则地选择图像区域? c/c++ [关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 最近在学习opencv 有没有办法使用鼠标事件选择图像区域 我已经尝试过三角形的了 如果我想选择特定区域而不是三角形怎么办 谢谢你 我对此进
  • OpenCV 读取视频文件时内存不足

    此示例从文件中读取视频cv2 VideoCapture在 python OpenCV 中内存不足 import cv2 cap cv2 VideoCapture file mp4 while True ret frame cap read
  • Android for OpenCV - 打开跟踪文件时出错,UnsatisfiedLinkError

    我对 Android 开发和 OpenCV 都是新手 我从 Android 下载了 OpenCV 库http sourceforge net projects opencvlibrary files opencv android http
  • 在OpenCV中将YUV转换为BGR或RGB

    我有一个电视采集卡 其输入内容为 YUV 格式 我在这里看到了与此问题类似的其他帖子 并尝试尝试所述的所有可能的方法 但它们都没有提供清晰的图像 目前最好的结果是 OpenCVcvCvtColor scr dst CV YUV2BGR 函数
  • 如何将 Opencv VideoWriter 与 GStreamer 结合使用?

    我正在尝试使用 Opencv VideoWriter 传输 h264 流 以使用 VideoCapture 将其传输到网络上的另一台电脑上 但是 我被困在 VideoWriter 上 执行此代码会返回错误 并且 out isOpened 始
  • Python 中的 Lanczos 插值与 2D 图像

    我尝试重新缩放 2D 图像 灰度 图像大小为 256x256 所需输出为 224x224 像素值范围从 0 到 1300 我尝试了两种使用 Lanczos 插值来重新调整它们的方法 首先使用PIL图像 import numpy as np
  • 如何使用 OpencV 从 Firebase 读取图像?

    有没有使用 OpenCV 从 Firebase 读取图像的想法 或者我必须先下载图片 然后从本地文件夹执行 cv imread 功能 有什么办法我可以使用cv imread link of picture from firebase 您可以
  • OpenCv 与 Android studio 1.3+ 使用新的 gradle - 未定义的参考

    我在使用原生 OpenCv 2 4 11 3 0 0 也可以 和 Android Studio 1 3 以及新的 ndk 支持时遇到问题 所有关于 mk 文件的教程 但我想将它与新的实验性 gradle 一起使用 使用 Kiran 答案An
  • 寻找两个框架之间的变换

    我有来自视频源的两个连续帧 并且我使用 FAST 算法检测这两个帧的关键点 我使用平方差之和法 SSD 来匹配关键点 所以基本上我已经匹配了两个框架之间的关键点 现在我想根据匹配的关键点集计算两个帧之间的仿射变换 缩放 旋转 平移 我知道如
  • 通过 cmake 链接作为外部项目包含的 opencv 库[重复]

    这个问题在这里已经有答案了 我对 cmake 比较陌生 经过几天的努力无法弄清楚以下事情 我有一个依赖于 opencv 的项目 它本身就是一个 cmake 项目 我想静态链接 opencv 库 我正在做的是我的项目中有一份 opencv 源

随机推荐