Aruco 库详解:计算机视觉中的高效标记检测工具

news2025/3/10 17:34:16
1. 引言:Aruco 在计算机视觉中的重要性

在计算机视觉领域,标记(Marker)检测和识别是许多应用的基础,包括 机器人导航、增强现实(AR)、相机标定(Calibration)以及物体跟踪 等。其中,Aruco 库 是一个广泛使用的 开源标记检测工具,它基于 OpenCV 开发,能够快速可靠地检测、识别和跟踪二维标记(fiducial markers)。

Aruco 标记是一种类似于二维码的方形图案,包含唯一的二进制 ID,并且能够被计算机视觉算法轻松识别。与传统的二维码不同,Aruco 主要用于 定位、空间映射和相机姿态估计(Pose Estimation),因此在机器人学、AR 应用和工业视觉检测中扮演着重要角色。

本文将深入解析 Aruco 库的 工作原理、核心功能、应用场景、实践示例 以及 潜在的挑战和优化策略,帮助你全面理解如何利用 Aruco 进行高效的计算机视觉开发。


2. Aruco 标记的基本概念

2.1 什么是 Aruco 标记?

Aruco 标记是一种 二进制方形标记,通常由一个黑色边框和一个内部的唯一编码组成,如下图所示:

+------------+
|            |
|  01010     |
|  11001     |
|  10100     |
|            |
+------------+

它与二维码(QR Code)的主要区别在于:

  • Aruco 不用于存储大规模数据,而仅用于存储少量 ID 信息。
  • 它的边框清晰,有助于 快速检测和姿态估计
  • 由于模式固定,Aruco 检测 速度更快,误识别率更低

Aruco 标记通常被用于相机标定、机器人导航、物体跟踪等任务中,特别适合需要 精确空间定位 的应用场景。


2.2 Aruco 库的核心模块

Aruco 库是 OpenCV 生态的一部分,主要提供以下核心功能:

标记检测(Marker Detection)
能够从图像中快速检测并识别 Aruco 标记的位置和 ID。

姿态估计(Pose Estimation)
通过标记的位置计算 相机的姿态(3D 位置和旋转角度),广泛用于 AR 和 SLAM(同步定位与建图)。

相机标定(Camera Calibration)
利用 Aruco 生成的标记阵列(Chessboard-like Pattern)来校正相机的 内参矩阵,提高计算机视觉系统的精度。

自定义字典(Custom Dictionary)
可以创建自定义标记集合,避免与已有的 Aruco ID 发生冲突,提高识别的安全性和唯一性。


3. Aruco 标记检测的工作原理

Aruco 标记检测的基本流程如下:

3.1 图像预处理
  • 灰度化(Grayscale Conversion):将输入图像转换为灰度,以减少计算量。
  • 阈值化(Thresholding):二值化处理,以突出黑白对比,提高检测精度。
3.2 轮廓检测
  • 通过 边缘检测(Edge Detection)连通区域分析(Connected Component Analysis) 提取可能的标记区域。
  • 利用 四边形拟合算法 识别出潜在的 Aruco 标记区域。
3.3 二进制编码解析
  • 将提取的方形区域按照预定义字典(Dictionary)进行比对。
  • 使用 汉明距离(Hamming Distance) 检查识别的正确性,并纠正误差。
3.4 姿态估计
  • 通过 PnP 算法(Perspective-n-Point) 计算相机的 3D 姿态。
  • 需要使用相机的 内参矩阵(Camera Intrinsics) 进行校正。

通过上述步骤,Aruco 库能够精准检测标记的位置和 ID,并计算它在 3D 空间中的姿态。


4. Aruco 的应用场景

Aruco 在多个计算机视觉领域中都有广泛应用,主要包括以下场景:

4.1 机器人导航 🚗🤖
  • 在机器人导航和自动驾驶中,Aruco 可以作为 路标,帮助机器人确定自身位置并规划路径。
  • 通过检测 Aruco 标记的 ID 和相对位置,机器人可以执行精准的路径跟踪。
