yolov5 7.0版本部署手机端。通过pnnx导出ncnn。

yolov5 7.0版本部署手机端。通过pnnx导出ncnn。

  • 流程
  • 配置ncnn android yolov5
  • 导出自己模型的ncnn
    • 修改yolo.py文件
    • 导出TorchScript文件
    • pnnx转torchscript为ncnn
  • 安卓运行
      • 权重路径
      • 输入输出
      • anchors 大小
      • 类别名
      • generate_proposals方法修改
    • 结果

流程

网络yolov5 的部署已经有很多了,但是他们很多都是老版本,2023.12.03最新的版本是7.0。导致现在部署碰到各种问题。如下:

  1. (根源) yolov5 export.py导出onnx时添加train参数。但是train参数在最新的7.0版本已经被去掉了。导致问题。
  2. 没有train参数后,使用export.py 导出onnx,再将onnx转ncnn时报错。修改onnx模型麻烦且容易出问题。

本文使用pnnx代码库https://github.com/pnnx/pnnx将torchscript转为ncnn.避免上述问题。流程如下:
在这里插入图片描述

配置ncnn android yolov5

代码库:https://github.com/nihui/ncnn-android-yolov5。先使用代码库中提供的yolov5s ncnn权重。手机端能正常运行并产生输出。
在这里插入图片描述

导出自己模型的ncnn

修改yolo.py文件

老版本的export.py 中,通过添加train参数,去除模型中的后处理。但是新版本中,这个参数没了,所以我们需要将模型中的后处理去掉。
找到yolov5代码中的models->yolo.py文件,将Detect类下面的forward函数替换(大概是56-80行),修改为下面的forward

    def forward(self, x):
        z = []  # inference output
        for i in range(self.nl):
            feat = self.m[i](x[i])  # conv
            # x(bs,255,20,20) -> x(bs,20,20,255)
            feat = feat.permute(0, 2, 3, 1).contiguous()
            z.append(feat.sigmoid())
        return tuple(z)

导出TorchScript文件

直接导出即可

python export.py --weights yolov5s.pt  --include torchscript

pnnx转torchscript为ncnn

代码库:https://github.com/pnnx/pnnx.直接使用releases中的可执行文件即可。使用下面的命令转。需要注意的是zsh不支持官网的[]命令,需要用""包裹

'./pnnx'  'yolov5s.torchscript'    "inputshape=[1,3,640,640]"

正常情况下,在yolov5s.torchscript的文件中已经产生了yolov5s.ncnn.bin 和yolov5s.ncnn.param。这就是我们要的ncnn文件。

安卓运行

将上面的yolov5s.ncnn.bin 和yolov5s.ncnn.param都放入ncnn-android项目文件夹。路径是ncnn-android-yolov5/app/src/main/assets/,这里面应该有一个yolov5s.bin和yolov5s.param。我们将我们转的模型也放进去。如下图。
在这里插入图片描述

然后我们修改yolov5ncnn_jni.cpp文件(上图中的绿色框)。修改模型权重路径,输入输出、anchors大小和类别名。

权重路径

全局搜索yolov5.load_param,将后面的yolov5s.param修改为自己的param名。就在这个代码附近有bin的加载.同理修改

输入输出

打开https://netron.app/,然后将param拖进去, 最上面的这个名字是in0,将in0填写到ex.input中。 模型有三个输出,分别对应stride 8,stride 16和stride 32.将这个输出的名字也填写到对应位置。一般情况下,stride 8对应out0,stride 16对应out1,stride 32对应out2.

最上面的模型输出,以及对应的名字最上面的模型输出,以及对应的名字
下面是应该填写的位置。红色是input,绿色是output.
在这里插入图片描述
模型的第一个头。同理可找另外两个头。
在这里插入图片描述

anchors 大小

anchors的大小就在ex.extract的下方。一共有3个地方需要填写,对应stride 8(小物体),stride 16和stride 32(大物体)。如果自己的网络anchors大小没变则不用改。下图是stride 8 的修改。
在这里插入图片描述

类别名

类别名。全局搜索static const char* class_names。改成自己的就好了。
在这里插入图片描述

generate_proposals方法修改

把整个generate_proposals方法的代码用下面的代码替换。大概在yolov5ncnn_jni.cpp文件的185行。


