VOC数据集格式转化成COCO数据集格式

                  VOC数据集格式转化成COCO数据集格式
一、唠叨
     之前写过一篇关于coco数据集转化成VOC格式的博客COCO2VOC,最近读到CenterNet的官方代码,实现上则是将voc转化成coco数据格式,这样的操作我个人感觉很不习惯,也觉得有些奇葩,可能是每个人习惯不一样吧,我们知道有时候我们会采用labelImg标注数据,标注出来的格式就是voc,如果直接训练就可以用来训练是不是更加友好。

     为了不大规模修改原始训练代码(虽然自己修改了一个版本的voc数据集就能直接训练centernet 😊),同时也看到网上很多大佬也做了将VOC数据格式转化成COCO用于其训练,这里我自己做一个精细一点的,作为笔记。

二、转化过程
   数据格式的转换实际是annotation标注文件的转化,voc的数据标注文件为以.xml结尾的文件,而且每张图片均有一个对应的同名标注文件;COCO则是将所有的标注信息写在一个json文件中。VOC数据集目录如下:

    在之前的coco2voc博客中做了详细的介绍,现在直接开始转化,目标就是将Annotations中的所有标注文件中的bbox标注信息转化为json文件,根据训练集和测试集,则主要转化为四个json文件,分别是test.json、train.json、val.json和trainval.json .这里我根据ImageSets中的train.txt val.txt trainval.txt生成后三个json文件,当然也可以直接从Annotations文件夹生成。

