前言

如果经常阅读我博客的读者,想必对YOLOv5并不陌生。在Pytorch:YOLO-v5目标检测(上)一文中,我使用了coco128数据集,非常轻松的跑通了。然而在使用VOC2007数据集时,却遇到重重阻碍。主要问题在数据标签转化这个阶段,VOC数据集标注形式是xml,需要将其转换为txt。很多博文并未把文件的放置位置交代清楚,导致走了不少弯路,本篇博文就记录如何不走弯路地跑通VOC数据集。

VOC数据集

我是用的VOC数据集是VOC2007,它的文件格式长这样:

注:官网上下载的话训练验集和测试集是分成两个压缩包VOCtrainval_06-Nov-2007.tarVOCtest_06-Nov-2007.tar,此处我将其进行合并,如需下载我合并后的数据集,可跳转到文末进行下载。

  • Annotations
    该文件包含数据标注的xml文件
  • ImageSets
    该文件包含数据集的划分
  • JPEGImages
    该文件包含图像数据集

拿到数据集,第一件需要干的事是把JPEGImages文件夹名称改成images,具体原因后面解释,改完之后如图所示:

数据集处理

从GitHub上,下载Yolov5代码
项目地址:
https://github.com/ultralytics/yolov5
下载完之后,在文件中新建一个文件,我起名为voc_label.py,起名,位置均随意,这个文件主要干两件事:

  • 1、将ImageSets中的训练集、测试集、验证集提出来,拼凑成可以直接访问的绝对路径,如图所示
  • 2、把xml格式的标注转换成txt格式,如图所示:

    图中红色方框圈住的是要提取出的数据,对于每一个目标,txt格式的数据有5个,分别为(class, x , y , w, h),即类别、中心点(x,y),宽高(w,h)。这里的转换公式在代码中有写道,不作细述。注意class必须是以0开始的序号,否则训练时会出现类别溢出的报错。

voc_label.py

import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import joinsets = ['train', 'test', 'val']Imgpath = 'D:/Desktop/Work/VOC2007/images'
xmlfilepath = 'D:/Desktop/Work/VOC2007/Annotations/'
ImageSets_path = 'D:/Desktop/Work/VOC2007/ImageSets/Segmentation/'
Label_path = 'D:/Desktop/Work/VOC2007/'
classes = ["aeroplane", "bicycle", "bird", "boat", "bottle", "bus", "car", "cat", "chair", "cow", "diningtable", "dog", "horse", "motorbike", "person", "pottedplant", "sheep", "sofa", "train", "tvmonitor"]def convert(size, box):dw = 1. / size[0]dh = 1. / size[1]x = (box[0] + box[1]) / 2.0y = (box[2] + box[3]) / 2.0w = box[1] - box[0]h = box[3] - box[2]x = x * dww = w * dwy = y * dhh = h * dhreturn (x, y, w, h)def convert_annotation(image_id):in_file = open(xmlfilepath + '%s.xml' % (image_id))out_file = open(Label_path + 'labels/%s.txt' % (image_id), 'w')tree = ET.parse(in_file)root = tree.getroot()size = root.find('size')w = int(size.find('width').text)h = int(size.find('height').text)for obj in root.iter('object'):difficult = obj.find('difficult').textcls = obj.find('name').textif cls not in classes or int(difficult) == 1:continuecls_id = classes.index(cls)xmlbox = obj.find('bndbox')b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text),float(xmlbox.find('ymax').text))bb = convert((w, h), b)out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')for image_set in sets:if not os.path.exists(Label_path + 'labels/'):os.makedirs(Label_path + 'labels/')image_ids = open(ImageSets_path + '%s.txt' % (image_set)).read().strip().split()list_file = open(Label_path + '%s.txt' % (image_set), 'w')for image_id in image_ids:list_file.write(Imgpath + '/%s.jpg\n' % (image_id))convert_annotation(image_id)list_file.close()

使用时,替换路径和类别classes即可。

运行之后,会在数据集文件夹下生成四个文件,labels中的txt文件和images中的图片名称一一对应。

训练准备

