写在前面:
🌟 欢迎光临 清流君 的博客小天地,这里是我分享技术与心得的温馨角落。📝
个人主页:清流君_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 机器视觉定位技术详解 的技术博客。 📚
🎯 如果您觉得这篇博客对您有所帮助,请不要吝啬您的点赞和评论 📢
🌟您的支持是我继续创作的动力。同时,别忘了收藏本篇博客,以便日后随时查阅。🚀
🚗 让我们一起期待更多的技术分享,共同探索移动机器人的无限可能!💡
🎭感谢您的支持与关注,让我们一起在知识的海洋中砥砺前行 🚀