当前位置:   article > 正文

【深度学习】准备个人数据集、YOLOV5 模型的训练和测试_选择一个应用场景,自己准备数据集,用深度学习模型进行训练,调整(修改)模型,测试,

选择一个应用场景,自己准备数据集,用深度学习模型进行训练,调整(修改)模型,测试,

上一篇描述了在win10下,基于anaconda & pytorch 的深度学习环境的准备搭建过程,下面进行个人数据集的准备,YOLOV5的代码下载测试,训练个人数据集测试识别效果。

一、个人数据集的准备

做深度学习,YOLOV5模型的图像识别,我们需要大量的数据集来进行训练,才能达到准确识别的效果。

制作数据集需要用到 lebelimg 来将我们的数据图片做数据标注生成xml文件。

1.1 libelimg 的安装

(下面是安装过程,可以按步骤进行安装,也可以直接用exe程序 省去安装过程 - 已经上传到我的资源)

首先打开cmd命令行(快捷键:win+R)。进入cmd命令行控制台。输入如下的命令:

 pip install labelimg -i https://pypi.tuna.tsinghua.edu.cn/simple

运行如上命令后,系统就会自动下载labelimg相关的依赖。由于这是一个很轻量的工具,所以下载起来很快。

 1.2 使用labelimg 准备个人数据集

首先我们需要准备 - 需要打标注的数据集。建议新建一个名为VOC2007的文件夹(通常yolo模型中数据集都以这个为名称,统一不易出错 & 当然你想要个性一点起一个自己名字***也不是不行,在后面的训练中自己可以分清楚就OK),

里面创建一个名为JPEGImages的文件夹存放我们需要打标签的图片文件;再创建一个名为Annotations存放标注的标签文件;最后创建一个名为 predefined_classes.txt 的txt文件来存放所要标注的类别名称。

VOC2007的目录结构为:

├── VOC2007
│├── JPEGImages 存放需要打标签的图片文件
│├── Annotations 存放标注的标签文件
│├── predefined_classes.txt 定义自己要标注的所有类别(在我们定义类别比较多的时候,创建一个这样的txt文件来存放类别)
 

将要所有训练的数据集图片放到JPEGImages文件夹下,待标注。

