Bootstrap

Canmv K210开发板案例——口罩检测

学习目标:

  • 在Canmv IDE环境下使用K210学习人脸检测功能,将摄像头采集的画面分析比对模型,如果在摄像头区域有人脸则画矩形框出来并检测人脸是否戴口罩并且打印相关信息

  • 使用口罩检测模型以及yolo2网络算法,通过通用神经网络处理器KPU来进行人脸检测


学习内容:

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

import sensor, image, time, lcd
from maix import KPU


lcd.init()  # 初始化LCD显示屏
sensor.reset()  # 复位并初始化摄像头
sensor.set_pixformat(sensor.RGB565)  # 设置摄像头输出格式为 RGB565
sensor.set_framesize(sensor.QVGA) # 设置摄像头输出大小为 QVGA (320x240)
sensor.skip_frames(time = 1000) # 等待摄像头稳定
clock = time.clock() # 创建一个clock对象,用来计算帧率

2、初始化KPU相关的参数,加载口罩检测模型以及使用yolo2网络算法,kpu需要加载kmodel文件

od_img = image.Image(size=(320,256), copy_to_fb=False) # 人脸检测模型需要320*256图输入,这里初始化一个image

# 口罩检测锚点;锚点参数与模型参数一致,同一个模型这个参数是固定的(即训练模型时确定了)
anchor = (0.156250, 0.222548, 0.361328, 0.489583, 0.781250, 0.983133, 1.621094, 1.964286, 3.574219, 3.94000)
kpu = KPU() #创建一个KPU类,用于口罩检测
print("ready load model")
kpu.load_kmodel("/sd/KPU/face_mask_detect/detect_5.kmodel") # 从文件系统中加载口罩检测模型
# 为yolo2网络模型传入初始化参数, 只有使用yolo2时使用;锚点参数,anchor的锚点数,输入图像的宽,输入图像的高,模型需要的图的宽,模型需要的图的高,模型层宽,模型层高,概率阈值,box_iou门限,要分辨的目标类数量
kpu.init_yolo2(anchor, anchor_num=5, img_w=320, img_h=240, net_w=320 , net_h=256 ,layer_w=10 ,layer_h=8, threshold=0.7, nms_value=0.4, classes=2)


3、使用while循环将图像传入KPU循环进行计算,使用yolo2神经网络算法解算,最终得到人脸的位置信息。画矩形框将人脸框出来,获取人脸是否有戴口罩,绘制标签表示出来口罩存在状态

while True:
    clock.tick() # 更新计算帧率的clock
    img = sensor.snapshot() # 拍照,获取一张图像
    od_img.draw_image(img, 0,0) # 将img图像写到od_img图像的坐标(0,0)位置处
    od_img.pix_to_ai() # 对rgb565的image生成ai运算需要的r8g8b8格式存储
    kpu.run_with_output(od_img) # 对输入图像进行kpu运算
    dect = kpu.regionlayer_yolo2() # yolo2后处理
    fps = clock.fps()  # 获取帧率
    if len(dect) > 0:
        print("dect:", dect)
        for l in dect :
            if l[4] :
                # 在图像上绘制一个矩形。 传递l[0],l[1],l[2],l[3]
                img.draw_rectangle(l[0],l[1],l[2],l[3], color=(0, 255, 0))
                img.draw_string(l[0],l[1]-24, "with mask", color=(0, 255, 0), scale=2) #  绘制标签类别
            else:
                img.draw_rectangle(l[0],l[1],l[2],l[3], color=(255, 0, 0))
                img.draw_string(l[0],l[1]-24, "without mask", color=(255, 0, 0), scale=2)

    img.draw_string(0, 0, "%2.1ffps" %(fps), color=(0, 60, 128), scale=2.0) # 显示屏显示FPS
    lcd.display(img)

# 创建的kpu对象去初始化,释放模型内存
kpu.deinit()


实验分析:

With Mask:

Performing Mask Detection:

在这里插入图片描述

Serial Terminal Printing:

在这里插入图片描述


Without Mask:

Performing Mask Detection:

在这里插入图片描述

Serial Terminal Printing:

在这里插入图片描述


实验结果:

等待摄像头稳定,在画面中检测到人脸时,就会画矩形框住。检测到人脸戴着口罩时显示绿色矩形框以及“with mask”,检测到人脸没有戴着口罩时显示红色矩形框以及“without mask”,可以实时检测多个人脸,并在串行终端打印出人脸的数据包括:人脸目标框的左上角x,y坐标人脸框的宽w高h类别序号:1,0代表有无戴口罩概率值([0, 1])


