论文阅读模块将分享点云处理,SLAM,三维视觉,高精地图相关的文章。公众号致力于理解三维视觉领域相关内容的干货分享,欢迎各位加入我,我们一起每天一篇文章阅读,开启分享之旅,有兴趣的可联系微信dianyunpcl@163.com。

opencv中ArUco模块实践(1)

ArUco的生成与检测

ArUco与AprilTag简介

ChAruco标定板

ArUCo标记板是非常有用的,因为他们的快速检测和多功能性。然而,ArUco标记的一个问题是,即使在应用亚像素细化后,其角点位置的精度也不太高。相反,棋盘图案的角点可以更精确地细化,因为每个角点被两个黑色正方形包围。然而,寻找棋盘图案并不像寻找aruco棋盘那样通用:它必须是完全可见的,并且不允许遮挡。

ChAruco标记板试图结合这两种方法的优点:

ArUco部分用于内插棋盘转角的位置,因此它具有标记板的多功能性,因为它允许遮挡或局部视图。此外,由于插值的角点属于棋盘,因此它们在亚像素精度方面非常精确。

当对角点加测的要求是高精度且必要的,如在相机校准,Charuco板是一个比标准aruco板更好的选择。

ChArUco标记板的创建

aruco模块提供cv::aruco::CharucoBoard类,该类表示Charuco板,并从Board类继承。

该类与ChArUco的其他功能一样,定义如下:

#include <opencv2/aruco/charuco.hpp>

要定义Charuco标记板,必须:

  • X方向的棋盘格数。

  • Y方向棋盘格数。

  • 正方形边的长度。

  • 标记侧的长度。

  • 标记词典。

  • 所有标记的ID。

对于GridBoard对象,aruco模块提供了一个创建CharucoBoards的函数。

cv::aruco::CharucoBoard::create():
cv::aruco::CharucoBoard board = cv::aruco::CharucoBoard::create(5, 7, 0.04, 0.02, dictionary);
  • 第一和第二参数分别是X和Y方向上的平方数。

  • 第三和第四个参数分别是正方形和标记的长度。它们可以以任何单位提供,记住该标记板的估计姿势将以相同单位测量(通常使用米)。

  • 最后给出了标记的字典。

默认情况下,每个标记的ID都是从0开始按升序分配的,就像在GridBoard::create()中一样。这可以通过board.ids访问ids向量来轻松定制,就像在board父类中一样。

一旦我们有了CharucoBoard对象,我们就可以创建一个图像来打印它。这可以通过

cv::aruco::CharucoBoard board = cv::aruco::CharucoBoard::create(5, 7, 0.04, 0.02, dictionary);cv::Mat boardImage;board.draw( cv::Size(600, 500), boardImage, 10, 1 );
  • 第一个参数是以像素为单位的输出图像的大小。在本例中为600x500像素。如果这与电路板尺寸不成比例,它将以图像为中心。

  • boardImage:根据标定板输出的图像。

  • 第三个参数是(可选)以像素为单位的边距,因此没有任何标记接触图像边界。在这种情况下,边距是10。

  • 最后,标记边框的大小,类似于drawMarker()函数。默认值为1。

ChArUco标定板检测

当你检测到一个ChArUco棋盘时,实际检测到的是棋盘的每个棋盘格角点。

ChArUco板上的每个角落都分配了一个唯一标识符(id)。这些ID从0到板中的角总数。

因此,检测到的ChArUco板包括:

vector<Point2f>charucoCorners:检测到的角点的图像位置列表。

vector<int>charucoIds:charucoCorners中每个检测到的角点的ID。

ChArUco角点的检测基于先前检测到的标记。因此,首先检测标记,然后从标记中插值ChArUco角点。检测ChArUco角点的函数是

cv::aruco::interpolateCornersCharuco()

这个例子展示了整个过程。首先,检测标记,然后从这些标记中插值ChArUco角点。

cv::Mat inputImage;
cv::Mat cameraMatrix, distCoeffs;
// camera parameters are read from somewhere
readCameraParameters(cameraMatrix, distCoeffs);cv::aruco::Dictionary dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250);cv::aruco::CharucoBoard board = cv::aruco::CharucoBoard::create(5, 7, 0.04, 0.02, dictionary);
...vector< int > markerIds;
vector< vector<Point2f> > markerCorners;cv::aruco::detectMarkers(inputImage, board.dictionary, markerCorners, markerIds);
// if at least one marker detected
if(markerIds.size() > 0) {
std::vector<cv::Point2f> charucoCorners;std::vector<int> charucoIds;cv::aruco::interpolateCornersCharuco(markerCorners, markerIds, inputImage, board, charucoCorners, charucoIds, cameraMatrix, distCoeffs);}