(若有多个类别将要定义,将类名输入到predefined_classes.txt文件中,如图:

 之后打开刚刚下载的labelimg(也可在python命令行终端输入labelimg打开)

 

(若直接使用exe程序 ,则直接打开就可以,如图:)

 打开后为如下界面:(后面为标注程序,前面终端可显示你的操作记录)

 下面介绍图中的我们常用的按钮。
在这里插入图片描述待标注图片数据的路径文件夹,这里输入命令的时候就选定了JPEGImages。(当然这是可以换的)
在这里插入图片描述保存类别标签的路径文件夹,这里我们选定了Annotations文件夹。

常用快捷键如下:

A:切换到上一张图片

D:切换到下一张图片

W:调出标注十字架

del :删除标注框框

Ctrl+u:选择标注的图片文件夹

Ctrl+r:选择标注好的label标签存在的文件夹

开始标注:

先点击open打开单个图片,或者open air直接打开要标注图片所在文件夹

再点击create rectbox ,出现红色十字进行框选标注,框选后需要输入标注框的类名,即我们进行训练的类名。 

最后点save ,我们所标注的xml文件就保存在了对应的文件夹。

按顺序将你要训练的图片一一标注即可。

 最终文件如图: 

1.3 VOC标签格式转yolo格式并划分训练集和测试集

我们的数据集标签的格式是VOC(xml格式)的,而yolov5训练所需要的文件格式是yolo(txt格式)的,这里就需要对xml格式的标签文件转换为txt文件。同时训练自己的yolov5检测模型的时候,数据集需要划分为训练集和验证集。这里提供了一份代码将xml格式的标注文件转换为txt格式的标注文件,并按比例划分为训练集和验证集。先上代码再讲解代码的注意事项。

1.3.1 这个py脚本用于提取数据图片的名称,存放在对应的四个文件夹里。在下面的数据标注文件格式转换中用到
  1. # coding:utf-8
  2. #这里生成的文件在后面转换VOC - YOLO格式时用到
  3. import os
  4. import random
  5. import argparse
  6. parser = argparse.ArgumentParser()
  7. #xml文件的地址,根据自己的数据进行修改 xml一般存放在Annotations下
  8. parser.add_argument('--xml_path', default='Annotations', type=str, help='input xml label path')
  9. #数据集的划分,地址选择自己数据下的ImageSets/Main
  10. parser.add_argument('--txt_path', default='ImageSets/Main', type=str, help='output txt label path')
  11. opt = parser.parse_args()
  12. trainval_percent = 0.7 # 训练集和验证集所占比例。 这里没有划分测试集
  13. train_percent = 0.8 # 训练集所占比例,可自己进行调整
  14. xmlfilepath = opt.xml_path
  15. txtsavepath = opt.txt_path
  16. total_xml = os.listdir(xmlfilepath)
  17. if not os.path.exists(txtsavepath):
  18. os.makedirs(txtsavepath)
  19. num = len(total_xml)
  20. list_index = range(num)
  21. tv = int(num * trainval_percent)
  22. tr = int(tv * train_percent)
  23. trainval = random.sample(list_index, tv)
  24. train = random.sample(trainval, tr)
  25. file_trainval = open(txtsavepath + '/trainval.txt', 'w')
  26. file_test = open(txtsavepath + '/test.txt', 'w')
  27. file_train = open(txtsavepath + '/train.txt', 'w')
  28. file_val = open(txtsavepath + '/val.txt', 'w')
  29. for i in list_index:
  30. name = total_xml[i][:-4] + '\n'
  31. if i in trainval:
  32. file_trainval.write(name)
  33. if i in train:
  34. file_train.write(name)
  35. else:
  36. file_val.write(name)
  37. else:
  38. file_test.write(name)
  39. file_trainval.close()
  40. file_train.close()
  41. file_val.close()
  42. file_test.close()
1.3.2  将xml格式的标注文件转换为txt格式

这里用到的['train', 'val', 'test']三个文件是在上一个脚本生成的,其他注释我都放在代码里了。

^要注意的是‘dataSet_path’ 这个文件夹是在以后跑YOLO训练时候在自己的VOC.yaml 中用到的指向训练用数据的地址。(后面附上我的VOC.yaml 文件)

  1. # -*- coding: utf-8 -*-
  2. import xml.etree.ElementTree as ET
  3. import os
  4. from os import getcwd
  5. sets = ['train', 'val', 'test'] #后面获取图片路径用到的文件夹名称
  6. classes = ["10分", "80分", "30分", "95分"] # 改成自己的类别
  7. abs_path = os.getcwd()
  8. print(abs_path)
  9. def convert(size, box):
  10. dw = 1. / (size[0])
  11. dh = 1. / (size[1])
  12. x = (box[0] + box[1]) / 2.0 - 1
  13. y = (box[2] + box[3]) / 2.0 - 1
  14. w = box[1] - box[0]
  15. h = box[3] - box[2]
  16. x = x * dw
  17. w = w * dw
  18. y = y * dh
  19. h = h * dh
  20. return x, y, w, h
  21. def convert_annotation(image_id):
  22. in_file = open('G:/yolov5-master/mydata/Annotations/%s.xml' % (image_id), encoding='UTF-8') #自己 xml 文件地址
  23. out_file = open('G:/yolov5-master/mydata/labels/%s.txt' % (image_id), 'w') #生成的yolo(txt格式)存放文件夹路径
  24. tree = ET.parse(in_file)
  25. root = tree.getroot()
  26. size = root.find('size')
  27. w = int(size.find('width').text)
  28. h = int(size.find('height').text)
  29. for obj in root.iter('object'):
  30. difficult = obj.find('difficult').text
  31. # difficult = obj.find('Difficult').text
  32. cls = obj.find('name').text
  33. if cls not in classes or int(difficult) == 1:
  34. continue
  35. cls_id = classes.index(cls)
  36. xmlbox = obj.find('bndbox')
  37. b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text),
  38. float(xmlbox.find('ymax').text))
  39. b1, b2, b3, b4 = b
  40. # 标注越界修正
  41. if b2 > w:
  42. b2 = w
  43. if b4 > h:
  44. b4 = h
  45. b = (b1, b2, b3, b4)
  46. bb = convert((w, h), b)
  47. out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
  48. wd = getcwd()
  49. for image_set in sets:
  50. if not os.path.exists('G:/yolov5-master/mydata/labels/'):
  51. os.makedirs('G:/yolov5-master/mydata/labels/')
  52. image_ids = open('G:/yolov5-master/mydata/ImageSets/Main/%s.txt' % (image_set)).read().strip().split() #获取图片名称,这里的三个txt文件是上一个.py生成的
  53. if not os.path.exists('G:/yolov5-master/mydata/dataSet_path/'):
  54. os.makedirs('G:/yolov5-master/mydata/dataSet_path/')
  55. list_file = open('dataSet_path/%s.txt' % (image_set), 'w') #训练用到的数据集数据存放在dataSet_path文件夹下
  56. # 这行路径不需更改,这是相对路径
  57. for image_id in image_ids:
  58. list_file.write('G:/yolov5-master/mydata/images/%s.jpg\n' % (image_id))
  59. convert_annotation(image_id)
  60. list_file.close()

