{"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":129135,"databundleVersionId":15490734,"sourceType":"competition"}],"dockerImageVersionId":31260,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2026-01-29T03:44:44.320297Z","iopub.execute_input":"2026-01-29T03:44:44.320599Z","iopub.status.idle":"2026-01-29T03:44:49.524617Z","shell.execute_reply.started":"2026-01-29T03:44:44.320562Z","shell.execute_reply":"2026-01-29T03:44:49.523602Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# --- 1. INSTALLATION & SETUP ---\n# Install Ultralytics YOLO (quiet mode)\n!pip install ultralytics -q\n\nimport os\nimport glob\nimport pandas as pd\nimport yaml\nfrom ultralytics import YOLO\n\nprint(\"✅ Setup complete. Identifying paths...\")\n\n# --- 2. AUTO-DETECT DATASET PATH ---\n# We search for the 'train' folder inside /kaggle/input to avoid path errors\nfound_train_images = glob.glob('/kaggle/input/**/train/images', recursive=True)\n\nif not found_train_images:\n    # Fallback: sometimes the folder is just 'train' without 'images' subdir\n    found_train_images = glob.glob('/kaggle/input/**/train', recursive=True)\n\nif not found_train_images:\n    raise FileNotFoundError(\"CRITICAL: Could not find dataset. Ensure 'FAIC Kaggle Competitions' data is added.\")\n\n# Determine the dataset root directory\nfull_train_path = found_train_images[0]\nif full_train_path.endswith('images'):\n    # If path is .../dataset/train/images, Root is .../dataset\n    ROOT_DIR = os.path.dirname(os.path.dirname(full_train_path))\n    train_dir = full_train_path\nelse:\n    # If path is .../dataset/train, Root is .../dataset\n    ROOT_DIR = os.path.dirname(full_train_path)\n    train_dir = os.path.join(ROOT_DIR, 'train')\n\nprint(f\"📂 Dataset Root: {ROOT_DIR}\")\n\n# --- 3. CREATE CONFIG (vinfast.yaml) ---\ndata_config = {\n    'path': ROOT_DIR,\n    'train': train_dir,\n    'val': train_dir,        # Using train as validation for the demo\n    'names': {0: 'vin_car'}  # Class ID 0 is VinFast car\n}\n\nconfig_path = 'vinfast_config.yaml'\nwith open(config_path, 'w') as f:\n    yaml.dump(data_config, f)\n\n# --- 4. TRAIN MODEL ---\nprint(\"🚀 Starting Training (YOLOv8 Nano)...\")\n# Using 'yolov8n.pt' for speed. Change to 'yolov8m.pt' for better accuracy.\nmodel = YOLO('yolov8n.pt') \n\nmodel.train(\n    data=config_path,\n    epochs=10,             # Increase to 50+ for real competition submission\n    imgsz=640,\n    batch=16,\n    project='vinfast_run', # This creates the folder structure\n    name='exp',\n    exist_ok=True,\n    verbose=True\n)\n\n# --- 5. INFERENCE (FIXED WEIGHT LOADING) ---\nprint(\"🔍 Finding best model weights...\")\n\n# FIX: Search for 'best.pt' recursively because YOLO paths can vary\nweight_files = glob.glob('/kaggle/working/**/best.pt', recursive=True)\n\nif not weight_files:\n    raise FileNotFoundError(\"❌ Training finished but 'best.pt' was not found. Check training logs errors.\")\n\nbest_weight_path = weight_files[0]\nprint(f\"✅ Found weights at: {best_weight_path}\")\n\n# Load the trained model\nbest_model = YOLO(best_weight_path)\n\n# Locate test images\ntest_images_path = os.path.join(ROOT_DIR, 'test/images')\nif not os.path.exists(test_images_path):\n     test_images_path = os.path.join(ROOT_DIR, 'test')\n\n# Find all jpg or png images\ntest_files = glob.glob(os.path.join(test_images_path, '*.jpg'))\nif not test_files:\n    test_files = glob.glob(os.path.join(test_images_path, '*.png'))\n\nprint(f\"🔍 Predicting on {len(test_files)} test images...\")\n\n# Run prediction\nresults = best_model.predict(\n    test_files, \n    conf=0.15,  # Confidence threshold (lower is often better for mAP)\n    iou=0.5,    # Intersection over Union threshold\n    verbose=False\n)\n\n# --- 6. FORMAT SUBMISSION ---\nsubmission_rows = []\n\nfor result in results:\n    image_id = os.path.basename(result.path)\n    preds = []\n    \n    # Iterate through detected boxes\n    for box in result.boxes:\n        # Get coordinates in pixels (x_min, y_min, x_max, y_max)\n        x1, y1, x2, y2 = box.xyxy[0].tolist()\n        conf = box.conf[0].item()\n        cls = int(box.cls[0].item())\n        \n        # Format: class score x_min y_min x_max y_max\n        preds.append(f\"{cls} {conf:.4f} {x1:.1f} {y1:.1f} {x2:.1f} {y2:.1f}\")\n        \n    # Join multiple predictions for one image with a space\n    pred_str = \" \".join(preds)\n    submission_rows.append({\"image_id\": image_id, \"PredictionString\": pred_str})\n\n# --- 7. SAVE TO CSV ---\ndf = pd.DataFrame(submission_rows)\ndf.to_csv('submission.csv', index=False)\n\nprint(f\"🎉 SUCCESS! 'submission.csv' generated with {len(df)} rows.\")\nprint(df.head())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-29T03:45:42.210291Z","iopub.execute_input":"2026-01-29T03:45:42.210681Z","iopub.status.idle":"2026-01-29T03:54:20.330839Z","shell.execute_reply.started":"2026-01-29T03:45:42.210647Z","shell.execute_reply":"2026-01-29T03:54:20.329840Z"}},"outputs":[],"execution_count":null}]}