{"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":19989,"databundleVersionId":1160143,"isSourceIdPinned":false,"sourceType":"competition"},{"sourceId":282702272,"sourceType":"kernelVersion"}],"dockerImageVersionId":31193,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Install packages and setup environment","metadata":{}},{"cell_type":"code","source":"!pip install /kaggle/input/sam3-project-offline-packages/wheels/portalocker-3.2.0-py3-none-any.whl\n!pip install /kaggle/input/sam3-project-offline-packages/wheels/iopath-0.1.10.tar.gz\n!pip install /kaggle/input/sam3-project-offline-packages/wheels/ftfy-6.1.1-py3-none-any.whl\n!pip install /kaggle/input/sam3-project-offline-packages/wheels/decord-0.6.0-py3-none-manylinux2010_x86_64.whl \n!pip install /kaggle/input/sam3-project-offline-packages/wheels/ultralytics-8.3.233-py3-none-any.whl --no-deps \n!cp /kaggle/input/sam3-project-offline-packages/sam3_repo -r ./sam3_repo","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-11-29T18:59:33.651110Z","iopub.execute_input":"2025-11-29T18:59:33.651910Z","iopub.status.idle":"2025-11-29T18:59:54.504151Z","shell.execute_reply.started":"2025-11-29T18:59:33.651881Z","shell.execute_reply":"2025-11-29T18:59:54.503134Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Load the SAM3 model","metadata":{}},{"cell_type":"code","source":"# add repository in the system path\nimport sys\nsys.path.insert(0, \"./sam3_repo\")\n\nSAM3_WEIGHT_FILE = \"/kaggle/input/sam3-project-offline-packages/weights/sam3.pt\"\nPROMPT = \"wheat, flower, seed head, green seed head, spike, green spike\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-29T18:59:54.505835Z","iopub.execute_input":"2025-11-29T18:59:54.506101Z","iopub.status.idle":"2025-11-29T18:59:54.509890Z","shell.execute_reply.started":"2025-11-29T18:59:54.506076Z","shell.execute_reply":"2025-11-29T18:59:54.509210Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sam3.model.sam3_image_processor import Sam3Processor\nfrom sam3.model_builder import build_sam3_image_model\n\n### build SAM3 model\nmodel = build_sam3_image_model(checkpoint_path=SAM3_WEIGHT_FILE, load_from_HF=False)\nprocessor = Sam3Processor(model, confidence_threshold=0.3)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-29T18:59:54.510668Z","iopub.execute_input":"2025-11-29T18:59:54.510884Z","iopub.status.idle":"2025-11-29T19:00:31.459874Z","shell.execute_reply.started":"2025-11-29T18:59:54.510862Z","shell.execute_reply":"2025-11-29T19:00:31.459302Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Define Utils visualize one image","metadata":{}},{"cell_type":"code","source":"from sam3.model.sam3_image_processor import Sam3Processor\nfrom typing import Union, Optional, Dict\nfrom PIL import Image, ImageDraw\nimport torch\n\n\ndef run_sam3(processor: Sam3Processor, image: Union[str, Image], prompt: str):\n    if isinstance(image, str):\n        image = Image.open(image)\n\n    # run the model\n    inference_state  = processor.set_image(image)\n    output = processor.set_text_prompt(state=inference_state, prompt=prompt)\n    return output\n\ndef visualize_predictions(image_path: str, outputs: Dict):\n    image = Image.open(image_path)\n    draw = ImageDraw.Draw(image)\n    for bbox in outputs['boxes']:\n        x1, y1, x2, y2 = bbox\n        draw.rectangle([x1, y1, x2, y2], outline=\"lime\", width=3)\n    return image\n\ndef nms(boxes, scores, iou_threshold=0.5):\n    # boxes: (N, 4) in xyxy\n    # scores: (N,)\n    idxs = scores.argsort(descending=True)\n    keep = []\n\n    while idxs.numel() > 0:\n        current = idxs[0].item()\n        keep.append(current)\n\n        if idxs.numel() == 1:\n            break\n\n        rest = idxs[1:]\n\n        x1 = torch.maximum(boxes[current, 0], boxes[rest, 0])\n        y1 = torch.maximum(boxes[current, 1], boxes[rest, 1])\n        x2 = torch.minimum(boxes[current, 2], boxes[rest, 2])\n        y2 = torch.minimum(boxes[current, 3], boxes[rest, 3])\n\n        inter_w = torch.clamp(x2 - x1, min=0)\n        inter_h = torch.clamp(y2 - y1, min=0)\n        inter = inter_w * inter_h\n\n        area_current = (boxes[current, 2] - boxes[current, 0]) * \\\n                       (boxes[current, 3] - boxes[current, 1])\n        area_rest = (boxes[rest, 2] - boxes[rest, 0]) * \\\n                    (boxes[rest, 3] - boxes[rest, 1])\n\n        union = area_current + area_rest - inter\n        iou = inter / union\n\n        idxs = rest[iou < iou_threshold]\n\n    return torch.tensor(keep, dtype=torch.long)\n\ndef perform_non_max_suppression(outputs, iou_threshold: float = 0.5):\n    keep_idx = nms(outputs['boxes'], outputs['scores'], iou_threshold=iou_threshold)\n    outputs['scores'] = outputs['scores'][keep_idx]\n    outputs['boxes'] = outputs['boxes'][keep_idx, :]\n    outputs['masks'] = outputs['masks'][keep_idx, :, :]\n    return outputs","metadata":{"trusted":true,"jupyter":{"source_hidden":true},"execution":{"iopub.status.busy":"2025-11-29T19:00:31.461095Z","iopub.execute_input":"2025-11-29T19:00:31.461387Z","iopub.status.idle":"2025-11-29T19:00:31.471380Z","shell.execute_reply.started":"2025-11-29T19:00:31.461361Z","shell.execute_reply":"2025-11-29T19:00:31.470681Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# visualize a random sample\nimport matplotlib.pyplot as plt\nimport random\nimport os\n\n# randomely select one image\nimage_base_path = \"/kaggle/input/global-wheat-detection/test\"\nimage_names = os.listdir(image_base_path)\nimage_name = random.choice(image_names)\nimage_path = os.path.join(image_base_path, image_name)\n\n# run the model on one image\nsam3_predictions = run_sam3(processor, image_path, prompt=PROMPT)\nsam3_predictions = perform_non_max_suppression(sam3_predictions, iou_threshold=0.5)\n\n# draw the bounding boxes on image and showcase\nimage_drawn = visualize_predictions(image_path, sam3_predictions)\nplt.figure(figsize=(16, 16))\nplt.imshow(image_drawn)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-29T19:00:31.472126Z","iopub.execute_input":"2025-11-29T19:00:31.472447Z","iopub.status.idle":"2025-11-29T19:00:35.803063Z","shell.execute_reply.started":"2025-11-29T19:00:31.472423Z","shell.execute_reply":"2025-11-29T19:00:35.802226Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Do inference on Test set and generate submission.csv","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nfrom PIL import Image\n\n\nsubmission_data = []\nfor image_name in image_names:\n    # collect the image\n    image_path = os.path.join(image_base_path, image_name)\n    image_pil = Image.open(image_path)\n    image_width, image_height = image_pil.size\n    \n    # run the model on one image\n    sam3_predictions = run_sam3(processor, image_pil, prompt=PROMPT)\n    sam3_predictions = perform_non_max_suppression(sam3_predictions, iou_threshold=0.5)\n\n    # collect the predictions\n    predictions = []\n    for score, bbox in zip(sam3_predictions['scores'].tolist(), sam3_predictions['boxes'].to(int).tolist()):\n        x1, y1, x2, y2 = bbox\n        x1, y1 = max(0, x1), max(0, y1)\n        x2, y2 = min(x2, 1024), min(y2, 1024)\n        width, height = x2-x1, y2- y1\n        predictions += [round(score, 4), x1, y1, width, height]\n\n    # append the predictions to the submission data\n    submission_data.append({\n        \"image_id\": image_name.split('.')[0],\n        \"PredictionString\": \" \".join(list(map(str, predictions)))\n    })\n\n\nsubmission_df = pd.DataFrame(submission_data)\nsubmission_df.to_csv(\"submission.csv\", index=False)\nsubmission_df","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-29T19:00:53.714774Z","iopub.execute_input":"2025-11-29T19:00:53.715311Z","iopub.status.idle":"2025-11-29T19:01:04.502744Z","shell.execute_reply.started":"2025-11-29T19:00:53.715280Z","shell.execute_reply":"2025-11-29T19:01:04.502011Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}