基于yolov5的Android版本目标检测app开发(部署安卓手机)

0、项目开发需求
(1)开发app部署到安卓手机
(2)支持VOC数据集上所有的目标检测
1、开发环境搭建
windows10+pytorch+pyCharm+Anaconda
python 3.8
torch 1.9.0+cu111
torchvision 0.10.0+cu111
显卡:NVIDIA GeForce RTX 3070

2、数据集准备
(1)下载VOC数据集(链接)
(2)将VOC数据集的格式调整为yolov5的(链接)
yolov5是通过读取.yaml文件进行数据集加载的,.yaml文件内容如下所示
其中原VOC数据集与yolov5数据集文件夹结构对比如图所示:

在需要训练模型的.yaml里修改类别个数:

3、模型训练

(1)需要修改初始参数

"""weights: 权重文件/需要提前下载,后面模型训练在此基础上进行,修改为自己的路径cfg: 模型配置文件 包括nc、depth_multiple、width_multiple、anchors、backbone、head等,修改为自己的路径data: 数据集配置文件 包括path、train、val、test、nc、names、download等,修改为自己的路径hyp: 初始超参文件,修改为自己的路径epochs: 训练轮次batch-size: 训练批次大小(根据自己硬件选择建议(6-32))img-size: 输入网络的图片分辨率大小resume: 断点续训, 从上次打断的训练结果处接着训练  默认Falsenosave: 不保存模型  默认False(保存)      True: only test final epochnotest: 是否只测试最后一轮 默认False  True: 只测试最后一轮   False: 每轮训练完都测试mAPworkers: dataloader中的最大work数(线程个数),根据自己硬件选择device: 训练的设备single-cls: 数据集是否只有一个类别 默认Falserect: 训练集是否采用矩形训练  默认Falsenoautoanchor: 不自动调整anchor 默认False(自动调整anchor)evolve: 是否进行超参进化 默认Falsemulti-scale: 是否使用多尺度训练 默认Falselabel-smoothing: 标签平滑增强 默认0.0不增强  要增强一般就设为0.1adam: 是否使用adam优化器 默认False(使用SGD)sync-bn: 是否使用跨卡同步bn操作,再DDP中使用  默认Falselinear-lr: 是否使用linear lr  线性学习率  默认False 使用cosine lrcache-image: 是否提前缓存图片到内存cache,以加速训练  默认Falseimage-weights: 是否使用图片采用策略(selection img to training by class weights) 默认False 不使用bucket: 谷歌云盘bucket 一般用不到project: 训练结果保存的根目录 默认是runs/trainname: 训练结果保存的目录 默认是exp  最终: runs/train/expexist-ok: 如果文件存在就ok不存在就新建或increment name  默认False(默认文件都是不存在的)quad: dataloader取数据时, 是否使用collate_fn4代替collate_fn  默认Falsesave_period: Log model after every "save_period" epoch    默认-1 不需要log model 信息artifact_alias: which version of dataset artifact to be stripped  默认lastest  貌似没用到这个参数?local_rank: rank为进程编号  -1且gpu=1时不进行分布式  -1且多块gpu使用DataParallel模式mathentity: wandb entity 默认Noneupload_dataset: 是否上传dataset到wandb tabel(将数据集作为交互式 dsviz表 在浏览器中查看、查询、筛选和分析数据集) 默认Falsebbox_interval: 设置界框图像记录间隔 Set bounding-box image logging interval for W&B 默认-1   opt.epochs // 10"""parser = argparse.ArgumentParser()# --------------------------------------------------- 常用参数 ---------------------------------------------parser.add_argument('--weights', type=str, default='weights/yolov5s.pt', help='initial weights path')parser.add_argument('--cfg', type=str, default='models/yolov5s.yaml', help='model.yaml path')parser.add_argument('--data', type=str, default='data/VOC.yaml', help='dataset.yaml path')parser.add_argument('--hyp', type=str, default='data/hyps/hyp.finetune.yaml', help='hyperparameters path')parser.add_argument('--epochs', type=int, default=200)parser.add_argument('--batch-size', type=int, default=8, help='total batch size for all GPUs')parser.add_argument('--img-size', nargs='+', type=int, default=[640, 640], help='[train, test] image sizes')parser.add_argument('--resume', nargs='?', const=True, default=False, help='resume most recent training')parser.add_argument('--nosave', action='store_true', help='True only save final checkpoint')parser.add_argument('--notest', action='store_true', help='True only test final epoch')parser.add_argument('--workers', type=int, default=1, help='maximum number of dataloader workers')parser.add_argument('--device', default='cuda:0', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')parser.add_argument('--single-cls', action='store_true', help='train multi-class data as single-class')# --------------------------------------------------- 数据增强参数 ---------------------------------------------parser.add_argument('--rect', action='store_true', help='rectangular training')parser.add_argument('--noautoanchor', action='store_true', help='disable autoanchor check')parser.add_argument('--evolve', default=False, action='store_true', help='evolve hyperparameters')parser.add_argument('--multi-scale', default=True, action='store_true', help='vary img-size +/- 50%%')parser.add_argument('--label-smoothing', type=float, default=0.0, help='Label smoothing epsilon')parser.add_argument('--adam', action='store_true', help='use torch.optim.Adam() optimizer')parser.add_argument('--sync-bn', action='store_true', help='use SyncBatchNorm, only available in DDP mode')parser.add_argument('--linear-lr', default=False, action='store_true', help='linear LR')parser.add_argument('--cache-images', action='store_true', help='cache images for faster training')parser.add_argument('--image-weights', default=True, action='store_true', help='use weighted image selection for training')# --------------------------------------------------- 其他参数 ---------------------------------------------parser.add_argument('--bucket', type=str, default='', help='gsutil bucket')parser.add_argument('--project', default='runs/train', help='save to project/name')parser.add_argument('--name', default='exp', help='save to project/name')parser.add_argument('--exist-ok', action='store_true', help='existing project/name ok, do not increment')parser.add_argument('--quad', action='store_true', help='quad dataloader')parser.add_argument('--save_period', type=int, default=-1, help='Log model after every "save_period" epoch')parser.add_argument('--artifact_alias', type=str, default="latest", help='version of dataset artifact to be used')parser.add_argument('--local_rank', type=int, default=-1, help='DDP parameter, wins do not modify')# --------------------------------------------------- 三个W&B(wandb)参数 ---------------------------------------------parser.add_argument('--entity', default=None, help='W&B entity')parser.add_argument('--upload_dataset', action='store_true', help='Upload dataset as W&B artifact table')parser.add_argument('--bbox_interval', type=int, default=-1, help='Set bounding-box image logging interval for W&B')# parser.parse_known_args()# 作用就是当仅获取到基本设置时,如果运行命令中传入了之后才会获取到的其他配置,不会报错;而是将多出来的部分保存起来,留到后面使用opt = parser.parse_known_args()[0] if known else parser.parse_args()return opt

