欢迎访问本站,希望站内信息可以帮助到您! 博主个人微信:xituxiaoshutong100

在Android上运行YOLOv5目标检测

YOLO 迷途小书童 0评论

软硬件环境

视频看这里

Youtube

Bilibili

前言

前面几篇文章,我们已经详细介绍过yolov5的检测、训练、可视化等内容,本文继续yolov5的话题,这回我们来看看,如何在android中去使用yolov5来进行目标检测?

yolov5 ncnn android

什么是ncnn

下面这段是官方的定义

ncnn是腾讯公司开源的一个专为手机端极致优化的高性能神经网络前向计算框架。ncnn从设计之初,就深刻考虑手机端的部署和使用,无需第三方依赖,跨平台,手机端cpu的速度快于目前所有已知的开源框架。基于ncnn,开发者能够将深度学习算法轻松移植到手机端高效执行,开发出人工智能APP,将AI带到你的指尖。

目前ncnn已经支持大部分的CNN网络,包括本文中用到的yolov5

  • Classical CNN: VGG AlexNet GoogleNet Inception ...
  • Practical CNN: ResNet DenseNet SENet FPN ...
  • Light-weight CNN: SqueezeNet MobileNetV1/V2/V3 ShuffleNetV1/V2 MNasNet ...
  • Face Detection: MTCNN RetinaFace ...
  • Detection: VGG-SSD MobileNet-SSD SqueezeNet-SSD MobileNetV2-SSDLite MobileNetV3-SSDLite ...
  • Detection: Faster-RCNN R-FCN ...
  • Detection: YOLOV2 YOLOV3 MobileNet-YOLOV3 YOLOV4 YOLOV5 ...
  • Segmentation: FCN PSPNet UNet YOLACT ...
  • Pose Estimation: SimplePose ...

项目实操

关于基础环境部分,这里需要用到android的开发环境,像android studiosdkndk等等,本文不做介绍,有问题的话,可以在留言区中留言。

我们直接拉取yolov5 for android的源码

git clone https://github.com/nihui/ncnn-android-yolov5

然后来到ncnn的版本发布页,下载编译好的包 https://github.com/Tencent/ncnn/releases,如果你有兴趣的话,也可以通过ndk自己去编译

yolov5 ncnn android

下载解压后拷贝到ncnn-android-yolov5项目的app/src/main/jni目录下,目录结构是这样的

yolov5 ncnn android

然后修改同级目录下的CMakeLists.txt,将其中的ncnn_DIR变量值修改成

set(ncnn_DIR ${CMAKE_SOURCE_DIR}/${ANDROID_ABI}/lib/cmake/ncnn)

yolov5 ncnn android

保存后就可以进行项目的编译了。

这里使用真机进行测试,需要自己打开手机的开发者模式,允许USB调试,APP安装后打开,首页是这样的

yolov5 ncnn android

界面布局非常简单,总共就三个按钮,一个选图,一个使用CPU检测,一个使用GPU检测。经过测试发现CPU的速度要比GPU慢上一倍,我的OnePlus 8GPU速度也只有5fps

yolov5 ncnn android

yolov5 ncnn android

如何使用自己的模型

当我们训练了自己的检测模型后,就需要一种中介,通过它,可以实现在不同框架之间进行转换。 Open Neural Network Exchange简称ONNX,意思是开放神经网络交换格式,它就是我们需要的中介。

yolov5的模型训练请参考这篇 https://xugaoxiang.com/2020/07/02/yolov5-training/,作为测试,我们也使用上文中训练出来的口罩检测模型

安装依赖库

pip install onnx coremltools onnx-simplifier

执行命令

python models/export.py --weights runs/exp2/weights/best.pt

yolov5 ncnn android

同时在best.pt的同级目录,还生成了best.onnxbest.mlmodelbest.torchscript.pt

yolov5 ncnn android

这里需要提醒一下大家,上述的导出操作在pytorch1.7yolov5 v4.0版本上会报错,我这里的环境是pytorch1.6yolov5 3.0版本。报错信息如下

Converting op 143 : listconstruct
Adding op '143' of type const
Converting op 144 : listconstruct
Adding op '144' of type const
Converting op 145 : listconstruct
Adding op '145' of type const
Converting op x.2 : _convolution
Converting Frontend ==> MIL Ops:   3%|██                                                           | 21/620 [00:00<00:00, 1350.49 ops/s]
CoreML export failure: unexpected number of inputs for node x.2 (_convolution): 13

