Bootstrap

Canmv K210开发板案例——AprilTag机器码识别

学习目标:

在Canmv IDE环境下使用K210学习机器码识别功能,根据识别到的机器码,将机器码位置标记并框出来,打印机器码类别、序列号以及角度等相关数据

机器码:AprilTag

  • AprilTag是一个由密歇根大学APRIL Robotics Laboratory开发的视觉基准系统,广泛应用于增强现实(AR)、机器人导航、相机校正等领域。它通过识别特定的二维码标志来确定相机相对于标志的位姿,即使在远距离、低分辨率、不均匀照明或图像扭曲等不利条件下也能实现精确定位
  • AprilTag是一种视觉基准系统,专为机器人导航、增强现实和相机校准等应用设计。AprilTag支持多标签检测,可快速计算标签的三维位置和相机的相对姿态。它AprilTag的设计专注于编码简单的数字ID,而不是像二维码那样存储复杂的文本或数据信息,这使得AprilTag在有效载荷上更为精简。这种简化的编码方式有助于提高其在各种视觉干扰下的识别可靠性
  • 与二维码相比,AprilTag具有更强的环境适应性和图像识别鲁棒性。它们能够在更远的距离和更不理想的光照条件下被成功检测,包括在图像扭曲或失真的情况下,AprilTag的开源性质和跨平台兼容性使其在研究和工业领域得到广泛应用

学习内容:

1、导入相关库,并初始化摄像头和LCD显示屏

# Find_apriltags - By: Jack - 周四 4月 18 2024

import sensor, image, time, math, lcd

lcd.init()
sensor.reset()
sensor.set_pixformat(sensor.RGB565) #设置为彩色显示
#sensor.set_framesize(sensor.QQVGA)#160x120
sensor.set_framesize(sensor.QQCIF)  # 如果分辨率太高,内存可能会溢出,此处选择最小分辨率可以换取较高的FPS
sensor.set_windowing((64, 64))    #边长必须为8的倍数
sensor.skip_frames(time = 1000)  # 在更改设置后,跳过一些帧,等待感光元件变稳定
sensor.set_auto_gain(False)   # 关闭图像增益,以防止图像冲洗
sensor.set_auto_whitebal(False)  # 关闭图像白平衡,以防止图像冲洗
clock = time.clock()

2、设置要识别的机器码家族成员

# 注释可以禁用族、TAG36H11为默认族
tag_families = 0
tag_families |= image.TAG16H5
tag_families |= image.TAG25H7
tag_families |= image.TAG25H9
tag_families |= image.TAG36H10
tag_families |= image.TAG36H11
tag_families |= image.ARTOOLKIT

3、创建函数将家族名转化成字符串

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"

4、使用while循环识别摄像头画面中的颜色,调用find_apriltags函数查找图像中的机器码,找到之后框出来并且打印相关信息

while(True):
    clock.tick()
    img = sensor.snapshot()

    #find_apriltags()显示的图像<64,000像素点
    #设置图像的大小
    #sensor.QQVGA: 160x120            sensor.QQVGA2: 128x160 (用于 lcd 扩展板)
    #sensor.HQVGA: 240x160            sensor.QVGA: 320x240
    #sensor.VGA: 640x480 (只用于OpenMV Cam M7 的灰度图处理图像,或者彩图采集图像)
    #sensor.QQCIF: 88x72              sensor.QCIF: 176x144
    #sensor.CIF: 352x288

    for tag in img.find_apriltags(families=tag_families):  # 遍历识别机器码家族
        img.draw_rectangle(tag.rect(), color = (255, 0, 0))  # 在tag.rect()获取到的ROI区域(坐标)上绘制一个矩形
        img.draw_cross(tag.cx(), tag.cy(), color = (0, 255, 0))  # ROI中心画十字
        print_args = (family_name(tag), tag.id(), (180 * tag.rotation()) / math.pi)
        print("Tag Family %s, Tag ID %d, rotation %f (degrees)" % print_args)  # 打印出获取到的机器码接码内容
    lcd.display(img)
    print(clock.fps()) # 打印帧率