4.2 增强现实(AR) 🎮📱
  • 在 AR 应用中,Aruco 标记可以用来 计算相机的姿态,从而让虚拟物体精准地叠加在现实环境中。
  • 许多 AR 设备(如 Microsoft HoloLens、Magic Leap)都使用类似的标记进行空间映射。
4.3 相机标定 📷
  • Aruco 库可以生成棋盘样式的标记阵列,用于相机 畸变校正焦距计算
  • 通过多个不同角度拍摄的 Aruco 阵列,可以提高相机校准的精度。
4.4 物体跟踪与测量 📏
  • 在工业检测和智能制造中,Aruco 标记可以帮助 精确测量物体的尺寸、角度和位置,提高自动化生产线的准确性。

5. Aruco 实践示例:Python 代码演示

生成一个图:

import cv2
import numpy as np

# 获取预定义的 ArUco 字典
aruco_dict = cv2.aruco.getPredefinedDictionary(cv2.aruco.DICT_ARUCO_ORIGINAL)

# 设定 4 个标记的 ID(可以自己调整)
marker_ids = [10, 20, 30, 40]  # 确保 ID 唯一
marker_size = 200  # 每个标记的大小(像素)

# 创建白色背景图像(比如 1000x1000 像素)
board_size = 1000
aruco_board = np.full((board_size, board_size), 255, dtype=np.uint8)

# 创建 4 个 ArUco 标记并放置在四个角落
for i, marker_id in enumerate(marker_ids):
    marker_img = cv2.aruco.drawMarker(aruco_dict, marker_id, marker_size)
    
    # 根据索引确定标记位置
    if i == 0:  # 左上角
        aruco_board[0:marker_size, 0:marker_size] = marker_img
    elif i == 1:  # 右上角
        aruco_board[0:marker_size, -marker_size:] = marker_img
    elif i == 2:  # 左下角
        aruco_board[-marker_size:, 0:marker_size] = marker_img
    else:  # 右下角
        aruco_board[-marker_size:, -marker_size:] = marker_img

# 保存 ArUco 标记板
cv2.imwrite("aruco_board.png", aruco_board)

# 显示结果
cv2.imshow("ArUco Board", aruco_board)
cv2.waitKey(0)
cv2.destroyAllWindows()

运行后:
在这里插入图片描述

以下是一个 基于 OpenCV 的 Aruco 标记检测代码,可以帮助你快速入门:

import cv2
import numpy as np
import imutils
#pip install opencv-contrib-python==4.6.0.66
def order_points(pts):
    # 初始化排序后的点的列表
    rect = np.zeros((4, 2), dtype=np.float32)
    
    # pts的和将作为排序的依据
    s = pts.sum(axis=1)
    # 左上角的点将有最小的和
    rect[0] = pts[np.argmin(s)]
    # 右下角的点将有最大的和
    rect[2] = pts[np.argmax(s)]
    
    # pts的差将作为排序的依据
    diff = np.diff(pts, axis=1)
    # 右上角的点将有最小的差
    rect[1] = pts[np.argmin(diff)]
    # 左下角的点将有最大的差
    rect[3] = pts[np.argmax(diff)]
    
    return rect

