【飞桨AI实战】人脸口罩检测:手把手带你从零搭建一个前后端分离的Flask应用,代码开源

前言

上次分享【飞桨AI实战】交通灯检测:手把手带你入门PaddleDetection,从训练到部署,我们以交通灯检测为案例,带着大家从0到1完成了检测任务的模型训练评估和推理部署全流程,了解了 PaddleDetection 为核心的常用组件的具体使用方法。

在此基础上,本篇将继续带领大家完成一个前后端分离的应用开发,最终实现的效果如下图所示,希望能为有类似项目需求的同学提供一点帮助。

代码地址:https://gitee.com/liuwei16/flask-paddle-demo

项目目标

  • 基于 PaddleDetection 组件完成一个人脸口罩检测任务的模型训练;
  • 基于 ONNX 完成模型转换和推理部署;
  • 基于 Flask 搭建一个前后端分离的项目。

项目实战

1 PaddleDetection完成模型训练

如何完成 PaddleDetection 的安装等环境配置,可跳转到【飞桨AI实战】交通灯检测:手把手带你入门PaddleDetection,从训练到部署查看。

这里主要介绍下我们采用的数据集,以及选用的模型。

1.1 数据集准备

这次我们选用的数据集包含两类图像:未带口罩的和带口罩的人脸图像。在 AI Studio 项目中添加数据集时,搜索 face_mask ,选择第一个即可。

打开项目后,首先需要将数据解压出来,然后划分训练集/验证集。

step1: 解压数据集

cd data
unzip data226320/face_mask.zip

step2: 划分训练集/验证集:我们按照 4:1 划分

python generate_voc_dataset.py
# 其中generate_voc_dataset.py中的代码如下:
import os
import xml.etree.ElementTree as ET

root_dir = '/home/aistudio/data/face_mask'
anno_dir = os.path.join(root_dir, 'Annotations')
image_dir = os.path.join(root_dir, 'JPEGImages')

# get train/valid data
image_files = os.listdir(image_dir)
val_files = image_files[::5]
train_files = [f for f in image_files if f not in val_files]
with open(os.path.join(root_dir, 'train.txt'), 'w') as f:
    for ifile in train_files:
        afile = ifile.replace('.jpg', '.xml')
        f.write(f'JPEGImages/{ifile} Annotations/{afile}\n')
print('train ready')

with open(os.path.join(root_dir, 'val.txt'), 'w') as f:
    for ifile in val_files:
        afile = ifile.replace('.jpg', '.xml')
        f.write(f'JPEGImages/{ifile} Annotations/{afile}\n')
print('valid ready')

step3: 新建数据集配置文件

这里假设您的 PaddleDetection 已经下载到本地

cd PaddleDetection/
# 复制一份数据集的config并进行修改
cp configs/datasets/roadsign_voc.yml configs/datasets/facemask_voc.yml
# 修改其中的文件位置,如下所示:
metric: VOC
map_type: integral
num_classes: 2

TrainDataset:
  name: VOCDataSet
  dataset_dir: /home/aistudio/data/face_mask
  anno_path: train.txt
  label_list: leable.txt
  data_fields: ['image', 'gt_bbox', 'gt_class', 'difficult']

EvalDataset:
  name: VOCDataSet
  dataset_dir: /home/aistudio/data/face_mask
  anno_path: val.txt
  label_list: label_list.txt
  data_fields: ['image', 'gt_bbox', 'gt_class', 'difficult']

TestDataset:
  name: VOCDataSet
  dataset_dir: /home/aistudio/data/face_mask
  anno_path: val.txt
  label_list: label_list.txt

1.2 模型训练

这次我们选用百度自研的 picodet 轻量级模型,同样我们先要复制一份有关模型的配置文件,并进行修改:

cp configs/picodet/picodet_xs_416_coco_lcnet.yml configs/picodet/picodet_xs_416_facemask.yml
# 修改其中的数据集配置为我们刚新建的数据集配置文件:
_BASE_: [
  '../datasets/facemask_voc.yml',
  ...
]
# 由于本次任务比较简单,还可以减少训练的轮数:
epoch: 30
snapshot_epoch: 5

接下来就可以开启训练了:

python tools/train.py -c configs/picodet/picodet_xs_416_facemask.yml --eval

训练成功后,可以在终端查看训练过程,loss下降说明没问题,我这里只训了 15 个 epoch 就可以了,测试发现效果还可以。接下来我们需要将训练得到的最好模型转成部署需要的 inference 格式。

python tools/export_model.py -c configs/picodet/picodet_xs_416_facemask.yml --output_dir=output/inference_model -o weights=output/14

成功后,会在 output/inference_model/picodet_xs_416_facemask/ 下生成 inference 格式的模型文件,如下所示:

output/inference_model/picodet_xs_416_facemask/
|-- infer_cfg.yml
|-- model.pdiparams
|-- model.pdiparams.info
|-- model.pdmodel

2 基于 ONNX 完成模型转换和推理部署

