【OpenMV】AprilTag 机器视觉定位技术详解

news2024/9/20 10:54:44

写在前面:
🌟 欢迎光临 清流君 的博客小天地,这里是我分享技术与心得的温馨角落。📝
个人主页:清流君_CSDN博客,期待与您一同探索 移动机器人 领域的无限可能。

🔍 本文系 清流君 原创之作,荣幸在CSDN首发🐒
若您觉得内容有价值,还请评论告知一声,以便更多人受益。
转载请注明出处,尊重原创,从我做起。

👍 点赞、评论、收藏,三连走一波,让我们一起养成好习惯😜
在这里,您将收获的不只是技术干货,还有思维的火花

📚 系列专栏:【机器视觉】系列,带您深入浅出,详解视觉技术。🖊
愿我的分享能为您带来启迪,如有不足,敬请指正,让我们共同学习,交流进步!

🎭 人生如戏,我们并非能选择舞台和剧本,但我们可以选择如何演绎 🌟
感谢您的支持与关注,让我们一起在知识的海洋中砥砺前行~~~


文章目录

  • 引言
  • 一、AprilTag简介
  • 二、OpenMV与AprilTag的结合
    • 1、AprilTag标签生成
    • 2、AprilTag标签获取
    • 3、AprilTag代码解读
  • 三、深入理解AprilTag定位
  • 四、AprilTag坐标与实际距离换算
    • 1、比例系数计算
    • 2、实际距离计算
  • 五、AprilTag与OpenMV摄像头的距离计算
    • 1、距离计算方法
    • 2、简化计算
  • 六、总结
  • 参考资料


引言

  本篇博客介绍OpenMV的 AprilTag 视觉定位。

一、AprilTag简介

  AprilTag是一种非常有用的视觉基准标记系统。可以利用 AprilTag 来获取标签相对摄像机的位置、距离以及坐标。

AprilTag 有非常多种类,叫做 家族(family)。常见的有:

  • TAG16H5 家族,共有 30 30 30 个 AprilTag 标签,编号 ID 分别是从 0 0 0 29 29 29
  • TAG36H11 家族,这个家族的 ID 数量非常多,从 0 0 0 586 586 586

在这里插入图片描述

  不同的 AprilTag 家族,数量和信息不一样。比如TAG16H5 共有 30 个 ID,每个标签图有 4 × 4 4 \times 4 4×4 的方块。对于 TAG36H11 家族来说,方块数量比较多,每个标签图有 6 × 6 6 \times 6 6×6 个方块。

  所以 TAG16H5家族的 AprilTag 标签比TAG36H11家族看的距离更远。因为 TAG36H11的方块数量更多,信息更准确,出错率更少。原因也是因为它的方块的数量多,有 6 × 6 6 \times 6 6×6 个方块,检验信息更多,所以出错率更少,因此一般情况下推荐使用TAG36H11

二、OpenMV与AprilTag的结合

1、AprilTag标签生成

  在OpenMV中,可直接在 IDE 生成 AprilTag 标签,或者也可以直接在网络上下载,生成后可打印出来,贴到物体上进行识别。
在这里插入图片描述

  比如可以打印TAG36H11的标签,这是直接OpenMV生成的,可以贴到的物体上来进行识别。

2、AprilTag标签获取

  将标签打印出来贴到物体上后,在 OpenMV 中就可以得到 AprilTag 标签相对于 OpenMV 相机的坐标和位置,坐标系以 OpenMV 为原点,共返回三个坐标量以及三个旋转量,分别是 AprilTag 标签相对 OpenMV 的坐标 ( T x , T y , T z ) (T_x,T_y,T_z) (Tx,Ty,Tz) 以及 x , y , z x,y,z x,y,z 三个方向的旋转量 ( R x , R y , R z ) (R_x,R_y,R_z) (Rx,Ry,Rz)

  通过三个坐标量以及三个旋转量可确定 AprilTag 相对于 OpenMV 的位置,并且AprilTag 会返回它的 ID,通过 ID 可以确定到底是哪个物体在视野中被识别到。

  AprilTag 的应用非常广泛,比如用在 AR 机器人或相机校准上。

3、AprilTag代码解读

  下面解读 AprilTag 的代码,先看一下这段比较简单的代码:

AprilTags Example1

import sensor, image, time, math

sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QQVGA) # 如果分辨率大得多,会耗尽内存
sensor.skip_frames(30)
sensor.set_auto_gain(False)  # 必须关闭此功能以防止图像流失
sensor.set_auto_whitebal(False)  # 设置白平衡关闭
clock = time.clock()