YOLOv5是通过yaml格式的配置文件来找到对应的训练测试数据,因此在训练前需要对该文件进行简单配置。
尽管YOLOv5已有自带的voc.yaml配置文件,但为了之后训练自己的数据,我这里还是新建一个mydata.yaml来将VOC数据进行导入。

train: D:/Desktop/Work/VOC2007/train.txt
val: D:/Desktop/Work/VOC2007/val.txt
test: D:/Desktop/Work/VOC2007/test.txt# number of classes
nc: 20# class names
names: [ 'aeroplane', 'bicycle', 'bird', 'boat', 'bottle', 'bus', 'car', 'cat', 'chair', 'cow', 'diningtable', 'dog', 'horse', 'motorbike', 'person', 'pottedplant', 'sheep', 'sofa', 'train', 'tvmonitor' ]

文件内容很简单,需要指定三个数据集的路径,类别个数和类别名称。

开始训练

打开train.py文件
主要需要调整三个参数
我使用yolov5s作为预训练模型,如下图所示进行修改。

运行之后,程序会自动从官网下载yolov5s.pt模型文件,放在根目录下面。
如果前面的操作和我一样,到此时应该能顺利跑通训练程序。
程序默认的epochs为300,为了尽快看到效果,可以改小些,训练完后,会在runs -> train -> exp 中看到训练和验证的文件。

如果再次运行,会发现生成了一个新的文件夹exp2…这是由于yolov5默认将每次运行结果单独放一个文件夹存储。
具体代码可参见train.py的518行

opt.save_dir = increment_path(Path(opt.project) / opt.name, exist_ok=opt.exist_ok | opt.evolve)  # increment run

这里的increment_path函数就是每次累加exp序号,如果需要将结果保存到指定路径,可以直接将路径替换到等号右边。

当然,Yolov5也提供了一种便捷的方式放置不断生成exp文件。
在超参数设定中,有个参数为exist-ok,其默认为False,将其设置为True,则程序再次运行会在最近的exp生成文件。