如何获取机器码:

在Canmv IID软件中:工具栏--->机器视觉--->AprilTag生成器--->下载各家族的标签码

在这里插入图片描述
在这里插入图片描述


实验分析:

实时检测结果

在这里插入图片描述

实时识别出AprilTag机器码,获取机器码的的家族、标签数字信息、检测时机器码与摄像头的角度(摄像头顺时针方向为正)、FPS等数据


实验过程与总结:

实验过程:

  • 实验首先导入了必要的库以便于二维码识别。接着并配置了LCD显示屏以实时展示摄像头捕获的图像。设置要识别的机器码家族成员,接着创建函数将家族名转化成字符串,最后通过编写一个循环不断从摄像头读取图像数据,然后使用find_apriltags函数检测图像中的AprilTag机器码。
  • 一旦检测到二维码,使用draw_rectangle函数在LCD显示屏上绘制矩形框、使用draw_cross函数在ROI中心绘制十字以标记二维码的位置,并通过终端打印出解码后的二维码机器码信息

总结:

  • 在实验中做了对比实验(参考前面案例),灰度/彩色图像显示显示窗口大小来提升FPS,实验结论如下:

    1 、find_apriltags()函数要求显示的图像<64,000像素点、像素边长为8的倍数

    2、控制变量使用HQVGA、QQVGA、QQCIF三种分辨率将机器码铺满窗口分别获得的FPS平均值为4、 7、12,我们可以确定在一定范围内减少分辨率可以增大检测速度

    3、转换为灰度图像可以略微提升少量FPS,但是会丢失彩色信息(例如彩色框、中心十字标记等)

完整代码展示:

# Find_apriltags - By: Jack - 周四 4月 18 2024

import sensor, image, time, math, lcd

lcd.init()
sensor.reset()
sensor.set_pixformat(sensor.RGB565) #设置为彩色显示
#sensor.set_framesize(sensor.QQVGA)#160x120
sensor.set_framesize(sensor.QQCIF)  # 如果分辨率太高,内存可能会溢出,此处选择最小分辨率可以换取较高的FPS
sensor.set_windowing((64, 64))    #边长必须为8的倍数
sensor.skip_frames(time = 1000)  # 在更改设置后,跳过一些帧,等待感光元件变稳定
sensor.set_auto_gain(False)   # 关闭图像增益,以防止图像冲洗
sensor.set_auto_whitebal(False)  # 关闭图像白平衡,以防止图像冲洗
clock = time.clock()

# 注释可以禁用族、TAG36H11为默认族
tag_families = 0
tag_families |= image.TAG16H5
tag_families |= image.TAG25H7
tag_families |= image.TAG25H9
tag_families |= image.TAG36H10
tag_families |= image.TAG36H11
tag_families |= image.ARTOOLKIT


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()

    #find_apriltags()显示的图像<64,000像素点
    #设置图像的大小
    #sensor.QQVGA: 160x120            sensor.QQVGA2: 128x160 (用于 lcd 扩展板)
    #sensor.HQVGA: 240x160            sensor.QVGA: 320x240
    #sensor.VGA: 640x480 (只用于OpenMV Cam M7 的灰度图处理图像,或者彩图采集图像)
    #sensor.QQCIF: 88x72              sensor.QCIF: 176x144
    #sensor.CIF: 352x288

    for tag in img.find_apriltags(families=tag_families):  # 遍历识别机器码家族
        img.draw_rectangle(tag.rect(), color = (255, 0, 0))  # 在tag.rect()获取到的ROI区域(坐标)上绘制一个矩形
        img.draw_cross(tag.cx(), tag.cy(), color = (0, 255, 0))  # ROI中心画十字
        print_args = (family_name(tag), tag.id(), (180 * tag.rotation()) / math.pi)
        print("Tag Family %s, Tag ID %d, rotation %f (degrees)" % print_args)  # 打印出获取到的机器码接码内容
    lcd.display(img)
    print(clock.fps()) # 打印帧率

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;