yolo数据集格式按照每一个类别的比例划分数据集

news2025/1/15 6:49:16

写在前面: 写脚本不易,写博客不易,请多点赞关注,谢谢。10多年来,我一直免费给大家毫无保留的分享技术等,不但从来没被打赏过,而且在分享有些模型转化处理的高级脚本中,有些同胞由于自身的问题,没有转化成功就出言伤人,各位同胞们,你们要知道,随着时间推移,各个第三方库的版本一致在更新,比如onnx,torch等,这就导致这些库的接口有所变化,写法也有所变化,包括你自己的环境等等各种原因导致你没能成功,而我是无私免费分享者,却遭到不礼貌的言语伤害,我伤心,但这并没有影响我的分享热情,我会继续分享给大家。
背景: 介于在用yolov系列模型训练模型时,数据集划分对训练结果的影响较大,所以写了一个数据集重新划分的脚本,支持两类检测的数据,标签分别为0和1,针对数据集中的空标签都有所考虑。
脚本功能: 按照不同标签,按比例进行划分,比如按照1:8的比例你设置训练集占80%,即train_ratio设置为0.8,那么你标签为0的数据数量的80%将划分为训练集,标签为1的80%将划分为训练集,针对空标签,你也可以选择不划分,或者将空标签仅放在训练集里面,或者正常按照训练集和验证集来划分,若一个标签中有多个不同类别的标签,也会单独把这一类数据拿出来,按照80%比例进行划分。

1、待划分数据集格式如下:

主目录yolodatas名称可以不一样,但是其下面的子目录文件夹的名字必须保持一致,若yolodatas名称不一样则需要在脚本当中修改,详细见3.
在这里插入图片描述

2、划分完成之后数据集格式如下:

在这里插入图片描述

3、划分脚本参数介绍:

–base_train_images_path       待划分数据的训练集图像路径
–base_val_images_path        待划分数据的验证集图像路径
–save_root_path        新的数据集保存路径 ,主目录名
–train_ratio        训练集所占的比例
–emptys        空的标签正常分训练集和验证集,否则不用空标签
–emptys_trian_val        空标签放训练集和验证集,否组只放训练集,emptys为True时有效,emptys为False时此参数无效。
说明: 如果原始待划分的数据集格式和1中所示一致,则不需要该脚本中的路径base_train_images_path和base_val_images_path,如果不一致,则需要修改。其他参数参考脚本参数修改即可。

4、转化脚本如下,可拷贝使用:

import os
import argparse
import shutil
import random
def makdirs(opt):
    images_train = os.path.join(opt.save_root_path, 'images/train')
    images_val = os.path.join(opt.save_root_path ,'images/val')

    label_train = os.path.join(opt.save_root_path, 'labels/train')
    label_val = os.path.join(opt.save_root_path,'labels/val')
    os.makedirs(images_train,exist_ok=True)
    os.makedirs(images_val, exist_ok=True)
    os.makedirs(label_train, exist_ok=True)
    os.makedirs(label_val, exist_ok=True)

    return images_train,images_val,label_train,label_val
