File size: 5,951 Bytes
76ec265
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
import json
from pathlib import Path

import pandas as pd
from sklearn.model_selection import train_test_split

DATA_DIR = Path(__file__).parent.parent / "data"
LABEL_FILE = Path(__file__).parent.parent / "web" / "labels.json"

# Define our selected 12 classes mapping: original_class_id -> (new_class_idx, label_name, korean_name)
SELECTED_CLASSES = {
    1: (0, "Speed Limit 30", "μ†λ„μ œν•œ 30km/h"),
    2: (1, "Speed Limit 50", "μ†λ„μ œν•œ 50km/h"),
    5: (2, "Speed Limit 80", "μ†λ„μ œν•œ 80km/h"),
    12: (3, "Priority Road", "μš°μ„ λ„λ‘œ"),
    13: (4, "Yield", "양보"),
    14: (5, "Stop", "μ •μ§€"),
    17: (6, "No Entry", "μ§„μž…κΈˆμ§€"),
    18: (7, "General Caution", "주의"),
    33: (8, "Turn Right Ahead", "μš°νšŒμ „"),
    34: (9, "Turn Left Ahead", "μ’ŒνšŒμ „"),
    38: (10, "Keep Right", "μš°μΈ‘ν†΅ν–‰"),
    40: (11, "Roundabout Mandatory", "νšŒμ „κ΅μ°¨λ‘œ"),
}


def find_gtsrb_images():
    # Check common paths for torchvision or manual extraction
    paths_to_check = [
        DATA_DIR / "gtsrb" / "GTSRB" / "Training",
        DATA_DIR / "gtsrb" / "GTSRB" / "Final_Training" / "Images",
        DATA_DIR / "GTSRB" / "Final_Training" / "Images",
        DATA_DIR / "GTSRB_Final_Training_Images" / "GTSRB" / "Final_Training" / "Images",
        DATA_DIR / "Final_Training" / "Images",
    ]

    for path in paths_to_check:
        if path.exists():
            print(f"Found GTSRB training images at: {path}")
            return path

    # Recursive search as last resort
    found = list(DATA_DIR.glob("**/Final_Training/Images"))
    if found:
        print(f"Found GTSRB training images via search at: {found[0]}")
        return found[0]

    raise FileNotFoundError(
        "Could not find GTSRB training images. Ensure download script finished successfully."
    )


def main():
    try:
        train_img_dir = find_gtsrb_images()
    except FileNotFoundError as e:
        print(e)
        return

    # Export label mapping to JSON for Web UI
    labels_mapping = {}
    for orig_id, (new_idx, name_en, name_ko) in SELECTED_CLASSES.items():
        labels_mapping[str(new_idx)] = {
            "english": name_en,
            "korean": name_ko,
            "original_id": orig_id,
        }

    # Create web folder if it doesn't exist
    LABEL_FILE.parent.mkdir(parents=True, exist_ok=True)
    with open(LABEL_FILE, "w", encoding="utf-8") as f:
        json.dump(labels_mapping, f, indent=4, ensure_ascii=False)
    print(f"Exported class mapping to {LABEL_FILE}")

    # Gather data paths
    data_records = []

    # GTSRB contains folders like 00000, 00001, etc.
    for orig_id, (new_idx, _name_en, _name_ko) in SELECTED_CLASSES.items():
        class_folder = train_img_dir / f"{orig_id:05d}"
        if not class_folder.exists():
            print(f"Warning: Class folder {class_folder} does not exist.")
            continue

        # Read the CSV inside the class folder for metadata (bounding boxes, etc.)
        csv_files = list(class_folder.glob("*.csv"))
        if not csv_files:
            # If no CSV, just grab images directly
            img_files = (
                list(class_folder.glob("*.ppm"))
                + list(class_folder.glob("*.jpg"))
                + list(class_folder.glob("*.png"))
            )
            for img_path in img_files:
                data_records.append(
                    {
                        "path": str(img_path),
                        "class_id": new_idx,
                        "roi_x1": 0,
                        "roi_y1": 0,
                        "roi_x2": 0,
                        "roi_y2": 0,
                    }
                )
        else:
            # Parse CSV metadata
            # Columns: Filename;Width;Height;Roi.X1;Roi.Y1;Roi.X2;Roi.Y2;ClassId
            df = pd.read_csv(csv_files[0], sep=";")
            for _, row in df.iterrows():
                img_path = class_folder / row["Filename"]
                if img_path.exists():
                    data_records.append(
                        {
                            "path": str(img_path),
                            "class_id": new_idx,
                            "roi_x1": int(row["Roi.X1"]),
                            "roi_y1": int(row["Roi.Y1"]),
                            "roi_x2": int(row["Roi.X2"]),
                            "roi_y2": int(row["Roi.Y2"]),
                        }
                    )

    df_dataset = pd.DataFrame(data_records)
    print(f"Total filtered samples collected: {len(df_dataset)}")

    if len(df_dataset) == 0:
        print("No samples found. Please wait for the download task to complete and try again.")
        return

    # Print distribution
    print("\nClass Distribution:")
    for new_idx in sorted(df_dataset["class_id"].unique()):
        count = len(df_dataset[df_dataset["class_id"] == new_idx])
        label = SELECTED_CLASSES[
            list(SELECTED_CLASSES.keys())[
                list(SELECTED_CLASSES.values()).index(
                    next(v for v in SELECTED_CLASSES.values() if v[0] == new_idx)
                )
            ]
        ][1]
        print(f"Class {new_idx} ({label}): {count} samples")

    # Split into train/validation sets (80/20 stratified split)
    train_df, val_df = train_test_split(
        df_dataset, test_size=0.2, random_state=42, stratify=df_dataset["class_id"]
    )

    # Save split info to data directory
    data_meta_dir = DATA_DIR / "processed"
    data_meta_dir.mkdir(parents=True, exist_ok=True)

    train_df.to_csv(data_meta_dir / "train_split.csv", index=False)
    val_df.to_csv(data_meta_dir / "val_split.csv", index=False)
    print(f"\nSaved splits to {data_meta_dir} (Train: {len(train_df)}, Val: {len(val_df)})")


if __name__ == "__main__":
    main()