YOLOv5训练自己的数据及rknn部署

YOLOv5训练自己的数据及rknn部署

  • 一、下载源码
  • 二、准备自己的数据集
    • 2.1 标注图像
    • 2.2 数据集结构
  • 三、配置YOLOv5训练
    • 3.1 修改配置文件
    • 3.2 模型选择
  • 四、训练
  • 五、测试
  • 六、部署
    • 6.1 pt转onnx
    • 6.2 onnx转rknn
  • 七、常见错误
    • 7.1 训练过程中的错误
      • 7.1.1 cuda: out of memory
      • 7.1.2 train: No such file or directory train.cache
      • 7.1.3 Expected object of scalar type __int64 but got scalar type float for sequence element 1.
      • 7.1.4 __init__() got an unexpected keyword argument 'generator'
      • 7.1.5 module 'torch.cuda.amp' has no attribute 'autocast'
    • 7.2 部署过程中的错误
      • 7.2.1 检测框越界/检测框不准
      • 7.2.2 检测框非常多、非常小

一、下载源码

https://github.com/ultralytics/yolov5/releases

二、准备自己的数据集

2.1 标注图像

利用LabelImg标注:

https://github.com/HumanSignal/labelImg

2.2 数据集结构

按照如下结构放置标注好的数据:

/path/to/dataset
    /images
        /train
            image1.jpg
            image2.jpg
            ...
        /val
            image1.jpg
            image2.jpg
            ...
    /labels
        /train
            image1.txt
            image2.txt
            ...
        /val
            image1.txt
            image2.txt
            ...

三、配置YOLOv5训练

3.1 修改配置文件

data文件夹中创建一个新的.yaml配置文件,例如my_dataset.yaml

train: /path/to/dataset/images/train
val: /path/to/dataset/images/val

nc: 2  # 类别数量
names: ['class1', 'class2']  # 类别名称

3.2 模型选择

models文件夹中选择一个适合你任务的模型配置文件(例如yolov5s.yaml),可以根据需要进行调整,例如修改nc参数以匹配你的类别数量。

四、训练

一切准备就绪后,可以开始训练模型。运行以下命令:

python train.py --img 640 --batch 16 --epochs 50 --data data/my_dataset.yaml --weights yolov5s.pt --device cuda:0

参数解释:

  • --img 640 指定训练时的图像尺寸为640x640。
  • --batch 16 指定每批次处理的图片数量为16。
  • --epochs 50 设置训练的轮数为50。
  • --data data/my_dataset.yaml 使用我们刚才配置的数据集文件。
  • --cfg models/yolov5s.yaml 使用YOLOv5s模型配置。
  • --weights yolov5s.pt 使用预训练权重。
  • --device 使用cuda还是cpu。

训练过程图:
在这里插入图片描述

五、测试

将best.pt和图像拷贝到detect.py同路径下,终端切换到该路径,输入:

python detect.py --weights best.pt --img 640 --source test2.jpg

按照终端显示的保存路径,查看效果。

在这里插入图片描述

六、部署

6.1 pt转onnx

将model/yolo.py的 Detect 类下的