static void generate_proposals(const ncnn::Mat& anchors, int stride, const ncnn::Mat& in_pad, const ncnn::Mat& feat_blob, float prob_threshold, std::vector<Object>& objects)
{
    const int num_w = feat_blob.w;
    const int num_grid_y = feat_blob.c;
    const int num_grid_x = feat_blob.h;

    const int num_anchors = anchors.w / 2;
    const int walk = num_w / num_anchors;
    const int num_class = walk - 5;

    for (int i = 0; i < num_grid_y; i++)
    {
        for (int j = 0; j < num_grid_x; j++)
        {

            const float* matat = feat_blob.channel(i).row(j);

            for (int k = 0; k < num_anchors; k++)
            {
                const float anchor_w = anchors[k * 2];
                const float anchor_h = anchors[k * 2 + 1];
                const float* ptr = matat + k * walk;
                float box_confidence = ptr[4];
                if (box_confidence >= prob_threshold)
                {
                    // find class index with max class score
                    int class_index = 0;
                    float class_score = -FLT_MAX;
                    for (int c = 0; c < num_class; c++)
                    {
                        float score = ptr[5 + c];
                        if (score > class_score)
                        {
                            class_index = c;
                            class_score = score;
                        }
                        float confidence = box_confidence * class_score;

                        if (confidence >= prob_threshold)
                        {
                            float dx = ptr[0];
                            float dy = ptr[1];
                            float dw = ptr[2];
                            float dh = ptr[3];

                            float pb_cx = (dx * 2.f - 0.5f + j) * stride;
                            float pb_cy = (dy * 2.f - 0.5f + i) * stride;

                            float pb_w = powf(dw * 2.f, 2) * anchor_w;
                            float pb_h = powf(dh * 2.f, 2) * anchor_h;

                            float x0 = pb_cx - pb_w * 0.5f;
                            float y0 = pb_cy - pb_h * 0.5f;
                            float x1 = pb_cx + pb_w * 0.5f;
                            float y1 = pb_cy + pb_h * 0.5f;

                            Object obj;
                            obj.x = x0;
                            obj.y = y0;
                            obj.w = x1 - x0;
                            obj.h = y1 - y0;
                            obj.label = class_index;
                            obj.prob = confidence;

                            objects.push_back(obj);

                        }
                    }
                }
            }
        }
    }
}

结果

点击运行。
在这里插入图片描述

参考:https://zhuanlan.zhihu.com/p/606440867

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/213266.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

分享一个国内可用的免费GPT4-AI提问AI绘画网站工具

一、前言 ChatGPT GPT4.0&#xff0c;Midjourney绘画&#xff0c;相信对大家应该不感到陌生吧&#xff1f;简单来说&#xff0c;GPT-4技术比之前的GPT-3.5相对来说更加智能&#xff0c;会根据用户的要求生成多种内容甚至也可以和用户进行创作交流。 然而&#xff0c;GPT-4对普…

Elasticsearch 优化查询中获取字段内容的方式,性能提升5倍!

1、背景 集群配置为&#xff1a;8 个 node 节点&#xff0c;16 核 32G&#xff0c;索引 4 分片 1 副本。应用程序的查询逻辑是按经纬度排序后找前 200 条文档。 1、应用对查询要求比较高&#xff0c;search 没有慢查询的状态。 2、集群压测性能不能上去&#xff0c;cpu 使用未打…

mybatis的一级缓存和二级缓存

mybatis的一级缓存和二级缓存 mybatis设计两级缓存来提高查询效率。 一级缓存是SqlSession级别&#xff0c;每个会话都需要创建一个sqlsession&#xff0c;避免同一个用户在多次查询中每次都去查询数据库就把查询结果做了缓存 二级缓存 跨SqlSession的缓存&#xff0c;以及缓存…

C#——Delegate(委托)与Event(事件)

C#——Delegate&#xff08;委托&#xff09;与Event&#xff08;事件&#xff09; 前言一、Delegate&#xff08;委托&#xff09;1.是什么&#xff1f;2.怎么用&#xff1f;Example 1&#xff1a;无输入无返回值Example 2&#xff1a;有输入Example 3&#xff1a;有返回值Exa…

抖音外卖商品模型

目录 一、抖音外卖商品模型 二、商家运营流程 &#xff08;一&#xff09;商家入驻流程 &#xff08;二&#xff09;商品发布流程 三、推广带货流程 &#xff08;一&#xff09;短视频带货 &#xff08;二&#xff09;直播视频带货 【直播工具】 【直播流程】 直播前…

SQL Server 数据库,创建数据表(使用T-SQL语句)

2.3表的基本概念 表是包含数据库中所有数据的数据库对象。数据在表中的组织方式与在电子表格中相似&#xff0c;都是 按行和列的格式组织的&#xff0c;每行代表一条唯一的记录&#xff0c;每列代表记录中的一个字段.例如&#xff0c;在包含公 司员工信息的表中&#xff0c;每行…

数据结构:图文详解双向链表的各种操作(头插法,尾插法,任意位置插入,查询节点,删除节点,求链表的长度... ...)

目录 一.双向链表的概念 二.双向链表的数据结构 三.双向链表的实现 节点的插入 头插法 尾插法 任意位置插入 节点的删除 删除链表中第一次出现的目标节点 删除链表中所有与关键字相同的节点 节点的查找 链表的清空 链表的长度 四.模拟实现链表的完整代码 前言&am…

初探Java之旅:探寻Java的奥秘

✨个人主页&#xff1a;全栈程序猿的CSDN博客 &#x1f4a8;系列专栏&#xff1a;Java从入门到精通 ✌座右铭&#xff1a;编码如诗&#xff0c;Bug似流星&#xff0c;持续追求优雅的代码&#xff0c;解决问题如同星辰般自如 在计算机编程的世界中&#xff0c;有一门被誉为“千变…