VOC2COCO.pyimport xml.etree.ElementTree as ET
import os
import jsoncoco = dict()
coco['images'] = []
coco['type'] = 'instances'
coco['annotations'] = []
coco['categories'] = []category_set = dict()
image_set = set()category_item_id = -1
image_id = 20180000000
annotation_id = 0def addCatItem(name):global category_item_idcategory_item = dict()category_item['supercategory'] = 'none'category_item_id += 1category_item['id'] = category_item_idcategory_item['name'] = namecoco['categories'].append(category_item)category_set[name] = category_item_idreturn category_item_iddef addImgItem(file_name, size):global image_idif file_name is None:raise Exception('Could not find filename tag in xml file.')if size['width'] is None:raise Exception('Could not find width tag in xml file.')if size['height'] is None:raise Exception('Could not find height tag in xml file.')image_id += 1image_item = dict()image_item['id'] = image_idimage_item['file_name'] = file_nameimage_item['width'] = size['width']image_item['height'] = size['height']coco['images'].append(image_item)image_set.add(file_name)return image_iddef addAnnoItem(object_name, image_id, category_id, bbox):global annotation_idannotation_item = dict()annotation_item['segmentation'] = []seg = []# bbox[] is x,y,w,h# left_topseg.append(bbox[0])seg.append(bbox[1])# left_bottomseg.append(bbox[0])seg.append(bbox[1] + bbox[3])# right_bottomseg.append(bbox[0] + bbox[2])seg.append(bbox[1] + bbox[3])# right_topseg.append(bbox[0] + bbox[2])seg.append(bbox[1])annotation_item['segmentation'].append(seg)annotation_item['area'] = bbox[2] * bbox[3]annotation_item['iscrowd'] = 0annotation_item['ignore'] = 0annotation_item['image_id'] = image_idannotation_item['bbox'] = bboxannotation_item['category_id'] = category_idannotation_id += 1annotation_item['id'] = annotation_idcoco['annotations'].append(annotation_item)def _read_image_ids(image_sets_file):ids = []with open(image_sets_file) as f:for line in f:ids.append(line.rstrip())return ids"""通过txt文件生成"""
#split ='train' 'va' 'trainval' 'test'
def parseXmlFiles_by_txt(data_dir,json_save_path,split='train'):print("hello")labelfile=split+".txt"image_sets_file = data_dir + "/ImageSets/Main/"+labelfileids=_read_image_ids(image_sets_file)for _id in ids:xml_file=data_dir + f"/Annotations/{_id}.xml"bndbox = dict()size = dict()current_image_id = Nonecurrent_category_id = Nonefile_name = Nonesize['width'] = Nonesize['height'] = Nonesize['depth'] = Nonetree = ET.parse(xml_file)root = tree.getroot()if root.tag != 'annotation':raise Exception('pascal voc xml root element should be annotation, rather than {}'.format(root.tag))# elem is <folder>, <filename>, <size>, <object>for elem in root:current_parent = elem.tagcurrent_sub = Noneobject_name = Noneif elem.tag == 'folder':continueif elem.tag == 'filename':file_name = elem.textif file_name in category_set:raise Exception('file_name duplicated')# add img item only after parse <size> tagelif current_image_id is None and file_name is not None and size['width'] is not None:if file_name not in image_set:current_image_id = addImgItem(file_name, size)print('add image with {} and {}'.format(file_name, size))else:raise Exception('duplicated image: {}'.format(file_name))# subelem is <width>, <height>, <depth>, <name>, <bndbox>for subelem in elem:bndbox['xmin'] = Nonebndbox['xmax'] = Nonebndbox['ymin'] = Nonebndbox['ymax'] = Nonecurrent_sub = subelem.tagif current_parent == 'object' and subelem.tag == 'name':object_name = subelem.textif object_name not in category_set:current_category_id = addCatItem(object_name)else:current_category_id = category_set[object_name]elif current_parent == 'size':if size[subelem.tag] is not None:raise Exception('xml structure broken at size tag.')size[subelem.tag] = int(subelem.text)# option is <xmin>, <ymin>, <xmax>, <ymax>, when subelem is <bndbox>for option in subelem:if current_sub == 'bndbox':if bndbox[option.tag] is not None:raise Exception('xml structure corrupted at bndbox tag.')bndbox[option.tag] = int(option.text)# only after parse the <object> tagif bndbox['xmin'] is not None:if object_name is None:raise Exception('xml structure broken at bndbox tag')if current_image_id is None:raise Exception('xml structure broken at bndbox tag')if current_category_id is None:raise Exception('xml structure broken at bndbox tag')bbox = []# xbbox.append(bndbox['xmin'])# ybbox.append(bndbox['ymin'])# wbbox.append(bndbox['xmax'] - bndbox['xmin'])# hbbox.append(bndbox['ymax'] - bndbox['ymin'])print('add annotation with {},{},{},{}'.format(object_name, current_image_id, current_category_id,bbox))addAnnoItem(object_name, current_image_id, current_category_id, bbox)json.dump(coco, open(json_save_path, 'w'))"""直接从xml文件夹中生成"""
def parseXmlFiles(xml_path,json_save_path):for f in os.listdir(xml_path):if not f.endswith('.xml'):continuebndbox = dict()size = dict()current_image_id = Nonecurrent_category_id = Nonefile_name = Nonesize['width'] = Nonesize['height'] = Nonesize['depth'] = Nonexml_file = os.path.join(xml_path, f)print(xml_file)tree = ET.parse(xml_file)root = tree.getroot()if root.tag != 'annotation':raise Exception('pascal voc xml root element should be annotation, rather than {}'.format(root.tag))# elem is <folder>, <filename>, <size>, <object>for elem in root:current_parent = elem.tagcurrent_sub = Noneobject_name = Noneif elem.tag == 'folder':continueif elem.tag == 'filename':file_name = elem.textif file_name in category_set:raise Exception('file_name duplicated')# add img item only after parse <size> tagelif current_image_id is None and file_name is not None and size['width'] is not None:if file_name not in image_set:current_image_id = addImgItem(file_name, size)print('add image with {} and {}'.format(file_name, size))else:raise Exception('duplicated image: {}'.format(file_name))# subelem is <width>, <height>, <depth>, <name>, <bndbox>for subelem in elem:bndbox['xmin'] = Nonebndbox['xmax'] = Nonebndbox['ymin'] = Nonebndbox['ymax'] = Nonecurrent_sub = subelem.tagif current_parent == 'object' and subelem.tag == 'name':object_name = subelem.textif object_name not in category_set:current_category_id = addCatItem(object_name)else:current_category_id = category_set[object_name]elif current_parent == 'size':if size[subelem.tag] is not None:raise Exception('xml structure broken at size tag.')size[subelem.tag] = int(subelem.text)# option is <xmin>, <ymin>, <xmax>, <ymax>, when subelem is <bndbox>for option in subelem:if current_sub == 'bndbox':if bndbox[option.tag] is not None:raise Exception('xml structure corrupted at bndbox tag.')bndbox[option.tag] = int(option.text)# only after parse the <object> tagif bndbox['xmin'] is not None:if object_name is None:raise Exception('xml structure broken at bndbox tag')if current_image_id is None:raise Exception('xml structure broken at bndbox tag')if current_category_id is None:raise Exception('xml structure broken at bndbox tag')bbox = []# xbbox.append(bndbox['xmin'])# ybbox.append(bndbox['ymin'])# wbbox.append(bndbox['xmax'] - bndbox['xmin'])# hbbox.append(bndbox['ymax'] - bndbox['ymin'])print('add annotation with {},{},{},{}'.format(object_name, current_image_id, current_category_id,bbox))addAnnoItem(object_name, current_image_id, current_category_id, bbox)json.dump(coco, open(json_save_path, 'w'))if __name__ == '__main__':#通过txt文件生成# voc_data_dir="E:/VOCdevkit/VOC2007"# json_save_path="E:/VOCdevkit/voc2007trainval.json"# parseXmlFiles_by_txt(voc_data_dir,json_save_path,"trainval")#通过文件夹生成ann_path="E:/VOCdevkit/VOC2007/Annotations"json_save_path="E:/VOCdevkit/test.json"parseXmlFiles(ann_path,json_save_path)

 生成之后就是这样:

