深度学习必备知识——模型数据集Yolo与Voc格式文件相互转化

在深度学习中,第一步要做的往往就是处理数据集,尤其是学习百度飞桨PaddlePaddle的小伙伴,数据集经常要用Voc格式的,比如性能突出的ppyolo等模型。所以学会数据集转化的本领是十分必要的。这篇博客就带你一起进行Yolo与Voc格式的相互转化,附详细代码!

文章目录

  • YOLO数据集介绍
  • VOC数据集介绍
  • Yolo转VOC
  • VOC转Yolo
  • from lxml import etree
  • classes=["ball"]

YOLO数据集介绍

Yolo数据集主要是txt文件,一般包括train文件夹和val文件夹,每一个文件夹下有与图片同名的txt文件,基本结构如下:
在这里插入图片描述
|–image

  • ||–train
  • ||–val

|–label

  • ||–train
  • ||–val

txt的标签如下图所示:

在这里插入图片描述
第一列为目标类别,后面四个数字为方框左上角与右下角的坐标,可以看到都是小于1的数字,是因为对应的整张图片的比例,所以就算图像被拉伸放缩,这种txt格式的标签也可以找到相应的目标。

VOC数据集介绍

VOC格式数据集一般有着如下的目录结构:

VOC_ROOT     #根目录
    ├── JPEGImages         # 存放源图片
    │     ├── aaaa.jpg     
    │     ├── bbbb.jpg  
    │     └── cccc.jpg
    ├── Annotations        # 存放xml文件,与JPEGImages中的图片一一对应,解释图片的内容等等
    │     ├── aaaa.xml 
    │     ├── bbbb.xml 
    │     └── cccc.xml 
    └── ImageSets          
        └── Main
          ├── train.txt    # txt文件中每一行包含一个图片的名称
          └── val.txt
 

其中JPEGImages目录中存放的是源图片的数据,(当然图片并不一定要是.jpg格式的,只是规定文件夹名字叫JPEGImages);Annotations目录中存放的是标注数据,VOC的标注是xml格式的,文件名与JPEGImages中的图片一一对应。
重点看下xml格式的标注格式:

<annotation>
    <folder>VOC_ROOT</folder>                           
    <filename>aaaa.jpg</filename>  # 文件名
    <size>                         # 图像尺寸(长宽以及通道数)                      
        <width>500</width>
        <height>332</height>
        <depth>3</depth>
    </size>
    <segmented>1</segmented>       # 是否用于分割(在图像物体识别中无所谓)
    <object>                       # 检测到的物体
        <name>horse</name>         # 物体类别
        <pose>Unspecified</pose>   # 拍摄角度,如果是自己的数据集就Unspecified
        <truncated>0</truncated>   # 是否被截断(0表示完整)
        <difficult>0</difficult>   # 目标是否难以识别(0表示容易识别)
        <bndbox>                   # bounding-box(包含左下角和右上角xy坐标)
            <xmin>100</xmin>
            <ymin>96</ymin>
            <xmax>355</xmax>
            <ymax>324</ymax>
        </bndbox>
    </object>
    <object>                       # 检测到多个物体
        <name>person</name>
        <pose>Unspecified</pose>
        <truncated>0</truncated>
        <difficult>0</difficult>
        <bndbox>
            <xmin>198</xmin>
            <ymin>58</ymin>
            <xmax>286</xmax>
            <ymax>197</ymax>
        </bndbox>
    </object>
</annotation>

Yolo转VOC

文件结构如下:

Yolo转VOC     #根目录
    ├── dataset         
    │     ├── Annotations     
    │     ├── image  
               └──image图像
    │     └── label
               └──txt文件
    ├── Yolo转VOC.py        # 代码文件

具体代码:

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Project :Yolo与VOC转化 
@File    :Yolo转Voc.py
@IDE     :PyCharm 
@Author  :咋
@Date    :2023/3/6 16:45 
"""
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标注文件
    """
    dic = {'0': "blue",  # 创建字典用来对类型进行转换
           '1': "red",  # 此处的字典要与自己的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.shape

        folder = 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子标签width
        widthcontent = xmlBuilder.createTextNode(str(Pwidth))
        width.appendChild(widthcontent)
        size.appendChild(width)  # size子标签width结束

        height = xmlBuilder.createElement("height")  # size子标签height
        heightcontent = xmlBuilder.createTextNode(str(Pheight))
        height.appendChild(heightcontent)
        size.appendChild(height)  # size子标签height结束

        depth = xmlBuilder.createElement("depth")  # size子标签depth
        depthcontent = 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 = "dataset/JPEGImages/"  # 图片所在文件夹路径,后面的/一定要带上
    txtPath = "dataset/YOLOLables/"  # txt所在文件夹路径,后面的/一定要带上
    xmlPath = "dataset/annotations/"  # xml文件保存路径,后面的/一定要带上
    makexml(picPath, txtPath, xmlPath)


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

from lxml import etree

#自己的类别
classes = [“0”, “1”,‘2’,‘3’,‘person’]

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)