while(True):
    clock.tick()
    img = sensor.snapshot()
    for tag in img.find_apriltags(): # 默认为TAG36H11。
        img.draw_rectangle(tag.rect(), color = (255, 0, 0)) # 在识别到的AprilTag 上面画框和十字
        img.draw_cross(tag.cx(), tag.cy(), color = (0, 255, 0))
        degress = 180 * tag.rotation() / math.pi # 求 AprilTag 旋转的角度
        print(tag.id(),degress) # 打印 AprilTag 的 ID 以及角度

  看一下 find_apriltags()函数返回的数值

  在 image 库中查找 find_apriltags(),链接如下:

  OpenMV image-机器视觉库

在这里插入图片描述
  find_apriltags()函数,里有几个参数:class image.apriltag

  运行代码效果如下:
在这里插入图片描述

  识别到 ID 为 8 8 8 的 AprilTag 标签,旋转量为 345 ° 345° 345°

三、深入理解AprilTag定位

  AprilTag 最常用的功能是 3D 定位,可得到 AprilTag 的空间位置。

  下面解读稍复杂的代码:

  AprilTags Example2

import sensor, image, time, math

sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QQVGA) 
sensor.skip_frames(30)
sensor.set_auto_gain(False)  
sensor.set_auto_whitebal(False) 
clock = time.clock()

# 注意,与find_qrcodes不同,find_apriltags 不需要软件矫正畸变就可以工作。
# 注意,输出的姿态的单位是弧度,可以转换成角度,但是位置的单位是和你的大小有关,需要等比例换算

# f_x 是x的像素为单位的焦距。对于标准的OpenMV,应该等于2.8/3.984*656,这个值是用毫米为单位的焦距除以x方向的感光元件的长度,乘以x方向的感光元件的像素(OV7725)
# f_y 是y的像素为单位的焦距。对于标准的OpenMV,应该等于2.8/2.952*488,这个值是用毫米为单位的焦距除以y方向的感光元件的长度,乘以y方向的感光元件的像素(OV7725)

# c_x 是图像的x中心位置
# c_y 是图像的y中心位置

f_x = (2.8 / 3.984) * 160 # fx 是以x的像素为单位的焦距,一般不需要更改,与OpenMV感光元件的尺寸有关, 2.8 是标配镜头的焦距, 2.8 毫米
f_y = (2.8 / 2.952) * 120 # 3.984 和 2.952 是感光元件OV7725的长宽
c_x = 160 * 0.5 # (image.w * 0.5)  160 和 120 是视野中像素的大小,即QQVGA的分辨率
c_y = 120 * 0.5 # 默认值(image.h * 0.5) #  CXCY 是图像的 XY 中心的位置
# 注意不是 ROI 的中心位置,是整幅图像的中心位置,也就是分辨率的一半

# 定义函数,把弧度转换为角度
def degrees(radians):
    return (180 * radians) / math.pi

while(True):
    clock.tick()
    img = sensor.snapshot()
    for tag in img.find_apriltags(fx=f_x, fy=f_y, cx=c_x, cy=c_y): # 家族默认为TAG36H11
        img.draw_rectangle(tag.rect(), color = (255, 0, 0)) # 把识别到的 AprilTag 圈出来
        img.draw_cross(tag.cx(), tag.cy(), color = (0, 255, 0))
        
        # 识别到的 AprilTag 的 6 个量
        print_args = (tag.x_translation(), tag.y_translation(), tag.z_translation(), \ # x,y,z 方向的平移变换量
            degrees(tag.x_rotation()), degrees(tag.y_rotation()), degrees(tag.z_rotation())) # x,y,z 方向上的角度
        # 旋转的单位是角度
        print("Tx: %f, Ty %f, Tz %f, Rx %f, Ry %f, Rz %f" % print_args)
    print(clock.fps())

  运行程序,效果如下:

在这里插入图片描述
  串口输出为6个变量, T x , T y , T z T_x, T_y, T_z Tx,Ty,Tz 为空间的 3 3 3 个位置量, R x , R y , R z R_x,R_y,R_z Rx,Ry,Rz 3 3 3 个旋转量。
在这里插入图片描述
首先测试位置量的变化

  • 将标签沿水平方向移动, T x T_x Tx 数值改变
  • 将标签沿竖直方向移动, T y T_y Ty 数值改变
  • 将标签沿靠近摄像头方向移动, T z T_z Tz 数值减小

同样的来看一下其余三个旋转量的变化

  • 将标签俯仰调节, R x R_x Rx 数值改变
  • 将标签水平旋转, R y R_y Ry 数值改变

