{"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":"gpu","dataSources":[{"sourceId":128792,"databundleVersionId":15494745,"sourceType":"competition"}],"dockerImageVersionId":31259,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"%pip install ultralytics\nimport ultralytics\nultralytics.checks()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-29T08:34:53.119024Z","iopub.execute_input":"2026-01-29T08:34:53.119297Z","iopub.status.idle":"2026-01-29T08:35:04.494035Z","shell.execute_reply.started":"2026-01-29T08:34:53.119273Z","shell.execute_reply":"2026-01-29T08:35:04.493317Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import json\nimport os\n\n# 1. Find the JSON file\njson_path = None\nfor root, dirs, files in os.walk('/kaggle/input'):\n    if \"instances_train.json\" in files:\n        json_path = os.path.join(root, \"instances_train.json\")\n        break\n\nif json_path:\n    print(f\"✅ Found file at: {json_path}\")\n    \n    # 2. Open it and count\n    with open(json_path, 'r') as f:\n        data = json.load(f)\n    \n    # Get all unique category IDs from annotations\n    unique_ids = set()\n    for ann in data['annotations']:\n        unique_ids.add(ann['category_id'])\n    \n    sorted_ids = sorted(list(unique_ids))\n    \n    print(\"-\" * 30)\n    print(f\"📊 TOTAL UNIQUE OBJECTS: {len(sorted_ids)}\")\n    print(f\"🔢 THE IDS ARE: {sorted_ids}\")\n    print(\"-\" * 30)\n    \n    # Check if they are simple (0, 1, 2...) or crazy (132, 194...)\n    if sorted_ids[-1] == len(sorted_ids) - 1:\n        print(\"✅ IDs are simple (0 to N). No fixing needed!\")\n    else:\n        print(\"⚠️ IDs are CRAZY (e.g. 194, 132). We MUST use the Mapper/Translator.\")\n\nelse:\n    print(\"❌ Could not find 'instances_train.json'\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-29T08:35:04.496054Z","iopub.execute_input":"2026-01-29T08:35:04.496670Z","iopub.status.idle":"2026-01-29T08:35:04.995388Z","shell.execute_reply.started":"2026-01-29T08:35:04.496634Z","shell.execute_reply":"2026-01-29T08:35:04.994435Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import cv2\nimport json\nimport os\nimport random\nimport numpy as np\nfrom tqdm import tqdm\nimport shutil\nfrom ultralytics import YOLO\n\n# --- 1. SETUP PATHS ---\n# We use the path YOU found:\nINPUT_ROOT = \"/kaggle/input/vista26/Vistas Dataset Public/Vistas Dataset Public\"\nJSON_PATH = os.path.join(INPUT_ROOT, \"instances_train.json\")\nTRAIN_IMG_DIR = os.path.join(INPUT_ROOT, \"train\")\nBG_IMG_PATH = \"/kaggle/input/vista26/Vistas Dataset Public/bg1.jpg\" # Trying likely path\nOUTPUT_DIR = \"/kaggle/working/vista_synthetic\"\n\nprint(f\"✅ Target Locked: {JSON_PATH}\")\n\n# --- 2. PREPARE THE DATA (With the 200-Class Logic) ---\nprint(\"✂️ extracting sprites...\")\nwith open(JSON_PATH, 'r') as f:\n    coco = json.load(f)\n\nsprites = []\nimg_map = {img['id']: img['file_name'] for img in coco['images']}\n\n# Limit to 1000 sprites for RAM safety\nMAX_SPRITES = 1000 \nall_anns = coco['annotations']\nrandom.shuffle(all_anns)\n\nfor ann in tqdm(all_anns):\n    if len(sprites) >= MAX_SPRITES: break\n    \n    img_id = ann['image_id']\n    cat_id = ann['category_id']\n    \n    # --- THE FIX YOU FOUND ---\n    # The JSON has IDs 1-200. YOLO needs 0-199.\n    # We simply subtract 1.\n    if cat_id < 1 or cat_id > 200: continue # Skip weird errors\n    \n    file_name = img_map.get(img_id)\n    if not file_name: continue\n    \n    path = os.path.join(TRAIN_IMG_DIR, file_name)\n    if not os.path.exists(path): continue # Skip missing files\n    \n    full_img = cv2.imread(path)\n    if full_img is None: continue\n    \n    x, y, w, h = map(int, ann['bbox'])\n    obj_crop = full_img[y:y+h, x:x+w]\n    if obj_crop.size == 0: continue\n\n    # Resize huge objects to save RAM\n    if obj_crop.shape[0] > 300:\n        scale = 300 / obj_crop.shape[0]\n        obj_crop = cv2.resize(obj_crop, (0,0), fx=scale, fy=scale)\n\n    # Remove background (Green Screen logic)\n    gray = cv2.cvtColor(obj_crop, cv2.COLOR_BGR2GRAY)\n    _, mask = cv2.threshold(gray, 240, 255, cv2.THRESH_BINARY_INV)\n    obj_crop = cv2.bitwise_and(obj_crop, obj_crop, mask=mask)\n\n    sprites.append({'img': obj_crop, 'cat_id': cat_id})\n\nprint(f\"✅ Extracted {len(sprites)} valid sprites.\")\n\n# --- 3. GENERATE IMAGES ---\nif os.path.exists(OUTPUT_DIR): shutil.rmtree(OUTPUT_DIR)\nos.makedirs(f\"{OUTPUT_DIR}/images/train\", exist_ok=True)\nos.makedirs(f\"{OUTPUT_DIR}/labels/train\", exist_ok=True)\nos.makedirs(f\"{OUTPUT_DIR}/images/val\", exist_ok=True)\nos.makedirs(f\"{OUTPUT_DIR}/labels/val\", exist_ok=True)\n\nprint(\"🎨 Painting 2500 synthetic scenes...\")\n# Create a black background if file not found\nif os.path.exists(BG_IMG_PATH):\n    bg_base = cv2.imread(BG_IMG_PATH)\n    bg_base = cv2.resize(bg_base, (640, 640))\nelse:\n    bg_base = np.zeros((640, 640, 3), dtype=np.uint8)\n\nbg_h, bg_w, _ = bg_base.shape\n\nfor i in tqdm(range(2500)):\n    subset = \"train\" if i < 2000 else \"val\"\n    scene = bg_base.copy()\n    labels = []\n    \n    for _ in range(random.randint(3, 8)):\n        if not sprites: break\n        sprite_data = random.choice(sprites)\n        sprite = sprite_data['img']\n        \n        # --- THE LOGIC FIX ---\n        # JSON ID (1-200) -> YOLO ID (0-199)\n        yolo_class_id = sprite_data['cat_id'] - 1\n        # ---------------------\n\n        # Random Rotate & Place\n        rot = random.choice([None, cv2.ROTATE_90_CLOCKWISE, cv2.ROTATE_180])\n        if rot: sprite = cv2.rotate(sprite, rot)\n        \n        h, w, _ = sprite.shape\n        max_x, max_y = bg_w - w, bg_h - h\n        if max_x <= 0 or max_y <= 0: continue\n        px, py = random.randint(0, max_x), random.randint(0, max_y)\n        \n        roi = scene[py:py+h, px:px+w]\n        gray_s = cv2.cvtColor(sprite, cv2.COLOR_BGR2GRAY)\n        _, mask = cv2.threshold(gray_s, 1, 255, cv2.THRESH_BINARY)\n        mask_inv = cv2.bitwise_not(mask)\n        scene[py:py+h, px:px+w] = cv2.add(cv2.bitwise_and(roi, roi, mask=mask_inv), cv2.bitwise_and(sprite, sprite, mask=mask))\n        \n        labels.append(f\"{yolo_class_id} {(px+w/2)/bg_w} {(py+h/2)/bg_h} {w/bg_w} {h/bg_h}\")\n\n    filename = f\"syn_{i:05d}\"\n    cv2.imwrite(f\"{OUTPUT_DIR}/images/{subset}/{filename}.jpg\", scene)\n    with open(f\"{OUTPUT_DIR}/labels/{subset}/{filename}.txt\", \"w\") as f:\n        f.write(\"\\n\".join(labels))\n\n# --- 4. CREATE CONFIG (NC=200) ---\nprint(\"📝 Creating vista.yaml with 200 classes...\")\nnames_list = [f\"Class_{i+1}\" for i in range(200)] # Names: Class_1 to Class_200\n\nyaml_content = f\"\"\"\npath: /kaggle/working/vista_synthetic\ntrain: images/train\nval: images/val\n\nnc: 200 \nnames: {names_list}\n\"\"\"\nwith open(\"vista.yaml\", \"w\") as f:\n    f.write(yaml_content)\n\n# --- 5. START TRAINING ---\nprint(\"🚀 Starting Training on 200 Classes...\")\nmodel = YOLO(\"yolo11n.pt\") \nresults = model.train(data=\"vista.yaml\", epochs=50, imgsz=640, batch=16, name=\"vista_final_200\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-29T08:35:04.996508Z","iopub.execute_input":"2026-01-29T08:35:04.996849Z","iopub.status.idle":"2026-01-29T09:04:14.665220Z","shell.execute_reply.started":"2026-01-29T08:35:04.996795Z","shell.execute_reply":"2026-01-29T09:04:14.664216Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from ultralytics import YOLO\nimport matplotlib.pyplot as plt\nimport cv2\nimport os\nimport random\n\n# 1. Load your trained brain\nmodel = YOLO(\"/kaggle/working/runs/detect/vista_final_200/weights/best.pt\")\n\n# 2. Pick a random image from the Validation set\nval_images_path = \"/kaggle/working/vista_synthetic/images/val\"\nrandom_file = random.choice(os.listdir(val_images_path))\nimage_path = os.path.join(val_images_path, random_file)\n\n# 3. Run Prediction\nresults = model.predict(image_path)\n\n# 4. Show the Result\n# Plotting logic using Matplotlib (since cv2.imshow doesn't work well in notebooks)\nresult_image = results[0].plot() # This draws the boxes\nresult_image = cv2.cvtColor(result_image, cv2.COLOR_BGR2RGB) # Fix colors for display\n\nplt.figure(figsize=(12, 12))\nplt.imshow(result_image)\nplt.axis('off')\nplt.title(f\"Prediction on: {random_file}\")\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-29T09:18:10.664666Z","iopub.execute_input":"2026-01-29T09:18:10.665024Z","iopub.status.idle":"2026-01-29T09:18:11.117583Z","shell.execute_reply.started":"2026-01-29T09:18:10.664991Z","shell.execute_reply":"2026-01-29T09:18:11.116768Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from ultralytics import YOLO\n\n# Load your best model\nmodel = YOLO(\"/kaggle/working/runs/detect/vista_final_200/weights/best.pt\")\n\nprint(\"📊 1. Checking TEST Data (Validation)...\")\n# This is what you already saw, but good to double-check\nmetrics_val = model.val(split='val') \nprint(f\"Test mAP50: {metrics_val.box.map50}\")\n\nprint(\"\\n📊 2. Checking TRAINING Data...\")\n# We force it to test on the 'train' split\nmetrics_train = model.val(split='train')\nprint(f\"Train mAP50: {metrics_train.box.map50}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-29T09:21:27.534916Z","iopub.execute_input":"2026-01-29T09:21:27.535798Z","iopub.status.idle":"2026-01-29T09:22:01.218522Z","shell.execute_reply.started":"2026-01-29T09:21:27.535756Z","shell.execute_reply":"2026-01-29T09:22:01.217269Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport cv2\nimport os\nimport random\n\ndef predict_and_plot(folder_path, title):\n    # Pick random file\n    files = os.listdir(folder_path)\n    if not files:\n        print(f\"No files in {folder_path}\")\n        return\n    filename = random.choice(files)\n    path = os.path.join(folder_path, filename)\n    \n    # Predict\n    results = model.predict(path)\n    \n    # Plot\n    img = results[0].plot()\n    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n    plt.imshow(img)\n    plt.title(f\"{title}\\n({filename})\")\n    plt.axis('off')\n\n# Set up the plot\nplt.figure(figsize=(15, 7))\n\n# Plot Training Example\nplt.subplot(1, 2, 1)\npredict_and_plot(\"/kaggle/working/vista_synthetic/images/train\", \"TRAINING DATA (Memorized)\")\n\n# Plot Test Example\nplt.subplot(1, 2, 2)\npredict_and_plot(\"/kaggle/working/vista_synthetic/images/val\", \"TEST DATA (New Exam)\")\n\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-29T09:22:01.615994Z","iopub.execute_input":"2026-01-29T09:22:01.616279Z","iopub.status.idle":"2026-01-29T09:22:02.035362Z","shell.execute_reply.started":"2026-01-29T09:22:01.616252Z","shell.execute_reply":"2026-01-29T09:22:02.034517Z"}},"outputs":[],"execution_count":null}]}