You need to enable JavaScript to run this app. YoloV4自定义数据集训练、验证集划分图片与标签不匹配问题求助
优惠活动
大模型
产品
解决方案
定价
更多

YoloV4自定义数据集训练、验证集划分图片与标签不匹配问题求助

错误原因定位

你之前的代码从两个层面破坏了图像和标注的配对关系:

  • 全局扫描的img_paths和txt_paths是两个完全独立的列表,没有做配对校验,只要存在无标注的孤儿图、无图的孤儿标注,两个列表的长度、元素对应关系从一开始就存在错位
  • 传入train_test_split做拆分时,两个列表是分别独立随机切分的,函数本身没有内置"某张图和对应txt必须分到同一组"的绑定规则,最终自然会出现图和标注被拆到不同子集的问题。
正确拆分的核心逻辑

全程 不将标注文件作为独立拆分输入,只以配对有效的图像为拆分决策单元:拆分完成后,再通过文件名匹配逻辑,把同名称的标注文件和对应图像一并复制到目标子集,从根源上避免配对错乱。

可直接复用的拆分实现
import os
import glob
import shutil
from sklearn.model_selection import train_test_split

# 基础配置
# 原始数据集路径,对应你之前代码里的../TrainingsData/(图像和txt标注混放的目录)
raw_data_dir = "../TrainingsData/"
# 拆分后输出的根目录
output_base_dir = "../SplitDataset/"
# 验证集占比,和你之前的设置保持一致
val_split_ratio = 0.3
# 固定随机种子,保证拆分结果可复现
random_seed = 42

# 第一步:校验图像和标注的配对关系,过滤无效文件
all_txt_files = set(glob.glob(os.path.join(raw_data_dir, "*.txt")))
valid_img_list = []

for img_path in glob.glob(os.path.join(raw_data_dir, "*.jpg")):
    # 通过文件名匹配对应的标注文件(YOLO格式要求同名对应)
    img_stem = os.path.splitext(img_path)[0]
    expected_txt = img_stem + ".txt"
    # 只有存在对应标注的图像才纳入拆分样本
    if expected_txt in all_txt_files:
        valid_img_list.append(img_path)

print(f"配对校验完成:共找到 {len(valid_img_list)} 组有效的图像-标注对")

# 第二步:仅对有效图像列表做拆分,不拆分标注列表,保证配对绑定
train_imgs, val_imgs = train_test_split(
    valid_img_list,
    test_size=val_split_ratio,
    random_state=random_seed
)

# 第三步:创建符合YOLO训练规范的输出目录结构
for split in ["train", "val"]:
    os.makedirs(os.path.join(output_base_dir, split, "images"), exist_ok=True)
    os.makedirs(os.path.join(output_base_dir, split, "labels"), exist_ok=True)

# 第四步:把拆分后的图像和对应标注一同复制到目标目录
def copy_split_resources(img_paths, split_name):
    for img_path in img_paths:
        # 复制图像文件
        img_name = os.path.basename(img_path)
        shutil.copy(
            img_path,
            os.path.join(output_base_dir, split_name, "images", img_name)
        )
        # 匹配并复制对应的标注文件
        txt_name = os.path.splitext(img_name)[0] + ".txt"
        src_txt = os.path.join(raw_data_dir, txt_name)
        shutil.copy(
            src_txt,
            os.path.join(output_base_dir, split_name, "labels", txt_name)
        )

copy_split_resources(train_imgs, "train")
copy_split_resources(val_imgs, "val")

print(f"拆分完成:训练集共 {len(train_imgs)} 个样本,验证集共 {len(val_imgs)} 个样本")
关键注意事项
  • 代码采用shutil.copy而非移动文件,不会改动原始数据集的内容,拆分操作完全可逆
  • 输出的目录结构为YOLO训练的标准结构,可直接在YOLOv4的.data配置文件中指定路径:
    train = ../SplitDataset/train/images
    valid = ../SplitDataset/val/images
    
  • 拆分完成后可快速校验:遍历每个子集的images目录,检查每个图像对应的同名txt是否存在于同子集的labels目录,确认没有配对遗漏后再开始训练。

内容的提问来源于stack exchange,提问作者Basti

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.30 15:24:03