{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":107469,"databundleVersionId":13058354,"sourceType":"competition"},{"sourceId":12756260,"sourceType":"datasetVersion","datasetId":8064119}],"dockerImageVersionId":31090,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"from IPython.display import clear_output\n!pip install git+https://github.com/3lc-ai/3lc-ultralytics@develop\nclear_output()","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-08-12T16:35:49.721312Z","iopub.execute_input":"2025-08-12T16:35:49.721598Z","iopub.status.idle":"2025-08-12T16:35:58.511123Z","shell.execute_reply.started":"2025-08-12T16:35:49.721574Z","shell.execute_reply":"2025-08-12T16:35:58.510172Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from kaggle_secrets import UserSecretsClient\nuser_secrets = UserSecretsClient()\ntlc_key = user_secrets.get_secret(\"tlc_key\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-12T16:40:01.495727Z","iopub.execute_input":"2025-08-12T16:40:01.496125Z","iopub.status.idle":"2025-08-12T16:40:01.577468Z","shell.execute_reply.started":"2025-08-12T16:40:01.496095Z","shell.execute_reply":"2025-08-12T16:40:01.576852Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!3lc login {tlc_key}\nclear_output()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-12T16:40:05.075665Z","iopub.execute_input":"2025-08-12T16:40:05.075944Z","iopub.status.idle":"2025-08-12T16:40:08.515754Z","shell.execute_reply.started":"2025-08-12T16:40:05.075925Z","shell.execute_reply":"2025-08-12T16:40:08.515032Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import tlc\nfrom tlc_ultralytics import Settings, YOLO\nfrom pathlib import Path\nimport csv\nimport os\nimport numpy as np\nimport pandas as pd\nimport random\nimport torch\n\nnp.random.seed(42)\nrandom.seed(42)\ntorch.manual_seed(42)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-12T16:40:10.507684Z","iopub.execute_input":"2025-08-12T16:40:10.508479Z","iopub.status.idle":"2025-08-12T16:40:15.167026Z","shell.execute_reply.started":"2025-08-12T16:40:10.508445Z","shell.execute_reply":"2025-08-12T16:40:15.166302Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"data_yaml='''\n\ntrain:  /kaggle/input/dataset1/my_dataset2/train/images\nval:  /kaggle/input/dataset1/my_dataset2/val/images\ntest:  /kaggle/input/multi-class-object-detection-challenge/testImages/images\nnc: 2\nnames: ['cheerios', 'soup']\n'''\nwith open('data.yaml', 'w') as file:\n    file.write(data_yaml)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-12T17:11:01.652097Z","iopub.execute_input":"2025-08-12T17:11:01.652826Z","iopub.status.idle":"2025-08-12T17:11:01.657575Z","shell.execute_reply.started":"2025-08-12T17:11:01.652789Z","shell.execute_reply":"2025-08-12T17:11:01.656790Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"PROJECT_NAME = \"Duality-3LC-Kaggle\"  # Place all 3LC Tables and Runs in the same project\n\n# This for loop allows you to create multiple 3LC Tables (e.g., train and val sets) in one go\nfor split in [\"train\", \"val\"]:\n    table = tlc.Table.from_yolo(\n        dataset_yaml_file=\"data.yaml\",  # the yolo_params.yaml file in the data folder you generate from Falcon\n        split=split,\n        table_name=\"initial\",\n        dataset_name=split,\n        project_name=PROJECT_NAME,\n    )\n\n    print(f\"Created table with URL: {table.url}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-12T17:11:55.367842Z","iopub.execute_input":"2025-08-12T17:11:55.368181Z","iopub.status.idle":"2025-08-12T17:16:25.663971Z","shell.execute_reply.started":"2025-08-12T17:11:55.368159Z","shell.execute_reply":"2025-08-12T17:16:25.663167Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"PROJECT_NAME = \"Duality-3LC-Kaggle\"  # Place all 3LC Tables and Runs in the same project\n\nRUN_NAME = \"run-1\"  # Define the run name to organize all your runs in a nice way\n\n# Set 3LC specific settings\nsettings = Settings(\n    project_name=PROJECT_NAME,\n    run_name=RUN_NAME,\n    run_description=\"starting run\",\n)\n\n# Update the URLs for the train and val tables when you make data revisions in 3LC Dashboard\ntrain_table = tlc.Table.from_url(\"/root/.local/share/3LC/projects/Duality-3LC-Kaggle/datasets/train/tables/initial\")  # Hint: Copy Table URLs from Dashboard\nval_table = tlc.Table.from_url(\"/root/.local/share/3LC/projects/Duality-3LC-Kaggle/datasets/val/tables/initial\")\n\nmodel = YOLO(\"yolov8l.pt\")\n\n# You may add any YOLO arguments here\nmodel.train(\n    tables={\"train\": train_table, \"val\": val_table},\n    settings=settings,\n    epochs=100,                \n    batch=16,                   \n    imgsz=640,\n    patience=50,               \n    optimizer='SGD',\n    momentum=0.937,          \n    lr0=0.001,                \n    weight_decay=0.0005,       \n    cos_lr=True,               \n    save_period=5,             \n    workers=8,\n    # Augmentations\n    close_mosaic=15,\n    hsv_h=0.015,\n    hsv_s=0.7,\n    hsv_v=0.4,\n    flipud=0.5,\n    fliplr=0.5,\n    translate=0.1,\n    scale=0.5,\n    shear=0.01,\n    agnostic_nms=True,\n    project=PROJECT_NAME,\n    name=RUN_NAME,\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-12T17:49:48.501450Z","iopub.execute_input":"2025-08-12T17:49:48.501760Z","iopub.status.idle":"2025-08-12T19:55:46.838188Z","shell.execute_reply.started":"2025-08-12T17:49:48.501742Z","shell.execute_reply":"2025-08-12T19:55:46.837025Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model=YOLO(\"/kaggle/working/Duality-3LC-Kaggle/run-1/weights/best.pt\")\n\ntest_images_path = \"/kaggle/input/multi-class-object-detection-challenge/testImages/images\"\noutput_dir = \"/kaggle/working/predictions/labels\"\n\nconf=0.001\n\ndef predict(test_images_path, output_dir , model, conf):\n    os.makedirs(output_dir, exist_ok=True)\n    model.eval()\n    model.training = False\n    for img_path in Path(test_images_path).glob(\"*\"):\n        if img_path.suffix.lower() not in ['.png', '.jpg', '.jpeg']:\n            continue\n    \n        results = model.predict(img_path, conf=conf, augment=True, iou=0.4, max_det=600, verbose=False)  \n        \n        output_txt = Path(output_dir) / f\"{img_path.stem}.txt\"\n    \n        with open(output_txt, \"w\") as f:\n            for result in results:\n                img_height, img_width = result.orig_shape\n                for box in result.boxes.data:\n                    x1, y1, x2, y2, confidence, cls_id = box.tolist()\n    \n                    x_center = ((x1 + x2) / 2) / img_width\n                    y_center = ((y1 + y2) / 2) / img_height\n                    width = (x2 - x1) / img_width\n                    height = (y2 - y1) / img_height\n    \n                    f.write(f\"{cls_id} {confidence:.6f} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}\\n\")\n    \n    print(f\"[notice] ✅ Predictions saved: {output_dir}\")\npredict(test_images_path, output_dir , model, conf)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-12T20:26:32.569678Z","iopub.execute_input":"2025-08-12T20:26:32.570639Z","iopub.status.idle":"2025-08-12T20:28:36.691681Z","shell.execute_reply.started":"2025-08-12T20:26:32.570604Z","shell.execute_reply":"2025-08-12T20:28:36.690795Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Convert predictions to CSV\ndef predictions_to_csv(\n    preds_folder: str = \"/kaggle/working/predictions/labels\", \n    output_csv: str = \"/kaggle/working/submission.csv\", \n    test_images_folder: str = \"/kaggle/input/multi-class-object-detection-challenge/testImages/images\",\n    allowed_extensions: tuple = (\".jpg\", \".png\", \".jpeg\")\n):\n    preds_path = Path(preds_folder)\n    test_images_path = Path(test_images_folder)\n\n    test_images = {p.stem for p in test_images_path.glob(\"*\") if p.suffix.lower() in allowed_extensions}\n\n    predictions = []\n    predicted_images = set()\n\n    for txt_file in preds_path.glob(\"*.txt\"):\n        image_id = txt_file.stem\n        predicted_images.add(image_id)\n\n        with open(txt_file, \"r\") as f:\n            valid_lines = [line.strip() for line in f if len(line.strip().split()) == 6]\n\n        pred_str = \" \".join(valid_lines) if valid_lines else \"no boxes\"\n        predictions.append({\"image_id\": image_id, \"prediction_string\": pred_str})\n\n    missing_images = test_images - predicted_images\n    for image_id in missing_images:\n        predictions.append({\"image_id\": image_id, \"prediction_string\": \"no boxes\"})\n\n    submission_df = pd.DataFrame(predictions)\n    submission_df.to_csv(output_csv, index=False, quoting=csv.QUOTE_MINIMAL)\n    print(submission_df.shape)\n    print(submission_df.head(10))\n    print(f\"[notice] ✅ Submission saved to {output_csv}\")\n\npredictions_to_csv()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-12T20:44:17.089485Z","iopub.execute_input":"2025-08-12T20:44:17.090078Z","iopub.status.idle":"2025-08-12T20:44:17.131490Z","shell.execute_reply.started":"2025-08-12T20:44:17.090052Z","shell.execute_reply":"2025-08-12T20:44:17.130859Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}