摘要:本案例将在ModelBox中使用YOLO v3模型,实现一个简单的口罩检测应用

本文分享自华为云社区《ModelBox开发体验Day05开发案例-使用YOLOv3做口罩检测》,作者: 孙小北。

  • 本案例将使用YOLO v3模型,实现一个简单的口罩检测应用
  • 代码:https://github.com/sunxiaobei/modelbox_gallery
  • 代码tag:v1.5 mask_det_yolo3,v1.5.1 mask_det_yolo3_camera

开发准备

  • 开发环境安装和部署,前面环境已完成
  • 模型训练,ModelArts训练模型
  • 模型转换,代码模型已完成转换

应用开发

打开VS Code,连接到ModelBox sdk所在目录或者远程开发板,开始进行口罩检测应用开发。

(1)创建工程

使用create.py创建mask_det_yolo3工程, 将会创建出一个空的ModelBox样例工程。

./create.py -t server -n mask_det_yolo3
git add .
git commit -m 'create mask_det_yolo3'

(2)创建推理功能单元

AI应用的核心是模型推理部分,我们用如下命令创建推理功能单元,该模块将会创建在工程目录的model文件夹下:

./create.py -t infer -n mask_infer -p mask_det_yolo3
git add .
git commit -m 'create mask_infer'

将资源包中model/mask_infer文件夹中的模型和配置文件拷贝到口罩检测工程的model/mask_infer目录下。其中yolo3_resnet18_mask_det_288x512-rknpu2.rknn是转换好的rknn模型,mask_infer.toml是该模型的ModelBox功能单元配置文件,其内容如下:

# Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved.
[base]
name = "mask_infer"
device = "rknpu"
version = "1.0.0"
description = "your description"
entry = "./yolo3_resnet18_mask_det_288x512-rknpu2.rknn" # model file path, use relative path
type = "inference"
virtual_type = "rknpu2" # inference engine type: rockchip now support rknpu, rknpu2(if exist)
group_type = "Inference" # flowunit group attribution, do not change
is_input_contiguous = "false" # rk do not support memory combine, fix, do not change
[input]
[input.input1]
name = "data"
type = "uint8"
device = "rknpu"
[output]
[output.output1]
name = "yolo/output1"
type = "float"
[output.output2]
name = "yolo/output2"
type = "float"
[output.output3]
name = "yolo/output3"
type = "float"

可以看到该模型有3个输出节点,即YOLO v3模型输出的3个feature map,需要从中解码出检测框。

(3)创建后处理功能单元

后处理功能单元负责从模型推理结果中解码出检测框,我们用如下命令创建该功能单元,其将会创建在工程目录的etc/flowunit文件夹下:

./create.py -t python -n yolo3_post -p mask_det_yolo3

将common资源包中etc/flowunit/yolo3_post文件夹中的代码和配置文件拷贝到口罩检测工程的同名目录下,解码过程的核心逻辑在yolo3_utils.py文件中,可以查阅YOLO v3模型细节阅读代码。

(4)创建画图功能单元

得到检测框后可以画在原图上进行输出展示,我们用如下命令创建画图功能单元:

./create.py -t python -n draw_mask_bbox -p mask_det_yolo3

将common资源包中etc/flowunit/draw_mask_bbox文件夹中的代码和配置文件拷贝到口罩检测工程的同名目录下,画图的核心逻辑在draw_mask_bbox.py文件的draw_mask_info函数中:

