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 outputfor 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 scoreint 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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

最新最全的Postman接口测试: postman实现参数化

什么时候会用到参数化 比如&#xff1a;一个模块要用多组不同数据进行测试 验证业务的正确性 Login模块&#xff1a;正确的用户名&#xff0c;密码 成功&#xff1b;错误的用户名&#xff0c;正确的密码 失败 postman实现参数化 在实际的接口测试中&#xff0c;部分参数…

2023第二届全国大学生数据分析大赛AB题代码

看大家需求量比较大&#xff0c;所以更新了一下A、B题的示例代码&#xff0c;部分截图如下 A题部分截图 B题部分截图 免费获取代码 关注威信公众号 Python风控模型与数据分析&#xff0c;回复 23年数据分析大赛代码 文末查看如何免费获取代码&#xff1b;编写不易&#xff0c;…

【数据结构】AOV网与拓扑排序

一.AOV网的概念&#xff08;Activity On Vertex Network&#xff09; 在一个表示工程的有向图中&#xff0c;用顶点表示活动&#xff0c;用弧表示活动之间的优先关系。这样的有向图为顶点表示活动的网&#xff0c;我们称为AOV网&#xff08;Activity On Vertex Network&#xf…

scikit-learn线性回归法进行利润预测

大家好&#xff0c;生成式人工智能无疑是一个改变游戏规则的技术&#xff0c;但对于大多数商业问题来说&#xff0c;回归和分类等传统的机器学习模型仍然是首选。 私募股权或风险投资这样的投资者利用机器学习&#xff0c;首先必须了解关注的数据以及它是如何被使用的。投资公…

k8s安装学习环境

目录 环境准备 配置hosts 关闭防火墙 关闭交换分区 调整swappiness参数 关闭setlinux Ipv4转发 时钟同步 安装Docker 配置Yum源 安装 配置 启动 日志 安装k8s 配置Yum源 Master节点 安装 初始化 配置kubectl 部署CNI网络插件 Node节点 检查 环境准备 准…

同步代码,异步代码-微任务 宏任务 事件循环(输出题)

1.知识点 事件循环&#xff1a; 由浏览器Web API管理的异步代码&#xff0c;如果有结果后&#xff0c;会根据这个异步代码的类型&#xff0c;被放入对应的微任务或宏任务当中。当执行栈的任务&#xff08;同步代码&#xff09;全部执行完毕后&#xff0c;再执行完所有微任务的…

Flutter 控件查阅清单

为了方便记录和使用Flutter中的各种控件&#xff0c;特写此博客以记之&#xff0c;好记性不如烂笔头嘛&#xff1a;&#xff09; 通过控件的首字母进行查找&#xff0c;本文会持续更新 控件目录 AAppBar BCContainerColumn &#xff08;列&#xff09; DDivider (分割线) EElev…

oj赛氪练习题,

区间内的真素数 import java.util.ArrayList; import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner new Scanner(System.in);int M scanner.nextInt();int N scanner.nextInt();scanner.close();ArrayList<Integer>…

吴恩达《机器学习》11-1-11-2:首先要做什么、误差分析

一、首先要做什么 选择特征向量的关键决策 以垃圾邮件分类器算法为例&#xff0c;首先需要决定如何选择和表达特征向量 &#x1d465;。视频提到的一个示例是构建一个由 100 个最常出现在垃圾邮件中的词构成的列表&#xff0c;根据这些词是否在邮件中出现来创建特征向量&…

Docker下安装可视化工具Portainer

目录 Portainer简介 Portainer安装 Portainer简介 Portainer是一款开源的容器管理平台&#xff0c;支持多种容器技术&#xff0c;如Docker、Kubernetes和Swarm等。它提供了一个易于使用的Web UI界面&#xff0c;可用于管理和监控容器和集群。Portainer旨在使容器管理更加简单…

内部类Lambda

静态内部类 /*** 静态成员是在类加载成字节码时就已经存在的,静态只能访问静态*/ public class Demo {public static void main(String[] args) {Outer.Inner.show();} }class Outer {int num1 10;static int num2 20;static class Inner {static void show() {Outer outer …

Kubernetes实战(六)-多系统架构容器镜像构建实战

1 背景 最近在一个国产化项目中遇到了这样一个场景&#xff0c;在同一个 Kubernetes 集群中的节点是混合架构的&#xff0c;即其中某些节点的 CPU 架构是 x86 的&#xff0c;而另一些节点是 ARM 的。为了让镜像在这样的环境下运行&#xff0c;一种最简单的做法是根据节点类型为…

6-15 复制字符串

#include<stdio.h> #include<string.h> int main(){int i;char s1[80],s2[80];printf("输入的s2是&#xff1a;");scanf("%s",s2);for(i0;i<strlen(s2);i)s1[i]s2[i];printf("复制后的s1是&#xff1a;%s\n",s1); return 0;}

HttpRunner自动化工具之实现参数化传递

参数化实现及重复执行 参数化测试&#xff1a;在接口测试中&#xff0c;为了实现不同组数据对同一个功能模块进行测试&#xff0c;需要准备多组测试数据对模块进行测试的过程。 在httprunner中可以通过如下方式实现参数化&#xff1a; 1、在YAML/JSON 中直接指定参数列表 2、…

【STM32】STM32学习笔记-STM32简介(02)

00. 目录 文章目录 00. 目录01. STM32简介1.1 STM32是什么1.2 STM32应用领域1.3 STM32命名规则1.4 STM32选型 02. ARM简介2.1 ARM是什么2.2 ARM系列 03. STM32开发板3.1 MCU简介3.2 STM32开发板3.3 STM32硬件资源 04. STM32系统架构05. STM32引脚定义06. STM32启动配置07. STM3…

构建第一个ArkTS应用(纯HarmonyOS应用)

1. 安装开发工具 在华为开发者官方上下载HarmonyOS应用专用的开发工具&#xff0c;链接地址&#xff1a;HUAWEI DevEco Studio和SDK下载和升级 | HarmonyOS开发者 要想使用开发工具让项目跑起来&#xff0c;需要10G的磁盘空间。开发工具需要的磁盘空间为2.36G&#xff1b;SDK需…

深度学习记录--logistic回归函数的计算图

计算图用于logistic回归函数 先回顾一下单一样本的logistic回归损失函数的公式&#xff0c;公式如下&#xff1a; 将logistic函数用计算图表示出来(以两个基础量为例)&#xff0c;计算图如下&#xff1a; 前向传播已经完成&#xff0c;接下来完成后向传播 运用链式法则依次求…

The Big IAM Challenge 云安全 CTF 挑战赛

The Big IAM Challenge 云安全 CTF 挑战赛 今天&#xff0c;我们来做一下有关于云安全 的CTF 挑战赛 The Big IAM Challenge,旨在让白帽子识别和利用 IAM错误配置&#xff0c;并从现实场景中学习&#xff0c;从而更好的认识和了解IAM相关的风险。比赛包括6个场景&#xff0c;每…

LeetCode 232.用栈实现队列

题目 请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作&#xff08;push、pop、peek、empty&#xff09;&#xff1a; 实现 MyQueue 类&#xff1a; void push(int x) 将元素 x 推到队列的末尾 int pop() 从队列的开头移除并返回元素 int peek() 返回…

智跃人力资源管理系统GenerateEntityFromTable.aspx接口存在SQL注入漏洞 附POC

@[toc] 智跃人力资源管理系统GenerateEntityFromTable.aspx接口存在SQL注入漏洞 附POC 免责声明:请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失,均由使用者本人负责,所产生的一切不良后果与文章作者…