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

news2025/2/25 23:11:24

目录

一、了解VOC数据格式

 1、Annotations目录

 2. JPEGImages目录

二、YOLO格式

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


一、了解VOC数据格式

 Pascal VOC数据集下载地址:The PASCAL Visual Object Classes Homepage

介绍一下VOC 数据集下载后的目录结构:

 1、Annotations目录

目录存放xml文件:

Annotations文件夹中存放的是xml格式的标签文件,每一个xml文件都对应于JPEGImages文件夹中的一张图片,包含了图片的重要信息:图片的名称图片中object的类别及其bounding box坐标

文件内容如下

<annotation>
	<folder>images</folder>
	<filename>HW57-2 (3).jpg</filename>
	<path>C:\Users\lrj\Pictures\开裂标定\images\HW57-2 (3).jpg</path>
	<source>
		<database>Unknown</database>
	</source>
	<size>
		<width>1008</width>
		<height>1397</height>
		<depth>3</depth>
	</size>
	<segmented>0</segmented>
	<object>
		<name>close</name>
		<pose>Unspecified</pose>
		<truncated>0</truncated>
		<difficult>0</difficult>
		<bndbox>
			<xmin>133</xmin>
			<ymin>748</ymin>
			<xmax>244</xmax>
			<ymax>854</ymax>

 2. JPEGImages目录

存放的是数据集的原图片,像素尺寸大小不一。这里是自己的数据集。

二、YOLO格式

yolo标注格式保存在.txt文件中,一共5个数据,用空格隔开,举例说明如下图所示:

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

标注数据最好选择VOC格式,因为VOC格式包含更多的信息。

下面介绍格式转换:

代码运行结果:

产生一个VOCdevkit目录,其下包含多个目录,其中YOLOLables文件夹是存储所有转换好的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 copy

classes = ["open", "close"] # 自己标注的数据集的类别
#classes=["ball"]



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  # bbox宽度与图像宽度比值
    y = y*dh  # 中心点纵坐标与图像高度比值
    h = h*dh  # bbox高度与图像高度比值
    return (x,y,w,h)

def convert_annotation(input, output):
    in_file = open(input)
    out_file = open(output, 'w')
    tree=ET.parse(in_file) # Python xml 读取
    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'): # 对于每个bbox
        difficult = obj.find('difficult').text
        cls = obj.find('name').text # 目标类别
        if cls not in classes or int(difficult) == 1: # 如果类别错误,则continue
            continue
        cls_id = classes.index(cls) # 获得类别索引
        xmlbox = obj.find('bndbox') # bbpx
        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) # voc转yolo
        out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n') # cls_id centerx centery w h
    in_file.close()
    out_file.close()


def generate_diretorys(wd):

    data_base_dir = os.path.join(wd, "VOCdevkit/")
    os.mkdir(data_base_dir)

    work_sapce_dir = os.path.join(data_base_dir, "VOC2007/")
    os.mkdir(work_sapce_dir)

    annotation_dir = os.path.join(work_sapce_dir, "Annotations/")
    os.mkdir(annotation_dir)

    image_dir = os.path.join(work_sapce_dir, "JPEGImages/")
    os.mkdir(image_dir)

    yolo_labels_dir = os.path.join(work_sapce_dir, "YOLOLabels/")
    os.mkdir(yolo_labels_dir)

    yolov5_images_dir = os.path.join(data_base_dir, "images/")
    os.mkdir(yolov5_images_dir)

    yolov5_labels_dir = os.path.join(data_base_dir, "labels/")
    os.mkdir(yolov5_labels_dir)

    yolov5_images_train_dir = os.path.join(yolov5_images_dir, "train/")
    os.mkdir(yolov5_images_train_dir)

    yolov5_images_test_dir = os.path.join(yolov5_images_dir, "val/")
    os.mkdir(yolov5_images_test_dir)

    yolov5_labels_train_dir = os.path.join(yolov5_labels_dir, "train/")
    os.mkdir(yolov5_labels_train_dir)

    yolov5_labels_test_dir = os.path.join(yolov5_labels_dir, "val/")
    os.mkdir(yolov5_labels_test_dir)


