使用YOLOv3训练BDD100K数据集之标签格式转换
BDD100K数据集介绍:
BDD100K的道路目标检测部分总共有10类:bus,traffic light,traffic sign,person,bike,truck,moter,car,train,rider。
BDD100K数据集的下载(百度云)
链接:https://pan.baidu.com/s/1fFSzGJt6Op4k7Gyo9QjtYA
提取码:kuld
一般只需要下载解压bdd100k_labels.zip和bdd100k_images.zip,会出现两个bdd100k文件夹,这两个文件夹内分别存储了images和labels两个子文件夹,其中images文件夹内存放了1280x720的图片,labels存放了json格式的标签文件,我们把两个子文件夹合并到一个bdd100k文件夹内,方便查看和处理。文件目录树如下:
├── bdd100k
│ ├── images
│ │ ├── 100k
│ │ │ ├── test # 20k测试集图片
│ │ │ ├── train # 70k训练集图片
│ │ │ └── val # 10k验证集图片
│ │ └── 10k
│ │ ├── test # 2k测试集图片
│ │ ├── train # 7k测试集图片
│ │ └── val # 1k验证集图片
│ ├── labels
│ │ └── 100k
│ │ ├── train # 70k训练集标签
│ │ ├── val # 10k验证集标签,这里没有提供20k测试集标签
首先,我们需要两个辅助脚本:parseJson.py(用来解析json里面的对象检测部分的数据)和pascal_voc_io.py(创建VOC格式的xml,并把json文件的数据填充到xml)。
parseJson.py
#!/usr/bin/env python
# -*- coding: utf8 -*-
#parse json,input json filename,output info needed by vocimport json
#这里是我需要的10个类别
categorys = ['car', 'bus', 'person', 'bike', 'truck', 'motor', 'train', 'rider', 'traffic sign', 'traffic light']def parseJson(jsonFile):'''params:jsonFile -- BDD00K数据集的一个json标签文件return:返回一个列表的列表,存储了一个json文件里面的方框坐标及其所属的类,形如:[[325, 342, 376, 384, 'car'], [245, 333, 336, 389, 'car']]'''objs = []obj = []f = open(jsonFile)info = json.load(f)objects = info['frames'][0]['objects']for i in objects:if(i['category'] in categorys):obj.append(int(i['box2d']['x1']))obj.append(int(i['box2d']['y1']))obj.append(int(i['box2d']['x2']))obj.append(int(i['box2d']['y2']))obj.append(i['category'])objs.append(obj)obj = []#print("objs",objs)return objs#test
#result = parseJson("/media/xavier/SSD256/global_datasets/BDD00K/bdd100k/labels/100k/val/b1c9c847-3bda4659.json")
#print(len(result))
#print(result)
pascal_voc_io.py`
#!/usr/bin/env python
# -*- coding: utf8 -*-
import sys
import os
from xml.etree import ElementTree
from xml.etree.ElementTree import Element, SubElement
from lxml import etree
from xml.dom.minidom import parseStringclass PascalVocWriter:def __init__(self, foldername, filename, imgSize, databaseSrc='Unknown', localImgPath=None):'''params:foldername -- 要存储的xml文件的父目录filename -- xml文件的文件名imgSize -- 图片的尺寸databaseSrc -- 数据库名,这里不需要,默认为UnknownlocalImaPath -- xml文件里面的<path></path>标签的内容'''self.foldername = foldernameself.filename = filenameself.databaseSrc = databaseSrcself.imgSize = imgSizeself.boxlist = []self.localImgPath = localImgPathdef prettify(self, elem):"""params:elem -- xml的根标签,以<annotation>开始return:返回一个美观输出的xml(用到minidom),本质是一个str"""xml = ElementTree.tostring(elem)dom = parseString(xml)
# print(dom.toprettyxml(' '))prettifyResult = dom.toprettyxml(' ')return prettifyResultdef genXML(self):"""return:生成一个VOC格式的xml,返回一个xml的根标签,以<annotation>开始"""# Check conditionsif self.filename is None or \self.foldername is None or \self.imgSize is None or \len(self.boxlist) <= 0:return Nonetop = Element('annotation') # 创建一个根标签<annotation>folder = SubElement(top, 'folder') # 在根标签<annotation>下创建一个子标签<folder>folder.text = self.foldername # 用self.foldername的数据填充子标签<folder>filename = SubElement(top, 'filename') # 在根标签<annotation>下创建一个子标签<filename>filename.text = self.filename # 用self.filename的数据填充子标签<filename>localImgPath = SubElement(top, 'path') # 在根标签<annotation>下创建一个子标签<path>localImgPath.text = self.localImgPath # 用self.localImgPath的数据填充子标签<path>source = SubElement(top, 'source') # 在根标签<annotation>下创建一个子标签<source>database = SubElement(source, 'database') # 在根标签<source>下创建一个子标签<database>database.text = self.databaseSrc # 用self.databaseSrc的数据填充子标签<database>size_part = SubElement(top, 'size') # 在根标签<annotation>下创建一个子标签<size>width = SubElement(size_part, 'width') # 在根标签<size>下创建一个子标签<width>height = SubElement(size_part, 'height') # 在根标签<size>下创建一个子标签<height>depth = SubElement(size_part, 'depth') # 在根标签<size>下创建一个子标签<depth>width.text = str(self.imgSize[1]) # 用self.imgSize[1]的数据填充子标签<width>height.text = str(self.imgSize[0]) # 用self.imgSize[0]的数据填充子标签<height>if len(self.imgSize) == 3: # 如果图片深度为3,则用self.imgSize[2]的数据填充子标签<height>,否则用1填充depth.text = str(self.imgSize[2])else:depth.text = '1'segmented = SubElement(top, 'segmented')segmented.text = '0'return topdef addBndBox(self, xmin, ymin, xmax, ymax, name):'''将检测对象框坐标及其对象类别作为一个字典加入到self.boxlist中params:xmin -- 检测框的左上角的x坐标ymin -- 检测框的左上角的y坐标xmax -- 检测框的右下角的x坐标ymax -- 检测框的右下角的y坐标name -- 检测框内的对象类别名'''bndbox = {'xmin': xmin, 'ymin': ymin, 'xmax': xmax, 'ymax': ymax}bndbox['name'] = nameself.boxlist.append(bndbox)def appendObjects(self, top):'''在xml文件中加入检测框的坐标及其对象类别名params:top -- xml的根标签,以<annotation>开始'''for each_object in self.boxlist:object_item = SubElement(top, 'object')name = SubElement(object_item, 'name')name.text = str(each_object['name'])pose = SubElement(object_item, 'pose')pose.text = "Unspecified"truncated = SubElement(object_item, 'truncated')truncated.text = "0"difficult = SubElement(object_item, 'Difficult')difficult.text = "0"bndbox = SubElement(object_item, 'bndbox')xmin = SubElement(bndbox, 'xmin')xmin.text = str(each_object['xmin'])ymin = SubElement(bndbox, 'ymin')ymin.text = str(each_object['ymin'])xmax = SubElement(bndbox, 'xmax')xmax.text = str(each_object['xmax'])ymax = SubElement(bndbox, 'ymax')ymax.text = str(each_object['ymax'])def save(self, targetFile=None):'''以美观输出的xml格式来保存xml文件params:targetFile -- 存储的xml文件名,不包括.xml部分'''root = self.genXML()self.appendObjects(root)out_file = Nonesubdir = self.foldername.split('/')[-1]if not os.path.isdir(subdir):os.mkdir(subdir)if targetFile is None:with open(self.foldername+'/'+self.filename + '.xml', 'w') as out_file:prettifyResult = self.prettify(root)out_file.write(prettifyResult)out_file.close()else:with open(targetFile, 'w') as out_file:prettifyResult = self.prettify(root)out_file.write(prettifyResult)out_file.close()class PascalVocReader:def __init__(self, filepath):# shapes type:# [labbel, [(x1,y1), (x2,y2), (x3,y3), (x4,y4)], color, color]self.shapes = []self.filepath = filepathself.parseXML()def getShapes(self):return self.shapesdef addShape(self, label, bndbox):xmin = int(bndbox.find('xmin').text)ymin = int(bndbox.find('ymin').text)xmax = int(bndbox.find('xmax').text)ymax = int(bndbox.find('ymax').text)points = [(xmin, ymin), (xmax, ymin), (xmax, ymax), (xmin, ymax)]self.shapes.append((label, points, None, None))def parseXML(self):assert self.filepath.endswith('.xml'), "Unsupport file format"parser = etree.XMLParser(encoding='utf-8')xmltree = ElementTree.parse(self.filepath, parser=parser).getroot()filename = xmltree.find('filename').textfor object_iter in xmltree.findall('object'):bndbox = object_iter.find("bndbox")label = object_iter.find('name').textself.addShape(label, bndbox)return True# tempParseReader = PascalVocReader('test.xml')
# print tempParseReader.getShapes()
#"""
# Test
#tmp = PascalVocWriter('temp','test', (10,20,3))
#tmp.addBndBox(10,10,20,30,'chair')
#tmp.addBndBox(1,1,600,600,'car')
#tmp.save()
#"""
其次,我们创建一个脚本bdd2voc.py将两个辅助脚本整合起来。
bdd2voc.py
# -*- coding: utf8 -*-
import os
import pascal_voc_io
import parseJsondef main(srcDir, dstDir):i = 1# os.walk()# dirName是你所要遍历的目录的地址, 返回的是一个三元组(root,dirs,files)# root所指的是当前正在遍历的这个文件夹的本身的地址# dirs是一个 list ,内容是该文件夹中所有的目录的名字(不包括子目录)# files 同样是 list , 内容是该文件夹中所有的文件(不包括子目录)for dirpath, dirnames, filenames in os.walk(srcDir):
# print(dirpath, dirnames, filenames)for filepath in filenames:fileName = os.path.join(dirpath,filepath)print(fileName)print("processing: {}, {}".format(i, fileName))i = i + 1xmlFileName = filepath[:-5] # remove ".json" 5 character# 解析该json文件,返回一个列表的列表,存储了一个json文件里面的所有方框坐标及其所属的类objs = parseJson.parseJson(str(fileName)) # 如果存在检测对象,创建一个与该json文件具有相同名的VOC格式的xml文件if len(objs):tmp = pascal_voc_io.PascalVocWriter(dstDir, xmlFileName, (720,1280,3), fileName)for obj in objs:tmp.addBndBox(obj[0],obj[1],obj[2],obj[3],obj[4])tmp.save()else:print(fileName)if __name__ == '__main__':# test# these paths should be your own path
# srcDir = '/media/xavier/SSD256/global_datasets/BDD00K/bdd100k/labels/100k/val'
# dstDir = '/media/xavier/SSD256/global_datasets/BDD00K/bdd100k/Annotations/val'srcDir = '/media/xavier/SSD256/global_datasets/BDD00K/bdd100k/labels/100k/train'dstDir = '/media/xavier/SSD256/global_datasets/BDD00K/bdd100k/Annotations/train'main(srcDir, dstDir)
运行脚本bdd2voc.py,将会在指定目录下生成xml标签)
使用YOLOv3训练BDD100K数据集之标签格式转换相关推荐
- BDD100K数据集转YOLO格式
前言 BDD100K由伯克利大学AI实验室(BAIR)发布,是目前最大规模.内容最具多样性的公开驾驶数据集.BDD100K 数据集包含10万段高清视频,每个视频约40秒,720p,30 fps .每个 ...
- WIN10 +pytorch版yolov3训练自己数据集
pytorch版yolov3训练自己数据集 目录 1. 环境搭建 2. 数据集构建 3. 训练模型 4. 测试模型 5. 评估模型 6. 可视化 7. 高级进阶-网络结构更改 1. 环境搭建 将git ...
- yolov3 训练及数据集准备【记录】
------------------------------ 本文仅供学习交流,如有错误,望交流指教 ------------------------------ yolov3 训练及数据集准备[记录 ...
- Yolov5-5.0源码分享以及环境配置——Yolov5训练及测试教程(超详细含数据集制作,格式转换,数据集划分)
yolov5-5.0百度网盘连接 链接: https://pan.baidu.com/s/1Hd2KKBixuEWRv3jcH6Bcsw 提取码: g6xf 复制这段内容后打开百度网盘手机App,操作 ...
- mmdetection实战,训练扑克牌数据集(VOC格式)并测试计算mAP
mmdetection实战,训练扑克牌数据集(VOC格式)并测试计算mAP 一.数据集准备 二.mmdetection的安装 三.修改相关文件 1. 修改class_names.py文件 2. 修改v ...
- 使用YOLOV7训练BDD100K数据集(数据格式转化+训练全流程)
目录 1. 前言 1.1 BDD100K数据集详细介绍(此节可跳过) 1.2 BDD100K数据集简要介绍 1.3 下载必要文件 2. bdd100k转yolo数据集格式 2.1 为什么要转格式 2. ...
- HRSID舰船检测数据集标签格式转换,json转为xml
HRSID数据集介绍参考原文:https://ieeexplore.ieee.org/document/9127939 数据集下载链接:https://github.com/chaozhong2010 ...
- (官方步骤)YOLO-V3训练VOC数据集
前提:编译好darknet,教程参考本人链接:https://blog.csdn.net/qq_34806812/article/details/81167836 开始: darknet目录下新建VO ...
- 行人检测-Caltech Pedestrian Dataset 数据集下载及格式转换
Caltech Pedestrian Dataset 数据集 加理工(caltech)提供的数据集, 该数据集主要包括 训练集+测试集:seq格式的数据: 行人标签数据:vbb(video bound ...
最新文章
- Iphone 指触行为会
- Linux使用错误小结(CentOS)- yum更新软件失败
- 前端学习(1432):模板引擎概述
- 某储云商城系统源码V1.782 绿色版
- 【开发工具】之source insight 4常用设置
- 速修复!开源 IT 基础设施管理解决方案 Salt 被曝多个严重漏洞
- 数据集:科研经费投入对生产能力提高的影响
- 计算机病毒与恶意代码期末总结
- 人大金仓数据库Docker部署
- Linux内核API手册——简略版
- java数据结构与算法之栈(Stack)设计与实现
- 激光雷达+imu_激光雷达slam-激光点云畸变补偿
- warning CS0108: `___' hides inherited member `___'. Use the new keyword if hiding was intended解决办法
- ​复盘共享经济2020:陷入艰难求生困境,转型能否拯救亏损怪圈
- 如何从初级程序员顺利晋升到高级程序员?
- vue中实现输入字数限制
- jxls对比_久别重逢 QQ影音4.0跟旧版对比更新了什么?
- 第二章 2.1 机器视觉——图像《2022年斯坦福AI指数报告》中文全解读
- Java Swing实现仿win7计算器
- 星策社区发起人谭中意:用开源方式推进企业智能化转型