【DL系列】VOC数据集转YOLO数据集(制作YOLOv5/v7自定义数据集)

这篇具有很好参考价值的文章主要介绍了【DL系列】VOC数据集转YOLO数据集(制作YOLOv5/v7自定义数据集)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。



前言

平时我们在使用YOLOv5YOLOv7官方模型进行魔改训练的时候,一般不会用到COCO2017等这样的大型数据集,一般是在自己的自定义数据集或者是一些小的开源数据集上进行调试,这时候就要涉及到数据集的问题。

这里我就VOC格式的数据集如何转成YOLO格式的数据集,如何写训练需要的datasets.yaml文件等问题进行探讨和分享。以我个人实际操作过程中的细节为例,如果有一些细节地方和数据文件位置等问题的,欢迎在评论区讨论交流。

另外YOLOv5、YOLOv7的代码是非常相似的(你懂的),所以两个网络中好多地方是可以互通的,因此在两个网络中制作数据集的操作是可以通用的,具体细节如文件夹地址等注意一下就okk。

【注】:文章中数据集划分以及操作问题是基于 <深度学习视觉-目标检测> 方向为基础,数据集用于YOLOv5/v7做图片目标检测。


1. 数据集准备

这里我划分的数据集是公共数据集,VOC2007trainval + VOC2012trainval。由于两个数据集数据量都很小,所以采用将两个数据集合并成一个数据集进行操作(可以看成是自定义的VOC格式的数据集),也就是之前论文上会遇见的VOC07+12数据集。

首先准备VOC07+12两个数据集,将两个数据集进行合并(直接将两个数据集的AnnotationsJPEGImages两个文件夹中的内容进行合并即可),其中我们只需要Annotations标签文件夹,JPEGImages图片文件夹两个文件夹即可。VOC格式的数据集文件夹划分如下图所示。

【DL系列】VOC数据集转YOLO数据集(制作YOLOv5/v7自定义数据集)

基于划分数据集代码制作自己的数据集VOC0712(images-22136,labels-22136),将其放在yolo代码的根目录(也就是放到yolo项目里)下,这就是待划分的数据集文件(自定义数据集)。

【注】: VOC07+12数据集 的制作过程就是将上图VOC2007 + VOC2012中的Annotations和JPEGImages中的数据分别进行合并即可(ctrl+c、ctrl+v)

【DL系列】VOC数据集转YOLO数据集(制作YOLOv5/v7自定义数据集)


2. 划分数据集

在yolo根目录下创建voc_to_yolo.py脚本,即划分数据集的脚本。

VOC数据集有20个类,如果是自定义的数据集,需要将类classes进行修改。划分比率自己定,这里80表示 train :val = 8 : 2

  • voc_to_yolo.py
"""
# VOC数据集 转 YOLO数据集 格式
"""


import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join
import random
from shutil import copyfile

classes = ["aeroplane", "bicycle", "bird", "boat", "bottle", "bus", "car", "cat", "chair", "cow", "diningtable", "dog",
           "horse", "motorbike", "person", "pottedplant", "sheep", "sofa", "train", "tvmonitor"]
# classes=["ball"]

# 划分比率
TRAIN_RATIO = 80


def clear_hidden_files(path):
    dir_list = os.listdir(path)
    for i in dir_list:
        abspath = os.path.join(os.path.abspath(path), i)
        if os.path.isfile(abspath):
            if i.startswith("._"):
                os.remove(abspath)
        else:
            clear_hidden_files(abspath)


# size是原图的宽和高
def convert(size, box):
    dw = 1. / size[0]
    dh = 1. / size[1]
    x = (box[0] + box[1]) / 2.0
    y = (box[2] + box[3]) / 2.0
    w = box[1] - box[0]
    h = box[3] - box[2]
    x = x * dw
    w = w * dw
    y = y * dh
    h = h * dh
    return (x, y, w, h)


def convert_annotation(image_id):
    in_file = open('VOCdevkit/VOC0712/Annotations/%s.xml' % image_id, 'rb')
    out_file = open('VOCdevkit/VOC0712/YOLOLabels/%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').text
        cls = obj.find('name').text
        if cls not in classes or int(difficult) == 1:
            continue
        cls_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')
    in_file.close()
    out_file.close()


wd = os.getcwd()
data_base_dir = os.path.join(wd, "VOCdevkit/")
if not os.path.isdir(data_base_dir):
    os.mkdir(data_base_dir)
work_sapce_dir = os.path.join(data_base_dir, "VOC0712/")
if not os.path.isdir(work_sapce_dir):
    os.mkdir(work_sapce_dir)
