ArUco与OpenCV

2024-03-03 00:58
文章标签 opencv aruco

本文主要是介绍ArUco与OpenCV,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

生成标记

检测标记

完整代码

一些链接

代码片段记录

创建Aruco的Board板

检测Board板



        ArUco标记可以用于增强现实、相机姿势估计和相机校准等应用场景,具体如无人机的自主降落地标、机器人定位。标记中白色部分为唯一标识的二进制编码。

生成标记

        通过为每个码生成唯一标记,可以获取到更丰富的信息。在OpenCV中有25个预定义的标记字典。字典中的所有标记都包含相同数量的块或位(4×4、5×5、6×6 或 7×7),并且每个字典包含固定数量的标记(50、100、250 或 1000)。

C++:

#include <opencv2/highgui.hpp>
#include <opencv2/core.hpp>
#include <opencv2/xfeatures2d.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc.hpp>// 导入aruco库
#include <opencv2/aruco.hpp>using namespace std;
using namespace cv;Mat markerImage;
// 加载预定义字典
Ptr<cv::aruco::Dictionary> dictionary = aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250);// 生成标记
int id = 33;  // 唯一标记
int pixsize = 200;  // 图像的像素大小
aruco::drawMarker(dictionary, id, pixsize , markerImage, 1);imshow("markerImage", markerImage);
waitKey();

Python:

import cv2 as cv
import numpy as np# Load the predefined dictionary
dictionary = cv.aruco.Dictionary_get(cv.aruco.DICT_6X6_250)# Generate the marker
ixsize = 200  # 图像的像素大小
id = 33 # 唯一标记
markerImage = np.zeros((ixsize , ixsize ), dtype=np.uint8)
markerImage = cv.aruco.drawMarker(dictionary, id, ixsize , markerImage, 1);cv.imwrite("marker33.png", markerImage);

对于cv.aruco.drawMarker函数:

  • 第一个参数视预定义字典。
  • 第二个参数标识唯一标记,允许从 id 从 0 到 249 的 250 个标记的集合中选择具有给定 id 的标记。
  • 第三个参数决定了生成的标记的大小。在上面的示例中,它将生成一个具有 200×200 像素的图像。
  • 第四个参数表示将存储生成的标记的对象(上面的标记图像)。
  • 第五个参数是厚度参数,它决定了应该将多少块作为边界添加到生成的二进制模式中。在上面的示例中,将在 6×6 生成的图案周围添加 1 位的边界,以在 200×200 像素的图像中生成具有 7×7 位的图像。

检测标记

C++:

// 加载用于生成标记的字典。
Ptr<cv::aruco::Dictionary> dictionary = getPredefinedDictionary(cv::aruco::DICT_6X6_250);
// 使用默认值初始化检测器参数
Ptr<cv::aruco::DetectorParameters> parameters = cv::aruco::DetectorParameters::create();// 声明将包含检测到的标记角和被拒绝的候选标记的向量
vector<vector<Point2f>> markerCorners, rejectedCandidates;
// 检测到的标记的id存储在一个向量中
vector<int> markerIds;
// 检测标记
detectMarkers(markerImage, dictionary, markerCorners, markerIds, parameters, rejectedCandidates);

Python:

#Load the dictionary that was used to generate the markers.
dictionary = cv.aruco.Dictionary_get(cv.aruco.DICT_6X6_250)# Initialize the detector parameters using default values
parameters =  cv.aruco.DetectorParameters_create()# Detect the markers in the image
markerCorners, markerIds, rejectedCandidates = cv.aruco.detectMarkers(frame, dictionary, parameters=parameters)

        对于每个成功的标记物检测,将按左上角、右上角、右下角、左下角的顺序检测标记的四个角点。在C++中,这4个检测到的角点被存储为点的向量,并且图像中的多个标记一起存储在点的向量向量中。在Python中,它们被存储为数组的Numpy数组。

        在打印、剪切和放置场景中的标记时,重要的是在标记的黑色边界周围保留一些白色边框,以便可以轻松检测到它们。因此对于上面生成的Aruco图不能直接用,可以使用以下代码来增加白边

完整代码

