将UAVDT数据集转化成YOLO样式

主要是将UAVDT数据集转化成VOC格式的目标检测数据集

1.生成txt文件

首先要将gt.whole.txt里边的DET数据集按照图片名称进行分割,保证分割后的txt文件中包含该图片的所有标注信息,代码如下:

import os
#文件夹的路径
folder_path = "/workspace/uavdt_night/UAV-benchmark-M/M1102"
folder_path1 = os.path.join(folder_path ,'gt')#存放分割后的txt文件的路径
folder_path2 = os.path.join(folder_path , 'img1')#照片的路径,主要用于统计有多少张照片,方便创建txt文件
folder_path3 = os.path.join(folder_path , 'gt', 'M1102_gt_whole.txt')#存放标签的txt文件

photo_count = 0
# 判断图片数量
for file_name in os.listdir(folder_path2):
    # 使用os.path.splitext()函数获取文件扩展名
    _, extension = os.path.splitext(file_name)
    # 如果文件是照片文件(例如.jpg或.png),则增加计数器
    if extension.lower() in ['.jpg', '.jpeg', '.png', '.gif', '.bmp']:
        photo_count += 1
print("Total photos:", photo_count)

if not os.path.exists(folder_path):
    os.makedirs(folder_path)

with open(folder_path3,'r') as file:
    lines = file.readlines()
    for i in range(1,photo_count+1):
        file_path1 = os.path.join(folder_path1, str(i) + '.txt')
        with open(file_path1, 'w') as target_file:
            for line in lines:
                data = line.split(',')
                if data[0] == str(i):
                    target_file.write(line)
 

2.生成完整的图片和标签文件夹

将各文件夹下的图片和txt文件按照依次递增的顺序存放到一个文件夹中,代码如下

import os
import shutil

# 图片文件夹和标签文件夹的根路径
root_folder = "/workspace/uavdt_night/UAV-benchmark-M"

# 目标图片文件夹路径
destination_img_folder = "/workspace/uavdt_night/all/img"

# 目标标签文件夹路径
destination_ann_folder = "/workspace/uavdt_night/all/ann"

# 用于计数的变量
img_count = 1
ann_count = 1

# 遍历指定文件夹中的所有文件夹
for folder_name in ["M0202", "M0203", "M0204","M0205","M0206","M0901","M0902","M1001","M1002","M1003","M1004","M1005","M1006","M1007","M1008","M1009","M1101","M1102"]:
    # 构建当前文件夹中的图片文件夹路径
    img_folder_path = os.path.join(root_folder, folder_name, "img1")
    
    # 如果图片文件夹存在
    if os.path.exists(img_folder_path):
        # 遍历图片文件夹中的所有文件
        for filename in os.listdir(img_folder_path):
            # 获取文件的完整路径
            file_path = os.path.join(img_folder_path, filename)
            # 获取文件的扩展名
            _, extension = os.path.splitext(filename)
            # 生成新的文件名
            new_filename = f"image_{img_count}{extension}"
            # 构建目标文件的完整路径
            destination_file = os.path.join(destination_img_folder, new_filename)
            # 移动文件到目标文件夹
            shutil.copy(file_path, destination_file)
            # 更新计数器
            img_count += 1

    # 构建当前文件夹中的标签文件夹路径
    ann_folder_path = os.path.join(root_folder, folder_name, "gt")
    
    # 如果标签文件夹存在
    if os.path.exists(ann_folder_path):
        # 遍历标签文件夹中的所有文件
        for filename in os.listdir(ann_folder_path):
            # 获取文件的完整路径
            file_path = os.path.join(ann_folder_path, filename)
            # 生成新的文件名
            new_filename = f"image_{ann_count}.txt"
            # 构建目标文件的完整路径
            destination_file = os.path.join(destination_ann_folder, new_filename)
            # 移动文件到目标文件夹
            shutil.copy(file_path, destination_file)
            # 更新计数器
            ann_count += 1

3.划分数据集

将全部的文件按照一定的比例进行切分,分成训练集和测试集

import os
import random
import shutil