annotation_dir = os.path.join(work_sapce_dir, "Annotations/")
if not os.path.isdir(annotation_dir):
    os.mkdir(annotation_dir)
clear_hidden_files(annotation_dir)
image_dir = os.path.join(work_sapce_dir, "JPEGImages/")
if not os.path.isdir(image_dir):
    os.mkdir(image_dir)
clear_hidden_files(image_dir)

# 这个部分可以不要
yolo_labels_dir = os.path.join(work_sapce_dir, "YOLOLabels/")
if not os.path.isdir(yolo_labels_dir):
    os.mkdir(yolo_labels_dir)
clear_hidden_files(yolo_labels_dir)

yolov5_images_dir = os.path.join(data_base_dir, "images/")
if not os.path.isdir(yolov5_images_dir):
    os.mkdir(yolov5_images_dir)
clear_hidden_files(yolov5_images_dir)
yolov5_labels_dir = os.path.join(data_base_dir, "labels/")
if not os.path.isdir(yolov5_labels_dir):
    os.mkdir(yolov5_labels_dir)
clear_hidden_files(yolov5_labels_dir)
yolov5_images_train_dir = os.path.join(yolov5_images_dir, "train/")
if not os.path.isdir(yolov5_images_train_dir):
    os.mkdir(yolov5_images_train_dir)
clear_hidden_files(yolov5_images_train_dir)
yolov5_images_test_dir = os.path.join(yolov5_images_dir, "val/")
if not os.path.isdir(yolov5_images_test_dir):
    os.mkdir(yolov5_images_test_dir)
clear_hidden_files(yolov5_images_test_dir)
yolov5_labels_train_dir = os.path.join(yolov5_labels_dir, "train/")
if not os.path.isdir(yolov5_labels_train_dir):
    os.mkdir(yolov5_labels_train_dir)
clear_hidden_files(yolov5_labels_train_dir)
yolov5_labels_test_dir = os.path.join(yolov5_labels_dir, "val/")
if not os.path.isdir(yolov5_labels_test_dir):
    os.mkdir(yolov5_labels_test_dir)
clear_hidden_files(yolov5_labels_test_dir)

# 这两个部分yolov5_train.txt, yolov5_val.txt可以不要
train_file = open(os.path.join(wd, "yolov5_train.txt"), 'w')
test_file = open(os.path.join(wd, "yolov5_val.txt"), 'w')
train_file.close()
test_file.close()
train_file = open(os.path.join(wd, "yolov5_train.txt"), 'a')
test_file = open(os.path.join(wd, "yolov5_val.txt"), 'a')
list_imgs = os.listdir(image_dir)  # list image_one files
prob = random.randint(1, 100)
print("Probability: %d" % prob)
for i in range(0, len(list_imgs)):
    path = os.path.join(image_dir, list_imgs[i])
    if os.path.isfile(path):
        image_path = image_dir + list_imgs[i]
        voc_path = list_imgs[i]
        (nameWithoutExtention, extention) = os.path.splitext(os.path.basename(image_path))
        (voc_nameWithoutExtention, voc_extention) = os.path.splitext(os.path.basename(voc_path))
        annotation_name = nameWithoutExtention + '.xml'
        annotation_path = os.path.join(annotation_dir, annotation_name)
        label_name = nameWithoutExtention + '.txt'
        label_path = os.path.join(yolo_labels_dir, label_name)
    prob = random.randint(1, 100)
    print("Probability: %d" % prob)
    if (prob < TRAIN_RATIO):  # train dataset
        if os.path.exists(annotation_path):
            train_file.write(image_path + '\n')
            convert_annotation(nameWithoutExtention)  # convert label
            copyfile(image_path, yolov5_images_train_dir + voc_path)
            copyfile(label_path, yolov5_labels_train_dir + label_name)
    else:  # test dataset
        if os.path.exists(annotation_path):
            test_file.write(image_path + '\n')
            convert_annotation(nameWithoutExtention)  # convert label
            copyfile(image_path, yolov5_images_test_dir + voc_path)
            copyfile(label_path, yolov5_labels_test_dir + label_name)
train_file.close()
test_file.close()

运行脚本,在原数据集中生成如下文件:

【DL系列】VOC数据集转YOLO数据集(制作YOLOv5/v7自定义数据集)

其中images、labels文件夹就是划分后的数据集,这一部分可以直接用于YOLOv5的训练,无需后续再进行 数据地址.txt 文件的生成。YOLOv7不行,YOLOv7必须用.txt文件进行训练。

如果直接用原图片进行训练(YOLOv5支持直接引用图片数据做训练;YOLOv7不支持,需要引用图片数据生成的绝对路径.txt文件训练)。这里说的是YOLOv5中的特殊情况,自定义数据集的yaml文件可以仿照coco.yaml写成如下格式。

  • mydataset.yaml