位图布隆过滤器(附面试题)

文章目录 目录 文章目录 前言 一 . 位图 1.1 面试题 1.2 位图概念 1.3 位图的实现 1.4 位图的应用 二 . 布隆过滤器 2.1 布隆过滤器提出 2.2布隆过滤器概念 2.3 布隆过滤器的查找 2.4 实现 2.5 布隆过滤器删除 2.6 布隆过滤器优点 2.7 布隆过滤器缺陷 2.8 布隆过滤器使用场景 三…

面试官:说说Vue中Proxy与Object.defineProperty的用法与区别

前言 面试时&#xff0c;我们说完Vue响应式原理&#xff0c;或者Vue2和Vue3的区别时&#xff0c;通常会引出Vue3使用了Proxy来优化响应式&#xff0c;而面试官会继续深挖&#xff1a;说说Proxy与Object.defineProperty的区别。 我们不能只说Proxy直接代理一个对象&#xff0c…

【java毕业设计源码】基于SSM框架的在线智能题库管理系统设计与实现

该项目含有源码、文档、PPT、配套开发软件、软件安装教程、项目发布教程等学习内容。 目录 一、项目介绍&#xff1a; 二、文档学习资料&#xff1a; 三、模块截图&#xff1a; 四、开发技术与运行环境&#xff1a; 五、代码展示&#xff1a; 六、数据库表截图&#xff1a…

【论文阅读 + 核心代码定位解读】(2023 AAAI)HiCLR

Hierarchical Consistent Contrastive Learning for Skeleton-Based Action Recognition with Growing Augmentations Contribution 直接使用 strong augmentations 会导致图片/骨架点序列的结构变形和语义信息损失&#xff0c;从而导致训练过程的不稳定。于是本文提出了一种逐…

Java Servlet

请求 请求行 方式 uri http/1.1 请求头 请求体 form表单标签提交Get请求时&#xff0c;参数以键值对形式放在url后&#xff0c;不放在请求体里&#xff0c;Get方式的请求也是可以有请求体的 Post请求时&#xff0c;放在请求头里面 Servlet (server applet) 是运行在服务端…

curl --compressed报错,此版本不支持此命令

出现这个问题是因为微软windows自带的curl不支持这个选项,验证如下 执行where curl 时,可以看到输出为 C:\Windows\System32\curl.ee 解决方法是使用其它curl,下载地址如下 curl for Windows https://curl.se/windows/ 然后把安装目录的bin目录放到path环境变量里最开始, 让…

基于微信小程序的高校活动系统

1 前言 1.1开发背景及意义 高校课余活动管理是中职学生素质教育的重要途径及有效方式&#xff0c;特别是对于一个院校的校园文化建设、校风学风建设和学生综合素质方面的提高至关重要t叫"。良好的学生活动组织可以更好地调动学生参与活动&#xff0c;让学生展示自己的能力…

理解SpringIOC和DI第一课(Spring的特点),IOC对应五大注解,ApplicationContext vs BeanFactory

Spring是一个包含众多工具等Ioc容器 对象这个词在Spring范围内&#xff0c;称为bean Spring两大核心思想 1.IOC (IOC是控制反转&#xff0c;意思是控制权反转-控制权&#xff08;正常是谁用这个对象&#xff0c;谁去创建&#xff0c;&#xff09;-控制对象的控制权&#xf…

十五届海峡两岸电视主持新秀大会竞赛流程

海峡两岸电视主持新秀会是两岸电视媒体共同举办的一项活动&#xff0c;旨在为两岸年轻的电视主持人提供一个展示才华的舞台&#xff0c;促进两岸文化交流和青年交流。本届新秀会是第十二届海峡两岸电视艺术节的重要活动之一。本次竞赛赛制流程如下&#xff1a; &#xff08;1&…

navicat某些表为什么不按主键排序

不知道大家注没注意过navicat的这种情况 为什么不是按主键排序呢 我们来全表扫描看下他的执行计划 explain select * from orsql3; 可以发现不是全表扫描而是索引树扫描&#xff0c;由此得知了共性&#xff0c;不按主键顺序排序的表&#xff0c;肯定是在二级索引上就保存着全部…

【uni-app】赋予你的APP(Android原生)小程序开发能力

采用DCloud(数字天堂&#xff08;北京&#xff09;网络技术有限公司)的uniMPsdk(uni小程序SDK)&#xff0c;是为原生App打造的可运行基于 uni-app 开发的小程序前端项目的框架&#xff0c;从而帮助原生App快速获取小程序的能力。 uni-app文档地址(小程序开发人员开发用) uniMP…

SmartsoftHelp8,条形码,二维码 生成,解析 专业工具

生成条形码 生成二维码 条形码解析 二维码解析 专业工具 下载地址&#xff1a; https://pan.baidu.com/s/1zBgeYsqWnSlNgiKPR2lUYg?pwd8888