到此就结束了,提供两个关键函数,一个是通过txt,另一个使用过文件夹,然后就可以用于centernet训练了,或者也可以用于其他的算法数据准备。

任何程序错误,以及技术疑问或需要解答的,请添加

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/547017.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

react native android6+拍照闪退或重启的解决方案

前言 android 6权限使用的时候需要动态申请&#xff0c;那么在使用rn的时候要怎么处理拍照权限问题呢&#xff1f;本文提供的是一揽子rn操作相册、拍照的解决方案&#xff0c;请看正文的提高班部分。 解决步骤 1、AndroidManifest.xml设置拍照权限&#xff1a; <uses-perm…

学术论文SCI、期刊、毕业设计中的图表专用软件

Origin Origin是由OriginLab公司开发的一个科学绘图、数据分析软件&#xff0c;支持在Microsoft Windows下运行。Origin支持各种各样的2D/3D图形。Origin中的数据分析功能包括统计&#xff0c;信号处理&#xff0c;曲线拟合以及峰值分析。 Origin中的曲线拟合是采用基于Lever…

常用的学术论文图表(折线图、柱状图)matplotlib python代码模板

最终选用了pythonMatplotlib。Matplotlib是著名Python的标配画图包&#xff0c;其绘图函数的名字基本上与 Matlab 的绘图函数差不多。优点是曲线精致&#xff0c;软件开源免费&#xff0c;支持Latex公式插入&#xff0c;且许多时候只需要一行或几行代码就能搞定。 然后小编经过…

史上最详细nodejs版本管理器nvm的安装与使用(附注意事项和优化方案)

使用场景 在Node版本快速更新迭代的今天&#xff0c;新老项目使用的node版本号可能已经不相同了&#xff0c;node版本更新越来越快&#xff0c;项目越做越多&#xff0c;node切换版本号的需求越来越迫切&#xff0c;传统卸载一个版本在安装另一个版本的方式太过于麻烦&#xf…

【TensorFlow】 基于视频时序LSTM的行为动作识别

简介 本文基于LSTM来完成用户行为识别。数据集来源&#xff1a;https://archive.ics.uci.edu/ml/machine-learning-databases/00240/ 此数据集一共有6种行为状态&#xff1a; 行走&#xff1b; 站立&#xff1b; 躺下&#xff1b; 坐下&#xff1b; 上楼&#xff1b; 下楼&am…

利用Asp.net MVC处理文件的上传下载

如果你仅仅只有Asp.net Web Forms背景转而学习Asp.net MVC的&#xff0c;我想你的第一个经历或许是那些曾经让你的编程变得愉悦无比的服务端控件都驾鹤西去了.FileUpload就是其中一个&#xff0c;而这个控件的缺席给我们带来一些小问题。这篇文章主要说如何在Asp.net MVC中上传…

Python遍历文件夹下所有文件及目录

遍历文件夹中的所有子文件夹及子文件使用os.walk()方法非常简单。 语法格式大致如下&#xff1a; os.walk(top[, topdownTrue[, onerrorNone[, followlinksFalse]]]) top – 根目录下的每一个文件夹(包含它自己), 产生3-元组 (dirpath, dirnames, filenames)【文件夹路径, 文…

华为交换机telnet和ftp服务开启/关闭命令

1.telnet开启/关闭 在系统视图下 启用方式如下&#xff1a; telnet server enable //使能telnet服务关闭方式如下&#xff1a; undo telnet server //关闭telnet服务2.FTP开启/关闭 通过display ftp-server查看启用状态 如果已经启用&#xff0c;会在查看的命令中显示&#…

为什么用Spring来管理Hibernate?

为什么用Spring来管理Hibernate&#xff1f;为什么要用Hibernate框架&#xff1f;这个在《Hibernate介绍》博客中已经提到了。既然用Hibernate框架访问管理持久层&#xff0c;那为何又提到用Spring来管理以及整合Hibernate呢&#xff1f;首先我们来看一下Hibernate进行操作的步…

