【正点原子K210连载】第三十三章 人脸口罩佩戴检测实验《DNK210使用指南-SDK版》
第三十三章 人脸口罩佩戴检测实验在上一章节中,介绍了利用KPU模块实现基于YOLO2的人手检测功能,本章将继续介绍利用KPU模块实现人脸口罩佩戴检测功能。通过本章的学习,读者将学习到使用SDK编程技术实现人脸口罩佩戴检测应用。本章分为如下几个小节:33.1 KPU模块介绍33.2 硬件设计33.3 程序设计33.4 运行验证
33.1 KPU模块介绍有关KPU模块的介绍,请见第30.1小节《KPU介绍》。33.2 硬件设计33.2.1 例程功能1. 获取摄像头输出的图像,并送入KPU进行人脸口罩佩戴检测模型运算,后将运算结果和摄像头输出的图像一起显示在LCD上。33.2.2 硬件资源本章实验内容,主要讲解KPU模块的使用,无需关注硬件资源。33.2.3 原理图本章实验内容,主要讲解KPU模块的使用,无需关注原理图。33.3 程序设计33.3.1 main.c代码main.c中的代码如下所示:INCBIN(model, "detect_5.kmodel"); uint8_t *disp;uint8_t *ai;image_t kpu_image,draw_image; static float g_anchor = {0.156250, 0.222548, 0.361328, 0.489583, 0.781250, 0.983133, 1.621094, 1.964286, 3.574219, 3.94000}; /*口罩*/char *classes_lable ={ "without mask", "with mask" }; static volatile uint8_t ai_done_flag; /* KPU运算完成回调 */static void ai_done_callback(void *userdata){ ai_done_flag = 1;} void draw_boxes_callback(uint32_t x1, uint32_t y1, uint32_t x2, uint32_t y2, uint32_t label, float prob){ char datatemp; if (x1 >= 320) { x1 = 319; } if (x2 >= 320) { x2 = 319; } if (y1 >= 240) { y1 = 239; } if (y2 >= 240) { y2 = 239; } draw_box_rgb565_image((uint16_t *)disp, 320, x1, y1, x2, y2, GREEN); sprintf((char *)datatemp,"%2.1ffps", prob * 100); draw_string_rgb565_image((uint16_t *)disp, 320, 240, x1, y1, datatemp, BLUE); draw_string_rgb565_image((uint16_t *)disp, 320, 240, x1, y1 + 16, classes_lable, BLUE); // lcd_draw_string(x1 + 6, y1,classes_lable,0xF800);} int main(void){ kpu_model_context_t task; float *output; size_t output_size; region_layer_t detect_rl; sysctl_pll_set_freq(SYSCTL_PLL0, 800000000); sysctl_pll_set_freq(SYSCTL_PLL1, 400000000); sysctl_pll_set_freq(SYSCTL_PLL2, 45158400); sysctl_clock_enable(SYSCTL_CLOCK_AI); sysctl_set_power_mode(SYSCTL_POWER_BANK6, SYSCTL_POWER_V18); sysctl_set_power_mode(SYSCTL_POWER_BANK7, SYSCTL_POWER_V18); sysctl_set_spi0_dvp_data(1); lcd_init(); lcd_set_direction(DIR_YX_LRUD); camera_init(24000000); camera_set_pixformat(PIXFORMAT_RGB565); camera_set_framesize(320, 240); if (kpu_load_kmodel(&task, (const uint8_t *)model_data) != 0) { printf("Kmodel load failed!\n"); while (1); } detect_rl.anchor_number = ANCHOR_NUM; detect_rl.anchor = g_anchor; detect_rl.threshold = 0.7; detect_rl.nms_value = 0.4; region_layer_init(&detect_rl, 10, 8, 35, 320, 256); kpu_image.pixel = 3; kpu_image.width = 320; kpu_image.height = 240; // image_init(&kpu_image); draw_image.pixel = 3; draw_image.width = 320; draw_image.height = 256; image_init(&draw_image); while (1) { if (camera_snapshot(&disp, &ai) == 0) { kpu_image.addr = ai; image_draw(&kpu_image, &draw_image, 0, 0); ai_done_flag = 0; if (kpu_run_kmodel(&task, (const uint8_t *)draw_image.addr, DMAC_CHANNEL5, ai_done_callback, NULL) != 0) { printf("Kmodel run failed!\n"); while (1); } while (ai_done_flag == 0); if (kpu_get_output(&task, 0, (uint8_t **)&output, &output_size) != 0) { printf("Output get failed!\n"); while (1); } detect_rl.input = output; region_layer_run(&detect_rl, NULL); region_layer_draw_boxes(&detect_rl, draw_boxes_callback); lcd_draw_picture(0, 0, 320, 240, (uint16_t *)disp); camera_snapshot_release(); } }}detect_5.kmodel是人脸口罩佩戴检测的模型,网络运算的图片大小为320*256。可以看到一开始是先初始化了LCD和摄像头,然后加载人脸口罩佩戴检测网络需要用到的网络模型,并初始化YOLO2网络,配置region_layer_t结构体参数的数据。最后在一个循环中不断地获取摄像头输出的图像,图像尺寸为320*240,由于网络需要的图像尺寸与摄像头直接输出的图像尺寸不一致,因此将其复制到网络需要的图像尺寸的图像上,再并将其送入KPU中进行运算,然后再进行YOLO2网络运算,接着将KPU运算的结果传入region_layer相关文件进行解析,最后将检测到的物体信息通过draw_boxes_callback回调函数绘制到LCD显示器上。33.4 运行验证将DNK210开发板连接到电脑主机,通过VSCode将固件烧录到开发板中,将摄像头分别对准正确佩戴口罩和未正确佩戴口罩的图像,让其采集到图像,随后便能在LCD上看到摄像头输出的图像,同时图像中的人脸均被绿色的矩形框框出,并在矩形框内的左上角标出了人脸口罩的佩戴状态,如下图所示: 图33.4.1 LCD显示正确佩戴口罩结果 图33.4.2 LCD显示未正确佩戴口罩结果
页:
[1]