def forward(self, x):
    z = []  # inference output
    for i in range(self.nl):
        if getattr(self, 'seg_seperate', False):
            c, s = self.m_replace[i](x[i])
            if getattr(self, 'export', False):
                z.append(c)
                z.append(s)
                continue
            bs, _, ny, nx = c.shape
            c = c.reshape(bs, self.na, -1, ny, nx)
            s = s.reshape(bs, self.na, -1, ny, nx)
            x[i] = torch.cat([c, s], 2).permute(0, 1, 3, 4, 2).contiguous()
        elif getattr(self, 'detect_seperate', False):
            z.append(torch.sigmoid(self.m[i](x[i])))
            continue
        else:
            x[i] = self.m[i](x[i])  # conv
            bs, _, ny, nx = x[i].shape  # x(bs,255,20,20) to x(bs,3,20,20,85)
            x[i] = x[i].view(bs, self.na, self.no, ny, nx).permute(0, 1, 3, 4, 2).contiguous()

        if not self.training:  # inference
            if self.dynamic or self.grid[i].shape[2:4] != x[i].shape[2:4]:
                self.grid[i], self.anchor_grid[i] = self._make_grid(nx, ny, i)

            if isinstance(self, Segment):  # (boxes + masks)
                xy, wh, conf, mask = x[i].split((2, 2, self.nc + 1, self.no - self.nc - 5), 4)
                xy = (xy.sigmoid() * 2 + self.grid[i]) * self.stride[i]  # xy
                wh = (wh.sigmoid() * 2) ** 2 * self.anchor_grid[i]  # wh
                y = torch.cat((xy, wh, conf.sigmoid(), mask), 4)
            else:  # Detect (boxes only)
                xy, wh, conf = x[i].sigmoid().split((2, 2, self.nc + 1), 4)
                xy = (xy * 2 + self.grid[i]) * self.stride[i]  # xy
                wh = (wh * 2) ** 2 * self.anchor_grid[i]  # wh
                y = torch.cat((xy, wh, conf), 4)
            z.append(y.view(bs, self.na * nx * ny, self.no))

    if getattr(self, 'export', False):
        return z
    return x if self.training else (torch.cat(z, 1),) if self.export else (torch.cat(z, 1), x)

修改为:

def forward(self, x):
    z = []
    for i in range(self.nl):
        x[i] = torch.sigmoid(self.m[i](x[i]))

    return x

将训练好的best.pt放在工程文件夹下,使用yolov5工程中的export.py将其转换为onnx模型。

python export.py --weights best.pt

生成onnx:

在这里插入图片描述

