百度飞桨,移动端推理实践

524 阅读9分钟

百度飞桨,移动端推理实践

前言

项目中要引入AI小运动,来增加产品的竞争力,于是调研下目前市场上竞品的方案,发现基本都是使用阿里开源的神经网络引擎MNN (github.com/alibaba/MNN)

通过使用TensorFlow或者PyTorch来训练人体骨骼模型,然后通过MNN来推理,实现在移动端使用。

如果采用这种方法,在公司比较难以实现,目前没有相关的深度学习的同事,对于模型训练过程,所需要的数据,也是难以去获取到。于是只能去查找有什么其他方案。

一 华为人体骨骼检测

在华为开发者文档上发现有人脸人体服务类的相关介绍,点开发现有人体骨骼检测 支持检测人体多部位关键点:头顶、脖子、肩、肘、手腕、髋、膝盖、脚踝等,同时能够返回骨骼关键点的位置数据。根据以上介绍是满足项目需求。

于是根据集成文档,集成完成,以下是华为开源的demo(github.com/huaweicodel…) , 运行效果,看起来更能够满足获取人体骨骼的关键点,虽然华为声明是免费试用,但是不能确保后续是否收费,所以使用起来存在商业收费的问题。

二 百度飞桨

在github上发现了百度飞桨Paddle(github.com/PaddlePaddl… ,生态相比目前国内的其他神经网络框架来说完整很多,开发了一些列的套件,比如 PaddleDetection (github.com/PaddlePaddl…)

该套件有许多训练好的模型可以使用,比如:

特色模型 : PP-TinyPose,支持: 健身、舞蹈等场景精度提升9.1% AP,支持侧身、卧躺、跳跃、高抬腿等非常规动作

场景能力 : PP-Human v2 支持打架、打电话、抽烟、闯入四大行为识别,底层算法性能升级,覆盖行人检测、跟踪、属性三类核心算法能力

根据以上模型,可以实现智能键身,打架识别,来客分析,车辆结构化

跳绳运动

基于关键点检测的健身动作识别和计数,核心方案如下图所示

模型选择

模型选择采用 PaddleDetection推出的轻量级关键点检测算法PP-TinyPose,采用Top-Down的方式,然后采用Lite-HRNet的移动端优化模型确保关键点检测的高精度。

数据收集

数据收集包含人体检测和人体关键点检测两部分,均使用COCO train2017和AI Challenger trainset作为训练集。将两数据集标注含义进行统一,并转换为COCO数据格式后执行训练。数据含义如下图所示

后处理逻辑

得到人体关键点检测结果后,可以结合不同关键点在相同帧的相对关系,或者不同帧下同一关键点的位置变化来进行动作识别和计数。以侧平举为例,当手臂抬起角度接近水平,则认为手臂处于抬起动作;当手臂放下角度接近垂直,则认为手臂处于放下动作;两动作交替完成后认为侧平举动作计数加一。参考代码如下

demo实现

参考该demo(github.com/zhiboniu/po…) 完成对跳绳运动的修改,同时根据该demo 引入项目中。如果对于目前检测的关键点不满足需求,可以根据文档描述:

  1. 训练模型导出为.nb后缀的Paddle-Lite模型
  2. 替换pose_demo_android中models下的nb模型文件
  3. 通过Android Studio编译运行代码,重新生成app

实战演示

环境准备


# 下载PaddleDetection代码
!git clone https://gitee.com/paddlepaddle/PaddleDetection.git

# 若因为网络原因无法正常克隆,可以使用gitee下载代码
!git clone https://gitee.com/paddlepaddle/PaddleDetection.git
!git checkout develop

# 安装相关环境依赖
!pip install --upgrade pip -i https://mirror.baidu.com/pypi/simple
!pip install paddlepaddle-gpu==2.2.2.post101 -f https://www.paddlepaddle.org.cn/whl/linux/mkl/avx/stable.html -i https://mirror.baidu.com/pypi/simple
%cd PaddleDetection
!pip install --upgrade -r requirements.txt -i https://mirror.baidu.com/pypi/simple
!pip install pycocotools

数据准备

# 下载/解压数据集,并整理数据集路径
!wget https://bj.bcebos.com/v1/paddledet/data/keypoint/coco_val_person_mini.tar
%cd PaddleDetection 
!tar -xf coco_val_person_mini.tar -C ./dataset/
!mv ./dataset/coco_val_person_mini/* ./dataset/coco
!cp ./dataset/coco/annotations/aic_coco_train_cocoformat.json ./dataset/
!cp ./dataset/coco/annotations/instances_val2017.json ./dataset/coco/annotations/person_keypoints_val2017.json

模型训练

# 训练PicoDet行人检测模型
!python tools/train.py -c configs/picodet/application/pedestrian_detection/picodet_s_320_lcnet_pedestrian.yml \
        --eval

#训练TinyPose关键点检测模型
!python tools/train.py -c configs/keypoint/tiny_pose/tinypose_128x96.yml

模型评估

当训练完成后,使用下面的命令评估模型的精度。这里使用了我们已经训练好的模型。如希望使用自己训练的模型,请对应将weights=后的值更改为对应模型.pdparams文件的存储路径。

# 行人检测模型
!python tools/eval.py -c configs/picodet/application/pedestrian_detection/picodet_s_320_lcnet_pedestrian.yml \
  -o weights=https://bj.bcebos.com/v1/paddledet/models/keypoint/tinypose_enhance/picodet_s_320_lcnet_pedestrian.pdparams

#关键点检测模型
!python tools/eval.py -c configs/keypoint/tiny_pose/tinypose_128x96.yml \
  -o weights=https://bj.bcebos.com/v1/paddledet/models/keypoint/tinypose_128x96.pdparams

模型导出

分别将行人检测、关键点检测模型导出,这里使用了我们已经训练好的模型。如希望使用自己训练的模型,请对应将weights=后的值更改为对应模型.pdparams文件的存储路径。导出的模型将默认存储在output_inference/路径下

# 导出行人检测模型
!python tools/export_model.py -c configs/picodet/application/pedestrian_detection/picodet_s_320_lcnet_pedestrian.yml \
        -o weights=https://paddledet.bj.bcebos.com/models/picodet_s_320_lcnet_pedestrian.pdparams

# 导出关键点检测模型
!python tools/export_model.py -c configs/keypoint/tiny_pose/tinypose_128x96.yml \
        -o weights=https://bj.bcebos.com/v1/paddledet/models/keypoint/tinypose_128x96.pdparams
        

模型预测

在完成模型导出后,我们使用联合部署预测的方式,对图片进行预测,预测的可视化结果图像默认将存储在output/下。

!python deploy/python/det_keypoint_unite_infer.py --det_model_dir=output_inference/picodet_s_320_lcnet_pedestrian \
        --keypoint_model_dir=output_inference/tinypose_128x96 \
        --image_file=demo/000000570688.jpg --device=GPU --keypoint_threshold=0.35
        
# 可视化预测图片

import cv2
import matplotlib.pyplot as plt
import numpy as np

image = cv2.imread('output/000000570688_vis.jpg')
plt.figure(figsize=(15,10))
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.show()

按照以上步骤可以实现视屏人体骨骼关键点的检查,标记,结果如下

image.png

卷积神经网络 – CNN

一 CNN的基本原理

保留图像特征

图片数字化的传统方式简化一下,就类似下图的过程:

假如有圆形是1,没有圆形是0,那么圆形的位置不同就会产生完全不同的数据表达。但是从视觉的角度来看,图像的内容(本质)并没有发生变化,只是位置发生了变化。

所以当我们移动图像中的物体,用传统的方式的得出来的参数会差异很大!这是不符合图像处理的要求的。

而 CNN 解决了这个问题,他用类似视觉的方式保留了图像的特征,当图像做翻转,旋转或者变换位置时,它也能有效的识别出来是类似的图像。

人类的视觉原理: 从原始信号摄入开始(瞳孔摄入像素 Pixels),接着做初步处理(大脑皮层某些细胞发现边缘和方向),然后抽象(大脑判定,眼前的物体的形状,是圆形的),然后进一步抽象(大脑进一步判定该物体是只气球)

image.png

 

对于不同的物体,人类视觉也是通过这样逐层分级,来进行认知的:

 

image.png

可以看到,在最底层特征基本上是类似的,就是各种边缘,越往上,越能提取出此类物体的一些特征(轮子、眼睛、躯干等),到最上层,不同的高级特征最终组合成相应的图像,从而能够让人类准确的区分不同的物体。

因此很自然的想到:可以不可以模仿人类大脑的这个特点,构造多层的神经网络,较低层的识别初级的图像特征,若干底层特征组成更上一层特征,最终通过多个层级的组合,最终在顶层做出分类,所以CNN 的基本原理如下3个组成:

  1. 卷积层 – 主要作用是保留图片的特征
  2. 池化层 – 主要作用是把数据降维,可以有效的避免过拟合
  3. 全连接层 – 根据不同任务输出我们想要的结果

卷积层负责提取图像中的局部特征;池化层用来大幅降低参数量级(降维);全连接层类似传统神经网络的部分,用来输出想要的结果。

 

卷积——提取特征

卷积层的运算过程如下图,用一个卷积核扫完整张图片:

 

这个过程可以理解为我们使用一个过滤器(卷积核)来过滤图像的各个小区域,从而得到这些小区域的特征值。

在具体应用中,往往有多个卷积核,可以认为,每个卷积核代表了一种图像模式,如果某个图像块与此卷积核卷积出的值大,则认为此图像块十分接近于此卷积核。如果我们设计了6个卷积核,可以理解:我们认为这个图像上有6种底层纹理模式,也就是我们用6中基础模式就能描绘出一副图像。以下就是25种不同的卷积核的示例:

image.png

 

总结:卷积层的通过卷积核的过滤提取出图片中局部的特征,跟上面提到的人类视觉的特征提取类似。

 

池化层(下采样)——数据降维,避免过拟合

池化层简单说就是下采样,他可以大大降低数据的维度。其过程如下:

image.png

上图中,我们可以看到,原始图片是20×20的,我们对其进行下采样,采样窗口为10×10,最终将其下采样成为一个2×2大小的特征图。

总结:池化层相比卷积层可以更有效的降低数据维度,这么做不但可以大大减少运算量,还可以有效的避免过拟合。

全连接层——输出结果

经过卷积层和池化层处理过的数据输入到全连接层,得到最终想要的结果。

经过卷积层和池化层降维过的数据,全连接层才能”跑得动”,不然数据量太大,计算成本高,效率低下。

image.png

 

二. CNN 价值

  1. 能够将大数据量的图片有效的降维成小数据量(并不影响结果)
  2. 能够保留图片的特征,类似人类的视觉原理

 

三. CNN 的实际应用

  1. 图片分类、检索
  2. 目标定位检测
  3. 目标分割
  4. 人脸识别
  5. 骨骼识别

 

课程知识

  1. 神经网络介绍入门视屏集: www.youtube.com/watch?v=mCz…

  2. 线性代数课程 :www.bilibili.com/video/BV1ys…

  3. 深度学习之反向传播算法 : www.bilibili.com/video/BV16x…

  4. 深度学习之梯度下降法: www.bilibili.com/video/BV1Ux…

  5. 深度学习之神经网络的结构: www.bilibili.com/video/BV1bx…

  6. Python语言和Numpy :zhuanlan.zhihu.com/p/20878530?…

  7. CS231n,面向视觉识别的卷积神经网络:github.com/whyscience/…