所以, R x Rx Rx 表征的是 AprilTag 标签沿 x x x 轴方向的旋转角度

  这 6 6 6 个量是表征 AprilTag 在以 OpenMV 为原点时,AprilTag标签相对于 OpenMV摄像头 的 x , y , z x,y,z x,y,z 的距离以及每个轴上旋转的角度。

四、AprilTag坐标与实际距离换算

可能会疑问 T x , T y , T z T_x, T_y, T_z Tx,Ty,Tz 这几个数值与实际距离是怎么换算的呢?

  通过前面的测量很容易可以得到 T x , T y , T z T_x, T_y, T_z Tx,Ty,Tz 和实际空间的坐标系一致,只是 T x , T y , T z T_x, T_y, T_z Tx,Ty,Tz 和实际坐标系的单位不同。

比如:

  • 20 c m 20cm 20cm 处,得到 T z = − 6.85 T_z =-6.85 Tz=6.85
  • 移动到 30 c m 30cm 30cm 处时,可得到 T z = − 9.89 T_z=-9.89 Tz=9.89

1、比例系数计算

  在 z z z 方向上可得到比例系数 k k k,表征实际距离与 T z T_z Tz 虚拟距离的关系,实际距离等于比例系数 k k k 乘以 T z T_z Tz,即正比例关系:
k z = 实际距离 T z k_z=\frac{实际距离}{T_z} kz=Tz实际距离  在 20 c m 20cm 20cm 处得到 T z = 6.85 T_z=6.85 Tz=6.85,则
k z = 200 m m 6.85 = 29.197 k_z=\frac{200mm}{6.85}=29.197 kz=6.85200mm=29.197  根据得到的 k z k_z kz,容易测得在 z z z 方向的实际距离。

2、实际距离计算

  比如在 T z T_z Tz 的绝对值为 9.89 9.89 9.89 时,可求得实际距离:
实际距离 = k z × T z = 9.89 × 200 6.85 = 288.759 \text{实际距离}=k_z\times T_z=9.89\times \frac{200}{6.85}=288.759 实际距离=kz×Tz=9.89×6.85200=288.759  得到的 288 m m 288mm 288mm 与实际 30 c m 30cm 30cm 距离基本一致。

  同理,可以求得其他 x , y x,y x,y 方向上的 k x , k y k_x,k_y kx,ky,这样就可得到实际空间坐标中 AprilTag 相对 OpenMV 的实际坐标。

  多数情况下不需要求得实际坐标值,在程序运算中,不必知道实际坐标,实际距离可直接通过 T x , T y , T z T_x, T_y, T_z Tx,Ty,Tz 来控制运动。

五、AprilTag与OpenMV摄像头的距离计算

另外,标签距离 OpenMV 摄像头的距离怎么计算呢?

1、距离计算方法

  上面计算的是 AprilTag 在实际空间中的 x , y , z x,y ,z x,y,z 坐标,现在要计算 AprilTag 距离OpenMV 摄像头的实际距离,这个距离粗略等于 T z T_z Tz 方向的距离,但稍微有点误差。根据勾股定理,实际距离等于 T x 2 + T y 2 + T z 2 \sqrt{T_{x}^{2}+T_{y}^{2}+T_{z}^{2}} Tx2+Ty2+Tz2 ,再乘以比例系数 k k k。利用勾股定理算出来的是更为准确的 AprilTag 与 OpenMV 之间的实际距离,可以再计算求一下 k k k
k = 实际距离 T x 2 + T y 2 + T z 2 k=\frac{\text{实际距离}}{\sqrt{T_{x}^{2}+T_{y}^{2}+T_{z}^{2}}} k=Tx2+Ty2+Tz2 实际距离可求得实际距离的比例系数 k k k k z k_z kz 基本一致,所以实际距离为
实际距离 = k × T x 2 + T y 2 + T z 2 \text{实际距离}=k\times \sqrt{T_{x}^{2}+T_{y}^{2}+T_{z}^{2}} 实际距离=k×Tx2+Ty2+Tz2

2、简化计算

  可直接粗略等于 z z z 方向的实际距离 k z × T z k_z\times T_z kz×Tz。得到 T x , T y , T z T_x, T_y, T_z Tx,Ty,Tz 以及 R x , R y , R z R_x,R_y,R_z Rx,Ry,Rz 后,就可以很轻松的知道 AprilTag 相对于 OpenMV 的位置坐标以及距离。

  这就是 Apriltag 最重要的应用。