def readdir(opt):
    #所有图像路径列表
    images_path_list = [os.path.join(opt.base_train_images_path, train_label_name) for train_label_name in
                               os.listdir(opt.base_train_images_path)] \
                              + [os.path.join(opt.base_val_images_path, base_label_val_patch) for base_label_val_patch in
                                 os.listdir(opt.base_val_images_path)]
    #打乱列表
    random.shuffle(images_path_list)
    # 所有标签路径列表
    txt_path_list = [one_images_path_list.replace('images','labels')[:-3]+'txt' for one_images_path_list in images_path_list]

    zero_class_images = []
    zero_class_labels = []


    one_class_images = []
    one_class_labels = []

    one_two_class_images = []
    one_two_class_labels = []

    empty_class_images = []
    empty_class_labels = []


    #所有数据集数量
    file_number = len(images_path_list)

    for idx in range(file_number):
        with open(txt_path_list[idx],'r',encoding='utf-8') as fo:
            lines = fo.readlines()

        if len(lines)>1:
            #标签文件中有多个目标时,将多个目标标签存入列表并统计不同类型标签数量
            class_index_list = []
            #每一行去除\n
            relines = [lls.strip() for lls in lines]

            #遍历每一行,并统计每个标签的数量
            for line in relines:
                #每一行第一个标签名放入列表
                # print(line,line[0])
                class_index_list.append(int(line[0]))
            # print(class_index_list)

            # print("class_index_list:", class_index_list)

            #标签类
            class_label_list = list(set(class_index_list))
            # print("class_label_list:",class_label_list)

            if len(class_label_list)==1:
                if class_label_list[0]==0:
                    zero_class_images.append(images_path_list[idx])
                    zero_class_labels.append(txt_path_list[idx])
                elif class_label_list[0]==1:
                    one_class_images.append(images_path_list[idx])
                    one_class_labels.append(txt_path_list[idx])
                else:
                    print("注意还有其他标签,请修改此处代码,确保所有标签都添加都了标签列表里面!!!!")

            else:
                print("***********************************")
                one_two_class_images.append(images_path_list[idx])
                one_two_class_labels.append(txt_path_list[idx])


        elif len(lines)==1:
            #签文件中有一个目标时
            relines = [lls.strip() for lls in lines]
            class_ids = int(relines[0][0])
            if class_ids == 0:
                zero_class_images.append(images_path_list[idx])
                zero_class_labels.append(txt_path_list[idx])
            elif class_ids == 1:
                one_class_images.append(images_path_list[idx])
                one_class_labels.append(txt_path_list[idx])
            else:
                print("注意还有其他标签,请修改此处代码,确保所有标签都添加都了标签列表里面!!!!")
        elif len(lines)==0:
            #标签为空文件时
            empty_class_images.append(images_path_list[idx])
            empty_class_labels.append(txt_path_list[idx])
        else:
            print("error")
    return zero_class_images,zero_class_labels,one_class_images,one_class_labels,one_two_class_images,one_two_class_labels,empty_class_images,empty_class_labels

