码农-小林 2025-09-11 16:51 采纳率: 54.8%
浏览 3

利用voc_label.py生成的生成的验证集合和训练集合路径问题

利用voc_label.py生成的生成的验证集合和训练集合路径是一样的对吗

import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join

sets=[('2025', 'train'), ('2025', 'val')]

classes = ["Shu"]


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(year, image_id):
    in_file = open('D:/YOLO/darknet-master/scripts/VOCdevkit/VOC%s/Annotations/%s.xml'%(year, image_id))
    out_file = open('D:/YOLO/darknet-master/scripts/VOCdevkit/VOC%s/labels/%s.txt'%(year, 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
            break
        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')
        
wd = getcwd()

for year, image_set in sets:
    if not os.path.exists('D:/YOLO/darknet-master/scripts/VOCdevkit/VOC%s/labels/'%(year)):
        os.makedirs('D:/YOLO/darknet-master/scripts/VOCdevkit/VOC%s/labels/'%(year))
    image_ids = open('D:/YOLO/darknet-master/scripts/VOCdevkit/VOC%s/ImageSets/Main/%s.txt'%(year, image_set)).read().strip().split()
   # list_file = open('%s_%s.txt'%(year, image_set), 'w')
    list_file = open('D:/YOLO/darknet-master/scripts/VOCdevkit/VOC2025/ImageSets/Main/%s_%s.txt'%(year, image_set), 'w')

    for image_id in image_ids:
        print(image_id)
        #list_file.write('%sD:/YOLO/darknet-master/scripts/VOCdevkit/VOC%s/JPEGImages/%s.jpg\n'%(wd, year, image_id))
        list_file.write('D:/YOLO/darknet-master/scripts/VOCdevkit/VOC%s/JPEGImages/%s.jpg\n'%(year, image_id))
        convert_annotation(year, image_id)
    list_file.close()

2025_trian.txt下

img


2025_val.txt下

img

  • 写回答

4条回答 默认 最新

  • 檀越@新空间 2025-09-11 16:52
    关注

    下午好🌅🌅🌅
    本答案参考通义千问

    你提到的问题是关于使用 voc_label.py 脚本生成的训练集和验证集的路径是否一致。根据你提供的代码片段,我们可以分析并解决这个问题。


    问题分析

    从你的代码中可以看出:

    • 你定义了 sets = [('2025', 'train'), ('2025', 'val')]
    • 这意味着你正在处理一个名为 VOC2025 的数据集
    • 在生成标签文件(.txt)时,脚本会将它们写入到 VOC2025/labels/ 目录下
    • 在生成图像列表文件(如 2025_train.txt2025_val.txt)时,你也指定了路径为 VOC2025/ImageSets/Main/

    但是,在以下部分,你存在一个明显的路径错误:

    list_file = open('D:/YOLO/darknet-master/scripts/VOCdevkit/VOC2025/ImageSets/Main/%s_%s.txt'%(year, image_set), 'w')
    

    这个路径中,VOC2025 是一个固定的名称,而 year'2025',所以最终路径是:

    D:/YOLO/darknet-master/scripts/VOCdevkit/VOC2025/ImageSets/Main/2025_train.txt
    D:/YOLO/darknet-master/scripts/VOCdevkit/VOC2025/ImageSets/Main/2025_val.txt
    

    这说明:

    训练集和验证集的路径是相同的,都是指向 VOC2025 文件夹下的 ImageSets/Main 目录

    因此,训练集和验证集的路径确实是一样的,这是不合理的,因为通常我们希望训练集和验证集保存在不同的目录中以避免混淆。


    解决方案

    1. 明确区分训练集和验证集的路径

    你应该确保训练集和验证集分别保存在不同的目录中。例如:

    • 训练集:VOC2025/train/
    • 验证集:VOC2025/val/

    2. 修改路径配置

    修改代码中的路径部分,确保 trainval 分别写入不同的文件夹。

    3. 更新代码示例(修改后)

    下面是修改后的代码段,重点部分已加粗:

    # 定义 sets 为年份和集合类型(train / val)
    sets = [('2025', 'train'), ('2025', 'val')]
    
    # 类别列表
    classes = ["Shu"]
    
    def convert(size, box):
        # ...(保持原样)
    
    def convert_annotation(year, image_id):
        # ...(保持原样)
    
    # 设置工作目录
    wd = getcwd()
    
    for year, image_set in sets:
        # 创建 labels 文件夹(按 train/val 分类)
        labels_dir = f'D:/YOLO/darknet-master/scripts/VOCdevkit/VOC{year}/labels/{image_set}'
        if not os.path.exists(labels_dir):
            os.makedirs(labels_dir)
        
        # 指定图像列表文件路径(按 train/val 分类)
        list_file_path = f'D:/YOLO/darknet-master/scripts/VOCdevkit/VOC{year}/ImageSets/Main/{image_set}.txt'
        list_file = open(list_file_path, 'w')
    
        # 获取图像 ID 列表
        image_ids = open(f'D:/YOLO/darknet-master/scripts/VOCdevkit/VOC{year}/ImageSets/Main/{image_set}.txt').read().strip().split()
    
        for image_id in image_ids:
            list_file.write(f'D:/YOLO/darknet-master/scripts/VOCdevkit/VOC{year}/JPEGImages/{image_id}.jpg\n')
            convert_annotation(year, image_id)
    
        list_file.close()
    

    关键点总结

    1. 路径重复问题
      原始代码中,trainval 的标签和图像列表都写入同一个目录(VOC2025/...),导致路径重复。

    2. 建议修改方向

      • 使用 image_set 字段动态生成路径(如 trainval
      • 确保 labelsImageSets 中的子目录独立
    3. 修改后的路径结构示例

      D:/YOLO/darknet-master/scripts/VOCdevkit/VOC2025/
          ├── JPEGImages/
          ├── Annotations/
          ├── labels/
          │   ├── train/
          │   └── val/
          └── ImageSets/
              └── Main/
                  ├── train.txt
                  └── val.txt
      

    结论

    是的,训练集和验证集的路径原本是相同的,但通过修改路径逻辑,可以实现它们的路径分离。

    如果你需要我进一步帮助你构建完整的 VOC 数据集结构或生成其他格式的数据,请告诉我!

    评论

报告相同问题?

问题事件

  • 创建了问题 9月11日