def split_dataset(source_dir, train_dir, test_dir, split_ratio=0.8):
    # 创建训练集和测试集文件夹
    os.makedirs(train_dir, exist_ok=True)
    os.makedirs(test_dir, exist_ok=True)
    
    # 获取所有图片文件的列表
    image_files = [f for f in os.listdir(source_dir) if f.endswith('.jpg') or f.endswith('.png')]
    
    # 随机化文件列表
    random.shuffle(image_files)
    
    # 计算训练集和测试集的数量
    num_train = int(len(image_files) * split_ratio)
    num_test = len(image_files) - num_train
    
    # 将文件移动到相应的文件夹中
    for i, image_file in enumerate(image_files):
        source_path = os.path.join(source_dir, image_file)
        if i < num_train:
            target_path = os.path.join(train_dir, image_file)
        else:
            target_path = os.path.join(test_dir, image_file)
        shutil.move(source_path, target_path)

# 设置源文件夹和目标文件夹路径
source_directory = "/workspace/uavdt_night/all/img"
train_directory = "/workspace/uavdt_night/all/train"
test_directory = "/workspace/uavdt_night/all/test"

# 划分数据集并移动文件
split_dataset(source_directory, train_directory, test_directory)

4.划分标签

按照分割后的图片名称,将对应的标签文件进行分割,代码如下

import os
import shutil

def copy_txt_files(image_folder, txt_folder, output_folder):
    # 创建输出文件夹
    os.makedirs(output_folder, exist_ok=True)
    
    # 获取图片文件夹中所有图片文件的名称列表
    image_files = [f for f in os.listdir(image_folder) if f.endswith('.jpg') or f.endswith('.png')]
    
    # 遍历图片文件夹中的图片文件
    for image_file in image_files:
        # 构建对应的txt文件路径
        txt_file = os.path.splitext(image_file)[0] + '.txt'
        txt_path = os.path.join(txt_folder, txt_file)
        
        # 检查对应的txt文件是否存在
        if os.path.exists(txt_path):
            # 复制txt文件到输出文件夹中
            shutil.copy(txt_path, output_folder)

# 设置图片文件夹路径、txt文件夹路径和输出文件夹路径
image_folder = "/workspace/uavdt_night/all/train"
txt_folder = "/workspace/uavdt_night/all/ann"
output_folder = "/workspace/uavdt_night/all/train_ann"

# 将txt文件复制到新的文件夹中
copy_txt_files(image_folder, txt_folder, output_folder)

5.转化成json(coco)格式

将分割后的标签文件由txt格式转化为json进行保存,代码如下

import json
import os

# 创建一个空的COCO格式数据结构
coco_data = {
    "info": {},
    "licenses": [],
    "categories": [],
    "images": [],
    "annotations": []
}

# 读取txt文件并解析数据
def parse_txt_file(txt_file):
    with open(txt_file, 'r') as f:
        lines = f.readlines()
        annotations = []
        for line in lines:
            # 解析每一行数据,格式为 <frame_index>,<target_id>,<bbox_left>,<bbox_top>,<bbox_width>,<bbox_height>,<out-of-view>,<occlusion>,<object_category>
            frame_index, target_id, bbox_left, bbox_top, bbox_width, bbox_height, out_of_view, occlusion, object_category = map(str.strip, line.split(','))
            annotations.append({
                "bbox": [int(bbox_left), int(bbox_top), int(bbox_width), int(bbox_height)],
                "category_id": int(object_category)
            })
        return annotations

# 遍历txt文件夹
txt_folder = "/workspace/uavdt_night/all/train_ann"
for filename in os.listdir(txt_folder):
    if filename.endswith('.txt'):
        txt_file = os.path.join(txt_folder, filename)
        # 解析txt文件
        annotations = parse_txt_file(txt_file)
        
        # 将图像信息添加到COCO数据结构中
        image_info = {
            "id": len(coco_data["images"]) + 1,
            "file_name": os.path.splitext(filename)[0] + '.jpg'  # 假设txt文件与图像文件同名
        }
        coco_data["images"].append(image_info)
        
        # 将目标标注信息添加到COCO数据结构中
        for annotation in annotations:
            annotation_info = {
                "id": len(coco_data["annotations"]) + 1,
                "image_id": image_info["id"],
                "bbox": annotation["bbox"],
                "category_id": annotation["category_id"],
                "iscrowd": 0  # 假设目标不是一个crowd
            }
            coco_data["annotations"].append(annotation_info)