interpolateCornersCharuco()函数的参数为:

markerCorners和markerIds:从detectMarkers()函数中检测到的标记物。

inputimage:检测到标记的原始图像。图像是必要的执行亚像素细化在Aruco角点。

board:CharucoBoard对象

charucockerners和charucoIds:输出插值Charuco角点

cameraMatrix和distcoefs:可选的摄像机校准参数

函数返回插值的Charuco角点的数目。

在这种情况下,我们调用interpolateCornersCharuco()来提供相机校准参数。但是,这些参数是可选的。没有这些参数的类似示例如下:

cv::Mat inputImage;
cv::aruco::Dictionary dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250);cv::aruco::CharucoBoard board = cv::aruco::CharucoBoard::create(5, 7, 0.04, 0.02, dictionary);...
vector< int > markerIds;vector< vector<Point2f> > markerCorners;DetectorParameters params;params.doCornerRefinement = false;cv::aruco::detectMarkers(inputImage, board.dictionary, markerCorners, markerIds, params);// if at least one marker detectedif(markerIds.size() > 0) {std::vector<cv::Point2f> charucoCorners;std::vector<int> charucoIds;cv::aruco::interpolateCornersCharuco(markerCorners, markerIds, inputImage, board, charucoCorners, charucoIds);}

如果提供了校准参数,ChArUco角点插值方法是,首先从ArUco标记估计一个粗略姿态,然后将ChArUco角点重新投影回图像。另一方面,如果不提供校准参数,则通过计算ChArUco平面和ChArUco图像投影之间的对应单应来插值ChArUco角点。

使用单应的主要问题是插值对图像失真更敏感。实际上,单应仅使用每个ChArUco角点的最近标记位来执行,以减少失真的影响。

在检测ChArUco板的标记时,特别是在使用单应性时,建议禁用标记的角点细化。其原因是,由于棋盘方块的接近性,亚像素过程会在角点位置产生重要的偏差,这些偏差会传播到ChArUco角点插值,产生较差的结果。

此外,仅返回其两个周围标记已找到的角点。如果没有检测到周围的两个标记中的任何一个,这通常意味着该区域存在某种遮挡或图像质量不好。在任何情况下,最好不要考虑该角点,因为我们想要的是确保插值的ChArUco角点非常精确。

在对ChArUco角点进行插值之后,执行亚像素细化。

一旦我们内插了ChArUco角点,我们可能会想画出来看看他们的检测是否正确。使用drawDetectedCornersCharuco()函数可以轻松完成此操作:

 cv::aruco::drawDetectedCornersCharuco(image, charucoCorners, charucoIds, color);
  • image是绘制角点的图像(通常与检测角点的图像相同)。

  • outputImage将是inputImage的克隆,并绘制了角点。

  • charucoCorners和charucoIds是从interpolateCornersCharuco()函数中检测到的Charuco角点。

  • 最后,最后一个参数是要绘制角点的(可选)颜色,类型为cv::Scalar。

最后,这是ChArUco检测的完整示例(不使用校准参数)

