| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 |
- import os
- import random
- import shutil
- import time
- # ================= 🔧 配置区域 =================
- # 请确保这个路径和你截图里的路径一模一样
- root_path = r"D:\data\20251210\20251210"
- # 划分比例 8:1:1
- split_ratios = {"train": 0.8, "val": 0.1, "test": 0.1}
- # 后缀配置
- valid_image_exts = ['.jpg', '.jpeg', '.png', '.bmp']
- valid_label_exts = ['.txt', '.xml', '.json']
- # ===============================================
- def main():
- print("==========================================")
- print(" 正在启动 8:1:1 随机划分程序")
- print("==========================================\n")
- images_root = os.path.join(root_path, "images")
- labels_root = os.path.join(root_path, "labels")
- # 1. 检查根目录
- if not os.path.exists(images_root):
- print(f"❌ 错误:找不到 images 文件夹!\n 试图寻找路径: {images_root}")
- return
- if not os.path.exists(labels_root):
- print(f"❌ 错误:找不到 labels 文件夹!\n 试图寻找路径: {labels_root}")
- return
- print(f"✅ 路径检查通过: {root_path}")
-
- # 2. 收集文件
- all_pairs = []
- # 扫描 images 下的所有文件夹(包括 train, test, val 或者其他)
- # 只要是在 images 目录下的子文件夹,都会被扫描
- sub_dirs = [d for d in os.listdir(images_root) if os.path.isdir(os.path.join(images_root, d))]
-
- # 如果 images 下没有子文件夹,可能是图片直接放在了 images 根目录下?
- # 为了兼容,如果下面没有文件夹,就扫描 images 本身
- if not sub_dirs:
- sub_dirs = ["."] # 代表当前目录
- print("⚠️ 提示:images 下没有子文件夹,将扫描 images 根目录...")
- print(f"📂 正在扫描以下文件夹: {sub_dirs}")
- for sub in sub_dirs:
- # 处理路径:如果是 "." 则不拼接子目录
- sub_img_dir = images_root if sub == "." else os.path.join(images_root, sub)
- sub_lbl_dir = labels_root if sub == "." else os.path.join(labels_root, sub)
-
- if not os.path.exists(sub_lbl_dir):
- # 如果对应的 label 文件夹不存在,跳过
- continue
- files = os.listdir(sub_img_dir)
- count_folder = 0
- for f in files:
- stem, ext = os.path.splitext(f)
- if ext.lower() in valid_image_exts:
- img_path = os.path.join(sub_img_dir, f)
-
- # 找标签
- lbl_path = None
- for lbl_ext in valid_label_exts:
- potential_lbl = os.path.join(sub_lbl_dir, stem + lbl_ext)
- if os.path.exists(potential_lbl):
- lbl_path = potential_lbl
- break
-
- if lbl_path:
- all_pairs.append({'img': img_path, 'lbl': lbl_path})
- count_folder += 1
-
- print(f" -> 在 [{sub}] 中找到 {count_folder} 对数据")
- total = len(all_pairs)
- print(f"\n📦 总共收集到: {total} 组数据")
-
- if total == 0:
- print("❌ 没有找到任何匹配的图片和标签,请检查文件名是否对应(例如 001.jpg 是否有 001.txt)。")
- return
- # 3. 打乱与计算
- print("🎲 正在打乱顺序...")
- random.shuffle(all_pairs)
-
- n_train = int(total * split_ratios["train"])
- n_val = int(total * split_ratios["val"])
- n_test = total - n_train - n_val
-
- print(f"📊 划分数量 -> Train: {n_train}, Val: {n_val}, Test: {n_test}")
- split_data = {
- "train": all_pairs[:n_train],
- "val": all_pairs[n_train : n_train + n_val],
- "test": all_pairs[n_train + n_val :]
- }
- # 4. 移动文件
- print("🚚 开始移动文件...")
-
- for split_name, items in split_data.items():
- # 目标目录
- dst_img_dir = os.path.join(images_root, split_name)
- dst_lbl_dir = os.path.join(labels_root, split_name)
-
- os.makedirs(dst_img_dir, exist_ok=True)
- os.makedirs(dst_lbl_dir, exist_ok=True)
-
- processed = 0
- for item in items:
- src_img, src_lbl = item['img'], item['lbl']
-
- # 只有当源路径不在目标路径时才移动
- if os.path.dirname(src_img) != dst_img_dir:
- try:
- shutil.move(src_img, os.path.join(dst_img_dir, os.path.basename(src_img)))
- shutil.move(src_lbl, os.path.join(dst_lbl_dir, os.path.basename(src_lbl)))
- except Exception as e:
- print(f" [Error] 移动失败: {os.path.basename(src_img)} -> {e}")
-
- processed += 1
- # 每处理 500 个打印一次进度,防止看着像死机
- if processed % 500 == 0:
- print(f" [{split_name}] 已处理 {processed} / {len(items)}")
- print(f" ✅ {split_name} 完成。")
- print("\n🎉🎉🎉 全部处理完毕! 🎉🎉🎉")
- if __name__ == "__main__":
- try:
- main()
- except Exception as e:
- print(f"\n❌ 发生严重错误: {e}")
-
- # 这里的 input 是为了防止窗口直接关闭
- print("\n--------------------------------")
- input("程序运行结束,请按回车键关闭窗口...")
|