前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >ArUco与OpenCV

ArUco与OpenCV

作者头像
小锋学长生活大爆炸
发布于 2022-05-09 08:09:07
发布于 2022-05-09 08:09:07
1.2K00
代码可运行
举报
运行总次数:0
代码可运行

目录

生成标记

检测标记

完整代码

一些链接

代码片段记录

创建Aruco的Board板

检测Board板

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

生成标记

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

C++:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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++:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 加载用于生成标记的字典。
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:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#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图不能直接用,可以使用以下代码来增加白边

完整代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#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',需要转换类型:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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时候不需要转换,只用提供额外参数就行(毕竟已经是网格形了):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cv::Ptr<cv::aruco::GridBoard> board =  
    cv::aruco::GridBoard::create(5,             //每行多少个Marker
                                 7,             //每列多少个Marker
                                 0.04,          //marker长度
                                 0.01,          //marker之间的间隔
                                 dictionary);   //字典

检测Board板

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 估计相机位姿(相对于每一个marker)
cv::aruco::estimatePoseSingleMarkers(markerCorners, 0.055, cameraMatrix, distCoeffs, rvecs, tvecs);

 输出:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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]

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 估计相机位姿(相对于 aruco 板)
int valid = cv::aruco::estimatePoseBoard(markerCorners, markerIds, board, cameraMatrix, distCoeffs, rvec, tvec);

 输出:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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]
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-04-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
Matplotlib绘制六种可视化图表,值得收藏
可视化图表,有相当多种,但常见的也就下面几种,其他比较复杂一点,大都也是基于如下几种进行组合,变换出来的。对于初学者来说,很容易被这官网上众多的图表类型给吓着了,由于种类太多,几种图表的绘制方法很有可能会混淆起来。
double
2019/08/20
1.1K0
matplotlib入门
MATlAB是美国MathWorks公司出品的商业数学软件,用于数据分析、无线通信、深度学习、量化金融与风险管理、机器人,控制系统等领域。MATLAB在数值计算方面首屈一指,也是使用最广泛的科研绘图软件之一。优点:编程效率高 便于矩阵计算。缺点:循环效率低 封装性不好。
用户2225445
2022/11/12
4.4K0
matplotlib入门
Matplotlib从入门到精通02-层次元素和容器
参考: https://datawhalechina.github.io/fantastic-matplotlib/%E7%AC%AC%E4%B8%80%E5%9B%9E%EF%BC%9AMatplotlib%E5%88%9D%E7%9B%B8%E8%AF%86/index.html
用户2225445
2023/10/16
5230
Matplotlib从入门到精通02-层次元素和容器
12个最常用的matplotlib图例 !!
折线图(Line Plot):用于显示数据随时间或其他连续变量的变化趋势。在实际项目中,可以用于可视化模型性能随着训练迭代次数的变化。
JOYCE_Leo16
2024/03/19
5890
12个最常用的matplotlib图例 !!
深度学习基础之matplotlib,一文搞定各个示例
Matplotlib 是 Python 的绘图库。它可与 NumPy 一起使用 ,Matplotlib也是深度学习的常用绘图库,主要是将训练的成果进行图形化,因为这样更直观,更方便发现训练中的问题,今天来学习下,走起!!
香菜聊游戏
2021/10/19
1.6K0
深度学习基础之matplotlib,一文搞定各个示例
这40个Python可视化图表案例,强烈建议收藏!
不过有些小伙伴也会遇到不少问题,比如选择何种图表,以及如何制作,代码如何编写,这些都是问题!
小F
2021/09/14
4.4K0
Matplotlib 基础
Matplotlib 是一个 Python 绘图库,可以跨平台生成各种硬拷贝格式和交互式环境的出版品质数据。
iOSDevLog
2019/05/28
2K0
Python数据分析Matplotlib
1.2 使用matplotlib.pyplot中的annotate()函数标注文字
荣仔_最靓的仔
2021/02/02
3.6K0
Python数据分析Matplotlib
数据可视化基础与应用-03-matplotlib库从入门到精通01-05
本系列是数据可视化基础与应用的第03篇,主要介绍基于matplotlib实现数据可视化。
用户2225445
2024/03/21
9000
数据可视化基础与应用-03-matplotlib库从入门到精通01-05
探索数据科学与机器学习中的视觉表达【Matplotlib实战指南】
在数据科学和机器学习领域,数据可视化是一项至关重要的任务。它不仅可以帮助我们更好地理解数据,还能够有效地传达数据的洞察和趋势。而在 Python 中,Matplotlib 是一个强大而灵活的工具,可以用来创建各种类型的数据可视化图表,从简单的折线图到复杂的热图都能胜任。
一键难忘
2024/06/26
2480
Python数据可视化大全:Matplotlib、Seaborn、Bokeh和Plotly实战指南
数据可视化是数据科学和分析中不可或缺的一部分,而Python中的Matplotlib和Seaborn库为用户提供了强大的工具来创建各种可视化图表。本文将介绍如何使用这两个库进行数据可视化,并提供一些实用的代码示例和解析。
一键难忘
2024/04/18
2K0
数据分析 ——— matplotlib基础(二)
在上面的三个面板中分别画出了sin,cos图,前面两个参数分别为x轴, y轴数据。ax2的第三个参数“go--”是matlab风格的绘图,ax3上给出了点的标记maker,这一块是可以自己定义的,可以参考我上一篇文章数据分析 ——数据可视化matplotlib(一)。
andrew_a
2019/09/26
8380
数据分析 ——— matplotlib基础(二)
趋势(一)利用python绘制折线图
折线图用于在连续间隔或时间跨度上显示定量数值,最常用来显示趋势和关系(与其他折线组合起来)。折线图既能直观地显示数量随时间的变化趋势,也能展示两个变量的关系。
HsuHeinrich
2024/11/23
2200
趋势(一)利用python绘制折线图
Matplotlib 学习笔记
在 matplotlib 中,整个图像为 Figure ,而一个 Figure 中可以有多个 axes。
zucchiniy
2020/05/22
5460
Python之Matplotlib绘图
Python中一个重要的绘图库Matplotlib,它可以生成各种硬拷贝格式和跨平台交互式环境的出版物质量数据。Matplotlib可用于Python脚本,Python和IPython shell,Jupyter笔记本等。
剑指工控
2021/11/09
1.5K0
Python之Matplotlib绘图
Matplotlib_Study01
from matplotlib.font_manager import FontProperties
Echo_Wish
2023/11/30
2180
Matplotlib_Study01
使用Matplotlib对数据进行高级可视化(基本图,3D图和小部件)
可视化在当今世界许多领域的结果传播中发挥着重要作用。如果没有适当的可视化,很难揭示结果,理解变量之间的复杂关系并描述数据的趋势。
代码医生工作室
2019/06/21
3.9K0
使用Matplotlib对数据进行高级可视化(基本图,3D图和小部件)
数据分析画图:50道练习玩转matplotlib
Matplotlib 是 Python 的绘图库。它可与 NumPy 一起使用,提供了一种有效的 MatLab 开源替代方案,也可以和图形工具包一起使用。和Pandas、Numpy并称为数据分析三兄弟。友情提示:代码虽好,自己动手才算学到。
Datawhale
2020/02/21
8790
Python 高级绘图:从基础到进阶的可视化实践
在 Python 中,我们可以使用多种库来进行绘图,其中 matplotlib 是一个非常强大的绘图库。以下将介绍一些高级的绘图技巧和代码实现:
用户10354340
2024/10/07
940
基于Matplotlib的高级数据可视化技术与实践探索
文章链接:https://cloud.tencent.com/developer/article/2466769
一键难忘
2024/11/21
2730
推荐阅读
相关推荐
Matplotlib绘制六种可视化图表,值得收藏
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档