| import shutil |
| import yaml |
| from pathlib import Path |
| from sklearn.model_selection import train_test_split |
|
|
|
|
| def load_config(config_path: Path) -> dict: |
| with open(config_path, "r") as f: |
| return yaml.safe_load(f) |
|
|
|
|
| def split_data(config: dict, project_root: Path) -> None: |
| crops_dir = project_root / config["data"]["cropped_persons_dir"] |
| staging_dir = project_root / config["data"]["staging_dir"] |
| class_names = config["classes"] |
| seed = config["project"]["random_seed"] |
| train_ratio = config["split"]["train_ratio"] |
| val_ratio = config["split"]["val_ratio"] |
|
|
| for split in ("train", "val", "test"): |
| for cls in class_names: |
| (crops_dir / split / cls).mkdir(parents=True, exist_ok=True) |
|
|
| all_files = [] |
| all_labels = [] |
|
|
| for cls in class_names: |
| cls_dir = staging_dir / cls |
| if not cls_dir.exists(): |
| print( |
| f"Warning: {cls_dir} does not exist, skipping." |
| ) |
| continue |
| for img in sorted(cls_dir.glob("*.jpg")): |
| all_files.append(img) |
| all_labels.append(cls) |
|
|
| if not all_files: |
| print( |
| f"No images found in staging subdirectories " |
| f"under {staging_dir}" |
| ) |
| return |
|
|
| val_test_ratio = 1.0 - train_ratio |
| relative_val = val_ratio / val_test_ratio |
|
|
| train_files, val_test_files, train_labels, val_test_labels = train_test_split( |
| all_files, all_labels, |
| test_size=val_test_ratio, |
| stratify=all_labels, |
| random_state=seed, |
| ) |
|
|
| val_files, test_files, _, _ = train_test_split( |
| val_test_files, val_test_labels, |
| test_size=(1.0 - relative_val), |
| stratify=val_test_labels, |
| random_state=seed, |
| ) |
|
|
| for f in train_files: |
| cls = f.parent.name |
| shutil.move(str(f), str(crops_dir / "train" / cls / f.name)) |
|
|
| for f in val_files: |
| cls = f.parent.name |
| shutil.move(str(f), str(crops_dir / "val" / cls / f.name)) |
|
|
| for f in test_files: |
| cls = f.parent.name |
| shutil.move(str(f), str(crops_dir / "test" / cls / f.name)) |
|
|
| print("Split complete.") |
| print(f" Train: {len(train_files)} crops") |
| print(f" Val: {len(val_files)} crops") |
| print(f" Test: {len(test_files)} crops") |
| print(f" Total: {len(train_files) + len(val_files) + len(test_files)} crops") |
|
|
|
|
| if __name__ == "__main__": |
| project_root = Path(__file__).resolve().parents[2] |
| config_path = project_root / "config.yaml" |
| config = load_config(config_path) |
| split_data(config, project_root) |
|
|