{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":14668762,"sourceType":"datasetVersion","datasetId":9371241}],"dockerImageVersionId":31260,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np \nimport pandas as pd\n\nimport os\n# for dirname, _, filenames in os.walk('/kaggle/input'):\n#     for filename in filenames:\n#         print(os.path.join(dirname, filename))\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2026-02-08T15:09:36.353330Z","iopub.execute_input":"2026-02-08T15:09:36.353656Z","iopub.status.idle":"2026-02-08T15:09:37.468934Z","shell.execute_reply.started":"2026-02-08T15:09:36.353627Z","shell.execute_reply":"2026-02-08T15:09:37.468131Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!pip install ultralytics\n!pip install albumentations \n\nimport os\nimport json\nimport cv2\nimport numpy as np\nimport pandas as pd\nimport glob\nimport random\nimport shutil\nfrom tqdm.notebook import tqdm\nfrom ultralytics import YOLO\nimport matplotlib.pyplot as plt\n\nBASE_PATH = \"/kaggle/input/vista-dataset/Vistas Dataset Public/Vistas Dataset Public\"\nTRAIN_IMG_DIR = os.path.join(BASE_PATH, \"train\")\nTEST_IMG_DIR = os.path.join(BASE_PATH, \"test\")\nBG_DIR = os.path.join(BASE_PATH, \"background\")  # Using the real background files\nANNOTATIONS_PATH = os.path.join(BASE_PATH, \"instances_train.json\")\nCATEGORIES_PATH = os.path.join(BASE_PATH, \"Categories.json\")\n\n\nWORK_DIR = \"/kaggle/working\"\nSYNTHETIC_DIR = os.path.join(WORK_DIR, \"synthetic_dataset\")\n\n# Clean up if exists to avoid errors on re-run\nif os.path.exists(SYNTHETIC_DIR):\n    shutil.rmtree(SYNTHETIC_DIR)\n\nfor p in ['images/train', 'images/val', 'labels/train', 'labels/val']:\n    os.makedirs(os.path.join(SYNTHETIC_DIR, p), exist_ok=True)\n    \nprint(\"Environment Ready. YOLO installed and directories created.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-08T15:09:37.469961Z","iopub.execute_input":"2026-02-08T15:09:37.470392Z","iopub.status.idle":"2026-02-08T15:09:54.268457Z","shell.execute_reply.started":"2026-02-08T15:09:37.470355Z","shell.execute_reply":"2026-02-08T15:09:54.267777Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import json\nimport cv2\nimport os\nimport glob\nimport numpy as np\nimport random\nfrom tqdm.notebook import tqdm\n\nprint(\"Loading metadata...\")\n\nwith open(CATEGORIES_PATH, 'r') as f:\n    cat_raw = json.load(f)\n\nif isinstance(cat_raw, dict) and 'categories' in cat_raw:\n    categories = cat_raw['categories']\nelif isinstance(cat_raw, list):\n    categories = cat_raw\nelse:\n    categories = [{'id': k, 'name': v} for k, v in cat_raw.items()]\n\ncategories = sorted(categories, key=lambda x: x['id'])\ncat_id_to_yolo = {cat['id']: i for i, cat in enumerate(categories)}\nyolo_to_cat_id = {i: cat['id'] for i, cat in enumerate(categories)}\nclass_names = [cat['name'] for cat in categories]\n\nprint(f\"Loaded {len(categories)} categories.\")\n\nwith open(ANNOTATIONS_PATH, 'r') as f:\n    train_data = json.load(f)\n\n# Index images and annotations\nimages_info = {img['id']: img for img in train_data['images']}\nimg_to_anns = {}\nfor ann in train_data['annotations']:\n    img_to_anns.setdefault(ann['image_id'], []).append(ann)\n\nbg_files = glob.glob(os.path.join(BG_DIR, \"*\"))\nbackgrounds = []\nfor f in bg_files:\n    img = cv2.imread(f)\n    if img is not None:\n        backgrounds.append(img)\n        \nprint(f\"Loaded {len(backgrounds)} background templates.\")\n\n# --- HELPER FUNCTIONS ---\ndef get_crop(img_id):\n    \"\"\"Crops the object from the source training image.\"\"\"\n    if img_id not in images_info: return None, None\n    img_info = images_info[img_id]\n    \n    img_path = os.path.join(TRAIN_IMG_DIR, img_info['file_name'])\n    if not os.path.exists(img_path): return None, None\n    \n    img = cv2.imread(img_path)\n    if img is None: return None, None\n    \n    if img_id not in img_to_anns: return None, None\n    ann = img_to_anns[img_id][0]\n    x, y, w, h = map(int, ann['bbox'])\n    \n    h_img, w_img = img.shape[:2]\n    x, y = max(0, x), max(0, y)\n    w = min(w, w_img - x)\n    h = min(h, h_img - y)\n    \n    if w <= 0 or h <= 0: return None, None\n    \n    crop = img[y:y+h, x:x+w]\n    return crop, ann['category_id']\n\n# --- GENERATION LOOP ---\nNUM_SYNTH_IMAGES = 1500  \nIMG_SIZE = 640\nvalid_ids = list(images_info.keys())\n\nprint(f\"Generating {NUM_SYNTH_IMAGES} synthetic images...\")\n\nfor i in tqdm(range(NUM_SYNTH_IMAGES)):\n    if backgrounds:\n        bg_base = random.choice(backgrounds).copy()\n        bg_base = cv2.resize(bg_base, (IMG_SIZE, IMG_SIZE))\n    else:\n        bg_base = np.full((IMG_SIZE, IMG_SIZE, 3), 200, dtype=np.uint8)\n\n    labels = []\n    \n    num_objs = random.randint(3, 8)\n    \n    for _ in range(num_objs):\n        rand_id = random.choice(valid_ids)\n        crop, cat_id = get_crop(rand_id)\n        \n        if crop is None: continue\n        \n        h, w = crop.shape[:2]\n        scale = random.uniform(0.3, 0.8) \n        new_w, new_h = int(w * scale), int(h * scale)\n        if new_w < 10 or new_h < 10: continue \n        \n        crop_resized = cv2.resize(crop, (new_w, new_h))\n        \n        if IMG_SIZE - new_w <= 0 or IMG_SIZE - new_h <= 0: continue\n        x_off = random.randint(0, IMG_SIZE - new_w)\n        y_off = random.randint(0, IMG_SIZE - new_h)\n        \n        bg_base[y_off:y_off+new_h, x_off:x_off+new_w] = crop_resized\n        \n        x_c = (x_off + new_w / 2) / IMG_SIZE\n        y_c = (y_off + new_h / 2) / IMG_SIZE\n        w_n = new_w / IMG_SIZE\n        h_n = new_h / IMG_SIZE\n        \n        labels.append(f\"{cat_id_to_yolo[cat_id]} {x_c:.6f} {y_c:.6f} {w_n:.6f} {h_n:.6f}\")\n    \n    subset = 'train' if i < NUM_SYNTH_IMAGES * 0.8 else 'val'\n    fname = f\"syn_{i:05d}\"\n    \n    cv2.imwrite(os.path.join(SYNTHETIC_DIR, f'images/{subset}/{fname}.jpg'), bg_base)\n    with open(os.path.join(SYNTHETIC_DIR, f'labels/{subset}/{fname}.txt'), 'w') as f:\n        f.write('\\n'.join(labels))\n\nprint(\"Step 2 Complete: Synthetic Data Generated.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-08T15:09:54.270088Z","iopub.execute_input":"2026-02-08T15:09:54.270473Z","iopub.status.idle":"2026-02-08T15:13:52.294296Z","shell.execute_reply.started":"2026-02-08T15:09:54.270446Z","shell.execute_reply":"2026-02-08T15:13:52.293531Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport glob\nimport os\nimport json\nfrom ultralytics import YOLO\nfrom tqdm.notebook import tqdm\n\n# --- CONFIGURATION ---\nWORK_DIR = \"/kaggle/working\"\nTEST_IMG_DIR = TEST_IMG_DIR = \"/kaggle/input/vista-dataset/Vistas Dataset Public/Vistas Dataset Public/test\"\nCATEGORIES_PATH = \"/kaggle/input/vista-dataset/Vistas Dataset Public/Vistas Dataset Public/Categories.json\"\nSYNTHETIC_DIR = os.path.join(WORK_DIR, \"synthetic_dataset\")\n\nprint(\"Verifying Class Names...\")\nwith open(CATEGORIES_PATH, 'r') as f:\n    cat_raw = json.load(f)\n    if isinstance(cat_raw, dict) and 'categories' in cat_raw: cats = cat_raw['categories']\n    elif isinstance(cat_raw, list): cats = cat_raw\n    else: cats = [{'id': k, 'name': v} for k, v in cat_raw.items()]\n    \n    cats = sorted(cats, key=lambda x: x['id'])\n    class_names = [c['name'] for c in cats]\n    # mapping: YOLO Index -> Real Category ID\n    yolo_to_cat_id = {i: c['id'] for i, c in enumerate(cats)}\n\n# Data YAML\nyaml_content = f\"\"\"\npath: {SYNTHETIC_DIR}\ntrain: images/train\nval: images/val\nnames: {class_names}\n\"\"\"\nwith open(\"vista.yaml\", \"w\") as f:\n    f.write(yaml_content)\n\n# YOLOv8\nprint(\"Starting Training...\")\nmodel = YOLO(\"yolov8s.pt\") \n\nmodel.train(\n    data=\"vista.yaml\",\n    epochs=50, \n    imgsz=640,\n    batch=16,\n    project=\"vista_cv\", \n    name=\"submission_run\",\n    verbose=True,\n    exist_ok=True\n)\n\nprint(\"Searching for trained model weights...\")\npossible_weights = glob.glob(os.path.join(WORK_DIR, \"**\", \"best.pt\"), recursive=True)\n\nif not possible_weights:\n    raise FileNotFoundError(\"Could not find 'best.pt'. Training might have failed.\")\n\nbest_weight_path = possible_weights[-1] \nprint(f\"FOUND WEIGHTS AT: {best_weight_path}\")\n\nbest_model = YOLO(best_weight_path)\n\ntest_files = glob.glob(os.path.join(TEST_IMG_DIR, \"*.jpg\"))\nif not test_files:\n    print(\"Test folder empty! Using Validation folder for demo purposes.\")\n    test_files = glob.glob(\"/kaggle/input/vista26/Vistas Dataset Public/Vistas Dataset Public/validation/*.jpg\")\n\nprint(f\"Predicting on {len(test_files)} images...\")\n\nsubmission_rows = []\nCONF_THRESHOLD = 0.50 \n\nfor img_path in tqdm(test_files):\n    img_id = os.path.basename(img_path).split('.')[0]\n    \n    results = best_model.predict(img_path, conf=CONF_THRESHOLD, verbose=False)[0]\n    \n    preds_str = []\n    for box in results.boxes:\n        cls_idx = int(box.cls[0])\n        # Map back to Real Category ID\n        real_cat_id = yolo_to_cat_id.get(cls_idx, cls_idx)\n        \n        conf = float(box.conf[0])\n        x1, y1, x2, y2 = box.xyxy[0].tolist()\n        \n        preds_str.append(f\"{real_cat_id} {conf:.4f} {x1:.2f} {y1:.2f} {x2:.2f} {y2:.2f}\")\n        \n    submission_rows.append({\n        \"ImageID\": img_id,\n        \"PredictionString\": \" \".join(preds_str)\n    })\n\ndf = pd.DataFrame(submission_rows)\ndf = df[['ImageID', 'PredictionString']] \ndf.to_csv(\"submission.csv\", index=False)\n\nprint(f\"SUCCESS: submission.csv generated with {len(df)} rows.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-08T15:13:52.295331Z","iopub.execute_input":"2026-02-08T15:13:52.295558Z","iopub.status.idle":"2026-02-08T16:08:46.219663Z","shell.execute_reply.started":"2026-02-08T15:13:52.295536Z","shell.execute_reply":"2026-02-08T16:08:46.218992Z"}},"outputs":[],"execution_count":null}]}