修改完以上参数就可以开始训练了。
(2)训练数据记录
1)训练参数
batch size:8
works:1
epoch:200

关于batch size和works有个疑问,第一次训练的时候batch size可以设置到12和works 为2 后面就不可以了,不知道为啥!!!!

2)训练耗时:接近23个小时。。。。。

3)CPU以及GPU占用率
4)result

5)模型验证:

  """opt参数解析weights: 模型的权重地址 默认 weights/best.ptsource: 测试数据文件(图片或视频)的保存路径 默认data/imagesimgsz: 网络输入图片的大小 默认640conf-thres: object置信度阈值 默认0.25iou-thres: 做nms的iou阈值 默认0.45max-det: 每张图片最大的目标个数 默认1000device: 设置代码执行的设备 cuda device, i.e. 0 or 0,1,2,3 or cpuview-img: 是否展示预测之后的图片或视频 默认Falsesave-txt: 是否将预测的框坐标以txt文件格式保存 默认True 会在runs/detect/expn/labels下生成每张图片预测的txt文件save-conf: 是否保存预测每个目标的置信度到预测tx文件中 默认Truesave-crop: 是否需要将预测到的目标从原图中扣出来 剪切好 并保存 会在runs/detect/expn下生成crops文件,将剪切的图片保存在里面  默认Falsenosave: 是否不要保存预测后的图片  默认False 就是默认要保存预测后的图片classes: 在nms中是否是只保留某些特定的类 默认是None 就是所有类只要满足条件都可以保留agnostic-nms: 进行nms是否也除去不同类别之间的框 默认Falseaugment: 预测是否也要采用数据增强 TTAupdate: 是否将optimizer从ckpt中删除  更新模型  默认Falseproject: 当前测试结果放在哪个主文件夹下 默认runs/detectname: 当前测试结果放在run/detect下的文件名  默认是expexist-ok: 是否存在当前文件 默认False 一般是 no exist-ok 连用  所以一般都要重新创建文件夹line-thickness: 画框的框框的线宽  默认是 3hide-labels: 画出的框框是否需要隐藏label信息 默认Falsehide-conf: 画出的框框是否需要隐藏conf信息 默认Falsehalf: 是否使用半精度 Float16 推理 可以缩短推理时间 但是默认是False"""parser = argparse.ArgumentParser()parser.add_argument('--weights', nargs='+', type=str, default='runs/train/exp19/weights/best.pt', help='model.pt path(s)')parser.add_argument('--source', type=str, default='data/images/112.mp4', help='file/dir/URL/glob, 0 for webcam')parser.add_argument('--imgsz', '--img', '--img-size', type=int, default=640, help='inference size (pixels)')parser.add_argument('--conf-thres', type=float, default=0.25, help='confidence threshold')parser.add_argument('--iou-thres', type=float, default=0.45, help='NMS IoU threshold')parser.add_argument('--max-det', type=int, default=1000, help='maximum detections per image')parser.add_argument('--device', default='', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')parser.add_argument('--view-img', action='store_true', help='show results')parser.add_argument('--save-txt', action='store_true', help='save results to *.txt')parser.add_argument('--save-conf', action='store_true', help='save confidences in --save-txt labels')parser.add_argument('--save-crop', action='store_true', help='save cropped prediction boxes')parser.add_argument('--nosave', action='store_true', help='do not save images/videos')parser.add_argument('--classes', nargs='+', type=int, help='filter by class: --class 0, or --class 0 2 3')parser.add_argument('--agnostic-nms', action='store_true', help='class-agnostic NMS')parser.add_argument('--augment', action='store_true', help='augmented inference')parser.add_argument('--update', action='store_true', help='update all models')parser.add_argument('--project', default='runs/detect', help='save results to project/name')parser.add_argument('--name', default='exp', help='save results to project/name')parser.add_argument('--exist-ok', action='store_true', help='existing project/name ok, do not increment')parser.add_argument('--line-thickness', default=3, type=int, help='bounding box thickness (pixels)')parser.add_argument('--hide-labels', default=False, action='store_true', help='hide labels')parser.add_argument('--hide-conf', default=False, action='store_true', help='hide confidences')parser.add_argument('--half', action='store_true', help='use FP16 half-precision inference')parser.add_argument('--prune-model', default=False, action='store_true', help='model prune')parser.add_argument('--fuse', default=False, action='store_true', help='fuse conv and bn')opt = parser.parse_args()

输入一张图,输入一段视屏:
修改图片路径或者视屏路径即可。代码里面的 cv2.waitKey(1) 需要修改,图片为 cv2.waitKey(0) ,视屏为 cv2.waitKey(1)

            # 是否需要显示我们预测后的结果  img0(此时已将pred结果可视化到了img0中)if view_img:cv2.imshow(str(p), im0)cv2.waitKey(1)  # 1 millisecond

输入电脑摄像头:
修改detect.py配置

4、模型转换
1).将.pt 转换为onnx
在模型pt转化为onnx的时候需要先进行修改models中的cocommon.py,修改Focus 去除slice数组操作,如果不改后续onnx2ncnn转换的时候会报错。

        #原代码中训练用的def forward(self, x):return self.conv(torch.cat([x[..., ::2, ::2], x[..., 1::2, ::2], x[..., ::2, 1::2], x[..., 1::2, 1::2]], 1))
     #模型转换用的代码def forward(self, x):#修改Focus去除slice数组操作,如果不改后续onnx2ncnn转换的时候会报错return self.conv(torch.cat([x, x,x,x], 1))