#数据转换
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(‘./dataset/annotations/%s.xml’ % image_id)
out_file = open(‘./dataset/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()

work_sapce_dir = os.path.join(wd, “dataset/”)
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(work_sapce_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(work_sapce_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(yolov5_images_dir, “yolov5_train.txt”), ‘w’)
test_file = open(os.path.join(yolov5_images_dir, “yolov5_val.txt”), ‘w’)
train_file.close()
test_file.close()
train_file = open(os.path.join(yolov5_images_dir, “yolov5_train.txt”), ‘a’)
test_file = open(os.path.join(yolov5_images_dir, “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 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()

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

力扣-超过经理收入的员工

大家好&#xff0c;我是空空star&#xff0c;本篇带大家了解一道简单的力扣sql练习题。 文章目录前言一、题目&#xff1a;181. 超过经理收入的员工二、解题1.正确示范①提交SQL运行结果2.正确示范②提交SQL运行结果3.正确示范③提交SQL运行结果4.正确示范④提交SQL运行结果5.其…

Android之屏幕适配方案

在说明适配方案之前&#xff0c;我们需要对如下几个概念有所了解&#xff1a;屏幕尺寸&#xff0c;屏幕分辨率&#xff0c;屏幕像素密度。 屏幕尺寸 屏幕尺寸指屏幕的对角线的物理长度&#xff0c;单位是英寸&#xff0c;1英寸2.54厘米。 比如常见的屏幕尺寸&#xff1a;5.0、5…

组件库项目搭建

创建项目 使用pnpm create vite@latest 命令创建项目。 输入项目名,选择对应参数。 删除不需要的文件 添加pnpm-workspace.yaml 在项目根目录下创建一个pnpm-workspace.yaml文件,配置如下: packages:- demo # 存放组件示例代码- packages # packages 目录下都是组件包…

【pygame游戏】Python实现蔡徐坤大战篮球游戏【附源码】

前言 话说在前面&#xff0c;我不是小黑子~&#x1f60f; 本文章纯属技术交流~娱乐 前几天我获得了一个坤坤打篮球的游戏&#xff0c;也给大家分享一下吧~ 好吧&#xff0c;其实并不是这样的游戏&#xff0c;往下慢慢看吧。 准备工作 开发环境 Python版本&#xff1a;3.7.8 …

右值和右值引用(C++11新特性)

文章目录右值VS左值右值引用VS左值引用定义move函数左值引用&&右值引用 与 函数重载模板完美转发左值引用的意义移动构造&&移动赋值默认移动构造&&赋值右值VS左值 关于什么是右值什么是左值&#xff0c;我们是这样判断的&#xff1a; 右值&#xff1…

VSCode使用技巧,代码编写效率提升2倍以上!

VSCode是一款开源免费的跨平台文本编辑器&#xff0c;它的可扩展性和丰富的功能使得它成为了许多程序员的首选编辑器。在本文中&#xff0c;我将分享一些VSCode的使用技巧&#xff0c;帮助您更高效地使用它。 1. 插件 VSCode具有非常丰富的插件生态系统&#xff0c;通过安装插…

Python直接复制已有的venv虚拟环境以创建新的虚拟环境

Python venv创建的虚拟环境复制到其他路径&#xff0c;如何断开与原始虚拟环境的连接&#xff0c;成为一个全新的虚拟环境&#xff0c;且两个虚拟环境之间的更新互不影响&#xff1f;1.软件环境⚙️2.问题描述&#x1f50d;3.解决方法&#x1f421;3.1.方法1&#xff1a;先复制…

用Python Flask为女朋友做一个简单的网站(附可运行的源码)

&#x1f31f;所属专栏&#xff1a;献给榕榕&#x1f414;作者简介&#xff1a;rchjr——五带信管菜只因一枚&#x1f62e;前言&#xff1a;该专栏系为女友准备的&#xff0c;里面会不定时发一些讨好她的技术作品&#xff0c;感兴趣的小伙伴可以关注一下~&#x1f449;文章简介…

什么是PCB走线的3W原则

在设计PCB的时候我们会经常说到3W原则&#xff0c; 它指的是两个PCB走线它们的中心间距不小于3倍线宽&#xff0c;这个W就是PCB走线的宽度。这样做的目的主要是为了减小走线1和走线2之间的串扰&#xff0c;一般对于时钟信号&#xff0c;复位信号等一些关键信号需要遵循3W原则。…

Vue插槽理解

Vue插槽理解插槽插槽 slot又名插槽&#xff0c;vue内容分发机制&#xff0c;组件内部的模板引擎使用slot元素作为承载分发内容的出口 插槽slot是子组件的一个模板标签元素&#xff0c;而这一个元素是否显示&#xff0c;以及怎么显示是由父组件决定的 slot分为三类&#xff1a;默…

链表带环问题(详解)

&#x1f506;链表带环问题&#xff08;详解&#xff09;&#x1f506;I 给定一个链表&#xff0c;判断链表中是否有环。&#x1f506;II 给定一个链表&#xff0c;返回链表开始入环的第一个结点。 如果链表无环&#xff0c;则返回 NULL。&#x1f506;复制带随机指针的链表&am…

集成方法!

目录 关注降低variance,选择bias较小的基学习器 Bagging Stacking Random Forest 关注降低bias,选择variance较小的基学习器 Adaboost Boosting 关注降低variance,选择bias较小的基学习器 Bagging 给定m个样本的数据集&#xff0c;利用有放回的随机采样法&#xff0c;得…

【Linux】操作系统(Operator System)

操作系统&#xff08;Operator System &#xff09;一、操作系统的概念二、操作系统的作用三、系统调用和库函数一、操作系统的概念 操作系统是一组控制和管理计算机软硬件资源&#xff0c;为用户提供便捷使用的计算机程序的集合&#xff0c;是配置在计算机硬件系统上的第一层…

模拟实现字符串有关函数(详细讲解)

在编写程序时&#xff0c;我们都喜欢写出简便并且效率高的代码&#xff0c;那么此时库函数中的有些函数就是我们的不二之选&#xff0c;那么&#xff0c;大家汇米你实现吗&#xff1f;下面就先从我们最简单的字符串函数说起&#xff1a; 1.strlen 这个是函数的格式&#xff0c…

做了个springboot接口参数解密的工具,我给它命名为万能钥匙(已上传maven中央仓库,附详细使用说明)

前言&#xff1a;之前工作中做过两个功能&#xff0c;就是之前写的这两篇博客&#xff0c;最近几天有个想法&#xff0c;给它做成一个springboot的start启动器&#xff0c;直接引入依赖&#xff0c;写好配置就能用了 springboot使用自定义注解实现接口参数解密&#xff0c;普通…

SpringSecurity学习(七)授权

授权 什么是权限管理 权限管理核心概念 SpringSecurity权限管理策略 基于URL地址的权限管理 基于方法的权限管理 一、权限管理 二、授权核心概念 在认证的过程成功之后会将当前用户登录信息保存到Authentication对象中&#xff0c;Authentication对象中有一个getAuthorities…

ChatGPT-4震撼发布

3月15日消息&#xff0c;美国当地时间周二&#xff0c;人工智能研究公司OpenAI发布了其下一代大型语言模型GPT-4&#xff0c;这是其支持ChatGPT和新必应等应用程序的最新AI大型语言模型。该公司表示&#xff0c;该模型在许多专业测试中的表现超出了“人类水平”。GPT-4, 相较于…

基于Java+Springboot+vue高校资源共享交流平台设计和实现

博主介绍&#xff1a;✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

SpringBoot介绍。

目录 一、SpringBoot简介 1、SpringBoot开发步骤 2、官网构建工程 3、SpringBoot概述 二、配置文件 1、配置文件格式 2、yaml格式 3、yaml配置文件数据读取 三、多环境配置 1、yam文件 2、properties文件 3、命令行启动参数设置 四、SpringBoot整合 1、SpringBo…

界面开发(4)--- PyQt5实现打开图像及视频播放功能

PyQt5创建打开图像及播放视频页面 上篇文章主要介绍了如何实现登录界面的账号密码注册及登录功能&#xff0c;还简单介绍了有关数据库的连接方法。这篇文章我们介绍一下如何在设计的页面中打开本地的图像&#xff0c;以及实现视频播放功能。 实现打开图像功能 为了便于记录实…