{"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":"# **Install MMDetection**","metadata":{"papermill":{"duration":0.034808,"end_time":"2021-10-28T17:34:14.981619","exception":false,"start_time":"2021-10-28T17:34:14.946811","status":"completed"},"tags":[]}},{"cell_type":"code","source":"# All you need to do is upload your configuration file and model file!\n","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from glob import glob\ntest_dir = glob('/kaggle/input/sartorius-cell-instance-segmentation/test/*')\nif len(test_dir) != 3:\n    debug = False\nelse:\n    debug = True\nprint(f\"debug={debug}\")","metadata":{"execution":{"iopub.status.busy":"2021-12-09T01:54:34.732812Z","iopub.execute_input":"2021-12-09T01:54:34.733561Z","iopub.status.idle":"2021-12-09T01:54:34.77811Z","shell.execute_reply.started":"2021-12-09T01:54:34.733437Z","shell.execute_reply":"2021-12-09T01:54:34.777436Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install '/kaggle/input/pytorch-170-cuda-toolkit-110221/torch-1.7.0+cu110-cp37-cp37m-linux_x86_64.whl' --no-deps\n!pip install '/kaggle/input/pytorch-170-cuda-toolkit-110221/torchvision-0.8.1+cu110-cp37-cp37m-linux_x86_64.whl' --no-deps\n!pip install '/kaggle/input/pytorch-170-cuda-toolkit-110221/torchaudio-0.7.0-cp37-cp37m-linux_x86_64.whl' --no-deps","metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","papermill":{"duration":127.55412,"end_time":"2021-10-28T17:36:22.571091","exception":false,"start_time":"2021-10-28T17:34:15.016971","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-12-09T01:54:38.47243Z","iopub.execute_input":"2021-12-09T01:54:38.473167Z","iopub.status.idle":"2021-12-09T01:56:32.824458Z","shell.execute_reply.started":"2021-12-09T01:54:38.473131Z","shell.execute_reply":"2021-12-09T01:56:32.823587Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install '/kaggle/input/mmdetectionv2140/addict-2.4.0-py3-none-any.whl' --no-deps\n!pip install '/kaggle/input/mmdetectionv2140/yapf-0.31.0-py2.py3-none-any.whl' --no-deps\n!pip install '/kaggle/input/mmdetectionv2140/terminal-0.4.0-py3-none-any.whl' --no-deps\n!pip install '/kaggle/input/mmdetectionv2140/terminaltables-3.1.0-py3-none-any.whl' --no-deps\n!pip install '/kaggle/input/mmdetectionv2140/mmcv_full-1_3_8-cu110-torch1_7_0/mmcv_full-1.3.8-cp37-cp37m-manylinux1_x86_64.whl' --no-deps\n!pip install '/kaggle/input/mmdetectionv2140/pycocotools-2.0.2/pycocotools-2.0.2' --no-deps\n!pip install '/kaggle/input/mmdetectionv2140/mmpycocotools-12.0.3/mmpycocotools-12.0.3' --no-deps\n\n!rm -rf mmdetection\n\n!cp -r ../input/edited-mmdetection /kaggle/working/\n!mv /kaggle/working/edited-mmdetection /kaggle/working/mmdetection\n%cd /kaggle/working/mmdetection\n!pip install -e .","metadata":{"papermill":{"duration":222.21755,"end_time":"2021-10-28T17:40:04.826612","exception":false,"start_time":"2021-10-28T17:36:22.609062","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-12-09T01:58:10.168369Z","iopub.execute_input":"2021-12-09T01:58:10.168858Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Import Libraries**","metadata":{"papermill":{"duration":0.098388,"end_time":"2021-10-28T17:40:04.980758","exception":false,"start_time":"2021-10-28T17:40:04.88237","status":"completed"},"tags":[]}},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torchvision.transforms as transforms\nimport torch.nn.functional as F\nimport sklearn\nimport torchvision\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.preprocessing import LabelEncoder\nimport numpy as np\nimport cupy as cp\nimport gc\nimport pandas as pd\nimport os\nimport matplotlib.pyplot as plt\nimport PIL\nimport json\nfrom PIL import Image, ImageEnhance\nimport albumentations as A\nimport mmdet\nimport mmcv\nfrom albumentations.pytorch import ToTensorV2\nimport seaborn as sns\nimport glob\nfrom pathlib import Path\nimport pycocotools\nfrom pycocotools import mask\nimport numpy.random\nimport random\nimport cv2\nimport re\nimport shutil\nfrom mmdet.datasets import build_dataset\nfrom mmdet.models import build_detector\nfrom mmdet.apis import train_detector\nfrom mmdet.apis import inference_detector, init_detector, show_result_pyplot, set_random_seed\nfrom glob import glob\nfrom tqdm.notebook import tqdm","metadata":{"papermill":{"duration":28.752894,"end_time":"2021-10-28T17:40:33.786328","exception":false,"start_time":"2021-10-28T17:40:05.033434","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-11-28T02:13:06.177775Z","iopub.execute_input":"2021-11-28T02:13:06.178079Z","iopub.status.idle":"2021-11-28T02:13:31.322836Z","shell.execute_reply.started":"2021-11-28T02:13:06.178014Z","shell.execute_reply":"2021-11-28T02:13:31.322019Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%cd ..","metadata":{"papermill":{"duration":0.077806,"end_time":"2021-10-28T17:40:33.91703","exception":false,"start_time":"2021-10-28T17:40:33.839224","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-11-28T02:13:31.325252Z","iopub.execute_input":"2021-11-28T02:13:31.325525Z","iopub.status.idle":"2021-11-28T02:13:31.33261Z","shell.execute_reply.started":"2021-11-28T02:13:31.325489Z","shell.execute_reply":"2021-11-28T02:13:31.331942Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Helper Functions**","metadata":{"papermill":{"duration":0.052766,"end_time":"2021-10-28T17:40:34.030284","exception":false,"start_time":"2021-10-28T17:40:33.977518","status":"completed"},"tags":[]}},{"cell_type":"code","source":"def rle_decode(mask_rle, shape):\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)\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)\ndef rle_encoding(x):\n    dots = np.where(x.flatten() == 1)[0]\n    run_lengths = []\n    prev = -2\n    for b in dots:\n        if (b>prev+1): run_lengths.extend((b + 1, 0))\n        run_lengths[-1] += 1\n        prev = b\n    return ' '.join(map(str, run_lengths))\ndef get_mask_from_result(result):\n    d = {True : 1, False : 0}\n    u,inv = np.unique(result,return_inverse = True)\n    mk = cp.array([d[x] for x in u])[inv].reshape(result.shape)\n#     print(mk.shape)\n    return mk\ndef does_overlap(mask, other_masks):\n    for other_mask in other_masks:\n        if np.sum(np.logical_and(mask, other_mask)) > 0:\n            return True\n    return False\n\n\ndef remove_overlapping_pixels(mask, other_masks):\n    for other_mask in other_masks:\n        if np.sum(np.logical_and(mask, other_mask)) > 0:\n            print(\"Overlap detected\")\n            mask[np.logical_and(mask, other_mask)] = 0\n    return mask\ndef get_img_and_mask(img_path, annotation, width, height):\n    \"\"\" Capture the relevant image array as well as the image mask \"\"\"\n    img_mask = np.zeros((height, width), dtype=np.uint8)\n    for i, annot in enumerate(annotation): \n        img_mask = np.where(rle_decode(annot, (height, width))!=0, i, img_mask)\n    img = cv2.imread(img_path)[..., ::-1]\n    return img[..., 0], img_mask\n\ndef plot_img_and_mask(img, mask, invert_img=True, boost_contrast=True):\n    \"\"\" Function to take an image and the corresponding mask and plot\n    \n    Args:\n        img (np.arr): 1 channel np arr representing the image of cellular structures\n        mask (np.arr): 1 channel np arr representing the instance masks (incrementing by one)\n        invert_img (bool, optional): Whether or not to invert the base image\n        boost_contrast (bool, optional): Whether or not to boost contrast of the base image\n        \n    Returns:\n        None; Plots the two arrays and overlays them to create a merged image\n    \"\"\"\n    plt.figure(figsize=(20,10))\n    \n    plt.subplot(1,3,1)\n    _img = np.tile(np.expand_dims(img, axis=-1), 3)\n    \n    # Flip black-->white ... white-->black\n    if invert_img:\n        _img = _img.max()-_img\n        \n    if boost_contrast:\n        _img = np.asarray(ImageEnhance.Contrast(Image.fromarray(_img)).enhance(16))\n        \n    plt.imshow(_img)\n    plt.axis(False)\n    plt.title(\"Cell Image\", fontweight=\"bold\")\n    \n    plt.subplot(1,3,2)\n    _mask = np.zeros_like(_img)\n    _mask[..., 0] = mask\n    plt.imshow(mask, cmap='rainbow')\n    plt.axis(False)\n    plt.title(\"Instance Segmentation Mask\", fontweight=\"bold\")\n    \n    merged = cv2.addWeighted(_img, 0.75, np.clip(_mask, 0, 1)*255, 0.25, 0.0,)\n    plt.subplot(1,3,3)\n    plt.imshow(merged)\n    plt.axis(False)\n    plt.title(\"Cell Image w/ Instance Segmentation Mask Overlay\", fontweight=\"bold\")\n    \n    plt.tight_layout()\n    plt.show()","metadata":{"papermill":{"duration":0.066347,"end_time":"2021-10-28T17:40:34.262446","exception":false,"start_time":"2021-10-28T17:40:34.196099","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-11-28T02:13:31.356979Z","iopub.execute_input":"2021-11-28T02:13:31.357464Z","iopub.status.idle":"2021-11-28T02:13:31.368122Z","shell.execute_reply.started":"2021-11-28T02:13:31.35743Z","shell.execute_reply":"2021-11-28T02:13:31.367426Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Model**","metadata":{"papermill":{"duration":0.053488,"end_time":"2021-10-28T17:40:34.718633","exception":false,"start_time":"2021-10-28T17:40:34.665145","status":"completed"},"tags":[]}},{"cell_type":"code","source":"config_file = '../input/cell-pt/job5000_cascade_mask_rcnn_x101_64x4d_fpn_20e_coco.py'\ncheckpoint_file = '../input/cell-pt/adam/epoch_20.pth'\nmodel = init_detector(config_file, checkpoint_file, device='cuda:0')","metadata":{"papermill":{"duration":0.083816,"end_time":"2021-10-28T17:40:34.857025","exception":false,"start_time":"2021-10-28T17:40:34.773209","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-11-28T02:25:45.757753Z","iopub.execute_input":"2021-11-28T02:25:45.758636Z","iopub.status.idle":"2021-11-28T02:25:45.802445Z","shell.execute_reply.started":"2021-11-28T02:25:45.758591Z","shell.execute_reply":"2021-11-28T02:25:45.801717Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"masks = []\nfiles = []\nconfidence_thresholds = {0: 0.25, 1: 0.55, 2: 0.65}\nfor imgs in tqdm(glob('../input/sartorius-cell-instance-segmentation/test/*')):\n    result = inference_detector(model, imgs)\n    pred_class_ls = [len(result[0][0]), len(result[0][1]), len(result[0][2])]\n    pred_class = pred_class_ls.index(max(len(result[0][0]), len(result[0][1]), len(result[0][2])))\n    if debug:\n        img = mmcv.imread(imgs)\n        show_result_pyplot(model, img, result)\n    msk = []\n    for i, classe in enumerate(result[0]):\n        if classe.shape != (0, 5):\n            bbs = classe\n            sgs = result[1][i]\n            for bb, sg in zip(bbs,sgs):\n                box = bb[:4]\n                cnf = bb[4]\n                if cnf >= confidence_thresholds[pred_class]:\n                    mask = get_mask_from_result(sg)\n                    mask = remove_overlapping_pixels(mask, msk)\n                    msk.append(mask)\n    for mk in msk:\n            rle_mask = rle_encoding(mk)\n            masks.append(rle_mask)\n            files.append(str(imgs.split('/')[4].split('.')[0]))","metadata":{"papermill":{"duration":0.784288,"end_time":"2021-10-28T17:40:35.695074","exception":false,"start_time":"2021-10-28T17:40:34.910786","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-11-28T02:25:46.799672Z","iopub.execute_input":"2021-11-28T02:25:46.799934Z","iopub.status.idle":"2021-11-28T02:25:49.253476Z","shell.execute_reply.started":"2021-11-28T02:25:46.799897Z","shell.execute_reply":"2021-11-28T02:25:49.252738Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"files = pd.Series(files, name='id')\npreds = pd.Series(masks, name='predicted')\nsubmission_df = pd.concat([files, preds], axis=1)\nsubmission_df.to_csv('submission.csv', index=False)\nsubmission_df","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%cd /kaggle/working\n!rm -rf /kaggle/working/mmpycocotools-12.0.3\n!rm -rf /kaggle/working/addict-2.4.0-py3-none-any.whl\n!rm -rf /kaggle/working/pycocotools-2.0.2\n!rm -rf /kaggle/working/cascade_rcnn_r2_101_fpn_20e_coco.py\n!rm -rf /kaggle/working/mmcv-1.3.8\n!rm -rf /kaggle/working/terminal-0.4.0-py3-none-any.whl\n!rm -rf /kaggle/working/mmcv_full-1_3_8-cu110-torch1_7_0\n!rm -rf /kaggle/working/terminaltables-3.1.0-py3-none-any.whl\n!rm -rf /kaggle/working/mmdetection\n!rm -rf /kaggle/working/yapf-0.31.0-py2.py3-none-any.whl\n!rm -rf /kaggle/working/cascade_mask_rcnn_x101_64x4d_fpn_20e_coco.py","metadata":{},"execution_count":null,"outputs":[]}]}