{"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":"!pip install ../input/detectron-05/whls/pycocotools-2.0.2/dist/pycocotools-2.0.2.tar --no-index --find-links ../input/detectron-05/whls &>/dev/null\n!pip install ../input/detectron-05/whls/fvcore-0.1.5.post20211019/fvcore-0.1.5.post20211019 --no-index --find-links ../input/detectron-05/whls &>/dev/null \n!pip install ../input/detectron-05/whls/antlr4-python3-runtime-4.8/antlr4-python3-runtime-4.8 --no-index --find-links ../input/detectron-05/whls &>/dev/null \n!pip install ../input/detectron-05/whls/detectron2-0.5/detectron2 --no-index --find-links ../input/detectron-05/whls &>/dev/null \n\n!pip install ../input/segmentation-models-pytorch/efficientnet_pytorch-0.6.3/efficientnet_pytorch-0.6.3/ --no-index --find-links ../input/segmentation-models-pytorch/  &>/dev/null \n!pip install ../input/segmentation-models-pytorch/pretrainedmodels-0.7.4/pretrainedmodels-0.7.4/ --no-index --find-links ../input/segmentation-models-pytorch/  &>/dev/null \n!pip install ../input/segmentation-models-pytorch/segmentation_models_pytorch-0.2.1-py3-none-any.whl --no-index --find-links ../input/segmentation-models-pytorch/  &>/dev/null ","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-12-28T23:45:31.530768Z","iopub.execute_input":"2021-12-28T23:45:31.531067Z","iopub.status.idle":"2021-12-28T23:49:17.663701Z","shell.execute_reply.started":"2021-12-28T23:45:31.530985Z","shell.execute_reply":"2021-12-28T23:49:17.662803Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import gc\nimport os\nimport cv2\nimport glob\nimport sys\nimport torch\nfrom tqdm.notebook import tqdm\nfrom PIL import Image\nimport cv2\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport numpy as np\nfrom fastcore.all import *\nimport pycocotools.mask as mask_util\nfrom detectron2 import model_zoo\nfrom detectron2.engine import DefaultPredictor\nfrom detectron2.config import get_cfg\nfrom detectron2.utils.visualizer import Visualizer, ColorMode\nfrom detectron2.data.datasets import register_coco_instances\nfrom detectron2.engine import BestCheckpointer\nfrom detectron2.checkpoint import DetectionCheckpointer\nfrom detectron2.data import MetadataCatalog, DatasetCatalog\nfrom detectron2.modeling.meta_arch.rcnn import GeneralizedRCNN\nfrom detectron2.layers import ShapeSpec\nfrom detectron2.modeling import build_proposal_generator, build_roi_heads\nimport detectron2.data.transforms as T\nimport segmentation_models_pytorch as smp\nfrom torchvision.models.detection.backbone_utils import FeaturePyramidNetwork, LastLevelMaxPool\nimport torch\nfrom torch import nn\nfrom torchvision.ops import misc as misc_nn_ops\nimport torchvision\nfrom detectron2.layers.batch_norm import FrozenBatchNorm2d\n\nsys.path.append('../input/resnest/d2')\nsys.path.append('../input/resnest/detectron2_resnest')\nsys.path.append('../input/detectron-swin/swin')\nsys.path.append('../input/timm-pytorch-image-models/pytorch-image-models-master')","metadata":{"execution":{"iopub.status.busy":"2021-12-28T23:49:17.666058Z","iopub.execute_input":"2021-12-28T23:49:17.66635Z","iopub.status.idle":"2021-12-28T23:49:23.987599Z","shell.execute_reply.started":"2021-12-28T23:49:17.666312Z","shell.execute_reply":"2021-12-28T23:49:23.986778Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from d2 import add_resnest_config\nfrom detectron2_resnest.modeling import build_model\nfrom swint import add_swinl_384_config","metadata":{"execution":{"iopub.status.busy":"2021-12-28T23:49:23.988988Z","iopub.execute_input":"2021-12-28T23:49:23.989268Z","iopub.status.idle":"2021-12-28T23:49:24.393809Z","shell.execute_reply.started":"2021-12-28T23:49:23.989228Z","shell.execute_reply":"2021-12-28T23:49:24.39309Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dataDir=Path('../input/sartorius-cell-instance-segmentation')\n\nregister_coco_instances('sartorius_val_fold_1',{},'../input/5-fold-x-152/5_fold_split_sartorius_coco_dataset/annotations_val_fold_1.json', dataDir)\nregister_coco_instances('sartorius_val_fold_2',{},'../input/5-fold-x-152/5_fold_split_sartorius_coco_dataset/annotations_val_fold_2.json', dataDir)\nregister_coco_instances('sartorius_val_fold_3',{},'../input/5-fold-x-152/5_fold_split_sartorius_coco_dataset/annotations_val_fold_3.json', dataDir)\nregister_coco_instances('sartorius_val_fold_4',{},'../input/5-fold-x-152/5_fold_split_sartorius_coco_dataset/annotations_val_fold_4.json', dataDir)\nregister_coco_instances('sartorius_val_fold_5',{},'../input/5-fold-x-152/5_fold_split_sartorius_coco_dataset/annotations_val_fold_5.json', dataDir)\nval_ds1 = DatasetCatalog.get('sartorius_val_fold_1')\nval_ds2 = DatasetCatalog.get('sartorius_val_fold_2')\nval_ds3 = DatasetCatalog.get('sartorius_val_fold_3')\nval_ds4 = DatasetCatalog.get('sartorius_val_fold_4')\nval_ds5 = DatasetCatalog.get('sartorius_val_fold_5')\nval_dss = [val_ds1, val_ds2, val_ds3, val_ds4, val_ds5]\n\nCFG_X152 = \"Misc/cascade_mask_rcnn_X_152_32x8d_FPN_IN5k_gn_dconv.yaml\"\n# X152_WEIGHTS = [f'../input/5-fold-x-152/R_152_pretrained_fold_{fold_idx}.pth' for fold_idx in range(1,6)]\nX152_WEIGHTS = [f'../input/sartorius-cascade-x152/cascade_mask_rcnn_X_152_32x8d_FPN_IN5k_gn_dconv_best_{fold_idx}.pth' for fold_idx in range(1,6)]\n\nCFG_RS200 = \"../input/resnest/resnest_configs/resnest_configs/COCO-InstanceSegmentation/mask_cascade_rcnn_ResNeSt_200_FPN_syncBN_all_tricks_3x.yaml\"\nRS200_WEIGHTS = [f'../input/resnest200-5folds-3classes/resnest200_f{fold_idx}.pth' for fold_idx in range(1,6)]\n\nCFG_SWINL = \"../input/detectron-swin/configs/configs/SwinT/mask_rcnn_swint_T_FPN_3x.yaml\"\nSWIN_WEIGHTS = [f'../input/detectron2-swint-l/mask_rcnn_swint_L_FPN_3x_best_{fold_idx}.pth' for fold_idx in range(1,6)]\n\nbest_models = (\n#     {'file': X152_WEIGHTS[0], 'config_name': CFG_X152, 'LB score': 0.3,'ths': [0.2, 0.35, 0.65], 'pxls': [80, 170, 80], 'iou_th': 0.275, 'mask_weight': 0.5},\n#     {'file': X152_WEIGHTS[1], 'config_name': CFG_X152, 'LB score': 0.3,'ths': [0.2, 0.35, 0.65], 'pxls': [80, 170, 80], 'iou_th': 0.275, 'mask_weight': 0.5},\n#     {'file': X152_WEIGHTS[2], 'config_name': CFG_X152, 'LB score': 0.3,'ths': [0.2, 0.35, 0.65], 'pxls': [80, 170, 80], 'iou_th': 0.275, 'mask_weight': 0.5},\n#     {'file': X152_WEIGHTS[3], 'config_name': CFG_X152, 'LB score': 0.3,'ths': [0.2, 0.35, 0.65], 'pxls': [80, 170, 80], 'iou_th': 0.275, 'mask_weight': 0.5},\n#     {'file': X152_WEIGHTS[4], 'config_name': CFG_X152, 'LB score': 0.3,'ths': [0.2, 0.35, 0.65], 'pxls': [80, 170, 80], 'iou_th': 0.275, 'mask_weight': 0.5},\n    {'file': RS200_WEIGHTS[0], 'config_name': CFG_RS200, 'LB score': 0.3,'ths': [0.3, 0.375, 0.675], 'pxls': [70, 100, 100], 'iou_th': 0.325, 'mask_weight': 1, 'v_flip': False, 'h_flip': False},\n    {'file': RS200_WEIGHTS[1], 'config_name': CFG_RS200, 'LB score': 0.3,'ths': [0.3, 0.375, 0.675], 'pxls': [70, 100, 100], 'iou_th': 0.325, 'mask_weight': 1, 'v_flip': False, 'h_flip': False},\n    {'file': RS200_WEIGHTS[2], 'config_name': CFG_RS200, 'LB score': 0.3,'ths': [0.3, 0.375, 0.675], 'pxls': [70, 100, 100], 'iou_th': 0.325, 'mask_weight': 1, 'v_flip': False, 'h_flip': False},\n    {'file': RS200_WEIGHTS[3], 'config_name': CFG_RS200, 'LB score': 0.3,'ths': [0.3, 0.375, 0.675], 'pxls': [70, 100, 100], 'iou_th': 0.325, 'mask_weight': 1, 'v_flip': False, 'h_flip': False},\n    {'file': RS200_WEIGHTS[4], 'config_name': CFG_RS200, 'LB score': 0.3,'ths': [0.3, 0.375, 0.675], 'pxls': [70, 100, 100], 'iou_th': 0.325, 'mask_weight': 1, 'v_flip': False, 'h_flip': False},\n    {'file': SWIN_WEIGHTS[0], 'config_name': CFG_SWINL, 'LB score': 0.3,'ths': [0.275, 0.5, 0.775], 'pxls': [80, 170, 60], 'iou_th': 0.25, 'mask_weight': 1, 'v_flip': False, 'h_flip': False},\n    {'file': SWIN_WEIGHTS[1], 'config_name': CFG_SWINL, 'LB score': 0.3,'ths': [0.275, 0.5, 0.775], 'pxls': [80, 170, 60], 'iou_th': 0.25, 'mask_weight': 1, 'v_flip': False, 'h_flip': False},\n    {'file': SWIN_WEIGHTS[2], 'config_name': CFG_SWINL, 'LB score': 0.3,'ths': [0.275, 0.5, 0.775], 'pxls': [80, 170, 60], 'iou_th': 0.25, 'mask_weight': 1, 'v_flip': False, 'h_flip': False},\n    {'file': SWIN_WEIGHTS[3], 'config_name': CFG_SWINL, 'LB score': 0.3,'ths': [0.275, 0.5, 0.775], 'pxls': [80, 170, 60], 'iou_th': 0.25, 'mask_weight': 1, 'v_flip': False, 'h_flip': False},\n    {'file': SWIN_WEIGHTS[4], 'config_name': CFG_SWINL, 'LB score': 0.3,'ths': [0.275, 0.5, 0.775], 'pxls': [80, 170, 60], 'iou_th': 0.25, 'mask_weight': 1, 'v_flip': False, 'h_flip': False},\n)\n\nNMS_TH = 0.25\nAVG_TH = 0.5\n\nAVERAGE_MASKS = True\nJOIN_SUPPRESSED = True\nKEEP_SUP_THR = 0.95\n\nMODEL_WEIGHTS = None\n\ntest_files = glob.glob('../input/sartorius-cell-instance-segmentation/test/*')","metadata":{"execution":{"iopub.status.busy":"2021-12-29T20:23:39.857976Z","iopub.execute_input":"2021-12-29T20:23:39.858523Z","iopub.status.idle":"2021-12-29T20:23:39.971723Z","shell.execute_reply.started":"2021-12-29T20:23:39.858389Z","shell.execute_reply":"2021-12-29T20:23:39.970386Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Utils","metadata":{}},{"cell_type":"code","source":"# From https://www.kaggle.com/stainsby/fast-tested-rle\ndef rle_decode(mask_rle, shape=(520, 704)):\n    '''\n    mask_rle: run-length as string formated (start length)\n    shape: (height,width) of array to return \n    Returns numpy array, 1 - mask, 0 - background\n\n    '''\n    s = mask_rle.split()\n    starts, lengths = [np.asarray(x, dtype=int) for x in (s[0:][::2], s[1:][::2])]\n    starts -= 1\n    ends = starts + lengths\n    img = np.zeros(shape[0]*shape[1], dtype=np.uint8)\n    for lo, hi in zip(starts, ends):\n        img[lo:hi] = 1\n    return img.reshape(shape)  # Needed to align to RLE direction\n\ndef rle_encode(img):\n    '''\n    img: numpy array, 1 - mask, 0 - background\n    Returns run length as string formated\n    '''\n    pixels = img.flatten()\n    pixels = np.concatenate([[0], pixels, [0]])\n    runs = np.where(pixels[1:] != pixels[:-1])[0] + 1\n    runs[1::2] -= runs[::2]\n    return ' '.join(str(x) for x in runs)\n\n\ndef get_masks(fn, predictor, idx=0):\n    im = cv2.imread(str(fn))\n    pred = predictor(im)\n    pred_classes = pred['instances'].pred_classes.cpu().numpy().tolist()\n    pred_class = max(set(pred_classes), key=pred_classes.count)\n    \n    take = pred['instances'].scores >= best_models[idx]['ths'][pred_class]\n    pred_masks = pred['instances'].pred_masks[take]\n    pred_masks = pred_masks.cpu().numpy()\n    res = []\n    used = np.zeros(im.shape[:2], dtype=int) \n    for mask in pred_masks:\n        mask = mask * (1-used)\n        if mask.sum() >= best_models[idx]['pxls'][pred_class]: # skip predictions with small area\n            used += mask\n            res.append(rle_encode(mask))\n    return res","metadata":{"execution":{"iopub.status.busy":"2021-12-28T23:49:26.203304Z","iopub.execute_input":"2021-12-28T23:49:26.203552Z","iopub.status.idle":"2021-12-28T23:49:26.216226Z","shell.execute_reply.started":"2021-12-28T23:49:26.203517Z","shell.execute_reply":"2021-12-28T23:49:26.215394Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def prepare_boxes(boxes, scores, labels, model_idxs):\n    result_boxes = boxes.copy()\n    cond = (result_boxes < 0)\n    cond_sum = cond.astype(np.int32).sum()\n    if cond_sum > 0:\n        print('Warning. Fixed {} boxes coordinates < 0'.format(cond_sum))\n        result_boxes[cond] = 0\n    cond = (result_boxes > 1)\n    cond_sum = cond.astype(np.int32).sum()\n    if cond_sum > 0:\n        print('Warning. Fixed {} boxes coordinates > 1. Check that your boxes was normalized at [0, 1]'.format(cond_sum))\n        print(result_boxes[cond])\n        result_boxes[cond] = 1\n    boxes1 = result_boxes.copy()\n    result_boxes[:, 0] = np.min(boxes1[:, [0, 2]], axis=1)\n    result_boxes[:, 2] = np.max(boxes1[:, [0, 2]], axis=1)\n    result_boxes[:, 1] = np.min(boxes1[:, [1, 3]], axis=1)\n    result_boxes[:, 3] = np.max(boxes1[:, [1, 3]], axis=1)\n    area = (result_boxes[:, 2] - result_boxes[:, 0]) * (result_boxes[:, 3] - result_boxes[:, 1])\n    cond = (area == 0)\n    cond_sum = cond.astype(np.int32).sum()\n    if cond_sum > 0:\n        print('Warning. Removed {} boxes with zero area!'.format(cond_sum))\n        result_boxes = result_boxes[area > 0]\n        scores = scores[area > 0]\n        labels = labels[area > 0]\n        model_idxs = model_idxs[area > 0]\n    return result_boxes, scores, labels, model_idxs","metadata":{"execution":{"iopub.status.busy":"2021-12-28T23:49:26.21746Z","iopub.execute_input":"2021-12-28T23:49:26.217882Z","iopub.status.idle":"2021-12-28T23:49:26.230697Z","shell.execute_reply.started":"2021-12-28T23:49:26.217842Z","shell.execute_reply":"2021-12-28T23:49:26.229996Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def nms_float_fast(dets, scores, model_idxs):\n    \"\"\"\n    # It's different from original nms because we have float coordinates on range [0; 1]\n    :param dets: numpy array of boxes with shape: (N, 5). Order: x1, y1, x2, y2, score. All variables in range [0; 1]\n    :param thresh: IoU value for boxes\n    :return: index of boxes to keep\n    \"\"\"\n    x1 = dets[:, 0]\n    y1 = dets[:, 1]\n    x2 = dets[:, 2]\n    y2 = dets[:, 3]\n\n    areas = (x2 - x1) * (y2 - y1)\n    order = scores.argsort()[::-1]\n\n    keep = []\n    supressed_list = []\n    while order.size > 0:\n        i = order[0]\n        keep.append(i)\n        xx1 = np.maximum(x1[i], x1[order[1:]])\n        yy1 = np.maximum(y1[i], y1[order[1:]])\n        xx2 = np.minimum(x2[i], x2[order[1:]])\n        yy2 = np.minimum(y2[i], y2[order[1:]])\n\n        w = np.maximum(0.0, xx2 - xx1)\n        h = np.maximum(0.0, yy2 - yy1)\n        inter = w * h\n        ovr = inter / (areas[i] + areas[order[1:]] - inter)\n        inds = np.where(ovr <= best_models[model_idxs[i]]['iou_th'])[0]\n#        print('inds in play:', order[1:])\n#        print('inds to live:', order[inds + 1])\n        supressed = np.where(ovr > KEEP_SUP_THR)[0].copy()\n#        print('inds to go:', order[supressed + 1])\n        supressed_list.append(order[supressed + 1].copy())\n        # leave only those that are not supressed on this step\n        order = order[inds + 1]\n    return keep, supressed_list","metadata":{"execution":{"iopub.status.busy":"2021-12-28T23:49:26.231792Z","iopub.execute_input":"2021-12-28T23:49:26.232281Z","iopub.status.idle":"2021-12-28T23:49:26.245586Z","shell.execute_reply.started":"2021-12-28T23:49:26.232244Z","shell.execute_reply":"2021-12-28T23:49:26.244789Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def nms_method(boxes, scores, labels, model_idxs, weights=None):\n    # If weights are specified\n    if weights is not None:\n        if len(boxes) != len(weights):\n            print('Incorrect number of weights: {}. Must be: {}. Skip it'.format(len(weights), len(boxes)))\n        else:\n            weights = np.array(weights)\n            for i in range(len(weights)):\n                scores[i] = (np.array(scores[i]) * weights[i]) / weights.sum()\n\n    # We concatenate everything\n    boxes = np.concatenate(boxes)\n    scores = np.concatenate(scores)\n    labels = np.concatenate(labels)\n    model_idxs = np.concatenate(model_idxs)\n\n    # Fix coordinates and removed zero area boxes\n    boxes, scores, labels, model_idxs = prepare_boxes(boxes, scores, labels, model_idxs)\n\n    # Run NMS independently for each label\n    unique_labels = np.unique(labels)\n    final_boxes = []\n    final_scores = []\n    final_labels = []\n    final_supressed = []\n    final_model_idxs = []\n    for l in unique_labels:\n        condition = (labels == l)\n        boxes_by_label = boxes[condition]\n        scores_by_label = scores[condition]\n        model_idxs_by_label = model_idxs[condition]\n        labels_by_label = np.array([l] * len(boxes_by_label))\n\n        keep, supressed = nms_float_fast(boxes_by_label, scores_by_label, model_idxs_by_label)\n\n        final_boxes.append(boxes_by_label[keep])\n        final_scores.append(scores_by_label[keep])\n        final_model_idxs.append(model_idxs_by_label[keep])\n        final_labels.append(labels_by_label[keep])\n        final_supressed.append(supressed)\n    final_boxes = np.concatenate(final_boxes)\n    final_scores = np.concatenate(final_scores)\n    final_model_idxs = np.concatenate(final_model_idxs)\n    final_labels = np.concatenate(final_labels)\n\n    return final_boxes, final_scores, final_labels, final_supressed, final_model_idxs\n\ndef nms(boxes, scores, labels, model_idxs, weights=None):\n    return nms_method(boxes, scores, labels, model_idxs, weights=weights)","metadata":{"execution":{"iopub.status.busy":"2021-12-28T23:49:26.246816Z","iopub.execute_input":"2021-12-28T23:49:26.247314Z","iopub.status.idle":"2021-12-28T23:49:26.261793Z","shell.execute_reply.started":"2021-12-28T23:49:26.247277Z","shell.execute_reply":"2021-12-28T23:49:26.261071Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def ensemble_preds(file_name, models):\n    img = cv2.imread(file_name)\n    height, width = img.shape[: 2]\n    classes = []\n    scores = []\n    bboxes = []\n    masks = []\n    model_idxs = []\n    for i, model in enumerate(models):\n        output = model(img)\n        pred_classes = output['instances'].pred_classes.cpu().numpy().tolist()\n        pred_class = max(set(pred_classes), key=pred_classes.count)\n        take = output['instances'].scores >= best_models[i]['ths'][pred_class]\n        # fix predicted classes to a single class\n        # otherwise NMS will work incorrectly, because it works each class separately\n        pred_classes = output['instances'].pred_classes[take].cpu().numpy().tolist()\n        pred_classes = [pred_class] * len(pred_classes)\n        classes.extend(pred_classes)\n        \n        scores.extend(output['instances'].scores[take].cpu().numpy().tolist())\n        bboxes.extend(output['instances'].pred_boxes[take].tensor.cpu().numpy().tolist())\n        masks.extend(output['instances'].pred_masks[take].cpu().numpy())\n#         print('Single model predicted mask number:', len(pred_classes))\n        \n        model_idxs.extend([i for _ in range(len(pred_classes))])\n        \n        h_flip = best_models[i]['h_flip']\n        v_flip = best_models[i]['v_flip']\n        \n        if (h_flip):\n            img2 = cv2.flip(img, 1)\n            output = model(img2)\n            pred_classes = output['instances'].pred_classes.cpu().numpy().tolist()\n            pred_class = max(set(pred_classes), key=pred_classes.count)\n            take = output['instances'].scores >= best_models[i]['ths'][pred_class]\n            # fix predicted classes to a single one\n            # otherwise NMS will crash, because it works each class separately\n            pred_classes = output['instances'].pred_classes[take].cpu().numpy().tolist()\n            pred_classes = [pred_class] * len(pred_classes)\n            classes.extend(pred_classes)\n        \n            scores.extend(output['instances'].scores[take].cpu().numpy().tolist())\n            boxes = output['instances'].pred_boxes[take].tensor.cpu().numpy()\n            # flip boxes and masks\n            boxes[:, [0, 2]] = width - boxes[:, [2, 0]]\n            bboxes.extend(boxes.tolist())\n            pred_masks = output['instances'].pred_masks[take].cpu().numpy()\n            for j in range(pred_masks.shape[0]):\n                pred_masks[j] = np.fliplr(pred_masks[j])\n            masks.extend(pred_masks)\n            print('Hor. flipped predicted mask number:', pred_masks.shape[0])\n            \n            model_idxs.extend([i for _ in range(len(pred_classes))])\n\n        if (v_flip):\n            img2 = cv2.flip(img, 0)\n            output = model(img2)\n            pred_classes = output['instances'].pred_classes.cpu().numpy().tolist()\n            pred_class = max(set(pred_classes), key=pred_classes.count)\n            take = output['instances'].scores >= best_models[i]['ths'][pred_class]\n            # fix predicted classes to a single one\n            # otherwise NMS will crash, because it works each class separately\n            pred_classes = output['instances'].pred_classes[take].cpu().numpy().tolist()\n            pred_classes = [pred_class] * len(pred_classes)\n            classes.extend(pred_classes)\n        \n            scores.extend(output['instances'].scores[take].cpu().numpy().tolist())\n            boxes = output['instances'].pred_boxes[take].tensor.cpu().numpy()\n            # flip boxes and masks\n            boxes[:, [1, 3]] = height - boxes[:, [3, 1]]\n            bboxes.extend(boxes.tolist())\n            pred_masks = output['instances'].pred_masks[take].cpu().numpy()\n            for j in range(pred_masks.shape[0]):\n                pred_masks[j] = np.flipud(pred_masks[j])\n            masks.extend(pred_masks)\n            print('Ver. flipped predicted mask number:', pred_masks.shape[0])\n            \n            model_idxs.extend([i for _ in range(len(pred_classes))])\n        del output\n        torch.cuda.empty_cache()\n        gc.collect()\n    assert len(classes) == len(masks) , 'ensemble lenght mismatch'\n    return classes, scores, bboxes, masks, model_idxs","metadata":{"execution":{"iopub.status.busy":"2021-12-28T23:49:26.263322Z","iopub.execute_input":"2021-12-28T23:49:26.263656Z","iopub.status.idle":"2021-12-28T23:49:26.289203Z","shell.execute_reply.started":"2021-12-28T23:49:26.263612Z","shell.execute_reply":"2021-12-28T23:49:26.288207Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def nms_predictions(classes, scores, bboxes, masks, model_idxs, nms_th=NMS_TH, shape=(520, 704)): # model_idxs\n    he, wd = shape[0], shape[1]\n    boxes_list = [[x[0] / wd, x[1] / he, x[2] / wd, x[3] / he] for x in bboxes]\n    scores_list = [x for x in scores]\n    labels_list = [x for x in classes]\n    nms_bboxes, nms_scores, nms_classes, sup_list, model_idxs_keep = nms([boxes_list], [scores_list], [labels_list], [model_idxs], weights=MODEL_WEIGHTS)\n    nms_scores = list(filter(lambda score: score >= nms_th, nms_scores))\n    nms_masks = []\n    sup_list = sup_list[0]\n    for i, s in enumerate(nms_scores):\n        current_mask = masks[scores.index(s)]\n        if JOIN_SUPPRESSED and i < len(sup_list):\n            if AVERAGE_MASKS:\n                current_mask = current_mask.astype(float)\n                total_masks = 1\n                for j in sup_list[i]:\n                    mask_weight = best_models[model_idxs[j]]['mask_weight']\n                    sup_mask = masks[j]\n                    current_mask += sup_mask * mask_weight\n                    total_masks += mask_weight\n                current_mask = current_mask / total_masks\n                current_mask = (current_mask >= AVG_TH).astype(int)\n            else:\n                for j in sup_list[i]:\n                    sup_mask = masks[j]\n                    current_mask = ((current_mask + sup_mask) > 0).astype(int)\n                    \n        nms_masks.append(current_mask)\n        \n    nms_scores, nms_classes, nms_masks, nms_model_idxs = zip(*sorted(zip(nms_scores, nms_classes, nms_masks, model_idxs_keep), key=lambda x: x[0], reverse=True))\n    return nms_classes, nms_scores, nms_masks, nms_model_idxs","metadata":{"execution":{"iopub.status.busy":"2021-12-28T23:49:26.290261Z","iopub.execute_input":"2021-12-28T23:49:26.290456Z","iopub.status.idle":"2021-12-28T23:49:26.304963Z","shell.execute_reply.started":"2021-12-28T23:49:26.290434Z","shell.execute_reply":"2021-12-28T23:49:26.304201Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def ensemble_pred_masks(masks, classes, model_idxs, shape=(520, 704)):\n    result = []\n    pred_class = max(set(classes), key=classes.count)\n    used = np.zeros(shape, dtype=int) \n    for i, mask in enumerate(masks):\n        mask = mask * (1 - used)\n        if mask.sum() >= best_models[model_idxs[i]]['pxls'][pred_class]:\n            used += mask\n            result.append(rle_encode(mask))\n    return result","metadata":{"execution":{"iopub.status.busy":"2021-12-28T23:49:26.306242Z","iopub.execute_input":"2021-12-28T23:49:26.30705Z","iopub.status.idle":"2021-12-28T23:49:26.314821Z","shell.execute_reply.started":"2021-12-28T23:49:26.30701Z","shell.execute_reply":"2021-12-28T23:49:26.314145Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class SMPBackboneWithFPN(nn.Module):\n    def __init__(\n                self, \n                encoder_name: str = \"resnet34\",\n                encoder_depth: int = 5,\n                pretrained: bool = True,\n                pyramid_channels: int = 256,\n                in_channels: int = 3,\n                fpn_depth: int = 4\n                ):\n        super(SMPBackboneWithFPN, self).__init__()\n        if pretrained:\n            if 'tu-tf' in encoder_name:\n                encoder_weights = 'imagenet'\n            else:\n                encoder_weights = list(smp.encoders.encoders[encoder_name]['pretrained_settings'].keys())[0]\n            \n        else:\n            encoder_weights = None\n        \n        self.fpn_depth = fpn_depth\n        self.encoder_name = encoder_name\n        self.names = ['p2', 'p3', 'p4', 'p5', 'p6']\n        self._out_feature_strides = {'p2': 4, 'p3': 8, 'p4': 16, 'p5': 32, 'p6': 64}\n        self.body = smp.encoders.get_encoder(encoder_name,\n                                            in_channels=in_channels,\n                                            depth=encoder_depth,\n                                            weights=encoder_weights,\n                                        )\n        \n        in_channels = list(self.body.out_channels[-self.fpn_depth:])\n        self.out_channels = pyramid_channels\n        self.fpn  = FeaturePyramidNetwork(in_channels_list=in_channels,\n                      out_channels=self.out_channels,\n                      extra_blocks=LastLevelMaxPool())\n        \n        \n    def forward(self, x):\n        x = self.body(x)\n        \n        x = dict(zip([f'layer_{i}' for i in range(self.fpn_depth)],x[-self.fpn_depth:]))\n        results = self.fpn(x)\n        values = results.values()\n        \n        x = {k:v.float() for k, v in zip(self.names, values)}\n        return x\n    \n    def output_shape(self):\n        return {\n            name: ShapeSpec(\n                channels=self.out_channels, stride=self._out_feature_strides[name]\n            )\n            for name in self.names\n        }\n    \ndef change_bn(module):\n    if isinstance(module, nn.BatchNorm2d):\n        #module.momentum = 0.1/32\n        return FrozenBatchNorm2d(num_features = module.num_features)\n    new_modules = []\n    for name ,child in (module.named_children()):\n        module.__setattr__(name, change_bn(child)) \n    return module","metadata":{"execution":{"iopub.status.busy":"2021-12-28T23:49:26.316141Z","iopub.execute_input":"2021-12-28T23:49:26.316459Z","iopub.status.idle":"2021-12-28T23:49:26.332681Z","shell.execute_reply.started":"2021-12-28T23:49:26.316402Z","shell.execute_reply":"2021-12-28T23:49:26.331995Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Resnest200Predictor:\n    \"\"\"\n    Create a simple end-to-end predictor with the given config that runs on\n    single device for a single input image.\n    Compared to using the model directly, this class does the following additions:\n    1. Load checkpoint from `cfg.MODEL.WEIGHTS`.\n    2. Always take BGR image as the input and apply conversion defined by `cfg.INPUT.FORMAT`.\n    3. Apply resizing defined by `cfg.INPUT.{MIN,MAX}_SIZE_TEST`.\n    4. Take one input image and produce a single output, instead of a batch.\n    This is meant for simple demo purposes, so it does the above steps automatically.\n    This is not meant for benchmarks or running complicated inference logic.\n    If you'd like to do anything more complicated, please refer to its source code as\n    examples to build and use the model manually.\n    Attributes:\n        metadata (Metadata): the metadata of the underlying dataset, obtained from\n            cfg.DATASETS.TEST.\n    Examples:\n    ::\n        pred = DefaultPredictor(cfg)\n        inputs = cv2.imread(\"input.jpg\")\n        outputs = pred(inputs)\n    \"\"\"\n\n    def __init__(self, cfg):\n        self.cfg = cfg.clone()  # cfg can be modified by model\n        self.model = build_model(self.cfg)\n        self.model.eval()\n        if len(cfg.DATASETS.TEST):\n            self.metadata = MetadataCatalog.get(cfg.DATASETS.TEST[0])\n\n        checkpointer = DetectionCheckpointer(self.model)\n        checkpointer.load(cfg.MODEL.WEIGHTS)\n\n        self.aug = T.ResizeShortestEdge(\n            [cfg.INPUT.MIN_SIZE_TEST, cfg.INPUT.MIN_SIZE_TEST], cfg.INPUT.MAX_SIZE_TEST\n        )\n\n        self.input_format = cfg.INPUT.FORMAT\n        assert self.input_format in [\"RGB\", \"BGR\"], self.input_format\n\n    def __call__(self, original_image):\n        \"\"\"\n        Args:\n            original_image (np.ndarray): an image of shape (H, W, C) (in BGR order).\n        Returns:\n            predictions (dict):\n                the output of the model for one image only.\n                See :doc:`/tutorials/models` for details about the format.\n        \"\"\"\n        with torch.no_grad():  # https://github.com/sphinx-doc/sphinx/issues/4258\n            # Apply pre-processing to image.\n            if self.input_format == \"RGB\":\n                # whether the model expects BGR inputs or RGB\n                original_image = original_image[:, :, ::-1]\n            height, width = original_image.shape[:2]\n            image = self.aug.get_transform(original_image).apply_image(original_image)\n            image = torch.as_tensor(image.astype(\"float32\").transpose(2, 0, 1))\n\n            inputs = {\"image\": image, \"height\": height, \"width\": width}\n            predictions = self.model([inputs])[0]\n            return predictions","metadata":{"execution":{"iopub.status.busy":"2021-12-28T23:49:26.334324Z","iopub.execute_input":"2021-12-28T23:49:26.335132Z","iopub.status.idle":"2021-12-28T23:49:26.347993Z","shell.execute_reply.started":"2021-12-28T23:49:26.335092Z","shell.execute_reply":"2021-12-28T23:49:26.347198Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Resnest269Predictor:\n    \"\"\"\n    Create a simple end-to-end predictor with the given config that runs on\n    single device for a single input image.\n    Compared to using the model directly, this class does the following additions:\n    1. Load checkpoint from `cfg.MODEL.WEIGHTS`.\n    2. Always take BGR image as the input and apply conversion defined by `cfg.INPUT.FORMAT`.\n    3. Apply resizing defined by `cfg.INPUT.{MIN,MAX}_SIZE_TEST`.\n    4. Take one input image and produce a single output, instead of a batch.\n    This is meant for simple demo purposes, so it does the above steps automatically.\n    This is not meant for benchmarks or running complicated inference logic.\n    If you'd like to do anything more complicated, please refer to its source code as\n    examples to build and use the model manually.\n    Attributes:\n        metadata (Metadata): the metadata of the underlying dataset, obtained from\n            cfg.DATASETS.TEST.\n    Examples:\n    ::\n        pred = DefaultPredictor(cfg)\n        inputs = cv2.imread(\"input.jpg\")\n        outputs = pred(inputs)\n    \"\"\"\n\n    def __init__(self, cfg):\n        self.cfg = cfg.clone()  # cfg can be modified by model\n        self.model = self.build_r269_model(self.cfg)\n        self.model.eval()\n        if len(cfg.DATASETS.TEST):\n            self.metadata = MetadataCatalog.get(cfg.DATASETS.TEST[0])\n\n        checkpointer = DetectionCheckpointer(self.model)\n        checkpointer.load(cfg.MODEL.WEIGHTS)\n\n        self.aug = T.ResizeShortestEdge(\n            [cfg.INPUT.MIN_SIZE_TEST, cfg.INPUT.MIN_SIZE_TEST], cfg.INPUT.MAX_SIZE_TEST\n        )\n\n        self.input_format = cfg.INPUT.FORMAT\n        assert self.input_format in [\"RGB\", \"BGR\"], self.input_format\n\n    def __call__(self, original_image):\n        \"\"\"\n        Args:\n            original_image (np.ndarray): an image of shape (H, W, C) (in BGR order).\n        Returns:\n            predictions (dict):\n                the output of the model for one image only.\n                See :doc:`/tutorials/models` for details about the format.\n        \"\"\"\n        with torch.no_grad():  # https://github.com/sphinx-doc/sphinx/issues/4258\n            # Apply pre-processing to image.\n            if self.input_format == \"RGB\":\n                # whether the model expects BGR inputs or RGB\n                original_image = original_image[:, :, ::-1]\n            height, width = original_image.shape[:2]\n            image = self.aug.get_transform(original_image).apply_image(original_image)\n            image = torch.as_tensor(image.astype(\"float32\").transpose(2, 0, 1))\n\n            inputs = {\"image\": image, \"height\": height, \"width\": width}\n            predictions = self.model([inputs])[0]\n            return predictions\n        \n    def build_r269_model(self,cfg):\n        #create base model\n        #model = detectron2.modeling.build_model(cfg)\n        #create new backbone\n        backbone = SMPBackboneWithFPN(backbone_name)\n        #freeze bachnorm\n        backbone = change_bn(backbone)\n        backbone.size_divisibility = 32\n        #create model with new backbone\n        model = GeneralizedRCNN(backbone=backbone, \n                                #proposal_generator=model.proposal_generator,\n                                #roi_heads=model.roi_heads,\n                                #\n                                proposal_generator=build_proposal_generator(cfg, backbone.output_shape()),\n                                roi_heads=build_roi_heads(cfg, backbone.output_shape()),\n                                pixel_mean=cfg.MODEL.PIXEL_MEAN,\n                                pixel_std=cfg.MODEL.PIXEL_STD,\n                               )\n\n        print(model)\n        return model.to(device)","metadata":{"execution":{"iopub.status.busy":"2021-12-28T23:49:26.352793Z","iopub.execute_input":"2021-12-28T23:49:26.353551Z","iopub.status.idle":"2021-12-28T23:49:26.36746Z","shell.execute_reply.started":"2021-12-28T23:49:26.353437Z","shell.execute_reply":"2021-12-28T23:49:26.366716Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Init models","metadata":{}},{"cell_type":"code","source":"MODELS = []\nTHSS = []\n\nfor model in best_models:\n    model_name = model[\"file\"]\n    model_ths = model[\"ths\"]\n    config_name = model[\"config_name\"]\n    THSS.append(model_ths)\n    cfg = get_cfg()\n    if config_name.startswith('Misc'):\n        cfg.merge_from_file(model_zoo.get_config_file(config_name))\n        cfg.INPUT.MASK_FORMAT = 'bitmask'\n        cfg.MODEL.ROI_HEADS.NUM_CLASSES = 3\n        cfg.MODEL.WEIGHTS = model_name\n        cfg.TEST.DETECTIONS_PER_IMAGE = 1000\n        cfg.MODEL.ROI_HEADS.NUM_CLASSES = 3\n        MODELS.append(DefaultPredictor(cfg))\n        print('Model loaded:', model_name)\n    elif config_name.startswith('../input/detectron'):\n        add_swinl_384_config(cfg)\n        cfg.merge_from_file(config_name)\n        cfg.INPUT.MASK_FORMAT = 'bitmask'\n        cfg.MODEL.ROI_HEADS.NUM_CLASSES = 3\n        cfg.MODEL.WEIGHTS = model_name\n        cfg.TEST.DETECTIONS_PER_IMAGE = 1000\n        cfg.MODEL.ROI_HEADS.NUM_CLASSES = 3\n        MODELS.append(DefaultPredictor(cfg))\n        print('Model loaded:', model_name)\n    elif config_name.startswith('../input/resnest'):\n        add_resnest_config(cfg)\n        cfg.merge_from_file(config_name)\n        cfg.INPUT.MASK_FORMAT = 'bitmask'\n        cfg.MODEL.WEIGHTS = model_name\n        cfg.TEST.DETECTIONS_PER_IMAGE = 1000\n        cfg.MODEL.ROI_HEADS.NUM_CLASSES = 3\n        cfg.MODEL.FPN.NORM = 'FrozenBN'\n        cfg.MODEL.ROI_BOX_HEAD.NORM = 'FrozenBN'\n        cfg.MODEL.ROI_MASK_HEAD.NORM = 'FrozenBN'\n        cfg.MODEL.RESNETS.NORM = 'FrozenBN'\n        MODELS.append(Resnest200Predictor(cfg))\n        print('Model loaded:', model_name)\n    elif config_name.startswith('../input/resnest269'):\n        model_zoo.get_config_file(\"COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml\")\n        cfg.INPUT.MASK_FORMAT = 'bitmask'\n        cfg.MODEL.WEIGHTS = model_name\n        cfg.TEST.DETECTIONS_PER_IMAGE = 1000\n        cfg.MODEL.ROI_HEADS.NUM_CLASSES = 3\n        cfg.MODEL.FPN.NORM = 'FrozenBN'\n        cfg.MODEL.ROI_BOX_HEAD.NORM = 'FrozenBN'\n        cfg.MODEL.ROI_MASK_HEAD.NORM = 'FrozenBN'\n        cfg.MODEL.RESNETS.NORM = 'FrozenBN'\n        MODELS.append(Resnest269Predictor(cfg))\n        print('Model loaded:', model_name)","metadata":{"execution":{"iopub.status.busy":"2021-12-28T23:49:26.37007Z","iopub.execute_input":"2021-12-28T23:49:26.370451Z","iopub.status.idle":"2021-12-28T23:52:28.415418Z","shell.execute_reply.started":"2021-12-28T23:49:26.370424Z","shell.execute_reply":"2021-12-28T23:52:28.414598Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Scoring function","metadata":{}},{"cell_type":"code","source":"def precision_at(threshold, iou):\n    matches = iou > threshold\n    true_positives = np.sum(matches, axis=1) == 1  # Correct objects\n    false_positives = np.sum(matches, axis=0) == 0  # Missed objects\n    false_negatives = np.sum(matches, axis=1) == 0  # Extra objects\n    return np.sum(true_positives), np.sum(false_positives), np.sum(false_negatives)\n\ndef score(classes, masks, targ, model_idxs):\n    res_masks = []\n    pred_class = max(set(classes), key=classes.count)\n    used = np.zeros((520, 704), dtype=int) \n    for i, mask in enumerate(masks):\n        pixels = best_models[model_idxs[i]]['pxls']\n        mask = mask * (1 - used)\n        if mask.sum() >= pixels[pred_class]: # skip predictions with small area\n            used += mask\n            res_masks.append(mask)\n    enc_preds = [mask_util.encode(np.asarray(p, order='F', dtype=np.uint8)) for p in res_masks]\n    enc_targs = list(map(lambda x:x['segmentation'], targ['annotations']))\n    ious = mask_util.iou(enc_preds, enc_targs, [0]*len(enc_targs))\n    prec = []\n    for t in np.arange(0.5, 1.0, 0.05):\n        tp, fp, fn = precision_at(t, ious)\n        p = tp / (tp + fp + fn)\n        prec.append(p)\n    return np.mean(prec)\n\n# def score_all():\n#     scores_all = []\n#     for item in tqdm(val_ds2, leave=False):\n#         fn =  item['file_name']\n#         classes, scores, bboxes, masks, model_idxs = ensemble_preds(fn, MODELS)\n#         classes, scores, masks, model_idxs = nms_predictions(classes, scores, bboxes, masks, model_idxs, nms_th=NMS_TH)     \n#         sc = score(classes, masks, item, model_idxs)\n#         scores_all.append(sc)\n#     return np.mean(scores_all)\n\n# best_thresh = 0.25\n# pixels = [80, 170, 60] # 3 - 65?\n# THRESHOLDS = [0.3, 0.38, 0.58]\n\n# best_score = 0\n# for i in tqdm(np.arange(0.2, 0.6, 0.025)):\n#     curr_score = score_all(i, pixels)\n#     if curr_score > best_score:\n#         best_score = curr_score\n#         best_thresh = i\n#     print(f'Threshold is {round(i, 2)}, score is {curr_score}')\n    \n# best_pixels = [80, 170, 60]\n# for i in tqdm(range(3)):\n#     best_score = 0\n#     for j in tqdm(np.arange(20, 180, 10)):\n#         pixels[i] = j\n#         curr_score = score_all(best_thresh, pixels)\n#         if curr_score > best_score:\n#             best_score = curr_score\n#             best_pixels[i] = j\n#         print(f'Class number is {i+1}, pixel thresh is {round(j, 2)}, score is {curr_score}')\n#     pixels[i] = best_pixels[i]\n    \n# best_thresholds = [0, 0, 0]\n# for i in tqdm(range(3)):\n#     best_score = 0\n#     for j in tqdm(np.arange(0.1, 0.75, 0.05)):\n#         THRESHOLDS[i] = j\n#         curr_score = score_all(best_thresh, best_pixels)\n#         if curr_score > best_score:\n#             best_score = curr_score\n#             best_thresholds[i] = j\n#         print(f'Class number is {i+1}, THRESHOLD is {round(j, 2)}, score is {curr_score}')\n#     THRESHOLDS[i] = best_thresholds[i]\n    \n# best_thresh, best_pixels, best_thresholds","metadata":{"execution":{"iopub.status.busy":"2021-12-28T23:52:28.417123Z","iopub.execute_input":"2021-12-28T23:52:28.418505Z","iopub.status.idle":"2021-12-28T23:52:28.431265Z","shell.execute_reply.started":"2021-12-28T23:52:28.41846Z","shell.execute_reply":"2021-12-28T23:52:28.430619Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def score_all():\n    scores_all = []\n    for val_ds in tqdm(val_dss[:1]):\n        scores_fold = []\n        for item in tqdm(val_ds, leave=False):\n            fn =  item['file_name']\n            classes, scores, bboxes, masks, model_idxs = ensemble_preds(fn, MODELS)\n            classes, scores, masks, model_idxs = nms_predictions(classes, scores, bboxes, masks, model_idxs, nms_th=NMS_TH)     \n            sc = score(classes, masks, item, model_idxs)\n            scores_fold.append(sc)\n        res = np.mean(scores_fold)\n        print(res)\n        scores_all.append(res)\n\nscore_all()","metadata":{"execution":{"iopub.status.busy":"2021-12-28T23:52:28.432628Z","iopub.execute_input":"2021-12-28T23:52:28.432887Z","iopub.status.idle":"2021-12-28T23:52:28.446785Z","shell.execute_reply.started":"2021-12-28T23:52:28.43285Z","shell.execute_reply":"2021-12-28T23:52:28.446126Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Visualisation function","metadata":{}},{"cell_type":"code","source":"def check_nms(model_num, ID_TEST):\n    encoded_masks_single = get_masks(\n                                    test_files[ID_TEST], \n                                    predictor=MODELS[model_num],\n                                    idx=0\n                                    )\n    classes, scores, bboxes, masks, model_idxs = ensemble_preds(\n                                                                file_name=test_files[ID_TEST], \n                                                                models=MODELS\n                                                                )\n    classes, scores, masks, model_idxs = nms_predictions(\n                                                        classes, \n                                                        scores, \n                                                        bboxes,\n                                                        masks, \n                                                        model_idxs,\n                                                    )\n    encoded_masks = ensemble_pred_masks(masks, classes, model_idxs)\n\n    _, axs = plt.subplots(2, 2, figsize=(24, 18))\n    axs[0][0].imshow(cv2.imread(test_files[ID_TEST]))\n    axs[0][0].axis('off')\n    axs[0][0].set_title(test_files[ID_TEST])\n    for en_mask in encoded_masks_single:\n        dec_mask = rle_decode(en_mask)\n        axs[0][1].imshow(np.ma.masked_where(dec_mask == 0, dec_mask))\n        axs[0][1].axis('off')\n        axs[0][1].set_title('single model')\n    axs[1][0].imshow(cv2.imread(test_files[ID_TEST]))\n    axs[1][0].axis('off')\n    axs[1][0].set_title(test_files[ID_TEST])\n    for en_mask in encoded_masks:\n        dec_mask = rle_decode(en_mask)\n        axs[1][1].imshow(np.ma.masked_where(dec_mask == 0, dec_mask))\n        axs[1][1].axis('off')\n        axs[1][1].set_title('ensemble models')\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2021-12-28T23:52:28.448876Z","iopub.execute_input":"2021-12-28T23:52:28.449411Z","iopub.status.idle":"2021-12-28T23:52:28.461642Z","shell.execute_reply.started":"2021-12-28T23:52:28.449372Z","shell.execute_reply":"2021-12-28T23:52:28.460885Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"check_nms(model_num=0, ID_TEST=0)","metadata":{"execution":{"iopub.status.busy":"2021-12-28T23:52:28.463105Z","iopub.execute_input":"2021-12-28T23:52:28.463487Z","iopub.status.idle":"2021-12-28T23:52:28.474252Z","shell.execute_reply.started":"2021-12-28T23:52:28.463453Z","shell.execute_reply":"2021-12-28T23:52:28.473485Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"check_nms(model_num=0, ID_TEST=1)","metadata":{"execution":{"iopub.status.busy":"2021-12-28T23:52:28.475509Z","iopub.execute_input":"2021-12-28T23:52:28.475837Z","iopub.status.idle":"2021-12-28T23:52:28.485901Z","shell.execute_reply.started":"2021-12-28T23:52:28.475798Z","shell.execute_reply":"2021-12-28T23:52:28.485198Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"check_nms(model_num=0, ID_TEST=2)","metadata":{"execution":{"iopub.status.busy":"2021-12-28T23:52:28.487109Z","iopub.execute_input":"2021-12-28T23:52:28.48749Z","iopub.status.idle":"2021-12-28T23:52:28.495699Z","shell.execute_reply.started":"2021-12-28T23:52:28.487454Z","shell.execute_reply":"2021-12-28T23:52:28.494703Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Submission","metadata":{}},{"cell_type":"code","source":"sub_ids = []\nsub_masks = []\n\nfor file_name in test_files:\n    base = os.path.basename(file_name)\n    file_id = os.path.splitext(base)[0]\n        \n    classes, scores, bboxes, masks, model_idxs = ensemble_preds(file_name, MODELS)\n    classes, scores, masks, model_idxs = nms_predictions(classes, scores, bboxes, masks, model_idxs, nms_th=NMS_TH)\n    encoded_masks = ensemble_pred_masks(masks, classes, model_idxs)\n        \n    for enc in encoded_masks:\n        sub_ids.append(file_id)\n        sub_masks.append(enc)","metadata":{"execution":{"iopub.status.busy":"2021-12-28T23:53:40.586538Z","iopub.execute_input":"2021-12-28T23:53:40.587214Z","iopub.status.idle":"2021-12-28T23:54:17.152792Z","shell.execute_reply.started":"2021-12-28T23:53:40.587172Z","shell.execute_reply":"2021-12-28T23:54:17.15204Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_sub = pd.DataFrame({'id': sub_ids, 'predicted': sub_masks})\ndf_sub.to_csv('submission.csv', index=False)\ndf_sub.head()","metadata":{"execution":{"iopub.status.busy":"2021-12-28T23:53:25.399343Z","iopub.execute_input":"2021-12-28T23:53:25.399618Z","iopub.status.idle":"2021-12-28T23:53:25.443981Z","shell.execute_reply.started":"2021-12-28T23:53:25.399586Z","shell.execute_reply":"2021-12-28T23:53:25.443307Z"},"trusted":true},"execution_count":null,"outputs":[]}]}