VOC.yaml

  1. train: G:/yolov5-master/mydata/dataSet_path/train.txt
  2. val: G:/yolov5-master/mydata/dataSet_path/val.txt
  3. nc: 4 #类别数量
  4. names: ["10分", "80分", "30分", "95分"] #所有 类 的名称

到这里训练用的数据集就准备完毕了。

二、克隆项目代码 & 必要的环境依赖

1.准备项目代码

YOLOv5的代码是开源的,我们可以从github上克隆其源码。

打开yolov5的github的官网(这个网站在国外打开是很慢的,需要一些魔法。若实在打不开也可以到这个网址下载gitee中的镜像库)

打开的官网界面如下,这个就是大神glenn-jocher开源的yolov5的项目。

 这个开源的项目通过大家的不断的完善和修复已经到了第5个分支,因此我们选择第五个版本来实验,首先点击左上角的master这个图标来选择项目的第5个分支,如下图所示,然后将版本选择好以后,点击右上角的code那个按键,将代码下载下来。至此整个项目就已经准备好了。

将我们下载好的yolov5的代码解压,然后用上个文章安装好的pycharm打开,打开之后整个代码目录如下图:(我已经进行过一些训练,有些自己的文件,所以文件目录可能有所不同)

现在来对代码的整体目录做一个介绍:


data:主要是存放一些超参数的配置文件(这些文件(yaml文件)是用来配置训练集和测试集还有验证集的路径的,其中还包括目标检测的种类数和种类的名称);还有一些官方提供测试的图片。如果是训练自己的数据集的话,那么就需要修改其中的yaml文件。但是自己的数据集不建议放在这个路径下面,而是建议把数据集放到yolov5项目的同级目录下面。


models:里面主要是一些网络构建的配置文件和函数,其中包含了该项目的四个不同的版本,分别为是s、m、l、x。从名字就可以看出,这几个版本的大小。他们的检测测度分别都是从快到慢,但是精确度分别是从低到高。这就是所谓的鱼和熊掌不可兼得。如果训练自己的数据集的话,就需要修改这里面相对应的yaml文件来训练自己模型。

utils:存放的是工具类的函数,里面有loss函数,metrics函数,plots函数等等。

weights:放置训练好的权重参数。

detect.py:利用训练好的权重参数进行目标检测,可以进行图像、视频和摄像头的检测。

train.py:训练自己的数据集的函数。

test.py:测试训练的结果的函数。

requirements.txt:这是一个文本文件,里面写着使用yolov5项目的环境依赖包的一些版本,可以利用该文本导入相应版本的包。

以上就是yolov5项目代码的整体介绍。我们训练和测试自己的数据集基本就是利用到如上的代码。
 

2. 安装环境和依赖库

打开requirements.txt这个文件,可以看到里面有很多的依赖库和其对应的版本要求。

我们打开pycharm的命令终端,在中输入如下的命令。

( ^ 这里要注意,有些包需要特定的库支持才可以,需要安装VS , 这里我的电脑之前就装了VS2019 ,所以没有报错)

pip install -r requirements.txt

三、准备数据集和YOLOV5预训练权重文件

1. 数据集就是上面用labelimg标注并处理过的数据集

2. 获得预训练权重