def copytofile(opt):
    images_train, images_val, label_train, label_val= makdirs(opt)
    zero_class_images, zero_class_labels, one_class_images, one_class_labels, one_two_class_images, one_two_class_labels, empty_class_images, empty_class_labels =readdir(opt)
    if len(zero_class_images)!=len(zero_class_labels) or len(one_class_images)!=len(one_class_labels):
        print("数据集列表不匹配1!!!!")
        return 0
    if len(one_two_class_images)!=len(one_two_class_labels) or len(empty_class_images)!=len(empty_class_labels):
        print("数据集列表不匹配2!!!!")
        return 0
    number_train_zero = int(opt.train_ratio*len(zero_class_images))
    number_train_one = int(opt.train_ratio*len(one_class_images))
    number_train_one_two = int(opt.train_ratio*len(one_two_class_images))
    number_train_empty = int(opt.train_ratio*len(empty_class_images))
    len_zero,len_one,len_one_two,len_empty = len(zero_class_images),len(one_class_images),len(one_two_class_images),len(empty_class_images)
    for z in range(len_zero):
        #标签为0的数据
        if z<number_train_zero:
            shutil.copy2(zero_class_images[z], os.path.join(images_train,zero_class_images[z].split('\\')[-1]))
            shutil.copy2(zero_class_labels[z], os.path.join(label_train, zero_class_labels[z].split('\\')[-1]))
        else:
            shutil.copy2(zero_class_images[z], os.path.join(images_val, zero_class_images[z].split('\\')[-1]))
            shutil.copy2(zero_class_labels[z], os.path.join(label_val, zero_class_labels[z].split('\\')[-1]))

    for o in range(len_one):
        #标签为1的数据
        print(one_class_images[o],os.path.join(images_train,one_class_images[o].split('\\')[-1]))
        print(one_class_labels[o],os.path.join(label_train, one_class_labels[o].split('\\')[-1]))
        if o<number_train_one:
            shutil.copy2(one_class_images[o], os.path.join(images_train,one_class_images[o].split('\\')[-1]))
            shutil.copy2(one_class_labels[o], os.path.join(label_train, one_class_labels[o].split('\\')[-1]))
        else:
            shutil.copy2(one_class_images[o], os.path.join(images_val, one_class_images[o].split('\\')[-1]))
            shutil.copy2(one_class_labels[o], os.path.join(label_val, one_class_labels[o].split('\\')[-1]))


    for ot in range(len_one_two):
        #标签为0和1的数据
        if ot<number_train_one_two:
            shutil.copy2(one_two_class_images[ot], os.path.join(images_train,one_two_class_images[ot].split('\\')[-1]))
            shutil.copy2(one_two_class_labels[ot], os.path.join(label_train, one_two_class_labels[ot].split('\\')[-1]))
        else:
            shutil.copy2(one_two_class_images[ot], os.path.join(images_val, one_two_class_images[ot].split('\\')[-1]))
            shutil.copy2(one_two_class_labels[ot], os.path.join(label_val, one_two_class_labels[ot].split('\\')[-1]))

    if opt.emptys:
        if opt.emptys_trian_val:
            for en in range(len_empty):
                #标签为空的数据
                if en<number_train_empty:
                    shutil.copy2(empty_class_images[en], os.path.join(images_train,empty_class_images[en].split('\\')[-1]))
                    shutil.copy2(empty_class_labels[en], os.path.join(label_train, empty_class_labels[en].split('\\')[-1]))
                else:
                    shutil.copy2(empty_class_images[en], os.path.join(images_val, empty_class_images[en].split('\\')[-1]))
                    shutil.copy2(empty_class_labels[en], os.path.join(label_val, empty_class_labels[en].split('\\')[-1]))
        else:
            for en in range(len_empty):
                #标签为空的数据
                shutil.copy2(empty_class_images[en], os.path.join(images_train,empty_class_images[en].split('\\')[-1]))
                shutil.copy2(empty_class_labels[en], os.path.join(label_train, empty_class_labels[en].split('\\')[-1]))


    print('#------------------------------------------------------总数据集数量为-----------------------------------------------------------------------#')
    print("划分前总数据集:",len_zero+len_one+len_one_two+len_empty)
    print('#-----------------------------------------------------所有数据集排布情况---------------------------------------------------------------------#')
    print("zero:%s\none:%s\nzero_two:%s\nempty:%s" % (len_zero,len_one,len_one_two,len_empty))
    print('#---------------------------------------------------数据集划分后训练集分布--------------------------------------------------------------------#')
    print("zero:%s\none:%s\nzero_two:%s\nempty:%s\n训练集总数:%s"%(number_train_zero,number_train_one,number_train_one_two,number_train_empty,number_train_zero+number_train_one+number_train_one_two+number_train_empty))
    print('#---------------------------------------------------数据集划分后验证集分布--------------------------------------------------------------------#')
    print("zero:%s\none:%s\nzero_two:%s\nempty:%s\n验证集总数:%s" % (len_zero-number_train_zero, len_one-number_train_one, len_one_two-number_train_one_two, len_empty-number_train_empty,len_zero+len_one+len_one_two+len_empty-(number_train_zero+number_train_one+number_train_one_two+number_train_empty)))
    print('#---------------------------------------------------数据集划分后数据集总数--------------------------------------------------------------------#')
    print("划分后总数据集:",number_train_zero+number_train_one+number_train_one_two+number_train_empty+len_zero+len_one+len_one_two+len_empty-(number_train_zero+number_train_one+number_train_one_two+number_train_empty))


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--base_train_images_path', type=str, default='yolodatas/images/train',help='原始图像的训练集路径')
    parser.add_argument('--base_val_images_path', type=str, default='yolodatas/images/val', help='原始图像的验证集路径')
    parser.add_argument('--save_root_path', nargs='+', type=str, default='./mynewyolodata', help='新的数据集保存路径')
    parser.add_argument('--train_ratio', type=float, default=0.8, help='训练集所占的比例')
    parser.add_argument('--emptys', type=bool, default=True, help='空的标签正常分训练集和验证集,否则不用空标签')
    parser.add_argument('--emptys_trian_val', type=bool, default=True, help='空标签放训练集和验证集,否组只放训练集')
    opt = parser.parse_args()

    copytofile(opt)

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

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

