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

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

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

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

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

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



引言

  本篇博客介绍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 机器视觉定位技术详解 的技术博客。 📚

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

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

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

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

  • 43
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

清流君

感恩有您,共创未来,愿美好常伴

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值