另外,还有各种不同的参数,参数含义补充如下,可供研究参考。

    parser = argparse.ArgumentParser()parser.add_argument('--weights', type=str, default='yolov5s.pt', help='initial weights path')parser.add_argument('--cfg', type=str, default='models/yolov5s.yaml', help='model.yaml path  模型配置和网络结构的yaml文件路径')parser.add_argument('--data', type=str, default='data/mydata.yaml', help='data.yaml path 数据集配置的yaml文件路径,包括数据集的路径,类名等关键信息')parser.add_argument('--hyp', type=str, default='data/hyp.scratch.yaml', help='超参数配置的yaml文件路径')parser.add_argument('--epochs', type=int, default=2)parser.add_argument('--batch-size', type=int, default=16, help='total batch size for all GPUs')parser.add_argument('--img-size', nargs='+', type=int, default=[640, 640], help='[train, test] image sizes  输入图像的分辨率大小')parser.add_argument('--rect', action='store_true', help='rectangular training  是否采用矩形图像训练,默认是False')parser.add_argument('--resume', nargs='?', const=True, default=False, help='resume most recent training 从给定的path/last.pt恢复训练,如果为空,则从最近保存的path/last.pt恢复训练')parser.add_argument('--nosave', action='store_true', help='only save final checkpoint 保存模型,只保存最后的检查点,默认为False')parser.add_argument('--notest', action='store_true', help='only test final epoch 训练中不进行test,只测试最后一个轮次,默认为False')parser.add_argument('--noautoanchor', action='store_true', help='disable autoanchor check 不自动调整anchor,默认为False')parser.add_argument('--evolve', action='store_true', help='evolve hyperparameters 是否进行超参数进化,默认为False')parser.add_argument('--bucket', type=str, default='', help='gsutil bucket')parser.add_argument('--cache-images', action='store_true', help='cache images for faster training 是否提前缓存图片到内存,以加快训练速度,默认为False')parser.add_argument('--image-weights', action='store_true', help='use weighted image selection for training')parser.add_argument('--device', default='', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')parser.add_argument('--multi-scale', action='store_true', help='vary img-size +/- 50%% 是否进行多尺度训练,默认为False')parser.add_argument('--single-cls', action='store_true', help='train multi-class data as single-class 将所有数据按照一个类别进行训')parser.add_argument('--adam', action='store_true', help='use torch.optim.Adam() optimizer 是否使用 torch.optim.Adam() 优化器,默认是False')parser.add_argument('--sync-bn', action='store_true', help='use SyncBatchNorm, only available in DDP mode 是否使用跨卡同步BN')parser.add_argument('--local_rank', type=int, default=-1, help='DDP parameter, do not modify')parser.add_argument('--workers', type=int, default=0, help='maximum number of dataloader workers')parser.add_argument('--project', default='runs/train', help='save to project/name')parser.add_argument('--entity', default=None, help='W&B entity')parser.add_argument('--name', default='exp', help='save to project/name')parser.add_argument('--exist-ok', default=False, action='store_true', help='existing project/name ok, do not increment')parser.add_argument('--quad', action='store_true', help='quad dataloader')parser.add_argument('--linear-lr', action='store_true', help='linear LR')parser.add_argument('--label-smoothing', type=float, default=0.0, help='Label smoothing epsilon')parser.add_argument('--upload_dataset', action='store_true', help='Upload dataset as W&B artifact table')parser.add_argument('--bbox_interval', type=int, default=-1, help='Set bounding-box image logging interval for W&B')parser.add_argument('--save_period', type=int, default=-1, help='Log model after every "save_period" epoch')parser.add_argument('--artifact_alias', type=str, default="latest", help='version of dataset artifact to be used')opt = parser.parse_args()

开始测试

上面的过程只运用到了模型的训练和验证,打开test.py,可使用测试集对模型进行测试。
需要修改的参数和训练程序差不多,值得注意的是,yolov5在每次训练之后会输出两个模型文件,一个是best.pt,即验证集上表现最好(mAP最高)的模型,另一个是last.pt,即最后一轮训练的模型。通常来说,输入best.pt进行测试即可。
测试运行之后,会在runs中生成一个test文件,其中可进行训练结果和标注结果的对比。

开始检测

训练/测试只停留在数据集范围内,下面要对一些数据集之外的数据进行检测,打开detect.py文件
修改source为检测图片的文件夹,运行之后,在run->detect中输出检测结果。

更多拓展

如果你的目的只是跑通VOC数据集,那现在估计已经成功了(可以给本文点个赞来分享你成功的快乐 )。
如果你想更深入地研究Yolov5模型,可继续进行阅读。

超参数注释

在训练时,引入了--hyp这个属性,在data/hyp.scratch.yaml这个文件中,包含了训练所有的参数设置。
下面是各参数含义的解释。

# Hyperparameters for COCO training from scratch
# python train.py --batch 40 --cfg yolov5m.yaml --weights '' --data coco.yaml --img 640 --epochs 300
# See tutorials for hyperparameter evolution https://github.com/ultralytics/yolov5#tutorials# 优化器相关
lr0: 0.01  # initial learning rate (SGD=1E-2, Adam=1E-3)  初始学习率
lrf: 0.2  # final OneCycleLR learning rate (lr0 * lrf)  余弦退火超参数
momentum: 0.937  # SGD momentum/Adam beta1  学习率动量
weight_decay: 0.0005  # optimizer weight decay 5e-4 权重衰减系数# 预热学习相关
warmup_epochs: 3.0  # warmup epochs (fractions ok) 预热学习epoch
warmup_momentum: 0.8  # warmup initial momentum 预热学习率动量
warmup_bias_lr: 0.1  # warmup initial bias lr 预热学习率# 不同损失函数权重,以及其他损失函数相关内容
box: 0.05  # box loss gain giou损失的系数
cls: 0.5  # cls loss gain 分类损失的系数
cls_pw: 1.0  # cls BCELoss positive_weight 分类BCELoss中正样本的权重
obj: 1.0  # obj loss gain (scale with pixels) 有无物体损失的系数
obj_pw: 1.0  # obj BCELoss positive_weight 有无物体BCELoss中正样本的权重
iou_t: 0.20  # IoU training threshold 标签与anchors的iou阈值iou training threshold# anchor锚框
anchor_t: 4.0  # anchor-multiple threshold 标签的长h宽w/anchor的长h_a宽w_a阈值, 即h/h_a, w/w_a都要在(1/4.0, 4.0)之间
# anchors: 3  # anchors per output layer (0 to ignore)# 数据增强相关 - 色彩转换
fl_gamma: 0.0  # focal loss gamma (efficientDet default gamma=1.5)
hsv_h: 0.015  # image HSV-Hue augmentation (fraction) 色调
hsv_s: 0.7  # image HSV-Saturation augmentation (fraction) 饱和度
hsv_v: 0.4  # image HSV-Value augmentation (fraction) 明度
# 数据增强相关:旋转、平移、扭曲等
degrees: 0.0  # image rotation (+/- deg) 旋转角度
translate: 0.1  # image translation (+/- fraction) 水平和垂直平移
scale: 0.5  # image scale (+/- gain)  缩放
shear: 0.0  # image shear (+/- deg) 剪切
perspective: 0.0  # image perspective (+/- fraction), range 0-0.001  透视变换参数
# 数据增强相关 - 翻转
flipud: 0.0  # image flip up-down (probability)  上下翻转概率
fliplr: 0.5  # image flip left-right (probability) 左右翻转概率
# 数据增强相关 - mosaic/mixup
mosaic: 1.0  # image mosaic (probability) 进行mosaic的概率(一幅图像融合四幅图像)
mixup: 0.0  # image mixup (probability) 进行mixup的概率(对两个样本-标签数据对按比例相加后生成新的样本-标签数据)

我所使用的是YOLOv5-5.0版本,只有这一个超参数文件。而在官网最新的版本中,已经添加了多个文件。

每个文件属性依旧是上面这些,只是数值不同。至于如何进行调参会让效果更好,有必要进行更多的实验尝试。

更改文件名的逻辑

现在来解决之前遗留的问题,为什么要把图片文件夹名改成images
在源码dataset.py的341行,定义了img2label_paths这个路径函数,这里面固定了images和labels的名称。

如果未改文件夹名,会产生这个报错。

AssertionError: train: No labels in D:\Desktop\Work\XDUAV-dataset2\train.cache. Can not train without labels.

数据集/源码

本文使用的VOC2007数据集下载地址:
https://pan.baidu.com/s/1Be9Ya5__2J9LKJhV5RkhaA?pwd=8888
本文编辑之后的Yolov5文件:
https://pan.baidu.com/s/1GHAbUdU-Rf0dNc-FYgonCA?pwd=8888

后记

经读者指出,这样操作存在一点小问题,即数据集并没有被充分利用,修改后版本见我的这篇博文【目标检测】YOLOv5跑通VOC2007数据集(修复版)

【目标检测】YOLOv5跑通VOC2007数据集相关推荐

  1. 【点云3D目标检测】跑通CIA-SSD过程中的一些报错集锦

    前言 本文主要是介绍了在跑通CIA-SSD系列算法过程中遇到的一些bug,下面是对CIASSD算法的一个简单的介绍. CIA-SSD其基本思想是校准单步目标检测中分类和定位两个任务,提出Confide ...

  2. 《深度学习与目标检测 YOLOv5》

    <深度学习与目标检测 YOLOv5> flyfish 基础 深度学习基础 - 向量 深度学习基础 - 累加符号和连乘符号 深度学习基础 - 最大似然估计 深度学习基础 - 朴素贝叶斯 深度 ...

  3. 目标检测 YOLOv5 - 卷积层和BN层的融合

    目标检测 YOLOv5 - 卷积层和BN层的融合 即Conv2d和 BatchNorm2d融合 flyfish 为了减少模型推理时间,YOLOv5源码中attempt_load已经包括两层的合并,主要 ...

  4. 目标检测 YOLOv5 anchor设置

    目标检测 YOLOv5 anchor设置 1 anchor的存储位置 1.1 yaml配置文件中例如 models/yolov5s.yaml # anchors anchors:- [10,13, 1 ...

  5. 目标检测 YOLOv5 自定义网络结构

    目标检测 YOLOv5 自定义网络结构(YOLOv5-ShuffleNetV2) flyfish 版本:YOLOv5:v5 具体已经借鉴的自定义网络结构包括 YOLOv5-MobileNetV3 Mo ...

  6. 简单快速建立pytorch环境YOLOv5目标检测 模型跑起来(超简单)

    简单快速建立pytorch环境+实现YOLOv5目标检测 模型跑起来(超简单) 一.下载yolov5模型代码: yolo代码 提取码:2022 下载后解压 二.简单快速创建pytorch环境: 1.条 ...

  7. 基于mmdetection 旋转目标检测(OBB detection)+DOTA数据集自定义数据集+配docker

    这两周得益于组里的任务需求,肝了一个遥感类的飞机旋转框目标检测,在给定的4096*4096的大尺度分辨率图片上去识别检测飞机. 经过模型检测后输出结果图如下图所示: 可以看到最终的结果还是不错的,通过 ...

  8. 目标检测 YOLOv5 - 如何提高模型的指标,提高精确率,召回率,mAP等

    目标检测 YOLOv5 - 如何提高模型的指标,提高精确率,召回率,mAP等 flyfish 文中包括了YOLOv5作者分享的提高模型指标小技巧和吴恩达(Andrew Ng)在做缺陷检测项目( ste ...

  9. 目标检测 YOLOv5网络v6 0版本总结

    目标检测 YOLOv5网络v6.0版本总结 YOLOv5对比YOLOv4 输入端:在模型训练阶段,提出了Mosaic数据增强.自适应锚框计算.自适应图片缩放等: Backbone网络:融合其它检测算法 ...

  10. [数据集][VOC][目标检测]河道垃圾水面漂浮物数据集目标检测可用yolo训练-1304张介绍

    数据集格式:Pascal VOC格式(不包含分割路径的txt文件和yolo格式的txt文件,仅仅包含jpg图片和对应的xml) 图片数量(jpg文件个数):1304 标注数量(xml文件个数):130 ...

最新文章

  1. nvidia-jetson系列硬件平台上安装Qt
  2. 基于神经网络的溶解度预测和回归分析
  3. GridView格式化数据失效
  4. JavaScript对象系统说明图
  5. POI的入门:创建单元格设置数据
  6. SAP UI5 应用开发教程之二十一 - SAP UI5 的自定义格式器(Custom Formatter)
  7. android viewpager 滑动方法,Android中Viewpager禁止滑动的实现
  8. 将Teams app升级到net6
  9. Github项目|几行代码即可实现人脸检测、目标检测的开源计算机视觉库
  10. 关于#if NET1的一点小得
  11. Java connot reduce_hadoop错误:org.apache.hadoop.mapreduce.lib.input.FileSplit cannot be cast t...
  12. 学计算机买笔记本还是平板,学生买平板还是笔记本电脑好
  13. 如何修改IDM下载器的临时文件夹位置
  14. Linux paste合并文件,使用多个字符作为间隔符
  15. 计算机二级考试怎么练题库,计算机二级考试单选题训练题库
  16. rangeOfString 与containsString
  17. 对接银行的方法与流程
  18. CentOS7如何设置开机自启动程序、开机自启动脚本?
  19. LintCode Find the Duplicate Number
  20. MySQL数据字典生成工具

热门文章

  1. 搭建简单JAVA分布式爬虫系统
  2. 【Java对象转换】002- Java 对象与 Map 互转
  3. python表示10的负次方_在计算器中怎样表示十的负几次方
  4. 幂级数——函数的幂级数展开
  5. 你有没有思考过,特斯拉为什么先进?
  6. 前端-js网页特效(三)动画效果及原理
  7. Kali 2020.4下载安装详细教程
  8. 腾达U12无线网卡驱动安装教程
  9. 【强档推荐】动漫初音未来Ⅱ主题
  10. android ios emoji兼容,web端怎么和移动端emoji表情兼容