yolov8使用ncnn部署

前言:

几个小时前,我整理了一个新版(v7.0) YOLOv5NCNN 部署教程:

详细记录u版YOLOv5目标检测ncnn实现(第三版) - 知乎

常言道用新不用旧,我顺便把 YOLOv8NCNN 部署放出来吧!(把自己观念持续贯彻!)

本文将基于当前时间最新的 YOLOv8 进行模型转换和模型推理部署。

背景知识:

YOLO 系列在短短的两年多升级了不知道多少代了,但是最火的还是 YOLOv5,同属于这个公司的 YOLOv8 想必也是精品,ultralytics 公司野心很大,发布 YOLOv8 的同时也想一统 YOLO,我们需要持续观望一波!

版本号 v8.0.38

commit id: d99e04daa1290c226a3fae825401361b17ce164c

0x1 缘由

YOLOv8 相对于 YOLOv5 在主干上改动较小,最大的改动就是检测头了,变成了基于 DFLanchor free 模型, 这部分变化较大的就是框解码了,我总结了下面 3 点:

  1. DFL 模块 Reshape+Transpose+Softmax+Conv+Reshape 这套组合是真折腾
  2. 解码已经是 ltrb 格式还要转回 xywh 比较麻烦。
  3. 没有置信度预测分支了,需要自己做 argmax

本文同样,重新组织后处理代码,然后实现 NCNN 推理 YOLOv8

0x2 pytorch测试和导出torchscript

首先是下载当前时间最新的 YOLOv8 ,当前时间是 : 2023-02-15 16:00

git clone https://github.com/ultralytics/ultralytics.git  # clone
cd ultralytics
git checkout d99e04daa1290c226a3fae825401361b17ce164c # switch to commit id
pip install -r requirements.txt  # install
pip install -e . # install ultralytics as package

YOLOv8 开始支持命令行启动任务了,对于搞 YOLOv5 的人转过来调试还是不太舒服。

老样子,用默认的配置和预训练模型推理一张图片:

yolo predict model=yolov8s.pt source=ultralytics/assets/bus.jpg show=True

接下来动源码,ultralytics/nn/modules.py 中的 398-411 行注释掉,换成下面的内容:

    # def forward(self, x):
    #     shape = x[0].shape  # BCHW
    #     for i in range(self.nl):
    #         x[i] = torch.cat((self.cv2[i](x[i]), self.cv3[i](x[i])), 1)
    #     if self.training:
    #         return x
    #     elif self.dynamic or self.shape != shape:
    #         self.anchors, self.strides = (x.transpose(0, 1) for x in make_anchors(x, self.stride, 0.5))
    #         self.shape = shape
    # 
    #     box, cls = torch.cat([xi.view(shape[0], self.no, -1) for xi in x], 2).split((self.reg_max * 4, self.nc), 1)
    #     dbox = dist2bbox(self.dfl(box), self.anchors.unsqueeze(0), xywh=True, dim=1) * self.strides
    #     y = torch.cat((dbox, cls.sigmoid()), 1)
    #     return y if self.export else (y, x)

    def forward(self, x):
        z = []  # inference output
        for i in range(self.nl):
            boxes = self.cv2[i](x[i]).permute(0, 2, 3, 1)
            scores = self.cv3[i](x[i]).sigmoid().permute(0, 2, 3, 1)
            feat = torch.cat((boxes, scores), -1)
            z.append(feat)
        return tuple(z)

导出 torchscript:

yolo export model=yolov8s.pt format=torchscript

会在当前工作目录下生成 yolov8s.torchscript

Netron 看一眼清爽的后处理长什么样:

会有三个上述的结构,这是我们修改的 forward 中的内容,把分类预测分支的 sigmoid 弄到了模型,然后 permute + cat

0x3 转换

下载编译好的 pnnx 工具包:PNNX

指定 inputshape 并且额外指定 inputshape2 转换成支持动态 shape 输入的模型:

./pnnx yolov8s.torchscript inputshape=[1,3,640,640] inputshape2=[1,3,320,320] 

转换日志:

转换主要产物:

看一眼 yolov8s.ncnn.param

in0 对应输入,尺寸是 3*640*640 或者动态输入的尺寸。

out0 对应输出,尺寸是 80*80*144 或者动态输出的尺寸。

out1 对应输出,尺寸是 40*40*144 或者动态输出的尺寸。

out2 对应输出,尺寸是 20*20*144 或者动态输出的尺寸。

注意,本文用pnnx转换后的模型,尾巴上有sigmoid层和permute层。

0x4 u版YOLOv8后处理

pytorch的后处理在ultralytics/nn/modules.py Detect类 forward函数,也就是我们注释掉的部分,对着它改写成 cpp。

本文最后的输出形状:

C = 80 或 40 或 20

H = 80 或 40 或 20

W = 144 = 64+80

64 对应了 DFL 中的 reg_max=16, 最终回归的 bbox 格式是 ltrb

ncnn实现代码和转好的模型已上传到github:

GitHub - triple-Mu/ncnn-examples: Learning ncnn with some examples

使用方式:

git clone https://github.com/triple-Mu/ncnn-examples.git
cd ncnn-examples/yolov8
mkdir build
cmake .. && make -j$(nproc) 
mv triplemu-yolov8 .. && cd ..
./triplemu-yolov8 ../bus.jpg

0x5 动态尺寸推理

与其他的教程相同,本文也支持动态输入尺寸,更多的探索请查看源码 src/triplemu-yolov8.cpp

0x6 总结

允许在不修改内容前提下转载本文!!

欢迎大家通过 triple-Mu 联系我哈~

顺便宣传一下我的 YOLOv8-TensorRT 部署仓库:

GitHub - triple-Mu/YOLOv8-TensorRT: YOLOv8 using TensorRT accelerate !

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值