File size: 6,533 Bytes
5b86813
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
#!/usr/bin/env python3
"""
Integrate GAN synthetic data into YOLO training dataset.

This script converts synthetic patches from GAN training into complete
YOLO-format images with annotations for dataset augmentation.

Usage:
    python integrate_gan.py [--num-synthetic 1000]
"""

import os
import sys
import argparse
import random
from pathlib import Path
import cv2
import numpy as np

# Paths
SYNTHETIC_ROOT = Path("/home/pragadeesh/ARM/model/dataset/synthetic")
DATASET_ROOT = Path("/home/pragadeesh/ARM/model/dataset")
TRAIN_IMAGES = DATASET_ROOT / "train" / "images"
TRAIN_LABELS = DATASET_ROOT / "train" / "labels"

# Class mapping
CLASS_NAMES = {
    "pothole": 0,
    "cracks": 1,
    "open_manhole": 2
}

PATCH_SIZE = 64
SYNTHETIC_IMAGE_SIZE = 416  # YOLO training size


def create_synthetic_yolo_image(patches, class_id, image_size=SYNTHETIC_IMAGE_SIZE):
    """
    Create a YOLO-format image by composing GAN patches.
    
    Args:
        patches: List of patch arrays
        class_id: Class ID for the patches
        image_size: Output image size
    
    Returns:
        Tuple of (image, label_data)
    """
    image = np.ones((image_size, image_size, 3), dtype=np.uint8) * 128  # Gray background
    label_bboxes = []
    pixel_bboxes = []
    
    # Place patches randomly on image
    num_patches = random.randint(2, 5)
    selected_patches = random.sample(patches, min(num_patches, len(patches)))
    
    for patch_idx, patch in enumerate(selected_patches):
        # Random position
        max_x = image_size - PATCH_SIZE
        max_y = image_size - PATCH_SIZE
        
        x = random.randint(0, max(1, max_x))
        y = random.randint(0, max(1, max_y))
        
        # Ensure no overlap with previous patches
        overlaps = False
        for bx1, by1, bx2, by2 in pixel_bboxes:
            if not (x + PATCH_SIZE < bx1 or x > bx2 or 
                   y + PATCH_SIZE < by1 or y > by2):
                overlaps = True
                break
        
        if overlaps and len(pixel_bboxes) > 0:
            continue
        
        # Place patch
        image[y:y+PATCH_SIZE, x:x+PATCH_SIZE] = patch
        
        # Record bounding box (center coordinates, normalized)
        x_center = (x + PATCH_SIZE / 2) / image_size
        y_center = (y + PATCH_SIZE / 2) / image_size
        width = PATCH_SIZE / image_size
        height = PATCH_SIZE / image_size
        
        label_bboxes.append((class_id, x_center, y_center, width, height))
        pixel_bboxes.append((x, y, x + PATCH_SIZE, y + PATCH_SIZE))
    
    return image, label_bboxes


def integrate_synthetic_data(num_synthetic_per_class):
    """Integrate synthetic data into training dataset."""
    
    print("\n" + "="*70)
    print("INTEGRATING GAN SYNTHETIC DATA INTO YOLO DATASET")
    print("="*70)
    
    # Check directories
    if not SYNTHETIC_ROOT.exists():
        print(f"✗ Synthetic data not found: {SYNTHETIC_ROOT}")
        print("  Run 'python gan_train.py' first")
        sys.exit(1)
    
    if not TRAIN_IMAGES.exists():
        print(f"✗ Training images directory not found: {TRAIN_IMAGES}")
        sys.exit(1)
    
    # Load synthetic patches per class
    synthetic_patches = {}
    
    for class_name, class_id in CLASS_NAMES.items():
        class_dir = SYNTHETIC_ROOT / class_name
        
        if not class_dir.exists():
            print(f"⚠ No synthetic data for {class_name}")
            continue
        
        patches = []
        patch_files = list(class_dir.glob("*.jpg"))
        
        print(f"\nLoading synthetic patches for {class_name}...")
        print(f"  Found: {len(patch_files)} patches")
        
        for patch_file in patch_files:
            try:
                patch = cv2.imread(str(patch_file))
                if patch is not None:
                    patches.append(patch)
            except:
                pass
        
        if patches:
            synthetic_patches[class_name] = patches
            print(f"  Loaded: {len(patches)} patches")
    
    if not synthetic_patches:
        print("✗ No synthetic patches loaded")
        sys.exit(1)
    
    # Generate synthetic YOLO images
    print(f"\n{'='*70}")
    print("GENERATING SYNTHETIC YOLO IMAGES")
    print(f"{'='*70}")
    
    # Get current image count for naming
    existing_images = list(TRAIN_IMAGES.glob("*.jpg")) + list(TRAIN_IMAGES.glob("*.png"))
    next_id = max([int(f.stem) for f in existing_images if f.stem.isdigit()] + [0]) + 1
    
    total_generated = 0
    
    for class_name, class_id in CLASS_NAMES.items():
        if class_name not in synthetic_patches:
            continue
        
        patches = synthetic_patches[class_name]
        print(f"\nGenerating for {class_name}...")
        
        for i in range(num_synthetic_per_class):
            # Create synthetic YOLO image
            image, bboxes = create_synthetic_yolo_image(patches, class_id)
            
            # Save image
            image_id = f"{next_id:06d}"
            image_path = TRAIN_IMAGES / f"{image_id}.jpg"
            cv2.imwrite(str(image_path), image)
            
            # Save label
            label_path = TRAIN_LABELS / f"{image_id}.txt"
            with open(label_path, 'w') as f:
                for class_id, x_center, y_center, width, height in bboxes:
                    f.write(f"{class_id} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}\n")
            
            next_id += 1
            total_generated += 1
            
            if (i + 1) % 100 == 0:
                print(f"  Progress: {i+1}/{num_synthetic_per_class}")
        
        print(f"  ✓ Generated {num_synthetic_per_class} images for {class_name}")
    
    print(f"\n{'='*70}")
    print("INTEGRATION COMPLETE")
    print(f"{'='*70}")
    print(f"Total synthetic images generated: {total_generated}")
    print(f"New training set size: {len(list(TRAIN_IMAGES.glob('*')))}")
    print(f"\nTo train with synthetic data:")
    print(f"  python train_road_anomaly_model.py")
    print(f"{'='*70}\n")


def main():
    """Main entry point."""
    parser = argparse.ArgumentParser(
        description="Integrate GAN synthetic data into YOLO training dataset"
    )
    parser.add_argument(
        "--num-synthetic",
        type=int,
        default=100,
        help="Number of synthetic images per class (default: 100)"
    )
    
    args = parser.parse_args()
    
    integrate_synthetic_data(args.num_synthetic)


if __name__ == "__main__":
    main()