1、yolov5模型转换NCNN模型部署

写作原因:最近看了下nihui大佬的ncnn,练习着将yolov5训练的模型转换成ncnn模型并部署,同时借鉴了网上优秀的博文,记录一下,如有不对的地方,请多多指教。 

说明:pytorch模型转换成onnx模型,及onnx模型简化和转ncnn模型在引用的文章中都有详细的说明,可移步至引用文章中查看。

先来看下ncnn模型,两个,一个是param一个是bin,需要修改的是param。

图1 

其实yolov5 v1-v5版本在训练完后,使用onnx2ncnn.exe将简化后的onnx模型转换成ncnn模型时主要出现这个问题。V6版本在输出上和前5个版本有一点不同,这里针对1-5版本。

 图2

图3

根据nihui大佬的方案看,主要做两步工作,一是删除这里报错的网络层,然后自定义一个新层作为替代,第二步是修改输出参数,做完这两步就可以使用了。

下面说下修改的是什么,这样就可以知道自己的模型应该修改哪里了。

一、param部分参数说明

  7767517   # 文件头 魔数
  75 83     # 层数量  输入输出blob数量
            # 下面有75行
  Input            data             0 1 data 0=227 1=227 2=3
  Convolution      conv1            1 1 data conv1 0=64 1=3 2=1 3=2 4=0 5=1 6=1728
  ReLU             relu_conv1       1 1 conv1 conv1_relu_conv1 0=0.000000
  Pooling          pool1            1 1 conv1_relu_conv1 pool1 0=0 1=3 2=2 3=0 4=0
  Convolution      fire2/squeeze1x1 1 1 pool1 fire2/squeeze1x1 0=16 1=1 2=1 3=1 4=0 5=1 6=1024
  ...
  层类型            层名字   输入blob数量 输出blob数量  输入blob名字 输出blob名字   参数字典
  
  参数字典,每一层的意义不一样:
  数据输入层 Input            data             0 1 data 0=227 1=227 2=3   图像宽度×图像高度×通道数量
  卷积层    Convolution  ...   0=64     1=3      2=1    3=2     4=0    5=1    6=1728           
           0输出通道数 num_output() ; 1卷积核尺寸 kernel_size();  2空洞卷积参数 dilation(); 3卷积步长 stride(); 
           4卷积填充pad_size();       5卷积偏置有无bias_term();   6卷积核参数数量 weight_blob.data_size();
                                                              C_OUT * C_in * W_h * W_w = 64*3*3*3 = 1728
  池化层    Pooling      0=0       1=3       2=2        3=0       4=0
                      0池化方式:最大值、均值、随机     1池化核大小 kernel_size();     2池化核步长 stride(); 
                      3池化核填充 pad();   4是否为全局池化 global_pooling();
  激活层    ReLU       0=0.000000     下限阈值 negative_slope();
           ReLU6      0=0.000000     1=6.000000 上下限
  
  综合示例:
  0=1 1=2.5 -23303=2,2.0,3.0
  
  数组关键字 : -23300 
  -(-23303) - 23300 = 3 表示该参数在参数数组中的index
  后面的第一个参数表示数组元素数量,2表示包含两个元素

 代码 1

 二、对 ncnn.param 进行修正

  • 算子替换

 图4 替换前

 图5 替换后 

 说明:为什么要这么做,nihui大佬对此的解释如下:

nihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuini

转换为 ncnn 模型,会输出很多 Unsupported slice step,这是focus模块转换的报错。

Unsupported slice step !
Unsupported slice step !
Unsupported slice step !
Unsupported slice step !
Unsupported slice step !
Unsupported slice step !
Unsupported slice step !
Unsupported slice step !

代码 2 

好多人遇到这种情况,便不知所措,这些警告表明focus模块这里要手工修复下

打开 yolov5/models/common.py 看看focus在做些什么

class Focus(nn.Module):
    # Focus wh information into c-space
    def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True):  # ch_in, ch_out, kernel, stride, padding, groups
        super(Focus, self).__init__()
        self.conv = Conv(c1 * 4, c2, k, s, p, g, act)

    def forward(self, x):  # x(b,c,w,h) -> y(b,4c,w/2,h/2)
        return self.conv(torch.cat([x[..., ::2, ::2], x[..., 1::2, ::2], x[..., ::2, 1::2], x[..., 1::2, 1::2]], 1))

 代码 3

这其实是一次 col-major space2depth 操作,pytorch 似乎并没有对应上层api实现(反向的 depth2space 可以用 nn.PixelShuffle),yolov5 用 stride slice 再 concat 方式实现,实乃不得已而为之的骚操作。

nihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuini

替换后修改的参数含义

