【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模块实现增强现实 的相关文章

  • 在 OpenCV 中对 RGB 图像进行阈值处理

    我有一个彩色图像 我想在 OpenCV 中设置阈值 我想要的是 如果任何 RGB 通道低于某个值 则将所有通道中的值设置为零 即黑色 因此 我使用 opencv 阈值函数 cv Mat frame thresholded read fram
  • Python opencv排序轮廓[重复]

    这个问题在这里已经有答案了 我正在关注这个问题 如何从左到右 从上到下对轮廓进行排序 https stackoverflow com questions 38654302 how can i sort contours from left
  • Matlab 中 interp2 的类似 OpenCV Api

    有没有类似的功能 其工作原理与 interp2 x y frame z xd yd linear 0 在 OpenCV 中 功能cv remap 几乎可以满足您的要求 请参阅文档here http docs opencv org modul
  • 使用 cmake 和 opencv 对符号“gzclose”的未定义引用[关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 我尝试构建该项目 doppia https bitbucket org rodrigob doppia 但发生链接错误 我想这是一
  • 相机姿态估计(OpenCV PnP)

    我正在尝试使用网络摄像头从具有已知全球位置的四个基准点的图像中获取全局姿态估计 我检查了许多 stackexchange 问题和一些论文 但似乎无法得到正确的解决方案 我得到的位置数字是可重复的 但与相机移动绝不成线性比例 仅供参考 我正在
  • cv2.cv.BoxPoints(rect) 返回什么?

    rect cv2 minAreaRect largest contour rect rect 0 0 self scale down rect 0 1 self scale down rect 1 0 self scale down rec
  • 如何将 OpenCV 等待键与 Chaquopy 一起使用

    我正在尝试使用 Chaquopy 将计算机视觉应用程序移植到 Android 当我尝试运行脚本时 以下行中出现以下错误 cv2 waitKey 100 打印到嵌入式 python 控制台的错误是 java chaquopy CQPEnv c
  • 屏幕截图中低分辨率文本的 OCR

    我正在编写一个 OCR 应用程序来从屏幕截图图像中读取字符 目前 我只关注数字 我的方法部分基于这篇博文 http blog damiles com 2008 11 basic ocr in opencv http blog damiles
  • opencv如何使用compareHist函数

    img cv2 imread mandrill png histg cv2 calcHist img 0 None 256 0 256 if len sys argv lt 2 print gt gt sys stderr Usage sy
  • 如何使图像呈现出陈旧、布满灰尘、颜色褪色的外观?

    我有旧画的图像 这些画很旧 布满灰尘 颜色褪色 如图所示here https i stack imgur com xuoEF jpg 如何赋予任何图像这种 旧 外观 我找不到任何过滤器或 openCV 函数来实现这种类型的外观 EDIT 我
  • opencv 视频上的颜色阈值

    I am thresholding for a color range in an opencv video The goal is to seperate the B mode black and white information on
  • OpenCV findContours 破坏源图像

    我编写了一个在单通道空白图像中绘制圆形 直线和矩形的代码 之后 我只需找出图像中的轮廓 就可以正确获取所有轮廓 但找到轮廓后 我的源图像变得扭曲 为什么会出现这种情况 任何人都可以帮我解决这个问题 我的代码如下所示 using namesp
  • brew 链接 jpeg 问题

    我正在尝试安装opencv在 Mac OSX Lion 上 brew install opencv 我收到以下错误 以及其他一些类似的错误 Error The linking step did not complete successful
  • Opencv matchTemplate 和 np.where():仅保留唯一值

    继带有马里奥硬币的 opencv 教程 https opencv python tutroals readthedocs io en latest py tutorials py imgproc py template matching p
  • 我是否必须使用我的数据库训练 Viola-Jones 算法才能获得准确的结果?

    我尝试提取面部数据库的面部特征 但我认识到 Viola Jones 算法在两种情况下效果不佳 当我尝试单独检测眼睛时 当我尝试检测嘴巴时 运作不佳 检测图像的不同部分 例如眼睛或嘴巴 或者有时会检测到其中几个 这是不可能的情况 我使用的图像
  • Python中最相似的人脸识别

    如何使用Python和OpenCV来查找面部相似 我已成功使用 OpenCV 和 Python 使用 Haar Cascades 从多张照片中提取人脸 我现在有一个图像目录 所有这些都是不同人的面孔 我想做的是拍摄一张样本图像 然后看看它最
  • 使用Python的工业视觉相机[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • opencv 2.3.* 读取不工作

    我无法让 imread 工作 与这个人有同样的问题 OpenCV imwrite 2 2 在 Windows 7 上导致异常 并显示消息 OpenCV 错误 未指定错误 无法找到指定扩展名的编写器 https stackoverflow c
  • 指纹奇异点检测

    我正在尝试确定指纹的核心点和增量点 我正在使用庞加莱指数方法 但我无法成功检测到这一点 而且我不明白为什么 First I divide the image in 15x15 blocks then I calculate the x an
  • 如何在 OpenCV 中从 YUV 文件读取帧?

    如何在 OpenCV 中从 YUV 文件读取帧 我编写了一个非常简单的 python 代码来从二进制文件读取 YUV NV21 流 import cv2 import numpy as np class VideoCaptureYUV de

随机推荐