六、总结

  本篇博客深入探讨了OpenMV与AprilTag视觉定位技术。AprilTag是一种高精度的视觉基准标记系统,通过其在摄像机视野中的位置、距离和坐标,能够实现精确的3D定位。AprilTag有多种家族,如TAG16H5和TAG36H11,它们在识别距离、精度等方面有所不同。OpenMV作为一个微控制器,可以直接在IDE中生成AprilTag标签,并将其应用于各种视觉定位任务。

  通过简单的示例代码,我们了解了如何使用OpenMV的image库来识别AprilTag,并获取其相对于摄像机的坐标和旋转角度。这些信息可以用于确定AprilTag在实际空间中的位置,并通过计算得到实际距离和方向。

  在深入的代码示例中,我们看到了如何通过设置焦距和图像中心点,来更准确地计算AprilTag的位置和旋转量。这些信息可以用于精确控制机器人的运动,或者在增强现实应用中定位虚拟物体。

  总的来说,OpenMV与AprilTag的结合为机器视觉和机器人定位提供了一个强大的工具。通过这些技术,可以实现精确的3D定位和控制,为各种应用提供支持。

参考资料

  1、OpenMV中文参考手册

  2、星瞳科技OpenMV视频教程11-AprilTag标记追踪

  3、[星瞳科技]OpenMV图像处理的方法(六):AprilTag标记跟踪


后记:

🌟 感谢您耐心阅读这篇关于 AprilTag 机器视觉定位技术详解 的技术博客。 📚

🎯 如果您觉得这篇博客对您有所帮助,请不要吝啬您的点赞和评论 📢

🌟您的支持是我继续创作的动力。同时,别忘了收藏本篇博客,以便日后随时查阅。🚀

🚗 让我们一起期待更多的技术分享,共同探索移动机器人的无限可能!💡

🎭感谢您的支持与关注,让我们一起在知识的海洋中砥砺前行 🚀

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

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

相关文章

C++开发基础之自定义异步日志库实现及性能测试

1. 前言 在软件开发中,日志记录是一个必不可少的部分。通过日志,我们可以记录系统的运行状态、错误信息以及调试数据。然而,当系统的日志量很大时,日志写入操作可能会影响系统的性能,尤其是在 I/O 操作较为频繁的情况…

VR虚拟展厅的应用场景有哪些?

虚拟展厅作为一种利用虚拟现实技术构建的三维展示空间,其应用场景广泛且多样。视创云展为企业虚拟展厅搭建提供技术支持。以下是一些主要的应用场景: 1. 博物馆和艺术展览 文物保护与展示: 在博物馆中,为了保护珍贵的文物和艺术…

初识命名空间

1.创建两个命名空间 ip netns add host1 ip netns add host2 2. 查看命名空间 ip netns ls 3 、 创建veth ip -netns host1 link add veth0 type veth peer name host1-peer 4、 查看命名空间接口 ip -netns host1 address 5、 把host1-peer移动到host2命名空间 ip -ne…

编译过程例题

答案:A 知识点: 词法分析:从左到右逐个扫描源程序中的字符,识别其中如关键字,标识符,常数,运算符以及分隔符 语法分析:根据语法规则将单词符号分解成各类语法单位,并分…

1.2CubeMAX创建FREERTOS入门示例

1.CUBEMAX快速配置 V2改为V1否则编译会报错 2.Freertos各配置选项卡解释 Events :事件相关的创建 Task and Queues : 任务与队列的创建 Timers and Semaphores : 定时器和信号量的创建 Mutexes : 互斥量的创建 FreeRTOS Heap…

android之bootchart的使用

文章目录 简述流程 简述 主要是记录开机运行时的一些进程记录情况 流程 1.开启bootchart 输入以下命令 adb shell touch /data/bootchart/enabled然后重新启动设备,即可记录开机过程中的一些文件,如下所示 如果不想要bootchart进行记录,直接删除掉/…

STM32单片机HAL库——ADC输入

一、单通道采集 二、单通道DMA采集 使能DMA 三、定时器采集DMA传输 选择定时器1的通道1作为触发源,在TIM1的上升沿进行采集 定时器1挂载在APB2上面,APB2上定时器的频率为168MHZ psc168-1 arr1000-1 TIM1的时钟频率为168/168/10001kHZ pulse设置为500…

云计算之大数据(下)

目录 一、Hologres 1.1 产品定义 1.2 产品架构 1.3 Hologres基本概念 1.4 最佳实践 - Hologres分区表 1.5 最佳实践 - 分区字段设置 1.6 最佳实践 - 设置字段类型 1.7 最佳实践 - 存储属性设置 1.8 最佳实践 - 分布键设置 1.9 最佳实践 - 聚簇键设置 1.10 最佳实践 -…

C# WPF燃气报警器记录读取串口工具