def transform(images_dir, annotations_dir, split_val_rate, wd):
    train_file = open(os.path.join(wd, "yolov5_train.txt"), 'w') # 记载训练集图片目录的txt文件
    val_file = open(os.path.join(wd, "yolov5_val.txt"), 'w') # # 记载测试集图片目录的txt文件
    train_file.close()
    val_file.close()
    train_file = open(os.path.join(wd, "yolov5_train.txt"), 'a')
    val_file = open(os.path.join(wd, "yolov5_val.txt"), 'a')


    assert os.path.exists(images_dir), "path '{}' does not exist.".format(images_dir)
    assert  os.path.exists(annotations_dir), "path '{}' does not exist.".format(annotations_dir)

    assert os.path.exists(os.path.join(wd, "VOCdevkit", "labels", "val")), "val path does not exist"
    assert os.path.exists(os.path.join(wd, "VOCdevkit", "labels", "train")), "train path does not exist"




    list_imgs = os.listdir(images_dir) # list image files  所有图片名字
    random.seed(0)
    num = len(list_imgs)
    eval_index = random.sample(list_imgs, k=int(num*split_val_rate))

    another_images_dir = os.path.join(wd, "VOCdevkit", "VOC2007", "JPEGImages")
    assert os.path.exists(another_images_dir), "dir '{}' does not exist".format(another_images_dir)
    another_yolo_labels_dir = os.path.join(wd, "VOCdevkit", "VOC2007", "YOLOLabels")
    assert os.path.exists(another_yolo_labels_dir), "dir '{}' does not exist".format(another_yolo_labels_dir)
    another_Annotations_dir = os.path.join(wd, "VOCdevkit", "VOC2007", "Annotations")
    assert os.path.exists(another_Annotations_dir), "'{}' path does not exist".format(another_Annotations_dir)

    for index, image in enumerate(list_imgs):
        if image in eval_index:
            image_path = os.path.join(images_dir, image)
            new_image_path = os.path.join(wd, "VOCdevkit","images", "val", image)
            copy(image_path, new_image_path)

            image_id, extention = os.path.splitext(image)
            annotation_name = image_id + ".xml"
            annotation_dir = os.path.join(annotations_dir, annotation_name)
            new_annation_name = image_id + ".txt"
            new_annotation_dir = os.path.join(wd, "VOCdevkit", "labels", "val", new_annation_name)
            convert_annotation(annotation_dir,new_annotation_dir)

            val_file.write(new_image_path +"\n")
            copy(image_path, another_images_dir)
            copy(new_annotation_dir, another_yolo_labels_dir)
            copy(annotation_dir, another_Annotations_dir)




        else:
            image_path = os.path.join(images_dir, image)
            new_image_path = os.path.join(wd, "VOCdevkit","images", "train", image)
            copy(image_path, new_image_path)

            image_id, extention = os.path.splitext(image)
            annotation_name = image_id + ".xml"
            annotation_dir = os.path.join(annotations_dir, annotation_name)
            new_annation_name = image_id + ".txt"
            new_annotation_dir = os.path.join(wd, "VOCdevkit", "labels", "train", new_annation_name)
            convert_annotation(annotation_dir,new_annotation_dir)

            train_file.write(new_image_path + "\n")
            copy(image_path, another_images_dir)
            copy(new_annotation_dir, another_yolo_labels_dir)
            copy(annotation_dir, another_Annotations_dir)

        print("\r processing [{}/{}]".format(index+1, num), end="")



    train_file.close()
    val_file.close()

def check_img_label(images_dir, labels_dir):
    assert os.path.exists(images_dir), "'{}' does not exist!".format(images_dir)
    assert os.path.exists(labels_dir), "'{}' dose not exist!".format(labels_dir)

    list_imgs = os.listdir(images_dir) # list image files  所有图片名字

    for img in list_imgs:
        img_id, extension = os.path.splitext(img)
        img_dir = os.path.join(images_dir, img)

        label_name = img_id + ".xml"
        label_dir = os.path.join(labels_dir, label_name)

        if not os.path.exists(labels_dir):
            os.remove(img_dir)
            os.remove(label_dir)


if __name__ == "__main__":
    wd = "/home/jason/work/my-datasets/"
    generate_diretorys(wd=wd) # 生成多级目录
    raw_images_dir = "/home/jason/work/my-datasets/images" # 图片所在目录
    raw_annotions_dir = "/home/jason/work/my-datasets/annotions" # voc 格式标签文件坐在目录
    check_img_label(images_dir=raw_images_dir, labels_dir=raw_annotions_dir) # 检查图片名字与标签文件名字是否一一对应
    transform(images_dir=raw_images_dir, annotations_dir=raw_annotions_dir,split_val_rate=0.2, wd=wd) # VOC转yolo,并划分训练集、测试集

      

