yolov5转hisi的nnie(c and c++)

article/2025/11/8 12:30:36

yolov5转hisi的nnie(c and c++)

    • 总述
    • 一. 训练前修改网络
    • 二. 导出模型
    • 三. 后处理
      • 1. c++版
      • 2. 基于hisi SDK的纯c版(后续更新)

总述

刚躺了坑,记录一下,目的是将yolov5(6.1)转成海思可以推理的wk文件,并完成后处理,实现在板子上进行推理并拿到正确结果。我的设备是3516dv300.,本文会梳理c++版本和c版本,其中c++版本可以方便调用opencv进行读图,show图,但不便于集成在hisi工程中,所以我也尝试了跟着hisi SDK sample中的yolov3改了一版纯c的v5,最终结果可以和c++版的完全对上。

ps: 附一张v5m在hisi的推理结果(size:608),效果还是很不错的:)
在这里插入图片描述

一. 训练前修改网络

1. 修改MaxPool层
nnie中:pooling层采用的是ceil mode(其实是因为caffe不支持floor mode)
在models/common.py如下图修改,开启ceil_model:
在这里插入图片描述
2. 修改Upsample层为反卷积
因为torch中的upsample是最近邻插值(nearest),而海思只支持uppooling方式,
[-1, 1, nn.Upsample, [None, 2, ‘nearest’]] 改为 [-1, 1, nn.ConvTranspose2d, [256,256, 2, 2]] 和 [-1, 1, nn.ConvTranspose2d, [128,128, 2, 2]], 其中的256与128数字是根据网络通道数来的,仅限于s模型,比如m模型需要改为384和192.
在这里插入图片描述
(注:6.1版yolov5没有focus层,不需要修改;6.1的激活函数是silu,即x*sigmod,也是可支持的,不需 要任何修改)

以上修改好后训练模型~

二. 导出模型

1. 导出onnx模型:
(1) 在export中opset改为9
(2) 在models/yolo.py中修改detect中代码如下:
原代码:
在这里插入图片描述

修改为:
在这里插入图片描述

改动有以下几点:
<1>:去掉了原先的permute;
<2>:将view原来的输出维度(bs, na, no, ny, nx) 改为 (bs, na, no, ny * nx);
<3>:去除了后处理坐标点和宽高decode代码,去除cat操作

现在来分析下为什么这么改:
<1>:nnie不支持5个维度的permute(即transpose),且只支持0231的方式,过于局限,我们不妨删掉这一层,在后处理中按照合适的读取方式去找结果就好了。
<2>:nnie的reshape也只支持4维,且第一维必须是0,为了能用nnie的reshape,我们不得不把x和y共享一个维度,这导致的结果是输出结果中,x和y在同一行,我们只需按个数取值即可。
<3>:后处理中,对三个检测层分别处理,所以不需要concat

2. 导出onnx-sim模型:python3 onnxsim xxx.onnx xxx-sim.onnx
3. 导出caffe model和prototex(网上有很多教程,没什么坑)
4. 导出wk:ruyistiodio中导出(网上很多教程,没什么坑)

三. 后处理

1. c++版

参考nnie-lite工程:https://github.com/mxsurui/NNIE-lite
在此基础上添加yolov5的功能,基于里面的yolov3修改

  1. yolo.cpp中yolov3DetectDemo拷贝一份,命名为yolov5DetectDemo,修改其中
    feature_index0 = 2;
    feature_index1 = 1;
    feature_index2 = 0;
    (亦可在导出onnx时交换append的顺序);

  2. 在parseYolov3Feature函数所在位置,拷贝一份命名parseYolov5Feature,并在yolo.cpp中yolov5DetectDemo中调用此函数,
    这里贴出我修改的parseYolov5Feature,其中需要考虑到数据读取方式以及后处理的方式

