{"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":"markdown","source":"Here is the training notebook [Training Notebook](https://www.kaggle.com/teykaihong/gwd-pytorch-fasterrcnn-training)","metadata":{}},{"cell_type":"code","source":"%cd ../input/myfile","metadata":{"execution":{"iopub.status.busy":"2021-05-24T03:47:52.694604Z","iopub.execute_input":"2021-05-24T03:47:52.694930Z","iopub.status.idle":"2021-05-24T03:47:52.702821Z","shell.execute_reply.started":"2021-05-24T03:47:52.694898Z","shell.execute_reply":"2021-05-24T03:47:52.701831Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport torchvision\nimport glob\nimport os\nimport cv2\nimport pandas as pd\nimport matplotlib\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport utils\nimport transforms as T\nfrom PIL import Image\nfrom ensemble_boxes_wbf import *\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision.models.detection.faster_rcnn import FastRCNNPredictor\n\n%matplotlib inline\nmatplotlib.rcParams['font.size'] = 14\nmatplotlib.rcParams['figure.figsize'] = (27, 27)","metadata":{"execution":{"iopub.status.busy":"2021-05-24T03:47:52.826633Z","iopub.execute_input":"2021-05-24T03:47:52.826909Z","iopub.status.idle":"2021-05-24T03:47:52.838573Z","shell.execute_reply.started":"2021-05-24T03:47:52.826880Z","shell.execute_reply":"2021-05-24T03:47:52.834991Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%cd ..\n%cd ..\n%cd working","metadata":{"execution":{"iopub.status.busy":"2021-05-24T03:47:52.978675Z","iopub.execute_input":"2021-05-24T03:47:52.978966Z","iopub.status.idle":"2021-05-24T03:47:52.993624Z","shell.execute_reply.started":"2021-05-24T03:47:52.978937Z","shell.execute_reply":"2021-05-24T03:47:52.992544Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class WheatDataset(Dataset):\n    def __init__(self, root, transform=None):\n        self.root = root\n        self.transform = transform\n        self.images = glob.glob(os.path.join(root, '*'))\n    \n    def __getitem__(self, index):\n        image_path = self.images[index]\n        image_name = image_path.split('.')[-2].split('/')[-1]\n        \n        image = Image.open(image_path).convert('RGB')\n        target = {}\n        if self.transform is not None:\n            image, _ = self.transform(image, target)\n        return image, image_name\n    \n    def __len__(self):\n        return len(self.images)\n\ndef get_transform(train):\n    transforms = []\n    transforms.append(T.ToTensor())\n    if train:\n        transforms.append(T.RandomHorizontalFlip(0.5))\n    return T.Compose(transforms)\n\nroot = '../input/global-wheat-detection/test'\n\ntest_ds = WheatDataset(root, transform=get_transform(train=False))\ntest_dl = DataLoader(test_ds, batch_size=1, shuffle=False, collate_fn=utils.collate_fn)","metadata":{"execution":{"iopub.status.busy":"2021-05-24T03:47:53.157572Z","iopub.execute_input":"2021-05-24T03:47:53.157889Z","iopub.status.idle":"2021-05-24T03:47:53.169721Z","shell.execute_reply.started":"2021-05-24T03:47:53.157860Z","shell.execute_reply":"2021-05-24T03:47:53.168687Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\nweight_path = '../input/gwd-pytorch-fasterrcnn-training/fasterrcnn_resnet50_fpn_plabel.pth'\n\ndef get_model(num_classes):\n    model = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=False, pretrained_backbone=False)\n    in_features = model.roi_heads.box_predictor.cls_score.in_features\n    model.roi_heads.box_predictor = FastRCNNPredictor(in_features, num_classes)\n    return model\n\nmodel = get_model(2).to(device)\nmodel.load_state_dict(torch.load(weight_path))","metadata":{"execution":{"iopub.status.busy":"2021-05-24T03:47:53.288296Z","iopub.execute_input":"2021-05-24T03:47:53.288553Z","iopub.status.idle":"2021-05-24T03:47:54.288135Z","shell.execute_reply.started":"2021-05-24T03:47:53.288527Z","shell.execute_reply":"2021-05-24T03:47:54.287137Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def to_PredString(scores, boxes):\n    result = []\n    for score, box in zip(scores, boxes):\n        if isinstance(scores, np.ndarray):\n            scores = torch.tensor(scores, device=device, dtype=torch.float)\n            \n        result.append(round(score.item(),4))\n        result.append(box[0].item())\n        result.append(box[1].item())\n        result.append(box[2].item())\n        result.append(box[3].item())\n    return ' '.join([str(x) for x in result])","metadata":{"execution":{"iopub.status.busy":"2021-05-24T03:47:54.289743Z","iopub.execute_input":"2021-05-24T03:47:54.290103Z","iopub.status.idle":"2021-05-24T03:47:54.297474Z","shell.execute_reply.started":"2021-05-24T03:47:54.290065Z","shell.execute_reply":"2021-05-24T03:47:54.296273Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class BaseWheatTTA():\n    image_size = 1024\n    \n    def augment(self, image):\n        raise NotImplementedError\n    \n    def batch_augment(self, images):\n        raise NotImplementedError\n    \n    def deaugmented_boxes(self, boxes):\n        raise NotImplementedError\n\nclass TTAHorizontalFlip(BaseWheatTTA):\n    def augment(self, image):\n        return image.flip(2)\n    \n    def batch_augment(self, images):\n        return images.flip(3)\n    \n    def deaugment_boxes(self, boxes):\n        boxes[:, [0, 2]] = self.image_size - boxes[:, [2, 0]]\n        return boxes\n\nclass TTAVerticalFlip(BaseWheatTTA):\n    def augment(self, image):\n        return image.flip(1)\n    \n    def batch_augment(self, images):\n        return images.flip(2)\n    \n    def deaugment_boxes(self, boxes):\n        boxes[:, [1, 3]] = self.image_size - boxes[:, [3, 1]]\n        return boxes\n\nclass TTARotate90(BaseWheatTTA):\n    def augment(self, image):\n        return torch.rot90(image, 1, (1, 2))\n\n    def batch_augment(self, images):\n        return torch.rot90(images, 1, (2, 3))\n    \n    def deaugment_boxes(self, boxes):\n        res_boxes = boxes.clone()\n        res_boxes[:, [0,2]] = self.image_size - boxes[:, [3,1]]\n        res_boxes[:, [1,3]] = boxes[:, [0,2]]\n        return res_boxes\n\nclass TTACompose(BaseWheatTTA):\n    def __init__(self, transforms):\n        self.transforms = transforms\n    \n    def augment(self, image):\n        for transform in self.transforms:\n            image = transform.augment(image)\n        return image\n    \n    def batch_augment(self, images):\n        for transform in self.transforms:\n            images = transform.batch_augment(images)\n        return images\n    \n    def deaugment_boxes(self, boxes):\n        for transform in self.transforms[::-1]:\n            boxes = transform.deaugment_boxes(boxes)\n        return boxes","metadata":{"execution":{"iopub.status.busy":"2021-05-24T03:47:54.299505Z","iopub.execute_input":"2021-05-24T03:47:54.299949Z","iopub.status.idle":"2021-05-24T03:47:54.316509Z","shell.execute_reply.started":"2021-05-24T03:47:54.299912Z","shell.execute_reply":"2021-05-24T03:47:54.315321Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from itertools import product\n\ntta_transforms = []\nfor tta_combination in product([TTAHorizontalFlip(), None],\n                              [TTAVerticalFlip(), None],\n                              [TTARotate90(), None]):\n    tta_transforms.append(TTACompose([tta_tranform for tta_tranform in tta_combination if tta_tranform is not None]))\n\ndef make_tta_prediction(model, image, threshold=0.5):\n    predictions = []\n    model.eval()\n    with torch.no_grad():\n        for tta_transform in tta_transforms:\n            result = []\n            tta_transformed_image = tta_transform.augment(image[0])\n            \n            prediction = model([tta_transformed_image.to(device)])\n            \n            boxes = prediction[0]['boxes']\n            scores = prediction[0]['scores']\n            \n            boxes = boxes[scores > threshold]\n            scores = scores[scores > threshold]\n            \n            boxes = tta_transform.deaugment_boxes(boxes)\n            \n            result.append({\n                'boxes': boxes,\n                'scores': scores,\n            })\n            predictions.append(result)\n    return predictions\n\ndef run_wbf(predictions, image_size, iou_thr=0.5, skip_box_thr=0.0001, weights=None):\n    '''\n    boxes: list\n    scores: list\n    labels: list\n    '''\n    \n    boxes = [((predictions[i][0]['boxes'].clip(min=0, max=1023)) / (image_size - 1)).tolist() for i in range(len(predictions))]\n    scores = [predictions[i][0]['scores'].tolist() for i in range(len(predictions))]\n    labels = [torch.ones((len(box),), device=device, dtype=torch.int8).tolist() for box in boxes]\n    \n    boxes, scores, labels = weighted_boxes_fusion(boxes, scores, labels, weights=weights, iou_thr=iou_thr, skip_box_thr=skip_box_thr)\n    boxes = boxes * (image_size - 1)\n    return boxes, scores, labels","metadata":{"execution":{"iopub.status.busy":"2021-05-24T03:47:54.318183Z","iopub.execute_input":"2021-05-24T03:47:54.318649Z","iopub.status.idle":"2021-05-24T03:47:54.334282Z","shell.execute_reply.started":"2021-05-24T03:47:54.318612Z","shell.execute_reply":"2021-05-24T03:47:54.332523Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_ids = []\nPredStrings = []\n\ndef show_result(image: torch.Tensor, boxes: np.ndarray):\n    img = Image.fromarray(image[0].permute(1,2,0).mul(255).byte().cpu().numpy().astype(np.uint8)).convert('RGB')\n    img = np.array(img)\n    for box in boxes:\n        cv2.rectangle(img, (box[0], box[1]), (box[2], box[3]), (225, 0, 0), 3)\n    plt.imshow(img)\n    plt.axis('off')\n\nmodel.eval()\nwith torch.no_grad(): \n    for i, (image, image_id) in enumerate(test_dl):\n        prediction = make_tta_prediction(model, image)\n        \n        boxes, scores, labels = run_wbf(predictions=prediction, image_size=1024)\n        boxes = boxes.round().astype(np.int32).clip(min=0, max=1023)\n        \n#         plt.subplot(5, 2, i + 1)\n#         show_result(image, boxes)\n    \n        boxes[:, 2] = boxes[:, 2] - boxes[:, 0]\n        boxes[:, 3] = boxes[:, 3] - boxes[:, 1]\n        \n        pred_string = to_PredString(scores, boxes)\n        \n        image_ids.append(image_id[0])\n        PredStrings.append(pred_string)","metadata":{"execution":{"iopub.status.busy":"2021-05-24T03:47:54.335451Z","iopub.execute_input":"2021-05-24T03:47:54.335715Z","iopub.status.idle":"2021-05-24T03:48:14.935632Z","shell.execute_reply.started":"2021-05-24T03:47:54.335672Z","shell.execute_reply":"2021-05-24T03:48:14.934680Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df = pd.DataFrame({'image_id': image_ids, 'PredictionString': PredStrings})\ntest_df","metadata":{"execution":{"iopub.status.busy":"2021-05-24T03:48:14.937536Z","iopub.execute_input":"2021-05-24T03:48:14.938053Z","iopub.status.idle":"2021-05-24T03:48:14.953081Z","shell.execute_reply.started":"2021-05-24T03:48:14.937995Z","shell.execute_reply":"2021-05-24T03:48:14.951985Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df.to_csv('submission.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2021-05-24T03:48:14.954734Z","iopub.execute_input":"2021-05-24T03:48:14.955214Z","iopub.status.idle":"2021-05-24T03:48:15.089222Z","shell.execute_reply.started":"2021-05-24T03:48:14.955170Z","shell.execute_reply":"2021-05-24T03:48:15.088444Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}