# 保存COCO格式数据为JSON文件
with open("/workspace/uavdt_night/all/train.json", 'w') as f:
    json.dump(coco_data, f)

6.转换为xml(voc)格式

将json格式转化为.xml格式

import os
import json
import xml.etree.ElementTree as ET

# VOC 数据集目录
voc_dataset_dir = "/workspace/uavdt_night/all/voc_UAVDT"

# 创建 VOC 数据集目录(如果不存在)
if not os.path.exists(voc_dataset_dir):
    os.makedirs(voc_dataset_dir)

# 解析 JSON 文件并生成 VOC 标注文件
def convert_to_voc(json_file):
    with open(json_file, 'r') as f:
        coco_data = json.load(f)
        for image_info in coco_data["images"]:
            image_filename = image_info["file_name"]
            annotations = [annotation for annotation in coco_data["annotations"] if annotation["image_id"] == image_info["id"]]

            # 获取图像序号(假设文件名格式为 /workspace/uavdt_night/all/test/image_1.jpg)
            image_number = int(os.path.splitext(os.path.basename(image_filename))[0].split('_')[-1])

            # 创建 VOC 标注文件
            root = ET.Element("annotation")

            # 添加图像文件名
            filename_element = ET.SubElement(root, "filename")
            filename_element.text = image_filename

            # 添加图像尺寸信息(假设图像尺寸信息已经在 JSON 文件中提供)
            width_element = ET.SubElement(root, "width")
            width_element.text = str(image_info.get("width", "unknown"))
            height_element = ET.SubElement(root, "height")
            height_element.text = str(image_info.get("height", "unknown"))
            depth_element = ET.SubElement(root, "depth")
            depth_element.text = "3"  # 假设图像是 RGB 格式的

            # 添加目标标注信息
            for annotation in annotations:
                bbox = annotation["bbox"]
                category_id = annotation["category_id"]

                # 将类别 ID 转换为 VOC 格式的类别名称
                category_name = "unknown"  # 默认值
                if category_id == 1:
                    category_name = "car"
                elif category_id == 2:
                    category_name = "truck"
                elif category_id == 3:
                    category_name = "bus"
                    
                # 添加 VOC 标签信息
                object_element = ET.SubElement(root, "object")
                name_element = ET.SubElement(object_element, "name")
                name_element.text = category_name
                bbox_element = ET.SubElement(object_element, "bndbox")
                xmin_element = ET.SubElement(bbox_element, "xmin")
                xmin_element.text = str(bbox[0])
                ymin_element = ET.SubElement(bbox_element, "ymin")
                ymin_element.text = str(bbox[1])
                xmax_element = ET.SubElement(bbox_element, "xmax")
                xmax_element.text = str(bbox[0] + bbox[2])
                ymax_element = ET.SubElement(bbox_element, "ymax")
                ymax_element.text = str(bbox[1] + bbox[3])

            # 保存 VOC 标注文件
            voc_annotation_file = os.path.join(voc_dataset_dir, os.path.splitext(image_filename)[0] + ".xml")
            tree = ET.ElementTree(root)
            tree.write(voc_annotation_file)

# 调用函数将 JSON 文件转换为 VOC 格式
json_file_path = "/workspace/uavdt_night/all/all.json"
convert_to_voc(json_file_path)

7.转化成yolo格式

将对应的xml格式转化为yolo格式

"""将voc格式转化为yolo格式"""

import os
import xml.etree.ElementTree as ET

def voc_to_yolo_multiple(voc_folder, yolo_folder, img_width, img_height):
    for filename in os.listdir(voc_folder):
        if filename.endswith('.xml'):
            voc_xml_file = os.path.join(voc_folder, filename)
            yolo_txt_file = os.path.join(yolo_folder, os.path.splitext(filename)[0] + '.txt')
            voc_to_yolo(voc_xml_file, yolo_txt_file, img_width, img_height)