一般为了缩短网络的训练时间,并达到更好的精度,我们一般加载预训练权重进行网络的训练。而yolov5的5.0版本给我们提供了几个预训练权重,我们可以对应我们不同的需求选择不同的版本的预训练权重。通过如下的图可以获得权重的名字和大小信息,可以预料的到,预训练权重越大,训练出来的精度就会相对来说越高,但是其检测的速度就会越慢。预训练权重可以通过这个网址进行下载(这依然是国外的网址,进不去的可以到这个网址下载镜像),本次训练自己的数据集用的预训练权重为yolov5s.pt。

 四、训练自己的模型

1.修改数据配置文件

预训练模型和数据集都准备好了,就可以开始训练自己的yolov5目标检测模型了,训练目标检测模型需要修改两个yaml文件中的参数。一个是data目录下的相应的yaml文件,一个是model目录文件下的相应的yaml文件。

【   修改data目录下的相应的yaml文件。找到目录下的voc.yaml文件,将该文件复制一份,将复制的文件重命名,最好和项目相关,这样方便后面操作。】

【我这里修改为myvoc.yaml。只保留了几行重要的代码,其他的都删掉了。即上面提到过的voc.yaml】

 2. 修改模型配置文件

我们使用的是yolov5s.pt这个预训练权重,所以要使用models目录下的yolov5s.yaml文件中的相应参数(因为不同的预训练权重对应着不同的网络层数,所以用错预训练权重会报错)。同上修改data目录下的yaml文件一样,我们将yolov5s.yaml文件复制一份,然后将其重命名。
打开自己复制的yolov5s.yaml文件 ,这里我们只需要修改如图中的数字,表示识别的类别个数。

至此,相应的配置参数就修改好了。

3. 训练自己的模型启用tensorbord查看参数

上面的工作都做好之后,就可以正式开始我们YOLOV5的训练了

首先找到train.py这个文件。

然后找到主函数的入口,有模型的主要参数。模型的主要参数解析如下所示:

  1.  > if name == ‘main’:
  2. > opt模型主要参数解析:
  3. > --weights:初始化的权重文件的路径地址
  4. > --cfg:模型yaml文件的路径地址
  5. > --data:数据yaml文件的路径地址
  6. > --hyp:超参数文件路径地址
  7. > --epochs:训练轮次
  8. > --batch-size:喂入批次文件的多少
  9. > --img-size:输入图片尺寸
  10. > --rect:是否采用矩形训练,默认False
  11. > --resume:接着打断训练上次的结果接着训练
  12. > --nosave:不保存模型,默认False
  13. > --notest:不进行test,默认False
  14. > --noautoanchor:不自动调整anchor,默认False
  15. > --evolve:是否进行超参数进化,默认False
  16. > --bucket:谷歌云盘bucket,一般不会用到
  17. > --cache-images:是否提前缓存图片到内存,以加快训练速度,默认False
  18. > --image-weights:使用加权图像选择进行训练
  19. > --device:训练的设备,cpu;0(表示一个gpu设备cuda:0);0,1,2,3(多个gpu设备)
  20. > --multi-scale:是否进行多尺度训练,默认False
  21. > --single-cls:数据集是否只有一个类别,默认False
  22. > --adam:是否使用adam优化器
  23. > --sync-bn:是否使用跨卡同步BN,在DDP模式使用
  24. > --local_rank:DDP参数,请勿修改
  25. > --workers:最大工作核心数
  26. > --project:训练模型的保存位置
  27. > --name:模型保存的目录名称
  28. > --exist-ok:模型目录是否存在,不存在就创建

其中最重要的,我们要(前三行)

将‘ 初始化的权重文件的路径地址’  修改为自己预训练权重的路径(即yolov5s.pt 的路径)

将 模型yaml文件的路径地址  修改为自己对应的地址

将数据yaml文件的路径地址  修改为自己对应的地址

接下来运行train.py 就会训练自己的模型了,我们只需要静静的等待,去泡壶茶 或者 开一局王者放松一下也不是不行的~~~

五、测试

在“漫长的等待后~ ”,就会在主目录下产生一个run文件夹,我们用自己的数据集训练的权重文件就在run/train/exp/weights目录下。会产生两个权重文件,一个是最后一轮的权重文件last.pt,一个是最好的权重文件best.pt,接下来我们就要利用这个best.pt来做测试。除此以外还会产生一些验证文件的图片等一些文件。

 

找到主目录下的detect.py文件,打开该文件。


然后找到主函数的入口,这里面有模型的主要参数。模型的主要参数解析如下所示。

