{"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":"# Detectron: ensemble inference with NMS","metadata":{"papermill":{"duration":0.013003,"end_time":"2021-10-27T20:21:06.575583","exception":false,"start_time":"2021-10-27T20:21:06.56258","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"## Acknowledgements","metadata":{}},{"cell_type":"markdown","source":"Based on these excellent notebooks [Positive score with Detectron 2/3 - Training](https://www.kaggle.com/slawekbiel/positive-score-with-detectron-2-3-training) and [Positive score with Detectron 3/3 - Inference](https://www.kaggle.com/slawekbiel/positive-score-with-detectron-3-3-inference). Please upvote them.\n\n[Weighted boxes fusion](https://github.com/ZFTurbo/Weighted-Boxes-Fusion) library is also used.","metadata":{}},{"cell_type":"markdown","source":"## Install and import libraries","metadata":{"papermill":{"duration":0.009696,"end_time":"2021-10-27T20:21:06.597177","exception":false,"start_time":"2021-10-27T20:21:06.587481","status":"completed"},"tags":[]}},{"cell_type":"code","source":"KAGGLE = True","metadata":{"execution":{"iopub.status.busy":"2021-12-29T06:59:47.634273Z","iopub.execute_input":"2021-12-29T06:59:47.634820Z","iopub.status.idle":"2021-12-29T06:59:47.640196Z","shell.execute_reply.started":"2021-12-29T06:59:47.634782Z","shell.execute_reply":"2021-12-29T06:59:47.638026Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"IPATH = '../input/detectron-05/whls'\nif KAGGLE:\n    !pip install {IPATH}/pycocotools-2.0.2/dist/pycocotools-2.0.2.tar --no-index --find-links ../input/detectron-05/whls \n    !pip install {IPATH}/fvcore-0.1.5.post20211019/fvcore-0.1.5.post20211019 --no-index --find-links ../input/detectron-05/whls \n    !pip install {IPATH}/antlr4-python3-runtime-4.8/antlr4-python3-runtime-4.8 --no-index --find-links ../input/detectron-05/whls \n    !pip install {IPATH}/detectron2-0.5/detectron2 --no-index --find-links ../input/detectron-05/whls \n    !pip install ../input/ensemble-boxes-104/ensemble_boxes-1.0.4/ -f ./ --no-index","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"papermill":{"duration":201.727571,"end_time":"2021-10-27T20:24:28.33438","exception":false,"start_time":"2021-10-27T20:21:06.606809","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-12-29T06:59:47.642862Z","iopub.execute_input":"2021-12-29T06:59:47.643461Z","iopub.status.idle":"2021-12-29T07:03:20.955555Z","shell.execute_reply.started":"2021-12-29T06:59:47.643421Z","shell.execute_reply":"2021-12-29T07:03:20.954542Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport cv2\nimport json\nimport time\nimport numpy as np\nimport pandas as pd\nimport torch\nimport detectron2\nfrom tqdm.auto import tqdm\nfrom detectron2 import model_zoo\nfrom detectron2.engine import DefaultPredictor\nfrom detectron2.config import get_cfg\nfrom detectron2.data.datasets import register_coco_instances\nfrom detectron2.evaluation import inference_on_dataset\nfrom detectron2.evaluation.evaluator import DatasetEvaluator\nfrom detectron2.data import DatasetCatalog, build_detection_test_loader\nimport pycocotools.mask as mask_util\nfrom PIL import Image\nimport matplotlib.pyplot as plt\nfrom fastcore.all import *\nfrom ensemble_boxes import *\nos.environ['CUDA_VISIBLE_DEVICES'] = '0' if KAGGLE else '1'\nif torch.cuda.is_available():\n    DEVICE = torch.device('cuda')\n    print('GPU is available')\nelse:\n    DEVICE = torch.device('cpu')\n    print('CPU is used')\nprint('detectron ver:', detectron2.__version__)","metadata":{"papermill":{"duration":1.200842,"end_time":"2021-10-27T20:24:29.563049","exception":false,"start_time":"2021-10-27T20:24:28.362207","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-12-29T07:03:20.957567Z","iopub.execute_input":"2021-12-29T07:03:20.957896Z","iopub.status.idle":"2021-12-29T07:03:22.752711Z","shell.execute_reply.started":"2021-12-29T07:03:20.957853Z","shell.execute_reply":"2021-12-29T07:03:22.751842Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Config load","metadata":{}},{"cell_type":"code","source":"config1 = 'COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml'\nconfig2 = 'Misc/cascade_mask_rcnn_R_50_FPN_3x.yaml'\nconfig3 = 'COCO-InstanceSegmentation/mask_rcnn_X_101_32x8d_FPN_3x.yaml'\n\nmdl_path1 = \"../input/best-transfer-100k\"\n#mdl_path2=\"../input/best-100k-firstrun\"\n\nbest_models=(\n  \n        {'file': 'model_x101_pseudo.pth','LB score': 0.314, 'CV Score': 0.298, 'ths':[.19, .39, .67],'config':config3},\n        {'file': 'model_cascade_pseudo.pth','LB score': 0.311, 'CV Score': 0.292, 'ths':[.19, .39, .73],'config':config2},\n         # {'file': 'model_mask_r50.pth','LB score': 0.307, 'CV Score': 0.3079, 'ths':[.15, .35, .58],'config':config1},\n            )\n\n\nDATA_PATH = \"../input/sartorius-cell-instance-segmentation\"\nMODELS = []\nBEST_MODELS =[]\nTHSS = []\nID_TEST = 0\nSUBM_PATH = f'{DATA_PATH}/test'\nSINGLE_MODE = False\nNMS = True\nMIN_PIXELS = [75, 150, 75]\nIOU_TH = .4\n\nfor model in best_models:\n    model_name=model[\"file\"]\n    model_ths=model[\"ths\"]\n    config=model['config']\n    BEST_MODELS.append(model_name)\n    THSS.append(model_ths)\n    cfg = get_cfg()\n    cfg.merge_from_file(model_zoo.get_config_file(config))\n    cfg.INPUT.MASK_FORMAT = 'bitmask'\n    cfg.MODEL.ROI_HEADS.NUM_CLASSES = 3 \n    cfg.MODEL.WEIGHTS = f'{mdl_path1}/{model_name}'  \n    cfg.TEST.DETECTIONS_PER_IMAGE = 1000\n\n    cfg.TEST.FLIP = True\n    cfg.TEST.PRECISE_BN.NUM_ITER = 200\n    \n    MODELS.append(DefaultPredictor(cfg))\nprint(f'all loaded:\\nthresholds: {THSS}\\nmodels: {BEST_MODELS}')","metadata":{"execution":{"iopub.status.busy":"2021-12-29T07:03:22.754018Z","iopub.execute_input":"2021-12-29T07:03:22.754283Z","iopub.status.idle":"2021-12-29T07:03:36.440832Z","shell.execute_reply.started":"2021-12-29T07:03:22.754246Z","shell.execute_reply":"2021-12-29T07:03:36.440030Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Utils","metadata":{}},{"cell_type":"code","source":"def 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) \n                       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    '''\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\ndef pred_masks(file_name, path, model, ths, min_pixels):\n    img = cv2.imread(f'{path}/{file_name}')\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 >= ths[pred_class]\n    pred_masks = output['instances'].pred_masks[take]\n    pred_masks = pred_masks.cpu().numpy()\n    result = []\n    used = np.zeros(img.shape[:2], dtype=int) \n    for i, mask in enumerate(pred_masks):\n        mask = mask * (1 - used)\n        if mask.sum() >= min_pixels[pred_class]:\n            used += mask\n            result.append(rle_encode(mask))\n    return result\n\ndef ensemble_preds(file_name, path, models, ths):\n    img = cv2.imread(f'{path}/{file_name}')\n    classes = []\n    scores = []\n    bboxes = []\n    masks = []\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 >= ths[i][pred_class]\n        classes.extend(output['instances'].pred_classes[take].cpu().numpy().tolist())\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    assert len(classes) == len(masks) , 'ensemble lenght mismatch'\n    scores, classes, bboxes, masks = zip(\n        *sorted(zip(scores, classes, bboxes, masks), \n                reverse=True))\n    return classes, scores, bboxes, masks\n\ndef nms_predictions(classes, scores, bboxes, masks, \n                    iou_th=.5, shape=(520, 704)):\n    he, wd = shape[0], shape[1]\n    boxes_list = [[x[0] / wd, x[1] / he, x[2] / wd, x[3] / he]\n                  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 = nms(\n        boxes=[boxes_list], \n        scores=[scores_list], \n        labels=[labels_list], \n        weights=None,\n        iou_thr=iou_th\n    )\n    nms_masks = []\n    for s in nms_scores:\n        nms_masks.append(masks[scores.index(s)])\n    nms_scores, nms_classes, nms_masks = zip(\n        *sorted(\n            zip(nms_scores, nms_classes, nms_masks), \n            reverse=True))\n    return nms_classes, nms_scores, nms_masks\n\ndef ensemble_pred_masks(masks, classes, min_pixels, 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() >= min_pixels[pred_class]:\n            used += mask\n            result.append(rle_encode(mask))\n    return result","metadata":{"papermill":{"duration":0.038173,"end_time":"2021-10-27T20:24:29.684335","exception":false,"start_time":"2021-10-27T20:24:29.646162","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-12-29T07:03:36.454248Z","iopub.execute_input":"2021-12-29T07:03:36.454717Z","iopub.status.idle":"2021-12-29T07:03:36.481234Z","shell.execute_reply.started":"2021-12-29T07:03:36.454679Z","shell.execute_reply":"2021-12-29T07:03:36.480506Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Demo inference","metadata":{"papermill":{"duration":0.025925,"end_time":"2021-10-27T20:24:37.162884","exception":false,"start_time":"2021-10-27T20:24:37.136959","status":"completed"},"tags":[]}},{"cell_type":"code","source":"test_names = os.listdir(SUBM_PATH)\nprint('test images:', len(test_names))","metadata":{"papermill":{"duration":0.037264,"end_time":"2021-10-27T20:24:29.748077","exception":false,"start_time":"2021-10-27T20:24:29.710813","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-12-29T07:03:36.482503Z","iopub.execute_input":"2021-12-29T07:03:36.482799Z","iopub.status.idle":"2021-12-29T07:03:36.501335Z","shell.execute_reply.started":"2021-12-29T07:03:36.482722Z","shell.execute_reply":"2021-12-29T07:03:36.500681Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"encoded_masks_single = pred_masks(\n    test_names[ID_TEST], \n    path=SUBM_PATH, \n    model=MODELS[0],\n    ths=THSS[0],\n    min_pixels=MIN_PIXELS\n)","metadata":{"papermill":{"duration":21.807086,"end_time":"2021-10-27T20:24:58.995678","exception":false,"start_time":"2021-10-27T20:24:37.188592","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-12-29T07:03:36.502505Z","iopub.execute_input":"2021-12-29T07:03:36.502756Z","iopub.status.idle":"2021-12-29T07:03:42.805399Z","shell.execute_reply.started":"2021-12-29T07:03:36.502723Z","shell.execute_reply":"2021-12-29T07:03:42.804646Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"classes, scores, bboxes, masks = ensemble_preds(\n    file_name=test_names[ID_TEST] , \n    path=SUBM_PATH, \n    models=MODELS, \n    ths=THSS\n)\nif NMS:\n    classes, scores, masks = nms_predictions(\n        classes, \n        scores, \n        bboxes,\n        masks, \n        iou_th=IOU_TH\n    )\nencoded_masks = ensemble_pred_masks(masks, classes, min_pixels=MIN_PIXELS)","metadata":{"execution":{"iopub.status.busy":"2021-12-29T07:04:45.736598Z","iopub.execute_input":"2021-12-29T07:04:45.737367Z","iopub.status.idle":"2021-12-29T07:04:46.684908Z","shell.execute_reply.started":"2021-12-29T07:04:45.737325Z","shell.execute_reply":"2021-12-29T07:04:46.684188Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"'''_, axs = plt.subplots(2, 2, figsize=(14, 8))\naxs[0][0].imshow(cv2.imread(f'{SUBM_PATH}/{test_names[ID_TEST]}'))\naxs[0][0].axis('off')\naxs[0][0].set_title(test_names[ID_TEST])\nfor 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')\naxs[1][0].imshow(cv2.imread(f'{SUBM_PATH}/{test_names[ID_TEST]}'))\naxs[1][0].axis('off')\naxs[1][0].set_title(test_names[ID_TEST])\nfor 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')\nplt.show()\n'''","metadata":{"execution":{"iopub.status.busy":"2021-12-29T07:04:51.258917Z","iopub.execute_input":"2021-12-29T07:04:51.259370Z","iopub.status.idle":"2021-12-29T07:04:51.269560Z","shell.execute_reply.started":"2021-12-29T07:04:51.259333Z","shell.execute_reply":"2021-12-29T07:04:51.268660Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Inference","metadata":{"papermill":{"duration":0.041734,"end_time":"2021-10-27T20:24:59.084607","exception":false,"start_time":"2021-10-27T20:24:59.042873","status":"completed"},"tags":[]}},{"cell_type":"code","source":"# create dict key from bbox\ndef bbox_to_key(bbox):\n    return str(np.round(bbox, 6))\n\n# TTA inputs:\n# file: image to process\n# predictor_list: list of predictors to use, single or multiple for ensembling\n# aug_list: list of augmentations to perform. Augmentations must be \"bidirectional\" - applying twice will get back to original.\n#           Also augmentations must support image, bboxes and masks\ndef TTA(file, predictor_list, aug_list=[None]):\n    boxes = []\n    box_scores = []\n    masks = []\n    masks_lkup =[]\n    pclass = []\n    im = cv2.imread(file)\n    for predict in predictor_list:\n        for aug in aug_list:\n            # perform augmentations\n            if aug is not None:\n                transform = aug\n                ima = transform(image=im)['image']\n            else:\n                ima = im\n            # make prediction\n            pred = predict(ima)\n            h, w = pred['instances'].image_size[0], pred['instances'].image_size[1]\n            classes = pred['instances'].pred_classes.cpu().numpy()-1\n            if len(pclass) == 0:\n                pclass = classes\n            else:\n                pclass = np.concatenate((pclass, classes))\n            # get box predictions, and nomrmalize to 0-1 range\n            pred_boxes = [A.normalize_bbox(box, h, w) for box in pred['instances'].pred_boxes.tensor.cpu().numpy()]\n            # transform back to original\n            if aug is not None:\n                pred_boxes = transform(image=ima, bboxes=pred_boxes)['bboxes']\n            # get mask prediction\n            pred_masks = pred['instances'].pred_masks.cpu().numpy()*1\n            # transform back to original\n            if aug is not None:\n                pred_masks = transform(image=ima, masks=pred_masks)['masks']\n            # lookup table for bbox to mask index reference\n            pred_dict = {}\n            for i in range(len(pred_boxes)):\n                pred_dict[bbox_to_key(pred_boxes[i])] = i\n            # append results to list\n            boxes.append(np.array(pred_boxes))\n            box_scores.append(np.array(pred['instances'].scores.detach().cpu().numpy()))\n            masks.append(np.array(pred_masks, dtype=np.uint8))\n            masks_lkup.append(pred_dict)\n    \n            del pred, pred_boxes, pred_masks, ima, pred_dict\n    \n    del im\n    gc.collect()\n    predicted_class = stats.mode(pclass)[0][0]\n    return boxes, box_scores, masks, masks_lkup, predicted_class","metadata":{"execution":{"iopub.status.busy":"2021-12-29T07:04:02.981395Z","iopub.execute_input":"2021-12-29T07:04:02.981637Z","iopub.status.idle":"2021-12-29T07:04:02.997894Z","shell.execute_reply.started":"2021-12-29T07:04:02.981603Z","shell.execute_reply":"2021-12-29T07:04:02.996292Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predictor20 = MODELS[0]\nfrom detectron2.utils.visualizer import Visualizer","metadata":{"execution":{"iopub.status.busy":"2021-12-29T07:04:02.999387Z","iopub.execute_input":"2021-12-29T07:04:02.999852Z","iopub.status.idle":"2021-12-29T07:04:03.010159Z","shell.execute_reply.started":"2021-12-29T07:04:02.999814Z","shell.execute_reply":"2021-12-29T07:04:03.009409Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"TITLES = ['Original', 'Horizontal flip', 'Vertical flip', 'Rotation 180']\n\ndef plt_pred(file):\n    fig = plt.figure(figsize=(20,15))\n    im = cv2.imread(file)\n    # org\n    fig.add_subplot(2, 2, 1)\n    plt.tight_layout()\n    outputs = predictor20(im)\n    v = Visualizer(im[:, :, ::-1])\n    out = v.draw_instance_predictions(outputs[\"instances\"].to(\"cpu\"))\n    plt.title(TITLES[0])\n    plt.imshow(out.get_image()[:, :, ::-1]);\n    # flip horizontal/vertical/both\n    for i in range(1, -2, -1):\n        imh = cv2.flip(im, i)\n        fig.add_subplot(2, 2, 3-i)\n        plt.tight_layout()\n        outputs = predictor20(imh)\n        v = Visualizer(imh[:, :, ::-1])\n        out = v.draw_instance_predictions(outputs[\"instances\"].to(\"cpu\"))\n        plt.title(TITLES[2-i])\n        plt.imshow(out.get_image()[:, :, ::-1]);\n\nFILE = '../input/sartorius-cell-instance-segmentation/test/7ae19de7bc2a.png'\nplt_pred(FILE)","metadata":{"execution":{"iopub.status.busy":"2021-12-29T07:04:03.013483Z","iopub.execute_input":"2021-12-29T07:04:03.013743Z","iopub.status.idle":"2021-12-29T07:04:10.345654Z","shell.execute_reply.started":"2021-12-29T07:04:03.013706Z","shell.execute_reply":"2021-12-29T07:04:10.343226Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import albumentations as A\nimport gc\nfrom scipy import stats","metadata":{"execution":{"iopub.status.busy":"2021-12-29T07:04:10.347027Z","iopub.execute_input":"2021-12-29T07:04:10.347485Z","iopub.status.idle":"2021-12-29T07:04:11.920854Z","shell.execute_reply.started":"2021-12-29T07:04:10.347446Z","shell.execute_reply":"2021-12-29T07:04:11.920153Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"AUGMENTATIONS = [None, A.HorizontalFlip(p=1.0), A.VerticalFlip(p=1.0), A.Rotate(limit=(180,180), p=1.0)]\n\nimg_org = cv2.imread(FILE)\nboxes, box_scores, masks, masks_lkup, pred_class = TTA(FILE, [MODELS[0]], AUGMENTATIONS)\n\ndef show_boxes(im, boxes_list, h, w, color=(31, 119, 180), orig=False):\n    thickness = 2\n    idx = 0\n    if orig:\n        idx = 4\n    for i in range(len(boxes_list)):\n        x1 = int(h * boxes_list[i][idx])\n        y1 = int(w * boxes_list[i][idx+1])\n        x2 = int(h * boxes_list[i][idx+2])\n        y2 = int(w * boxes_list[i][idx+3])\n        cv2.rectangle(im, (x1, y1), (x2, y2), color, thickness)\n    return im\n\nfig = plt.figure(figsize=(20, 15))\ncolumns = 2\nrows = (len(AUGMENTATIONS)//columns) + (len(AUGMENTATIONS) % 2)\nfor i in range(1,len(AUGMENTATIONS)+1):\n    fig.add_subplot(rows, columns, i)\n    plt.tight_layout()\n    img = img_org\n    img = show_boxes(img, boxes[i-1], img.shape[1], img.shape[0])\n    plt.title(TITLES[i-1])\n    plt.imshow(img)\n    \nplt.show();","metadata":{"execution":{"iopub.status.busy":"2021-12-29T07:04:11.922163Z","iopub.execute_input":"2021-12-29T07:04:11.922613Z","iopub.status.idle":"2021-12-29T07:04:17.159942Z","shell.execute_reply.started":"2021-12-29T07:04:11.922572Z","shell.execute_reply":"2021-12-29T07:04:17.159171Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def show_masks(im, masks_list, h, w):\n    m = np.zeros((w,h), dtype=np.uint8)\n    for i in range(len(masks_list)):\n        m = np.logical_or(m, masks_list[i])\n    return im * np.dstack([m]*3)\n\nfig = plt.figure(figsize=(20, 15))\ncolumns = 2\nrows = (len(AUGMENTATIONS)//columns) + (len(AUGMENTATIONS) % 2)\nfor i in range(1,len(AUGMENTATIONS)+1):\n    fig.add_subplot(rows, columns, i)\n    plt.tight_layout()\n    img = img_org\n    plt.imshow(show_masks(img, masks[i-1], img.shape[1], img.shape[0]))\n    plt.title(TITLES[i-1])\nplt.show();","metadata":{"execution":{"iopub.status.busy":"2021-12-29T07:04:17.161259Z","iopub.execute_input":"2021-12-29T07:04:17.162294Z","iopub.status.idle":"2021-12-29T07:04:18.365123Z","shell.execute_reply.started":"2021-12-29T07:04:17.162252Z","shell.execute_reply":"2021-12-29T07:04:18.363980Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"subm_ids, subm_masks = [], []\nfor test_name in tqdm(test_names):\n    FILE = test_name\n    boxes, box_scores, masks, masks_lkup, pred_class = TTA(SUBM_PATH+'/'+FILE, [MODELS[0]], AUGMENTATIONS) #, MODELS[1]\n    encoded_masks=[]\n\n    for mask in masks:\n        enc_mask  = rle_encode(mask)\n        subm_masks.append(enc_mask)\n        subm_ids.append(test_name[:test_name.find('.')])","metadata":{"papermill":{"duration":0.673062,"end_time":"2021-10-27T20:24:59.800298","exception":false,"start_time":"2021-10-27T20:24:59.127236","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-12-29T07:04:18.367119Z","iopub.execute_input":"2021-12-29T07:04:18.367591Z","iopub.status.idle":"2021-12-29T07:04:30.265460Z","shell.execute_reply.started":"2021-12-29T07:04:18.367548Z","shell.execute_reply":"2021-12-29T07:04:30.264748Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pd.DataFrame({\n    'id': subm_ids, \n    'predicted': subm_masks\n}).to_csv('submission.csv', index=False)\npd.read_csv('submission.csv').head()\n","metadata":{"papermill":{"duration":0.07156,"end_time":"2021-10-27T20:24:59.914224","exception":false,"start_time":"2021-10-27T20:24:59.842664","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-12-29T07:04:30.266567Z","iopub.execute_input":"2021-12-29T07:04:30.267299Z","iopub.status.idle":"2021-12-29T07:04:30.321567Z","shell.execute_reply.started":"2021-12-29T07:04:30.267257Z","shell.execute_reply":"2021-12-29T07:04:30.320904Z"},"trusted":true},"execution_count":null,"outputs":[]}]}