将生成的onnx文件导入netron(https://netron.app/)中,查看输出是否为3个分支。

在这里插入图片描述

若是3个分支,表示onnx生成成功。

6.2 onnx转rknn

文件结构

/path
    /bus.jpg
    /datasets.txt
    /yolov5_convert.py
    /best.onnx

datasets的内容:

./bus.jpg

下载转换的程序:
https://github.com/airockchip/rknn-toolkit2/blob/master/rknn-toolkit2/examples/onnx/yolov5/test.py

结合自己的文件路径与类别,修改test.py后运行,便可得到rknn文件。

七、常见错误

7.1 训练过程中的错误

7.1.1 cuda: out of memory

说明内存不足,修改batch的数量,由16改为8或者更小的数。

7.1.2 train: No such file or directory train.cache

方法 1:使用--cache选项强制缓存

python train.py --img 640 --batch 16 --epochs 50 --data data/my_dataset.yaml --weights yolov5s.pt --device cuda:0 --cache

这样,YOLOv5会在数据加载时创建train.cache文件。

方法 2:手动创建缓存

通过运行YOLOv5的dataloaders.py中的create_dataloader函数来创建缓存文件。

python utils/dataloaders.py --data my_dataset.yaml --cache

7.1.3 Expected object of scalar type __int64 but got scalar type float for sequence element 1.

错误位置:

matches = torch.cat((torch.stack(x, 1).long(), iou[x[0], x[1]][:, None]), 1).cpu().numpy()  # [label, detect, iou]

错误原因:索引应该为整型,而不是浮点型,应该利用.long()转成int_64。

修改:

matches = torch.cat((torch.stack(x, 1).long(), iou[x[0], x[1]].long()[:, None]), 1).cpu().numpy()

7.1.4 init() got an unexpected keyword argument ‘generator’

该属性是1.6版本新增加的,所以升级pytorch1.6及以上。

7.1.5 module ‘torch.cuda.amp’ has no attribute ‘autocast’

该属性是1.6版本新增加的,所以升级pytorch1.6及以上。

7.2 部署过程中的错误

7.2.1 检测框越界/检测框不准

在train.py中,noaotoanchor的默认为False,如果设定为True,则会使用默认的anchor设定。
所以,如果经过autoanchor,给出了新的anchor设定,那么在推理和转完rknn后的设定,都需要与之相匹配的anchor,而不是用默认的coco数据集的anchor。

默认的coco数据集anchor:
anchors = [[10, 13], [16, 30], [33, 23], [30, 61], [62, 45],
            [59, 119], [116, 90], [156, 198], [373, 326]]

利用如下代码,查看自己数据集的anchor:

from models.experimental import attempt_load

model = attempt_load('best.pt')  # 加载权重路径
m = model.module.model[-1] if hasattr(model, 'module') else model.model[-1]
print(m.anchor_grid)

在6.2小节的test.py:
yolov5_post_process函数中的anchors参数值,修改为自己数据集的anchors值。

7.2.2 检测框非常多、非常小

由于6.1小节中在修改forward方法时,为了避免置信度大于1,增加了sigmoid函数。所以在6.2小节中test.py的process方法里不应该再有sigmoid函数。不能两个方法都写sigmoid函数,要么forward方法里写sigmoid函数,要么process方法里写sigmoid函数。

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

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

相关文章

MATLAB 如何避免复杂shp文件对inpolygon的影响

**任务描述:**当我想用inpolygon函数将属于非洲的pixel选出来时,发现因为周边小岛的影响,pixel选取有问题,如下图。 第一种解决办法: 首先将复杂shp文件查分成简单的shp文件,即将不相交的元素分离开 [QGIS…

2025.01春节可用两个带源的TV直播软件

电视直播pro 2.612 论坛的分享: https://tieba.baidu.com/p/9183010315 我的网盘 http://pan.ezdial.cn/nasone/tvbox/%E7%94%B5%E8%A7%86%E7%9B%B4-pro.apk 这个软件挺牛逼的,因为虽然有直播购物,但是里面的频道是真好,有电影解说有电视剧, 最后还能自定义播放源. 唯一不足找…

Ubuntu24.04初始化MySQL报错 error while loading shared libraries libaio.so.1

Ubuntu24.04初始化MySQL报错 error while loading shared libraries: libaio.so.1 问题一:libaio1不存在 # 提示libaio1不存在 [rootzabbix-mysql-master.example.com x86_64-linux-gnu]#apt install numactl libaio1 Reading package lists... Done Building depe…

【Linux】其他备选高级IO模型

其他高级 I/O 模型 以上基本介绍的都是同步IO相关知识点,即在同步I/O模型中,程序发起I/O操作后会等待I/O操作完成,即程序会被阻塞,直到I/O完成。整个I/O过程在同一个线程中进行,程序在等待期间不能执行其他任务。下面…

RV1126+FFMPEG推流项目源码

源码在我的gitee上面,感兴趣的可以自行了解 nullhttps://gitee.com/x-lan/rv126-ffmpeg-streaming-projecthttps://gitee.com/x-lan/rv126-ffmpeg-streaming-project

VMware虚拟机克隆或复制linux后无法上网的解决方案

1.首先转移虚拟机到另一台电脑 【虚拟机转移】超详细的将虚拟机(ubuntu)从一台电脑复制到另一台电脑教程_虚拟机复制到另一台电脑-CSDN博客 1.先把虚拟机整个文件拷贝到另一台电脑 2。打开vmware,选择打开虚拟机,选择 .vmx 就可…

具有CLI命令和Web界面的WOL

简介 什么是 wol ? wol 是一个命令行工具,用于发送唤醒网络上设备的 Wake-On-LAN(WOL)魔法包。具有命令行界面和网页界面两种功能。本文只介绍了网页界面。 主要特点 功能:通过发送 Wake-On-LAN(WOL&…

Vue2:使用sortablejs实现el-table中行拖拽调整顺序

如图,实现拖拽表格中的行来调整行顺序,但是其中的编号仍然是1、2、3、4的顺序,不跟着变化。 实现如下: 一、导入sortablejs import Sortable from "sortablejs";export default { components: {Sortable},data() {return {//数据中的id很重要,拖拽行重新排序…

分布式光纤应变监测是一种高精度、分布式的监测技术

一、土木工程领域 桥梁结构健康监测 主跨应变监测:在大跨度桥梁的主跨部分,如悬索桥的主缆、斜拉桥的斜拉索和主梁,分布式光纤应变传感器可以沿着这些关键结构部件进行铺设。通过实时监测应变情况,能够精确捕捉到车辆荷载、风荷…

智能手机“混战”2025:谁将倒下而谁又将突围?

【潮汐商业评论原创】 “去年做手机比较艰难,几乎每个品牌都在调价、压货,像华为这种以前都不给我们分货的厂商,也开始成为我的主要库存。不过今年开头比较好,20号国补一开始,店里的人流和手机销量就明显涨了不少&…

OpenCV文字绘制支持中文显示

OpenCV版本:4.4 IDE:VS2019 功能描述 OpenCV绘制文本的函数putText()不支持中文的显示,网上很多方法推荐的都是使用FreeType来支持,FreeType是什么呢?FreeType的官网上有介绍 FreeType官网 https://www.freetype.or…

MyBatis-Plus的条件构造器和常用接口

一、wrapper介绍 Wrapper : 条件构造抽象类,最顶端父类 ​ AbstractWrapper : 用于查询条件封装,生成 sql 的 where 条件 ​ QueryWrapper : 查询条件封装 ​ UpdateWrapper : Update 条件封装 ​ Abst…

结合实例分析A2DP SBC帧结构和编解码算法

SBC也就是Sub band codec,俗称子带编码,是蓝牙A2DP必须支持的唯一编码。下面结合实例看看SBC编码数据在蓝牙传输中帧结构以及SBC的编解码算法流程: AVDTP Frame 首先AVDTP Frame是基于L2CAP协议,所以会包含有4个字节的L2CAP头部&…

接口(3)

大家好,今天我们接着上一篇的内容继续往下来看看,了解一下如何实现多个接口,与继承父类不同,一个类可以实现接口,那么话不多说,来看。 2.5实现多个接口. 在Java中,类和类之间是单继承的,一个类只能有一个…

MATLAB提供的颜色映射表colormap——伪彩色

图像处理领域的一个习惯:不是真实的颜色,一般用伪彩色。一是说明不是物体本身的颜色,二是彩色更容易分辨。 MATLAB陆续提供了16种颜色映射表colormap。 之前的都很丑,近5年新增的4种还可以。总的说来还是丑。 这是一种鸟的名字。…

网络安全 | 入侵检测系统(IDS)与入侵防御系统(IPS):如何识别并阻止威胁

网络安全 | 入侵检测系统(IDS)与入侵防御系统(IPS):如何识别并阻止威胁 一、前言二、入侵检测系统(IDS)2.1 IDS 的工作原理2.2 IDS 的技术类型2.3 IDS 的部署方式 三、入侵防御系统(…

工业“MCU+AI”

随着工业4.0的推进,传统工业设备正向智能化和自动化方向转型。这要求设备具备更高的算力、更强的实时处理能力以及支持AI算法的能力,以应对工业机器人、电机控制、预测性维护等复杂应用场景。 近年来越来越多的芯片厂商纷纷推出工业“MCUAI”产品&#…

【统计的思想】假设检验(二)

假设检验是根据人为设定的显著水平,对被测对象的总体质量特性进行统计推断的方法。 如果我们通过假设检验否定了零假设,只是说明在设定的显著水平下,零假设成立的概率比较小,并不是说零假设就肯定不成立。如果零假设事实上是成立…

[云讷科技]Kerloud Falcon四旋翼飞车虚拟仿真空间发布

虚拟仿真环境作为一个独立的专有软件包提供给我们的客户,用于帮助用户在实际测试之前验证自身的代码,并通过在仿真引擎中添加新的场景来探索新的飞行驾驶功能。 环境要求 由于环境依赖关系,虚拟仿真只能运行在装有Ubuntu 18.04的Intel-64位…

【数据结构】深入解析:构建父子节点树形数据结构并返回前端

树形数据结构列表 一、前言二、测试数据生成三、树形代码3.1、获取根节点3.2、遍历根节点,递归获取所有子节点3.3、排序3.4、完整代码 一、前言 返回前端VO对象中,有列情况列表展示需要带树形结构,例如基于RBAC权限模型中的菜单返回&#xf…