def voc_to_yolo(voc_xml_file, yolo_txt_file, img_width, img_height):
    with open(voc_xml_file, 'r') as f:
        tree = ET.parse(f)
        root = tree.getroot()

        yolo_labels = []
        for obj in root.findall('object'):
            name = obj.find('name').text
            bndbox = obj.find('bndbox')
            xmin = float(bndbox.find('xmin').text)
            ymin = float(bndbox.find('ymin').text)
            xmax = float(bndbox.find('xmax').text)
            ymax = float(bndbox.find('ymax').text)

            # 计算归一化坐标
            x_center = (xmin + xmax) / (2 * img_width)
            y_center = (ymin + ymax) / (2 * img_height)
            box_width = (xmax - xmin) / img_width
            box_height = (ymax - ymin) / img_height

            # 将类别名转换为类别编号
            class_id = -1
            if name == 'car':
                class_id = 0
            elif name == 'truck':
                class_id = 1
            elif name == 'bus':
                class_id = 2

            if class_id != -1:
                yolo_labels.append((class_id, x_center, y_center, box_width, box_height))

    # 将 YOLO 格式的标签写入文件
    with open(yolo_txt_file, 'w') as f:
        for label in yolo_labels:
            f.write('{} {:.6f} {:.6f} {:.6f} {:.6f}\n'.format(label[0], label[1], label[2], label[3], label[4]))

# 使用示例:将 VOC 文件夹中的所有 XML 文件转换为 YOLO 格式
voc_folder = '/workspace/uavdt_night/all/voc_UAVDT'
yolo_folder = '/workspace/uavdt_night/all/labels'
img_width = 1024  # 图像宽度
img_height = 540  # 图像高度
voc_to_yolo_multiple(voc_folder, yolo_folder, img_width, img_height)

部分转化后的格式为:

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
UAVDT数据集是以XML格式存储的,而Yolo格式是以txt文件存储的。因此,需要将UAVDT数据集中的XML标签转换为Yolo格式的txt文件。以下是将UAVDT数据集标签转为Yolo格式的步骤: 1. 首先需要下载UAVDT数据集,并解压缩。 2. 创建一个Python脚本,用于将XML标签转换为Yolo格式的txt文件。 3. 在脚本中导入必要的库,如xml.etree.ElementTree和os。 4. 使用os.listdir()函数来获取UAVDT数据集中所有的图像文件名,并遍历每个图像文件。 5. 对于每个图像文件,使用xml.etree.ElementTree库中的parse()函数来解析XML标签文件,并获取每个目标的类别、边界框坐标等信息。 6. 将类别转换为数字格式,并计算出中心点坐标和边界框的宽度和高度。 7. 根据Yolo格式的要求,将目标信息存储在一个txt文件中,并将该文件保存在与图像文件同名的文件夹中。 下面是一个简单的Python脚本,用于将UAVDT数据集标签转换为Yolo格式的txt文件: ```python import xml.etree.ElementTree as ET import os def convert_labels(label_dir, image_dir, output_dir): # 获取所有图像文件名 image_files = os.listdir(image_dir) for image_file in image_files: # 获取标签文件名 label_file = image_file.replace('.jpg', '.xml') label_path = os.path.join(label_dir, label_file) # 解析标签文件 tree = ET.parse(label_path) root = tree.getroot() # 遍历每个目标 for obj in root.findall('object'): # 获取类别 class_name = obj.find('name').text if class_name == 'car': class_id = 0 elif class_name == 'bus': class_id = 1 elif class_name == 'truck': class_id = 2 # 获取边界框坐标 bbox = obj.find('bndbox') x_min = float(bbox.find('xmin').text) y_min = float(bbox.find('ymin').text) x_max = float(bbox.find('xmax').text) y_max = float(bbox.find('ymax').text) # 计算中心点坐标和宽度、高度 x = (x_min + x_max) / 2.0 y = (y_min + y_max) / 2.0 w = x_max - x_min h = y_max - y_min # 将目标信息写入txt文件 txt_file = image_file.replace('.jpg', '.txt') txt_path = os.path.join(output_dir, txt_file) with open(txt_path, 'a') as f: f.write(f"{class_id} {x} {y} {w} {h}\n") ``` 在上述脚本中,convert_labels()函数接受三个参数:标签文件夹路径、图像文件夹路径和输出文件夹路径。该函数会将每个图像文件的标签转换为一个txt文件,并将该文件保存在输出文件夹中。其中,类别名称car、bus和truck分别转换为数字0、1和2。如果UAVDT数据集中有其他类别,需要根据实际情况进行修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值