参考:

目标检测数据集标注-VOC格式_AI学长的博客-CSDN博客

YOLO数据格式说明与转换_yolo格式_lokvke的博客-CSDN博客

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

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

相关文章

Vue(动画、过渡、动画库)

一、动画 1.使用场景 在插入、更新或者移除DOM元素时候&#xff0c;在合适的时候给元素添加样式类型。 2. 使用 首先在组件style创建出现和离开的动画 然后对动画进行处理&#xff08;命名注意是v-enter-action和v-leave-action&#xff09; 如果name命名在默认标签中使用之后…

Redis高可用系列——ZSet类型底层详解

文章目录 概述skiplistredis的skiplist 概述 Redis 中的 zset 是一种有序集合类型&#xff0c;它可以存储不重复的字符串元素&#xff0c;并且给每个元素赋予一个排序权重值&#xff08;score&#xff09;。Redis 通过权重值来为集合中的元素进行从小到大的排序。zset 的成员是…

一、H3C-NE实验-Telnet实验

实验环境&#xff1a; 1. 在电脑搜索栏&#xff0c;搜“程序”&#xff0c;确保Telnet服务开启 2. 防火墙处于关闭状态 实验工具&#xff1a;H3C Cloud Lab、SecureCRT 实验拓扑&#xff1a; 实验步骤&#xff1a; 1. 登录路由器&#xff0c;配置路由器相关信息&#xff0c;…

【容器化】Docker 使用Ⅰ

【容器化】Docker 使用Ⅰ Docker Hello World运行交互式的容器启动容器&#xff08;后台模式&#xff09;停止容器Docker 的使用获取镜像启动容器后台运行停止一个容器进入容器导出和导入容器删除容器运行一个 web 应用查看 WEB 应用容器网络端口的快捷方式查看 WEB 应用程序日…

618前夕,淘宝天猫大变革,探索电商天花板之上的价值

2023年淘宝天猫618商家大会&#xff0c;恰逢淘宝20周年&#xff0c;也是阿里“16N”组织架构改革&#xff0c;淘宝天猫“独立”经营后&#xff0c;管理和运营团队的首次亮相。除了淘宝天猫618的具体策略&#xff0c;最受关注的&#xff0c;还有淘宝天猫的大变革——涉及淘宝天猫…

JavaScript实现贪吃蛇小游戏(网页单机版)

文章目录 项目地址项目介绍游戏开始游戏暂停游戏模式游戏死亡重新开始 结尾 今天使用 JavaScript 实现了一个网页版的贪吃蛇小游戏。 项目地址 Github: https://github.com/herenpeng/snakeGitee: https://gitee.com/herenpeng/snake 项目介绍 游戏开始 使用浏览器打开 sn…

【历史上的今天】4 月 21 日:微处理器先驱诞生;Winamp 发布;COPPA 正式生效

整理 | 王启隆 透过「历史上的今天」&#xff0c;从过去看未来&#xff0c;从现在亦可以改变未来。 今天是 2023 年 4 月 21 日&#xff0c;在 2006 年的今天&#xff0c;数码资讯网站 IT168 CEO 确认公司已经收购技术社区 ITPUB。宋刚则表示&#xff0c;收购 ITPUB 将有助于 …

C++string类的模拟实现

string类的模拟实现 1.string构造函数的实现问题2.浅拷贝3.深拷贝4.写时拷贝&#xff08;只做了解&#xff09;5.string类的模拟实现 1.string构造函数的实现问题 【问题1】 【问题2】没有显示定义拷贝构造函数&#xff0c;使用编译器默认生成拷贝构造函数 显示定义&#x…

git: fatal: detected dubious ownership

原因及解决&#xff1a; 当一个 仓库被与当前用户不同的用户克隆时&#xff0c;就会发生这种情况。我是在重新安装 Windows 后遇到了这个问题&#xff0c;但使用了以前克隆的 git 存储库&#xff08;在单独的分区上&#xff09; 右键单击 仓库文件夹&#xff0c;属性&#xf…

DNSPod十问周康:如何成为办公硬件领域的乔布斯?

本期嘉宾 周康 成者科技 CEO 周康&#xff0c;成者科技CEO、首席产品官。2013年创办成者科技&#xff0c;通过AI和互联网技术&#xff0c;推动办公设备智能化。担任CEO期间&#xff0c;带领成者科技攻克书籍扫描技术&#xff0c;融入大量的AI视觉技术&#xff0c;优化扫描质量…