# train and val data as 1) directory: path/images/, 2) file: path/images.txt, or 3) list: [path1/images/, path2/images/]
train: ./VOCdevkit/images/train  # 17420 images
val: ./VOCdevkit/images/val # 4716 images

# number of classes
nc: 20

# Classes
names: ["aeroplane", "bicycle", "bird", "boat", "bottle", "bus", "car", "cat", "chair", "cow", "diningtable", "dog",
           "horse", "motorbike", "person", "pottedplant", "sheep", "sofa", "train", "tvmonitor"]

【注】:另外脚本生成的几个没有用的文件可以直接删除。其中包括上图在原数据集下生成的YOLOLabels文件夹、下图的在根目录下生成的yolov5_train.txt、yolov5_val.txt文件都可以直接删除。

(这是因为源代码是down网上的代码,不影响使用所以懒得做修改)

【DL系列】VOC数据集转YOLO数据集(制作YOLOv5/v7自定义数据集)


3. 生成datasets.txt文件

如果看过YOLOv5/v7代码中的COCO.yaml文件的都清楚,文件中的数据路径用的是txt文件。尤其是v7必须要用txt地址文件进行训练(这里不清楚v7可否直接用图片,但是我想操作起来要修改很多地方的代码,容易产生bug,不如直接生成数据集的地址txt文件方便)

在根目录下创建get_data_img_dir.py脚本,用于生成划分完数据集后的images下train、val中图片的绝对路径。

  • get_data_img_dir.py
"""
# 制作数据集的步骤:
1. voc_to_yolo.py划分数据集,留下images、labels
2. get_data_img_dir.py 分别生成images下train、val图片的绝对路径(yolov7训练数据集需要.txt文件)
------------------------------------------------------------------------------------------------------------------------
# 生成图片数据的绝对路径
"""

import os


def listdir(path, list_name):  # 传入存储的list
    for file in os.listdir(path):
        file_path = os.path.join(path, file)
        if os.path.isdir(file_path):
            listdir(file_path, list_name)
        else:
            list_name.append(file_path)


list_name = []
path = '/root/Desktop/code/base-yolov7/VOCdevkit/images/val'  # 文件夹路径
listdir(path, list_name)
print(list_name)

with open('./val0712.txt', 'w') as f:  # 要存入的txt
    write = ''
    for i in list_name:
        write = write + str(i) + '\n'
    f.write(write)

运行脚本,在根目录下生成 train0712.txtval0712.txt 两个txt文件,这两个文件就是训练集图片数据的绝对地址,文件如下图所示。

我这里是因为要在服务器上训练网络,所以生成的地址是linux系统下的地址。

【DL系列】VOC数据集转YOLO数据集(制作YOLOv5/v7自定义数据集)


4. 基于数据集制作训练的datasets.yaml文件

在yolov5/v7训练过程中,将上图生成的txt文件移动到创建的datasets-VOC0712文件夹下,这样数据集就制作完成,接下来就是制作模型训练需要用到的yaml文件,仿照coco.yaml文件制作自己的yaml文件,代码如下图所示。

  • mydatasets.yaml
# train and val data as 1) directory: path/images/, 2) file: path/images.txt, or 3) list: [path1/images/, path2/images/]
train: ./datasets/VOC0712/train0712.txt  # 17420 images
val: ./datasets/VOC0712/val0712.txt  # 4716 images

# number of classes
nc: 20

# Classes
names: ["aeroplane", "bicycle", "bird", "boat", "bottle", "bus", "car", "cat", "chair", "cow", "diningtable", "dog",
           "horse", "motorbike", "person", "pottedplant", "sheep", "sofa", "train", "tvmonitor"]

OK,到这一步自定义数据集就整体制作完成。接下来就可以按照模型训练需要注意的地方进行下一步的训练啦!



【注】:由于本人水平有限,如有错误,敬请指正!!!文章来源地址https://www.toymoban.com/news/detail-436183.html