由代码1可知,param第二行的第一个数据是层数量,按niuhui大佬的意思需要替换的行数为4-13行,总共10行,因此第二行的第一个参数就是238-10=228,然后,新增加一层替换,因此最后第二行第一个参数就变成了228+1=229。

然后就是就是新增加一行的输入、输出参数修改了,由代码1中参数说明可知,input层的输出是iamges,原来第14层的输入为205,因此增加层的输入输出就确定了,分别为images、205。

  • 动态尺寸推理

 图6

 说明:为什么要修改这里,nihui大佬的解释是

nihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuini

u版yolov5 是支持动态尺寸推理,但是ncnn天然支持动态尺寸输入,无需reshape或重新初始化,给多少就算多少。u版yolov5 将最后 Reshape 层把输出grid数写死了,导致检测小图时会出现检测框密密麻麻布满整个画面,或者根本检测不到东西。

nihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuini

 解决方案就是将reshape层的输出grid数量改为 -1 便可以自适应。

引用文章:

NCNN之ONNX模型解析及其使用(YOLO5)_sxj731533730-CSDN博客

yolov5模型转换(二) onnx转ncnn_橘也的博客-CSDN博客_yolov5转为onnx

yolov5s6.pt 转 onnx 再转 ncnn 教程【yolov5s6.pt 转 onnx 转 ncnn】_专注于AI领域前沿技术学习与分享、略懂实战、学术菜鸟、日常审稿-CSDN博客_yolov5s 转onnx


 

  • 4
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 要在C语言中部署YoloV5模型,可以使用以下步骤: 1. 安装C语言的深度学习库,例如Darknet或者ncnn。 2. 下载训练好的YoloV5模型权重文件(.pt文件)和模型配置文件(.yaml文件)。 3. 将下载的权重文件和配置文件移动到C语言深度学习库中指定的目录下。 4. 在C语言中编写代码,使用深度学习库加载YoloV5模型,输入待检测的图像,输出检测结果。 需要注意的是,在使用YoloV5模型进行推理时,需要将输入图像进行预处理,例如将图像缩放到指定大小,并且将像素值转换模型所需的数据类型。同时,也需要将模型输出的检测结果进行后处理,例如将边界框坐标转换为图像坐标,并去除重叠的检测框。 ### 回答2: 要在C中部署Yolov5模型,可以按照以下步骤进行: 首先,确保你已经成功编译了C语言环境,并已安装了必要的开发工具和库。 1. 下载Yolov5模型的代码库和权重文件。可以从GitHub上的ultralytics/yolov5仓库下载https://github.com/ultralytics/yolov5。 2. 在C项目中创建一个文件夹,用于存放相关文件。 3. 将Yolov5模型的代码库文件拷贝到你的C项目文件夹中。 4. 在你的C代码中,导入相关的头文件并编写对应的函数调用代码。这些头文件包括一些必要的包含YOLOv5模型定义的头文件。 5. 将YOLOv5的权重文件(例如"yolov5s.pt")拷贝到C项目文件夹中。 6. 在你的C代码中,编写加载模型和权重的代码。这可以通过调用相应的函数并传递模型和权重文件的路径来完成。 7. 编译你的C项目,并确保所有的依赖项都正确配置。 8. 运行你的C程序,验证是否能够成功部署Yolov5模型。你可以通过输入图像并观察输出结果来进行验证。 通过按照以上步骤,你就能够在C中成功部署Yolov5模型了。当然,在实际项目中,还可能需要根据具体的需求进行一些更详细和复杂的配置,但以上步骤可以作为基本的指导供你参考。 ### 回答3: 要使用C语言部署Yolov5模型,我们需要使用C语言的深度学习库来加载模型并进行推理。以下是一个简单的步骤: 1. 首先,我们需要安装合适的深度学习库,如TensorFlow或PyTorch,用于加载和推理Yolov5模型。这些库提供了C语言的接口,让我们能够在C中调用深度学习功能。 2. 通过使用上述深度学习库的预训练模型加载器,我们可以将Yolov5模型加载到C中。 3. 加载模型后,我们可以使用C语言提供的图像处理库,如OpenCV,读取输入图像,并将其转换模型可接受的格式。这可能包括调整图像大小、归一化像素值等。 4. 接下来,我们将读取的图像传递给已加载的Yolov5模型进行推理。通过调用模型的推理函数,我们可以获取在图像中检测到的对象、其位置以及其对应的置信度。 5. 最后,我们可以使用C语言提供的绘图库或图像处理库,如OpenCV,将检测到的对象以及其信息绘制在图像上或进行其他处理。 总的来说,要用C语言部署Yolov5模型,我们需要使用深度学习库加载模型并进行推理,使用图像处理库处理输入图像,并使用绘图库将检测结果显示在图像上。这个过程需要一定的编程和计算机视觉知识,以及对C语言和深度学习库的熟悉。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值