{"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":"<h2 align=center style=\"color:blue; border:1px dotted blue\">Global Wheat Detection - Faster RCNN</h2>","metadata":{}},{"cell_type":"code","source":"#importing all the required libraries\nimport numpy as np\nimport pandas as pd\nfrom tqdm.notebook import tqdm\nimport torch\nimport torchvision\nimport torchvision.transforms as T\nfrom collections import defaultdict, deque\nfrom torchvision.models.detection.faster_rcnn import FastRCNNPredictor\nfrom torchvision.models.detection import FasterRCNN\nfrom torchvision.models.detection.faster_rcnn import FastRCNNPredictor\nfrom torchvision.models.detection import FasterRCNN\nfrom torchvision.models.detection.rpn import AnchorGenerator\nimport ast\nfrom torch.utils.data import DataLoader, Dataset\nfrom torch.utils.data.sampler import SequentialSampler\n\nimport cv2\nimport os,sys,matplotlib,re\nfrom PIL import Image\nfrom skimage import exposure\nfrom pydicom.pixel_data_handlers.util import apply_voi_lut\nimport matplotlib.pyplot as plt\nimport matplotlib.image as immg\nimport matplotlib\n\nimport warnings\nwarnings.filterwarnings(\"ignore\")","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_kg_hide-input":false,"execution":{"iopub.status.busy":"2021-07-25T10:11:40.145854Z","iopub.execute_input":"2021-07-25T10:11:40.146191Z","iopub.status.idle":"2021-07-25T10:11:42.696276Z","shell.execute_reply.started":"2021-07-25T10:11:40.146113Z","shell.execute_reply":"2021-07-25T10:11:42.695398Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#check if a GPU is available or not\ndevice = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')","metadata":{"execution":{"iopub.status.busy":"2021-07-25T10:11:46.431352Z","iopub.execute_input":"2021-07-25T10:11:46.431700Z","iopub.status.idle":"2021-07-25T10:11:46.503200Z","shell.execute_reply.started":"2021-07-25T10:11:46.431666Z","shell.execute_reply":"2021-07-25T10:11:46.502099Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#read the train dataset\npath = '../input/gwd-512-image-resized/'\ntrain_df = pd.read_csv('../input/global-wheat-detection/train.csv')\ntrain_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-07-25T10:11:47.537267Z","iopub.execute_input":"2021-07-25T10:11:47.537588Z","iopub.status.idle":"2021-07-25T10:11:47.827850Z","shell.execute_reply.started":"2021-07-25T10:11:47.537549Z","shell.execute_reply":"2021-07-25T10:11:47.826968Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#define the bounding boxes in terms of the minimum x and y coordinates and the given height and width\ntrain_df['x_min'] = -1\ntrain_df['y_min'] = -1\ntrain_df['w'] = -1\ntrain_df['h'] = -1\n\ntrain_df[['x_min', 'y_min', 'w', 'h']] = np.stack(train_df['bbox'].apply(lambda x: ast.literal_eval(x)))\ntrain_df.drop(columns=['bbox'], inplace=True)\ntrain_df['x_min'] = train_df['x_min'].astype(np.float)\ntrain_df['y_min'] = train_df['y_min'].astype(np.float)\ntrain_df['w'] = train_df['w'].astype(np.float)\ntrain_df['h'] = train_df['h'].astype(np.float)\ntrain_df['x_max'] = train_df['x_min']+train_df['w']\ntrain_df['y_max'] = train_df['y_min']+train_df['h']","metadata":{"execution":{"iopub.status.busy":"2021-07-25T10:11:48.787095Z","iopub.execute_input":"2021-07-25T10:11:48.787416Z","iopub.status.idle":"2021-07-25T10:11:51.677686Z","shell.execute_reply.started":"2021-07-25T10:11:48.787385Z","shell.execute_reply":"2021-07-25T10:11:51.676763Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-07-25T10:11:51.679196Z","iopub.execute_input":"2021-07-25T10:11:51.679640Z","iopub.status.idle":"2021-07-25T10:11:51.699846Z","shell.execute_reply.started":"2021-07-25T10:11:51.679604Z","shell.execute_reply":"2021-07-25T10:11:51.698322Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = train_df.copy()","metadata":{"execution":{"iopub.status.busy":"2021-07-25T10:11:57.574349Z","iopub.execute_input":"2021-07-25T10:11:57.574719Z","iopub.status.idle":"2021-07-25T10:11:57.583595Z","shell.execute_reply.started":"2021-07-25T10:11:57.574682Z","shell.execute_reply":"2021-07-25T10:11:57.582440Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#normalization\ndf['x_min'] = df['x_min']*512/1024\ndf['x_max'] = np.ceil(df['x_max']*512/1024)\ndf['y_min'] = df['y_min']*512/1024\ndf['y_max'] = np.ceil(df['y_max']*512/1024)","metadata":{"execution":{"iopub.status.busy":"2021-07-25T10:11:58.345864Z","iopub.execute_input":"2021-07-25T10:11:58.346230Z","iopub.status.idle":"2021-07-25T10:11:58.363434Z","shell.execute_reply.started":"2021-07-25T10:11:58.346195Z","shell.execute_reply":"2021-07-25T10:11:58.362466Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.describe()","metadata":{"execution":{"iopub.status.busy":"2021-07-25T10:11:59.606649Z","iopub.execute_input":"2021-07-25T10:11:59.607020Z","iopub.status.idle":"2021-07-25T10:11:59.677606Z","shell.execute_reply.started":"2021-07-25T10:11:59.606984Z","shell.execute_reply":"2021-07-25T10:11:59.676720Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h2 align=center style=\"color:red; border:1px dotted red\">Dataset</h2>","metadata":{}},{"cell_type":"code","source":"df = df.reset_index(drop=True)","metadata":{"execution":{"iopub.status.busy":"2021-07-25T10:12:01.601395Z","iopub.execute_input":"2021-07-25T10:12:01.601768Z","iopub.status.idle":"2021-07-25T10:12:01.614792Z","shell.execute_reply.started":"2021-07-25T10:12:01.601734Z","shell.execute_reply":"2021-07-25T10:12:01.613503Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_grp = df.groupby(['image_id'])\nb_fea = ['x_min', 'y_min', 'x_max', 'y_max']","metadata":{"execution":{"iopub.status.busy":"2021-07-25T10:12:03.078106Z","iopub.execute_input":"2021-07-25T10:12:03.078440Z","iopub.status.idle":"2021-07-25T10:12:03.083633Z","shell.execute_reply.started":"2021-07-25T10:12:03.078407Z","shell.execute_reply":"2021-07-25T10:12:03.082405Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#show a training image\nname = df.image_id.unique()[9]\nloc = path+name+'.jpg'\naaa = df_grp.get_group(name)\nbbx = aaa.loc[:,b_fea]\nimg = immg.imread(loc)\nfig,ax = plt.subplots(figsize=(18,10))\nax.imshow(img,cmap='binary')\nfor i in range(len(bbx)):\n    box = bbx.iloc[i].values\n    x,y,w,h = box[0], box[1], box[2]-box[0], box[3]-box[1]\n    rect = matplotlib.patches.Rectangle((x,y),w,h,linewidth=1,edgecolor='r',facecolor='none',)\n    ax.text(*box[:2], \"wheat\", verticalalignment='top', color='white', fontsize=13, weight='bold')\n    ax.add_patch(rect)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-07-25T10:12:10.456278Z","iopub.execute_input":"2021-07-25T10:12:10.456609Z","iopub.status.idle":"2021-07-25T10:12:11.076497Z","shell.execute_reply.started":"2021-07-25T10:12:10.456571Z","shell.execute_reply":"2021-07-25T10:12:11.075701Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Dataset","metadata":{}},{"cell_type":"code","source":"#given a csv dataset with bounding box coordinates, create the bounding boxes on the image\nclass WheatDataset(object):\n    def __init__(self, df, IMG_DIR, transforms=None):\n        # select only those classes that have boxes\n        \n        self.df = df\n        self.img_dir = IMG_DIR\n        self.image_ids = self.df['image_id'].unique().tolist()\n        self.transforms = transforms\n        \n    def __len__(self):\n        return len(self.image_ids)\n    \n    \n    def __getitem__(self, idx):\n        image_id = self.image_ids[idx]\n        records = self.df[self.df['image_id'] == image_id]\n        image = cv2.imread(self.img_dir+image_id+\".jpg\",cv2.IMREAD_COLOR)\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB).astype(np.float32)\n        image /= 255.0\n        \n        boxes = records[['x_min', 'y_min', 'x_max', 'y_max']].to_numpy()\n        area = (boxes[:, 3] - boxes[:, 1]) * (boxes[:, 2] - boxes[:, 0])\n        labels = torch.ones((records.shape[0],), dtype=torch.int64)\n        \n        target = {}\n        target['boxes'] = boxes\n        target['labels'] = labels\n        target['image_id'] = torch.tensor([idx])\n        target['area'] = torch.as_tensor(area, dtype=torch.float32)\n        target['iscrowd'] = torch.zeros((records.shape[0],), dtype=torch.int64)\n    \n        if self.transforms:\n            sample = {\n                'image': image,\n                'bboxes': target['boxes'],\n                'labels': labels\n            }\n            sample = self.transforms(**sample)\n            image = sample['image']\n            \n            target['boxes'] = torch.stack(tuple(map(torch.tensor, zip(*sample['bboxes'])))).permute(1, 0)\n\n        return torch.tensor(image), target, image_id","metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","execution":{"iopub.status.busy":"2021-07-25T10:12:14.664697Z","iopub.execute_input":"2021-07-25T10:12:14.665043Z","iopub.status.idle":"2021-07-25T10:12:14.677498Z","shell.execute_reply.started":"2021-07-25T10:12:14.665012Z","shell.execute_reply":"2021-07-25T10:12:14.675061Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Transforms","metadata":{}},{"cell_type":"code","source":"IMG_SIZE = (512,512)","metadata":{"execution":{"iopub.status.busy":"2021-07-25T10:12:24.009609Z","iopub.execute_input":"2021-07-25T10:12:24.009965Z","iopub.status.idle":"2021-07-25T10:12:24.015917Z","shell.execute_reply.started":"2021-07-25T10:12:24.009928Z","shell.execute_reply":"2021-07-25T10:12:24.012979Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import albumentations as A\nfrom albumentations.pytorch.transforms import ToTensorV2\ndef get_train_transform():\n    return A.Compose([\n        A.Flip(0.5),\n        ToTensorV2(p=1.0)\n    ], bbox_params={'format': 'pascal_voc', 'label_fields': ['labels']})\n\ndef get_valid_transform():\n    return A.Compose([\n        ToTensorV2(p=1.0)\n    ], bbox_params={'format': 'pascal_voc', 'label_fields': ['labels']})","metadata":{"execution":{"iopub.status.busy":"2021-07-25T10:12:26.118303Z","iopub.execute_input":"2021-07-25T10:12:26.118930Z","iopub.status.idle":"2021-07-25T10:12:27.366507Z","shell.execute_reply.started":"2021-07-25T10:12:26.118881Z","shell.execute_reply":"2021-07-25T10:12:27.365746Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img_dir = \"../input/gwd-512-image-resized/\"","metadata":{"execution":{"iopub.status.busy":"2021-07-25T10:12:27.447102Z","iopub.execute_input":"2021-07-25T10:12:27.447377Z","iopub.status.idle":"2021-07-25T10:12:27.450977Z","shell.execute_reply.started":"2021-07-25T10:12:27.447351Z","shell.execute_reply":"2021-07-25T10:12:27.450129Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"WDS = WheatDataset(df, img_dir ,get_train_transform())","metadata":{"execution":{"iopub.status.busy":"2021-07-25T10:12:27.665285Z","iopub.execute_input":"2021-07-25T10:12:27.665591Z","iopub.status.idle":"2021-07-25T10:12:27.681344Z","shell.execute_reply.started":"2021-07-25T10:12:27.665560Z","shell.execute_reply":"2021-07-25T10:12:27.680371Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Checking a Dataset Sample","metadata":{}},{"cell_type":"code","source":"#view a random image from training set\n\nimport random\nimg, tar,_ = WDS[random.randint(0,1000)]\nbbox = tar['boxes'].numpy()\nfig,ax = plt.subplots(figsize=(18,10))\nax.imshow(img.permute(1,2,0).cpu().numpy())\nfor i in range(len(bbox)):\n    box = bbox[i]\n    x,y,w,h = box[0], box[1], box[2]-box[0], box[3]-box[1]\n    rect = matplotlib.patches.Rectangle((x,y),w,h,linewidth=2,edgecolor='r',facecolor='none',)\n    ax.text(*box[:2], \"wheat\", verticalalignment='top', color='red', fontsize=13, weight='bold')\n    ax.add_patch(rect)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-07-25T10:12:30.244604Z","iopub.execute_input":"2021-07-25T10:12:30.244960Z","iopub.status.idle":"2021-07-25T10:12:30.879150Z","shell.execute_reply.started":"2021-07-25T10:12:30.244922Z","shell.execute_reply":"2021-07-25T10:12:30.878214Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_ids = df['image_id'].unique()\nvalid_ids = image_ids[-665:]\ntrain_ids = image_ids[:-665]\nvalid_df = df[df['image_id'].isin(valid_ids)]\ntrain_df = df[df['image_id'].isin(train_ids)]\ntrain_df.shape,valid_df.shape","metadata":{"execution":{"iopub.status.busy":"2021-07-25T10:12:37.161265Z","iopub.execute_input":"2021-07-25T10:12:37.161581Z","iopub.status.idle":"2021-07-25T10:12:37.210293Z","shell.execute_reply.started":"2021-07-25T10:12:37.161551Z","shell.execute_reply":"2021-07-25T10:12:37.209402Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## DataLoader","metadata":{}},{"cell_type":"code","source":"def collate_fn(batch):\n    return tuple(zip(*batch))\n\ntrain_dataset = WheatDataset(train_df,img_dir , get_train_transform())\nvalid_dataset = WheatDataset(valid_df,img_dir, get_valid_transform())\n\n\n# split the dataset into train and test set\nindices = torch.randperm(len(train_dataset)).tolist()\n\ntrain_data_loader = DataLoader(\n    train_dataset,\n    batch_size=8,\n    shuffle=False,\n    num_workers=4,\n    collate_fn=collate_fn\n)\n\nvalid_data_loader = DataLoader(\n    valid_dataset,\n    batch_size=8,\n    shuffle=False,\n    num_workers=4,\n    collate_fn=collate_fn\n)","metadata":{"execution":{"iopub.status.busy":"2021-07-25T10:12:47.098234Z","iopub.execute_input":"2021-07-25T10:12:47.098565Z","iopub.status.idle":"2021-07-25T10:12:47.117118Z","shell.execute_reply.started":"2021-07-25T10:12:47.098527Z","shell.execute_reply":"2021-07-25T10:12:47.116129Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h2 align=center style=\"color:blue; border:1px dotted blue\">Training</h2>","metadata":{}},{"cell_type":"code","source":"num_classes = 2  # 1 class (wheat) + background\n# load a model; pre-trained on COCO\nmodel = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=True)\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)","metadata":{"execution":{"iopub.status.busy":"2021-07-25T10:12:50.848637Z","iopub.execute_input":"2021-07-25T10:12:50.849012Z","iopub.status.idle":"2021-07-25T10:13:07.880338Z","shell.execute_reply.started":"2021-07-25T10:12:50.848978Z","shell.execute_reply":"2021-07-25T10:13:07.879579Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.to(device)\nparams = [p for p in model.parameters() if p.requires_grad]\noptimizer = torch.optim.SGD(params, lr=0.005, momentum=0.9, weight_decay=0.0005)\nlr_scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=3, gamma=0.1)\n#lr_scheduler = None","metadata":{"execution":{"iopub.status.busy":"2021-07-25T10:13:13.459755Z","iopub.execute_input":"2021-07-25T10:13:13.460101Z","iopub.status.idle":"2021-07-25T10:13:17.642494Z","shell.execute_reply.started":"2021-07-25T10:13:13.460068Z","shell.execute_reply":"2021-07-25T10:13:17.641768Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Averager","metadata":{}},{"cell_type":"code","source":"class Averager:\n    def __init__(self):\n        self.current_total = 0.0\n        self.iterations = 0.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.0\n        self.iterations = 0.0","metadata":{"execution":{"iopub.status.busy":"2021-07-25T10:13:22.528395Z","iopub.execute_input":"2021-07-25T10:13:22.528727Z","iopub.status.idle":"2021-07-25T10:13:22.534233Z","shell.execute_reply.started":"2021-07-25T10:13:22.528694Z","shell.execute_reply":"2021-07-25T10:13:22.533281Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Below apply_nms function\n\n**Performs non-maximum suppression (NMS) on the boxes according to their intersection-over-union (IoU).**\n\n**NMS iteratively removes lower scoring boxes which have an IoU greater than iou_threshold with another (higher scoring) box.**\n\n**If multiple boxes have the exact same score and satisfy the IoU criterion with respect to a reference box, the selected box is not guaranteed to be the same between CPU and GPU. This is similar to the behavior of argsort in PyTorch when repeated values are present.**\n\nSource : https://pytorch.org/vision/stable/ops.html","metadata":{}},{"cell_type":"code","source":"# the function takes the original prediction and the iou threshold.\ndef apply_nms(orig_prediction, iou_thresh=0.2):\n    \n    # torchvision returns the indices of the bboxes to keep\n    keep = torchvision.ops.nms(orig_prediction['boxes'], orig_prediction['scores'], iou_thresh)\n    \n    final_prediction = orig_prediction\n    final_prediction['boxes'] = final_prediction['boxes'][keep]\n    final_prediction['scores'] = final_prediction['scores'][keep]\n    final_prediction['labels'] = final_prediction['labels'][keep]\n    \n    return final_prediction","metadata":{"execution":{"iopub.status.busy":"2021-07-25T10:13:24.493271Z","iopub.execute_input":"2021-07-25T10:13:24.493598Z","iopub.status.idle":"2021-07-25T10:13:24.498686Z","shell.execute_reply.started":"2021-07-25T10:13:24.493566Z","shell.execute_reply":"2021-07-25T10:13:24.497838Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Training","metadata":{}},{"cell_type":"code","source":"num_epochs = 10","metadata":{"execution":{"iopub.status.busy":"2021-07-25T10:13:27.774848Z","iopub.execute_input":"2021-07-25T10:13:27.775172Z","iopub.status.idle":"2021-07-25T10:13:27.778697Z","shell.execute_reply.started":"2021-07-25T10:13:27.775141Z","shell.execute_reply":"2021-07-25T10:13:27.777846Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"loss_hist = Averager()\nbest_epoch = 0\nmin_loss = sys.maxsize\nfor epoch in range(num_epochs):\n    loss_hist.reset()\n    tk = tqdm(train_data_loader)\n    model.train();\n    for images, targets, image_ids in tk:\n        \n        images = list(image.to(device) for image in images)\n        targets = [{k: v.to(device) for k, v in t.items()} for t in targets]\n\n        loss_dict = model(images, targets)\n\n        losses = sum(loss for loss in loss_dict.values())\n        loss_value = losses.item()\n\n        loss_hist.send(loss_value)\n\n        optimizer.zero_grad()\n        losses.backward()\n        optimizer.step()\n        \n        tk.set_postfix(train_loss=loss_value)\n    tk.close()\n    \n    # update the learning rate\n    if lr_scheduler is not None:\n        lr_scheduler.step()\n\n    print(f\"Epoch #{epoch} loss: {loss_hist.value}\") \n    \n    if loss_hist.value<min_loss:\n        print(\"Better model found at epoch {0} with {1:0.5f} loss value\".format(epoch,loss_hist.value))\n        torch.save(model.state_dict(), f\"model_state_epoch_{epoch}.pth\")\n        min_loss = loss_hist.value\n        best_epoch = epoch\n    #validation \n    model.eval();\n    with torch.no_grad():\n        tk = tqdm(valid_data_loader)\n        for images, targets, image_ids in tk:\n        \n            images = list(image.to(device) for image in images)\n            targets = [{k: v.to(device) for k, v in t.items()} for t in targets]\n            val_output = model(images)\n            val_output = [{k: v.to('cpu') for k, v in t.items()} for t in val_output]\n            IOU = []\n            for j in range(len(val_output)):\n                val_out = apply_nms(val_output[j])\n                a,b = val_out['boxes'].cpu().detach(), targets[j]['boxes'].cpu().detach()\n                chk = torchvision.ops.box_iou(a,b)\n                res = np.nanmean(chk.sum(axis=1)/(chk>0).sum(axis=1))\n                IOU.append(res)\n            tk.set_postfix(IoU=np.mean(IOU))\n        tk.close()\n        \nmodel.load_state_dict(torch.load(f\"./model_state_epoch_{best_epoch}.pth\"));","metadata":{"execution":{"iopub.status.busy":"2021-07-25T10:13:28.856799Z","iopub.execute_input":"2021-07-25T10:13:28.857140Z","iopub.status.idle":"2021-07-25T11:12:05.916535Z","shell.execute_reply.started":"2021-07-25T10:13:28.857108Z","shell.execute_reply":"2021-07-25T11:12:05.915624Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.load_state_dict(torch.load(f\"./model_state_epoch_{best_epoch}.pth\"));","metadata":{"execution":{"iopub.status.busy":"2021-07-25T11:12:05.918854Z","iopub.execute_input":"2021-07-25T11:12:05.919226Z","iopub.status.idle":"2021-07-25T11:12:06.076157Z","shell.execute_reply.started":"2021-07-25T11:12:05.919186Z","shell.execute_reply":"2021-07-25T11:12:06.075078Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h2 align=center style=\"color:blue; border:1px dotted blue\">Analyze</h2>","metadata":{}},{"cell_type":"markdown","source":"## Validation And Prediction","metadata":{}},{"cell_type":"code","source":"#show prediction\nimg,target,_ = valid_dataset[50]\n# put the model in evaluation mode\nmodel.eval()\nwith torch.no_grad():\n    prediction = model([img.to(device)])[0]\n    \nprint('predicted #boxes: ', len(prediction['boxes']))\nprint('real #boxes: ', len(target['boxes']))","metadata":{"execution":{"iopub.status.busy":"2021-07-25T11:12:06.077793Z","iopub.execute_input":"2021-07-25T11:12:06.078185Z","iopub.status.idle":"2021-07-25T11:12:06.172253Z","shell.execute_reply.started":"2021-07-25T11:12:06.078146Z","shell.execute_reply":"2021-07-25T11:12:06.171376Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Ground Truths","metadata":{}},{"cell_type":"code","source":"bbox = target['boxes'].numpy()\nfig,ax = plt.subplots(1,figsize=(18,10))\nax.imshow(img.permute(1,2,0).cpu().numpy())\nfor i in range(len(bbox)):\n    box = bbox[i]\n    x,y,w,h = box[0], box[1], box[2]-box[0], box[3]-box[1]\n    rect = matplotlib.patches.Rectangle((x,y),w,h,linewidth=2,edgecolor='r',facecolor='none',)\n    ax.text(*box[:2], \"wheat\", verticalalignment='top', color='red', fontsize=13, weight='bold')\n    ax.add_patch(rect)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-07-25T11:12:06.173470Z","iopub.execute_input":"2021-07-25T11:12:06.173965Z","iopub.status.idle":"2021-07-25T11:12:06.849140Z","shell.execute_reply.started":"2021-07-25T11:12:06.173928Z","shell.execute_reply":"2021-07-25T11:12:06.848369Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_valid(img,prediction,nms=True,detect_thresh=0.5):\n    fig,ax = plt.subplots(figsize=(18,10))\n    val_img = img.permute(1,2,0).cpu().numpy()\n    ax.imshow(val_img)\n    nms_prediction = apply_nms(prediction, iou_thresh=0.2) if nms else prediction\n    val_scores = nms_prediction['scores'].cpu().detach().numpy()\n    bbox = nms_prediction['boxes'].cpu().detach().numpy()\n    for i in range(len(bbox)):\n        if val_scores[i]>=detect_thresh:\n            box = bbox[i]\n            x,y,w,h = box[0], box[1], box[2]-box[0], box[3]-box[1]\n            rect = matplotlib.patches.Rectangle((x,y),w,h,linewidth=2 ,edgecolor='r',facecolor='none',)\n            ax.text(*box[:2], \"wheat {0:.3f}\".format(val_scores[i]), verticalalignment='top', color='white', fontsize=12, weight='bold')\n            ax.add_patch(rect)\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2021-07-25T11:12:06.851640Z","iopub.execute_input":"2021-07-25T11:12:06.852105Z","iopub.status.idle":"2021-07-25T11:12:06.863155Z","shell.execute_reply.started":"2021-07-25T11:12:06.852061Z","shell.execute_reply":"2021-07-25T11:12:06.862050Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Predictions on valid set","metadata":{}},{"cell_type":"code","source":"plot_valid(img,prediction)","metadata":{"execution":{"iopub.status.busy":"2021-07-25T11:12:06.865426Z","iopub.execute_input":"2021-07-25T11:12:06.866145Z","iopub.status.idle":"2021-07-25T11:12:07.820548Z","shell.execute_reply.started":"2021-07-25T11:12:06.866107Z","shell.execute_reply":"2021-07-25T11:12:07.819673Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h2 align=center style=\"color:blue; border:1px dotted blue\">Predictions on Test Dataset</h2>","metadata":{}},{"cell_type":"code","source":"submission = pd.read_csv('../input/global-wheat-detection/sample_submission.csv')","metadata":{"execution":{"iopub.status.busy":"2021-07-25T11:12:07.822097Z","iopub.execute_input":"2021-07-25T11:12:07.822407Z","iopub.status.idle":"2021-07-25T11:12:07.837061Z","shell.execute_reply.started":"2021-07-25T11:12:07.822374Z","shell.execute_reply":"2021-07-25T11:12:07.836359Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class TestDataset(object):\n    def __init__(self, df, IMG_DIR, transforms=None):\n        # select only those classes that have boxes\n        \n        self.df = df\n        self.img_dir = IMG_DIR\n        self.transforms = transforms\n        self.image_ids = self.df['image_id'].tolist()\n        \n    def __len__(self):\n        return len(self.image_ids)\n    \n    def __getitem__(self, idx):\n        \n        image_id = self.image_ids[idx]\n        image = cv2.imread(self.img_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","metadata":{"execution":{"iopub.status.busy":"2021-07-25T11:12:07.838637Z","iopub.execute_input":"2021-07-25T11:12:07.838988Z","iopub.status.idle":"2021-07-25T11:12:07.845895Z","shell.execute_reply.started":"2021-07-25T11:12:07.838953Z","shell.execute_reply":"2021-07-25T11:12:07.844896Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_test_transform(IMG_SIZE=(512,512)):\n    return A.Compose([\n         A.Normalize(mean=(0, 0, 0), std=(1, 1, 1), max_pixel_value=255.0, p=1.0),\n        A.Resize(*IMG_SIZE),\n        ToTensorV2(p=1.0)\n    ])","metadata":{"execution":{"iopub.status.busy":"2021-07-25T11:12:07.847409Z","iopub.execute_input":"2021-07-25T11:12:07.847845Z","iopub.status.idle":"2021-07-25T11:12:07.855802Z","shell.execute_reply.started":"2021-07-25T11:12:07.847795Z","shell.execute_reply":"2021-07-25T11:12:07.854843Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_img_dir = '../input/global-wheat-detection/test/'","metadata":{"execution":{"iopub.status.busy":"2021-07-25T11:12:07.857281Z","iopub.execute_input":"2021-07-25T11:12:07.857633Z","iopub.status.idle":"2021-07-25T11:12:07.864678Z","shell.execute_reply.started":"2021-07-25T11:12:07.857597Z","shell.execute_reply":"2021-07-25T11:12:07.863899Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"IMG_SIZE = (512,512)","metadata":{"execution":{"iopub.status.busy":"2021-07-25T11:12:07.867662Z","iopub.execute_input":"2021-07-25T11:12:07.868114Z","iopub.status.idle":"2021-07-25T11:12:07.877399Z","shell.execute_reply.started":"2021-07-25T11:12:07.868078Z","shell.execute_reply":"2021-07-25T11:12:07.876768Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_dataset = TestDataset(submission, test_img_dir ,get_test_transform(IMG_SIZE))","metadata":{"execution":{"iopub.status.busy":"2021-07-25T11:12:07.878332Z","iopub.execute_input":"2021-07-25T11:12:07.878712Z","iopub.status.idle":"2021-07-25T11:12:07.887786Z","shell.execute_reply.started":"2021-07-25T11:12:07.878676Z","shell.execute_reply":"2021-07-25T11:12:07.886858Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for j in range(submission.shape[0]):\n    img,_ = test_dataset[j]\n    # put the model in evaluation mode\n    model.eval()\n    with torch.no_grad():\n        prediction = model([img.to(device)])[0]\n    plot_valid(img,prediction)","metadata":{"execution":{"iopub.status.busy":"2021-07-25T11:12:07.889171Z","iopub.execute_input":"2021-07-25T11:12:07.889512Z","iopub.status.idle":"2021-07-25T11:12:14.019437Z","shell.execute_reply.started":"2021-07-25T11:12:07.889478Z","shell.execute_reply":"2021-07-25T11:12:14.018510Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}