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

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

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 copyfileclasses = ["hat", "person"]
#classes=["ball"]TRAIN_RATIO = 80def 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)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('VOCdevkit/VOC2007/Annotations/%s.xml' %image_id)out_file = open('VOCdevkit/VOC2007/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').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')in_file.close()out_file.close()wd = os.getcwd()
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, "VOC2007/")
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)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 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 datasetif os.path.exists(annotation_path):train_file.write(image_path + '\n')convert_annotation(nameWithoutExtention) # convert labelcopyfile(image_path, yolov5_images_train_dir + voc_path)copyfile(label_path, yolov5_labels_train_dir + label_name)else: # test datasetif os.path.exists(annotation_path):test_file.write(image_path + '\n')convert_annotation(nameWithoutExtention) # convert labelcopyfile(image_path, yolov5_images_test_dir + voc_path)copyfile(label_path, yolov5_labels_test_dir + label_name)
train_file.close()
test_file.close()

首先数据集的格式结构必须严格按照如图的样式来,因为代码已经将文件名写死了。其实这样也好,因为统一就会规范 。

Annotations里面存放着xml格式的标签文件

JPEGImages里面存放着照片数据文件

特别要注意的是,classes里面必须正确填写xml里面已经标注好的类,要不然生成的txt的文件是不对的。TRAIN_RATIO是训练集和验证集的比例,当等于80的时候,说明划分80%给训练集,20%给验证集。

将代码和数据在同一目录下运行,得到如下的结果

在VOCdevkit目录下生成images和labels文件夹,文件夹下分别生成了train文件夹和val文件夹,里面分别保存着训练集的照片和txt格式的标签,还有验证集的照片和txt格式的标签。images文件夹和labels文件夹就是训练yolov5模型所需的训练集和验证集。在VOCdevkit/VOC2007目录下还生成了一个YOLOLabels文件夹,里面存放着所有的txt格式的标签文件。

至此,xml格式的标签文件转换为txt格式的标签文件并划分为训练集和测试集就讲完了。

2  标签为yolo格式数据集划分训练集和验证集

由于yolov5训练需要的数据标签格式为txt格式,所以大家在利用labelimg标注的时候会用yolo格式(标注生成的标签为txt格式)。标注好的数据集训练的时候就要划分为训练集和验证集,因此就需要有划分为训练集和测试集的代码。这里需要讲的是我写的脚本代码可以成功将数据集划分为训练集和验证集,但是在训练模型的时候,加载数据集一直会出现问题。因此我就想到了,先把txt格式的数据集替换成xml格式的数据集,然后再按上述将xml格式标签转化为txt格式标签并划分为训练集和验证集的方法划分就好了。但是这里建议大家以后标注的时候就标注为voc格式(xml格式),因为该格式的标签里面有图片标注的具体内容,例如标注类别,图片大小,标注坐标。但是yolo格式(txt格式)里面是用数字来代表类别,这样很不直观,而且标注的坐标也是经过转化归一化的,坐标信息更加不直观。先上yolo转voc的代码。