def draw_mask_info(self, image, bboxes):
'''在图中画出口罩佩戴信息'''
thickness = 2
font_scale = 1
text_font = cv2.FONT_HERSHEY_SIMPLEX
for bbox in bboxes:
label_index = int(bbox[5])
if self.labels[label_index] != 'head':
continue
x_min, y_min, x_max, y_max = bbox[0], bbox[1], bbox[2], bbox[3]
face_bbox = self.find_max_cover_bbox(
bbox, bboxes, 'face', self.face_cover_ratio)
if not face_bbox:
cv2.rectangle(image, (x_min, y_min),
(x_max, y_max), (255, 255, 0), thickness)
cv2.putText(image, 'unknown', (x_min, y_min-20),
text_font, font_scale, (255, 255, 0), thickness)
continue
mask_bbox = self.find_max_cover_bbox(
face_bbox, bboxes, 'mask', self.mask_cover_ratio)
if not mask_bbox:
cv2.putText(image, 'no mask', (x_min, y_min-20),
text_font, font_scale, (255, 0, 0), thickness)
cv2.rectangle(image, (x_min, y_min),
(x_max, y_max), (255, 0, 0), thickness)
else:
cv2.putText(image, 'has mask', (x_min, y_min-20),
text_font, font_scale, (0, 255, 0), thickness)
cv2.rectangle(image, (x_min, y_min),
(x_max, y_max), (0, 255, 0), thickness)
cv2.rectangle(image, (mask_bbox[0], mask_bbox[1]),
(mask_bbox[2], mask_bbox[3]), (0, 255, 255), thickness)
return image

针对每个人,该模型会尝试检测出head(头肩部)、face和mask三个检测框。如果face检测框与mask检测框的重合度大于某个阈值,就判为佩戴口罩;否则,就判为没有佩戴口罩;如果没有检测到face检测框,就会显示Unknown,表示未知。

(5)修改流程图

模型推理和配套的功能单元准备好后,我们就可以串联出流程图进行测试了,口罩检测工程默认在graph目录下生成了mask_det_yolo3.toml,我们参考资源包中的graph/mask_det_yolo3.toml将其修改为:

# Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved.
[driver]
dir = ["${HILENS_APP_ROOT}/etc/flowunit",
"${HILENS_APP_ROOT}/etc/flowunit/cpp",
"${HILENS_APP_ROOT}/model",
"${HILENS_MB_SDK_PATH}/flowunit"]
skip-default = true
[profile]
profile=false
trace=false
dir=""
[graph]
format = "graphviz"
graphconf = """digraph mask_det_yolo3 {
node [shape=Mrecord];
queue_size = 4
batch_size = 1
input1[type=input,flowunit=input,device=cpu,deviceid=0]
data_source_parser[type=flowunit, flowunit=data_source_parser, device=cpu, deviceid=0]
video_demuxer[type=flowunit, flowunit=video_demuxer, device=cpu, deviceid=0]
video_decoder[type=flowunit, flowunit=video_decoder, device=rknpu, deviceid=0, pix_fmt=bgr]
image_resize[type=flowunit, flowunit=resize, device=rknpu, deviceid=0, width=512, height=288]
mask_detection[type=flowunit, flowunit=mask_infer, device=rknpu, deviceid=0]
yolo3_post[type=flowunit, flowunit=yolo3_post, device=cpu, deviceid=0]
draw_mask_bbox[type=flowunit, flowunit=draw_mask_bbox, device=cpu, deviceid=0]
video_out[type=flowunit, flowunit=video_out, device=rknpu, deviceid=0]
input1:input -> data_source_parser:in_data
data_source_parser:out_video_url -> video_demuxer:in_video_url
video_demuxer:out_video_packet -> video_decoder:in_video_packet
video_decoder:out_video_frame -> image_resize:in_image
image_resize:out_image -> mask_detection:data
mask_detection:"yolo/output1" -> yolo3_post:in_feat1
mask_detection:"yolo/output2" -> yolo3_post:in_feat2
mask_detection:"yolo/output3" -> yolo3_post:in_feat3
video_decoder:out_video_frame -> draw_mask_bbox:in_image
yolo3_post:out_data -> draw_mask_bbox:in_bbox
draw_mask_bbox:out_image -> video_out:in_video_frame
}"""
[flow]
desc = "mask_det_yolo3 run in modelbox-rk-aarch64"

该流程图对于某个视频流,经过视频解码、图像缩放、口罩检测推理、检测框后处理、画图等一系列操作后,将结果保存下来。

然后,参考common资源包中mock_task.toml,将口罩检测工程的任务配置文件bin/mock_task.toml中输入输出部分修改为:

# 任务输入,mock模拟目前仅支持一路rtsp或者本地url
# rtsp摄像头,type = "rtsp", url里面写入rtsp地址
# 其它用"url",比如可以是本地文件地址, 或者httpserver的地址,(摄像头 url = "0")
[input]
type = "url"
url = "../data/mask_test.mp4"
# 任务输出,目前仅支持"webhook", 和本地输出"local"(输出到屏幕,url="0", 输出到rtsp,填写rtsp地址)
# (local 还可以输出到本地文件,这个时候注意,文件可以是相对路径,是相对这个mock_task.toml文件本身)
[output]
type = "local"
url = "../hilens_data_dir/mask_test_result.mp4"

将common资源包中的data/mask_test.mp4测试视频拷贝到口罩检测工程的data目录下,该流程图使用这一视频进行口罩检测,检测结果绘制后保存为hilens_data_dir/mask_test_result.mp4文件。

(6)运行应用

在mask_det_yolo3工程路径下执行build_project.sh进行工程构建:

cd workspace/mask_det_yolo3
./build_project.sh

执行bin/main.sh运行应用(如果运行报错请切换到root账号再运行,本应用需要事先使用pip安装好OpenCV和NumPy),运行结束后在hilens_data_dir目录下生成了mask_test_result.mp4文件,可以下载到PC端查看。

bin/main.sh
git add .
git commit -m 'run mask_det_yolo3'
git push
git tag -a v1.5 -m 'mask_det_yolo3'
git push origin --tags

(7)实时摄像头

# 用于本地mock文件读取任务,脚本中已经配置了IVA_SVC_CONFIG环境变量, 添加了此文件路径
########### 请确定使用linux的路径类型,比如在windows上要用 D:/xxx/xxx 不能用D:\xxx\xxx ###########
# 任务的参数为一个压缩并转义后的json字符串
# 直接写需要转义双引号, 也可以用 content_file 添加一个json文件,如果content和content_file都存在content会被覆盖
# content_file支持绝对路径或者相对路径,不支持解析环境变量(包括${HILENS_APP_ROOT}、${HILENS_DATA_DIR}等)
[common]
content = "{\"param_str\":\"string param\",\"param_int\":10,\"param_float\":10.5}"
# 任务输入,mock模拟目前仅支持一路rtsp或者本地url
# rtsp摄像头,type = "rtsp", url里面写入rtsp地址
# 其它用"url",比如可以是本地文件地址, 或者httpserver的地址,(摄像头 url = "0")
[input]
type = "url"
# url = "../data/mask_test.mp4"
url = "0"
# 任务输出,目前仅支持"webhook", 和本地输出"local"(输出到屏幕,url="0", 输出到rtsp,填写rtsp地址)
# (local 还可以输出到本地文件,这个时候注意,文件可以是相对路径,是相对这个mock_task.toml文件本身)
[output]
type = "local"
# url = "../hilens_data_dir/mask_test_result.mp4"
url = "rtsp://192.168.3.3:8554/outstream"

运行测试

bin/main.sh camera

小结

本次案例实践口罩识别,通过本次案例的实践对于开发板的使用有了进一步了解,同时也体会到了这个开发板的便捷开发模式,非常值得推荐,希望后续可以体验更多案例,真正落地实践。

参考文献:

点击关注,第一时间了解华为云新鲜技术~

