数据集中如何将yaml后缀的变成VOC数据集格式xml教学,通过交通红绿灯Lara3D数据集为例。

文章介绍了如何将yaml格式的数据转换为VOC标准的XML格式,用于目标检测任务。提供了数据集的下载链接,详细解释了yaml格式中坐标的含义,并展示了转换前后的格式差异。接着,给出了Python代码示例,说明了代码的执行流程,包括读取yaml文件、创建XML结构并填充信息,最后保存为XML文件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.数据集分享

首先分享这个数据集,已经分好了,图片和xml。

下载地址
链接:https://pan.quark.cn/s/0ea548c4dcfb
提取码:mZGz
Green3004
Yellow54
Red4757

一共5340张图片,上面表格是图片数据分散情况。

2.将yaml格式转化成正常的VOC格式xml

首先我们来看看yaml格式是什么样子的,如下图1所示。

 图1 yaml格式

下图2所示是转换后的xml格式

 图2 xml格式

首先我们来分析一下yaml格式的文件,其中有类别、一个坐标和检测框的长宽。这里的坐标什么意思呢,就可以看下图3所示。

 图3 图像在电脑中的坐标

图1中的的坐标(xmin,ymin)就是一个图片在这个坐标系中,左上角坐标。比如说一个图片以原点(0,0)点进行绘画,那么其左上角坐标就是(0,0)。

ps:这个坐标跟数学上的有点不一样,y是向下的,x是向右边。

现在我们有了最小坐标,还有了长宽,就可以求出最大坐标,也就是右下角的坐标。如下图4所示,知道了最小坐标D(x,y),也知道了长宽,就可以求出最大坐标也就是D2(x+w,y+h)

 图4坐标

这里求出两个坐标也就可以写道了xml文件中了。

 3.代码

首先我们来看一下xml的格式,在图2中,可以分为以下这样的分支:

 一个xml的分支大概就这样,这些数据对于目标检测任务来说已经足够了。

我们程序要做的就是先创建这样一个分支,然后再把信息填进去就完成了。

ps:解释一下这里面都是什么意思:

filename图片的名称非常重要,网络在进行读取数据的时候,每一个batchsize读取的内容就包含了图片名字。

size:图片的长宽,一般知道了图片的名字,程序就可以去读取图片,通过PIL或者opencv函数就可以读取图片的长宽,有的程序里说不定就直接读取xml文件里的长宽,所以也非常重要,一般是用于图片等比缩放,填充使用。

object:就是你真实检测框的位置,label标签。

程序流程:

图1中可以看出,所有信息都是以annotations为一组分开的,程序里我们只需要读取了yaml文件,然后再写一个for循环就可以读取每一个annotations的信息。

读取了每一个annotations的信息,就往生成的xml里面填内容就好了,下面是整个代码,里面都有注释。

import PIL.Image
import yaml
import xml.etree.ElementTree as ET
import os
pic_position=r'B:\software\deeplearning\hhh123\redgreenlight\Lara3D\Lara3D_UrbanSeq1_JPG'
#这上面是图片的地址,主要用来读取图片的长宽的,写到xml文件中
yaml_position=r'B:\software\deeplearning\hhh123\redgreenlight\Lara3D\ggg.yaml'
#这里是yaml的地址
output_dir=r'B:\software\deeplearning\hhh123\redgreenlight\Lara3D\ss'
#这里是输出的空文件夹,主要放生成的xml的

def convert_yaml_to_xml(yaml_position,output_dir):
    with open(yaml_position,'r') as f:
        data=yaml.safe_load(f) #这里是读取了yaml文件,里面包含了所有的annocations的信息

    for i,entry in enumerate(data): #yaml里面的信息一个一个读取出来然后放到xml文件中
        root=ET.Element('annotation')#创建annotation这个大分枝,然后下面就创建每一个小分支

        filename=ET.SubElement(root,'filename')#ET.Element是创建大分支,SubElement创建小分支,注意前面是root和关键,后面的'filename'是分支的名字!前面图片里有
        filename.text=entry['filename'].split('/',1)[1] #这里我先读取了yaml每个annocations中的filename,也就是图片名称,这里要与你自己的yaml文件里标签文件一样'filename'这个。
#这里还用了.split主要是因为yaml里面那个filename不只有图片名字,还有其他的所以我要删除了,就留下一个图片的名字

        size=ET.SubElement(root,'size')#再annotation大分支下,创建小分支size

        width=ET.SubElement(size,'width')#在size分支下面创建三个小分支分别是w,h,d
        height=ET.SubElement(size,'height')
        depth=ET.SubElement(size,'depth')
        pic_dir=os.path.join(pic_position,filename.text)#这里是读取单个图片的路径
        pic=PIL.Image.open(pic_dir)
        width.text=str(pic.size[0])#这里读取图片的长宽,并写到分支中
        height.text=str(pic.size[1])#同上
        depth.text=str(3)#同上

        for i in entry['annotations']: #这里可以这么理解每一个yaml中单独annocations也有三个分支分别是annotations、class、filename然后annotations里面又有分支,也就是entry这里有三个分支,就前面的,然后要读取annotations所以就写成这样
            object=ET.SubElement(root,'object')#跟上面一样在root建立object的分支
            name=ET.SubElement(object,'name')#在object中建立小分支
            name.text=i['class']#填充类别进去

            bndbox=ET.SubElement(object,'bndbox')#在object中建立bndbox的分支
            xmin=ET.SubElement(bndbox,'xmin')#在bndbox中建立坐标分支
            ymin=ET.SubElement(bndbox,'ymin')
            xmax=ET.SubElement(bndbox,'xmax')
            ymax=ET.SubElement(bndbox,'ymax')
            xmin.text=str(i['xmin'])#输入坐标信息
            ymin.text=str(i['ymin'])
            xmax.text=str(i['xmin']+i['x_width'])
            ymax.text=str(i['ymin']+i['y_height'])

        tree=ET.ElementTree(root)#写入到xml文件中
        new_name=filename.text.split('.')[0]
        output_dir=f'{output_dir}/{new_name}.xml'#xml文件保存的详细地址
        tree.write(output_dir)#写入xml文件并保存生成xml


if __name__ == '__main__':
    k=convert_yaml_to_xml(yaml_position,output_dir)

具体的方法就如上所示,大家可以根据自己的yaml文件内容来进行修改,如果有不同的地方可以进行私聊或者评论

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值