#include <iostream>
#include <opencv2/highgui.hpp>
#include <opencv2/core.hpp>
#include <opencv2/xfeatures2d.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/aruco.hpp>using namespace std;
using namespace cv;vector<Mat> generateAruco(int nums, int pixSize=200, int border=1) {vector<Mat> markerImages;Ptr<cv::aruco::Dictionary> dictionary = aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250);for (int i = 0; i < nums; ++i) {Mat tempImage;aruco::drawMarker(dictionary, i, pixSize, tempImage, border);markerImages.push_back(tempImage);}return markerImages;
}void detectAruco(const Mat& markerImage, vector<vector<Point2f>> &markerCorners, vector<vector<Point2f>> &rejectedCandidates, vector<int> &markerIds) {// 加载用于生成标记的字典。Ptr<cv::aruco::Dictionary> dictionary = getPredefinedDictionary(cv::aruco::DICT_6X6_250);// 使用默认值初始化检测器参数Ptr<cv::aruco::DetectorParameters> parameters = cv::aruco::DetectorParameters::create();// 检测标记detectMarkers(markerImage, dictionary, markerCorners, markerIds, parameters, rejectedCandidates);
}int main(int argc, char* argv[])
{vector<Mat> markerImages = generateAruco(1);Mat markerImage = markerImages[0];vector<vector<Point2f>> markerCorners;vector<vector<Point2f>> rejectedCandidates;vector<int> markerIds;cv::copyMakeBorder(markerImage, markerImage, 5, 5, 5, 5, cv::BORDER_CONSTANT, Scalar(255,0,0));detectAruco(markerImage, markerCorners, rejectedCandidates, markerIds);cout << markerIds.size() << endl;imshow("markerImage", markerImage);waitKey();return 0;
}

一些链接

OpenCV:检测dArUco标记(单个)

在OpenCV中使用ArUco Markers的增强现实(C++ / Python)

ArUco: a minimal library for Augmented Reality applications based on OpenCV

OpenCV:检测ArUco板(多个)

代码片段记录

创建Aruco的Board板

更:这个好像不对??)创建Aruco中Board(与GridBoard不同,Board不限于网格形,可以是任意排列的2D、3D图形)时,出现类型错误objPoints.type() == CV_32FC3 || objPoints.type() == CV_32FC1 in function 'create',需要转换类型:

if (markerCorners.empty()) {cout<<"无可用Marker"<<endl;return 0;
}std::vector< std::vector< Point3f > > objPoints;
for (auto corner: markerCorners) {vector< Point3f > temp;for (int i = 0; i < 4; ++i) {temp.emplace_back(Point3f(corner[i].x, corner[i].y, 0));}objPoints.emplace_back(temp);
}
cv::Ptr<cv::aruco::Board> board = cv::aruco::Board::create(objPoints, dictionary, markerIds);

而对于创建GridBoard时候不需要转换,只用提供额外参数就行(毕竟已经是网格形了):

