将两个YOLO格式的数据集合并,并保持相同类别

1. 需求分析

最近在做两个YOLO格式的数据集合并,第一个数据集包含了第二个数据集的类别,但是相应的类别id对应不住,需要修改第二个数据集的类别标签与第一个数据集对应住。

2. 修改第二个数据集标签对应

2.1 实现思路

  1. 导入所需的库:

    • os:用于操作文件和文件夹路径。
    • tqdm:用于在循环中显示进度条。
  2. 定义类别 ID 映射字典 class_id_mapping

    • 这个字典用于将原始类别 ID 映射到新的类别 ID。
  3. 定义函数 convert_yolo_annotations(yolo_annotations_root, new_yolo_annotations_root)

    • 这个函数接受两个参数,即原始 YOLO 格式的标注文件夹路径 yolo_annotations_root 和新的 YOLO 格式的标注文件夹路径 new_yolo_annotations_root
    • 函数首先遍历 train、val、test 数据集分割文件夹。
    • 对于每个数据集分割,如果该分割不存在标注文件夹,则打印警告信息并跳过处理。
    • 如果标注文件夹存在,则遍历其中的每个文件。
    • 对于每个文件,打开原始 YOLO 格式的标注文件和新的 YOLO 格式的标注文件,并逐行读取原始标注文件。
    • 对于每一行,将其按空格分割为列表,获取原始类别 ID,并根据 class_id_mapping 字典将其替换为新的类别 ID。
    • 将修改后的行写入新的标注文件。
    • 在处理完成后,打印消息表示类别 ID 映射完成,并保存为新的 YOLO 格式的标注文件。
  4. 调用 convert_yolo_annotations() 函数:

    • 最后,调用 convert_yolo_annotations() 函数,传入了原始 YOLO 格式的标注文件夹路径和新的 YOLO 格式的标注文件夹路径。

2.2 实现代码

import os
from tqdm import tqdm

# 创建类别 ID 映射字典
class_id_mapping = {
    0: 0,  # 将原始类别 ID 为 0 的类别映射为新的类别 ID 为 0
    1: 13,  # 将原始类别 ID 为 1 的类别映射为新的类别 ID 为 13
    # 添加更多的映射关系...
}

# 定义原始 YOLO 格式的标注文件夹路径和新的 YOLO 格式的标注文件夹路径
yolo_annotations_root = r'D:\data\AIR-MOT\labels'
new_yolo_annotations_root = r'D:\data\AIR-MOT\labels_new'

def convert_yolo_annotations(yolo_annotations_root, new_yolo_annotations_root):
    # 遍历 train、val、test 数据集分割文件夹
    for dataset_type in ['train', 'val', 'test']:
        # 拼接原始 YOLO 格式的标注文件夹路径
        yolo_annotations_folder = os.path.join(yolo_annotations_root, dataset_type)

        # 如果当前数据集分割中没有标注文件夹,则跳过处理
        if not os.path.exists(yolo_annotations_folder):
            print(f"警告:{dataset_type} 数据集分割中没有标注文件夹,跳过处理。")
            continue

        # 拼接新的 YOLO 格式的标注文件夹路径
        new_yolo_annotations_folder = os.path.join(new_yolo_annotations_root, dataset_type)

        # 确保新的 YOLO 格式的标注文件夹存在
        if not os.path.exists(new_yolo_annotations_folder):
            os.makedirs(new_yolo_annotations_folder)

        # 遍历原始 YOLO 格式的标注文件夹中的所有文件
        for filename in tqdm(os.listdir(yolo_annotations_folder), desc="新类别标签转换"):
            # 拼接原始 YOLO 格式的标注文件路径
            original_file_path = os.path.join(yolo_annotations_folder, filename)

            # 拼接新的 YOLO 格式的标注文件路径
            new_file_path = os.path.join(new_yolo_annotations_folder, filename)

            # 打开原始 YOLO 格式的标注文件和新的 YOLO 格式的标注文件
            with open(original_file_path, 'r') as f, open(new_file_path, 'w') as f_new:
                # 逐行读取原始标注文件
                for line in f:
                    # 将每行按空格分割成列表
                    parts = line.strip().split()

                    # 获取原始类别 ID
                    class_id = int(parts[0])

                    # 如果原始类别 ID 在映射字典中,则替换为新的类别 ID
                    if class_id in class_id_mapping:
                        parts[0] = str(class_id_mapping[class_id])

                    # 将修改后的行写入新的标注文件
                    f_new.write(' '.join(parts) + '\n')

        print(f"类别 ID 映射完成,并保存为新的 YOLO 格式的标注文件,数据集类型:{dataset_type}。")

