当前位置: 首页 > article >正文

【讲解+样例】使用opencv对aruco Markers识别

aruco标记与传统棋盘格功能相似,但是更快更便捷。棋盘格使用移步:【鱼眼+普通相机】相机标定

一、 aruco简介

aruco又称为aruco标记、aruco标签、aruco二维码。ArUco 标记通常是正方形的黑白图案。由黑色边框和内部的二进制矩阵组成。内部矩阵编码了一个唯一的 ID。
它有不同大小的 Aruco 标记,如 4x4, 5x5, 6x6, 7x7 等,指的是内部矩阵的尺寸。aruco二维码生成网站:https://chev.me/arucogen/
在这里插入图片描述

不同的字典定义了不同的标记集,如 DICT_6X6_250 表示 6x6 大小的 250 个唯一标记。
在这里插入图片描述

1.1 aruco码具有以下优点:

  • 快速检测:设计允许快速、可靠的检测。
  • 唯一识别:每个标记都有唯一的 ID。
  • 姿态估计:可以用于计算相机相对于标记的位置和方向。
  • 抗干扰:设计考虑了抗干扰性,如旋转、部分遮挡等。 应用:

1.2 aruco码可以实现以下功能:

  1. 增强现实(AR):作为参考点来放置虚拟对象。
  2. 机器人导航:帮助机器人定位和导航。
  3. 相机校准:用于相机参数的快速校准。
  4. 物体跟踪:在视频中跟踪物体的移动。

1.3 aruco码检测过程:

图像预处理(如灰度转换、阈值化)→ 轮廓检测 → 多边形近似(找到方形候选区域) → 透视变换 → 内部矩阵解码

二、样例

1.代码

import cv2
import numpy as np

print(cv2.__version__)

# 从文件读取图像
image = cv2.imread('./markers.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 指定字典类型
dict_type = cv2.aruco.DICT_6X6_1000

# 加载预定义字典
dictionary = cv2.aruco.getPredefinedDictionary(dict_type)

# 创建Aruco参数
aruco_params = cv2.aruco.DetectorParameters()
aruco_params.adaptiveThreshWinSizeMin = 3  #
aruco_params.adaptiveThreshWinSizeMax = 80  #
aruco_params.adaptiveThreshWinSizeStep = 10  # 代表自适应阈值的窗口大小
aruco_params.adaptiveThreshConstant = 7  # 代表自适应阈值的常数
aruco_params.minMarkerPerimeterRate = 0.1  # 假设marker至少占图像的10%
aruco_params.maxMarkerPerimeterRate = 10.0  # 允许marker最大占图像的80%
aruco_params.polygonalApproxAccuracyRate = 0.1  # 代表多边形逼近的精度
aruco_params.minCornerDistanceRate = 0.05  # 代表marker的最小角距离
aruco_params.minDistanceToBorder = 0  # 代表marker的最小边界距离

# 创建Aruco检测器
detector = cv2.aruco.ArucoDetector(dictionary, aruco_params)

# 检测Aruco markers
corners, ids, rejected = detector.detectMarkers(gray)
print(f"Adaptive Threshold - Detected: {len(corners)}, Rejected: {len(rejected)}")

rej_img = image.copy()
for r in rejected:
    try:
        pts = r.reshape((-1, 1, 2)).astype(np.int32)
        cv2.polylines(rej_img, [pts], True, (0, 0, 255), 2)
    except Exception as e:
        print(f"Error drawing rejected candidate: {e}")

# 如果检测到markers,绘制它们
if ids is not None:
    print(f"Detected Aruco markers: {ids}")
    cv2.aruco.drawDetectedMarkers(image, corners, ids)

    # 遍历每个检测到的marker
    for i in range(len(ids)):
        c = corners[i][0]
        cv2.putText(image, f"id: {ids[i][0]}", (int(c[0][0]), int(c[0][1]) - 15),
                    cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)

        # 绘制marker的边界框
        cv2.polylines(image, [np.int32(c)], True, (0, 255, 0), 2)

        # 计算marker的中心
        cx = int((c[0][0] + c[2][0]) / 2)
        cy = int((c[0][1] + c[2][1]) / 2)
        cv2.circle(image, (cx, cy), 2, (0, 0, 255), -1)

        # 计算marker的方向
        cv2.line(image, (cx, cy), (int(c[0][0]), int(c[0][1])), (255, 0, 0), 2)
        cv2.line(image, (cx, cy), (int(c[1][0]), int(c[1][1])), (0, 255, 0), 2)

        # 计算marker的旋转角度
        dx = c[0][0] - c[1][0]
        dy = c[0][1] - c[1][1]
        angle = np.arctan2(dy, dx)
        angle = np.degrees(angle)
        cv2.putText(image, f"angle: {angle:.1f}", (cx, cy + 15),
                    cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
        # 计算marker的尺寸
        size = np.sqrt(dx * dx + dy * dy)
        cv2.putText(image, f"size: {size:.1f}", (cx, cy + 30),
                    cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)

        # 计算marker的坐标
        cv2.putText(image, f"({cx},{cy})", (cx, cy + 45),
                    cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)

# 显示结果
cv2.imshow('gray', gray)
cv2.imshow('Image with rejected candidates', rej_img)
cv2.imshow("Aruco markers", image)
cv2.waitKey(0)
cv2.destroyAllWindows()

2.结果

在这里插入图片描述

三、参考

  1. opencv: https://docs.opencv.org/3.1.0/d5/dae/tutorial_aruco_detection.html
  2. 开源AR库ArUco的原理与位姿估计实战
  3. [OpenCV] aruco Markers识别
  4. https://blog.csdn.net/sinat_16643223/article/details/137357584

http://www.kler.cn/a/331478.html

相关文章:

  • IIC I2C子协议 SMBus协议 通信协议原理 时序 SMBus深度剖析
  • ViEW生命周期
  • C++ 面向对象编程:友元、
  • Android详解——ConstraintLayout约束布局
  • C语言编程1.27汉诺塔
  • 使用k6进行MongoDB负载测试
  • 【Python】正则表达式及其在Python中的应用
  • 解决centos 删除文件后但空间没有释放
  • 2024 夸克网盘优质免费资源合集分享推荐 - 原创
  • elementPlus的tree组件点击后有白色背景
  • 音视频入门基础:FLV专题(6)——FFmpeg源码中,解码FLV header的实现
  • std::map
  • UE4_Niagara基础实例—3、使用自定义模块二
  • 螺蛳壳里做道场:老破机搭建的私人数据中心---Centos下Docker学习06(Docker网络连接)
  • Java | Leetcode Java题解之第454题四数相加II
  • Linux学习之路 -- 线程 -- 死锁及线程安全相关问题
  • centos一些常用命令
  • 计算机网络:计算机网络体系结构 —— OSI 模型 与 TCP/IP 模型
  • 蓝桥杯【物联网】零基础到国奖之路:十八. 扩展模块之光敏和AS312
  • 7.3树形查找
  • 国庆刷题(day2)
  • Redis-哨兵
  • C++ 语言特性10 - 委托构造函数
  • QQ机器人搭建
  • iframe标签是做什么用的
  • 计算机毕业设计 Java酷听音乐系统的设计与实现 Java实战项目 附源码+文档+视频讲解