{"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":"## Ref\n* https://www.kaggle.com/steamedsheep/yolov5-is-all-you-need\n* https://www.kaggle.com/parapapapam/yolox-inference-tracking-on-cots-lb-0-539\n* https://www.kaggle.com/awsaf49/great-barrier-reef-yolov5-infer\n* https://www.kaggle.com/remekkinas/sahi-slicing-aided-hyper-inference-yv5-and-yx","metadata":{"execution":{"iopub.status.busy":"2022-01-28T23:48:48.560053Z","iopub.execute_input":"2022-01-28T23:48:48.560337Z","iopub.status.idle":"2022-01-28T23:48:48.591112Z","shell.execute_reply.started":"2022-01-28T23:48:48.560254Z","shell.execute_reply":"2022-01-28T23:48:48.589513Z"}}},{"cell_type":"markdown","source":"# Install Module","metadata":{}},{"cell_type":"code","source":"!mkdir -p /root/.config/Ultralytics\n!cp /kaggle/input/yolov5-font/Arial.ttf /root/.config/Ultralytics/","metadata":{"execution":{"iopub.status.busy":"2022-02-13T06:30:26.580666Z","iopub.execute_input":"2022-02-13T06:30:26.58176Z","iopub.status.idle":"2022-02-13T06:30:27.968792Z","shell.execute_reply.started":"2022-02-13T06:30:26.581628Z","shell.execute_reply":"2022-02-13T06:30:27.967826Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%cd /kaggle/input/sahihub/s-lib\n!pip install ./fire-0.4.0/fire-0.4.0.tar -f ./ --no-index\n!pip install terminaltables-3.1.10-py2.py3-none-any.whl -f ./ --no-index\n!pip install sahi-0.8.22-py3-none-any.whl -f ./ --no-index\n!pip install thop-0.0.31.post2005241907-py3-none-any.whl -f ./ --no-index\n!pip install yolov5-6.0.6-py36.py37.py38-none-any.whl -f ./ --no-index\n!pip install yolo5-0.0.1-py36.py37.py38-none-any.whl -f ./ --no-index","metadata":{"execution":{"iopub.status.busy":"2022-02-13T06:30:27.970681Z","iopub.execute_input":"2022-02-13T06:30:27.970948Z","iopub.status.idle":"2022-02-13T06:31:15.530761Z","shell.execute_reply.started":"2022-02-13T06:30:27.97092Z","shell.execute_reply":"2022-02-13T06:31:15.529921Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%cd /kaggle/input/norfair031py3/\n!pip install commonmark-0.9.1-py2.py3-none-any.whl -f ./ --no-index\n!pip install rich-9.13.0-py3-none-any.whl\n\n!mkdir /kaggle/working/tmp\n!cp -r /kaggle/input/norfair031py3/filterpy-1.4.5/filterpy-1.4.5/ /kaggle/working/tmp/\n%cd /kaggle/working/tmp/filterpy-1.4.5/\n!pip install .\n!rm -rf /kaggle/working/tmp\n\n# norfair\n%cd /kaggle/input/norfair031py3/\n!pip install norfair-0.3.1-py3-none-any.whl -f ./ --no-index","metadata":{"execution":{"iopub.status.busy":"2022-02-13T06:31:15.532263Z","iopub.execute_input":"2022-02-13T06:31:15.532521Z","iopub.status.idle":"2022-02-13T06:32:30.057998Z","shell.execute_reply.started":"2022-02-13T06:31:15.532482Z","shell.execute_reply":"2022-02-13T06:32:30.057148Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%cd /kaggle/working/","metadata":{"execution":{"iopub.status.busy":"2022-02-13T06:32:30.061382Z","iopub.execute_input":"2022-02-13T06:32:30.062246Z","iopub.status.idle":"2022-02-13T06:32:30.06915Z","shell.execute_reply.started":"2022-02-13T06:32:30.062188Z","shell.execute_reply":"2022-02-13T06:32:30.068286Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Import Modules","metadata":{}},{"cell_type":"code","source":"import numpy as np\nfrom tqdm.notebook import tqdm\ntqdm.pandas()\nimport pandas as pd\nimport os\nimport cv2\nimport matplotlib.pyplot as plt\nimport glob\nimport shutil\nimport sys\nsys.path.append('../input/tensorflow-great-barrier-reef')\nimport torch\nfrom PIL import Image as Img\nimport ast\nimport albumentations as albu\nfrom norfair import Detection, Tracker\nfrom IPython.display import display\nCUSTOM_YOLO5_CLASS = True\n\nimport warnings\nwarnings.filterwarnings(\"ignore\")\n\n","metadata":{"execution":{"iopub.status.busy":"2022-02-13T06:32:30.070883Z","iopub.execute_input":"2022-02-13T06:32:30.071478Z","iopub.status.idle":"2022-02-13T06:32:33.555922Z","shell.execute_reply.started":"2022-02-13T06:32:30.071396Z","shell.execute_reply":"2022-02-13T06:32:33.555163Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"DATASET_PATH = '/kaggle/input/tensorflow-great-barrier-reef/train_images/'\nCKPT_PATH = '../input/yolov5s6/f2_sub2.pt'\n\n#CUSTOM_YOLO5_CLASS const (we can execute using standard SAHI predict or custom one implemented in this notebook). \nCUSTOM_YOLO5_CLASS = True","metadata":{"execution":{"iopub.status.busy":"2022-02-13T06:32:33.55716Z","iopub.execute_input":"2022-02-13T06:32:33.558169Z","iopub.status.idle":"2022-02-13T06:32:33.563481Z","shell.execute_reply.started":"2022-02-13T06:32:33.55813Z","shell.execute_reply":"2022-02-13T06:32:33.562776Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from IPython.core.magic import (register_line_cell_magic)","metadata":{"execution":{"iopub.status.busy":"2022-02-13T06:32:33.564763Z","iopub.execute_input":"2022-02-13T06:32:33.565255Z","iopub.status.idle":"2022-02-13T06:32:33.575647Z","shell.execute_reply.started":"2022-02-13T06:32:33.565219Z","shell.execute_reply":"2022-02-13T06:32:33.574848Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"@register_line_cell_magic\ndef custom_yolo5(line, cell=None):\n    if eval(line):\n        print(\"Cell skipped - not executed\")\n        return\n    get_ipython().ex(cell)","metadata":{"execution":{"iopub.status.busy":"2022-02-13T06:32:33.578196Z","iopub.execute_input":"2022-02-13T06:32:33.579098Z","iopub.status.idle":"2022-02-13T06:32:33.586506Z","shell.execute_reply.started":"2022-02-13T06:32:33.579Z","shell.execute_reply":"2022-02-13T06:32:33.585743Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sahi.model import Yolov5DetectionModel\nfrom sahi.utils.cv import read_image\nfrom sahi.predict import get_prediction, get_sliced_prediction, predict\nfrom IPython.display import Image\nfrom sahi.utils.yolov5 import (\n    download_yolov5s6_model,\n)","metadata":{"execution":{"iopub.status.busy":"2022-02-13T06:32:33.587767Z","iopub.execute_input":"2022-02-13T06:32:33.58858Z","iopub.status.idle":"2022-02-13T06:32:33.64559Z","shell.execute_reply.started":"2022-02-13T06:32:33.588531Z","shell.execute_reply":"2022-02-13T06:32:33.644924Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Helpers","metadata":{}},{"cell_type":"code","source":"def voc2yolo(bboxes, image_height=720, image_width=1280):\n    \"\"\"\n    voc  => [x1, y1, x2, y1]\n    yolo => [xmid, ymid, w, h] (normalized)\n    \"\"\"\n    \n    bboxes = bboxes.copy().astype(float) # otherwise all value will be 0 as voc_pascal dtype is np.int\n    \n    bboxes[..., [0, 2]] = bboxes[..., [0, 2]]/ image_width\n    bboxes[..., [1, 3]] = bboxes[..., [1, 3]]/ image_height\n    \n    w = bboxes[..., 2] - bboxes[..., 0]\n    h = bboxes[..., 3] - bboxes[..., 1]\n    \n    bboxes[..., 0] = bboxes[..., 0] + w/2\n    bboxes[..., 1] = bboxes[..., 1] + h/2\n    bboxes[..., 2] = w\n    bboxes[..., 3] = h\n    \n    return bboxes\n\ndef yolo2voc(bboxes, image_height=720, image_width=1280):\n    \"\"\"\n    yolo => [xmid, ymid, w, h] (normalized)\n    voc  => [x1, y1, x2, y1]\n    \n    \"\"\" \n    bboxes = bboxes.copy().astype(float) # otherwise all value will be 0 as voc_pascal dtype is np.int\n    \n    bboxes[..., [0, 2]] = bboxes[..., [0, 2]]* image_width\n    bboxes[..., [1, 3]] = bboxes[..., [1, 3]]* image_height\n    \n    bboxes[..., [0, 1]] = bboxes[..., [0, 1]] - bboxes[..., [2, 3]]/2\n    bboxes[..., [2, 3]] = bboxes[..., [0, 1]] + bboxes[..., [2, 3]]\n    \n    return bboxes\n\ndef coco2yolo(bboxes, image_height=720, image_width=1280):\n    \"\"\"\n    coco => [xmin, ymin, w, h]\n    yolo => [xmid, ymid, w, h] (normalized)\n    \"\"\"\n    \n    bboxes = bboxes.copy().astype(float) # otherwise all value will be 0 as voc_pascal dtype is np.int\n    \n    # normolizinig\n    bboxes[..., [0, 2]]= bboxes[..., [0, 2]]/ image_width\n    bboxes[..., [1, 3]]= bboxes[..., [1, 3]]/ image_height\n    \n    # converstion (xmin, ymin) => (xmid, ymid)\n    bboxes[..., [0, 1]] = bboxes[..., [0, 1]] + bboxes[..., [2, 3]]/2\n    \n    return bboxes\n\ndef yolo2coco(bboxes, image_height=720, image_width=1280):\n    \"\"\"\n    yolo => [xmid, ymid, w, h] (normalized)\n    coco => [xmin, ymin, w, h]\n    \n    \"\"\" \n    bboxes = bboxes.copy().astype(float) # otherwise all value will be 0 as voc_pascal dtype is np.int\n    \n    # denormalizing\n    bboxes[..., [0, 2]]= bboxes[..., [0, 2]]* image_width\n    bboxes[..., [1, 3]]= bboxes[..., [1, 3]]* image_height\n    \n    # converstion (xmid, ymid) => (xmin, ymin) \n    bboxes[..., [0, 1]] = bboxes[..., [0, 1]] - bboxes[..., [2, 3]]/2\n    \n    return bboxes\n\ndef voc2coco(bboxes, image_height=720, image_width=1280):\n    bboxes  = voc2yolo(bboxes, image_height, image_width)\n    bboxes  = yolo2coco(bboxes, image_height, image_width)\n    return bboxes\n\ndef load_image(image_path):\n    return cv2.cvtColor(cv2.imread(image_path), cv2.COLOR_BGR2RGB)\n\n\ndef plot_one_box(x, img, color=None, label=None, line_thickness=None):\n    # Plots one bounding box on image img\n    tl = line_thickness or round(0.002 * (img.shape[0] + img.shape[1]) / 2) + 1  # line/font thickness\n    color = color or [random.randint(0, 255) for _ in range(3)]\n    c1, c2 = (int(x[0]), int(x[1])), (int(x[2]), int(x[3]))\n    cv2.rectangle(img, c1, c2, color, thickness=tl, lineType=cv2.LINE_AA)\n    if label:\n        tf = max(tl - 1, 1)  # font thickness\n        t_size = cv2.getTextSize(label, 0, fontScale=tl / 3, thickness=tf)[0]\n        c2 = c1[0] + t_size[0], c1[1] - t_size[1] - 3\n        cv2.rectangle(img, c1, c2, color, -1, cv2.LINE_AA)  # filled\n        cv2.putText(img, label, (c1[0], c1[1] - 2), 0, tl / 3, [225, 255, 255], thickness=tf, lineType=cv2.LINE_AA)\n\ndef draw_bboxes(img, bboxes, classes, class_ids, colors = None, show_classes = None, bbox_format = 'yolo', class_name = False, line_thickness = 2):  \n     \n    image = img.copy()\n    show_classes = classes if show_classes is None else show_classes\n    colors = (0, 255 ,0) if colors is None else colors\n    \n    if bbox_format == 'yolo':\n        \n        for idx in range(len(bboxes)):  \n            \n            bbox  = bboxes[idx]\n            cls   = classes[idx]\n            cls_id = class_ids[idx]\n            color = colors[cls_id] if type(colors) is list else colors\n            \n            if cls in show_classes:\n            \n                x1 = round(float(bbox[0])*image.shape[1])\n                y1 = round(float(bbox[1])*image.shape[0])\n                w  = round(float(bbox[2])*image.shape[1]/2) #w/2 \n                h  = round(float(bbox[3])*image.shape[0]/2)\n\n                voc_bbox = (x1-w, y1-h, x1+w, y1+h)\n                plot_one_box(voc_bbox, \n                             image,\n                             color = color,\n                             label = cls if class_name else str(get_label(cls)),\n                             line_thickness = line_thickness)\n            \n    elif bbox_format == 'coco':\n        \n        for idx in range(len(bboxes)):  \n            \n            bbox  = bboxes[idx]\n            cls   = classes[idx]\n            cls_id = class_ids[idx]\n            color = colors[cls_id] if type(colors) is list else colors\n            \n            if cls in show_classes:            \n                x1 = int(round(bbox[0]))\n                y1 = int(round(bbox[1]))\n                w  = int(round(bbox[2]))\n                h  = int(round(bbox[3]))\n\n                voc_bbox = (x1, y1, x1+w, y1+h)\n                plot_one_box(voc_bbox, \n                             image,\n                             color = color,\n                             label = cls if class_name else str(cls_id),\n                             line_thickness = line_thickness)\n\n    elif bbox_format == 'voc_pascal':\n        \n        for idx in range(len(bboxes)):  \n            \n            bbox  = bboxes[idx]\n            cls   = classes[idx]\n            cls_id = class_ids[idx]\n            color = colors[cls_id] if type(colors) is list else colors\n            \n            if cls in show_classes: \n                x1 = int(round(bbox[0]))\n                y1 = int(round(bbox[1]))\n                x2 = int(round(bbox[2]))\n                y2 = int(round(bbox[3]))\n                voc_bbox = (x1, y1, x2, y2)\n                plot_one_box(voc_bbox, \n                             image,\n                             color = color,\n                             label = cls if class_name else str(cls_id),\n                             line_thickness = line_thickness)\n    else:\n        raise ValueError('wrong bbox format')\n\n    return image\n\ndef get_bbox(annots):\n    bboxes = [list(annot.values()) for annot in annots]\n    return bboxes\n\ndef get_imgsize(row):\n    row['width'], row['height'] = imagesize.get(row['image_path'])\n    return row","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-02-13T06:32:33.648635Z","iopub.execute_input":"2022-02-13T06:32:33.648829Z","iopub.status.idle":"2022-02-13T06:32:33.685593Z","shell.execute_reply.started":"2022-02-13T06:32:33.648805Z","shell.execute_reply":"2022-02-13T06:32:33.684886Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def show_img(img, bboxes, bbox_format='yolo', bbox_colors = None):\n    names  = ['starfish']*len(bboxes)\n    labels = [0]*len(bboxes)\n    img    = draw_bboxes(img = img,\n                           bboxes = bboxes,\n                           classes = names,\n                           class_ids = labels,\n                           class_name = True,\n                           colors = colors if bbox_colors is None else bbox_colors,\n                           bbox_format = bbox_format,\n                           line_thickness = 2)\n    img = Img.fromarray(img).resize((1280, 720))\n    return img","metadata":{"execution":{"iopub.status.busy":"2022-02-13T06:32:33.686809Z","iopub.execute_input":"2022-02-13T06:32:33.68754Z","iopub.status.idle":"2022-02-13T06:32:33.697487Z","shell.execute_reply.started":"2022-02-13T06:32:33.687507Z","shell.execute_reply":"2022-02-13T06:32:33.696778Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# SAHI","metadata":{}},{"cell_type":"code","source":"from sahi.prediction import ObjectPrediction\nfrom sahi.model import DetectionModel\nfrom typing import Dict, List, Optional, Union\nfrom sahi.utils.compatibility import fix_full_shape_list, fix_shift_amount_list","metadata":{"execution":{"iopub.status.busy":"2022-02-13T06:32:33.699727Z","iopub.execute_input":"2022-02-13T06:32:33.700513Z","iopub.status.idle":"2022-02-13T06:32:33.70652Z","shell.execute_reply.started":"2022-02-13T06:32:33.700476Z","shell.execute_reply":"2022-02-13T06:32:33.705858Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class COTSYolov5DetectionModel(DetectionModel):\n\n    \n    def load_model(self):\n        model = torch.hub.load('/kaggle/input/yolov5-lib-ds', \n                               'custom', \n                               path=self.model_path,\n                               source='local',\n                               force_reload=True)\n        \n        model.conf = self.confidence_threshold\n        self.model = model\n        \n        if not self.category_mapping:\n            category_mapping = {str(ind): category_name for ind, category_name in enumerate(self.category_names)}\n            self.category_mapping = category_mapping\n\n    def perform_inference(self, image: np.ndarray, image_size: int = None):\n        if image_size is not None:\n            warnings.warn(\"Set 'image_size' at DetectionModel init.\", DeprecationWarning)\n            prediction_result = self.model(image, size=image_size, augment=True)\n            if debug_mode:\n                display(Img.fromarray(image).resize((320, 200)))\n        elif self.image_size is not None:\n            prediction_result = self.model(image, size=self.image_size, augment=True)\n        else:\n            prediction_result = self.model(image)\n\n        self._original_predictions = prediction_result\n\n    @property\n    def num_categories(self):\n        \"\"\"\n        Returns number of categories\n        \"\"\"\n        return len(self.model.names)\n\n    @property\n    def has_mask(self):\n        \"\"\"\n        Returns if model output contains segmentation mask\n        \"\"\"\n        has_mask = self.model.with_mask\n        return has_mask\n\n    @property\n    def category_names(self):\n        return self.model.names\n\n    def _create_object_prediction_list_from_original_predictions(\n        self,\n        shift_amount_list: Optional[List[List[int]]] = [[0, 0]],\n        full_shape_list: Optional[List[List[int]]] = None,):\n\n        original_predictions = self._original_predictions\n        shift_amount_list = fix_shift_amount_list(shift_amount_list)\n        full_shape_list = fix_full_shape_list(full_shape_list)\n\n        # handle all predictions\n        object_prediction_list_per_image = []\n        for image_ind, image_predictions_in_xyxy_format in enumerate(original_predictions.xyxy):\n            shift_amount = shift_amount_list[image_ind]\n            full_shape = None if full_shape_list is None else full_shape_list[image_ind]\n            object_prediction_list = []\n\n            # process predictions\n            for prediction in image_predictions_in_xyxy_format.cpu().detach().numpy():\n                x1 = int(prediction[0])\n                y1 = int(prediction[1])\n                x2 = int(prediction[2])\n                y2 = int(prediction[3])\n                bbox = [x1, y1, x2, y2]\n                score = prediction[4]\n                category_id = int(prediction[5])\n                category_name = self.category_mapping[str(category_id)]\n\n                # ignore invalid predictions\n                if bbox[0] > bbox[2] or bbox[1] > bbox[3] or bbox[0] < 0 or bbox[1] < 0 or bbox[2] < 0 or bbox[3] < 0:\n                    logger.warning(f\"ignoring invalid prediction with bbox: {bbox}\")\n                    continue\n                if full_shape is not None and (\n                    bbox[1] > full_shape[0]\n                    or bbox[3] > full_shape[0]\n                    or bbox[0] > full_shape[1]\n                    or bbox[2] > full_shape[1]\n                ):\n                    logger.warning(f\"ignoring invalid prediction with bbox: {bbox}\")\n                    continue\n\n                object_prediction = ObjectPrediction(\n                    bbox=bbox,\n                    category_id=category_id,\n                    score=score,\n                    bool_mask=None,\n                    category_name=category_name,\n                    shift_amount=shift_amount,\n                    full_shape=full_shape,\n                )\n                object_prediction_list.append(object_prediction)\n            object_prediction_list_per_image.append(object_prediction_list)\n\n        self._object_prediction_list_per_image = object_prediction_list_per_image ","metadata":{"execution":{"iopub.status.busy":"2022-02-13T06:32:33.707911Z","iopub.execute_input":"2022-02-13T06:32:33.70868Z","iopub.status.idle":"2022-02-13T06:32:33.728534Z","shell.execute_reply.started":"2022-02-13T06:32:33.708645Z","shell.execute_reply":"2022-02-13T06:32:33.727875Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def predict(img, model, sw, sh, ohr, owr, pmt, img_size, verb):\n    result = get_sliced_prediction(img,\n                                   model,\n                                   slice_width = sw,\n                                   slice_height = sh,\n                                   overlap_height_ratio = ohr,\n                                   overlap_width_ratio = owr,\n                                   postprocess_match_threshold = pmt,\n                                   image_size = img_size,\n                                   verbose = verb,\n                                   perform_standard_pred = True)\n    \n    \n    bboxes = []\n    scores = []\n    result_len = result.to_coco_annotations()\n    for pred in result_len:\n        bboxes.append(pred['bbox'])\n        scores.append(pred['score'])\n    \n    return bboxes, scores ","metadata":{"execution":{"iopub.status.busy":"2022-02-13T06:32:33.7308Z","iopub.execute_input":"2022-02-13T06:32:33.732672Z","iopub.status.idle":"2022-02-13T06:32:33.740188Z","shell.execute_reply.started":"2022-02-13T06:32:33.732642Z","shell.execute_reply":"2022-02-13T06:32:33.739493Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"detection_model = COTSYolov5DetectionModel(\n   model_path = CKPT_PATH,\n   confidence_threshold = 0.45,\n   device=\"cuda\",\n)\n\ndetection_model.model.iou = 0.5","metadata":{"execution":{"iopub.status.busy":"2022-02-13T06:32:33.741327Z","iopub.execute_input":"2022-02-13T06:32:33.741823Z","iopub.status.idle":"2022-02-13T06:32:43.76997Z","shell.execute_reply.started":"2022-02-13T06:32:33.741787Z","shell.execute_reply":"2022-02-13T06:32:43.768968Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%custom_yolo5 $CUSTOM_YOLO5_CLASS\n\ndetection_model = Yolov5DetectionModel(\n   model_path = CKPT_PATH,\n   confidence_threshold = 0.25,\n   device=\"cuda\",\n)\n\ndetection_model.model.iou = 0.45","metadata":{"execution":{"iopub.status.busy":"2022-02-13T06:32:43.771819Z","iopub.execute_input":"2022-02-13T06:32:43.772132Z","iopub.status.idle":"2022-02-13T06:32:43.778468Z","shell.execute_reply.started":"2022-02-13T06:32:43.772075Z","shell.execute_reply":"2022-02-13T06:32:43.777527Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Tracking ","metadata":{}},{"cell_type":"code","source":"##############################################################\n#                      Tracking helpers                      #\n##############################################################\n\nimport numpy as np\nfrom norfair import Detection, Tracker\n\n# Helper to convert bbox in format [x_min, y_min, x_max, y_max, score] to norfair.Detection class\ndef to_norfair(detects, frame_id):\n    result = []\n    for x_min, y_min, x_max, y_max, score in detects:\n        xc, yc = (x_min + x_max) / 2, (y_min + y_max) / 2\n        w, h = x_max - x_min, y_max - y_min\n        result.append(Detection(points=np.array([xc, yc]), scores=np.array([score]), data=np.array([w, h, frame_id])))\n        \n    return result\n\n# Euclidean distance function to match detections on this frame with tracked_objects from previous frames\ndef euclidean_distance(detection, tracked_object):\n    return np.linalg.norm(detection.points - tracked_object.estimate)","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-02-13T06:32:43.780198Z","iopub.execute_input":"2022-02-13T06:32:43.780764Z","iopub.status.idle":"2022-02-13T06:32:43.7889Z","shell.execute_reply.started":"2022-02-13T06:32:43.780727Z","shell.execute_reply":"2022-02-13T06:32:43.788142Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def tracking_function(tracker, frame_id, bboxes, scores):\n    \n    detects = []\n    predictions = []\n    \n    if len(scores)>0:\n        for i in range(len(bboxes)):\n            box = bboxes[i]\n            score = scores[i]\n            x_min = int(box[0])\n            y_min = int(box[1])\n            bbox_width = int(box[2])\n            bbox_height = int(box[3])\n            detects.append([x_min, y_min, x_min+bbox_width, y_min+bbox_height, score])\n            predictions.append('{:.2f} {} {} {} {}'.format(score, x_min, y_min, bbox_width, bbox_height))\n#             print(predictions[:-1])\n    # Update tracks using detects from current frame\n    tracked_objects = tracker.update(detections=to_norfair(detects, frame_id))\n    for tobj in tracked_objects:\n        bbox_width, bbox_height, last_detected_frame_id = tobj.last_detection.data\n        if last_detected_frame_id == frame_id:  # Skip objects that were detected on current frame\n            continue\n        # Add objects that have no detections on current frame to predictions\n        xc, yc = tobj.estimate[0]\n        x_min, y_min = int(round(xc - bbox_width / 2)), int(round(yc - bbox_height / 2))\n        score = tobj.last_detection.scores[0]\n\n        predictions.append('{:.2f} {} {} {} {}'.format(score, x_min, y_min, bbox_width, bbox_height))\n        \n    return predictions","metadata":{"execution":{"iopub.status.busy":"2022-02-13T06:32:43.789805Z","iopub.execute_input":"2022-02-13T06:32:43.791237Z","iopub.status.idle":"2022-02-13T06:32:43.802663Z","shell.execute_reply.started":"2022-02-13T06:32:43.791198Z","shell.execute_reply":"2022-02-13T06:32:43.801949Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tracker = Tracker(\n    distance_function=euclidean_distance, \n    distance_threshold=30,\n    hit_inertia_min=3,\n    hit_inertia_max=6,\n    initialization_delay=1,\n)","metadata":{"execution":{"iopub.status.busy":"2022-02-13T06:32:43.804053Z","iopub.execute_input":"2022-02-13T06:32:43.80461Z","iopub.status.idle":"2022-02-13T06:32:43.814081Z","shell.execute_reply.started":"2022-02-13T06:32:43.804571Z","shell.execute_reply":"2022-02-13T06:32:43.813345Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ROOT_DIR  = '/kaggle/input/tensorflow-great-barrier-reef/'\ndef get_path(row):\n    row['image_path'] = f'{ROOT_DIR}/train_images/video_{row.video_id}/{row.video_frame}.jpg'\n    return row","metadata":{"execution":{"iopub.status.busy":"2022-02-13T06:32:43.815531Z","iopub.execute_input":"2022-02-13T06:32:43.816125Z","iopub.status.idle":"2022-02-13T06:32:43.821654Z","shell.execute_reply.started":"2022-02-13T06:32:43.816068Z","shell.execute_reply":"2022-02-13T06:32:43.820894Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Train Data\ndf = pd.read_csv('/kaggle/input/tensorflow-great-barrier-reef/train.csv')\ndf = df.progress_apply(get_path, axis=1)\ndf['annotations'] = df['annotations'].progress_apply(lambda x: ast.literal_eval(x))\ndf['num_bbox'] = df['annotations'].progress_apply(lambda x: len(x))\ndata = (df.num_bbox>0).value_counts()/len(df)*100\nimage_paths = df[df.num_bbox>1].sample(100).image_path.tolist()","metadata":{"execution":{"iopub.status.busy":"2022-02-13T06:32:43.822983Z","iopub.execute_input":"2022-02-13T06:32:43.823526Z","iopub.status.idle":"2022-02-13T06:33:00.221593Z","shell.execute_reply.started":"2022-02-13T06:32:43.82349Z","shell.execute_reply":"2022-02-13T06:33:00.22096Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# SAHI + Tracking","metadata":{}},{"cell_type":"code","source":"debug_mode = False\ndir = f'{DATASET_PATH}'\nimage_paths = df[df.num_bbox>1].sample(100).image_path.tolist()\nframe_id = 0\nfor idx, path in enumerate(image_paths):\n    im = cv2.imread(path)[...,::-1]\n    if debug_mode:\n        print(\"\\n>>>> DEBUG MODE - SHOW SLICES AND FULL FRAME <<<<\")\n    bboxes, scores = predict(im, detection_model, 768, 432, 0.2, 0.2, 0.45, 3200, 0) \n    predictions = tracking_function(tracker, frame_id, bboxes, scores)\n    \n    if frame_id < 7:\n        if len(predictions)>0:\n            box = [list(map(int,box.split(' ')[1:])) for box in predictions]\n        else:\n            box = []\n        print('\\n Tracking')\n        display(show_img(im, box, bbox_format='coco', bbox_colors =(0, 0 ,255)))\n\n    frame_id += 1   \n    print('\\n SAHI: ')\n    display(show_img(im, bboxes, bbox_format='coco', bbox_colors = (255, 0 ,0)))\n    print(\"******************************************************************\")\n    \n    if idx>5:\n        break\n    ","metadata":{"execution":{"iopub.status.busy":"2022-02-13T06:33:00.222724Z","iopub.execute_input":"2022-02-13T06:33:00.223048Z","iopub.status.idle":"2022-02-13T06:33:11.47599Z","shell.execute_reply.started":"2022-02-13T06:33:00.223009Z","shell.execute_reply":"2022-02-13T06:33:11.475325Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Submission","metadata":{}},{"cell_type":"code","source":"%cd /kaggle/working/\nimport greatbarrierreef\nenv = greatbarrierreef.make_env()# initialize the environment\niter_test = env.iter_test()      # an iterator which loops over the test set and sample submission","metadata":{"execution":{"iopub.status.busy":"2022-02-13T06:33:11.477135Z","iopub.execute_input":"2022-02-13T06:33:11.477661Z","iopub.status.idle":"2022-02-13T06:33:11.502625Z","shell.execute_reply.started":"2022-02-13T06:33:11.477618Z","shell.execute_reply":"2022-02-13T06:33:11.501798Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tracker = Tracker(\n    distance_function=euclidean_distance, \n    distance_threshold=30,\n    hit_inertia_min=3,\n    hit_inertia_max=6,\n    initialization_delay=1,\n)","metadata":{"execution":{"iopub.status.busy":"2022-02-13T06:33:11.50476Z","iopub.execute_input":"2022-02-13T06:33:11.505012Z","iopub.status.idle":"2022-02-13T06:33:11.515206Z","shell.execute_reply.started":"2022-02-13T06:33:11.50498Z","shell.execute_reply":"2022-02-13T06:33:11.51252Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"debug_mode = False\nframe_id =0\nfor (image_np, pred_df) in iter_test:\n    \n    bboxes, scores = predict(image_np, detection_model, 768, 432, 0.2, 0.2, 0.45, 3200, 0)\n    predictions = tracking_function(tracker, frame_id, bboxes, scores)\n    \n    prediction_str = ' '.join(predictions)\n    pred_df['annotations'] = prediction_str\n    env.predict(pred_df)\n    if frame_id < 3:\n        if len(predictions)>0:\n            box = [list(map(int,box.split(' ')[1:])) for box in predictions]\n        else:\n            box = []\n        #display(show_img(image_np, box, bbox_format='coco',bbox_colors =(0, 0 ,255)))\n    frame_id += 1","metadata":{"execution":{"iopub.status.busy":"2022-02-13T06:33:11.517334Z","iopub.execute_input":"2022-02-13T06:33:11.517972Z","iopub.status.idle":"2022-02-13T06:33:14.124547Z","shell.execute_reply.started":"2022-02-13T06:33:11.517937Z","shell.execute_reply":"2022-02-13T06:33:14.123759Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub_df = pd.read_csv('submission.csv')\nsub_df.head()","metadata":{"execution":{"iopub.status.busy":"2022-02-13T06:33:14.125931Z","iopub.execute_input":"2022-02-13T06:33:14.126378Z","iopub.status.idle":"2022-02-13T06:33:14.140776Z","shell.execute_reply.started":"2022-02-13T06:33:14.126337Z","shell.execute_reply":"2022-02-13T06:33:14.14001Z"},"trusted":true},"execution_count":null,"outputs":[]}]}