{"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":"VGIS MiniProject\n\n* Hyperparameter: Epoch 20\n* Batchsize: 32\n* Number of hidden layers: Model depht mulitiple 0.33\n* BatchNormalization: Yes\n* DataAugmentation: Yes\n\n","metadata":{}},{"cell_type":"code","source":"import warnings\nwarnings.filterwarnings(\"ignore\")\n\nimport ast\nimport os\nimport json\nimport pandas as pd\nimport torch\nimport importlib\nimport cv2 \n\nfrom shutil import copyfile\nfrom tqdm.notebook import tqdm\ntqdm.pandas()\nfrom sklearn.model_selection import GroupKFold\nfrom PIL import Image\nfrom string import Template\nfrom IPython.display import display\n\nTRAIN_PATH = '/kaggle/input/tensorflow-great-barrier-reef'","metadata":{"execution":{"iopub.status.busy":"2022-01-31T11:09:12.78609Z","iopub.execute_input":"2022-01-31T11:09:12.786388Z","iopub.status.idle":"2022-01-31T11:09:12.795662Z","shell.execute_reply.started":"2022-01-31T11:09:12.786359Z","shell.execute_reply":"2022-01-31T11:09:12.794609Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# check Torch and CUDA version\nprint(f\"Torch: {torch.__version__}\")\n!nvcc --version","metadata":{"execution":{"iopub.status.busy":"2022-01-31T11:09:12.797771Z","iopub.execute_input":"2022-01-31T11:09:12.798309Z","iopub.status.idle":"2022-01-31T11:09:13.72961Z","shell.execute_reply.started":"2022-01-31T11:09:12.798263Z","shell.execute_reply":"2022-01-31T11:09:13.728069Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 1. INSTALL YOLOX","metadata":{}},{"cell_type":"code","source":"!git clone https://github.com/Megvii-BaseDetection/YOLOX -q\n\n%cd YOLOX\n!pip install -U pip && pip install -r requirements.txt\n!pip install -v -e . ","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2022-01-31T11:09:13.731578Z","iopub.execute_input":"2022-01-31T11:09:13.736724Z","iopub.status.idle":"2022-01-31T11:10:14.760295Z","shell.execute_reply.started":"2022-01-31T11:09:13.736675Z","shell.execute_reply":"2022-01-31T11:10:14.759092Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install 'git+https://github.com/cocodataset/cocoapi.git#subdirectory=PythonAPI'","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2022-01-31T11:10:14.764578Z","iopub.execute_input":"2022-01-31T11:10:14.764936Z","iopub.status.idle":"2022-01-31T11:10:36.229731Z","shell.execute_reply.started":"2022-01-31T11:10:14.7649Z","shell.execute_reply":"2022-01-31T11:10:36.22847Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 2. PREPARE COTS DATASET FOR YOLOX\nThis section is taken from  notebook created by Awsaf [Great-Barrier-Reef: YOLOv5 train](https://www.kaggle.com/awsaf49/great-barrier-reef-yolov5-train)\n\n## A. PREPARE DATASET AND ANNOTATIONS","metadata":{}},{"cell_type":"code","source":"def get_bbox(annots):\n    bboxes = [list(annot.values()) for annot in annots]\n    return bboxes\n\ndef get_path(row):\n    row['image_path'] = f'{TRAIN_PATH}/train_images/video_{row.video_id}/{row.video_frame}.jpg'\n    return row","metadata":{"execution":{"iopub.status.busy":"2022-01-31T11:10:36.233768Z","iopub.execute_input":"2022-01-31T11:10:36.234287Z","iopub.status.idle":"2022-01-31T11:10:36.251191Z","shell.execute_reply.started":"2022-01-31T11:10:36.234236Z","shell.execute_reply":"2022-01-31T11:10:36.249833Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.read_csv(\"/kaggle/input/tensorflow-great-barrier-reef/train.csv\")\ndf.head(5)","metadata":{"execution":{"iopub.status.busy":"2022-01-31T11:10:36.254149Z","iopub.execute_input":"2022-01-31T11:10:36.257851Z","iopub.status.idle":"2022-01-31T11:10:36.329489Z","shell.execute_reply.started":"2022-01-31T11:10:36.257803Z","shell.execute_reply":"2022-01-31T11:10:36.32862Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Taken only annotated photos\ndf[\"num_bbox\"] = df['annotations'].apply(lambda x: str.count(x, 'x'))\ndf_train = df[df[\"num_bbox\"]>0]\n\n#Annotations \ndf_train['annotations'] = df_train['annotations'].progress_apply(lambda x: ast.literal_eval(x))\ndf_train['bboxes'] = df_train.annotations.progress_apply(get_bbox)\n\n#Images resolution\ndf_train[\"width\"] = 1280\ndf_train[\"height\"] = 720\n\n#Path of images\ndf_train = df_train.progress_apply(get_path, axis=1)","metadata":{"execution":{"iopub.status.busy":"2022-01-31T11:10:36.339093Z","iopub.execute_input":"2022-01-31T11:10:36.341826Z","iopub.status.idle":"2022-01-31T11:10:42.132867Z","shell.execute_reply.started":"2022-01-31T11:10:36.341767Z","shell.execute_reply":"2022-01-31T11:10:42.131781Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"kf = GroupKFold(n_splits = 5) \ndf_train = df_train.reset_index(drop=True)\ndf_train['fold'] = -1\nfor fold, (train_idx, val_idx) in enumerate(kf.split(df_train, y = df_train.video_id.tolist(), groups=df_train.sequence)):\n    df_train.loc[val_idx, 'fold'] = fold\n\ndf_train.head(5)","metadata":{"execution":{"iopub.status.busy":"2022-01-31T11:10:42.134953Z","iopub.execute_input":"2022-01-31T11:10:42.1358Z","iopub.status.idle":"2022-01-31T11:10:42.175353Z","shell.execute_reply.started":"2022-01-31T11:10:42.135736Z","shell.execute_reply":"2022-01-31T11:10:42.174242Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"HOME_DIR = '/kaggle/working/' \nDATASET_PATH = 'dataset/images'\n\n!mkdir {HOME_DIR}dataset\n!mkdir {HOME_DIR}{DATASET_PATH}\n!mkdir {HOME_DIR}{DATASET_PATH}/train2017\n!mkdir {HOME_DIR}{DATASET_PATH}/val2017\n!mkdir {HOME_DIR}{DATASET_PATH}/annotations","metadata":{"execution":{"iopub.status.busy":"2022-01-31T11:10:42.177679Z","iopub.execute_input":"2022-01-31T11:10:42.178288Z","iopub.status.idle":"2022-01-31T11:10:46.031837Z","shell.execute_reply.started":"2022-01-31T11:10:42.178231Z","shell.execute_reply":"2022-01-31T11:10:46.030708Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"SELECTED_FOLD = 4\n\nfor i in tqdm(range(len(df_train))):\n    row = df_train.loc[i]\n    if row.fold != SELECTED_FOLD:\n        copyfile(f'{row.image_path}', f'{HOME_DIR}{DATASET_PATH}/train2017/{row.image_id}.jpg')\n    else:\n        copyfile(f'{row.image_path}', f'{HOME_DIR}{DATASET_PATH}/val2017/{row.image_id}.jpg') ","metadata":{"execution":{"iopub.status.busy":"2022-01-31T11:10:46.037197Z","iopub.execute_input":"2022-01-31T11:10:46.038265Z","iopub.status.idle":"2022-01-31T11:11:44.216428Z","shell.execute_reply.started":"2022-01-31T11:10:46.038205Z","shell.execute_reply":"2022-01-31T11:11:44.215416Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(f'Number of training files: {len(os.listdir(f\"{HOME_DIR}{DATASET_PATH}/train2017/\"))}')\nprint(f'Number of validation files: {len(os.listdir(f\"{HOME_DIR}{DATASET_PATH}/val2017/\"))}')","metadata":{"execution":{"iopub.status.busy":"2022-01-31T11:11:44.218741Z","iopub.execute_input":"2022-01-31T11:11:44.219411Z","iopub.status.idle":"2022-01-31T11:11:44.231541Z","shell.execute_reply.started":"2022-01-31T11:11:44.21936Z","shell.execute_reply":"2022-01-31T11:11:44.230595Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## B. CREATE COCO ANNOTATION FILES","metadata":{}},{"cell_type":"code","source":"def save_annot_json(json_annotation, filename):\n    with open(filename, 'w') as f:\n        output_json = json.dumps(json_annotation)\n        f.write(output_json)","metadata":{"execution":{"iopub.status.busy":"2022-01-31T11:11:44.233261Z","iopub.execute_input":"2022-01-31T11:11:44.233634Z","iopub.status.idle":"2022-01-31T11:11:45.290218Z","shell.execute_reply.started":"2022-01-31T11:11:44.233587Z","shell.execute_reply":"2022-01-31T11:11:45.288809Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"annotion_id = 0","metadata":{"execution":{"iopub.status.busy":"2022-01-31T11:11:45.292295Z","iopub.execute_input":"2022-01-31T11:11:45.292702Z","iopub.status.idle":"2022-01-31T11:11:45.301383Z","shell.execute_reply.started":"2022-01-31T11:11:45.292655Z","shell.execute_reply":"2022-01-31T11:11:45.300247Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def dataset2coco(df, dest_path):\n    \n    global annotion_id\n    \n    annotations_json = {\n        \"info\": [],\n        \"licenses\": [],\n        \"categories\": [],\n        \"images\": [],\n        \"annotations\": []\n    }\n    \n    info = {\n        \"year\": \"2021\",\n        \"version\": \"1\",\n        \"description\": \"COTS dataset - COCO format\",\n        \"contributor\": \"\",\n        \"url\": \"https://kaggle.com\",\n        \"date_created\": \"2021-11-30T15:01:26+00:00\"\n    }\n    annotations_json[\"info\"].append(info)\n    \n    lic = {\n            \"id\": 1,\n            \"url\": \"\",\n            \"name\": \"Unknown\"\n        }\n    annotations_json[\"licenses\"].append(lic)\n\n    classes = {\"id\": 0, \"name\": \"starfish\", \"supercategory\": \"none\"}\n\n    annotations_json[\"categories\"].append(classes)\n\n    \n    for ann_row in df.itertuples():\n            \n        images = {\n            \"id\": ann_row[0],\n            \"license\": 1,\n            \"file_name\": ann_row.image_id + '.jpg',\n            \"height\": ann_row.height,\n            \"width\": ann_row.width,\n            \"date_captured\": \"2021-11-30T15:01:26+00:00\"\n        }\n        \n        annotations_json[\"images\"].append(images)\n        \n        bbox_list = ann_row.bboxes\n        \n        for bbox in bbox_list:\n            b_width = bbox[2]\n            b_height = bbox[3]\n            \n            # some boxes in COTS are outside the image height and width\n            if (bbox[0] + bbox[2] > 1280):\n                b_width = bbox[0] - 1280 \n            if (bbox[1] + bbox[3] > 720):\n                b_height = bbox[1] - 720 \n                \n            image_annotations = {\n                \"id\": annotion_id,\n                \"image_id\": ann_row[0],\n                \"category_id\": 0,\n                \"bbox\": [bbox[0], bbox[1], b_width, b_height],\n                \"area\": bbox[2] * bbox[3],\n                \"segmentation\": [],\n                \"iscrowd\": 0\n            }\n            \n            annotion_id += 1\n            annotations_json[\"annotations\"].append(image_annotations)\n        \n        \n    print(f\"Dataset COTS annotation to COCO json format completed! Files: {len(df)}\")\n    return annotations_json","metadata":{"execution":{"iopub.status.busy":"2022-01-31T11:11:45.303269Z","iopub.execute_input":"2022-01-31T11:11:45.303653Z","iopub.status.idle":"2022-01-31T11:11:45.32158Z","shell.execute_reply.started":"2022-01-31T11:11:45.303607Z","shell.execute_reply":"2022-01-31T11:11:45.320224Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Convert COTS dataset to JSON COCO\ntrain_annot_json = dataset2coco(df_train[df_train.fold != SELECTED_FOLD], f\"{HOME_DIR}{DATASET_PATH}/train2017/\")\nval_annot_json = dataset2coco(df_train[df_train.fold == SELECTED_FOLD], f\"{HOME_DIR}{DATASET_PATH}/val2017/\")\n\n# Save converted annotations\nsave_annot_json(train_annot_json, f\"{HOME_DIR}{DATASET_PATH}/annotations/train.json\")\nsave_annot_json(val_annot_json, f\"{HOME_DIR}{DATASET_PATH}/annotations/valid.json\")","metadata":{"execution":{"iopub.status.busy":"2022-01-31T11:11:45.323692Z","iopub.execute_input":"2022-01-31T11:11:45.324236Z","iopub.status.idle":"2022-01-31T11:11:45.452229Z","shell.execute_reply.started":"2022-01-31T11:11:45.324185Z","shell.execute_reply":"2022-01-31T11:11:45.451178Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 3. PREPARE CONFIGURATION FILE\n\nConfiguration files for Yolox:\n- [YOLOX-nano](https://github.com/Megvii-BaseDetection/YOLOX/blob/main/exps/default/nano.py)\n- [YOLOX-s](https://github.com/Megvii-BaseDetection/YOLOX/blob/main/exps/default/yolox_s.py)\n- [YOLOX-m](https://github.com/Megvii-BaseDetection/YOLOX/blob/main/exps/default/yolox_m.py)\n","metadata":{}},{"cell_type":"code","source":"# Choose model for your experiments NANO or YOLOX-S (you can adapt for other model type)\n\nNANO = False","metadata":{"execution":{"iopub.status.busy":"2022-01-31T11:11:45.453776Z","iopub.execute_input":"2022-01-31T11:11:45.454875Z","iopub.status.idle":"2022-01-31T11:11:45.459998Z","shell.execute_reply.started":"2022-01-31T11:11:45.454801Z","shell.execute_reply":"2022-01-31T11:11:45.458851Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 3A. YOLOX-S EXPERIMENT CONFIGURATION FILE\nTraining parameters could be set up in experiment config files. I created custom files for YOLOX-s and nano. You can create your own using files from oryginal github repo.","metadata":{}},{"cell_type":"markdown","source":"<div class=\"alert alert-warning\">\n<strong> For YOLOX_s I use input size 960x960 but you can change it for your experiments.</strong> \n</div>","metadata":{}},{"cell_type":"code","source":"config_file_template = \"\"\"\n\n#!/usr/bin/env python3\n# -*- coding:utf-8 -*-\n# Copyright (c) Megvii, Inc. and its affiliates.\n\nimport os\n\nfrom yolox.exp import Exp as MyExp\n\n\nclass Exp(MyExp):\n    def __init__(self):\n        super(Exp, self).__init__()\n        self.depth = 0.33\n        self.width = 0.50\n        self.exp_name = os.path.split(os.path.realpath(__file__))[1].split(\".\")[0]\n        \n        # Define yourself dataset path\n        self.data_dir = \"/kaggle/working/dataset/images\"\n        self.train_ann = \"train.json\"\n        self.val_ann = \"valid.json\"\n\n        self.num_classes = 1\n\n        self.max_epoch = $max_epoch\n        self.data_num_workers = 2\n        self.eval_interval = 1\n        \n        self.mosaic_prob = 1.0\n        self.mixup_prob = 1.0\n        self.hsv_prob = 1.0\n        self.flip_prob = 0.5\n        self.no_aug_epochs = 2\n        \n        self.input_size = (960, 960)\n        self.mosaic_scale = (0.5, 1.5)\n        self.random_size = (10, 20)\n        self.test_size = (960, 960)\n\"\"\"","metadata":{"execution":{"iopub.status.busy":"2022-01-31T11:11:45.462106Z","iopub.execute_input":"2022-01-31T11:11:45.462895Z","iopub.status.idle":"2022-01-31T11:11:45.47417Z","shell.execute_reply.started":"2022-01-31T11:11:45.462835Z","shell.execute_reply":"2022-01-31T11:11:45.472885Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 3B. YOLOX-NANO CONFIG FILE\n<div class=\"alert alert-warning\">\n<strong> For YOLOX_nano I use input size 460x460 but you can change it for your experiments.</strong> \n</div","metadata":{}},{"cell_type":"code","source":"if NANO:\n    config_file_template = '''\n\n#!/usr/bin/env python3\n# -*- coding:utf-8 -*-\n# Copyright (c) Megvii, Inc. and its affiliates.\n\nimport os\n\nimport torch.nn as nn\n\nfrom yolox.exp import Exp as MyExp\n\n\nclass Exp(MyExp):\n    def __init__(self):\n        super(Exp, self).__init__()\n        self.depth = 0.33 #changes the layers\n        self.width = 0.25\n        self.input_size = (416, 416)\n        self.mosaic_scale = (0.5, 1.5)\n        self.random_size = (10, 20)\n        self.test_size = (416, 416)\n        self.exp_name = os.path.split(\n            os.path.realpath(__file__))[1].split(\".\")[0]\n        self.enable_mixup = False\n\n        # Define yourself dataset path\n        self.data_dir = \"/kaggle/working/dataset/images\"\n        self.train_ann = \"train.json\"\n        self.val_ann = \"valid.json\"\n\n        self.num_classes = 1\n\n        self.max_epoch = $max_epoch\n        self.data_num_workers = 2\n        self.eval_interval = 1\n\n    def get_model(self, sublinear=False):\n        def init_yolo(M):\n            for m in M.modules():\n                if isinstance(m, nn.BatchNorm2d):\n                    m.eps = 1e-3\n                    m.momentum = 0.03\n\n        if \"model\" not in self.__dict__:\n            from yolox.models import YOLOX, YOLOPAFPN, YOLOXHead\n            in_channels = [256, 512, 1024]\n            # NANO model use depthwise = True, which is main difference.\n            backbone = YOLOPAFPN(self.depth,\n                                 self.width,\n                                 in_channels=in_channels,\n                                 depthwise=True)\n            head = YOLOXHead(self.num_classes,\n                             self.width,\n                             in_channels=in_channels,\n                             depthwise=True)\n            self.model = YOLOX(backbone, head)\n\n        self.model.apply(init_yolo)\n        self.model.head.initialize_biases(1e-2)\n        return self.model\n\n'''","metadata":{"execution":{"iopub.status.busy":"2022-01-31T11:11:45.476213Z","iopub.execute_input":"2022-01-31T11:11:45.476627Z","iopub.status.idle":"2022-01-31T11:11:45.487302Z","shell.execute_reply.started":"2022-01-31T11:11:45.476534Z","shell.execute_reply":"2022-01-31T11:11:45.48622Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"PIPELINE_CONFIG_PATH='cots_config.py'\n\npipeline = Template(config_file_template).substitute(max_epoch = 1)\n\nwith open(PIPELINE_CONFIG_PATH, 'w') as f:\n    f.write(pipeline)","metadata":{"execution":{"iopub.status.busy":"2022-01-31T11:11:45.489462Z","iopub.execute_input":"2022-01-31T11:11:45.489912Z","iopub.status.idle":"2022-01-31T11:11:45.501663Z","shell.execute_reply.started":"2022-01-31T11:11:45.489869Z","shell.execute_reply":"2022-01-31T11:11:45.500599Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# ./yolox/data/datasets/voc_classes.py\n\nvoc_cls = '''\nVOC_CLASSES = (\n  \"starfish\",\n)\n'''\nwith open('./yolox/data/datasets/voc_classes.py', 'w') as f:\n    f.write(voc_cls)\n\n# ./yolox/data/datasets/coco_classes.py\n\ncoco_cls = '''\nCOCO_CLASSES = (\n  \"starfish\",\n)\n'''\nwith open('./yolox/data/datasets/coco_classes.py', 'w') as f:\n    f.write(coco_cls)\n\n# check if everything is ok    \n!more ./yolox/data/datasets/coco_classes.py","metadata":{"execution":{"iopub.status.busy":"2022-01-31T11:11:45.505194Z","iopub.execute_input":"2022-01-31T11:11:45.505585Z","iopub.status.idle":"2022-01-31T11:11:46.254458Z","shell.execute_reply.started":"2022-01-31T11:11:45.505517Z","shell.execute_reply":"2022-01-31T11:11:46.253382Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"List of pretrained models:\n* YOLOX-s\n* YOLOX-m\n* YOLOX-nano for inference speed (!)\n* etc.","metadata":{}},{"cell_type":"code","source":"sh = 'wget https://github.com/Megvii-BaseDetection/storage/releases/download/0.0.1/yolox_s.pth'\nMODEL_FILE = 'yolox_s.pth'\n\nif NANO:\n    sh = '''\n    wget https://github.com/Megvii-BaseDetection/storage/releases/download/0.0.1/yolox_nano.pth\n    '''\n    MODEL_FILE = 'yolox_nano.pth'\n\nwith open('script.sh', 'w') as file:\n  file.write(sh)\n\n!bash script.sh","metadata":{"execution":{"iopub.status.busy":"2022-01-31T11:11:46.256852Z","iopub.execute_input":"2022-01-31T11:11:46.257488Z","iopub.status.idle":"2022-01-31T11:11:49.571472Z","shell.execute_reply.started":"2022-01-31T11:11:46.257442Z","shell.execute_reply":"2022-01-31T11:11:49.5704Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 5. TRAIN MODEL","metadata":{}},{"cell_type":"code","source":"!cp ./tools/train.py ./","metadata":{"execution":{"iopub.status.busy":"2022-01-31T11:11:49.573913Z","iopub.execute_input":"2022-01-31T11:11:49.574669Z","iopub.status.idle":"2022-01-31T11:11:50.333539Z","shell.execute_reply.started":"2022-01-31T11:11:49.574615Z","shell.execute_reply":"2022-01-31T11:11:50.332413Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!python train.py \\\n    -f cots_config.py \\\n    -d 1 \\\n    -b 32 \\\n    --fp16 \\\n    -o \\\n    -c {MODEL_FILE}   # Remember to chenge this line if you take different model eg. yolo_nano.pth, yolox_s.pth or yolox_m.pth","metadata":{"execution":{"iopub.status.busy":"2022-01-31T11:11:50.336048Z","iopub.execute_input":"2022-01-31T11:11:50.336848Z","iopub.status.idle":"2022-01-31T11:17:14.262341Z","shell.execute_reply.started":"2022-01-31T11:11:50.336768Z","shell.execute_reply":"2022-01-31T11:17:14.261287Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 6. RUN INFERENCE\n\n## 6A. INFERENCE USING YOLOX TOOL","metadata":{}},{"cell_type":"code","source":"# I have to fix demo.py file because it:\n# - raises error in Kaggle (cvWaitKey does not work) \n# - saves result files in time named directory eg. /2021_11_29_22_51_08/ which is difficult then to automatically show results\n\n%cp /kaggle/input/yolox-kaggle-fix-for-demo-inference/demo.py /kaggle/working/YOLOX/yolox/tools","metadata":{"execution":{"iopub.status.busy":"2022-01-31T11:17:14.264602Z","iopub.execute_input":"2022-01-31T11:17:14.264935Z","iopub.status.idle":"2022-01-31T11:17:15.057703Z","shell.execute_reply.started":"2022-01-31T11:17:14.264889Z","shell.execute_reply":"2022-01-31T11:17:15.056412Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"TEST_IMAGE_PATH = \"/kaggle/working/dataset/images/val2017/0-4614.jpg\"\nMODEL_PATH = \"./YOLOX_outputs/cots_config/best_ckpt.pth\"\n\n!python tools/demo.py image \\\n    -f cots_config.py \\\n    -c {MODEL_PATH} \\\n    --path {TEST_IMAGE_PATH} \\\n    --conf 0.1 \\\n    --nms 0.45 \\\n    --tsize 960 \\\n    --save_result \\\n    --device gpu","metadata":{"execution":{"iopub.status.busy":"2022-01-31T11:22:08.732777Z","iopub.execute_input":"2022-01-31T11:22:08.733134Z","iopub.status.idle":"2022-01-31T11:22:14.724017Z","shell.execute_reply.started":"2022-01-31T11:22:08.733103Z","shell.execute_reply":"2022-01-31T11:22:14.722802Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Imagepath = './YOLOX_outputs/cots_config/vis_res/'\nfolders = []\n# r=root, d=directories, f = files\nfor r, d, f in os.walk(Imagepath):\n    for folder in d:\n        folders.append(os.path.join(r, folder))\nfor f in folders:\n    print(f)\nprint(folders)\nunknownPath = str(f)+\"/0-4614.jpg\"\nOUTPUT_IMAGE_PATH = unknownPath\nImage.open(OUTPUT_IMAGE_PATH)","metadata":{"execution":{"iopub.status.busy":"2022-01-31T11:22:17.960828Z","iopub.execute_input":"2022-01-31T11:22:17.961112Z","iopub.status.idle":"2022-01-31T11:22:17.994874Z","shell.execute_reply.started":"2022-01-31T11:22:17.961081Z","shell.execute_reply":"2022-01-31T11:22:17.993453Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 6B. INFERENCE USING CUSTOM SCRIPT (IT WOULD BE USED FOR COTS INFERENCE PART)\n\n### 6B.1 SETUP MODEL","metadata":{}},{"cell_type":"code","source":"from yolox.utils import postprocess\nfrom yolox.data.data_augment import ValTransform\n\nCOCO_CLASSES = (\n  \"starfish\",\n)\n\n# get YOLOX experiment\ncurrent_exp = importlib.import_module('cots_config')\nexp = current_exp.Exp()\n\n# set inference parameters\ntest_size = (960, 960)\nnum_classes = 1\nconfthre = 0.1\nnmsthre = 0.45\n\n\n# get YOLOX model\nmodel = exp.get_model()\nmodel.cuda()\nmodel.eval()\n\n# get custom trained checkpoint\nckpt_file = \"./YOLOX_outputs/cots_config/best_ckpt.pth\"\nckpt = torch.load(ckpt_file, map_location=\"cpu\")\nmodel.load_state_dict(ckpt[\"model\"])","metadata":{"execution":{"iopub.status.busy":"2022-01-31T11:17:21.494556Z","iopub.status.idle":"2022-01-31T11:17:21.494957Z","shell.execute_reply.started":"2022-01-31T11:17:21.494752Z","shell.execute_reply":"2022-01-31T11:17:21.494788Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 6B.2 INFERENCE BBOXES","metadata":{}},{"cell_type":"code","source":"def yolox_inference(img, model, test_size): \n    bboxes = []\n    bbclasses = []\n    scores = []\n    \n    preproc = ValTransform(legacy = False)\n\n    tensor_img, _ = preproc(img, None, test_size)\n    tensor_img = torch.from_numpy(tensor_img).unsqueeze(0)\n    tensor_img = tensor_img.float()\n    tensor_img = tensor_img.cuda()\n\n    with torch.no_grad():\n        outputs = model(tensor_img)\n        outputs = postprocess(\n                    outputs, num_classes, confthre,\n                    nmsthre, class_agnostic=True\n                )\n\n    if outputs[0] is None:\n        return [], [], []\n    \n    outputs = outputs[0].cpu()\n    bboxes = outputs[:, 0:4]\n\n    bboxes /= min(test_size[0] / img.shape[0], test_size[1] / img.shape[1])\n    bbclasses = outputs[:, 6]\n    scores = outputs[:, 4] * outputs[:, 5]\n    \n    return bboxes, bbclasses, scores","metadata":{"execution":{"iopub.status.busy":"2022-01-31T11:17:21.496391Z","iopub.status.idle":"2022-01-31T11:17:21.496969Z","shell.execute_reply.started":"2022-01-31T11:17:21.496626Z","shell.execute_reply":"2022-01-31T11:17:21.496655Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 6B.3 DRAW RESULT","metadata":{}},{"cell_type":"code","source":"def draw_yolox_predictions(img, bboxes, scores, bbclasses, confthre, classes_dict):\n    for i in range(len(bboxes)):\n            box = bboxes[i]\n            cls_id = int(bbclasses[i])\n            score = scores[i]\n            if score < confthre:\n                continue\n            x0 = int(box[0])\n            y0 = int(box[1])\n            x1 = int(box[2])\n            y1 = int(box[3])\n\n            cv2.rectangle(img, (x0, y0), (x1, y1), (0, 255, 0), 2)\n            cv2.putText(img, '{}:{:.1f}%'.format(classes_dict[cls_id], score * 100), (x0, y0 - 3), cv2.FONT_HERSHEY_PLAIN, 0.8, (0,255,0), thickness = 1)\n    return img","metadata":{"execution":{"iopub.status.busy":"2022-01-31T11:17:21.498508Z","iopub.status.idle":"2022-01-31T11:17:21.499151Z","shell.execute_reply.started":"2022-01-31T11:17:21.498848Z","shell.execute_reply":"2022-01-31T11:17:21.498878Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 6B.4 ALL PUZZLES TOGETHER","metadata":{}},{"cell_type":"code","source":"TEST_IMAGE_PATH = \"/kaggle/working/dataset/images/val2017/0-4614.jpg\"\nimg = cv2.imread(TEST_IMAGE_PATH)\n\n# Get predictions\nbboxes, bbclasses, scores = yolox_inference(img, model, test_size)\n\n# Draw predictions\nout_image = draw_yolox_predictions(img, bboxes, scores, bbclasses, confthre, COCO_CLASSES)\n\n# Since we load image using OpenCV we have to convert it \nout_image = cv2.cvtColor(out_image, cv2.COLOR_BGR2RGB)\ndisplay(Image.fromarray(out_image))","metadata":{"execution":{"iopub.status.busy":"2022-01-31T11:17:21.501913Z","iopub.status.idle":"2022-01-31T11:17:21.502288Z","shell.execute_reply.started":"2022-01-31T11:17:21.502076Z","shell.execute_reply":"2022-01-31T11:17:21.502105Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<div class=\"alert alert-success\" role=\"alert\">\n    Find this notebook helpful? :) Please give me a vote ;) Thank you\n </div>","metadata":{}},{"cell_type":"markdown","source":"# 7. SUBMIT TO COTS COMPETITION AND EVALUATE","metadata":{}},{"cell_type":"code","source":"import greatbarrierreef\n\nenv = greatbarrierreef.make_env()   # initialize the environment\niter_test = env.iter_test()  ","metadata":{"execution":{"iopub.status.busy":"2022-01-31T11:17:21.504779Z","iopub.status.idle":"2022-01-31T11:17:21.505759Z","shell.execute_reply.started":"2022-01-31T11:17:21.50543Z","shell.execute_reply":"2022-01-31T11:17:21.505461Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission_dict = {\n    'id': [],\n    'prediction_string': [],\n}\n\nfor (image_np, sample_prediction_df) in iter_test:\n \n    bboxes, bbclasses, scores = yolox_inference(image_np, model, test_size)\n    \n    predictions = []\n    for i in range(len(bboxes)):\n        box = bboxes[i]\n        cls_id = int(bbclasses[i])\n        score = scores[i]\n        if score < confthre:\n            continue\n        x_min = int(box[0])\n        y_min = int(box[1])\n        x_max = int(box[2])\n        y_max = int(box[3])\n        \n        bbox_width = x_max - x_min\n        bbox_height = y_max - y_min\n        \n        predictions.append('{:.2f} {} {} {} {}'.format(score, x_min, y_min, bbox_width, bbox_height))\n    \n    prediction_str = ' '.join(predictions)\n    sample_prediction_df['annotations'] = prediction_str\n    env.predict(sample_prediction_df)\n\n    print('Prediction:', prediction_str)","metadata":{"execution":{"iopub.status.busy":"2022-01-31T11:17:21.507588Z","iopub.status.idle":"2022-01-31T11:17:21.508518Z","shell.execute_reply.started":"2022-01-31T11:17:21.508148Z","shell.execute_reply":"2022-01-31T11:17:21.508179Z"},"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-01-31T11:17:21.510322Z","iopub.status.idle":"2022-01-31T11:17:21.511393Z","shell.execute_reply.started":"2022-01-31T11:17:21.510974Z","shell.execute_reply":"2022-01-31T11:17:21.511009Z"},"trusted":true},"execution_count":null,"outputs":[]}]}