convert_yolo_annotations(yolo_annotations_root, new_yolo_annotations_root)

3. 合并两个数据集

将两个不同格式的数据集合并成一个符合YOLO格式的数据集。具体流程如下:

  1. 创建一个新的目录作为合并后的数据集根目录。
  2. 遍历数据集的不同类型(如训练集、验证集、测试集)。
  3. 对于每种类型的数据集:
    • 创建符合YOLO格式的目录结构(包括images和labels子目录)。
    • 将第一个数据集中的图像文件和标签文件复制到合并后的数据集目录中。
    • 然后将第二个数据集中的图像文件和标签文件复制到合并后的数据集目录中,但会避免覆盖已存在的文件。
    • 生成符合YOLO格式的索引文件,将图像文件路径写入索引文件中。

这样一来,就能够将两个不同格式的数据集合并成一个符合YOLO格式的数据集,并且保证了不会覆盖已有的文件。
数据集格式:
在这里插入图片描述
在这里插入图片描述

import os
from tqdm import tqdm
import shutil


def copy_files(src_dir, dst_dir):
    """
    复制源目录中的所有文件到目标目录。
    """
    if not os.path.exists(dst_dir):
        os.makedirs(dst_dir)

    if not os.path.exists(src_dir):
        print(f"警告:源文件夹 {src_dir} 不存在,无法复制任何文件。")
        return

    # 检查源目录是否为空
    src_files = os.listdir(src_dir)
    if not src_files:
        print(f"警告:源文件夹 {src_dir} 是空的,无法复制任何文件。")
        return

    for filename in tqdm(os.listdir(src_dir), desc=f'Copying {src_dir}'):
        src_path = os.path.join(src_dir, filename)
        dst_path = os.path.join(dst_dir, filename)
        if not os.path.exists(dst_path):
            shutil.copy2(src_path, dst_path)
        elif os.path.isdir(dst_path):
            print(f"警告:目标路径 {dst_path} 已经存在且是一个文件夹,跳过复制文件 {filename}。")
        else:
            print(f"警告:目标文件 {dst_path} 已经存在,跳过复制文件 {filename}。")


def merge_yolo_datasets(dataset1_root, dataset2_root, merged_dataset_root):
    # 创建合并后的数据集根目录
    if not os.path.exists(merged_dataset_root):
        os.makedirs(merged_dataset_root)

    # 定义数据集类型列表
    dataset_types = ['train', 'val', 'test']

    # 遍历数据集类型
    for dataset_type in tqdm(dataset_types, desc="创建合并后数据集"):

        # 创建符合 YOLO 格式的目录结构
        os.makedirs(os.path.join(merged_dataset_root, 'images', dataset_type), exist_ok=True)
        os.makedirs(os.path.join(merged_dataset_root, 'labels', dataset_type), exist_ok=True)

        # 复制第一个数据集的图像文件和标注文件到合并后的数据集目录
        src_dataset1_images = os.path.join(dataset1_root, 'images', dataset_type)
        dst_dataset_images = os.path.join(merged_dataset_root, 'images', dataset_type)
        copy_files(src_dataset1_images, dst_dataset_images)

        src_dataset1_labels = os.path.join(dataset1_root, 'labels', dataset_type)
        dst_dataset_labels = os.path.join(merged_dataset_root, 'labels', dataset_type)
        copy_files(src_dataset1_labels, dst_dataset_labels)

        # 复制第二个数据集的图像文件和标注文件到合并后的数据集目录,避免覆盖第一个数据集的文件
        src_dataset2_images = os.path.join(dataset2_root, 'images', dataset_type)
        copy_files(src_dataset2_images, dst_dataset_images)

        src_dataset2_labels = os.path.join(dataset2_root, 'labels', dataset_type)
        copy_files(src_dataset2_labels, dst_dataset_labels)

        # 生成合并后的数据集类型的索引文件
        with open(os.path.join(merged_dataset_root, 'labels',  f'{dataset_type}.txt'), 'w') as f:
            for image_file in os.listdir(dst_dataset_images):
                f.write(f"{os.path.join('images', image_file)}\n")

    print("数据集合并完成!")