from xml.dom.minidom import Document
import os
import cv2# def makexml(txtPath, xmlPath, picPath):  # txt所在文件夹路径,xml文件保存路径,图片所在文件夹路径
def makexml(picPath, txtPath, xmlPath):  # txt所在文件夹路径,xml文件保存路径,图片所在文件夹路径"""此函数用于将yolo格式txt标注文件转换为voc格式xml标注文件在自己的标注图片文件夹下建三个子文件夹,分别命名为picture、txt、xml"""dic = {'0': "hat",  # 创建字典用来对类型进行转换'1': "person",  # 此处的字典要与自己的classes.txt文件中的类对应,且顺序要一致}files = os.listdir(txtPath)for i, name in enumerate(files):xmlBuilder = Document()annotation = xmlBuilder.createElement("annotation")  # 创建annotation标签xmlBuilder.appendChild(annotation)txtFile = open(txtPath + name)txtList = txtFile.readlines()img = cv2.imread(picPath + name[0:-4] + ".jpg")Pheight, Pwidth, Pdepth = img.shapefolder = xmlBuilder.createElement("folder")  # folder标签foldercontent = xmlBuilder.createTextNode("driving_annotation_dataset")folder.appendChild(foldercontent)annotation.appendChild(folder)  # folder标签结束filename = xmlBuilder.createElement("filename")  # filename标签filenamecontent = xmlBuilder.createTextNode(name[0:-4] + ".jpg")filename.appendChild(filenamecontent)annotation.appendChild(filename)  # filename标签结束size = xmlBuilder.createElement("size")  # size标签width = xmlBuilder.createElement("width")  # size子标签widthwidthcontent = xmlBuilder.createTextNode(str(Pwidth))width.appendChild(widthcontent)size.appendChild(width)  # size子标签width结束height = xmlBuilder.createElement("height")  # size子标签heightheightcontent = xmlBuilder.createTextNode(str(Pheight))height.appendChild(heightcontent)size.appendChild(height)  # size子标签height结束depth = xmlBuilder.createElement("depth")  # size子标签depthdepthcontent = xmlBuilder.createTextNode(str(Pdepth))depth.appendChild(depthcontent)size.appendChild(depth)  # size子标签depth结束annotation.appendChild(size)  # size标签结束for j in txtList:oneline = j.strip().split(" ")object = xmlBuilder.createElement("object")  # object 标签picname = xmlBuilder.createElement("name")  # name标签namecontent = xmlBuilder.createTextNode(dic[oneline[0]])picname.appendChild(namecontent)object.appendChild(picname)  # name标签结束pose = xmlBuilder.createElement("pose")  # pose标签posecontent = xmlBuilder.createTextNode("Unspecified")pose.appendChild(posecontent)object.appendChild(pose)  # pose标签结束truncated = xmlBuilder.createElement("truncated")  # truncated标签truncatedContent = xmlBuilder.createTextNode("0")truncated.appendChild(truncatedContent)object.appendChild(truncated)  # truncated标签结束difficult = xmlBuilder.createElement("difficult")  # difficult标签difficultcontent = xmlBuilder.createTextNode("0")difficult.appendChild(difficultcontent)object.appendChild(difficult)  # difficult标签结束bndbox = xmlBuilder.createElement("bndbox")  # bndbox标签xmin = xmlBuilder.createElement("xmin")  # xmin标签mathData = int(((float(oneline[1])) * Pwidth + 1) - (float(oneline[3])) * 0.5 * Pwidth)xminContent = xmlBuilder.createTextNode(str(mathData))xmin.appendChild(xminContent)bndbox.appendChild(xmin)  # xmin标签结束ymin = xmlBuilder.createElement("ymin")  # ymin标签mathData = int(((float(oneline[2])) * Pheight + 1) - (float(oneline[4])) * 0.5 * Pheight)yminContent = xmlBuilder.createTextNode(str(mathData))ymin.appendChild(yminContent)bndbox.appendChild(ymin)  # ymin标签结束xmax = xmlBuilder.createElement("xmax")  # xmax标签mathData = int(((float(oneline[1])) * Pwidth + 1) + (float(oneline[3])) * 0.5 * Pwidth)xmaxContent = xmlBuilder.createTextNode(str(mathData))xmax.appendChild(xmaxContent)bndbox.appendChild(xmax)  # xmax标签结束ymax = xmlBuilder.createElement("ymax")  # ymax标签mathData = int(((float(oneline[2])) * Pheight + 1) + (float(oneline[4])) * 0.5 * Pheight)ymaxContent = xmlBuilder.createTextNode(str(mathData))ymax.appendChild(ymaxContent)bndbox.appendChild(ymax)  # ymax标签结束object.appendChild(bndbox)  # bndbox标签结束annotation.appendChild(object)  # object标签结束f = open(xmlPath + name[0:-4] + ".xml", 'w')xmlBuilder.writexml(f, indent='\t', newl='\n', addindent='\t', encoding='utf-8')f.close()if __name__ == "__main__":picPath = "VOCdevkit/VOC2007/JPEGImages/"  # 图片所在文件夹路径,后面的/一定要带上txtPath = "VOCdevkit/VOC2007/YOLO/"  # txt所在文件夹路径,后面的/一定要带上xmlPath = "VOCdevkit/VOC2007/Annotations/"  # xml文件保存路径,后面的/一定要带上makexml(picPath, txtPath, xmlPath)

首先讲一下数据的格式,要严格按照下图的目录结构来。为了后续数据集的划分做出统一数据集目录结构。且数据目录要和代码在同一目录下,这样就可以一键运行了。

JPEGImages为图片数据所在的目录
    YOLO为yolo格式的标签数据所在目录
    Annotations为生成的voc格式数据标签目录(程序运行前这是一个空目录)

如下图这里要对应好,且顺序要一致,例如我这里是0对应hat,1对应person。

运行如上的代码,就可以将yolo格式的标签转化为voc格式,并保存在  Annotations目录中,最后可以按照上述1的方法,将voc转为yolo再划分数据集就可以了。

至此yolo格式数据集划分训练集和验证集就结束了

