{"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":"# Global Wheat Detection","metadata":{}},{"cell_type":"markdown","source":"### The competition description:\n\n    Welcome to the \"Global Wheat Detection\" competition! In this competition, contestent will detect wheat heads from outdoor images of wheat plants, including wheat datasets from around the globe. Using worldwide data, contestent will focus on a generalized solution to estimate the number and size of wheat heads. To better gauge the performance for unseen genotypes, environments, and observational conditions, the training dataset covers multiple regions. contestent will use more than 3,000 images from Europe (France, UK, Switzerland) and North America (Canada). The test data includes about 1,000 images from Australia, Japan, and China.","metadata":{}},{"cell_type":"markdown","source":"### The steps will go through :\n\n<h5><a href=\"#eda\">1. EDA.</a></h5>\n<h5><a href=\"#custom_dataset\">2. Creating custom dataset.</a></h5>\n<h5><a href=\"#ft_model\">3. Finetuning from a pretrained model.</a></h5>\n<h5><a href=\"#train_model\">4. Train the model.</a></h5>\n<h5><a href=\"#inference\">5. Inference time.</a></h5>\n<h5><a href=\"#conc\">6. conclusion.</a></h5>\n<h5><a href=\"#app\">Appendices</a></h5>\n","metadata":{}},{"cell_type":"markdown","source":"<div name=\"eda\" id=\"eda\"><h2>1. EDA</h2></div>\n","metadata":{}},{"cell_type":"markdown","source":"### importing dependencies","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport os\nimport re\nimport cv2\nimport torch\nfrom torch.utils.data import DataLoader, Dataset\nfrom torch.utils.data.sampler import SequentialSampler\nimport torchvision\nfrom torchvision import transforms \nfrom torchvision.models.detection import FasterRCNN\nfrom torchvision.models.detection.faster_rcnn import FastRCNNPredictor\nfrom torchvision.models.detection.rpn import AnchorGenerator\n\nfrom matplotlib import pyplot as plt","metadata":{"execution":{"iopub.status.busy":"2023-06-02T22:51:30.519804Z","iopub.execute_input":"2023-06-02T22:51:30.520193Z","iopub.status.idle":"2023-06-02T22:51:34.458809Z","shell.execute_reply.started":"2023-06-02T22:51:30.520161Z","shell.execute_reply":"2023-06-02T22:51:34.45738Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"WEIGHTS_FILE = '/kaggle/input/fasterrcnn/fasterrcnn_resnet50_fpn_best.pth'","metadata":{"execution":{"iopub.status.busy":"2023-06-02T22:51:34.460608Z","iopub.execute_input":"2023-06-02T22:51:34.461616Z","iopub.status.idle":"2023-06-02T22:51:34.46565Z","shell.execute_reply.started":"2023-06-02T22:51:34.461586Z","shell.execute_reply":"2023-06-02T22:51:34.464799Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df = pd.read_csv(\"/kaggle/input/global-wheat-detection/train.csv\")\nsubmit = pd.read_csv(\"/kaggle/input/global-wheat-detection/sample_submission.csv\")","metadata":{"execution":{"iopub.status.busy":"2023-06-02T22:51:34.467572Z","iopub.execute_input":"2023-06-02T22:51:34.467871Z","iopub.status.idle":"2023-06-02T22:51:34.863029Z","shell.execute_reply.started":"2023-06-02T22:51:34.467844Z","shell.execute_reply":"2023-06-02T22:51:34.861855Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.head(10)","metadata":{"execution":{"iopub.status.busy":"2023-06-02T22:51:34.865957Z","iopub.execute_input":"2023-06-02T22:51:34.866834Z","iopub.status.idle":"2023-06-02T22:51:34.901414Z","shell.execute_reply.started":"2023-06-02T22:51:34.866792Z","shell.execute_reply":"2023-06-02T22:51:34.900366Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df=train_df.drop(columns=['width','height','source']) #Drop unwanted columns","metadata":{"execution":{"iopub.status.busy":"2023-06-02T22:51:34.903068Z","iopub.execute_input":"2023-06-02T22:51:34.903737Z","iopub.status.idle":"2023-06-02T22:51:34.916775Z","shell.execute_reply.started":"2023-06-02T22:51:34.903693Z","shell.execute_reply":"2023-06-02T22:51:34.915417Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.info()","metadata":{"execution":{"iopub.status.busy":"2023-06-02T22:51:34.918311Z","iopub.execute_input":"2023-06-02T22:51:34.919279Z","iopub.status.idle":"2023-06-02T22:51:35.057178Z","shell.execute_reply.started":"2023-06-02T22:51:34.919241Z","shell.execute_reply":"2023-06-02T22:51:35.056238Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df['image_id'].nunique() ","metadata":{"execution":{"iopub.status.busy":"2023-06-02T22:51:35.058772Z","iopub.execute_input":"2023-06-02T22:51:35.059385Z","iopub.status.idle":"2023-06-02T22:51:35.083297Z","shell.execute_reply.started":"2023-06-02T22:51:35.059352Z","shell.execute_reply":"2023-06-02T22:51:35.082441Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"value_counts = (train_df['image_id'].value_counts())\nvalue_counts.max(),value_counts.min()  # maximum and minimum number of boxes in a single image are 116\n","metadata":{"execution":{"iopub.status.busy":"2023-06-02T22:51:35.084699Z","iopub.execute_input":"2023-06-02T22:51:35.085745Z","iopub.status.idle":"2023-06-02T22:51:35.120693Z","shell.execute_reply.started":"2023-06-02T22:51:35.085705Z","shell.execute_reply":"2023-06-02T22:51:35.119442Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Splitting the dimension of box \n\nnote that : the dimension of box is `x` , `y` , `w` , `h` and we will convert it later to be `[xmin, ymin, xmax, ymax]`\n","metadata":{}},{"cell_type":"code","source":"train_df['x'],train_df['y'],train_df['h'],train_df['w'] = -1,-1,-1,-1\n\ndef expand_bbox(x):\n    r = np.array(re.findall(\"([0-9]+[.]?[0-9]*)\", x))\n    if len(r) == 0:\n        r = [-1, -1, -1, -1]\n    return r","metadata":{"execution":{"iopub.status.busy":"2023-06-02T22:51:35.122875Z","iopub.execute_input":"2023-06-02T22:51:35.123496Z","iopub.status.idle":"2023-06-02T22:51:35.13317Z","shell.execute_reply.started":"2023-06-02T22:51:35.123458Z","shell.execute_reply":"2023-06-02T22:51:35.132349Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df[['x', 'y', 'w', 'h']] = np.stack(train_df['bbox'].apply(lambda x: expand_bbox(x))) ##Lets convert the Box in \ntrain_df['x'] = train_df['x'].astype(float)                                        #in our desired formate    \ntrain_df['y'] = train_df['y'].astype(float)\ntrain_df['w'] = train_df['w'].astype(float)\ntrain_df['h'] = train_df['h'].astype(float)","metadata":{"execution":{"iopub.status.busy":"2023-06-02T22:51:35.13727Z","iopub.execute_input":"2023-06-02T22:51:35.137645Z","iopub.status.idle":"2023-06-02T22:51:36.753846Z","shell.execute_reply.started":"2023-06-02T22:51:35.137617Z","shell.execute_reply":"2023-06-02T22:51:36.752943Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.head(10) ","metadata":{"execution":{"iopub.status.busy":"2023-06-02T22:51:36.755297Z","iopub.execute_input":"2023-06-02T22:51:36.755994Z","iopub.status.idle":"2023-06-02T22:51:36.776861Z","shell.execute_reply.started":"2023-06-02T22:51:36.755954Z","shell.execute_reply":"2023-06-02T22:51:36.775756Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Okay ... Now our data is ready to be Splited into training set and validation set\n## Splitting the data into train and validation set","metadata":{}},{"cell_type":"code","source":"image_ids = train_df['image_id'].unique()\nvalid_ids = image_ids[-665:]\ntrain_ids = image_ids[:-665]\nvalid_df = train_df[train_df['image_id'].isin(valid_ids)]\ntrain_df = train_df[train_df['image_id'].isin(train_ids)]","metadata":{"execution":{"iopub.status.busy":"2023-06-02T22:51:36.778173Z","iopub.execute_input":"2023-06-02T22:51:36.778985Z","iopub.status.idle":"2023-06-02T22:51:36.83549Z","shell.execute_reply.started":"2023-06-02T22:51:36.778956Z","shell.execute_reply":"2023-06-02T22:51:36.834386Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"trans = transforms.Compose([transforms.ToTensor()])   #Apply transform to image ","metadata":{"execution":{"iopub.status.busy":"2023-06-02T22:51:36.83759Z","iopub.execute_input":"2023-06-02T22:51:36.838016Z","iopub.status.idle":"2023-06-02T22:51:36.843858Z","shell.execute_reply.started":"2023-06-02T22:51:36.837975Z","shell.execute_reply":"2023-06-02T22:51:36.84268Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<div name=\"custom_dataset\" id=\"custom_dataset\"><h2>2. Creating custom dataset</h2></div>\n","metadata":{}},{"cell_type":"code","source":"class WheatDataset(Dataset):\n\n    def __init__(self, dataframe, image_dir, transforms=None,train=True):\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        self.train=train\n\n    def __len__(self) -> int:\n        return self.image_ids.shape[0]\n\n    def __getitem__(self, index: int):\n\n        image_id = self.image_ids[index]\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        if self.transforms is not None:  #Apply transformation\n            image = self.transforms(image)\n        if(self.train==False):  # For test data\n            return image, image_id\n        #Else for train and validation data\n        records = self.df[self.df['image_id'] == image_id]   \n        boxes = records[['x', 'y', 'w', 'h']].values\n        boxes[:, 2] = boxes[:, 0] + boxes[:, 2]\n        boxes[:, 3] = boxes[:, 1] + boxes[:, 3]\n        boxes = torch.as_tensor(boxes, dtype=torch.float32)\n        \n        area = (boxes[:, 3] - boxes[:, 1]) * (boxes[:, 2] - boxes[:, 0])\n        area = torch.as_tensor(area, dtype=torch.float32)\n\n        # there is only one class\n        labels = torch.ones((records.shape[0],), dtype=torch.int64)\n        \n        # suppose all instances are not crowd\n        iscrowd = torch.zeros((records.shape[0],), dtype=torch.int64)\n        \n        target = {}\n        target['boxes'] = boxes\n        target['labels'] = labels\n        target['image_id'] = torch.tensor([index])\n        target['area'] = area\n        target['iscrowd'] = iscrowd\n\n        return image, target,image_id  ","metadata":{"execution":{"iopub.status.busy":"2023-06-02T22:51:36.845839Z","iopub.execute_input":"2023-06-02T22:51:36.84625Z","iopub.status.idle":"2023-06-02T22:51:36.86165Z","shell.execute_reply.started":"2023-06-02T22:51:36.846211Z","shell.execute_reply":"2023-06-02T22:51:36.860406Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dir = '/kaggle/input/global-wheat-detection/train'\ntest_dir = '/kaggle/input/global-wheat-detection/test'","metadata":{"execution":{"iopub.status.busy":"2023-06-02T22:51:36.863706Z","iopub.execute_input":"2023-06-02T22:51:36.864148Z","iopub.status.idle":"2023-06-02T22:51:36.876758Z","shell.execute_reply.started":"2023-06-02T22:51:36.864112Z","shell.execute_reply":"2023-06-02T22:51:36.875358Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Averager:      ##Return the average loss \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\n        \n        \ndef collate_fn(batch):\n    return tuple(zip(*batch))\n\ntrain_dataset = WheatDataset(train_df, train_dir, trans,True)\nvalid_dataset = WheatDataset(valid_df, train_dir, trans,True)\n\n\n# split the dataset in train and test set\nindices = torch.randperm(len(train_dataset)).tolist()\n\ntrain_data_loader = DataLoader(\n    train_dataset,\n    batch_size=16,\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)\n\n#device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')","metadata":{"execution":{"iopub.status.busy":"2023-06-02T22:51:36.878744Z","iopub.execute_input":"2023-06-02T22:51:36.879909Z","iopub.status.idle":"2023-06-02T22:51:36.932671Z","shell.execute_reply.started":"2023-06-02T22:51:36.879869Z","shell.execute_reply":"2023-06-02T22:51:36.931655Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')","metadata":{"execution":{"iopub.status.busy":"2023-06-02T22:51:36.934298Z","iopub.execute_input":"2023-06-02T22:51:36.935253Z","iopub.status.idle":"2023-06-02T22:51:36.941264Z","shell.execute_reply.started":"2023-06-02T22:51:36.935207Z","shell.execute_reply":"2023-06-02T22:51:36.939957Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Now lets visualize some of the images with bounding box (exactly 4 images)","metadata":{}},{"cell_type":"code","source":"images, targets, image_ids = next(iter(train_data_loader))\nimages = list(image.to(device) for image in images)\ntargets = [{k: v.to(device) for k, v in t.items()} for t in targets]\n\nfig, axs = plt.subplots(2, 2, figsize=(16, 16))\n\nfor i, ax in enumerate(axs.flatten()):\n    boxes = targets[i]['boxes'].cpu().numpy().astype(np.int32)\n    sample = images[i].permute(1, 2, 0).cpu().numpy().squeeze()\n\n    # convert from RGB to BGR format\n    sample = cv2.cvtColor(sample, cv2.COLOR_RGB2BGR)\n\n    for box in boxes:\n        cv2.rectangle(sample,\n                      (box[0], box[1]),\n                      (box[2], box[3]),\n                      (220, 0, 0), 3)\n\n    ax.set_axis_off()\n    ax.imshow(sample)\n    \nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-06-02T22:51:36.942669Z","iopub.execute_input":"2023-06-02T22:51:36.942979Z","iopub.status.idle":"2023-06-02T22:51:42.709951Z","shell.execute_reply.started":"2023-06-02T22:51:36.942951Z","shell.execute_reply":"2023-06-02T22:51:42.708748Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<div name=\"ft_model\" id=\"ft_model\"><h2>3.Finetuuning the model</h2></div>\n","metadata":{}},{"cell_type":"code","source":"# load a model; pre-trained on COCO\nmodel = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=False, pretrained_backbone=False)","metadata":{"execution":{"iopub.status.busy":"2023-06-02T22:51:42.711752Z","iopub.execute_input":"2023-06-02T22:51:42.712297Z","iopub.status.idle":"2023-06-02T22:51:43.44418Z","shell.execute_reply.started":"2023-06-02T22:51:42.712263Z","shell.execute_reply":"2023-06-02T22:51:43.442968Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"num_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=model.to('cpu')\nmodel.load_state_dict(torch.load(WEIGHTS_FILE, map_location=torch.device('cpu')))  ##Load pre trained weights\n","metadata":{"execution":{"iopub.status.busy":"2023-06-02T22:51:43.445694Z","iopub.execute_input":"2023-06-02T22:51:43.446102Z","iopub.status.idle":"2023-06-02T22:51:45.059063Z","shell.execute_reply.started":"2023-06-02T22:51:43.446074Z","shell.execute_reply":"2023-06-02T22:51:45.05775Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Alright , model loaded and all keys matched succefully , now what ? it's time for Training our model ","metadata":{}},{"cell_type":"markdown","source":"<div name=\"train_model\" id=\"train_model\"><h2>4. Train the model</h2></div>\n","metadata":{}},{"cell_type":"code","source":"model.train()\nmodel.to(device)\nparams = [p for p in model.parameters() if p.requires_grad]\noptimizer = torch.optim.SGD(params, lr=0.01, momentum=0.9, weight_decay=0.00001)\nlr_scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=1, gamma=0.5)\n\nnum_epochs = 5\n\nloss_hist = Averager()\nitr = 1\n\nfor epoch in range(num_epochs):\n    loss_hist.reset()\n    \n    for images, targets, image_ids in train_data_loader:\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)   ##Return the loss\n\n        losses = sum(loss for loss in loss_dict.values())\n        loss_value = losses.item()\n\n        loss_hist.send(loss_value)  #Average out the loss\n\n        optimizer.zero_grad()\n        losses.backward()\n        optimizer.step()\n\n        if itr % 50 == 0:\n            print(f\"Iteration #{itr} loss: {loss_value}\")\n\n        itr += 1\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}\")","metadata":{"execution":{"iopub.status.busy":"2023-06-02T22:51:45.060398Z","iopub.execute_input":"2023-06-02T22:51:45.060732Z","iopub.status.idle":"2023-06-02T22:52:59.394732Z","shell.execute_reply.started":"2023-06-02T22:51:45.060702Z","shell.execute_reply":"2023-06-02T22:52:59.392958Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<div name=\"inference\" id=\"inference\"><h2>5. Inference time</h2></div>\n","metadata":{}},{"cell_type":"markdown","source":"### Load test data and create test loader","metadata":{}},{"cell_type":"code","source":"test_dataset = WheatDataset(submit,test_dir, trans,False)","metadata":{"execution":{"iopub.status.busy":"2023-06-02T22:52:59.396024Z","iopub.status.idle":"2023-06-02T22:52:59.397258Z","shell.execute_reply.started":"2023-06-02T22:52:59.397027Z","shell.execute_reply":"2023-06-02T22:52:59.397051Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_data_loader = DataLoader( test_dataset, batch_size=8, shuffle=False)  ##Test dataloader","metadata":{"execution":{"iopub.status.busy":"2023-06-02T22:52:59.398511Z","iopub.status.idle":"2023-06-02T22:52:59.398925Z","shell.execute_reply.started":"2023-06-02T22:52:59.398728Z","shell.execute_reply":"2023-06-02T22:52:59.398748Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Set the threshold value for predicting bounding box.","metadata":{}},{"cell_type":"code","source":"detection_threshold = 0.50","metadata":{"execution":{"iopub.status.busy":"2023-06-02T22:52:59.400142Z","iopub.status.idle":"2023-06-02T22:52:59.400554Z","shell.execute_reply.started":"2023-06-02T22:52:59.400359Z","shell.execute_reply":"2023-06-02T22:52:59.400379Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def format_prediction_string(boxes, scores): ## Define the formate for storing prediction results\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":{"execution":{"iopub.status.busy":"2023-06-02T22:52:59.401454Z","iopub.status.idle":"2023-06-02T22:52:59.401834Z","shell.execute_reply.started":"2023-06-02T22:52:59.401644Z","shell.execute_reply":"2023-06-02T22:52:59.401662Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Prediction ","metadata":{}},{"cell_type":"code","source":"## Lets make the prediction\nresults=[]\nmodel.eval()\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()    ##Formate of the output's box is [Xmin,Ymin,Xmax,Ymax]\n        scores = outputs[i]['scores'].data.cpu().numpy()\n        \n        boxes = boxes[scores >= detection_threshold].astype(np.int32) #Compare the score of output with the threshold and\n        scores = scores[scores >= detection_threshold]                    #slelect only those boxes whose score is greater\n                                                                          # than threshold value\n        image_id = image_ids[i]\n        \n        boxes[:, 2] = boxes[:, 2] - boxes[:, 0]         \n        boxes[:, 3] = boxes[:, 3] - boxes[:, 1]         #Convert the box formate to [Xmin,Ymin,W,H]\n        \n        \n            \n        result = {                                     #Store the image id and boxes and scores in result dict.\n            'image_id': image_id,\n            'PredictionString': format_prediction_string(boxes, scores)\n        }\n\n        \n        results.append(result)              #Append the result dict to Results list","metadata":{"execution":{"iopub.status.busy":"2023-06-02T22:52:59.40294Z","iopub.status.idle":"2023-06-02T22:52:59.403303Z","shell.execute_reply.started":"2023-06-02T22:52:59.403122Z","shell.execute_reply":"2023-06-02T22:52:59.403139Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df = pd.DataFrame(results, columns=['image_id', 'PredictionString'])\ntest_df.head()","metadata":{"execution":{"iopub.status.busy":"2023-06-02T22:52:59.405232Z","iopub.status.idle":"2023-06-02T22:52:59.405597Z","shell.execute_reply.started":"2023-06-02T22:52:59.405417Z","shell.execute_reply":"2023-06-02T22:52:59.405434Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample = images[1].permute(1,2,0).cpu().numpy()\nboxes = outputs[1]['boxes'].data.cpu().numpy()\nscores = outputs[1]['scores'].data.cpu().numpy()\n\nboxes = boxes[scores >= detection_threshold].astype(np.int32)","metadata":{"execution":{"iopub.status.busy":"2023-06-02T22:52:59.407229Z","iopub.status.idle":"2023-06-02T22:52:59.40762Z","shell.execute_reply.started":"2023-06-02T22:52:59.407432Z","shell.execute_reply":"2023-06-02T22:52:59.40745Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, ax = plt.subplots(1, 1, figsize=(16, 8))\n\nfor box in boxes:\n    cv2.rectangle(sample,\n                  (box[0], box[1]),\n                  (box[2], box[3]),\n                  (220, 0, 0), 2)\n    \nax.set_axis_off()\nax.imshow(sample)","metadata":{"execution":{"iopub.status.busy":"2023-06-02T22:52:59.408679Z","iopub.status.idle":"2023-06-02T22:52:59.409045Z","shell.execute_reply.started":"2023-06-02T22:52:59.408861Z","shell.execute_reply":"2023-06-02T22:52:59.408878Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df.to_csv('submission.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2023-06-02T22:52:59.410192Z","iopub.status.idle":"2023-06-02T22:52:59.412984Z","shell.execute_reply.started":"2023-06-02T22:52:59.412689Z","shell.execute_reply":"2023-06-02T22:52:59.412717Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<div name=\"conc\" id=\"conc\"><h2>6. Conculsion</h2></div>\n\nIn this project, I applied the Fast R-CNN object detection method to detect wheat heads in images for the Global Wheat Detection challenge on Kaggle. I prepared the data by removing unnecessary  columns and doing some simple EDA on the images and creating bounding boxes for the wheat heads using the provided annotations. I then trained the Fast R-CNN model using the prepared data.\nOverall, this project demonstrated the effectiveness of the Fast R-CNN object detection method for detecting wheat heads in images, which could have important applications in agriculture.\nI am satisfied with the results of this project and believe that it could be further improved by exploring other object detection methods or fine-tuning the hyperparameters of the Fast R-CNN model.","metadata":{}},{"cell_type":"markdown","source":"<div name=\"app\" id=\"capp\"><h2>Appendix</h2></div>\n","metadata":{}},{"cell_type":"markdown","source":"1. What's Custom dataset ? \nhttps://pytorch.org/tutorials/beginner/data_loading_tutorial.html\n2. What is Object Detection?\nhttps://medium.com/ml-research-lab/what-is-object-detection-51f9d872ece7\n3. Object detection using RCNN\nhttps://towardsdatascience.com/object-detection-explained-r-cnn-a6c813937a76","metadata":{}},{"cell_type":"markdown","source":"## If you found this notebook helpful, please up vote it !","metadata":{}},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}