实验过程与总结:

实验过程:

  • 在Canmv IDE中进行面部识别实验,首先配置开发环境,引入必要的库和模块。接着初始化摄像头和显示屏。将面部识别的kmodel文件加载到KPU中。然后进入一个循环,实时从摄像头捕获图像,利用KPU执行yolo2算法进行分析。检测面部并判断出是否佩戴口罩,在LCD屏幕上绘制相应的边界框,并显示口罩佩戴状态的标签。输出面部的坐标信息和分类标签,实现实时动态的口罩检测功能

总结:

  • 实验成功在K210板上实现人脸检测,利用yolo2模型实时识别并检测面部有无戴口罩,系统能够准确检测面部并判断口罩佩戴情况,实时在LCD上显示边界框和状态标签,输出坐标信息,实现了动态口罩检测功能。证明了KPU的神经网络推理能力,并展示了嵌入式设备上执行复杂机器学习任务的潜力。此处检测人脸的阈值:threshold=0.7,如果需要检测人脸更加准确,可以适当调整阈值

完整代码展示:

# Face_mask_detect - By: Jack - 周日 4月 21 2024

import sensor, image, time, lcd
from maix import KPU


lcd.init()  # 初始化LCD显示屏
sensor.reset()  # 复位并初始化摄像头
sensor.set_pixformat(sensor.RGB565)  # 设置摄像头输出格式为 RGB565
sensor.set_framesize(sensor.QVGA) # 设置摄像头输出大小为 QVGA (320x240)
sensor.skip_frames(time = 1000) # 等待摄像头稳定
clock = time.clock() # 创建一个clock对象,用来计算帧率

od_img = image.Image(size=(320,256), copy_to_fb=False) # 人脸检测模型需要320*256图输入,这里初始化一个image

# 口罩检测锚点;锚点参数与模型参数一致,同一个模型这个参数是固定的(即训练模型时确定了)
anchor = (0.156250, 0.222548, 0.361328, 0.489583, 0.781250, 0.983133, 1.621094, 1.964286, 3.574219, 3.94000)
kpu = KPU() #创建一个KPU类,用于口罩检测
print("ready load model")
kpu.load_kmodel("/sd/KPU/face_mask_detect/detect_5.kmodel") # 从文件系统中加载人脸检测模型
# 为yolo2网络模型传入初始化参数, 只有使用yolo2时使用;锚点参数,anchor的锚点数,输入图像的宽,输入图像的高,模型需要的图的宽,模型需要的图的高,模型层宽,模型层高,概率阈值,box_iou门限,要分辨的目标类数量
kpu.init_yolo2(anchor, anchor_num=5, img_w=320, img_h=240, net_w=320 , net_h=256 ,layer_w=10 ,layer_h=8, threshold=0.7, nms_value=0.4, classes=2)

while True:
    clock.tick() # 更新计算帧率的clock
    img = sensor.snapshot() # 拍照,获取一张图像
    od_img.draw_image(img, 0,0) # 将img图像写到od_img图像的坐标(0,0)位置处
    od_img.pix_to_ai() # 对rgb565的image生成ai运算需要的r8g8b8格式存储
    kpu.run_with_output(od_img) # 对输入图像进行kpu运算
    dect = kpu.regionlayer_yolo2() # yolo2后处理
    fps = clock.fps()  # 获取帧率
    if len(dect) > 0:
        print("dect:", dect)
        for l in dect :
            if l[4] :
                # 在图像上绘制一个矩形。 传递l[0],l[1],l[2],l[3]
                img.draw_rectangle(l[0],l[1],l[2],l[3], color=(0, 255, 0))
                img.draw_string(l[0],l[1]-24, "with mask", color=(0, 255, 0), scale=2) #  绘制标签类别
            else:
                img.draw_rectangle(l[0],l[1],l[2],l[3], color=(255, 0, 0))
                img.draw_string(l[0],l[1]-24, "without mask", color=(255, 0, 0), scale=2)

    img.draw_string(0, 0, "%2.1ffps" %(fps), color=(0, 60, 128), scale=2.0) # 显示屏显示FPS
    lcd.display(img)

# 创建的kpu对象去初始化,释放模型内存
kpu.deinit()

悦读

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

;