inline void parseYolov5Feature(int img_width,int img_height,int num_classes,int kBoxPerCell,int feature_index,float conf_threshold,const std::vector<cv::Size2f> &anchors,const nnie::Mat feature,std::vector<int> &ids,std::vector<cv::Rect> &boxes,std::vector<float> &confidences,int print_level)
{const float downscale = static_cast<float>(std::pow(2, feature_index) / 32); // downscale, 1/32, 1/16, 1/8int cell_w = (int)std::pow(feature.width, 0.5);int cell_h = cell_w;for (int cy = 0; cy < cell_h; ++cy){for (int cx = 0; cx < cell_w; ++cx){for (int b = 0; b < kBoxPerCell; ++b){int channel = b * (num_classes + 5);float tc = feature.data[cx + (cy * cell_w) + (channel + 4) * cell_h * cell_w];float confidence = Sigmoid(tc);if (confidence >= conf_threshold){float tx = feature.data[cx + (cy * cell_w) + channel * cell_h * cell_w];float ty = feature.data[cx + (cy * cell_w) + (channel + 1) * cell_h * cell_w];float tw = feature.data[cx + (cy * cell_w) + (channel + 2) * cell_h * cell_w];float th = feature.data[cx + (cy * cell_w) + (channel + 3) * cell_h * cell_w];float tc = feature.data[cx + (cy * cell_w) + (channel + 4) * cell_h * cell_w];tx = Sigmoid(tx);ty = Sigmoid(ty);tw = Sigmoid(tw);th = Sigmoid(th);float x = ((float)cx - 0.5f + 2.0f * tx) / cell_w;float y = ((float)cy - 0.5f + 2.0f * ty) / cell_h;float w = (2.0f *  tw) * (2.0f *  tw) * anchors[b].width * downscale / cell_w;float h = (2.0f * th) * (2.0f * th) * anchors[b].height * downscale / cell_h;std::vector<float> classes(num_classes);for (int i = 0; i < num_classes; ++i){float tc_by_class = feature.data[cx + (cy * cell_w) + (channel + 5 + i) * cell_h * cell_w];float tc_by_class_sigmoid = Sigmoid(tc_by_class);classes[i] = tc_by_class_sigmoid;}auto max_itr = std::max_element(classes.begin(), classes.end());int index = static_cast<int>(max_itr - classes.begin());if (num_classes > 1){confidence = confidence * classes[index];}int center_x = (int) (x * img_width);int center_y = (int) (y * img_height);int width = (int) (w * img_width);int height = (int) (h * img_height);int left = static_cast<int>(center_x - (width - 1.0f) * 0.5f);int top = static_cast<int>(center_y - (height - 1.0f) * 0.5f);if (confidence > conf_threshold){ids.push_back(index);boxes.emplace_back(left, top, width, height);confidences.push_back(confidence);}}}}}

2. 基于hisi SDK的纯c版(后续更新)

。 。 。

参考:

  1. https://blog.csdn.net/tangshopping/article/details/110038605

http://chatgpt.dhexx.cn/article/NclQkugU.shtml

相关文章

HISI_3516_vi

主要的解释还是看这些大牛的&#xff0c;我这里只是想自己整理一遍&#xff1a;海思3518E开发笔记2.5——海思VI&#xff08;video input&#xff09;模块详解_Spark&#xff01;的博客-CSDN博客_海思wdr目录海思video input模块架构介绍海思video input模块功能介绍结构体说明…

hisi Camera 开发--HiMPP媒体处理软件开发基本概念

1. HIMPP平台架构简介 海思提供的媒体处理软件平台(Media Process Platform,简称 MPP),可支持应用软件快速开发。该平台对应用软件屏蔽了芯片相关的复杂的底层处理,并对应用软件直接提供 MPI(MPP Program Interface)接口完成相应功能。该平台支持应用软件快速开发以下功能:输入…

Hisiphp

最近有个项目要用到后台&#xff0c;就选用了hisiphp这个框架&#xff0c;框架使用的是thinkphp5.1。现在将里面的应用记录下来&#xff0c;为了以后方便使用。 1&#xff0c;首先要开启&#xff0c;系统-系统开发-开发模式 2&#xff0c;进入系统--系统扩展--模块管理--设计新…

海思芯片介绍

1.芯片介绍 芯片SOC里集成了众多控制芯片&#xff0c;比如负责深度学习的NNIE硬核&#xff0c;负责图像处理的IVE硬核&#xff0c;视频编解码单元H265/H264Codec&#xff0c;以及图像处理单元ISP等 为了减少用户对于硬件的直接操作&#xff0c;海思为用户封装了许多对于硬件的操…

hisi平台异常重启问题分析

Hisi平台开发之异常重启问题分析 目录 1. 问题描述...................................................................................................................... 3 2. 问题跟踪排查......................................................................…

【HISI系列】之开发板调试基本知识

1. HISI 根文件系统简介 Linux 的目录结构的最顶层是一个被称为“ / ”的根目录。系统加载 Linux 内核之后&#xff0c;就会挂载一个设备到根目录上。存在于这个设备中的文件系统被称为根文件系统。所有的系统命令、系统配置以及其他文件系统的挂载点都位于这个根文件系统中。 …

HTTP Digest接入方式鉴权认证流程

HTTP Digest接入方式鉴权认证流程 一、摘要认证原理 摘要认证与基础认证的工作原理很相似&#xff0c;用户先发出一个没有认证证书的请求&#xff0c;Web服务器回复一个带有WWW-Authenticate头的响应&#xff0c;指明访问所请求的资源需要证书。但是和基础认证发送以Base 64编…

C++ libcurl Digest Auth

C libcurl Digest Auth postman操作如下&#xff1a; 附认证原理如下&#xff1a; MD5 md5; string HA1 md5("username:realm:password"); string HA2 md5("method:uri"); string response md5("HA1:nouce:nc:cnonce:qop:HA2"); 这里…

mysql sql语句digest收集与展示

1.前言 mysql慢查询&#xff0c;已经有现成的成熟的方案收集展示了&#xff1a;pt-query-digest结合box公司的anemometer&#xff0c;没用过的移步&#xff1a;《mysql慢查询可视化》&#xff08;本章内容需要提前了解anemometer&#xff09;。 但DBA们一定还遇到过这样的问题…

HTTP Digest authentication

什么是摘要认证 摘要认证&#xff08; Digest authentication&#xff09;是一个简单的认证机制&#xff0c;最初是为HTTP协议开发的&#xff0c;因而也常叫做HTTP摘要&#xff0c;在RFC2617中描述。其身份验证机制很简单&#xff0c;它采用杂凑式&#xff08;hash&#xff09…

配置Apache Digest认证

Apache常见的用户认证可以分为下面三种&#xff1a; 基于IP&#xff0c;子网的访问控制(ACL)基本用户验证(Basic Authentication)消息摘要式身份验证(Digest Authentication) 消息摘要式身份验证(Digest Authentication) Digest Authentication在基本身份验证上面扩展了安全…

http Digest认证计算方法整理

摘要认证及实现HTTP digest authentication - 简书 HTTP Basic和Digest认证介绍与计算 - 诸子流 - 博客园 不要不知道上面说的URI是什么意思啊 图解HTTP 第 8 章 确认访问用户身份的认证 - 简书8.1 何为认证 为了弄清究竟是谁在访问服务器&#xff0c;就得让对方的客户端自报家…

业务维度digest日志的记录与监控方案

需求 ​   为了满足从业务整体的维度 实现监控和链路复原&#xff0c;我们希望对于一个业务接口&#xff0c;记录一行请求日志&#xff0c;并通过某个 Unique Id&#xff08;如UserId、OrderId&#xff09;将多行日志关联起来&#xff0c;最终产出一批和业务强相关的数据&am…

java发起Digest Auth请求

常规认证方式 上代码&#xff1a; 需要的Maven <dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5</version></dependency><dependency><groupId>org.…

认证学习3 - Digest摘要认证讲解、代码实现、演示

文章目录 Digest摘要认证 - 密文讲解&#xff08;Digest摘要认证&#xff09;实现&#xff08;Digest认证&#xff09;代码&#xff08;Digest认证&#xff09;代码&#xff08;Digest认证-客户端&#xff09;演示&#xff08;Digest认证-postman&#xff09; 认证大全&#xf…

HTTP的认证方式之DIGEST 认证(摘要认证)

核心步骤&#xff1a; 步骤 1&#xff1a; 请求需认证的资源时&#xff0c;服务器会随着状态码 401Authorization Required&#xff0c;返回带WWW-Authenticate 首部字段的响应。该字段内包含质问响应方式认证所需的临时质询码&#xff08;随机数&#xff0c;nonce&#xff09;…

Digest Auth 摘要认证

Digest Auth 摘要认证 1.非常规方式 转载&#xff1a;https://blog.csdn.net/qq_25391785/article/details/86595529 public static void postMethod(String url, String query) {try {CredentialsProvider credsProvider new BasicCredentialsProvider();credsProvider.setC…

digest鉴权

“摘要”式认证&#xff08; Digest authentication&#xff09;是一个简单的认证机制&#xff0c;最初是为HTTP协议开发的&#xff0c;因而也常叫做HTTP摘要&#xff0c;在RFC2671中描述。其身份验证机制很简单&#xff0c;它采用杂凑式&#xff08;hash&#xff09;加密方法&…

消息摘要(Digest),数字签名(Signature),数字证书(Certificate)是什么?

1. 消息摘要&#xff08;Digest&#xff09; 1. 什么是消息摘要&#xff1f; 对一份数据&#xff0c;进行一个单向的 Hash 函数&#xff0c;生成一个固定长度的 Hash 值&#xff0c;这个值就是这份数据的摘要&#xff0c;也称为指纹。 2. 摘要算法 常见的摘要算法有 MD5、SHA…

HTTP通讯安全中的Digest摘要认证释义与实现

摘要 出于安全考虑&#xff0c;HTTP规范定义了几种认证方式以对访问者身份进行鉴权&#xff0c;最常见的认证方式之一是Digest认证 Digest认证简介 HTTP通讯采用人类可阅读的文本格式进行数据通讯&#xff0c;其内容非常容易被解读。出于安全考虑&#xff0c;HTTP规范定义了几…