相关文章

pmp证书实用性怎么样,考这个性价比高不高,难度?

要是 PMP 证书没有价值&#xff0c;还会有那么多人愿意去考吗&#xff1f; 我觉得一个原因是因为行业/岗位需求高&#xff0c;还有就是拿证后能不能用得上&#xff0c;看人看公司&#xff0c;很大一部分考证的人都是因为应聘跟投标书要求。 据我了解&#xff0c;PMP 证书目前…

八戒会修特斯拉 特斯拉如何磨合制动器

--------------------------------------------------------------------------------------------------------------------------------- -------------------------------------- 作者&#xff1a; 八戒会修特斯拉 -------------------------…

动态注意力机制新突破!11个最新idea,看了就能发顶会!

在处理复杂数据时&#xff0c;可以通过引入动态注意力机制&#xff0c;让模型根据输入数据的特点动态调整关注点&#xff0c;聚焦最关键的信息&#xff0c;来提高模型的处理能力和效率。 这种比传统方法更高效、灵活的技术足以应对各种复杂任务和挑战&#xff0c;具有强大的适…

C语言程序设计22

《C程序设计教程&#xff08;第四版&#xff09;——谭浩强》 例题2.10 先后输出B、O、Y三个字符 代码&#xff1a; //《C程序设计教程&#xff08;第四版&#xff09;——谭浩强》 //例题2.10 先后输出B、O、Y三个字符#include <stdio.h> int main() {char a B;char …

E22.【C语言】练习:“详解函数递归”文中青蛙跳台阶的答案

点击查看原文 代码实现 jump(n)jump(n-1)jump(n-2) #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> int jump(int n) {if (1 n){return 1;}else if (2 n){return 2;}else{return jump(n - 1) jump(n - 2);} }int main() {int n 0;printf("请输入台阶总数…

MIGO 常用移动类型

MIGO的移动类型&#xff1a; 101&#xff1a;可以指采购订单收货和生产订单收货&#xff0c;在MB51中可以通过移动标识来进行区分。B指采购订单。F指生产订单。 122&#xff1a;采购订单退货。通过A02 物料凭证进行退货后&#xff0c;系统自动带出122的移动类型。 161&#xf…

华清IOday5 24-8-1

1、使用两个线程完成两个文件的拷贝&#xff0c;分支线程1拷贝前一半&#xff0c;分支线程2拷贝后一半&#xff0c;主线程回收两个分支线程的资源 #include <myhead.h> //文件信息结构体创建 struct File {const char *file1;//文件1地址const char *file2;//文件2地址i…

中文网址导航模版HaoWa1.3.1/模版网站wordpress导航主题

HaoWa v1.3.1由挖主题开发的一款网址导航类主题。 HaoWA主题除主体导航列表外&#xff0c;对主题所需的小模块都进行了开放式的HTML编辑器形式的功能配置&#xff0c;同时预留出默认的代码结构&#xff0c;方便大家在现有的代码结构上进行功能调整。 同时加入了字体图标Font …

一文解决3D车道线检测:最新单目3D车道线检测综述

前言 场景理解是自动驾驶中极具挑战的任务&#xff0c;尤其是车道检测。车道是道路分割的关键&#xff0c;对车辆安全高效行驶至关重要。车道检测技术能自动识别道路标记&#xff0c;对自动驾驶车辆至关重要&#xff0c;缺乏这项技术可能导致交通问题和事故。车道检测面临多种…

JS 逆向补环境