cv::VideoCapture inputVideo;inputVideo.open(0);cv::aruco::Dictionary dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250);cv::aruco::CharucoBoard board = cv::aruco::CharucoBoard::create(5, 7, 0.04, 0.02, dictionary);DetectorParameters params;params.doCornerRefinement = false;while (inputVideo.grab()) {cv::Mat image, imageCopy;inputVideo.retrieve(image);image.copyTo(imageCopy);std::vector<int> ids;std::vector<std::vector<cv::Point2f> > corners;cv::aruco::detectMarkers(image, dictionary, corners, ids, params);// if at least one marker detectedif (ids.size() > 0) {cv::aruco::drawDetectedMarkers(imageCopy, corners, ids);std::vector<cv::Point2f> charucoCorners;std::vector<int> charucoIds;cv::aruco::interpolateCornersCharuco(corners, ids, image, board, charucoCorners, charucoIds);// if at least one charuco corner detectedif(charucoIds.size() > 0)cv::aruco::drawDetectedCornersCharuco(imageCopy, charucoCorners, charucoIds, cv::Scalar(255, 0, 0));}cv::imshow("out", imageCopy);char key = (char) cv::waitKey(waitTime);if (key == 27)break;}

ChArUco姿态估计

ChArUco板的最终目标是非常精确地找到角点,以便进行高精度校准或姿态估计。

aruco模块提供了一个简单的ChArUco姿态估计功能。与在GridBoard中一样,CharucoBoard的坐标系放置在板平面中,Z轴指向外,并居中于板的左下角。

姿态估计的函数是estimatePosecharocboard():

cv::aruco::EstimatePoseCharocboard(charucoCorners、charucoIds、board、cameraMatrix、Distceffs、rvec、tvec);

charucoCorners和charucoIds参数是从interpolateCornersCharuco()函数中检测到的charuco角点。

  • 第三个参数是CharucoBoard对象。

  • cameraMatrix和distcoefs是姿态估计所必需的摄像机标定参数。

  • 最后,rvec和tvec参数是Charuco板的输出姿态。

如果正确估计了姿势,则函数返回true,否则返回false。失败的主要原因是没有足够的角点进行姿态估计或它们在同一条直线上。可以使用drawAxis()绘制轴,以检查姿势是否正确估计。结果是:(X:红色,Y:绿色,Z:蓝色)

完整的的位姿估计的代码

cv::VideoCapture inputVideo;
inputVideo.open(0);cv::Mat cameraMatrix, distCoeffs;// camera parameters are read from somewherereadCameraParameters(cameraMatrix, distCoeffs);cv::aruco::Dictionary dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250);cv::aruco::CharucoBoard board = cv::aruco::CharucoBoard::create(5, 7, 0.04, 0.02, dictionary);while (inputVideo.grab()) {cv::Mat image, imageCopy;inputVideo.retrieve(image);image.copyTo(imageCopy);std::vector<int> ids;std::vector<std::vector<cv::Point2f> > corners;cv::aruco::detectMarkers(image, dictionary, corners, ids);// if at least one marker detectedif (ids.size() > 0) {std::vector<cv::Point2f> charucoCorners;std::vector<int> charucoIds;cv::aruco::interpolateCornersCharuco(corners, ids, image, board, charucoCorners, charucoIds, cameraMatrix, distCoeffs);// if at least one charuco corner detectedif(charucoIds.size() > 0) {cv::aruco::drawDetectedCornersCharuco(imageCopy, charucoCorners, charucoIds, cv::Scalar(255, 0, 0));cv::Vec3d rvec, tvec;bool valid = cv::aruco::estimatePoseCharucoBoard(charucoCorners, charucoIds, board, cameraMatrix, distCoeffs, rvec, tvec);// if charuco pose is validif(valid)cv::aruco::drawAxis(imageCopy, cameraMatrix, distCoeffs, rvec, tvec, 0.1);}}cv::imshow("out", imageCopy);char key = (char) cv::waitKey(waitTime);if (key == 27)break;}

资源

三维点云论文及相关应用分享

【点云论文速读】基于激光雷达的里程计及3D点云地图中的定位方法

3D目标检测:MV3D-Net

三维点云分割综述(上)

3D-MiniNet: 从点云中学习2D表示以实现快速有效的3D LIDAR语义分割(2020)

win下使用QT添加VTK插件实现点云可视化GUI

JSNet:3D点云的联合实例和语义分割

大场景三维点云的语义分割综述

PCL中outofcore模块---基于核外八叉树的大规模点云的显示

基于局部凹凸性进行目标分割

基于三维卷积神经网络的点云标记

点云的超体素(SuperVoxel)

基于超点图的大规模点云分割

更多文章可查看:点云学习历史文章大汇总

SLAM及AR相关分享

【开源方案共享】ORB-SLAM3开源啦!

【论文速读】AVP-SLAM:自动泊车系统中的语义SLAM

【点云论文速读】StructSLAM:结构化线特征SLAM

SLAM和AR综述

常用的3D深度相机

AR设备单目视觉惯导SLAM算法综述与评价

SLAM综述(4)激光与视觉融合SLAM

Kimera实时重建的语义SLAM系统

SLAM综述(3)-视觉与惯导,视觉与深度学习SLAM

易扩展的SLAM框架-OpenVSLAM

高翔:非结构化道路激光SLAM中的挑战

SLAM综述之Lidar SLAM

基于鱼眼相机的SLAM方法介绍

如果你对本文感兴趣,请点击“原文阅读”获取知识星球二维码,务必按照“姓名+学校/公司+研究方向”备注加入免费知识星球,免费下载pdf文档,和更多热爱分享的小伙伴一起交流吧!

以上内容如有错误请留言评论,欢迎指正交流。如有侵权,请联系删除

扫描二维码

关注我们

让我们一起分享一起学习吧!期待有想法,乐于分享的小伙伴加入免费星球注入爱分享的新鲜活力。分享的主题包含但不限于三维视觉,点云,高精地图,自动驾驶,以及机器人等相关的领域。

分享及合作:群主微信“920177957”(需要按要求备注) 联系邮箱:dianyunpcl@163.com,欢迎企业来联系公众号展开合作。

点一下“在看”你会更好看耶

OpenCV中检测ChArUco的角点(2)相关推荐

  1. OpenCV中的几种角点检测方法

    1.Harris角点检测 import numpy as np import cv2 as cv import matplotlib.pyplot as pltplt.rcParams['font.s ...

  2. 如何使用Python在OpenCV中检测图像中的猫脸?

    haar 级联分类器是一种有效的对象检测方法.这是一种基于机器学习的方法.为了训练用于猫脸检测的haar级联分类器,该算法最初需要大量的正面图像(有猫脸的图像)和负面图像(没有猫脸的图像).分类器是从 ...

  3. opencv检测相交点_在网络摄像头feed opencv中检测2条线之间的交点

    我正在尝试检测摄像头Feed中两条线之间的交点.这是我已经拥有的屏幕截图 我尝试找到红线和绿线之间的交点. 这是我已经拥有的代码 #include "stdafx.h" #incl ...

  4. 【OpenCV 例程 300篇】240. OpenCV 中的 Shi-Tomas 角点检测

    『youcans 的 OpenCV 例程300篇 - 总目录』 [youcans 的 OpenCV 例程 300篇]240. OpenCV 中的 Shi-Tomas 角点检测 角是直线方向的快速变化. ...

  5. linux打开网络摄像头失败,Opencv没有检测到linux上的firewire网络摄像头

    我通过firewire连接了一个凸轮,并尝试使用opencv访问它 . 相机在香菜中被检测到并且能够获得视频流 . 以下是我使用的代码 #include "/home/iiith/openc ...

  6. cv2.cornerHarris()详解 python+OpenCV 中的 Harris 角点检测

    原文作者:aircraft 原文地址:https://www.cnblogs.com/DOMLX/p/8763369.html 参考文献----------OpenCV-Python-Toturial ...

  7. OpenCV中角点未检测到原因与FindChessboardCorners函数

    本博客参考两位前辈的实验记录角点检测与FindChessboardCorners函数 和 OpenCV学习笔记(33)棋盘格角点检测练习程序,总结整理而成. 实验历程: 我在前几天的实验中,总是检测不 ...

  8. OpenCV中的Harris角点检测

    OpenCV中的Harris角点检查 1. 效果图 2. 原理 3. 源码 3.1 Harris角点检测 3.2 精细角点检测 参考 这篇博客将了解什么是特征,角点,哈里斯角点检测(Harris Co ...

  9. OpenCV中角点检测:Harris、Shi-Tomasi、亚像素级角点检测

    1.角点的定义 角点通常被定义为两条边的交点,或者说,角点的局部邻域应该具有两个不同区域的不同方向的边界.比如,三角形有三个角,矩形有四个角,这些就是角点,也是他们叫做矩形.三角形的特征. 角点是个很 ...

最新文章

  1. Microbiome: 再论扩增子功能预测分析(Picrust)的效果
  2. Linux_进程管理计划任务
  3. 使用hibernate实现树形结构无限级分类
  4. python全栈开发百度云_价值2400 2016年11月全栈开发Flask Python Web 网站编程
  5. UVa 11059 Maximum Product
  6. 天池 在线编程 分割数组
  7. 卡顿人生,如何拯救?
  8. android git 版本管理,Android版本管理(git 和 repo)
  9. 黑苹果mac未能安装在你的电脑上_mac电脑上全新视频剪辑软件安装包分享,让你剪辑视频从此无忧!...
  10. php 回调通知 连连支付_微信小程序支付及退款流程详解
  11. Ruby Tip:定义索引操作符
  12. 为资产分类定义折旧范围_SAP FICO零基础学习_0006_资产-概述和基本配置
  13. 最新PHP超精简全站自适应小说网网站源码
  14. 《计算机组成原理》作业,《计算机组成原理》作业一解答.doc
  15. druid数据库连接池 数据库配置密码加密
  16. 【历史上的今天】10 月 27 日:世界上第一次网络瘫痪;网络广告的诞生;短视频鼻祖 Vine 关闭
  17. chrome自动代理检测(这玩意并没什么用,还会影响你访问某些网页)
  18. Part-02/通过案例学爬虫(豆瓣电影TOP250)
  19. 基于RT-Thread的环境监测装置(含IO口模拟8080时序驱动TFT屏幕)
  20. 开学季,中学生用什么样护眼台灯好?中学生用护眼台灯排行

热门文章

  1. springboot日志logback配置
  2. 知识图谱学习笔记(1)
  3. Eclipse使用Maven建立SSM多模块的项目
  4. MySQL 学习笔记(18)— 索引的分类、创建、查看、删除等
  5. NBUT 1457 Sona(莫队算法+离散化)
  6. YTU 2723: 默认参数--求圆的面积
  7. 1m网速是什么意思,1m带宽是什么意思
  8. 用C#来开发CAD插件,含源代
  9. CS Tip 16: 利用注释
  10. 未能从程序集 XX加载类型XXX的错误解决方法(借以提醒NHibernate使用者)