Export complete (12.83s). Visualize with https://github.com/lutzroeder/netron.

这是coremltools的一个bug。相关链接请查看 https://github.com/ultralytics/yolov5/issues/1667

接下来使用工具onnx-simplifier来简化onnx,执行命令

python -m onnxsim runs/exp2/weights/best.onnx runs/exp2/weights/best-sim.onnx

yolov5 ncnn android

下面开始编译ncnn,首先准备基础环境

sudo apt install build-essential libopencv-dev cmake

编译安装protobuf依赖库

git clone https://github.com/protocolbuffers/protobuf.git
cd protobuf
git submodule update --init --recursive
./autogen.sh
./configure
make
make install
sudo ldconfig

编译安装好以后,可以查看下protobuf的版本号

yolov5 ncnn android

接下来,需要编译ncnn,目的是生成onnxncnn的命令行工具

git clone https://github.com/Tencent/ncnn.git
cd ncnn
git submodule update --init
mkdir build
cd build
cmake ..
make -j8
make install

编译安装完成后,就可以使用onnx2ncnn工具进行转换了

cd tools/onnx
./onnx2ncnn ~/Works/weights/best-sim.onnx ~/Works/weights/model.param ~/Works/weights/model.bin

oh, no,报错了

yolov5 ncnn android

这是由于slice没有被支持。为了解决这个问题,我们需要编辑生成的param文件,使用文本工具打开即可

yolov5 ncnn android

修改后的param是这样的

yolov5 ncnn android

第二行的第一个数是层数,因为我们删除了8个Crop和1个Concat,所以它的值是201-9=192

另外,需要修改的是Reshape层的输出grid,将对应的值都改成-1,这是为了解决实际中出现的多检测框的问题

可以用netron这个工具打开查看网络结构,windowslinuxmacos上都有,地址 https://github.com/lutzroeder/netron/releases/tag/v4.7.5

yolov5 ncnn android

图片中,我们要删除SplitConcat和8个Crop节点,并且加入新的节点YoloV5Focus,这个节点名称是和android源码中的yolov5ncnn_jni.cpp中的类名匹配的。这里可以将文本编辑器和netron结合起来用,修改完后立刻查看。

yolov5 ncnn android

yolov5 ncnn android

接下来就可以替换原android工程中assets文件夹下的yolov5s.paramyolov5s.bin

yolov5 ncnn android

然后接着修改源码文件yolov5ncnn_jni.cpp,修改2个Permute节点的output

yolov5 ncnn android

yolov5 ncnn android

yolov5 ncnn android

最后,修改class names

yolov5 ncnn android

重新编译工程,连上手机,安装apk并运行

最后的检测效果如下

yolov5 ncnn android

FAQ

这里列出了几个常见问题,供大家参考。

Could not install Gradle distribution from 'https://services.gradle.org/distributions/gradle-5.4.1-all.zip'.

关闭android studio,手动从站点 https://services.gradle.org/distributions/gradle-5.4.1-all.zip 下载压缩包,然后进入文件夹C:\Users\Administrator\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx,将原有的内容全部删除,将下载的压缩包拷贝进来,再次打开android studio,点击右上角的Sync Project with Gradle Files

yolov5 ncnn android

Cause: jcenter.bintray.com:443 failed to respond

这个问题可能跟代理相关,在File --> Settings --> HTTP Proxy,关闭代理

yolov5 ncnn android

或者编辑文件~\.gradle\gradle.properties,将proxy相关的语句注释掉

yolov5 ncnn android

另一个错误,是在编译ncnn的时候,出现tiff相关的错误信息

yolov5 ncnn android

这里主要是anaconda的环境导致,我的做法是完全退出anaconda环境

conda deactivate
unset LD_LIBRARY_PATH

最后一个问题,模型转换经常碰到的错误

yolov5 ncnn android

这个错误是yolov5ncnn_jni.cpp中的output没有和实际模型匹配起来导致的

源码下载

百度网盘链接:https://pan.baidu.com/s/1U4XfNSeMARbe5sJgY69Zxw
提取码:x8oi

参考资料

喜欢 (3)
发表我的评论
取消评论

表情