ModelBox开发体验:使用YOLOv3做口罩检测的更多相关文章

  1. 使用新一代js模板引擎NornJ提升React.js开发体验

    当前的前端世界中有很多著名的开源javascript模板引擎如Handlebars.Nunjucks.EJS等等,相信很多人对它们都并不陌生. js模板引擎的现状 通常来讲,这些js模板引擎项目都有一 ...

  2. dotnet core开发体验之开始MVC

    开始 在上一篇文章:dotnet core多平台开发体验 ,体验了一把dotnet core 之后,现在想对之前做的例子进行改造,想看看加上mvc框架是一种什么样的体验,于是我就要开始诞生今天的这篇文 ...

  3. NET Core全新的开发体验

    NET Core全新的开发体验 2016年6月27日,这是一个特殊的日子,微软全新的.NET开发平台.NET Core的RTM版本正式发布.我个人将.NET Core的核心特性归结为三点,它们的首字母 ...

  4. .NET Core多平台开发体验[1]: Windows

    微软在千禧年推出 .NET战略,并在两年后推出第一个版本的.NET Framework和IDE(Visual Studio.NET 2002,后来改名为Visual Studio),如果你是一个资深的 ...

  5. .NET Core多平台开发体验[2]: Mac OS X

    除了微软自家的Windows平台, .NET Core针对Mac OS以及各种Linux(RHEL.Ubuntu.Debian.Fedora.CentOS和SUSE等)都提供了很好的支持,我们先来体验 ...

  6. Microsoft Graph Web应用程序极致开发体验

    作者:陈希章 重写于 2017年5月24日 前言 这篇文章最早写于2017年5月2日,当时的想法是从最简单的方式来写如何在一个ASP.NET MVC应用程序中集成Microsoft Graph,但实际 ...

  7. .NET Core多平台开发体验[3]: Linux (Windows Linux子系统)

    如果想体验Linux环境下开发和运行.NET Core应用,我们有多种选择.一种就是在一台物理机上安装原生的Linux,我们可以根据自身的喜好选择某种Linux Distribution,目前来说像R ...

  8. (转)如何用TensorLayer做目标检测的数据增强

    数据增强在机器学习中的作用不言而喻.和图片分类的数据增强不同,训练目标检测模型的数据增强在对图像做处理时,还需要对图片中每个目标的坐标做相应的处理.此外,位移.裁剪等操作还有可能使得一些目标在处理后只 ...

  9. 从YOLOv1到YOLOv3,目标检测的进化之路

    https://blog.csdn.net/guleileo/article/details/80581858 本文来自 CSDN 网站,作者 EasonApp. 作者专栏: http://dwz.c ...

随机推荐

  1. Redis - 持久化 AOF 和 RDB

    Redis - 持久化 AOF 和 RDB AOF AOF 持久化记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集. AOF 文件中的命令全部以 Redis 协议的格 ...

  2. Java - ConcurrentHashMap的原理

    Java - ConcurrentHashMap的原理 **这是JDK1.7的实现** ConcurrentHashMap 类中包含两个静态内部类 HashEntry 和 Segment. HashE ...

  3. 1. Docker的中央仓库安装设置及镜像的操作

    具体也可参考:https://developer.aliyun.com/mirror/docker-ce?spm=a2c6h.13651102.0.0.3e221b11G7cfhr https://d ...

  4. .NET C#基础(7):接口 - 人如何和猫互动

    0. 文章目的   面向有一定基础的C#初学者,介绍C#中接口的意义.使用以及特点. 1. 阅读基础   了解C#基本语法(如定义一个类.继承一个类)   理解OOP中的基本概念(如继承,多态) 2. ...

  5. 【SpringBoot】YAML 配置文件

    博客主页:准Java全栈开发工程师 00年出生,即将进入职场闯荡,目标赚钱,可能会有人觉得我格局小.觉得俗,但不得不承认这个世界已经不再是以一条线来分割的平面,而是围绕财富旋转的球面,成为有钱人不是为 ...

  6. ansible变量引用

    1. 在/etc/ansible/hosts默认文件中定义变量 [test] 192.168.163.130 #[test:vars] #key=ansible 或者 192.168.163.130 ...

  7. Java:如何打印整个字符串数组?

    例: public static void main(String[] args) { String prodName = "雇员姓名,雇员唯一号"; String[] prodN ...

  8. 记一次 .NET 差旅管理后台 CPU 爆高分析

    一:背景 1. 讲故事 前段时间有位朋友在微信上找到我,说他的 web 系统 cpu 运行一段时候后就爆高了,让我帮忙看一下是怎么回事,那就看吧,声明一下,我看 dump 是免费的,主要是锤炼自己技术 ...

  9. NC19115 选择颜色

    NC19115 选择颜色 题目 题目描述 \(n\) 个人排成一个环形,每个人要从 \(c\) 种颜色中选择一个. 牛牛希望相邻的人选择的颜色是不同的 问有多少种方案. 输出方案数对 \(10007\ ...

  10. Python 用configparser读写ini文件

    一.configparser 简介Python用于读写ini文件的一个官方标准库.具体详见官网链接 二.configparser 部分方法介绍 方法 描述 read(filenames) filesn ...