修改export.py参数

    img-size: 输入模型的图片size=(height, width) 默认=[640, 640]  可以减小一下尺寸免得手机卡爆了batch-size: batch大小 默认=1device: 模型运行设备 cuda device, i.e. 0 or 0,1,2,3 or cpu 默认=cpuinclude: 要将pt文件转为什么格式 可以为单个原始也可以为list 默认=['torchscript', 'onnx', 'coreml']half: 是否使用半精度FP16export转换 默认=Falseinplace: 是否set YOLOv5 Detect() inplace=True  默认=Falsetrain: 是否开启model.train() mode 默认=True  coreml转换必须为Trueoptimize: TorchScript转化参数 是否进行移动端优化  默认=Falsedynamic: ONNX转换参数  dynamic_axes  ONNX转换是否要进行批处理变量  默认=Falsesimplify: ONNX转换参数 是否简化onnx模型  默认=Falseopset-version: ONNX转换参数 设置版本  默认=10"""parser = argparse.ArgumentParser()parser.add_argument('--weights', type=str, default='../runs/train/exp19/weights/best.pt', help='weights path')parser.add_argument('--img-size', nargs='+', type=int, default=[416, 416], help='image (height, width)')parser.add_argument('--batch-size', type=int, default=1, help='batch size')parser.add_argument('--device', default='cpu', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')parser.add_argument('--include', nargs='+', default=['torchscript', 'onnx', 'coreml'], help='include formats')parser.add_argument('--half', action='store_true', help='FP16 half-precision export')parser.add_argument('--inplace', action='store_true', help='set YOLOv5 Detect() inplace=True')parser.add_argument('--train', default="True", action='store_true', help='model.train() mode')parser.add_argument('--optimize', action='store_true', help='TorchScript: optimize for mobile')parser.add_argument('--dynamic', action='store_true', help='ONNX: dynamic axes')parser.add_argument('--simplify', action='store_true', help='ONNX: simplify model')parser.add_argument('--opset-version', type=int, default=10, help='ONNX: opset version')opt = parser.parse_args()return opt

模型简化可以用以下命令:
python -m onnxsim yolov5s.onnx yolov5ssim.onnx,自己把“yolov5s.onnx”修改成自己的名字就好了,如果没有安装onnxsim,先安装pip install onnx-simplifier再运行上面的简化指令python -m onnxsim yolov5s.onnx yolov5ssim.onnx
或者在export.py中设置参数,则转换为onnx 以后模型已经被简化了。

2).将onnx转换为ncnn
a.简单粗暴的:https://convertmodel.com/
直接选择输入输出模型就可以使用,简单粗暴,方便快捷。

b.使用cmake 进行编译,过程较复杂难道较大,切容易出错,后面进行补充。

c、在ncnn(https://github.com/Tencent/ncnn/releases)库下载对应的Windows和VS版本的文件,比如说我这里安装的VS2019,我下载的文件就是:https://github.com/Tencent/ncnn/releases/download/20220216/ncnn-20220216-windows-vs2019.zip
版本问题的话没有太多要求,下好后解压,在X64/bin文件下有对应的exe文件,把模型文件拷贝到当前目录,在文件夹里面按住shift点右键打开Powershell窗口,输入***./onnx2ncnn yolov5s.onnx yolov5s.param yolov5s.bin当前目录就会出现 yolov5s.param yolov5s.bin两个文件.
然后接着重复打开Powershell,
./ncnnoptimize yolov5s.param yolov5s.bin yolov5s_out.param yolov5s_out.bin 65536*** 压缩文件大小。

4、修改转换后的模型.param文件

打开上一步生成的 .param文件,直接拉到最后,将图中的3个数字改为-1,这一步是为了防止Android移植后,检测结果正确显示用,如果不改的话,会出现n多个框,密密麻麻的覆盖你的原本图片。
修改前:
修改后:
log.csdnimg.cn/c23f82279b344211b023cbd8e313db30.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6aqR552A5ouW5ouJ5py65Y675peF6KGM,size_18,color_FFFFFF,t_70,g_se,x_16)

自此模型准备完毕下一步在app开发里面加载。
5、Androidapp开发
官网提供了现成的模块:ncnn-android-yolov5 https://github.com/nihui/ncnn-android-yolov5

1)下载ncnn-20220216-android-vulkan(链接:https://github.com/Tencent/ncnn/releases
2)修改代码
找到3个Permute查看对应的Output的name,修改完成后,继续修改class_names,换成自己的标签,最后连上设备就可以识别图像了。

6、运行检测

基于yolov5的Android版本目标检测app开发(部署安卓手机)相关推荐

  1. 基于yolov5的交通标志牌的目标检测研究设计——思路及概念

    有需要项目的可以私信博主!!!!! 一.选题的目的.意义及研究现状 (1)选题的目的和意义 随着人们对道路安全性的重视和城市交通量的不断增加,交通标志牌作为道路交通安全的重要组成部分之一,扮演着十分重 ...

  2. 基于深度卷积神经网络的目标检测研究综述

    基于深度卷积神经网络的目标检测研究综述 人工智能技术与咨询 来自<光学精密工程> ,作者范丽丽等 摘要:作为计算机视觉中的基本视觉识别问题,目标检测在过去的几十年中得到了广泛地研究.目标检 ...

  3. 使用yolov5训练自己的目标检测数据集

    使用yolov5训练自己的目标检测数据集 yolov4出来后不久,又出现了yolov5,没有论文.虽然作者没有放上和yolov4的直接测试对比,但在COCO数据集的测试效果还是很可观的.很多人考虑到Y ...

  4. 目标检测-使用YOLOV5搭建自己的目标检测平台(手把手)

    鄙人刚接触目标检测,将自己的心得体会写出来,希望对大家有帮助 文章目录 一.说在前面 二.实验步骤 1.搭建实验环境 2.数据集的标注与划分 3.使用YOLOV5训练自己的目标检测模型 三.参考文章 ...

  5. 基于PPYOLOE+的水下生物目标检测

    基于PP-YOLOE+的水下生物目标检测+部署 项目链接[https://aistudio.baidu.com/aistudio/projectdetail/4647849?contributionT ...

  6. 基于深度学习的小目标检测方法综述

    随着深度学习的发展,基于深度学习的目标检测技术取得了巨大的进展,但小目标由于像素少,难以提取有效信息,造成小目标的检测面临着巨大的困难和挑战. 为了提高小目标的检测性能,研究人员从网络结构.训练策略. ...

  7. 基于YOLO的目标检测界面化部署实现(支持yolov1-yolov5、yolop、yolox)

    基于YOLO的目标检测界面化部署实现(支持yolov1-yolov5.yolop.yolox) 代码下载地址:下载地址 安装 操作系统:Win10.Win7.Ubuntu16.04(其他操作系统没有测 ...

  8. 基于YOLOv5的智慧工地安全帽检测(1)

    基于YOLOv5的智慧工地安全帽检测 数据集+代码下载地址:下载地址

  9. 目标检测YOLO实战应用案例100讲-基于深度学习的显著性目标检测研究与应用(论文篇)

    目录 基于深度学习的显著性目标检测综述 基于深度学习的显著性目标检测分类及难点分析

最新文章

  1. openstack代码解读之 neutron.agent.linux.iptables_manager模块
  2. 使用Xshell生成key,避免password登录linux
  3. Python学习:numpy点乘,按元素相乘,以及转置的处理
  4. Java 常见的 30 个误区与细节
  5. 英伟达3080Ti、3070Ti来了!
  6. python 算法库_一个易用又功能强大的 Python遗传算法库
  7. 服务器LCD显示面板,DELL服务器2950的错误代码表(前LCD面板)
  8. CSS3属性 box-shadow
  9. C语言将raw转为bmp,RAW格式数据转BMP格式数据
  10. Tricks(二十二) —— zip(python) 的实现及使用
  11. python怎样终止程序_python终止程序
  12. oracle 索引问题梳理
  13. HTML5+CSS大作业——年会抽奖网页设计(1页)
  14. 【渝粤教育】21秋期末考试招投标与合同管理10217k2
  15. 我的世界服务器附魔修改器,[娱乐|RPG]NshowEnchant —— 一个简单附魔插件[1.7.10-1.12.2]...
  16. Linux中fork函数详解
  17. matlab英文文本信息量,实验一英文文本信息量的计算-Read.doc
  18. 何时“大庇天下寒士俱欢颜”(附笑话)
  19. 微信小程序分页功能实现
  20. 谁动了我的奶酪之奶酪墙上的话。

热门文章

  1. 10.js中的计时器
  2. 从苏宁电器到卡巴斯基第10篇:我在苏宁电器当营业员 I
  3. 2016脑力高危职业榜出炉,高薪与高危同在?
  4. C++入门级——函数重载
  5. 【附源码】计算机毕业设计SSM校服征订系统
  6. 近两年小样本学习取得重大进展了吗?
  7. 极限多标签之-PfastreXML
  8. Windows server——部署web服务
  9. 推荐系统算法原理:向量空间和欧几里得距离的应用
  10. busybox的下载、配置、编译、安装一条龙服务