{"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":"import time\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport cv2\nimport seaborn as sns\nfrom PIL import Image\nfrom tqdm import tqdm\nfrom collections import defaultdict\nimport ast\nfrom matplotlib import pyplot as plt\n\nimport albumentations as A\nfrom albumentations.pytorch.transforms import ToTensorV2\n\nimport torch\nimport torchvision\nimport torch.nn as nn\nfrom torchmetrics.metric import Metric\n\nfrom torch.cuda.amp import GradScaler, autocast\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision import transforms\nfrom torchvision.models.detection.faster_rcnn import FastRCNNPredictor\nfrom torchvision.models.detection import FasterRCNN","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-11-14T09:22:28.851808Z","iopub.execute_input":"2022-11-14T09:22:28.852226Z","iopub.status.idle":"2022-11-14T09:22:33.711491Z","shell.execute_reply.started":"2022-11-14T09:22:28.852142Z","shell.execute_reply":"2022-11-14T09:22:33.710308Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import wandb\n\n\nfrom kaggle_secrets import UserSecretsClient\nuser_secrets = UserSecretsClient()\nsecret_value_0 = user_secrets.get_secret(\"se1\")\nwandb.login(key=secret_value_0)\nanonymous = None","metadata":{"execution":{"iopub.status.busy":"2022-11-14T09:41:08.731188Z","iopub.execute_input":"2022-11-14T09:41:08.731577Z","iopub.status.idle":"2022-11-14T09:41:10.692113Z","shell.execute_reply.started":"2022-11-14T09:41:08.731545Z","shell.execute_reply":"2022-11-14T09:41:10.691159Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Load Train Data**","metadata":{}},{"cell_type":"code","source":"BASE_DIR = \"../input/tensorflow-great-barrier-reef/train_images/\"\n\ndf = pd.read_csv('../input/tensorflow-great-barrier-reef/train.csv')\n\ntqdm.pandas()\n\ndf['annotations'] = df['annotations'].progress_apply(lambda x: ast.literal_eval(x))\n\ndf.head()","metadata":{"execution":{"iopub.status.busy":"2022-11-14T05:59:47.071696Z","iopub.execute_input":"2022-11-14T05:59:47.074523Z","iopub.status.idle":"2022-11-14T05:59:47.916881Z","shell.execute_reply.started":"2022-11-14T05:59:47.074411Z","shell.execute_reply":"2022-11-14T05:59:47.915885Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df['num_bbox'] = df['annotations'].progress_apply(lambda x: len(x))\n \ndf.head()","metadata":{"execution":{"iopub.status.busy":"2022-11-14T05:59:47.918350Z","iopub.execute_input":"2022-11-14T05:59:47.923075Z","iopub.status.idle":"2022-11-14T05:59:48.006702Z","shell.execute_reply.started":"2022-11-14T05:59:47.923035Z","shell.execute_reply":"2022-11-14T05:59:48.005747Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = df[df[\"num_bbox\"]>0].reset_index(drop=True)\n\ndf.head()","metadata":{"execution":{"iopub.status.busy":"2022-11-14T05:59:48.010972Z","iopub.execute_input":"2022-11-14T05:59:48.013668Z","iopub.status.idle":"2022-11-14T05:59:48.040866Z","shell.execute_reply.started":"2022-11-14T05:59:48.013629Z","shell.execute_reply":"2022-11-14T05:59:48.039989Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df['image_path'] = \"video_\" + df['video_id'].astype(str) + \"/\" + df['video_frame'].astype(str) + \".jpg\"\ndf.head()","metadata":{"execution":{"iopub.status.busy":"2022-11-14T05:59:48.044918Z","iopub.execute_input":"2022-11-14T05:59:48.047480Z","iopub.status.idle":"2022-11-14T05:59:48.091047Z","shell.execute_reply.started":"2022-11-14T05:59:48.047442Z","shell.execute_reply":"2022-11-14T05:59:48.090096Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_bbox(annots):\n    bboxes = [list(annot.values()) for annot in annots]\n    return bboxes","metadata":{"execution":{"iopub.status.busy":"2022-11-14T05:59:48.095096Z","iopub.execute_input":"2022-11-14T05:59:48.095873Z","iopub.status.idle":"2022-11-14T05:59:48.104403Z","shell.execute_reply.started":"2022-11-14T05:59:48.095820Z","shell.execute_reply":"2022-11-14T05:59:48.103399Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df['bboxes_location'] = df.annotations.progress_apply(get_bbox)\ndf.sample(2)","metadata":{"execution":{"iopub.status.busy":"2022-11-14T05:59:48.111943Z","iopub.execute_input":"2022-11-14T05:59:48.114529Z","iopub.status.idle":"2022-11-14T05:59:48.167144Z","shell.execute_reply.started":"2022-11-14T05:59:48.114482Z","shell.execute_reply":"2022-11-14T05:59:48.166247Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\n\ntrain, valid = train_test_split(df, test_size=0.2, random_state=53)\n\nprint(\"Training size = \",train.shape)\nprint(\"Valid size = \",valid.shape)","metadata":{"execution":{"iopub.status.busy":"2022-11-14T05:59:48.171143Z","iopub.execute_input":"2022-11-14T05:59:48.173824Z","iopub.status.idle":"2022-11-14T05:59:48.187953Z","shell.execute_reply.started":"2022-11-14T05:59:48.173787Z","shell.execute_reply":"2022-11-14T05:59:48.186868Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Build Dataset**","metadata":{}},{"cell_type":"code","source":"class ReefDataset:\n\n    def __init__(self, df, transforms=None):\n        self.df = df\n        self.transforms = transforms\n\n    def can_augment(self, boxes):\n        \"\"\" Check if bounding boxes are OK to augment\n        \n        \n        For example: image_id 1-490 has a bounding box that is partially outside of the image\n        It breaks albumentation\n        Here we check the margins are within the image to make sure the augmentation can be applied\n        \"\"\"\n        \n        box_outside_image = ((boxes[:, 0] < 0).any() or (boxes[:, 1] < 0).any() \n                             or (boxes[:, 2] > 1280).any() or (boxes[:, 3] > 720).any())\n        return not box_outside_image\n\n    def get_boxes(self, row):\n        \"\"\"Returns the bboxes for a given row as a 3D matrix with format [x_min, y_min, x_max, y_max]\"\"\"\n        boxes = pd.DataFrame(row['annotations'], columns=['x', 'y', 'width', 'height']).astype(np.float32).values\n        \n        # Change from [x_min, y_min, w, h] to [x_min, y_min, x_max, y_max]\n        boxes[:, 2] = boxes[:, 0] + boxes[:, 2]\n        boxes[:, 3] = boxes[:, 1] + boxes[:, 3]\n        return boxes\n    \n    def get_image(self, row):\n        \"\"\"Gets the image for a given row\"\"\"\n        \n        image = cv2.imread(f'{BASE_DIR}/{row[\"image_path\"]}', cv2.IMREAD_COLOR)\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB).astype(np.float32)\n        image /= 255.0\n        return image\n    \n    def __getitem__(self, i):\n\n        row = self.df.iloc[i]\n        image = self.get_image(row)\n        boxes = self.get_boxes(row)\n        \n        n_boxes = boxes.shape[0]\n        \n        # Calculate the area\n        area = (boxes[:, 3] - boxes[:, 1]) * (boxes[:, 2] - boxes[:, 0])\n        \n        \n        target = {\n            'boxes': torch.as_tensor(boxes, dtype=torch.float32),\n            'area': torch.as_tensor(area, dtype=torch.float32),\n            \n            'image_id': torch.tensor([i]),\n            \n            # There is only one class\n            'labels': torch.ones((n_boxes,), dtype=torch.int64),\n            \n            'iscrowd': torch.zeros((n_boxes,), dtype=torch.int64)\n                        \n        }\n\n        if self.transforms and self.can_augment(boxes):\n            sample = {\n                'image': image,\n                'bboxes': target['boxes'],\n                'labels': target['labels']\n            }\n            sample = self.transforms(**sample)\n            image = sample['image']\n            \n            if n_boxes > 0:\n                target['boxes'] = torch.stack(tuple(map(torch.tensor, zip(*sample['bboxes'])))).permute(1, 0)\n        else:\n            image = ToTensorV2(p=1.0)(image=image)['image']\n\n        return image, target\n\n    def __len__(self):\n        return len(self.df)","metadata":{"execution":{"iopub.status.busy":"2022-11-14T05:59:48.192617Z","iopub.execute_input":"2022-11-14T05:59:48.194969Z","iopub.status.idle":"2022-11-14T05:59:48.216909Z","shell.execute_reply.started":"2022-11-14T05:59:48.194931Z","shell.execute_reply":"2022-11-14T05:59:48.215868Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_train_transform():\n    return A.Compose([A.Flip(0.5), # flip the image vertically or horizontally to genelizate model\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":"2022-11-14T05:59:48.221971Z","iopub.execute_input":"2022-11-14T05:59:48.222797Z","iopub.status.idle":"2022-11-14T05:59:48.232983Z","shell.execute_reply.started":"2022-11-14T05:59:48.222706Z","shell.execute_reply":"2022-11-14T05:59:48.231971Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Collate function\ndef collate_fn(batch):\n    return tuple(zip(*batch))","metadata":{"execution":{"iopub.status.busy":"2022-11-14T05:59:48.237722Z","iopub.execute_input":"2022-11-14T05:59:48.240577Z","iopub.status.idle":"2022-11-14T05:59:48.247061Z","shell.execute_reply.started":"2022-11-14T05:59:48.240541Z","shell.execute_reply":"2022-11-14T05:59:48.246137Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dataset = ReefDataset(train, get_train_transform())\nvalid_dataset = ReefDataset(valid, get_valid_transform())","metadata":{"execution":{"iopub.status.busy":"2022-11-14T05:59:48.251621Z","iopub.execute_input":"2022-11-14T05:59:48.253598Z","iopub.status.idle":"2022-11-14T05:59:48.261017Z","shell.execute_reply.started":"2022-11-14T05:59:48.253562Z","shell.execute_reply":"2022-11-14T05:59:48.260080Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Create PyTorch DataLoader**","metadata":{}},{"cell_type":"code","source":"BATCH_SIZE = 8\n\ntrain_loader = DataLoader(train_dataset,\n                          batch_size=BATCH_SIZE,\n                          shuffle=False,  \n                          collate_fn=collate_fn)\n\nvalid_loader = DataLoader(valid_dataset,\n                          batch_size=BATCH_SIZE,\n                          shuffle=False,  \n                          collate_fn=collate_fn)","metadata":{"execution":{"iopub.status.busy":"2022-11-14T05:59:48.263843Z","iopub.execute_input":"2022-11-14T05:59:48.265208Z","iopub.status.idle":"2022-11-14T05:59:48.275159Z","shell.execute_reply.started":"2022-11-14T05:59:48.265173Z","shell.execute_reply":"2022-11-14T05:59:48.274158Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Test one Sample**","metadata":{}},{"cell_type":"code","source":"num_bboxes = 0\ntries = 10\nwhile (num_bboxes == 0):\n    images, targets = next(iter(train_loader))\n    # images and targets are of list type\n    idx = np.random.randint(0, BATCH_SIZE)\n    img = images[idx]\n    target = targets[idx]\n    num_bboxes = len(target['boxes'])\n    tries -= 1\n    if tries == 0:\n        break\n\nif num_bboxes > 0:        \n    print(img.shape)\n    print(target.keys())\n    print(target['boxes'])\n\n    img = img.permute(1,2,0).numpy()\n    fig, ax = plt.subplots(1, 1, figsize=(16, 8))\n    if num_bboxes > 0:\n        boxes = target['boxes'].numpy()\n        for box in boxes:\n            c1, c2 = (int(box[0]), int(box[1])), (int(box[2]), int(box[3]))\n            cv2.rectangle(img, c1, c2,\n                      (220, 0, 0), 3)\n\n    plt.title(print(target['image_id']))\n    plt.imshow(img)\n    plt.show()\nelse:\n    print(':(')","metadata":{"execution":{"iopub.status.busy":"2022-11-14T05:59:48.276737Z","iopub.execute_input":"2022-11-14T05:59:48.277415Z","iopub.status.idle":"2022-11-14T05:59:49.561004Z","shell.execute_reply.started":"2022-11-14T05:59:48.277380Z","shell.execute_reply":"2022-11-14T05:59:49.559747Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Create the model**","metadata":{}},{"cell_type":"code","source":"device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')\n\n# load a model; pre-trained on COCO\nmodel = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=True)\nmodel = model.to(device)\n\nnum_classes = 2  # 1 class (starfish) + 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).to(device)","metadata":{"execution":{"iopub.status.busy":"2022-11-14T05:59:49.562091Z","iopub.execute_input":"2022-11-14T05:59:49.562393Z","iopub.status.idle":"2022-11-14T06:00:02.919700Z","shell.execute_reply.started":"2022-11-14T05:59:49.562365Z","shell.execute_reply":"2022-11-14T06:00:02.918627Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Test the model architecture on sample data**","metadata":{}},{"cell_type":"code","source":"images = list(image.to(device) for image in images)\ntargets = [{k: v.long().to(device) for k, v in t.items()} for t in targets]","metadata":{"execution":{"iopub.status.busy":"2022-11-14T06:00:02.925202Z","iopub.execute_input":"2022-11-14T06:00:02.927860Z","iopub.status.idle":"2022-11-14T06:00:02.962706Z","shell.execute_reply.started":"2022-11-14T06:00:02.927797Z","shell.execute_reply":"2022-11-14T06:00:02.961373Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"loss_dict = model(images, targets)\nlosses = sum(loss for loss in loss_dict.values())\nloss = losses.item()\nloss","metadata":{"execution":{"iopub.status.busy":"2022-11-14T06:00:02.964161Z","iopub.execute_input":"2022-11-14T06:00:02.964539Z","iopub.status.idle":"2022-11-14T06:00:10.018749Z","shell.execute_reply.started":"2022-11-14T06:00:02.964492Z","shell.execute_reply":"2022-11-14T06:00:10.017833Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Train","metadata":{}},{"cell_type":"code","source":"params = [p for p in model.parameters() if p.requires_grad]\noptimizer = torch.optim.SGD(params, lr=0.001)\n\nlr_scheduler = None\n\nnum_epochs = 10","metadata":{"execution":{"iopub.status.busy":"2022-11-14T06:00:10.022901Z","iopub.execute_input":"2022-11-14T06:00:10.025199Z","iopub.status.idle":"2022-11-14T06:00:10.036791Z","shell.execute_reply.started":"2022-11-14T06:00:10.025161Z","shell.execute_reply":"2022-11-14T06:00:10.035887Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"total_train_loss = []\ntotal_valid_loss = []\n\nlosses_value = 0\n\nfor epoch in range(num_epochs):\n    \n    start_time = time.time()\n    \n    # train\n    \n    train_loss = []\n    \n    for batch_idx, (images, targets) in enumerate(tqdm(train_loader)):\n        \n        images = list(image.to(device) for image in images)\n        targets = [{k: v.long().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        losses_value = losses.item()\n        train_loss.append(losses_value)   \n\n        optimizer.zero_grad()\n        losses.backward()\n        optimizer.step()\n        \n    epoch_train_loss = np.mean(train_loss)\n    total_train_loss.append(epoch_train_loss)\n            \n    if lr_scheduler is not None:\n        lr_scheduler.step()\n        \n    # valid\n    with torch.no_grad():\n        valid_loss = []\n        for batch_idx,(images, targets) in enumerate(valid_loader,1):\n            images = list(image.to(device) for image in images)\n            targets = [{k: v.long().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            valid_loss.append(loss_value)\n    \n    epoch_valid_loss = np.mean(valid_loss)           \n    total_valid_loss.append(epoch_valid_loss)\n    \n    chk_name = f'fasterrcnn_resnet50_fpn-e{epoch+1}.bin'\n    torch.save(model.state_dict(), chk_name)\n    \n    print(f\"Epoch Completed: {epoch+1}/{num_epochs}, Train Loss: {epoch_train_loss}, Valid Loss: {epoch_valid_loss} --> {chk_name}\")\n","metadata":{"execution":{"iopub.status.busy":"2022-11-14T06:00:10.041660Z","iopub.execute_input":"2022-11-14T06:00:10.044030Z","iopub.status.idle":"2022-11-14T07:54:46.628478Z","shell.execute_reply.started":"2022-11-14T06:00:10.043984Z","shell.execute_reply":"2022-11-14T07:54:46.626323Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(8, 5))\nsns.set_style(style=\"whitegrid\")\nsns.lineplot(x=range(1, len(total_train_loss)+1), y=total_train_loss, label=\"Train Loss\")\nsns.lineplot(x=range(1, len(total_train_loss)+1), y=total_valid_loss, label=\"Valid Loss\")\nplt.xlabel(\"Epochs\")\nplt.ylabel(\"Loss\")\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-11-14T07:54:46.629992Z","iopub.execute_input":"2022-11-14T07:54:46.630448Z","iopub.status.idle":"2022-11-14T07:54:46.917654Z","shell.execute_reply.started":"2022-11-14T07:54:46.630412Z","shell.execute_reply":"2022-11-14T07:54:46.916740Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# import os\n\n# import numpy as np\n# import pandas as pd\n# import seaborn as sns\n# from matplotlib import pyplot as plt\n# from PIL import Image\n# import cv2 as cv\n\n# import albumentations as A\n# from albumentations.pytorch.transforms import ToTensorV2\n\n# import torch\n# from torch.utils.data import Dataset\n\n# import torchvision\n# from torchvision.models.detection.faster_rcnn import FastRCNNPredictor\n# from torchvision.models.detection import FasterRCNN\n# from torchvision.models.detection.rpn import AnchorGenerator\n\n# WEIGHTS_FILE = \"fasterrcnn_resnet50_fpn-e10.bin\"","metadata":{"execution":{"iopub.status.busy":"2022-11-14T07:54:46.919289Z","iopub.execute_input":"2022-11-14T07:54:46.919673Z","iopub.status.idle":"2022-11-14T07:54:46.924333Z","shell.execute_reply.started":"2022-11-14T07:54:46.919631Z","shell.execute_reply":"2022-11-14T07:54:46.923416Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')\n\n# # create a Faster R-CNN model without pre-trained\n# model = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=False, pretrained_backbone=False)\n\n# num_classes = 2 # wheat or not(background)\n\n# # get number of input features for the classifier\n# in_features = model.roi_heads.box_predictor.cls_score.in_features\n\n# # replace the pre-trained model's head with a new one\n# model.roi_heads.box_predictor = FastRCNNPredictor(in_features, num_classes)\n\n# # load the trained weights\n# model.load_state_dict(torch.load(WEIGHTS_FILE, map_location=device))\n# model.eval()\n\n# # move model to the right device\n# _ = model.to(device)","metadata":{"execution":{"iopub.status.busy":"2022-11-14T07:54:46.929342Z","iopub.execute_input":"2022-11-14T07:54:46.929985Z","iopub.status.idle":"2022-11-14T07:54:46.935064Z","shell.execute_reply.started":"2022-11-14T07:54:46.929958Z","shell.execute_reply":"2022-11-14T07:54:46.933760Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# score_threshold = 0.7","metadata":{"execution":{"iopub.status.busy":"2022-11-14T07:54:46.936460Z","iopub.execute_input":"2022-11-14T07:54:46.936917Z","iopub.status.idle":"2022-11-14T07:54:46.944523Z","shell.execute_reply.started":"2022-11-14T07:54:46.936884Z","shell.execute_reply":"2022-11-14T07:54:46.943516Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# images,targets = next(iter(valid_loader))\n\n# for idx, (image, df_pred) in enumerate(iter_test):  # iterate through all test set images\n    \n#     image = image.astype(np.float32) / 255.0\n#     image = ToTensorV2()(image=image)['image']\n#     images = image.unsqueeze(0)\n    \n#     model.eval()\n    \n#     # Get predictions\n#     with torch.no_grad():\n#         outputs = model(images.to(device))[0]\n    \n#     # Move predictions to cpu and numpy\n#     boxes = outputs['boxes'].data.cpu().numpy()\n#     scores = outputs['scores'].data.cpu().numpy()\n    \n#     # Filter predictions with low score\n#     boxes = boxes[scores >= score_threshold].astype(np.int32)\n#     scores = scores[scores >= score_threshold]\n    \n#     # Go back from x_min, y_min, x_max, y_max to x_min, y_min, w, h\n#     boxes[:, 2] = boxes[:, 2] - boxes[:, 0]\n#     boxes[:, 3] = boxes[:, 3] - boxes[:, 1]\n    \n#     predictions = []\n    \n#     for j in zip(scores, boxes):\n#         predictions.append(\"{0:.2f} {1} {2} {3} {4}\".format(j[0], j[1][0], j[1][1], j[1][2], j[1][3]))\n    \n#     df_pred['annotations'] = ' '.join(predictions)\n#     env.predict(df_pred)","metadata":{"execution":{"iopub.status.busy":"2022-11-14T07:54:46.945785Z","iopub.execute_input":"2022-11-14T07:54:46.946226Z","iopub.status.idle":"2022-11-14T07:54:46.954935Z","shell.execute_reply.started":"2022-11-14T07:54:46.946189Z","shell.execute_reply":"2022-11-14T07:54:46.953884Z"},"trusted":true},"execution_count":null,"outputs":[]}]}