{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# efficientdet\n!pip install --no-deps '../input/timm-package/timm-0.1.26-py3-none-any.whl' > /dev/null\n\n!cp -r ../input/timm-efficientdet-pytorch .\n!cp -r ../input/omegaconf .\n!cp -r ../input/weightedboxesfusion .\n\n# hack to solve dependency bug\nwith open('/opt/conda/lib/python3.10/site-packages/timm/models/layers/helpers.py', 'r') as file:\n    data = file.readlines()\nfor i in range(len(data)):\n    if 'from torch._six import container_abcs' in data[i]:\n        data[i] = data[i].replace('from torch._six import container_abcs', 'import collections.abc as container_abcs')\nwith open('/opt/conda/lib/python3.10/site-packages/timm/models/layers/helpers.py', 'w') as file:\n    file.writelines(data)\n\nwith open(\"/kaggle/working/timm-efficientdet-pytorch/effdet/bench.py\", \"r\") as f:\n    lines = f.readlines()\nlines.insert(38, \"    indices_all = indices_all.long()\\n\")\nwith open(\"/kaggle/working/timm-efficientdet-pytorch/effdet/bench.py\", \"w\") as f:\n    f.writelines(lines)\n\nimport sys\nsys.path.insert(0, \"./timm-efficientdet-pytorch\")\nsys.path.insert(0, \"./omegaconf\")\nsys.path.insert(0, \"./weightedboxesfusion\")\n\nfrom ensemble_boxes import *\nimport torch\nimport numpy as np\nimport pandas as pd\nfrom glob import glob\nfrom torch.utils.data import Dataset,DataLoader\nimport albumentations as A\nfrom albumentations.pytorch.transforms import ToTensorV2\nimport cv2\nimport gc\nfrom matplotlib import pyplot as plt\nfrom effdet import get_efficientdet_config, EfficientDet, DetBenchEval\nfrom effdet.efficientdet import HeadNet\n\ndef get_valid_transforms():\n    return A.Compose([\n            A.Resize(height=512, width=512, p=1.0),\n            ToTensorV2(p=1.0),\n        ], p=1.0)\n\nDATA_ROOT_PATH = '../input/global-wheat-detection/test'\n\nclass DatasetRetriever(Dataset):\n\n    def __init__(self, image_ids, transforms=None):\n        super().__init__()\n        self.image_ids = image_ids\n        self.transforms = transforms\n\n    def __getitem__(self, index: int):\n        image_id = self.image_ids[index]\n        image = cv2.imread(f'{DATA_ROOT_PATH}/{image_id}.jpg', cv2.IMREAD_COLOR)\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB).astype(np.float32)\n        image /= 255.0\n        if self.transforms:\n            sample = {'image': image}\n            sample = self.transforms(**sample)\n            image = sample['image']\n        return image, image_id\n\n    def __len__(self) -> int:\n        return self.image_ids.shape[0]\n    \ndataset = DatasetRetriever(\n    image_ids=np.array([path.split('/')[-1][:-4] for path in glob(f'{DATA_ROOT_PATH}/*.jpg')]),\n    transforms=get_valid_transforms()\n)\n\ndef collate_fn(batch):\n    return tuple(zip(*batch))\n\ndata_loader = DataLoader(\n    dataset,\n    batch_size=2,\n    shuffle=False,\n    num_workers=4,\n    drop_last=False,\n    collate_fn=collate_fn\n)\n\ndef load_net(checkpoint_path):\n    config = get_efficientdet_config('tf_efficientdet_d7')\n    net = EfficientDet(config, pretrained_backbone=False)\n\n    config.num_classes = 1\n    config.image_size=512\n    net.class_net = HeadNet(config, num_outputs=config.num_classes, norm_kwargs=dict(eps=.001, momentum=.01))\n\n    checkpoint = torch.load(checkpoint_path)\n    net.load_state_dict(checkpoint['model_state_dict'])\n\n    del checkpoint\n    gc.collect()\n\n    net = DetBenchEval(net, config)\n    net.eval();\n    return net.cuda()\n\nnet = load_net('/kaggle/input/soc-efficientdet-infer/efficientdet/best-checkpoint-039epoch.bin')\n\ndef make_predictions(images, score_threshold = 0):\n    images = torch.stack(images).cuda().float()\n    predictions = []\n    with torch.no_grad():\n        det = net(images, torch.tensor([1]*images.shape[0]).float().cuda())\n        for i in range(images.shape[0]):\n            boxes = det[i].detach().cpu().numpy()[:,:4]    \n            scores = det[i].detach().cpu().numpy()[:,4]\n            indexes = np.where(scores > score_threshold)[0]\n            boxes = boxes[indexes]\n            boxes[:, 2] = boxes[:, 2] + boxes[:, 0]\n            boxes[:, 3] = boxes[:, 3] + boxes[:, 1]\n            predictions.append({\n                'boxes': boxes[indexes],\n                'scores': scores[indexes],\n            })\n    return [predictions]\n\n# def run_wbf(predictions, image_index, image_size=512, iou_thr=0.44, skip_box_thr=0.43, weights=None):\n#     boxes = [(prediction[image_index]['boxes']/(image_size-1)).tolist()  for prediction in predictions]\n#     scores = [prediction[image_index]['scores'].tolist()  for prediction in predictions]\n#     labels = [np.ones(prediction[image_index]['scores'].shape[0]).tolist() for prediction in predictions]\n#     boxes, scores, labels = weighted_boxes_fusion(boxes, scores, labels, weights=None, iou_thr=iou_thr, skip_box_thr=skip_box_thr)\n#     boxes = boxes*(image_size-1)\n#     return boxes, scores, labels\n\neffdet_predictions = {}\n\nfor images, image_ids in data_loader:\n    predictions = make_predictions(images)\n    for i, image in enumerate(images):\n        boxes = np.stack([prediction[i]['boxes'].tolist() for prediction in predictions])\n        scores = np.array([prediction[i]['scores'].tolist() for prediction in predictions])\n#         boxes, scores, labels = run_wbf(predictions, image_index=i)\n        boxes = (boxes*2).astype(np.int32).clip(min=0, max=1023)\n        image_id = image_ids[i]\n        \n        boxes = boxes.squeeze()\n        scores = scores.squeeze()\n        boxes[:, 2] = boxes[:, 2] - boxes[:, 0]\n        boxes[:, 3] = boxes[:, 3] - boxes[:, 1]\n\n        effdet_predictions[image_id] = (boxes, scores)","metadata":{"execution":{"iopub.status.busy":"2023-05-30T12:21:09.419226Z","iopub.execute_input":"2023-05-30T12:21:09.419615Z","iopub.status.idle":"2023-05-30T12:21:18.788556Z","shell.execute_reply.started":"2023-05-30T12:21:09.419583Z","shell.execute_reply":"2023-05-30T12:21:18.787281Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# yolo\nimport sys\nsys.path.insert(0, \"/kaggle/input/yolosoc/resources/Weighted-Boxes-Fusion\")\nsys.path.insert(0, '/kaggle/input/yolosoc/resources/yolov5')\n\nimport numpy as np # linear algebra\nimport os\nfrom tqdm.auto import tqdm\nimport shutil as sh\nimport torch\nimport cv2\nfrom ensemble_boxes import *\nfrom utils.augmentations import *\nfrom utils.general import *\nfrom glob import glob\n\nYOLO_CONF_THRES = 0.5\nYOLO_IOU_THRES = 0.6\nYOLO_IMG_SZ = 1024\n\ndef clip_coords(boxes, img_shape):\n    # Clip bounding xyxy bounding boxes to image shape (height, width)\n    boxes[:, 0].clamp_(0, img_shape[1])  # x1\n    boxes[:, 1].clamp_(0, img_shape[0])  # y1\n    boxes[:, 2].clamp_(0, img_shape[1])  # x2\n    boxes[:, 3].clamp_(0, img_shape[0])  # y2\n\ndef scale_coords(img1_shape, coords, img0_shape, ratio_pad=None):\n    # Rescale coords (xyxy) from img1_shape to img0_shape\n    if ratio_pad is None:  # calculate from img0_shape\n        gain = max(img1_shape) / max(img0_shape)  # gain  = old / new\n        pad = (img1_shape[1] - img0_shape[1] * gain) / 2, (img1_shape[0] - img0_shape[0] * gain) / 2  # wh padding\n    else:\n        gain = ratio_pad[0][0]\n        pad = ratio_pad[1]\n\n    coords[:, [0, 2]] -= pad[0]  # x padding\n    coords[:, [1, 3]] -= pad[1]  # y padding\n    coords[:, :4] /= gain\n    clip_coords(coords, img0_shape)\n    return coords\n\ndef detectSingle(im0, imgsz, model, device, conf_thres, iou_thres):\n    img = letterbox(im0, new_shape=imgsz)[0]\n    # Convert\n    img = img[:, :, ::-1].transpose(2, 0, 1)  # BGR to RGB, to 3x416x416\n    img = np.ascontiguousarray(img)\n\n\n    img = torch.from_numpy(img).to(device)\n    img =  img.float()  # uint8 to fp16/32\n    img /= 255.0   \n    if img.ndimension() == 3:\n        img = img.unsqueeze(0)\n\n    # Inference\n    pred = model(img, augment=False)[0]\n\n    # Apply NMS\n    pred = non_max_suppression(pred, conf_thres, iou_thres)\n\n    boxes = []\n    scores = []\n    for i, det in enumerate(pred):  # detections per image\n        # save_path = 'draw/' + image_id + '.jpg'\n        if det is not None and len(det):\n            # Rescale boxes from img_size to im0 size\n            det[:, :4] = scale_coords(img.shape[2:], det[:, :4], im0.shape).round()\n\n            # Write results\n            for *xyxy, conf, cls in det:\n                boxes.append([int(xyxy[0]), int(xyxy[1]), int(xyxy[2]), int(xyxy[3])])\n                scores.append(conf)\n\n    return torch.tensor(boxes), torch.tensor(scores)\n\ndef detect(weight_path, test_path):\n    device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')\n    model = torch.load(weight_path, map_location=device)['model'].to(device).float().eval()\n\n    image_ids=np.array([path.split('/')[-1][:-4] for path in glob(f'{test_path}/*.jpg')])\n    results = {}\n    for image_id in image_ids:\n        try:\n            image_path = f'{test_path}/{image_id}.jpg'\n            im01 = cv2.imread(image_path)  # BGR\n            assert im01 is not None, 'Image Not Found ' + name\n            # Padded resize\n            im_w, im_h = im01.shape[:2]\n\n            boxes, scores = detectSingle(im01, YOLO_IMG_SZ, model, device, YOLO_CONF_THRES, YOLO_IOU_THRES)\n\n            boxes[:, 2] = boxes[:, 2] - boxes[:, 0]\n            boxes[:, 3] = boxes[:, 3] - boxes[:, 1]\n\n#             boxes = boxes[scores >= 0.05].type(torch.int32)\n#             scores = scores[scores >=float(0.05)]\n\n            results[image_id] = (boxes, scores)\n        except Exception as e:\n            results[image_id] = (np.array([]), np.array([]))\n    return results\n\nyolo_predictions = detect('/kaggle/input/yolosoc/weights/best.pt', '/kaggle/input/global-wheat-detection/test')","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-05-30T12:21:18.791124Z","iopub.execute_input":"2023-05-30T12:21:18.792237Z","iopub.status.idle":"2023-05-30T12:21:20.116327Z","shell.execute_reply.started":"2023-05-30T12:21:18.792194Z","shell.execute_reply":"2023-05-30T12:21:20.115360Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport cv2\nimport os\nimport re\n\nfrom PIL import Image\n\nimport albumentations as A\nfrom albumentations.pytorch.transforms import ToTensorV2\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\nWEIGHTS_FILE = f'/kaggle/input/soc-frcnn/best.pth'\n\ntest_df = pd.read_csv(f'{DIR_INPUT}/sample_submission.csv')\ntest_df.shape\n\nclass 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]\n\n# Albumentations\ndef get_test_transform():\n    return A.Compose([\n        ToTensorV2(p=1.0)\n    ])\n# load a model; pre-trained on COCO\nmodel = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=False, pretrained_backbone=False)\ndevice = 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)\ndef 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)\ndef 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)\n\ndetection_threshold = 0\nfrcnn_predictions = {}\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        boxes[:, 2] = boxes[:, 2] - boxes[:, 0]\n        boxes[:, 3] = boxes[:, 3] - boxes[:, 1]\n        \n        frcnn_predictions[image_id] = (boxes, scores)","metadata":{"execution":{"iopub.status.busy":"2023-05-30T12:21:20.118125Z","iopub.execute_input":"2023-05-30T12:21:20.118509Z","iopub.status.idle":"2023-05-30T12:21:22.074514Z","shell.execute_reply.started":"2023-05-30T12:21:20.118477Z","shell.execute_reply":"2023-05-30T12:21:22.073175Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_ids = []\nfor image_id in effdet_predictions.keys():\n    image_ids.append(image_id)","metadata":{"execution":{"iopub.status.busy":"2023-05-30T12:21:22.081450Z","iopub.execute_input":"2023-05-30T12:21:22.083784Z","iopub.status.idle":"2023-05-30T12:21:22.091016Z","shell.execute_reply.started":"2023-05-30T12:21:22.083743Z","shell.execute_reply":"2023-05-30T12:21:22.089716Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# all_predictions = [effdet_predictions, yolo_predictions, frcnn_predictions]\ndef format_prediction(boxes, scores):\n    pred_strings = []\n    for j in zip(scores, boxes):\n        pred_strings.append(f\"{j[0]:.4f} {int(j[1][0])} {int(j[1][1])} {int(j[1][2])} {int(j[1][3])}\")\n    return \" \".join(pred_strings)","metadata":{"execution":{"iopub.status.busy":"2023-05-30T12:21:22.096089Z","iopub.execute_input":"2023-05-30T12:21:22.098701Z","iopub.status.idle":"2023-05-30T12:21:22.106475Z","shell.execute_reply.started":"2023-05-30T12:21:22.098668Z","shell.execute_reply":"2023-05-30T12:21:22.105539Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"results = []\n\nfor image_id in image_ids:\n#     boxes = []\n#     scores = []\n#     for predictions in all_predictions:\n#         if predictions[image_id] is not None:\n#             for box, score in zip(*predictions[image_id]):\n#                 boxes.append(box/1024)\n#                 scores.append(score)\n#     labels =  np.ones(len(scores))\n    boxes, scores, labels = weighted_boxes_fusion(\n        [effdet_predictions[image_id][0] / 1024, yolo_predictions[image_id][0] / 1024, frcnn_predictions[image_id][0] / 1024],\n        [effdet_predictions[image_id][1], yolo_predictions[image_id][1], frcnn_predictions[image_id][1]],\n        [np.ones(len(effdet_predictions[image_id][1])), np.ones(len(yolo_predictions[image_id][1])), np.ones(len(frcnn_predictions[image_id][1]))],\n        skip_box_thr=0.5)\n    boxes *= 1024\n    results.append({\n                'image_id': image_id,\n                'PredictionString': format_prediction(boxes, scores)\n    })\n\nresults_df = pd.DataFrame(results, columns=['image_id', 'PredictionString'])\nresults_df.to_csv('submission.csv', index=False)\nresults_df.head()","metadata":{"execution":{"iopub.status.busy":"2023-05-30T12:21:22.111089Z","iopub.execute_input":"2023-05-30T12:21:22.112961Z","iopub.status.idle":"2023-05-30T12:21:22.376201Z","shell.execute_reply.started":"2023-05-30T12:21:22.112923Z","shell.execute_reply":"2023-05-30T12:21:22.375371Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}