cv::Ptr<cv::aruco::GridBoard> board =  cv::aruco::GridBoard::create(5,             //每行多少个Marker7,             //每列多少个Marker0.04,          //marker长度0.01,          //marker之间的间隔dictionary);   //字典

检测Board板

相对于上面创建的Board,此处有两种方式来检测:单次检测、一起检测。

        对于单次检测,是分开每次检测一个,分别估计位姿

// 估计相机位姿(相对于每一个marker)
cv::aruco::estimatePoseSingleMarkers(markerCorners, 0.055, cameraMatrix, distCoeffs, rvecs, tvecs);

 输出:

R_{camera<---marker} :[-0.0003413119903118433, 0.9999500428020713, 0.009989765075384124;0.9998031880569347, 0.0001430703615183937, 0.0198384647103005;0.01983604439689155, 0.00999457007618388, -0.9997532895228086]
t_{camera<---marker} :[0.236643, 0.554003, 1.73982]R_{camera<---marker} :[-0.9987024032747158, -0.04667896450031111, 0.02036133508603012;-0.03554963247130007, 0.9252917858620086, 0.3775861949905609;-0.03646550869605953, 0.3763724024014953, -0.9257505503028689]
t_{camera<---marker} :[-0.353789, 0.2201, 1.68946]R_{camera<---marker} :[0.9926712669967025, 0.0045609525196265, 0.120759899765092;0.01132149090445043, -0.998402461553577, -0.05535655884769745;0.1203145025458768, 0.05631804751473418, -0.9911370732654825]
t_{camera<---marker} :[0.164678, 0.105936, 1.38113]R_{camera<---marker} :[0.974149731293016, -0.09977617778369052, -0.2026746539866854;-0.04192481488856337, -0.961439121983884, 0.2718034668936692;-0.2219788524123525, -0.2562801768879826, -0.9407687601190632]
t_{camera<---marker} :[0.745065, 0.110989, 1.73927]R_{camera<---marker} :[0.001805456772273173, -0.995139605508609, -0.09845763491986455;-0.9661010203335827, -0.02715349161609959, 0.2567323633737377;-0.2581580113733717, 0.09465650237159776, -0.9614544127115553]
t_{camera<---marker} :[0.153552, -0.265153, 1.90376]

        而一起检测,是对所有的一起检测后,算一个总的位姿:(比较适用于需要高精度、有遮挡、有形变的情况)

// 估计相机位姿(相对于 aruco 板)
int valid = cv::aruco::estimatePoseBoard(markerCorners, markerIds, board, cameraMatrix, distCoeffs, rvec, tvec);

 输出:

R_{camera<---marker} :[0.009618842263444671, -0.07316045611916067, -0.997273796674688;-0.7388014820617763, -0.672599545516235, 0.04221636501022974;-0.6738544709184865, 0.7363812864486647, -0.06052068234393715]
t_{camera<---marker} :[-5.07066, 571.684, -24.9751]

这篇关于ArUco与OpenCV的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/767962

相关文章

使用Python和OpenCV库实现实时颜色识别系统

《使用Python和OpenCV库实现实时颜色识别系统》:本文主要介绍使用Python和OpenCV库实现的实时颜色识别系统,这个系统能够通过摄像头捕捉视频流,并在视频中指定区域内识别主要颜色(红... 目录一、引言二、系统概述三、代码解析1. 导入库2. 颜色识别函数3. 主程序循环四、HSV色彩空间详解

OpenCV实现实时颜色检测的示例

《OpenCV实现实时颜色检测的示例》本文主要介绍了OpenCV实现实时颜色检测的示例,通过HSV色彩空间转换和色调范围判断实现红黄绿蓝颜色检测,包含视频捕捉、区域标记、颜色分析等功能,具有一定的参考... 目录一、引言二、系统概述三、代码解析1. 导入库2. 颜色识别函数3. 主程序循环四、HSV色彩空间

Python中OpenCV与Matplotlib的图像操作入门指南

《Python中OpenCV与Matplotlib的图像操作入门指南》:本文主要介绍Python中OpenCV与Matplotlib的图像操作指南,本文通过实例代码给大家介绍的非常详细,对大家的学... 目录一、环境准备二、图像的基本操作1. 图像读取、显示与保存 使用OpenCV操作2. 像素级操作3.

C/C++中OpenCV 矩阵运算的实现

《C/C++中OpenCV矩阵运算的实现》本文主要介绍了C/C++中OpenCV矩阵运算的实现,包括基本算术运算(标量与矩阵)、矩阵乘法、转置、逆矩阵、行列式、迹、范数等操作,感兴趣的可以了解一下... 目录矩阵的创建与初始化创建矩阵访问矩阵元素基本的算术运算 ➕➖✖️➗矩阵与标量运算矩阵与矩阵运算 (逐元

C/C++的OpenCV 进行图像梯度提取的几种实现

《C/C++的OpenCV进行图像梯度提取的几种实现》本文主要介绍了C/C++的OpenCV进行图像梯度提取的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录预www.chinasem.cn备知识1. 图像加载与预处理2. Sobel 算子计算 X 和 Y

C/C++和OpenCV实现调用摄像头

《C/C++和OpenCV实现调用摄像头》本文主要介绍了C/C++和OpenCV实现调用摄像头,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录准备工作1. 打开摄像头2. 读取视频帧3. 显示视频帧4. 释放资源5. 获取和设置摄像头属性

c/c++的opencv图像金字塔缩放实现

《c/c++的opencv图像金字塔缩放实现》本文主要介绍了c/c++的opencv图像金字塔缩放实现,通过对原始图像进行连续的下采样或上采样操作,生成一系列不同分辨率的图像,具有一定的参考价值,感兴... 目录图像金字塔简介图像下采样 (cv::pyrDown)图像上采样 (cv::pyrUp)C++ O

c/c++的opencv实现图片膨胀

《c/c++的opencv实现图片膨胀》图像膨胀是形态学操作,通过结构元素扩张亮区填充孔洞、连接断开部分、加粗物体,OpenCV的cv::dilate函数实现该操作,本文就来介绍一下opencv图片... 目录什么是图像膨胀?结构元素 (KerChina编程nel)OpenCV 中的 cv::dilate() 函

qtcreater配置opencv遇到的坑及实践记录

《qtcreater配置opencv遇到的坑及实践记录》我配置opencv不管是按照网上的教程还是deepseek发现都有些问题,下面是我的配置方法以及实践成功的心得,感兴趣的朋友跟随小编一起看看吧... 目录电脑环境下载环境变量配置qmake加入外部库测试配置我配置opencv不管是按照网上的教程还是de

python+OpenCV反投影图像的实现示例详解

《python+OpenCV反投影图像的实现示例详解》:本文主要介绍python+OpenCV反投影图像的实现示例详解,本文通过实例代码图文并茂的形式给大家介绍的非常详细,感兴趣的朋友一起看看吧... 目录一、前言二、什么是反投影图像三、反投影图像的概念四、反向投影的工作原理一、利用反向投影backproj