文章目录
一、AprilTag简介
AprilTag是一个视觉基准系统,可用于多种任务,包括增强现实,机器人和相机校准。通过特定的标志(与二维码相似,但是降低了复杂度以满足实时性要求),可以快速地检测标志,并计算相对位置。它可以从普通打印机创建目标,AprilTag检测软件可以计算标签相对于相机的精确3D位置,方向和身份。AprilTag库在C中实现,没有任何外部依赖关系。它被设计为易于包含在其他应用程序中,并且可移植到嵌入式设备中。即使在手机级处理器上也可以实现实时性能。
官网:https://april.eecs.umich.edu/software/apriltag.html
git仓库地址:https://github.com/AprilRobotics/apriltag
AprilTags在概念上与QR码类似,因为它们是一种二维条形码。但是,它们被设计为对更小的数据有效载荷(4到12位之间)进行编码,从而可以更健壮地检测到它们,并且检测距离更长。此外,它们的设计具有很高的定位精度-您可以计算AprilTag相对于摄像机的精确3D位置。
与二维码相比, AprilTags可在更远距离、较差光线和更扭曲的图像环境下被检测到。 AprilTags可应对所有种类的图像失真问题,而二维码并不能。也就是说, AprilTags只能将数字D编码作为其有效载荷。
二、AprilTag原理
AprilTag内容主要包含三个步骤。
- 第一步:根据梯度检测出图像中的各种边缘
- 第二步:在边缘图像中找出需要的四边形图案并进行筛选
AprilTag尽可能的对检测出的边缘检测,首先剔除非直线边缘,在直线边缘进行邻接边缘查找,最终若形成闭环则为检测到一个四边形)
- 第三步:进行二维码编码和二维码解码
编码方式分为三种,其黑边色块长度分别为8,7,6三个色块长度,对于解码内容,要在检测到的四边形内生成点阵列用于计算每色块的值,再根据局部二值模式(Local Binary Patterns)构造简单分类器对四边形内的色块进行分类,将正例色块编码为1将负例色块编码为0,就可以得到该二维码的编码。得到编码以后再与已知库内的编码进行匹配,确定解码出的二维码是否为正确。
三、AprilTag图像生成
下载openmv软件
安装后打开,依次按照图示进行,选择相应文件夹生成即可
标签系列的区别?
例如,TAG16H5家族,16为16个像素块,5为假阳性值,其实际上是一个4x4的方形标签。一般来说,默认使用族TAG36H11。当然现在AprilTag更新到了第三代,使用tagStandard41h12更好。
四、OpenMV实现
利用OpenMV自带函数 find_apriltags 寻找Apriltag
https://book.openmv.cc/example/26-April-Tags/find-apriltags.html
import sensor, image, time, math
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QQVGA) # 如果分辨率更大,我们的内存会耗尽...
sensor.skip_frames(time = 2000)
sensor.set_auto_gain(False) # 必须关闭此功能,以防止图像冲洗…
sensor.set_auto_whitebal(False) # 必须关闭此功能,以防止图像冲洗…
clock = time.clock()
# 注意!与find_qrcodes不同,find_apriltags方法不需要对图像进行镜头校正
# apriltag代码最多支持可以同时处理6种tag家族。
# 返回的tag标记对象,将有其tag标记家族及其在tag标记家族内的id。
def family_name(tag):
if(tag.family() == image.TAG16H5):
return "TAG16H5"
if(tag.family() == image.TAG25H7):
return "TAG25H7"
if(tag.family() == image.TAG25H9):
return "TAG25H9"
if(tag.family() == image.TAG36H10):
return "TAG36H10"
if(tag.family() == image.TAG36H11):
return "TAG36H11"
if(tag.family() == image.ARTOOLKIT):
return "ARTOOLKIT"
while(True):
clock.tick()
img = sensor.snapshot()
for tag in img.find_apriltags(): # 如果没有给出家族,默认TAG36H11。
img.draw_rectangle(tag.rect(), color = (255, 0, 0))
img.draw_cross(tag.cx(), tag.cy(), color = (0, 255, 0))
print_args = (family_name(tag), tag.id(), (180 * tag.rotation()) / math.pi)
print("Tag Family %s, Tag ID %d, rotation %f (degrees)" % print_args)
print(clock.fps())
另外,在查阅资料的时候发现MaixPY 也可以实现类似的功能【MaixPY 教程】用mixly玩转k210——条形码、二维码、AprilTag识别
五、pupil-apriltags
python的apriltag库还是比较多的,但是大同小异,推荐的是apriltags(Linux)或者pupil-apriltags(Windows)
pip install pupil-apriltags
基本使用方法
from pupil_apriltags import Detector
at_detector = Detector(families='tag36h11',
nthreads=1,
quad_decimate=1.0,
quad_sigma=0.0,
refine_edges=1,
decode_sharpening=0.25,
debug=0)
The options of apriltag_detector():
Option | Default | Explanation |
---|---|---|
families | ‘tag36h11’ | Tag families, separated with a space |
nthreads | 1 | Number of threads |
quad_decimate | 2.0 | Detection of quads can be done on a lower-resolution image, improving speed at a cost of pose accuracy and a slight decrease in detection rate. Decoding the binary payload is still done at full resolution. Set this to 1.0 to use the full resolution. |
quad_sigma | 0.0 | What Gaussian blur should be applied to the segmented image. Parameter is the standard deviation in pixels. Very noisy images benefit from non-zero values (e.g. 0.8) |
refine_edges | 1 | When non-zero, the edges of the each quad are adjusted to “snap to” strong gradients nearby. This is useful when decimation is employed, as it can increase the quality of the initial quad estimate substantially. Generally recommended to be on (1). Very computationally inexpensive. Option is ignored if quad_decimate = 1 |
decode_sharpening | 0.25 | How much sharpening should be done to decoded images? This can help decode small tags but may or may not help in odd lighting conditions or low light conditions |
debug | 0 | If 1, will save debug images. Runs very slow |
提取位姿信息。需要提供相机的内参数,包括[fx, fy, cx, cy]
,相机标定可以通过matlab或者opencv来做(出门左转百度即可),注意设置estimate_tag_pose=True
。
If you als