到了这里,关于【DL系列】VOC数据集转YOLO数据集(制作YOLOv5/v7自定义数据集)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • YOLO系列 --- YOLOV7算法(四):YOLO V7算法网络结构解析

    今天来讲讲YOLO V7算法网络结构吧~ 在 train.py 中大概95行的地方开始创建网络,如下图(YOLO V7下载的时间不同,可能代码有少许的改动,所以行数跟我不一定一样) 我们进去发现,其实就是在 yolo.py 里面。后期,我们就会发现相关的网络结构都是在该py文件里面。这篇blog就主

    2024年02月05日
    浏览(46)
  • YOLO系列 --- YOLOV7算法(六):YOLO V7算法onnx模型部署

    有很多人来问我,基于YOLO v7算法训练出来一个权重文件,如何进行部署。所以特地写一篇部署的blog~ 一般,我们基于pytorch深度学习框架训练出来的权重文件是pt格式的,我们可以用python来直接调用这个文件。但是实际工业中,一般都是c++去调用权重文件的,所以我们需要将

    2024年02月07日
    浏览(45)
  • YOLOv5|YOLOv7|YOLOv8改进之实验结果(四):将多种算法的Loss精度曲线图绘制到一张图上,便于YOLOv5、v7系列模型对比实验获取更多精度数据,丰富实验数据

    💡该教程为改进YOLO高阶指南,属于 《芒果书》 📚系列,包含大量的原创首发改进方式🚀 💡更多改进内容📚可以点击查看:YOLOv5改进、YOLOv7改进、YOLOv8改进、YOLOX改进原创目录 | 老师联袂推荐🏆 💡 🚀🚀🚀本博客内含·改进源代码·,按步骤操作运行改进后的代码即可

    2023年04月17日
    浏览(54)
  • YOLOv5系列 1、制作自己的数据集

    YOLOv5系列 1、制作自己的数据集 YOLOv5系列 2、使用yolov5识别自己的数据 本文所使用的Yolov5为6.1版本,所用为GPU版(亲测CPU也一样能跑,只是速度会慢很多),使用的环境是torch1.7.1+cuda10.1。 Labelme的安装很简单,如果想直接安装就直接在命令行中: 如果是想把labelme安装在Anac

    2024年02月10日
    浏览(46)
  • YOLO系列梳理(三)YOLOv5

    前言   YOLOv5 是在 YOLOv4 出来之后没多久就横空出世了。今天笔者介绍一下 YOLOv5 的相关知识。目前 YOLOv5 发布了新的版本,6.0版本。在这里,YOLOv5 也在5.0基础上集成了更多特性,同时也对模型做了微调,并且优化了模型大小,减少了模型的参数量。那么这样,就更加适合移动

    2024年02月05日
    浏览(44)
  • 【目标检测】YOLOv5跑通VOC2007数据集

    如果经常阅读我博客的读者,想必对YOLOv5并不陌生。在Pytorch:YOLO-v5目标检测(上)一文中,我使用了coco128数据集,非常轻松的跑通了。然而在使用VOC2007数据集时,却遇到重重阻碍。主要问题在数据标签转化这个阶段,VOC数据集标注形式是xml,需要将其转换为txt。很多博文并未

    2024年02月06日
    浏览(34)
  • yolov5-7.0训练自己的VOC数据集

    这个笔记可能只适用于7.0版本的,写这个笔记主要是给工作室伙伴参考的,大佬请绕行 有错误之处欢迎指出 yolov5的GitHub仓库地址:Release v7.0 - YOLOv5 SOTA Realtime Instance Segmentation · ultralytics/yolov5 (github.com) 需要下载源码和预训练模型 将源码解压,在其文件夹里面新建一个weights文

    2024年02月12日
    浏览(59)
  • 【YOLO】基于YOLOv8实现自定义数据的自动标注(针对VOC格式的数据集)

    利用yolov8的检测模型实现数据集的自标注,针对VOC数据集,.xml文件,labelimg标注工具 yolov8模型的训练可以参考笔者的博客 【YOLO】YOLOv8实操:环境配置/自定义数据集准备/模型训练/预测 训练好自定义的模型,就可以执行下面的代码实现模型自标注数据集 修改下面三个参数即

    2024年02月11日
    浏览(48)
  • 【YOLO系列】YOLOv5超详细解读(网络详解)

    吼吼!终于来到了YOLOv5啦! 首先,一个热知识:YOLOv5没有发表正式论文哦~ 为什么呢?可能YOLOv5项目的作者Glenn Jocher还在吃帽子吧,hh 前言 一、YOLOv5的网络结构  二、输入端 (1)Mosaic数据增强 (2)自适应锚框计算 (3)自适应图片缩放 三、Backbone (1)Focus结构 (2)CSP结构

    2023年04月09日
    浏览(80)
  • 【数据集转换】VOC数据集转COCO数据集·代码实现+操作步骤

    在自己的数据集上实验时,往往需要将VOC数据集转化为coco数据集,因为这种需求所以才记录这篇文章,代码出处未知,感谢开源。 在远程服务器上测试目标检测算法需要用到测试集,最常用的是coco2014/2017和voc07/12数据集。 coco数据集的地址为http://cocodataset.org/#download voc和co

    2024年02月04日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包