def detect_color_correction_card(image_path):
    # Load image
    image = cv2.imread(image_path)
    
    # Resize image 
    image = imutils.resize(image, width=600)
    
    # Convert to grayscale
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    
    # Create ArUco dictionary and parameters
    arucoDict = cv2.aruco.Dictionary_get(cv2.aruco.DICT_ARUCO_ORIGINAL)
    arucoParams = cv2.aruco.DetectorParameters_create()
    
    # Detect ArUco markers
    (corners, ids, rejected) = cv2.aruco.detectMarkers(gray, arucoDict, parameters=arucoParams)
    
    # Check if markers are detected
    if ids is not None and len(ids) > 0:
        try:
            ids = ids.flatten()
            print(ids)    
            if all(id in ids for id in ids):
                # 创建一个字典来存储每个ID对应的角点
                marker_corners = {}
                for i, marker_id in enumerate(ids):
                    corner = np.squeeze(corners[i])
                    marker_corners[marker_id] = corner
                
                # 收集所有标记的所有角点
                all_corners = []
                for corner in corners:
                    corner = np.squeeze(corner)
                    for point in corner:
                        all_corners.append(point)
                
                # 将所有角点转换为numpy数组
                all_corners = np.array(all_corners, dtype=np.float32)
                
                # 计算凸包
                hull = cv2.convexHull(all_corners)
                hull = np.squeeze(hull)
                
                # 找到最小外接矩形的四个角点
                rect = cv2.minAreaRect(hull)
                box = cv2.boxPoints(rect)
                box = np.array(box, dtype=np.float32)
                print(box)
                # 对这四个角点进行排序
                ordered_corners = order_points(box)
                
                # 找到ID为10的标记的位置
                marker_10_corners = marker_corners[10]
                marker_10_center = np.mean(marker_10_corners, axis=0)
                
                # 找到ordered_corners中最接近marker_10_center的点的索引
                distances = np.linalg.norm(ordered_corners - marker_10_center, axis=1)
                marker_10_idx = np.argmin(distances)
                
                # 如果ID为10的标记不在左上角,重新排序点
                if marker_10_idx != 0:
                    ordered_corners = np.roll(ordered_corners, -marker_10_idx, axis=0)
                
                # 扩大边界以确保包含所有标记
                # 计算边界扩展因子
                padding = 0  # 可以调整这个值
                
                # 获取排序后的角点
                topLeft, topRight, bottomRight, bottomLeft = ordered_corners
                
                # 向外扩展边界
                vector_top = topRight - topLeft
                vector_left = bottomLeft - topLeft
                
                topLeft = topLeft - (vector_top + vector_left) * padding / 100
                topRight = topRight + (vector_top - vector_left) * padding / 100
                bottomRight = bottomRight + (vector_top + vector_left) * padding / 100
                bottomLeft = bottomLeft + (-vector_top + vector_left) * padding / 100
                
                # print([topLeft, topRight, bottomRight, bottomLeft])
                # Prepare points for perspective transform
                pts1 = np.float32([topLeft, topRight, bottomRight, bottomLeft])
                
                # Define destination points
                width, height = 300, 600
                pts2 = np.float32([
                    [0, 0],            # Top-left (ID 10)
                    [width-1, 0],      # Top-right
                    [width-1, height-1],  # Bottom-right
                    [0, height-1]      # Bottom-left
                ])
                
                # Compute perspective transform matrix
                matrix = cv2.getPerspectiveTransform(pts1, pts2)
                
                # Apply perspective transformation
                warped = cv2.warpPerspective(image, matrix, (width, height))
                
                # Draw detected markers on original image
                cv2.aruco.drawDetectedMarkers(image, corners, ids)
                
                # Display results
                cv2.namedWindow('Original Image', cv2.WINDOW_NORMAL)
                cv2.namedWindow('Warped Image', cv2.WINDOW_NORMAL)
                
                cv2.imshow('Original Image', image)
                cv2.imshow('Warped Image', warped)
                
                cv2.waitKey(0)
                cv2.destroyAllWindows()
                
                return warped
            else:
                print("Not all expected markers found")
                return None
        
        except Exception as e:
            print(f"An error occurred: {e}")
            return None
    
    else:
        print("No ArUco markers detected")
        return None

# Usage example
result = detect_color_correction_card('14.png')

原图
在这里插入图片描述
识别后:
在这里插入图片描述
在这里插入图片描述

运行效果:

  • 代码会在图像中检测 Aruco 标记,并在检测到的标记上绘制边框和 ID。
  • 你可以尝试不同的 Aruco 字典(DICT_4X4_50、DICT_6X6_100 等) 来生成不同种类的标记。

6. Aruco 的挑战与优化策略

误检测问题

  • 复杂背景可能导致误检测,可以使用 自适应阈值化 提高精度。

标记角度影响

  • 角度过大时,透视变形可能影响识别,建议使用 PnP 进行姿态优化

光照变化

  • 低光环境下,推荐使用 HDR 预处理,增强标记的对比度。