C# WPF燃气报警器记录读取串口工具 概要串口帧数据布局文件代码文件运行效果源码下载 概要 符合国标文件《GB15322.2-2019.pdf》串口通信协议定义;可读取燃气报警器家用版设备历史记录信息等信息; 串口帧数据 串口通信如何确定一帧数据接收完成是个…

golang学习笔记06——怎么实现本地文件及目录监控-fsnotify

推荐学习文档 基于golang开发的一款超有个性的旅游计划app经历golang实战大纲golang优秀开发常用开源库汇总golang学习笔记01——基本数据类型golang学习笔记02——gin框架及基本原理golang学习笔记03——gin框架的核心数据结构golang学习笔记04——如何真正写好Golang代码&…

在嵌入式板子上搭建和自定义live555服务器---编译问题和方法整理

live555 官方网站 点我直达,live555是一个简单的专注于实现RTSP服务器的开源库。它自带解析H264 H265 mp3等源的API,有一个简单的推流文件参考RTSP服务器例程testH264VideoStreamer也有官方实现的LIVE555 Media Server。无论是命令行使用还是用API实现定…

【最新华为OD机试E卷-支持在线评测】分糖果(100分)-多语言题解-(Python/C/JavaScript/Java/Cpp)

🍭 大家好这里是春秋招笔试突围 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-E/D卷的三语言AC题解 💻 ACM金牌🏅️团队| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢💗 🍿 最新华为OD机试D卷目录,全、新、准,题目覆盖率达 95% 以上,…

pyautogui进行点击失效,pyautogui.click()失效

背景:在Pycharm里,使用pythonpyautogui调用 .exe程序文件时候,当程序界面出来之后,鼠标失去反应,用pyautogui进行点击。后面尝试使用图片相似也无法实行点击。 解决方法:运行Pycharm或者其他ide的时候选择…

鸿蒙(API 12 Beta6版)超帧功能开发【顶点标记】

超帧提供两种运动估计模式供开发者选择:分别为基础模式和增强模式。其中增强模式需要对绘制顶点的Draw Call命令进行额外的标记,在相机和物体快速运动的游戏场景超帧效果较基础模式更优,能够有效改善拖影问题。本章主要介绍增强模式的运动估计…

【VB6|第27期】如何在VB6中使用Shell函数实现同步执行

日期:2024年9月1日 作者:Commas 签名:(ง •_•)ง 积跬步以致千里,积小流以成江海…… 注释:如果您觉得有所帮助,帮忙点个赞,也可以关注我,我们一起成长;如果有不对的地方&#xff…

算法打卡——田忌赛马问题

问题简介&#xff1a;就是一个贪心的思想&#xff0c;下面上题目 要求示例输出输入 大体上先比较快马&#xff0c;田的快马与王的快马 其次比较田的慢马与王的慢马&#xff0c; 两处边界比较完全之后可以直接贪心了 几份示例的代码 代码一 #include <bits/stdc.h> …

【数据结构-二维前缀和】力扣1504. 统计全 1 子矩形

给你一个 m x n 的二进制矩阵 mat &#xff0c;请你返回有多少个 子矩形 的元素全部都是 1 。 示例 1&#xff1a; 输入&#xff1a;mat [[1,0,1],[1,1,0],[1,1,0]] 输出&#xff1a;13 解释&#xff1a; 有 6 个 1x1 的矩形。 有 2 个 1x2 的矩形。 有 3 个 2x1 的矩形。 有…

ia复习笔记

HCIA 常用配置以及快捷键&#xff1a;! 查看时间&#xff1a;display clock&#xff1b;修改时间&#xff1a;clock datetime 11:11:11 2023-1-1 查看设备当前的配置&#xff1a;display current-configuration&#xff1b;查看已保存的配置&#xff1a;display saved-config…

水晶连连看 - 无限版软件操作说明书

水晶连连看 – 无限版游戏软件使用说明书 文章目录 水晶连连看 – 无限版游戏软件使用说明书1 引言1.1 编写目的1.2 项目名称1.3 项目背景1.4 项目开发环境 2 概述2.1 目标2.2 功能2.3 性能 3 运行环境3.1 硬件3.2 软件 4 使用说明4.1 游戏开始界面4.2 游戏设定4.2.1 游戏帮助4…

docker拉取redis5.0.5并建立redis集群

1.配置文件 mkdir -p redis-cluster/7001/ mkdir -p redis-cluster/7002/ mkdir -p redis-cluster/7003/ mkdir -p redis-cluster/7004/ mkdir -p redis-cluster/7005/ mkdir -p redis-cluster/7006/cd redis-clustervim 7001/redis.confbind 0.0.0.0port 7001cluster-enabled…