芒果YOLO专栏的YOLOv8的Baseline改进:打造更方便版本NEW YOLOv8

关于芒果YOLO改进专栏的YOLOv5和YOLOv8的改进 - YOLOAir3解析 本篇文章作为一个Baseline改进解析篇 优势在于:改起来更加方便 文章目录 第一种改进方式第二种改进方式使用方式网络配置训练其他使用关于官方YOLOv8的改进方式:由于YOLOv5作者 发布的 YOLOv8,是使用的全新架构…

微服务分布式事务处理

当我们向微服务架构迁移时&#xff0c;如何处理好分布式事务是必须考虑的问题。这篇文章介绍了分布式事务处理的两种方案&#xff0c;可以结合实际采用合适的解决方案。原文&#xff1a;Handling Distributed Transactions in the Microservice world[1] 如今每个人&#xff08…

图片投票小程序微信投票软件发起投票软件互动酷投票

现在来说&#xff0c;公司、企业、学校更多的想借助短视频推广自己。 通过微信投票小程序&#xff0c;网友们就可以通过手机拍视频上传视频参加活动&#xff0c;而短视频微信投票评选活动既可以给用户发挥的空间激发参与的热情&#xff0c;又可以让商家和企业实现推广的目的&am…

Linux指令 热键

热键 上一次我们说到了linux的基本指令&#xff0c;这次我们先说一下热键 TAB TAB键在linux中有什么作用呢&#xff1f;&#xff1f; 在Linux中&#xff0c;假设我们想要输入的指令忘记了&#xff0c;我们可以TAB两下&#xff0c;帮我们补全命令或者假如命令太多&#xff0…

openfeign源码解析

概括 Feign是Netflix开发的声明式、模板化的HTTP客户端&#xff0c;其灵感来自Retrofit、JAXRS-2.0以及WebSocket。 Feign可帮助我们更加便捷、优雅地调用HTTP API。 Feign支持多种注解&#xff0c;例如Feign自带的注解或者JAX-RS注解等。Spring Cloud openfeign对Feign进行了 …

QT软件开发: 获取CPU序列号、硬盘序列号、主板序列号 (采用wmic命令)

[TOC](QT软件开发: 获取CPU序列号、硬盘序列号、主板序列号 (采用wmic命令)) [1] QT软件开发: 获取CPU序列号、硬盘序列号、主板序列号 (采用wmic命令) https://blog.51cto.com/xiaohaiwa/5380259 一、环境介绍 QT版本: 5.12.6 环境: win10 64位 编译器: MinGW 32 二、功…

陷入“营销迷城”的小仙炖,需要回归消费行业本质

消费行业往往受经济周期波动影响较小&#xff0c;因此被认为是一条长坡赛道。近年来&#xff0c;随着消费者收入水平提高&#xff0c;消费市场也出现了诸多以社交、休闲、健康等为目的的新消费形式&#xff0c;如饮料领域的元气森林、江小白&#xff0c;生鲜零售赛道的锅圈食汇…

Go gRPC etcd实现服务注册发现与负载均衡

一、前置 如果不了解go grpc 调用方式和实现细节&#xff0c;可以参考上一篇文章 golang grpc配置使用实战教程 涉及技术点 技术点版本描述golang1.19基础版本grpcv1.41.0gRPC golang包etcd server3.5.0注册中心etcd clientv3.5.8客户端服务发现和负载均衡 服务注册 服务…

【JavaSE】多态(多态实现的条件 重写 向上转移和向下转型 向上转型 向下转型 多态的优缺点 避免在构造方法种调用重写的方法)

文章目录 多态多态实现的条件重写向上转移和向下转型向上转型向下转型 多态的优缺点避免在构造方法种调用重写的方法 多态 一种事物&#xff0c;多种形态。 多态的概念&#xff1a;去完成某个行为&#xff0c;当不同对象去完成时会产生出不同的状态。 多态实现的条件 1.必须…

路径规划算法:基于被囊群优化的路径规划算法- 附代码

路径规划算法&#xff1a;基于被囊群优化的路径规划算法- 附代码 文章目录 路径规划算法&#xff1a;基于被囊群优化的路径规划算法- 附代码1.算法原理1.1 环境设定1.2 约束条件1.3 适应度函数 2.算法结果3.MATLAB代码4.参考文献 摘要&#xff1a;本文主要介绍利用智能优化算法…