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
相关产品推荐
相关产品推荐