报错信息ReferenceError: window is not defined 看到此报错应该在env文件中写入一下代码 windowglobal报错信息Cannot read properties of undefined (reading ‘userAgent’) 看到此报错应该在env文件中写入一下代码 navigator{"userAgent":Mozilla/5.0 (Windo…

[GYCTF2020]Blacklist1

打开题目 判断注入类型&#xff0c;输入1试试 输入2 输入1 判断为字符型注入 堆叠查询2;show databases;# 然后来输入2; show tables;#来查看数据库的表 然后我们通过FlagHere表来查看列输入2;show columns from FlagHere;# 来查看列 、 重新构造payload&#xff1a;0;HAND…

手机在网状态接口如何对接?(二)

一、什么是手机在网状态&#xff1f; 传入手机号码&#xff0c;查询该手机号的在网状态&#xff0c;返回内容有正常使用、停机、在网但不可用、不在网&#xff08;销号/未启用/异常&#xff09;、预销户等多种状态。 二、手机在网状态使用场景&#xff1f; 1.用户验证与联系…

C语言数据在内存中的存储超详解

文章目录 1. 整数在内存中的存储2. 大小端字节序和字节序判断2. 1 什么是大小端&#xff1f;2. 2 为什么会有大小端&#xff1f;2. 3 练习 3. 浮点数在内存中的存储3. 1 一个代码3. 2 浮点数的存储3. 2. 1 浮点数存的过程3. 2. 2 浮点数取的过程3. 3 题目解析 1. 整数在内存中的…

vue大数据量列表渲染性能优化:虚拟滚动原理

前面咱完成了自定义JuanTree组件各种功能的实现。在数据量很大的情况下&#xff0c;我们讲了两种实现方式来提高渲染性能&#xff1a;前端分页和节点数据懒加载。 前端分页小节&#xff1a;Vue3扁平化Tree组件的前端分页实现 节点数据懒加载小节&#xff1a;Element Tree Plu…

镜像制作和管理

文章目录 一、Docker镜像说明Docker镜像中没有内核为什么没有内核容器中的程序后台运行会导致此容器启动后立即退出镜像的生命周期和制作方式 二、手动构建镜像基于容器手动制作镜像步骤实际操作基于 busybox 制作httpd镜像制作tomcat镜像基于ubuntu的基础镜像手动安装nginx镜像…

空间域注意力机制(Spatial Attention)

空间域注意力机制&#xff08;Spatial Attention&#xff09;是深度学习中一种重要的注意力机制&#xff0c;用于在处理如图像或视频数据时聚焦于特定区域&#xff0c;以提高模型的性能和效率。举例来说&#xff0c;首先&#xff0c;卷积神经网络处理一张图像&#xff0c;经过特…

【Docker】认识 Docker(版本、官方网站、架构、生态)

一、Docker 版本 Docker 发展过程中衍生了以下版本&#xff0c;目前我学习和使用提到的版本是 docker-ce。 1、lxc lxc 是最早的 linux 容器技术&#xff0c;早期版本的 docker 直接使用 lxc 来实现容器的底层功能。虽然使用者相对较少&#xff0c;但 lxc 项目仍在持续开发演…

理想发周榜,不是新能源市场的原罪

余华在他的小说《在细雨中呼喊》曾写过这么一段话&#xff1a; “仓廪实而知礼节&#xff0c;衣食足而知荣辱”&#xff0c;在物质需求得到满足以前&#xff0c;精神文明的发展难免会有所滞后。所以&#xff0c;贫穷&#xff0c;不是原罪。 同样的&#xff0c;在如今的新能源…

常见API(一)

API(Application Programming interface):应用程序编程接口&#xff0c;别人写好的程序&#xff0c;直接拿来调用。主要是为了灵活解决需求。这次只先简单学习了一下String和ArrayList两个。 1.包 包是分门别类管理程序的&#xff0c;类似于文件夹。别人写好的包通常都在别人的…

Android Studio2024安装教程

软件介绍 Android Studio 是谷歌推出的一个Android集成开发工具。 基于IntelliJ IDEA. 类似 Eclipse ADT&#xff0c;Android Studio 提供了集成的 Android 开发工具用于开发和调试。 软件下载 https://docs.qq.com/doc/DR0hWZ0l4aGtVTmVr软件安装 1、双击运行安装文件 2、…