目录
1. 前言
2.笔尖笔帽检测方法
(1)Top-Down(自上而下)方法
(2)Bottom-Up(自下而上)方法:
3.笔尖笔帽关键点检测模型训练
4.笔尖笔帽关键点检测模型Android部署
(1) 将Pytorch模型转换ONNX模型
(2) 将ONNX模型转换为TNN模型
(3) Android端上部署模型
(4) Android测试效果
(5) 运行APP闪退:dlopen failed: library "libomp.so" not found
5.Android项目源码下载
6.C++实现笔尖笔帽关键点检测
7.特别版:笔尖指尖检测
1. 前言
目前在AI智慧教育领域,有一个比较火热的教育产品,即指尖点读或者笔尖点读功能,其核心算法就是通过深度学习的方法获得笔尖或者指尖的位置,在通过OCR识别文本,最后通过TTS(TextToSpeech)将文本转为语音;其中OCR和TTS算法都已经研究非常成熟了,而指尖或者笔尖检测的方法也有一些开源的项目可以参考实现。本项目将实现笔尖笔帽关键点检测算法,其中使用YOLOv5模型实现手部检测(手握着笔目标检测),使用HRNet,LiteHRNet和Mobilenet-v2模型实现笔尖笔帽关键点检测。项目分为数据标注,模型训练和Android部署等多个章节,本篇是项目《笔尖笔帽检测》系列文章之Android实现笔尖笔帽检测算法;为了方便后续模型工程化和Android平台部署,项目支持高精度HRNet检测模型,轻量化模型LiteHRNet和Mobilenet模型训练和测试,并提供Python/C++/Android多个版本;
更多项目《笔尖笔帽检测》系列文章请参考:
- 笔尖笔帽检测1:笔尖笔帽检测数据集(含下载链接)
- 笔尖笔帽检测2:Pytorch实现笔尖笔帽检测算法(含训练代码和数据集)
- 笔尖笔帽检测3:Android实现笔尖笔帽检测算法(含源码 可是实时检测)
- 笔尖笔帽检测4:C++实现笔尖笔帽检测算法(含源码 可是实时检测)
2.笔尖笔帽检测方法
笔尖笔帽目标较小,如果直接使用目标检测,很难达到像素级别的检测精度;一般建议使用类似于人体关键点检测的方案。目前主流的关键点方法主要两种:一种是Top-Down(自上而下)方法,另外一种是Bottom-Up(自下而上)方法;
(1)Top-Down(自上而下)方法
将手部检测(手握笔的情况)和笔尖笔帽关键点检测分离,在图像上首先进行手部目标检测,定位手部位置;然后crop每一个手部图像,再估计笔尖笔帽关键点;这类方法往往比较慢,但姿态估计准确度较高。目前主流模型主要有CPN,Hourglass,CPM,Alpha Pose,HRNet等。
(2)Bottom-Up(自下而上)方法:
先估计图像中所有笔尖笔帽关键点,然后在通过Grouping的方法组合成一个一个实例;因此这类方法在测试推断的时候往往更快速,准确度稍低。典型就是COCO2016年人体关键点检测冠军Open Pose。
通常来说,Top-Down具有更高的精度,而Bottom-Up具有更快的速度;就目前调研而言,Top-Down的方法研究较多,精度也比Bottom-Up(自下而上)方法高。
本项目采用Top-Down(自上而下)方法,使用YOLOv5模型实现手部检测(手握笔检测),使用HRNet进行笔尖笔帽关键点检测;也可以简单理解为,先使用YOLOv5定位手握笔的区域位置,再使用HRNet进行笔尖笔帽精细化位置定位。
本项目基于开源的HRNet进行改进,关于HRNet项目请参考GitHub
HRNet: https://github.com/leoxiaobin/deep-high-resolution-net.pytorch
3.笔尖笔帽关键点检测模型训练
本项目采用Top-Down(自上而下)方法,使用YOLOv5模型实现手部检测(手笔检测),并基于开源的HRNet进行改进实现笔尖笔帽关键点检测;为了方便后续模型工程化和Android平台部署,项目支持轻量化模型LiteHRNet和Mobilenet模型训练和测试,并提供Python/C++/Android多个版本;轻量化Mobilenet-v2模型在普通Android手机上可以达到实时的检测效果,CPU(4线程)约50ms左右,GPU约30ms左右 ,基本满足业务的性能需求
本篇博文主要分享C++版本的模型部署,不包含Python版本的训练代码和相关数据集,关于笔尖笔帽关键点检测的训练方法和数据集说明,可参考 :
笔尖笔帽检测2:Pytorch实现笔尖笔帽检测算法(含训练代码和数据集)
下表格给出HRNet,以及轻量化模型LiteHRNet和Mobilenet的计算量和参数量,以及其检测精度AP; 高精度检测模型HRNet-w32,AP可以达到0.8418,但其参数量和计算量比较大,不合适在移动端部署;LiteHRNet18和Mobilenet-v2参数量和计算量比较少,合适在移动端部署;虽然LiteHRNet18的理论计算量和参数量比Mobilenet-v2低,但在实际测试中,发现Mobilenet-v2运行速度更快。轻量化Mobilenet-v2模型在普通Android手机上可以达到实时的检测效果,CPU(4线程)约50ms左右,GPU约30ms左右 ,基本满足业务的性能需求
模型 | input-size | params(M) | GFLOPs | AP |
HRNet-w32 | 192×192 | 28.48M | 5734.05M | 0.8418 |
LiteHRNet18 | 192×192 | 1.10M | 182.15M | 0.7469 |
Mobilenet-v2 | 192×192 | 2.63M | 529.25M | 0.7531 |
HRNet-w32参数量和计算量太大,不适合在Android手机部署,本项目Android版本只支持部署LiteHRNet和Mobilenet-v2模型;C++版本可支持部署HRNet-w32,LiteHRNet和Mobilenet-v2模型
4.笔尖笔帽关键点检测模型Android部署
目前CNN模型有多种部署方式,可以采用TNN,MNN,NCNN,以及TensorRT等部署工具,鄙人采用TNN进行Android端上部署。部署流程可分为四步:训练模型->将模型转换ONNX模型->将ONNX模型转换为TNN模型->Android端上部署TNN模型。
(1) 将Pytorch模型转换ONNX模型
训练好Pytorch模型后,我们需要先将模型转换为ONNX模型,以便后续模型部署。
- 原始Python项目提供转换脚本,你只需要修改model_file和config_file为你模型路径即可
- convert_torch_to_onnx.py实现将Pytorch模型转换ONNX模型的脚本
python libs/convert_tools/convert_torch_to_onnx.py
""" This code is used to convert the pytorch model into an onnx format model. """ import os import torch.onnx from pose.inference import PoseEstimation from basetrainer.utils.converter import pytorch2onnx def load_model(config_file, model_file, device="cuda:0"): pose = PoseEstimation(config_file, model_file, device=device) model = pose.model config = pose.config return model, config def convert2onnx(config_file, model_file, device="cuda:0", onnx_type="kp"): """ :param model_file: :param input_size: :param device: :param onnx_type: :return: """ model, config = load_model(config_file, model_file, device=device) model = model.to(device) model.eval() model_name = os.path.basename(model_file)[:-len(".pth")] onnx_file = os.path.join(os.path.dirname(model_file), model_name + ".onnx") # dummy_input = torch.randn(1, 3, 240, 320).to("cuda") input_size = tuple(config.MODEL.IMAGE_SIZE) # w,h input_shape = (1, 3, input_size[1], input_size[0]) pytorch2onnx.convert2onnx(model, input_shape=input_shape, input_names=['input'], output_names=['output'], onnx_file=onnx_file, opset_version=11) if __name__ == "__main__": config_file = "../../work_space/pen/mobilenet_v2_2_192_192_custom_coco_20231114_000651_3262/mobilenetv2_192_192.yaml" model_file = "../../work_space/pen/mobilenet_v2_2_192_192_custom_coco_20231114_000651_3262/model/model_199_0.7518.pth" convert2onnx(config_file, model_file)
(2) 将ONNX模型转换为TNN模型
目前CNN模型有多种部署方式,可以采用TNN,MNN,NCNN,以及TensorRT等部署工具,鄙人采用TNN进行Android端上部署
TNN转换工具:
- (1)将ONNX模型转换为TNN模型,请参考TNN官方说明:TNN/onnx2tnn.md at master · Tencent/TNN · GitHub
- (2)一键转换,懒人必备:一键转换 Caffe, ONNX, TensorFlow 到 NCNN, MNN, Tengine (可能存在版本问题,这个工具转换的TNN模型可能不兼容,建议还是自己build源码进行转换,2022年9约25日测试可用)
5.Android项目源码下载
Android项目源码下载地址:Android实现笔尖笔帽检测算法(含源码 可是实时检测)
整套Android项目源码内容包含:
- Android Demo源码支持YOLOv5手部检测(手握笔检测)
- Android Demo源码支持轻量化模型LiteHRNet和Mobilenet-v2笔尖笔帽关键点检测
- Android Demo在普通手机CPU/GPU上可以实时检测,CPU约50ms,GPU约30ms左右
- Android Demo支持图片,视频,摄像头测试
- 所有依赖库都已经配置好,可直接build运行,若运行出现闪退,请参考dlopen failed: library “libomp.so“ not found解决。
6.C++实现笔尖笔帽关键点检测
- 笔尖笔帽检测4:C++实现笔尖笔帽检测算法(含源码 可是实时检测)
7.特别版:笔尖指尖检测
碍于篇幅,本文章只实现了笔尖笔帽关键点检测;实质上,要实现指尖点读或者笔尖点读功能,我们可能并不需要笔帽检测,而是需要实现笔尖+指尖检测功能;其实现方法与笔尖笔帽关键点检测类似。
下面是成功产品落地应用的笔尖+指尖检测算法Demo,其检测精度和速度性能都比笔尖笔帽检测的效果要好。
如果你需要笔尖+指尖检测算法,可在公众号咨询联系
指尖笔尖Android Demo体检:
指尖笔尖检测Demo01
指尖笔尖检测Demo02