“”"
–weights:权重的路径地址
–source:测试数据,可以是图片/视频路径,也可以是’0’(电脑自带摄像头),也可以是rtsp等视频流
–output:网络预测之后的图片/视频的保存路径
–img-size:网络输入图片大小
–conf-thres:置信度阈值
–iou-thres:做nms的iou阈值
–device:是用GPU还是CPU做推理
–view-img:是否展示预测之后的图片/视频,默认False
–save-txt:是否将预测的框坐标以txt文件形式保存,默认False
–classes:设置只保留某一部分类别,形如0或者0 2 3
–agnostic-nms:进行nms是否也去除不同类别之间的框,默认False
–augment:推理的时候进行多尺度,翻转等操作(TTA)推理
–update:如果为True,则对所有模型进行strip_optimizer操作,去除pt文件中的优化器等信息,默认为False
–project:推理的结果保存在runs/detect目录下
–name:结果保存的文件夹名称
“”"

  1. f name == ‘main’:
  2. parser = argparse.ArgumentParser()
  3. parser.add_argument(‘–weights’, nargs=‘+’, type=str, default=‘yolov5s.pt’, help=‘model.pt path(s)’)
  4. parser.add_argument(‘–source’, type=str, default=‘data/images’, help=‘source’) # file/folder, 0 for webcam
  5. parser.add_argument(‘–img-size’, type=int, default=640, help=‘inference size (pixels)’)
  6. parser.add_argument(‘–conf-thres’, type=float, default=0.25, help=‘object confidence threshold’)
  7. parser.add_argument(‘–iou-thres’, type=float, default=0.45, help=‘IOU threshold for NMS’)
  8. parser.add_argument(‘–device’, default=‘’, help=‘cuda device, i.e. 0 or 0,1,2,3 or cpu’)
  9. parser.add_argument(‘–view-img’, action=‘store_true’, help=‘display results’)
  10. parser.add_argument(‘–save-txt’, action=‘store_true’, help=‘save results to *.txt’)
  11. parser.add_argument(‘–save-conf’, action=‘store_true’, help=‘save confidences in --save-txt labels’)
  12. parser.add_argument(‘–nosave’, action=‘store_true’, help=‘do not save images/videos’)
  13. parser.add_argument(‘–classes’, nargs=‘+’, type=int, help=‘filter by class: --class 0, or --class 0 2 3’)
  14. parser.add_argument(‘–agnostic-nms’, action=‘store_true’, help=‘class-agnostic NMS’)
  15. parser.add_argument(‘–augment’, action=‘store_true’, help=‘augmented inference’)
  16. parser.add_argument(‘–update’, action=‘store_true’, help=‘update all models’)
  17. parser.add_argument(‘–project’, default=‘runs/detect’, help=‘save results to project/name’)
  18. parser.add_argument(‘–name’, default=‘exp’, help=‘save results to project/name’)
  19. parser.add_argument(‘–exist-ok’, action=‘store_true’, help=‘existing project/name ok, do not increment’)
  20. opt = parser.parse_args()


这里需要将刚刚训练好的最好的权重传入到推理函数中去。然后就可以对图像视频进行推理了。
parser.add_argument(‘–weights’, nargs=‘+’, type=str, default=‘自己训练的权重路径/best.pt’, help=‘model.pt path(s)’)
对图片进行测试推理,将如下参数修改成图片的路径,然后运行detect.py就可以进行测试了。
parser.add_argument(‘–source’, type=str, default=‘你要做推理测试的路径’, help=‘source’)

推理测试结束以后,在run下面会生成一个detect目录,推理结果会保存在exp目录下。如图所示。

 


  图片的推理结果如下所示。效果还是很不错的。
1

 
对视频进行测试,需要将图片的路径改为视频的路径。

利用摄像头进行测试只需将路径改写为0。

利用摄像头测试报错,解决方法之一(来源于@每天写bug):

在这里插入图片描述

解决方法:首先找到datasets.py这个py文件。在这里插入图片描述

打开文件,找到第279行代码,给两个url参数加上str就可以了,如图所示,就可以完美运行电脑的摄像头了。在这里插入图片描述

到这yolov5训练自己的模型就完成了,可以使用自己训练的权重去识别。

修改训练参数 以提高训练速度or识别精度,待下一章

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/292239
推荐阅读
相关标签
  

闽ICP备14008679号