上篇【飞桨AI实战】交通灯检测:手把手带你入门PaddleDetection,从训练到部署我们分享了多种部署方式,这里我们采用 ONNX 来完成模型转换和推理部署。

step1: ONNX模型导出

# 将部署模型转为ONNX格式
pip install paddle2onnx
# cd到inference模型路径
cd output/inference_model/picodet_xs_416_facemask
paddle2onnx --model_dir ./ --model_filename model.pdmodel --params_filename model.pdiparams --opset_version 11 --save_file picoxs.onnx

导出后在当前目录生成 picoxs.onnx 模型文件。

step2: onnxruntime模型推理

pip install onnxruntime
# 执行推理,找张图像测试了看看吧
python deploy/third_engine/onnx/infer.py --infer_cfg output/inference_mode
l/picodet_xs_416_facemask/infer_cfg.yml --onnx_file output/inference_model/picodet_xs_416_facemask/picoxs.onnx --image_file ~/data/face_mask/JPEGImages/test_00001329.jpg

推理结果中的数字分别表示:类别 置信度得分 左上角坐标xy 右下角坐标xy。
onnxruntime推理结果

3 基于 Flask 搭建一个前后端分离的项目

参考示例代码:https://gitee.com/liuwei16/flask-paddle-demo

Flask 是一个非常小的 Python Web 框架,被称为微型框架;为了简单搭建一个应用,你不需要了解 Flask 的所有技术细节,你只需要将任务拆解为:

  • 如何调用 ONNX 模型得到推理结果;
  • 如何搭建一个界面,显示推理结果。

可以先将上面的示例代码git clone到本地,然后安装好依赖项:

pip install requirements.txt

step 1: 实现调用 ONNX 模型的接口

首先将模型文件和配置文件存放在models文件下:

models/
├── infer_cfg.yml
└── picoxs.onnx

然后编写接口函数,这里主要参考了PaddleDetection/deploy/third_engine/onnx/infer.py的具体写法,接口函数的位置在:

backend/
├── __init__.py
├── paddle_inference.py
└── preprocess.py

其中predict函数实现了读取数据的两种方式:一是读取本地图片,而是读取二进制文件,其中前者用于本地测试,后者用于线上调用。编成成功后,可以先在本地测试一下:

if __name__ == "__main__":
    detector = PicoDetector()
    img_path = 'images/test_mask.jpg'
    result = detector.predict(img_path)
    print(result)
    with open(img_path, 'rb') as f:
        img_bin = f.read()
    result = detector.predict(img_bin=img_bin)
    print(result)

step 2: 搭建界面 可视化结果

界面的核心逻辑在根目录的index.html中,其中依赖的 css 和 js 文件分别在cssjs文件夹下,通过python -m http.server就可以起一个 web 服务(默认在8000端口),渲染index.html

为了使得index.html中能够调用预测函数,一种最简单的方式是:基于 flask 写一个接口函数,然后后端通过 ajax 来发送一个请求,取回推理结果,在前端展示就可以了。

基于 flask 实现的接口函数在 app.py中:

detector = PicoDetector()

@app.route('/api/', methods=["POST"])
def main_interface():
    response = request.get_json(force=True)
    data_str = response['image']
    base64_str = re.sub('^data:image/.+;base64,', '', data_str)
    image = base64.b64decode(base64_str)
    results = detector.predict(img_bin=image)
    print(results)
    return jsonify(results)

后端的 ajax 请求代码在js/index.js中:

function communicate(img_base64_url) {
  $.ajax({
    url: URL,
    type: "POST",
    contentType: "application/json",
    data: JSON.stringify({"image": img_base64_url}),
    dataType: "json"
  }).done(function(response_data) {
      drawResult(response_data.results);
  });
}

更多实现细节,可参考代码仓库。

step 3: 服务启动

sh test.sh
# test.sh
python3 app.py & # 启动 flask app 并放到后台运行,准备推理函数的接口
python3 -m http.server # 启动 web 服务,渲染 index.html

如果发现 5000 端口被占用了,可以通过如下命令查看是被哪个进程占用了,然后 kill 掉再重新启动服务:

netstat -ntlp
kill 29403

服务启动成功后,可以发现 web 服务在本地的 8000 端口,而 flask app的服务在 5000 端口,所以我们在本地游览器中输入 localhost:8000 就可以看到文章开头的界面了。

总结

在掌握PaddleDetection完成模型训练和推理部署的基础上,本文带领大家从零开始构建一个人脸口罩检测的前后端分离的Flask应用。首先,我们采用PaddleDetection训练得到了人脸口罩检测模型,然后基于 ONNX 完成了模型推理,最后基于Flask框架搭建了一个前后端分离的Web应用,包括如何实现模型推理的后端接口、如何搭建前端界面,以及启动和运行整个服务。

本系列的后续文章将沿袭这一思路,继续分享更多采用Paddle深度学习框架服务更多产业应用的案例。

  • 12
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值