目标检测---数据集格式转化及训练集和验证集划分相关推荐

  1. PASCAL VOC目标检测数据集格式转化为COCO目标检测数据集格式

    VOC2012目标检测数据集格式转化为COCO目标检测数据集格式 你只需要传入一个VOC数据集根路径可以直接运行,简直不要太方便好吧 需要材料: VOC2012原始数据集 一个pycharm项目文件夹 ...

  2. [机器学习]三行代码快速划分交叉训练中训练集和验证集

    使用numpy.random.choice()和set()快速划分交叉训练数据集 之前在划分训练集和验证集时,都是手工随机生成index,很笨. 学到的新方法如下: import numpy as n ...

  3. 神经网络训练集和验证集的原理理解

    今天在学习<python深度学习>的时候,看到了这么一段话: 评估模型的重点是将数据划分为三个集合:训练集.验证集和测试集.在训练数据上训练模型,在验证数据上评估模型.一旦找到了最佳参数, ...

  4. fgvc-aircraft-2013b飞机细粒度数据训练集和测试集划分python代码

    fgvc-aircraft-2013b是细粒度图像分类和识别研究中经典的benchmarks,它包含四种类型的标注: (1)按照manufacturer进行划分,可分为30个类别,例如ATR.Airb ...

  5. csv数据,已区分训练集和验证集,需要用r语言建立随机森林回归模型,计算模型精度,包括训练集和验证集的r方、mae、rmse

    csv数据,已区分训练集和验证集,需要用r语言建立随机森林回归模型,计算模型精度,包括训练集和验证集的r方.mae.rmse #读取训练集 train <- read.csv("tra ...

  6. iris数据集_sklearn日志(二)训练集和测试集划分

    机器学习算法需要大量的数据,这些数据一部分用于模型训练,另一部分作为测试或验证. 机器学习入坑者:sklearn日志(一)体验官方提供的标准数据集​zhuanlan.zhihu.com sklearn ...

  7. 目标检测--RFBNet环境配置、训练及验证 (血和泪的教训)

    最近接到任务,需要对目标检测进行一下调研.于是我面向GitHub进行了一波编程.经过一番比较发现,RFBNet貌似是非常不错的选择.所以就打算和跟我一样的新手们分享一下经验,也算是记录一下踩过的坑.哪 ...

  8. 【yolo5】目标检测数据集制作

    目录 1.先验知识 2. VOC和COCO数据集: 2.1 VOC形式及其数据结构XML特点(好像可以使用py库中工具直接进行清洗) 2.1.1 VOC数据集的组织结构如下所示 2.1.2 XML的操 ...

  9. 使用yolov5训练自动驾驶目标检测数据集BDD100K

    文章目录 一.什么是BDD100K 二.数据预处理 三.环境配置 四.修改模型结构 五.迁移学习 六.训练BDD100K 七.评估性能 八.结语 一.什么是BDD100K BDD100K是伯克利发布的 ...

  10. VOC数据集格式转化

    在做深度学习目标检测模型训练的时候,首先是要获取数据集,然后再对数据集进行标注.然后再把标注完的数据集划分为训练集和验证集,这样更加方便模型的训练和测试. 我们经常从网上获取一些目标检测的数据集资源标 ...

最新文章

  1. 将一个MapString, String写入properties文件,并且覆盖原来的内容
  2. Silverlight C# 游戏开发:未写代码先设计
  3. 堆(heap)与栈(stack)的区别(二)
  4. [原创][连载].基于SOPC的简易数码相框 - Nios II SBTE部分(软件部分) - 从SD卡内读取图片文件,然后显示在TFT-LCD上...
  5. 尼日利亚学生开发者,用阿里云PAI打造了卡通头像神器
  6. SAP Hybris WCMS cockpit 的登录 url
  7. 收集一些常用查询SQL语句以及显示格式
  8. python 调用外部程序 终端异常_python调用外部命令
  9. webRTC:jssip登录freeswitch的正确办法及代码
  10. 卡拉曼达聊天服务器断开修复也没用,英雄联盟新版客户端 聊天系统神似QQ
  11. fst和skiplist
  12. 校运会计算机应用口号,校运会入场霸气押韵口号(精选60句)
  13. 单个字符的输入输出函数
  14. Sherlock之Instructions指令介绍(Sherlock Version: 7.2.5.1 64-bit)
  15. csr867x入门之spp使用(七)
  16. opencv生成棋盘格
  17. 云虚拟主机、云服务器、VPS三者有什么区别?
  18. Spring环绕通知Around
  19. 互联网日报 | 2月24日 星期三 | 华为去年收入利润保持正增长;特斯拉公开全国统一维保价目表;途虎养车回应赴美上市传闻...
  20. 全国高等教师资格证考试复习笔记-高等教育学(1)-教育学概述

热门文章

  1. java tomcat 内存溢出怎么解决_Tomcat内存溢出解决:TomcatJVM内存设置
  2. 房屋出租管理软件,打造一体化的管理模式
  3. PHP 导出excel
  4. 淘宝网购物车jquery源码和网易新用户注册页面表单验证的练习
  5. Kaggle Tabular Playground Series - Jan 2022 学习笔记1(数据分析)
  6. 从googleDriver下载大数据集
  7. 微星刀锋 无法进入bios_微星MPG X570 GAMING EDGE WIFI刀锋板主板BIOS设置u盘启动教程...
  8. axure rp编辑html模板,AxureRP教程—用模板封装UI标准
  9. android 四大组件,安卓四大组件及其作用
  10. Matlab lowess拟合,matlab拟合出曲面后,还需要对应的公式