Python-Pandas之两个Dataframe的差异比较

昨天在外网找到一个比较dataframe的好库&#xff0c;叫datacompy&#xff0c;它的优点有&#xff1a; 1、可以把对比后的信息详情打印出来&#xff0c;比如列是否相等&#xff0c;行是否相等&#xff1b; 2、在数据中如果有不相等列&#xff0c;那么就只比较相同的列&#xf…

华为交换机如何通过tftp服务器上传下载文件

温馨提示:为了防止更新交换机配置文件操作失败,操作前交换机配置文件一定要做备份,可以通过copy vrpcfg.zip vrpcfg_backup.zip 工具/原料: windows电脑: Tftpd64 SecureCRT USB转串口,串口转RJ45 console线 2米网线 华为交换机S3700一台 方法/步骤: 1.准备材料,按照下…

js节流函数和js防止重复提交的N种方法

应用情景 经典使用情景&#xff1a;js的一些事件&#xff0c;比如&#xff1a;onresize、scroll、mousemove、mousehover等&#xff1b; 还比如&#xff1a;手抖、手误、服务器没有响应之前的重复点击&#xff1b; 这些都是没有意义的&#xff0c;重复的无效的操作&#xff…

使用IPFS集群搭建创建私有IPFS网络

基本介绍 IPFS 网络分两类: 公有私有 对于大多数商用应用尤其是企业级解决方案而言&#xff0c;需要对自身数据有完全的控制&#xff0c;这种场合公有IPFS网络并不适用&#xff0c;搭建私有IPFS往往是这类应用的必要需求。 本文我们讲解创建一个私有 IPFS 网络的过程&#xf…

MongoDB基础介绍安装与使用

MongoDB已经日益成为流程和主流的数据库了&#xff0c;原因有两个&#xff1a;第一个就是技术优势&#xff0c;第二就是便利性&#xff0c;个人使用部署都很方便。 MongoDB的优缺点&#xff0c;以及使用场景 优点&#xff1a; 面向文档存储&#xff08;自由读高&#xff0c;…

python调用cv2.findContours时报错:ValueError: not enough values to unpack (expected 3, got 2)

python调用cv2.findContours时报错&#xff1a;ValueError: not enough values to unpack (expected 3, got 2) OpenCV旧版&#xff0c;返回三个参数&#xff1a; im2, contours, hierarchy cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) 要想返回三个参数…

优先级队列用的的数据结构

2019独角兽企业重金招聘Python工程师标准>>> 优先级队列和队列没有本质的区别 只是 每次出队列的时候出队列中优先级最高的 这里假定数字越小&#xff0c;优先级越高 优先级队列 是不同于先进先出队列的另一种队列。每次从队列中取出的是具有最高优先权的元素。 通…

公网访问阿里云数据库MongoDB——填坑笔记

业务情景 两台服务器&#xff0c;一台阿里云ECS云服务器&#xff08;专用网络&#xff09;&#xff0c;另一台是阿里云数据库MongoDB&#xff0c;处于安全考虑MongoDB是不运行外网连接的&#xff0c;那接下来就看怎么实现公网访问。 看到上面红色的网络类型描述&#xff0c;有…

华为S5700交换机开启telnet远程登陆配置(推荐)

实验目标: 电脑PC1经过S3700交换机,telnet远程登录到S5700交换机。 连接拓扑图如下:(测试时用实物测试) 一、配置S5700交换机。 1.交换机开启Telnet服务 <Huawei>system-view Enter system view, return user view with Ctrl+Z. [Huawei]sysname LSW1 [LSW1]

2021最新Python量化A股投资必赚策略

一、板块信息&#xff1a; 1、每隔30分钟后台自动采集一个开盘啦的板块信息&#xff08;9:15开始到15:00是股票开市时间&#xff0c;如果15点以后已经采集过数据&#xff0c;就不需要重复采集&#xff0c;避免频繁采集被网站屏蔽&#xff09;。按照codelist.txt列表&#xff0…

Ubuntu安装设置nginx和nohup常用操作

nginx安装 Ubuntu直接从常规源中安装 apt-get install nginx 安装的目录 配置文件&#xff1a;/etc/nginx/主程序文件&#xff1a;/usr/sbin/nginxWeb默认目录&#xff1a;/usr/share/nginx/http/日志目录&#xff1a;/var/log/nginx/ nginx常用命令 1、启动/停止nginx服务 1…