# 调用函数进行数据集合并
merge_yolo_datasets(r'D:\data\DIOR\yolo', r'D:\data\AIR-MOT', r'D:\data\mot')

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

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

相关文章

CCF-CSP真题题解:201409-2 画图

201409-2 画图 #include <iostream> #include <cstring> #include <algorithm> using namespace std;const int N 110;int n; bool a[N][N];int main() {scanf("%d", &n);while (n--) {int x1, y1, x2, y2;scanf("%d%d%d%d", &…

R语言的学习——day1

将数据框中某一列数据改成行名 代码 结果

社交媒体数据恢复:Skype国内、际版

恢复已删除的Skype聊天记录可能需要一些操作&#xff0c;但请注意&#xff0c;这不一定总是可行的&#xff0c;并且可能需要一些技术知识。以下是一些步骤&#xff0c;您可以尝试恢复您的Skype聊天记录&#xff1a; 1. 检查备份&#xff1a; - 如果您有Skype备份&#xff0…

Ollama配置webui连接大预言模型

Ollama配置Web UI连接大预言模型 默认ollama安装后&#xff0c;chat对话只有命令行界面&#xff0c;交互体验较差。借助open-webui可以通过web界面连接ollama&#xff0c;从而实现类似chatgpt式的web交互体验。 使用家用PC实践记录如下&#xff1a; 1. 环境配置 本次使用的操作…

智能私信软件:转化率提升的神器

在数字化营销领域&#xff0c;利用智能私信软件策略提升转化率已经成为一种不可忽视的趋势。随着人工智能技术的发展&#xff0c;这些软件变得越来越智能&#xff0c;能够根据用户的行为和偏好提供个性化的沟通体验。在这篇文章中&#xff0c;我们将探讨如何有效地运用智能私信…

启明云端2.4寸屏+ESP32-S3+小型智能调速电动家用除草机案例 触控三档调速,能显示电压故障码

今天给大家分享个启明云端2.4寸屏ESP32-S3小型智能调速电动家用除草机案例&#xff0c;国外有草坪文化&#xff0c;这个机器能智能触控三档调速&#xff0c;带屏能显示电压故障码&#xff0c;数显档位&#xff08;3档最大&#xff09;&#xff0c;触控屏&#xff0c;长按3秒就能…

git 的迁移

现象是gitlab经常会挂掉&#xff0c;linux会显示磁盘空间不足&#xff0c;实际上&#xff0c;我们linux某个目录的空间是4T。这个空间应该是足够的。猜测是gitlab的安装目录不对导致的空间不足。 1、查找原因 用rpm 安装gitlab会有自己的目录&#xff0c;很多安装文件会在opt…

Android binder死亡通知机制

在Andorid 的binder系统中&#xff0c;当Bn端由于种种原因死亡时&#xff0c;需要通知Bp端&#xff0c;Bp端感知Bn端死亡后&#xff0c;做相应的处理。 使用 Bp需要先注册一个死亡通知&#xff0c;当Bn端死亡时&#xff0c;回调到Bp端。 1&#xff0c;java代码注册死亡通知 …

使用硬盘对拷方法将数据无损转移到另一个硬盘!

硬盘对拷&#xff0c;其实就是磁盘克隆&#xff0c;很多人喜欢将其说成对拷&#xff0c;或者硬盘复制等&#xff0c;但不管怎么说&#xff0c;他们的目的都是一个&#xff0c;想要把原硬盘上的全部数据&#xff08;包括系统、程序、个人文件、隐藏配置数据等&#xff09;都无损…

