{"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":"# [Sartorius - Cell Instance Segmentation](https://www.kaggle.com/c/petfinder-pawpularity-score)\n> Detect single neuronal cells in microscopy images\n\n![](https://storage.googleapis.com/kaggle-competitions/kaggle/30201/logos/header.png?t=2021-09-03-15-27-46)","metadata":{"papermill":{"duration":0.009854,"end_time":"2021-02-02T02:49:13.549001","exception":false,"start_time":"2021-02-02T02:49:13.539147","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"# Notebooks:\n* Train: [Sartorius: MMDetection [Train]](https://www.kaggle.com/awsaf49/sartorius-mmdetection-train)\n* Infer: [Sartorius: MMDetection [Infer]](https://www.kaggle.com/awsaf49/sartorius-mmdetection-infer)","metadata":{}},{"cell_type":"markdown","source":"# Please Upvote If you find this notebook Useful :)","metadata":{}},{"cell_type":"markdown","source":"# Install Libraries","metadata":{}},{"cell_type":"code","source":"!rsync -a ../input/mmdetection-v280/mmdetection ../\n!pip install ../input/mmdetection-v280/src/mmdet-2.8.0/mmdet-2.8.0/\n!pip install ../input/mmdetection-v280/src/mmpycocotools-12.0.3/mmpycocotools-12.0.3/\n!pip install ../input/mmdetection-v280/src/addict-2.4.0-py3-none-any.whl\n!pip install ../input/mmdetection-v280/src/yapf-0.30.0-py2.py3-none-any.whl\n!pip install ../input/mmdetection-v280/src/mmcv_full-1.2.6-cp37-cp37m-manylinux1_x86_64.whl","metadata":{"_kg_hide-output":true,"papermill":{"duration":151.034626,"end_time":"2021-02-02T02:51:44.592784","exception":false,"start_time":"2021-02-02T02:49:13.558158","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-10-24T08:47:02.384326Z","iopub.execute_input":"2021-10-24T08:47:02.384659Z","iopub.status.idle":"2021-10-24T08:49:30.043628Z","shell.execute_reply.started":"2021-10-24T08:47:02.384631Z","shell.execute_reply":"2021-10-24T08:49:30.042566Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport cupy as cp\nfrom glob import glob\nimport os\nimport cv2\nfrom tqdm.notebook import tqdm\nimport pickle\nfrom itertools import groupby\nfrom pycocotools import mask as mutils\nfrom pycocotools import _mask as coco_mask\nimport matplotlib.pyplot as plt\nimport os\nimport base64\nimport typing as t\nimport zlib\nimport random\nrandom.seed(0)\n","metadata":{"papermill":{"duration":0.216599,"end_time":"2021-02-02T02:51:44.826551","exception":false,"start_time":"2021-02-02T02:51:44.609952","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-10-24T08:49:30.047025Z","iopub.execute_input":"2021-10-24T08:49:30.0474Z","iopub.status.idle":"2021-10-24T08:49:31.953502Z","shell.execute_reply.started":"2021-10-24T08:49:30.047361Z","shell.execute_reply":"2021-10-24T08:49:31.952716Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Meta Data","metadata":{}},{"cell_type":"code","source":"conf_name = \"mask_rcnn_s50_fpn_syncbn-backbone+head_mstrain_1x_coco\"\nmodel_name = 'epoch_10'\nROOT = '../input/sartorius-cell-instance-segmentation'\ntrain_or_test = 'test'\nTHR = 0.50\n# Test Data\ndf  = pd.DataFrame(glob(ROOT+f'/{train_or_test}/*'), columns=['image_path'])\ndf['id'] = df.image_path.map(lambda x: x.split('/')[-1].split('.')[0])\n# df= df.sample(frac=20, replace=True)\ndisplay(df.head())","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:49:31.954753Z","iopub.execute_input":"2021-10-24T08:49:31.955066Z","iopub.status.idle":"2021-10-24T08:49:31.984885Z","shell.execute_reply.started":"2021-10-24T08:49:31.955034Z","shell.execute_reply":"2021-10-24T08:49:31.984192Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Helper Function","metadata":{"papermill":{"duration":0.016707,"end_time":"2021-02-02T02:51:44.860458","exception":false,"start_time":"2021-02-02T02:51:44.843751","status":"completed"},"tags":[]}},{"cell_type":"code","source":"def encode_binary_mask(mask: np.ndarray) -> t.Text:\n    \"\"\"Converts a binary mask into OID challenge encoding ascii text.\"\"\"\n    # check input mask --\n    if mask.dtype != np.bool:\n        raise ValueError(\n            \"encode_binary_mask expects a binary mask, received dtype == %s\" %\n            mask.dtype)\n\n    mask = np.squeeze(mask)\n    if len(mask.shape) != 2:\n        raise ValueError(\n            \"encode_binary_mask expects a 2d mask, received shape == %s\" %\n            mask.shape)\n\n    # convert input mask to expected COCO API input --\n    mask_to_encode = mask.reshape(mask.shape[0], mask.shape[1], 1)\n    mask_to_encode = mask_to_encode.astype(np.uint8)\n    mask_to_encode = np.asfortranarray(mask_to_encode)\n\n    # RLE encode mask --\n    encoded_mask = coco_mask.encode(mask_to_encode)[0][\"counts\"]\n\n    # compress and base64 encoding --\n    binary_str = zlib.compress(encoded_mask, zlib.Z_BEST_COMPRESSION)\n    base64_str = base64.b64encode(binary_str)\n    return base64_str.decode()\n\ndef mask2rle(msk):\n    '''\n    img: numpy array, 1 - mask, 0 - background\n    Returns run length as string formated\n    '''\n    msk    = cp.array(msk)\n    pixels = msk.flatten()\n    pad    = cp.array([0])\n    pixels = cp.concatenate([pad, pixels, pad])\n    runs   = cp.where(pixels[1:] != pixels[:-1])[0] + 1\n    runs[1::2] -= runs[::2]\n    return ' '.join(str(x) for x in runs)\n\ndef rle2mask(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 = 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 read_img(image_id, train_or_test='train', image_size=None):\n    filename = f'{ROOT}/{train_or_test}/{image_id}.png'\n    assert os.path.exists(filename), f'not found {filename}'\n    img = cv2.imread(filename, cv2.IMREAD_UNCHANGED)\n    if image_size is not None:\n        img = cv2.resize(img, (image_size, image_size))\n    if img.dtype == 'uint16':\n        img = (img/256).astype('uint8')\n    return img\n\ndef load_RGBY_image(image_id, train_or_test='train', image_size=None):\n    img = read_img(image_id, train_or_test, image_size)\n    stacked_images = np.stack([img for _ in range(3)],axis=-1)\n    return stacked_images\n\ndef print_masked_img(image_id, mask):\n    img   = load_RGBY_image(image_id, train_or_test)[...,0]\n    clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8,8))\n    img2  = clahe.apply(img)\n    img3  = cv2.equalizeHist(img)\n    img   = np.stack([img, img2, img3],axis=-1)\n    \n    plt.figure(figsize=(15, 15))\n    plt.subplot(1, 3, 1)\n    plt.imshow(img)\n    plt.title('Image')\n    plt.axis('off')\n    \n    plt.subplot(1, 3, 2)\n    plt.imshow(mask,cmap='inferno')\n    plt.title('Mask')\n    plt.axis('off')\n    \n    plt.subplot(1, 3, 3)\n    plt.imshow(img)\n    plt.imshow(mask, alpha=0.4, cmap='inferno')\n    plt.title('Image + Mask')\n    plt.axis('off')\n    plt.tight_layout()\n    plt.show()","metadata":{"papermill":{"duration":0.033138,"end_time":"2021-02-02T02:51:44.910682","exception":false,"start_time":"2021-02-02T02:51:44.877544","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-10-24T08:49:31.987653Z","iopub.execute_input":"2021-10-24T08:49:31.987889Z","iopub.status.idle":"2021-10-24T08:49:32.008491Z","shell.execute_reply.started":"2021-10-24T08:49:31.987866Z","shell.execute_reply":"2021-10-24T08:49:32.007749Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Generate Data for **MMDet**","metadata":{"papermill":{"duration":0.016528,"end_time":"2021-02-02T02:51:44.94507","exception":false,"start_time":"2021-02-02T02:51:44.928542","status":"completed"},"tags":[]}},{"cell_type":"code","source":"out_image_dir = f'../work/mmdet_{train_or_test}/'\n!mkdir -p {out_image_dir}\n\nannos = []\nfor idx in tqdm(range(len(df))):\n    image_id = df.iloc[idx]['id']\n    img = load_RGBY_image(image_id, train_or_test)\n    \n    cv2.imwrite(f'{out_image_dir}/{image_id}.png', img)\n    ann = {\n        'filename': image_id+'.png',\n        'width': img.shape[1],\n        'height': img.shape[0],\n        'ann': {\n            'bboxes': None,\n            'labels': None,\n            'masks': None\n        }\n    }\n    annos.append(ann)\n    \nwith open(f'../work/mmdet_tst.pkl', 'wb') as f:\n    pickle.dump(annos, f)","metadata":{"lines_to_next_cell":2,"papermill":{"duration":2.240857,"end_time":"2021-02-02T02:51:47.202634","exception":false,"start_time":"2021-02-02T02:51:44.961777","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-10-24T08:49:32.012708Z","iopub.execute_input":"2021-10-24T08:49:32.012973Z","iopub.status.idle":"2021-10-24T08:49:32.950874Z","shell.execute_reply.started":"2021-10-24T08:49:32.012939Z","shell.execute_reply":"2021-10-24T08:49:32.949907Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Custom Config","metadata":{"papermill":{"duration":0.018048,"end_time":"2021-02-02T02:51:47.239699","exception":false,"start_time":"2021-02-02T02:51:47.221651","status":"completed"},"tags":[]}},{"cell_type":"code","source":"!cp -r /kaggle/input/sartorius-mmdet-config-ds/sartorius /kaggle/mmdetection/configs/sartorius","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:49:32.953085Z","iopub.execute_input":"2021-10-24T08:49:32.953673Z","iopub.status.idle":"2021-10-24T08:49:33.654526Z","shell.execute_reply.started":"2021-10-24T08:49:32.953635Z","shell.execute_reply":"2021-10-24T08:49:33.653132Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# I just made following config files based on default mask_rcnn.\n# The main changes are CustomDataset, num_classes, data path, etc.\n# Other than that, I used it as is for mmdetection.\n!ls -l ../mmdetection/configs/sartorius/","metadata":{"papermill":{"duration":0.652169,"end_time":"2021-02-02T02:51:47.910085","exception":false,"start_time":"2021-02-02T02:51:47.257916","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-10-24T08:49:33.65644Z","iopub.execute_input":"2021-10-24T08:49:33.656831Z","iopub.status.idle":"2021-10-24T08:49:34.317653Z","shell.execute_reply.started":"2021-10-24T08:49:33.65679Z","shell.execute_reply":"2021-10-24T08:49:34.316584Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Config: `Base Model`\n* **Num Classes** \n* **Score-Theshold**\n* **IoU**","metadata":{}},{"cell_type":"code","source":"%%writefile /kaggle/mmdetection/configs/sartorius/mask_rcnn_r50_fpn.py\n\n# model settings\nmodel = dict(\n    type='MaskRCNN',\n    pretrained='torchvision://resnet50',\n    backbone=dict(\n        type='ResNet',\n        depth=50,\n        num_stages=4,\n        out_indices=(0, 1, 2, 3),\n        frozen_stages=1,\n        norm_cfg=dict(type='BN', requires_grad=True),\n        norm_eval=True,\n        style='pytorch'),\n    neck=dict(\n        type='FPN',\n        in_channels=[256, 512, 1024, 2048],\n        out_channels=256,\n        num_outs=5),\n    rpn_head=dict(\n        type='RPNHead',\n        in_channels=256,\n        feat_channels=256,\n        anchor_generator=dict(\n            type='AnchorGenerator',\n            scales=[8],\n            ratios=[0.5, 1.0, 2.0],\n            strides=[4, 8, 16, 32, 64]),\n        bbox_coder=dict(\n            type='DeltaXYWHBBoxCoder',\n            target_means=[.0, .0, .0, .0],\n            target_stds=[1.0, 1.0, 1.0, 1.0]),\n        loss_cls=dict(\n            type='CrossEntropyLoss', use_sigmoid=True, loss_weight=1.0),\n        loss_bbox=dict(type='L1Loss', loss_weight=1.0)),\n    roi_head=dict(\n        type='StandardRoIHead',\n        bbox_roi_extractor=dict(\n            type='SingleRoIExtractor',\n            roi_layer=dict(type='RoIAlign', output_size=7, sampling_ratio=0),\n            out_channels=256,\n            featmap_strides=[4, 8, 16, 32]),\n        bbox_head=dict(\n            type='Shared2FCBBoxHead',\n            in_channels=256,\n            fc_out_channels=1024,\n            roi_feat_size=7,\n            num_classes=1, # number of class\n            bbox_coder=dict(\n                type='DeltaXYWHBBoxCoder',\n                target_means=[0., 0., 0., 0.],\n                target_stds=[0.1, 0.1, 0.2, 0.2]),\n            reg_class_agnostic=False,\n            loss_cls=dict(\n                type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0),\n            loss_bbox=dict(type='L1Loss', loss_weight=1.0)),\n        mask_roi_extractor=dict(\n            type='SingleRoIExtractor',\n            roi_layer=dict(type='RoIAlign', output_size=14, sampling_ratio=0),\n            out_channels=256,\n            featmap_strides=[4, 8, 16, 32]),\n        mask_head=dict(\n            type='FCNMaskHead',\n            num_convs=4,\n            in_channels=256,\n            conv_out_channels=256,\n            num_classes=1, # number of class\n            loss_mask=dict(\n                type='CrossEntropyLoss', use_mask=True, loss_weight=1.0))))\n# model training and testing settings\ntrain_cfg = dict(\n    rpn=dict(\n        assigner=dict(\n            type='MaxIoUAssigner',\n            pos_iou_thr=0.7,\n            neg_iou_thr=0.3,\n            min_pos_iou=0.3,\n            match_low_quality=True,\n            ignore_iof_thr=-1),\n        sampler=dict(\n            type='RandomSampler',\n            num=256,\n            pos_fraction=0.5,\n            neg_pos_ub=-1,\n            add_gt_as_proposals=False),\n        allowed_border=-1,\n        pos_weight=-1,\n        debug=False),\n    rpn_proposal=dict(\n        nms_across_levels=False,\n        nms_pre=2000,\n        nms_post=1000,\n        max_num=1000,\n        nms_thr=0.7,\n        min_bbox_size=0),\n    rcnn=dict(\n        assigner=dict(\n            type='MaxIoUAssigner',\n            pos_iou_thr=0.5,\n            neg_iou_thr=0.5,\n            min_pos_iou=0.5,\n            match_low_quality=True,\n            ignore_iof_thr=-1),\n        sampler=dict(\n            type='RandomSampler',\n            num=512,\n            pos_fraction=0.25,\n            neg_pos_ub=-1,\n            add_gt_as_proposals=True),\n        mask_size=28,\n        pos_weight=-1,\n        debug=False))\ntest_cfg = dict(\n    rpn=dict(\n        nms_across_levels=False,\n        nms_pre=1000,\n        nms_post=1000,\n        max_num=1000,\n        nms_thr=0.7,\n        min_bbox_size=0),\n    rcnn=dict(\n        score_thr=0.05,\n        nms=dict(type='nms', iou_threshold=0.5),\n        max_per_img=200,\n        mask_thr_binary=0.5))","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:49:34.319501Z","iopub.execute_input":"2021-10-24T08:49:34.319871Z","iopub.status.idle":"2021-10-24T08:49:34.328629Z","shell.execute_reply.started":"2021-10-24T08:49:34.319822Z","shell.execute_reply":"2021-10-24T08:49:34.327456Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Config: `Model` & `Augmentation`\n* **Augmentation** \n    * **Flip**\n    * **Multi-Scale**\n* **Batch Size**\n* **IoU**","metadata":{}},{"cell_type":"code","source":"%%writefile /kaggle/mmdetection/configs/sartorius/mask_rcnn_s50_fpn_syncbn-backbone+head_mstrain_1x_coco.py\n_base_ = 'mask_rcnn_r50_fpn_1x_coco.py'\nnorm_cfg = dict(type='SyncBN', requires_grad=True)\nmodel = dict(\n    pretrained='open-mmlab://resnest50',\n    backbone=dict(\n        type='ResNeSt',\n        stem_channels=64,\n        depth=50,\n        radix=2,\n        reduction_factor=4,\n        avg_down_stride=True,\n        num_stages=4,\n        out_indices=(0, 1, 2, 3),\n        frozen_stages=1,\n        norm_cfg=norm_cfg,\n        norm_eval=False,\n        style='pytorch'),\n    roi_head=dict(\n        bbox_head=dict(\n            type='Shared4Conv1FCBBoxHead',\n            conv_out_channels=256,\n            norm_cfg=norm_cfg),\n        mask_head=dict(norm_cfg=norm_cfg)))\n# # use ResNeSt img_norm\nimg_norm_cfg = dict(\n    mean=[123.68, 116.779, 103.939], std=[58.393, 57.12, 57.375], to_rgb=True)\ntrain_pipeline = [\n    dict(type='LoadImageFromFile'),\n    dict(type='LoadAnnotations', with_bbox=True, with_mask=True, poly2mask=True),\n    dict(type='Resize', img_scale=[(1333, 1333), (1280, 1280), (1024, 1024)], multiscale_mode='value',keep_ratio=True),\n    dict(type='RandomFlip', direction=['horizontal', 'vertical'], flip_ratio=0.5),\n    dict(type='Normalize', **img_norm_cfg),\n    dict(type='Pad', size_divisor=32),\n    dict(type='DefaultFormatBundle'),\n    dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels', 'gt_masks']),\n]\ntest_pipeline = [\n    dict(type='LoadImageFromFile'),\n    dict(type='MultiScaleFlipAug',\n        img_scale=[(1333, 1333), (1280, 1280), (1024, 1024)],\n        flip=True,\n        transforms=[\n            dict(type='Resize', keep_ratio=True),\n            dict(type='RandomFlip',direction=['horizontal','vertical']),\n            dict(type='Normalize', **img_norm_cfg),\n            dict(type='Pad', size_divisor=32),\n            dict(type='ImageToTensor', keys=['img']),\n            dict(type='Collect', keys=['img']),\n        ])\n]\ndata = dict(\n    samples_per_gpu=2, # batch size\n    train=dict(pipeline=train_pipeline),\n    val=dict(pipeline=test_pipeline),\n    test=dict(pipeline=test_pipeline))","metadata":{"execution":{"iopub.status.busy":"2021-10-24T09:17:46.268245Z","iopub.execute_input":"2021-10-24T09:17:46.268784Z","iopub.status.idle":"2021-10-24T09:17:46.27711Z","shell.execute_reply.started":"2021-10-24T09:17:46.268739Z","shell.execute_reply":"2021-10-24T09:17:46.276039Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Infer","metadata":{}},{"cell_type":"code","source":"config = f'configs/sartorius/{conf_name}.py'\nmodel_file = f'../input/sartorius-mmdetection-train-ds/work_dir/{model_name}.pth'\nresult_pkl = f'../work/{model_name}.pkl'\nadditional_conf = '--cfg-options'\nadditional_conf += f' test_cfg.rcnn.score_thr={THR}'\ncmd = f'python tools/test.py {config} {model_file} --out {result_pkl} {additional_conf}'\n!cd ../mmdetection; {cmd}\nresult = pickle.load(open('../mmdetection/'+result_pkl, 'rb'))","metadata":{"papermill":{"duration":22.227907,"end_time":"2021-02-02T02:52:10.157446","exception":false,"start_time":"2021-02-02T02:51:47.929539","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-10-24T09:16:52.392185Z","iopub.execute_input":"2021-10-24T09:16:52.392532Z","iopub.status.idle":"2021-10-24T09:17:08.945661Z","shell.execute_reply.started":"2021-10-24T09:16:52.392501Z","shell.execute_reply":"2021-10-24T09:17:08.944754Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Visualization","metadata":{"papermill":{"duration":0.020518,"end_time":"2021-02-02T02:52:10.198232","exception":false,"start_time":"2021-02-02T02:52:10.177714","status":"completed"},"tags":[]}},{"cell_type":"code","source":"for ii in range(3):\n    image_id = annos[ii]['filename'].replace('.jpg','').replace('.png','')\n    for class_id in range(1):\n        #print(ii,class_id,len(result[ii][0][class_id]), len(result[ii][1][class_id]))\n        bbs = result[ii][0][class_id]\n        sgs = result[ii][1][class_id]\n        for idx, (bb, sg) in enumerate(zip(bbs,sgs)):\n            box = bb[:4]\n            cnf = bb[4]\n            h = sg['size'][0]\n            w = sg['size'][0]\n            if cnf > 0.1:\n#                 print(f'class_id:{class_id}, image_id:{image_id}, confidence:{cnf}')\n                if idx==0:\n                    mask = mutils.decode(sg)\n                else:\n                    mask+=mutils.decode(sg)\n        print_masked_img(image_id, mask)","metadata":{"execution":{"iopub.status.busy":"2021-10-24T09:17:08.949356Z","iopub.execute_input":"2021-10-24T09:17:08.94963Z","iopub.status.idle":"2021-10-24T09:17:10.362699Z","shell.execute_reply.started":"2021-10-24T09:17:08.949604Z","shell.execute_reply":"2021-10-24T09:17:10.358408Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Fix-Overlap\n<pre>\nThe metric checks that the pairs are sorted, positive, and the decoded pixel values are not duplicated. It also checks that no two predicted masks for the same image are overlapping.\n</pre>","metadata":{}},{"cell_type":"code","source":"import cupy as cp\nimport gc\n\ndef one_hot(y, num_classes, dtype=cp.uint8): # GPU\n    y = cp.array(y, dtype='int')\n    input_shape = y.shape\n    if input_shape and input_shape[-1] == 1 and len(input_shape) > 1:\n        input_shape = tuple(input_shape[:-1])\n    y = y.ravel()\n    if not num_classes:\n        num_classes = cp.max(y) + 1\n    n = y.shape[0]\n    categorical = cp.zeros((n, num_classes), dtype=dtype)\n    categorical[cp.arange(n), y] = 1\n    output_shape = input_shape + (num_classes,)\n    categorical = cp.reshape(categorical, output_shape)\n    return categorical\n\ndef fix_overlap(msk): # GPU\n    \"\"\"\n    Args:\n        mask: multi-channel mask, each channel is an instance of cell, shape:(520,704,None)\n    Returns:\n        multi-channel mask with non-overlapping values, shape:(520,704,None)\n    \"\"\"\n    msk = cp.array(msk)\n    msk = cp.pad(msk, [[0,0],[0,0],[1,0]]) # add dummy mask for background\n    ins_len = msk.shape[-1]\n    msk = cp.argmax(msk,axis=-1)# convert multi channel mask to single channel mask, argmax will remove overlap\n    msk = one_hot(msk, num_classes=ins_len) # back to multi-channel mask, some instance might get removed\n    msk = msk[...,1:] # remove background mask\n    msk = msk[...,cp.any(msk, axis=(0,1))] # remove all-zero masks\n    #assert np.prod(msk, axis=-1).sum()==0 # overlap check, will raise error if there is overlap\n    return msk\n\ndef check_overlap(msk):\n    msk = msk.astype(cp.bool).astype(cp.uint8) # binary mask\n    return cp.any(cp.sum(msk, axis=-1)>1) # only one channgel will contain value","metadata":{"execution":{"iopub.status.busy":"2021-10-24T00:41:30.95874Z","iopub.execute_input":"2021-10-24T00:41:30.95938Z","iopub.status.idle":"2021-10-24T00:41:30.972139Z","shell.execute_reply.started":"2021-10-24T00:41:30.959329Z","shell.execute_reply":"2021-10-24T00:41:30.971317Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Submission","metadata":{"papermill":{"duration":0.371128,"end_time":"2021-02-02T02:54:07.345079","exception":false,"start_time":"2021-02-02T02:54:06.973951","status":"completed"},"tags":[]}},{"cell_type":"code","source":"data = []\nfor ii in tqdm(range(len(annos))):\n    image_id = annos[ii]['filename'].replace('.jpg','').replace('.png','')\n    mask = []\n    for class_id in range(1):\n        bbs = result[ii][0][class_id]\n        sgs = result[ii][1][class_id]\n        for bb, sg in zip(bbs,sgs):\n            box = bb[:4]\n            cnf = bb[4]\n            h = sg['size'][0]\n            w = sg['size'][1]\n            #convert coco format to kaggle format\n            mask.append(cp.array(mutils.decode(sg)))\n        mask = cp.stack(mask, axis=-1)\n        if check_overlap(mask): # if mask instances have overlap then fix it\n            mask = fix_overlap(mask)\n        for idx in range(mask.shape[-1]):\n            mask_ins = mask[...,idx]\n            rle  = mask2rle(mask_ins)\n            data.append([image_id, rle])\n#             del mask_ins\n#             gc.collect()\n        del mask, rle, sgs, bbs\n        gc.collect()\npred_df = pd.DataFrame(data, columns=['id','predicted'])","metadata":{"papermill":{"duration":1.168848,"end_time":"2021-02-02T02:54:08.874759","exception":false,"start_time":"2021-02-02T02:54:07.705911","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-10-21T05:45:04.895876Z","iopub.execute_input":"2021-10-21T05:45:04.896206Z","iopub.status.idle":"2021-10-21T05:45:13.078684Z","shell.execute_reply.started":"2021-10-21T05:45:04.896174Z","shell.execute_reply":"2021-10-21T05:45:13.07781Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub_df  = pd.read_csv('../input/sartorius-cell-instance-segmentation/sample_submission.csv')\ndel sub_df['predicted']\nsub_df = sub_df.merge(pred_df, on='id', how='left')\nsub_df.to_csv('submission.csv',index=False)\nsub_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-10-21T05:45:16.308227Z","iopub.execute_input":"2021-10-21T05:45:16.308578Z","iopub.status.idle":"2021-10-21T05:45:16.569743Z","shell.execute_reply.started":"2021-10-21T05:45:16.308546Z","shell.execute_reply":"2021-10-21T05:45:16.568717Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!ls -l ","metadata":{"papermill":{"duration":1.006478,"end_time":"2021-02-02T02:54:10.234273","exception":false,"start_time":"2021-02-02T02:54:09.227795","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-10-19T18:32:26.171528Z","iopub.execute_input":"2021-10-19T18:32:26.171966Z","iopub.status.idle":"2021-10-19T18:32:26.862491Z","shell.execute_reply.started":"2021-10-19T18:32:26.171928Z","shell.execute_reply":"2021-10-19T18:32:26.86149Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Reference\n* [mmdetection for segmentation [inference]](https://www.kaggle.com/its7171/mmdetection-for-segmentation-inference) by @its7171","metadata":{}},{"cell_type":"markdown","source":"# Please Upvote If you find this notebook Useful :)","metadata":{}}]}