{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.11","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":11942286,"sourceType":"datasetVersion","datasetId":7507562},{"sourceId":409982,"sourceType":"modelInstanceVersion","isSourceIdPinned":false,"modelInstanceId":334833,"modelId":355861},{"sourceId":410303,"sourceType":"modelInstanceVersion","isSourceIdPinned":false,"modelInstanceId":335049,"modelId":356067},{"sourceId":412127,"sourceType":"modelInstanceVersion","isSourceIdPinned":true,"modelInstanceId":336465,"modelId":357457}],"dockerImageVersionId":31041,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"#!pip download ensemble_boxes\n#!pip download ultralytics\n\n!pip install --no-index --find-links /kaggle/input/ultralytics-and-ensemble-boxes /kaggle/input/ultralytics-and-ensemble-boxes/ensemble_boxes-1.0.9-py3-none-any.whl\n!pip install --no-index --find-links /kaggle/input/ultralytics-and-ensemble-boxes /kaggle/input/ultralytics-and-ensemble-boxes/ultralytics-8.3.144-py3-none-any.whl","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-05-25T07:20:04.316168Z","iopub.execute_input":"2025-05-25T07:20:04.316989Z","iopub.status.idle":"2025-05-25T07:20:11.143093Z","shell.execute_reply.started":"2025-05-25T07:20:04.316956Z","shell.execute_reply":"2025-05-25T07:20:11.141870Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from ensemble_boxes import *\nimport pandas as pd\nimport numpy as np\nfrom sklearn.model_selection import StratifiedKFold\nfrom torch.utils.data import Dataset,DataLoader\nimport albumentations as A\nfrom albumentations.pytorch.transforms import ToTensorV2\nfrom glob import glob\nimport torch\nimport cv2\nfrom ultralytics import YOLO\nimport os\nimport re\nimport matplotlib.pyplot as plt\nfrom sklearn import model_selection\nfrom sklearn.model_selection import train_test_split\nfrom tqdm import tqdm\nimport shutil\nfrom glob import glob\n\nfrom PIL import Image\n\nimport albumentations as A\nfrom albumentations.pytorch.transforms import ToTensorV2\n\n\nimport torch\nimport torchvision\n\nfrom torchvision.models.detection.faster_rcnn import FastRCNNPredictor\nfrom torchvision.models.detection import FasterRCNN\nfrom torchvision.models.detection.rpn import AnchorGenerator\n\nfrom torch.utils.data import DataLoader, Dataset\nfrom torch.utils.data.sampler import SequentialSampler\n\nfrom matplotlib import pyplot as plt\n\nDIR_INPUT = '/kaggle/input/global-wheat-detection'\nDIR_TRAIN = f'{DIR_INPUT}/train'\nDIR_TEST = f'{DIR_INPUT}/test'\n\nDIR_WEIGHTS = '/kaggle/input/global-wheat-detection-faster-rcnn/pytorch/default/1'\n\nWEIGHTS_FILE = f'{DIR_WEIGHTS}/fasterrcnn_resnet50_fpn_global_wheat_detection.pth'","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-25T07:20:11.145012Z","iopub.execute_input":"2025-05-25T07:20:11.145349Z","iopub.status.idle":"2025-05-25T07:20:11.155168Z","shell.execute_reply.started":"2025-05-25T07:20:11.145315Z","shell.execute_reply":"2025-05-25T07:20:11.154106Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_df = pd.read_csv(f\"{DIR_INPUT}/sample_submission.csv\")\ntest_df.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-25T06:46:36.414549Z","iopub.execute_input":"2025-05-25T06:46:36.414838Z","iopub.status.idle":"2025-05-25T06:46:36.424414Z","shell.execute_reply.started":"2025-05-25T06:46:36.414809Z","shell.execute_reply":"2025-05-25T06:46:36.423686Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class WheatTestDataset(Dataset):\n\n    def __init__(self, dataframe, image_dir, transforms=None):\n        super().__init__()\n\n        self.image_ids = dataframe['image_id'].unique()\n        self.df = dataframe\n        self.image_dir = image_dir\n        self.transforms = transforms\n\n    def __getitem__(self, index: int):\n\n        image_id = self.image_ids[index]\n        records = self.df[self.df['image_id'] == image_id]\n\n        image = cv2.imread(f'{self.image_dir}/{image_id}.jpg', cv2.IMREAD_COLOR)\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB).astype(np.float32)\n        image /= 255.0\n\n        if self.transforms:\n            sample = {\n                'image': image,\n            }\n            sample = self.transforms(**sample)\n            image = sample['image']\n\n        return image, image_id\n\n    def __len__(self) -> int:\n        return self.image_ids.shape[0]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-25T06:46:37.117777Z","iopub.execute_input":"2025-05-25T06:46:37.118462Z","iopub.status.idle":"2025-05-25T06:46:37.124266Z","shell.execute_reply.started":"2025-05-25T06:46:37.118437Z","shell.execute_reply":"2025-05-25T06:46:37.123406Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def get_test_transform():\n    return A.Compose([\n        # A.Resize(512, 512),\n        ToTensorV2(p=1.0)\n    ])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-25T06:46:37.863679Z","iopub.execute_input":"2025-05-25T06:46:37.864256Z","iopub.status.idle":"2025-05-25T06:46:37.867925Z","shell.execute_reply.started":"2025-05-25T06:46:37.864234Z","shell.execute_reply":"2025-05-25T06:46:37.867243Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=False, pretrained_backbone=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-25T06:46:42.767961Z","iopub.execute_input":"2025-05-25T06:46:42.768739Z","iopub.status.idle":"2025-05-25T06:46:43.382061Z","shell.execute_reply.started":"2025-05-25T06:46:42.768705Z","shell.execute_reply":"2025-05-25T06:46:43.381463Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')\n\nnum_classes = 2  # 1 class (wheat) + background\n\n# get number of input features for the classifier\nin_features = model.roi_heads.box_predictor.cls_score.in_features\n\n# replace the pre-trained head with a new one\nmodel.roi_heads.box_predictor = FastRCNNPredictor(in_features, num_classes)\n\n# Load the trained weights\nmodel.load_state_dict(torch.load(WEIGHTS_FILE))\nmodel.eval()\n\nx = model.to(device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-25T06:46:49.136920Z","iopub.execute_input":"2025-05-25T06:46:49.137616Z","iopub.status.idle":"2025-05-25T06:46:49.452162Z","shell.execute_reply.started":"2025-05-25T06:46:49.137590Z","shell.execute_reply":"2025-05-25T06:46:49.451596Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def collate_fn(batch):\n    return tuple(zip(*batch))\n\ntest_dataset = WheatTestDataset(test_df, DIR_TEST, get_test_transform())\n\ntest_data_loader = DataLoader(\n    test_dataset,\n    batch_size=4,\n    shuffle=False,\n    num_workers=4,\n    drop_last=False,\n    collate_fn=collate_fn\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-25T06:46:50.113596Z","iopub.execute_input":"2025-05-25T06:46:50.114489Z","iopub.status.idle":"2025-05-25T06:46:50.121336Z","shell.execute_reply.started":"2025-05-25T06:46:50.114464Z","shell.execute_reply":"2025-05-25T06:46:50.120475Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def format_prediction_string(boxes, scores):\n    pred_strings = []\n    for j in zip(scores, boxes):\n        pred_strings.append(\"{0:.4f} {1} {2} {3} {4}\".format(j[0], j[1][0], j[1][1], j[1][2], j[1][3]))\n\n    return \" \".join(pred_strings)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-25T06:46:52.299912Z","iopub.execute_input":"2025-05-25T06:46:52.300648Z","iopub.status.idle":"2025-05-25T06:46:52.304810Z","shell.execute_reply.started":"2025-05-25T06:46:52.300624Z","shell.execute_reply":"2025-05-25T06:46:52.304071Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"detection_threshold = 0.5\nrcnn_results = []\n\nfor images, image_ids in test_data_loader:\n\n    images = list(image.to(device) for image in images)\n    outputs = model(images)\n\n    for i, image in enumerate(images):\n\n        boxes = outputs[i]['boxes'].data.cpu().numpy()\n        scores = outputs[i]['scores'].data.cpu().numpy()\n        \n        boxes = boxes[scores >= detection_threshold].astype(np.int32)\n        scores = scores[scores >= detection_threshold]\n        image_id = image_ids[i]\n        \n        result = {\n            'image_id': image_id,\n            'boxes': boxes,\n            'scores': scores\n        }\n\n        rcnn_results.append(result)\n\nrcnn_results[:2]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-25T06:46:56.612182Z","iopub.execute_input":"2025-05-25T06:46:56.612506Z","iopub.status.idle":"2025-05-25T06:46:57.513099Z","shell.execute_reply.started":"2025-05-25T06:46:56.612484Z","shell.execute_reply":"2025-05-25T06:46:57.512148Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from ultralytics import YOLO\nmodel = YOLO('/kaggle/input/global-wheat-detection-yolov11n-v2/pytorch/default/1/custom_yolo (1).pt')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-25T06:45:35.386668Z","iopub.execute_input":"2025-05-25T06:45:35.387321Z","iopub.status.idle":"2025-05-25T06:45:35.424611Z","shell.execute_reply.started":"2025-05-25T06:45:35.387298Z","shell.execute_reply":"2025-05-25T06:45:35.424000Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_dir = \"/kaggle/input/global-wheat-detection/test\"\ntest_images = sorted(glob(os.path.join(test_dir, \"*.jpg\")))\n\nyolo_results = []\n\nfor image_path in test_images:\n    image_id = os.path.splitext(os.path.basename(image_path))[0]\n    preds = model.predict(source=image_path, conf=0.5, iou=0.5, save=False, verbose=False)\n    boxes = preds[0].boxes\n    \n    \"\"\"prediction_string = \"\"\n    for xyxy, score in zip(boxes.xyxy.cpu().numpy(), boxes.conf.cpu().numpy()):\n        x_min, y_min, x_max, y_max = xyxy\n        width = x_max - x_min\n        height = y_max - y_min\n        prediction_string += f\\\"{score:.4f} {int(x_min)} {int(y_min)} {int(width)} {int(height)} \\\"\"\"\"\n\n    yolo_results.append({\n        \"image_id\": image_id,\n        'boxes': boxes.xyxy.cpu().numpy().astype(np.int32),\n        'scores': boxes.conf.cpu().numpy()\n    })\n\nprint(yolo_results[:2])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-25T06:45:35.585354Z","iopub.execute_input":"2025-05-25T06:45:35.585881Z","iopub.status.idle":"2025-05-25T06:45:35.853699Z","shell.execute_reply.started":"2025-05-25T06:45:35.585857Z","shell.execute_reply":"2025-05-25T06:45:35.852896Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"rcnn_results = sorted(rcnn_results, key=lambda x: x['image_id'])\nyolo_results = sorted(yolo_results, key=lambda x: x['image_id'])\n\nlist(zip(rcnn_results, yolo_results))[:2]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-25T06:47:06.126093Z","iopub.execute_input":"2025-05-25T06:47:06.126755Z","iopub.status.idle":"2025-05-25T06:47:06.135683Z","shell.execute_reply.started":"2025-05-25T06:47:06.126724Z","shell.execute_reply":"2025-05-25T06:47:06.134888Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"image_size = 1024\nresults = []\nfor rcnn_result, yolo_result in list(zip(rcnn_results, yolo_results)):\n    boxes = [rcnn_result['boxes'] / (image_size - 1), yolo_result['boxes'] / (image_size - 1)]\n    scores = [rcnn_result['scores'], yolo_result['scores']]\n    labels = [np.ones(rcnn_result['scores'].shape[0]), np.ones(yolo_result['scores'].shape[0])]\n    boxes, scores, labels = weighted_boxes_fusion(boxes, scores, labels, weights=None, iou_thr=0.5, skip_box_thr=0.5)\n    boxes = boxes * (image_size - 1)\n    boxes = boxes.astype(np.int32)\n    result = {\n        'image_id': rcnn_result['image_id'],\n        'rcnn_boxes': rcnn_result['boxes'],\n        'yolo_boxes': yolo_result['boxes'],\n        'boxes': boxes,\n        'scores': scores,\n        \n    }\n    results.append(result)\n\nresults[:2]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-25T06:49:17.958790Z","iopub.execute_input":"2025-05-25T06:49:17.959514Z","iopub.status.idle":"2025-05-25T06:49:17.996071Z","shell.execute_reply.started":"2025-05-25T06:49:17.959491Z","shell.execute_reply":"2025-05-25T06:49:17.995061Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\nimage = cv2.imread(f'{DIR_TEST}/2fd875eaa.jpg', cv2.IMREAD_COLOR)\nimage = cv2.cvtColor(image, cv2.COLOR_BGR2RGB).astype(np.float32)\nimage /= 255.0\n\nboxes = []\nfor result in results:\n    if result['image_id'] == '2fd875eaa':\n        boxes = result['boxes']\n\nfig, ax = plt.subplots(1, 1, figsize=(16, 8))\n\nfor box in boxes:\n    cv2.rectangle(image,\n                  (box[0], box[1]),\n                  (box[2], box[3]),\n                  (220, 0, 0), 2)\n    \nax.set_axis_off()\nax.imshow(image);\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-25T06:49:22.641920Z","iopub.execute_input":"2025-05-25T06:49:22.642233Z","iopub.status.idle":"2025-05-25T06:49:23.292251Z","shell.execute_reply.started":"2025-05-25T06:49:22.642183Z","shell.execute_reply":"2025-05-25T06:49:23.291333Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(results[:1])\nfor i in range(len(results)):\n    results[i]['boxes'][:, 2] = results[i]['boxes'][:, 2] - results[i]['boxes'][:, 0]\n    results[i]['boxes'][:, 3] = results[i]['boxes'][:, 3] - results[i]['boxes'][:, 1]\n    results[i]['PredictionString'] = format_prediction_string(results[i]['boxes'], results[i]['scores'])\nprint(results[:1])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-25T08:07:00.402897Z","iopub.execute_input":"2025-05-25T08:07:00.403240Z","iopub.status.idle":"2025-05-25T08:07:00.411071Z","shell.execute_reply.started":"2025-05-25T08:07:00.403212Z","shell.execute_reply":"2025-05-25T08:07:00.410220Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_df = pd.DataFrame(results, columns=['image_id', 'PredictionString'])\ntest_df.to_csv('submission.csv', index=False)\ntest_df.head()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-25T06:49:33.561668Z","iopub.execute_input":"2025-05-25T06:49:33.562275Z","iopub.status.idle":"2025-05-25T06:49:33.588913Z","shell.execute_reply.started":"2025-05-25T06:49:33.562252Z","shell.execute_reply":"2025-05-25T06:49:33.588233Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}