7. 结论

Aruco 是一个强大且高效的计算机视觉工具,广泛应用于 机器人、AR、相机标定和物体跟踪 领域。它的高检测速度和低误识别率使其成为许多项目的首选方案。

如果你正在开发涉及 空间定位、相机标定或增强现实 的应用,Aruco 绝对是一个值得深入研究的技术! 🚀

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2311811.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第005文-模拟入侵网站实现0元购

1、部署导入靶场,部署购物网站 首先在虚拟机中新增一个centos虚拟机,在上面部署一套完整的购物网站,使用mysql数据库,访问端口是80。这个新增的centos虚拟机就是我们的靶场。购物网站在网上随便找一套开源的部署即可。 2、在网站…

23种设计模式简介

一、创建型(5种) 1.工厂方法 总店定义制作流程,分店各自实现特色披萨(北京店-烤鸭披萨,上海店-蟹粉披萨) 2.抽象工厂 套餐工厂(家庭装含大披萨薯条,情侣装含双拼披萨红酒&#…

HTML前端手册

HTML前端手册 记录前端框架在使用过程中遇到的各种问题和解决方案,供后续快速进行手册翻阅使用 文章目录 HTML前端手册1-前端框架1-TypeScript框架2-CSS框架 2-前端Demo1-Html常用代码 2-知云接力3-Live2D平面动画 3-前端运维1-NPM版本管理 1-前端框架 1-TypeScrip…

利用 requestrepo 工具验证 XML外部实体注入漏洞

1. 前言 在数字化浪潮席卷的当下,网络安全的重要性愈发凸显。应用程序在便捷生活与工作的同时,也可能暗藏安全风险。XXE(XML外部实体)漏洞作为其中的典型代表,攻击者一旦利用它,便能窃取敏感信息、掌控服务…

引领变革!北京爱悦诗科技有限公司荣获“GAS消费电子科创奖-产品创新奖”!

在2025年“GAS消费电子科创奖”评选中,北京爱悦诗科技有限公司提交的“aigo爱国者GS06”,在技术创新性、设计创新性、工艺创新性、智能化创新性及原创性五大维度均获得评委的高度认可,荣获“产品创新奖”。 这一奖项不仅是对爱悦诗在消费电子…

纯html文件实现目录和文档关联

目录结构 效果图 代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><title>项目结题报告</title><style lang"scss">::-webkit-scrollbar {width: 6px;height: 6px;}::-webkit-scro…

共绘智慧升级,看永洪科技助力由由集团起航智慧征途

在数字化洪流汹涌澎湃的当下&#xff0c;企业如何乘风破浪&#xff0c;把握转型升级的黄金机遇&#xff0c;已成为所有企业必须直面的时代命题。由由集团&#xff0c;作为房地产的领航者&#xff0c;始终以前瞻视野引领变革&#xff0c;坚决拥抱数字化浪潮&#xff0c;携手数字…

自学嵌入式第27天------TCP和UDP,URL爬虫

1. TCP和UDP区别 **TCP&#xff08;传输控制协议&#xff09;和UDP&#xff08;用户数据报协议&#xff09;**是两种主要的传输层协议&#xff0c;它们在数据传输方式上有显著区别&#xff1a; 连接性&#xff1a; TCP是面向连接的协议&#xff0c;通信前需通过三次握手建立连…

三维建模与视频融合(3D-Video Integration)技术初探。

三维建模与视频融合&#xff08;3D-Video Integration&#xff09;是一种将虚拟三维模型无缝嵌入实拍视频场景的技术&#xff0c;广泛应用于影视特效、增强现实&#xff08;AR&#xff09;、游戏开发、广告制作 、视频监控 等领域。 一、技术核心流程 三维建模与动画 使用工具…

分布式存储学习——HBase概述

1.1 HBase概述 1.1.1 理解大数据背景 1.1.2 HBase是什么 1.1.3 HBase与Hadoop的关系 1.1.4 HBase的核心功能模块 1.1.5 HBase的应用场景和经典案例 1.1.6 小结 本文参考于学校《HBase应用于开发》教材 1.1 HBase概述 本节将介绍大数据背景和HBase的基本概念&#xff0c…

LLM run

lmstudio lmstudio ollama ollama N 卡使用自带UI gpu加速推理 ,选择满足条件的&#xff0c; ds模型选择列表 https://ollama.com/library/deepseek-r1 a卡当前支持的显卡型号 I卡 gpu加速配置 2025.3 intel Official project optimization https://www.modelscope.cn/m…

【大模型基础_毛玉仁】2.2 大语言模型架构概览

【大模型基础_毛玉仁】2.2 大语言模型架构概览 2.2 大语言模型架构概览2.2.1 主流模型架构的类别1&#xff09;Encoder-only 架构2&#xff09;Encoder-Decoder 架构3&#xff09;Decoder-only 架构 2.2.2 模型架构的功能对比1&#xff09;注意力矩阵2&#xff09;适用任务 2.2…

pt-archiver删除数据库的数据表/各种报错类型

这篇帖子是前面文的一部分延申 mysqlimport导入一亿数据的csv文件/一行命令删除表-CSDN博客 如需转载&#xff0c;标记出处 目录 pt-archiver命令格式 如果执行后出现下面报错 1&#xff09;Cannot find an ascendable index in table at /usr/bin/pt-archiver line 3233. …

LLM 学习(一 序言)

文章目录 LLM 学习&#xff08;一 序言&#xff09;知识点1&#xff1a;“Embedding” 在人工智能领域&#xff1a;知识点2&#xff1a;Embedding 引入位置信息的原因知识点3&#xff1a;在 Transformer 的 Decoder 翻译第 i 个单词时进行 Mask 第 i1 个单词的操作 LLM 学习&am…

STM32-HAL库初始化时钟

使能和失能外设GPIOA 时钟信号初始化函数 HAL_RCC_OscConfig函数&#xff1a; HAL_StatusTypeDef是该函数的返回值类型,最顶上的那句话只是这个函数的原型 HAL_RCC_ClockConfig函数&#xff1a; 因为FLASH实际上只能支持24MHz的时钟信号所以如果用高于24MHz的信号输入则要用到等…

批量将 Word 拆分成多个文件

当一个 Word 文档太大的时候&#xff0c;我们通常会将一个大的 Word 文档拆分成多个小的 Word 文档&#xff0c;在 Office 中拆分 Word 文档是比较麻烦的&#xff0c;我们需要将 Word 文档的页面复制到另外一个 Word 文档中去&#xff0c;然后删除原 Word 文档中的内容。当然也…

【算法系列】桶排序算法介绍及实现

文章目录 桶排序算法介绍及实现桶排序的基本原理算法实现步骤Java代码实现性能优化结论 桶排序算法介绍及实现 桶排序的基本原理 桶排序&#xff08;Bucket Sort&#xff09;是一种基于分组的排序算法&#xff0c;其核心思想是将一组数据按某种 规则分配到多个桶中&#xff0…

13.数据结构(软考)

13.数据结构&#xff08;软考&#xff09; 13.1:线性表 13.1.1 顺序表 顺序存储方式:数组的内存是连续分配的并且是静态分配的&#xff0c;即在使用数组之前需要分配固定大小的空间。 时间复杂度&#xff1a; 读&#xff1a;O(1) 查询&#xff1a;1&#xff0c;(n1)/2&#x…

拉拉扯扯adfda

read -p "请输入一个成绩&#xff1a;" sorce if [ "$sorce" -ge 90 -a "$sorce" -le 100 ] thenecho A elif [ "$sorce" -ge 80 -a "$sorce" -lt 90 ] thenecho B elif [ "$sorce" -ge 70 -a "$sorce"…

【计算机网络】TCP

1.基本概念及报文格式 基本概念&#xff1a; TCP的中文全称为传输控制协议&#xff08;Transmission Control Protocol&#xff09;&#xff0c;是一种可靠的&#xff0c;面向连接的&#xff0c;基于字节流的传输层通信协议。 报文格式&#xff1a; 序号 &#xff1a;占32⽐…