mysql基础知识汇总

本文自行整理&#xff0c;只做学习记忆之用&#xff0c;若有不当之处请指出 一、数据库三层结构 &#xff08;1&#xff09;所谓安装Mysql数据库&#xff0c;就是在主机安装一个数据库管理系统(DBMS),这个管理程序可以管理多个数据库。DBMS(database manage system) &#xf…

【JVM】简述类加载器及双亲委派机制

双亲委派模型&#xff0c;是加载class文件的一种机制。在介绍双亲委派模型之前&#xff0c;我需要先介绍几种类加载器&#xff08;Class Loader&#xff09;。 1&#xff0c;类加载器 Bootstrap&#xff0c;加载lib/rt.jar&#xff0c;charset.jar等中的核心类&#xff0c;由…

港口数据复杂不知道如何监控?来试试FineVis所展现的智慧港口看板

一、智慧港口是什么 智慧港口代表着港口建设的未来趋势和发展方向。以信息物理系统为框架&#xff0c;智慧港口通过创新应用高新技术&#xff0c;实现了物流供给方和需求方之间的沟通&#xff0c;并将它们融入集疏运一体化系统中。这种系统极大地提升了港口及其相关物流园区对…

ospf路由过滤及策略实验

目录 一、实验拓扑 二、实验要求 三、实验思路 四、实验步骤 1、配置IP 2、配置RIP协议和OSPF协议 3、在R2上做双向路由引入 &#xff08;1&#xff09;进入到rip协议的1进程中引入ospf &#xff08;2&#xff09;进入到ospf协议的1进程中引入rip 4、在R2上使用acl和…

逻辑回归实战 -- 是否通过考试

http://链接: https://pan.baidu.com/s/1-uy-69rkc4WjMpPj6iRDDw 提取码: e69y 复制这段内容后打开百度网盘手机App&#xff0c;操作更方便哦 数据集下载链接 这是个二分类问题&#xff0c;通过x1,x2两个指标得出是否通过考试的结论。 逻辑回归的激活函数是sigmoid函数&…

【论文阅读】ChipNeMo中的数据集处理

前面总体学习了《ChipNeMo: Domain-Adapted LLMs for Chip Design》&#xff0c;然后又继续仔细看了论文中的领域适配分词和领域数据微调的预训练检索模型&#xff0c;对于数据集的处理&#xff0c;也需要仔细看一下。 提炼重点&#xff1a;1&#xff09;对于数据集&#xff0…

二维码门楼牌管理应用平台建设:创新社区管理模式

文章目录 前言一、二维码门楼牌管理应用平台的建设背景二、在线打卡功能的实现与意义三、查看浏览网格员在线打卡记录的重要性四、二维码门楼牌管理应用平台的未来展望五、结语 前言 随着信息技术的不断发展&#xff0c;社区管理正逐步迈向智能化、便捷化。二维码门楼牌管理应…

Databend 开源周报第 142 期

Databend 是一款现代云数仓。专为弹性和高效设计&#xff0c;为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务&#xff1a;https://app.databend.cn 。 Whats On In Databend 探索 Databend 本周新进展&#xff0c;遇到更贴近你心意的 Databend 。 支持 WASM UDF …

Linux专栏01:Linux发展历史及背景介绍

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Linux专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Linux发展历史及背景介绍 编号&#xff1a;01 文章目录 Linux发展历…

在kuboard中添加k8s集群

1.登录kuboard后&#xff0c;点击添加集群面板 系统会跳转到k8s集群添加页面&#xff0c;按照页面提示输入自身的集群信息即可&#xff0c;此处没有什么难点。 添加成功后&#xff0c;点击集群面板&#xff0c;然后点击集群概要信息&#xff0c;就可以查看集群节点信息。 集群节…

C++-8

1.C中list容器实现 using namespace std;int main() {list<int> l1;l1.assign(2,3);list<int>::iterator n l1.begin();for(n l1.begin();n!l1.end();n){cout << *n << "\t";}cout << endl;cout << "last one " &l…