{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# Import required packages\nimport numpy as np\nimport os\nimport pandas as pd\nimport re\nfrom PIL import Image\nfrom PIL import ImageDraw\nimport gc\nimport warnings\nimport time\nfrom numba import jit\nimport glob\n\n\nimport albumentations as A\n\nwarnings.filterwarnings('ignore')\n\n# PyTorch libraries\nimport torch\nimport torchvision\n\nfrom torchvision.models.detection.faster_rcnn import FastRCNNPredictor\nfrom torchvision.models.detection import FasterRCNN\n\nfrom torch.utils.data import DataLoader, Dataset\nfrom tqdm import tqdm\n\n# OpenCV\nimport cv2\n\n# Plotting libraries\nimport seaborn as sns\nimport matplotlib.pyplot as plt\n\n# %matplotlib inline\n# sns.set_style('whitegrid')\n# sns.set_palette('muted')\n# pd.set_option('display.max_columns', 500)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"BATCH = 4\n# Define the root directory\nroot_dir = '../input/global-wheat-detection'\ndevice = 'cuda' if torch.cuda.is_available() else 'cpu'\nDATA_ROOT_PATH = '../input/global-wheat-detection/test/'\n# DATA_ROOT_PATH = '../input/test222/'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# # Add columns for bbox coordinates\n# train_data['xmin'] = -1\n# train_data['ymin'] = -1\n# train_data['width'] = -1\n# train_data['height'] = -1\n\n# # join lists along `axis=0` \n# print(train_data['bbox'].apply(lambda x: bbox_coordinates(x)).shape)\n# coordinates = np.stack(train_data['bbox'].apply(lambda x: bbox_coordinates(x)))\n# print(coordinates.shape)\n\n# # Updating the newly created columns\n# train_data[['xmin', 'ymin', 'width', 'height']] = coordinates\n\n# # dropping the bbox column\n# train_data.drop(columns='bbox', inplace=True)\n# train_data.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class WheatDataset(Dataset):\n    def __init__(self, image_ids, transforms=None):\n        super().__init__()\n#         self.data = data_dir\n        self.image_ids = image_ids\n        self.transforms = transforms\n\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        \n#         image_id = self.images[idx].split('.')[0]\n#         path = os.path.join(self.data, image_id) + '.jpg'\n#         image = Image.open(path).convert(\"RGB\")\n        \n        if self.transforms is not None:\n            image = self.transforms(image)\n          \n        return image, image_id\n#         return image, target, image_id\n    \n    def __len__(self):\n#         return len(self.images)\n        return self.image_ids.shape[0]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# # helper class to keep track of loss and loss per iteration\n# # source: https://www.kaggle.com/pestipeti/pytorch-starter-fasterrcnn-train\n# class Averager:\n#     def __init__(self):\n#         self.current_total = 0\n#         self.iterations = 0\n        \n#     def send(self, value):\n#         self.current_total += value\n#         self.iterations += 1\n        \n#     @property\n#     def value(self):\n#         if self.iterations == 0:\n#             return 0\n#         else:\n#             return 1.0 * self.current_total / self.iterations\n        \n#     def reset(self):\n#         self.current_total = 0\n#         self.iterations = 0","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_model(num_classes):\n    # load the object detection model pre-trained on COCO\n    model = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=False, pretrained_backbone=False)\n    \n    # get the input features in the classifier\n    in_features = model.roi_heads.box_predictor.cls_score.in_features\n    \n    # replace the input features of pretrained head with the num_classes\n    model.roi_heads.box_predictor = FastRCNNPredictor(in_features, num_classes)\n    \n    return model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# creating some transforms\n# source: https://github.com/pytorch/vision/blob/master/references/detection/transforms.py\n# source: https://github.com/microsoft/computervision-recipes/blob/master/utils_cv/detection/dataset.py\n\n\nclass Compose(object):\n    def __init__(self, transforms):\n        self.transforms = transforms\n        \n    def __call__(self, image):\n        for t in self.transforms:\n            image = t(image)\n        return image\n\nclass RandomHorizontalFlip(object):\n    \"\"\"\n    Wrapper for torchvision's HorizontalFlip\n    \"\"\"\n    def __init__(self, prob):\n        self.prob = prob\n        \n    def __call__(self, image):\n        if random.random() < self.prob:\n            height, width = image.shape[-2:]  # image must be a ndarray or torch tensor (PIL.Image has no attribute `.shape`)\n            image = image.flip(-1)\n#             bbox = target['boxes']    # bbox coordinates MUST be of form [xmin, ymin, xmax, ymax]\n#             bbox[:, [0, 2]] = width - bbox[:, [2, 0]]\n#             target['boxes'] = bbox\n        return image\n\nclass ColorJitterTransform(object):\n    \"\"\"\n    Wrapper for torchvision's ColorJitter\n    \"\"\"\n    def __init__(self, brightness, contrast, saturation, hue):\n        self.brightness = brightness\n        self.contrast = contrast\n        self.saturation = saturation\n        self.hue = hue\n    \n    def __call__(self, image):\n        image = ColorJitter(\n            brightness=self.brightness,\n            contrast=self.contrast,\n            saturation=self.saturation,\n            hue=self.hue\n        )(image)\n        return image\n        \nclass ToTensor(object):\n    def __call__(self, image):\n        image = F.to_tensor(image)   # normalizes the image and converts PIL image to torch.tensor\n        return image\n\nclass Resize(object):\n    def __init__(self, height, width):\n        self.height = height\n        self.width = width\n    \n    def __call__(self, image):\n        image = torchvision.transforms.Resize((self.height, self.width))\n        return image\n        \nclass eli_bright(object):\n    def __init__(self, threshold, value):\n        self.threshold = threshold\n        self.value = value\n    \n    def __call__(self, image):\n        image[image > self.threshold] = self.value\n        \n        return image\n    \nclass gamma(object):\n    def __init__(self, gama, gain):\n        self.gama = gama\n        self.gain = gain\n    \n    def __call__(self, image):\n        image = F.adjust_gamma(image, self.gama, self.gain)\n        \n        return image\n        ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import random\nfrom torchvision.transforms import functional as F\nfrom torchvision.transforms import ColorJitter\n\n# merge all the images in a batch\ndef collate_fn(batch):\n    return tuple(zip(*batch))\n\n# add some image augmentation operations\ndef get_transform(train):\n    transforms = []\n    \n#     transforms.append(A.Resize(height=1024, width=1024, p=1.0))\n#     if train:\n#     transforms.append(Resize(1024, 1024))\n        \n#     if train:\n        # needs the image to be a PIL image\n#     transforms.append(ColorJitterTransform(brightness=0.2, contrast=0.2, saturation=0.4, hue=0.05))\n        \n#     if train:\n#         transforms.append(gamma(2, 1))\n        \n    # converts a PIL image to pytorch tensor\n    transforms.append(ToTensor())\n    \n#     if train:\n        # randomly flip the images, bboxes and ground truth (only during training)\n#     transforms.append(RandomHorizontalFlip(0.5))  # this operation needs image to be a torch tensor\n    \n#     if train:\n#         transforms.append(eli_bright(0.5, 0))\n#     return transforms.append(A.Compose([\n#             A.Resize(height=1024, width=1024, p=1.0),\n#             ToTensorV2(p=1.0),\n#         ], p=1.0))\n    \n        \n    return Compose(transforms)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"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)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# data_dir = os.path.join(root_dir, 'test')\n# dataset_train = WheatDataset(data_dir=data_dir, \n#                              transforms=get_transform(train=False))\ndataset_train = WheatDataset(np.array([path.split('/')[-1][:-4] for path in glob.glob(f'{DATA_ROOT_PATH}/*.jpg')]), \n                             transforms=get_transform(train=False))\ndataloader_train = DataLoader(dataset_train, batch_size=BATCH, shuffle=True, \n                                   num_workers=4, collate_fn=collate_fn)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"batch = iter(dataloader_train)\nimgs,img_id = next(batch)\nimages = list(img.to(device) for img in imgs)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"num_classes = 2\nmodel = get_model(num_classes)\nsaved_model_path = '../input/the-model/fasterrcnn_resnet50_fpn.pth'\nmodel.load_state_dict(torch.load(saved_model_path))\nmodel.eval()\nmodel.to(device)\n# predictions = model(images)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# predictions[0]['boxes']","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"results = []\nfor images, image_ids in dataloader_train:\n    images = torch.stack(images).float().cuda()\n    preds = model(images)\n\n    for i,img in enumerate(images):\n        if len(preds[i]['boxes']) > 0:\n            boxes = preds[i]['boxes'].cpu().detach().numpy().astype(np.int32).clip(min=0, max=1023)\n            scores = preds[i]['scores'].detach().cpu().numpy()\n    #         boxes_s = boxes.round().astype(np.int32).clip(min=0, max=1023)\n\n\n\n            boxes[:, 2] = boxes[:, 2] - boxes[:, 0]\n            boxes[:, 3] = boxes[:, 3] - boxes[:, 1]\n            \n            score_threshold = 0.5\n            indexes = np.where(scores > score_threshold)[0]\n            boxes = boxes[indexes]\n            image_id = image_ids[i]\n            \n            print(len(boxes))\n            \n            result = {\n              'image_id': image_id,\n              'PredictionString': format_prediction_string(boxes,scores)\n            }\n    \n        else:\n            image_id = image_ids[i]\n            result = {\n              'image_id': image_id,\n              'PredictionString': ''\n            }\n            \n        results.append(result)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_df = pd.DataFrame(results, columns=['image_id', 'PredictionString'])\ntest_df.to_csv('submission.csv', index=False)\ntest_df.head(10)\n\n# SUBMISSION_PATH = '/kaggle/working'\n# submission_id = 'submission'\n# cur_submission_path = os.path.join(SUBMISSION_PATH, '{}.csv'.format(submission_id))\n# sample_submission = pd.DataFrame(results, columns=[\"image_id\",\"PredictionString\"])\n# sample_submission.to_csv(cur_submission_path, index=False)\n# submission_df = pd.read_csv(cur_submission_path)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# submission_df.head(10)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# def show_bbox_single_image(images, targets):\n#     score_threshold = 0.4\n#     image = Image.fromarray(images[0].mul(255).permute(1,2,0).cpu().byte().numpy())\n#     boxes = targets[0]['boxes'].cpu().detach().numpy().astype(np.int64)\n# #     boxes[:, 2] = boxes[:, 2] - boxes[:, 0]\n# #     boxes[:, 3] = boxes[:, 3] - boxes[:, 1]\n    \n#     indexes = np.where(scores > score_threshold)[0]\n#     boxes = boxes[indexes]\n#     draw = ImageDraw.Draw(image)\n\n#     for box in boxes:\n#         coord1 = (box[0], box[1])\n#         coord2 = (box[2], box[3])\n#         draw.rectangle([coord1, coord2], outline=(220,20,60), width=3)\n#     return image\n\n# images, image_ids = next(iter(dataloader_train))\n# images = list(img.to(device) for img in images)\n# targets = model(images)\n# image = show_bbox_single_image(images, targets)\n# image","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# def createSubmission(models, device, data_loader, detection_threshold=0.9, iou_thr=0.5):\n#     SUBMISSION_PATH = '/kaggle/working'\n#     submission_id = 'submission'\n#     final_csv = []\n#     preds = model(images)\n#     for (image, boxes, scores, image_path) in results:\n#         boxes = boxes.detach().cpu().numpy()\n#         if boxes.shape[0] > 0 :\n#             boxes[:, 2] = boxes[:, 2] - boxes[:, 0]\n#             boxes[:, 3] = boxes[:, 3] - boxes[:, 1]\n#             image_id = image_path.split(\"/\")[-1]\n#             result = [image_id,format_prediction_string(boxes, scores)]\n#             final_csv.append(result)\n\n#     cur_submission_path = os.path.join(SUBMISSION_PATH, '{}.csv'.format(submission_id))\n#     sample_submission = pd.DataFrame(final_csv, columns=[\"image_id\",\"PredictionString\"])\n#     sample_submission.to_csv(cur_submission_path, index=False)\n#     submission_df = pd.read_csv(cur_submission_path)\n#     return submission_df\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# submission = createSubmission([resnet50,desnet121], device, test_loader, detection_threshold=0.5, iou_thr=0.3)","execution_count":null,"outputs":[]}],"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":4,"nbformat_minor":4}