{"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":"# **KDDM 2 SARTORIUS CELL INSTANCE SEGMENTATION CELLPOSE INFERENCE NOTEBOOK**","metadata":{}},{"cell_type":"markdown","source":"# INSTALL All DEPENDENCIES\n* **Install PyTorch version required by MMClassification**\n* **Install MMClassifcation and required dependencies**\n* **Install Cellpose and required dependencies**","metadata":{}},{"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":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-01-26T12:11:42.25976Z","iopub.execute_input":"2022-01-26T12:11:42.260285Z","iopub.status.idle":"2022-01-26T12:13:38.589319Z","shell.execute_reply.started":"2022-01-26T12:11:42.260184Z","shell.execute_reply":"2022-01-26T12:13:38.588499Z"},"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/kddm2/mmcls/mmcv_full-1.3.18-cp37-cp37m-manylinux1_x86_64.whl' --no-deps\n\n!cp -r /kaggle/input/mmdetectionv2140/pycocotools-2.0.2/* /kaggle/working/\n!cp -r /kaggle/input/mmdetectionv2140/mmpycocotools-12.0.3/* /kaggle/working/\n\n!pip install '/kaggle/working/mmpycocotools-12.0.3/' --no-deps\n!pip install '/kaggle/working/pycocotools-2.0.2/' --no-deps\n\n!rm -rf /kaggle/working/pycocotools-2.0.2/\n!rm -rf /kaggle/working/mmpycocotools-12.0.3/\n\n!rm -rf mmdetection\n\n!cp -r /kaggle/input/kddm2/mmcls/mmclassification-0.18.0/mmclassification-0.18.0 /kaggle/working/mmclassification/\n%cd /kaggle/working/mmclassification\n!pip install -e .","metadata":{"execution":{"iopub.status.busy":"2022-01-26T12:27:35.848964Z","iopub.execute_input":"2022-01-26T12:27:35.8496Z","iopub.status.idle":"2022-01-26T12:31:06.557443Z","shell.execute_reply.started":"2022-01-26T12:27:35.84956Z","shell.execute_reply":"2022-01-26T12:31:06.556633Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install /kaggle/input/kddm2/cellpose/fastremap-1.12.2-cp37-cp37m-manylinux2010_x86_64.whl --no-deps\n!pip install /kaggle/input/kddm2/cellpose/natsort-8.0.1-py3-none-any.whl --no-deps\n!pip install /kaggle/input/kddm2/cellpose/pytorch_ranger-0.1.1-py3-none-any.whl --no-deps\n!pip install /kaggle/input/kddm2/cellpose/torch_optimizer-0.3.0-py3-none-any.whl --no-deps\n!pip install /kaggle/input/kddm2/cellpose/numpy-1.20.3-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl --no-deps\n!pip install /kaggle/input/kddm2/cellpose/cellpose-0.7.2-py3-none-any.whl --no-deps\n!pip install /kaggle/input/kddm2/cellpose/edt-2.1.1-cp37-cp37m-manylinux2014_x86_64.whl --no-deps","metadata":{"execution":{"iopub.status.busy":"2022-01-26T12:42:20.601631Z","iopub.execute_input":"2022-01-26T12:42:20.601922Z","iopub.status.idle":"2022-01-26T12:44:57.371989Z","shell.execute_reply.started":"2022-01-26T12:42:20.601869Z","shell.execute_reply":"2022-01-26T12:44:57.371108Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"* **Check Installation**","metadata":{}},{"cell_type":"code","source":"!nvidia-smi\n\nimport torch\nprint(torch.__version__, torch.cuda.is_available(),  torch.cuda.get_device_properties(0) if torch.cuda.is_available() else 'NO CUDA DEVICE')\n!nvcc --version\n\n# Check mmcv installation\nimport mmcv\nprint(mmcv.__version__)\n\n# Check MMClassification installation\nimport mmcls\nprint(mmcls.__version__)\n\nfrom mmcv.ops import get_compiling_cuda_version, get_compiler_version\nprint(\"Cuda:\", get_compiling_cuda_version(), \"Compiler:\", get_compiler_version())","metadata":{"execution":{"iopub.status.busy":"2022-01-26T12:48:40.785626Z","iopub.execute_input":"2022-01-26T12:48:40.785912Z","iopub.status.idle":"2022-01-26T12:48:50.430168Z","shell.execute_reply.started":"2022-01-26T12:48:40.785868Z","shell.execute_reply":"2022-01-26T12:48:50.4285Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"* **Enable Cellpose logging for notebooks**","metadata":{}},{"cell_type":"code","source":"with open(\"/opt/conda/lib/python3.7/site-packages/cellpose/core.py\", \"r\") as f:\n    core_file = f.read().split(\"\\n\")\ncore_file[35] = \"core_logger.addHandler(logging.StreamHandler(stream=sys.stdout))\"\nwith open(\"/opt/conda/lib/python3.7/site-packages/cellpose/core.py\", \"w\") as f:\n    f.write( (\"\\n\").join(core_file) )","metadata":{"execution":{"iopub.status.busy":"2022-01-26T12:48:50.431982Z","iopub.execute_input":"2022-01-26T12:48:50.432399Z","iopub.status.idle":"2022-01-26T12:48:50.44034Z","shell.execute_reply.started":"2022-01-26T12:48:50.432361Z","shell.execute_reply":"2022-01-26T12:48:50.439112Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **INFERENCE**","metadata":{}},{"cell_type":"markdown","source":"* **Inference script has to be written to file due to numpy version issues on Kaggle notebooks**","metadata":{}},{"cell_type":"code","source":"%%writefile run.py\nfrom cellpose import models, io, plot\nfrom mmcls.apis import init_model, inference_model\nimport numpy as np\nimport os\nimport pandas as pd\nfrom pathlib import Path\n\ndef rle_encode(img):\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\nclasses = [\"astro\", \"cort\", \"shsy5y\"]\ntest_dir = Path('/kaggle/input/sartorius-cell-instance-segmentation/test')\ntest_files = [fname for fname in test_dir.iterdir()]\n\n#set and initialize MMClassification model used to select class-specific cellpose model\nmmcls_model = init_model(\"/kaggle/input/kddm2/mmcls/mmcls_resnext50_sartorius.py\", \"/kaggle/input/kddm2/mmcls/mmcls_resnext50_0.9836_sartorius.pth\")\ncp_model_dir = \"/kaggle/input/kddm2/cellpose/\"\n#define which version of cellpose model should be used\ncp_model_files = [\"astro4\", \"cort9\", \"shsy5y5\"]\n#set per class parameters for cellpose models (diameter, flow threshold, mask threshold)\nparams = [{\"dm\": 25, \"ft\": 0.5, \"mt\": -0.3}, {\"dm\": 16, \"ft\": 0.3, \"mt\": -0.3}, {\"dm\": 23, \"ft\": 0.5, \"mt\": 0.3}]\n#initialize the three cellpose models\ncp_models = []\nfor i in range(3):\n    cp_models.append(models.CellposeModel(gpu=True, pretrained_model=os.path.join(cp_model_dir, cp_model_files[i])))\n\n#run inference for all test files and store predictions in competition submission format\nids, masks = [],[]\nfor fn in test_files:\n    print(fn)\n    res = inference_model(mmcls_model, str(fn))\n    pred_label = int(res[\"pred_label\"])\n    print(\"{:s}: class {:s} ({:d}) - conf: {:.3f}\".format(fn.stem, classes[pred_label], pred_label, res[\"pred_score\"]))\n\n    cp_model = cp_models[pred_label]\n    p = params[pred_label]\n    preds, flows, _ = cp_model.eval(io.imread(str(fn)), diameter=p[\"dm\"], channels=[0,0], augment=True, resample=True, flow_threshold=p[\"ft\"], mask_threshold=p[\"mt\"], omni=False)\n    for i in range (1, preds.max() + 1):\n        ids.append(fn.stem)\n        masks.append(rle_encode(preds == i))\n        \npd.DataFrame({'id': ids, 'predicted': masks}).to_csv('/kaggle/working/submission.csv', index=False)\nprint(pd.read_csv('/kaggle/working/submission.csv').head())","metadata":{"execution":{"iopub.status.busy":"2022-01-26T12:52:23.090434Z","iopub.execute_input":"2022-01-26T12:52:23.090731Z","iopub.status.idle":"2022-01-26T12:52:23.097538Z","shell.execute_reply.started":"2022-01-26T12:52:23.090702Z","shell.execute_reply":"2022-01-26T12:52:23.096792Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"* **Execute inference script**","metadata":{}},{"cell_type":"code","source":"!python run.py","metadata":{"execution":{"iopub.status.busy":"2022-01-26T12:52:26.018604Z","iopub.execute_input":"2022-01-26T12:52:26.018863Z","iopub.status.idle":"2022-01-26T12:53:06.311538Z","shell.execute_reply.started":"2022-01-26T12:52:26.018833Z","shell.execute_reply":"2022-01-26T12:53:06.310708Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"* **Visualize result images**","metadata":{}},{"cell_type":"code","source":"import cv2\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport os\n\nwith open(\"/kaggle/working/submission.csv\", \"r\") as f:\n    anns = f.read().split(\"\\n\")\nanns = anns[1:-1]\nprint(\"number of annotations\", len(anns))\n\n#convert predictions stored in csv file\nmasks_per_id = {}\nfor a in anns:\n    if len(a) < 1:\n        continue\n    values = a.split(\",\")\n    id = values[0]\n    rle_mask = values[1].split(\" \")\n    starts = list(map(lambda x: int(x) - 1, rle_mask[0::2]))\n    lengths = list(map(int, rle_mask[1::2]))\n\n    ends = [x + y for x, y in zip(starts, lengths)]\n\n    if id not in masks_per_id.keys():\n        masks_per_id[id] = []\n\n    masks_per_id[id].append( [starts, ends] )\nprint(\"number of img ids\", len(masks_per_id.keys()))\n\n#add mask overlay to images and store masked images\nimg_dir = '/kaggle/input/sartorius-cell-instance-segmentation/test'\nfor f in os.listdir(img_dir):\n        if (f[-3:] != \"png\" and f[-3:] != \"tif\") or \"_\" in f:\n            continue\n            \n        im = cv2.imread( \"{:s}/{:s}\".format(img_dir, f), cv2.IMREAD_GRAYSCALE )\n\n        if f[:-4] not in list(masks_per_id.keys()):\n            continue\n        masks = masks_per_id[f[:-4]]\n        \n        print(f, len(masks))\n\n        masked_img = np.empty((im.shape[0], im.shape[1], 3), dtype=np.uint8)\n        masked_img[:, :, 0] = im\n        masked_img[:, :, 1] = im\n        masked_img[:, :, 2] = im\n\n        flattened = masked_img.reshape( (masked_img.shape[0]*masked_img.shape[1], 3) )\n        c = 0\n        for m in masks:\n            c += 1\n            color = np.random.choice(range(256), size=3)\n            for start, end in zip(m[0], m[1]):\n                if start >= end:\n                    print(\"ERROR1\")\n                for y in range(start, end):\n                    if flattened[y, 0] == 255 and flattened[y, 1] == 0 and flattened[y, 2] == 0:\n                        print(\"ERROR2\")\n                flattened[start:end] = color\n\n        masked_img = flattened.reshape( (masked_img.shape[0], masked_img.shape[1], 3) )\n        cv2.imwrite( \"/kaggle/working/{:s}.png\".format(f[:-4]), masked_img )\n        plt.figure(figsize=(13, 13))\n        plt.title(f)\n        plt.imshow(masked_img)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-01-26T12:53:35.124196Z","iopub.execute_input":"2022-01-26T12:53:35.124995Z","iopub.status.idle":"2022-01-26T12:53:37.046395Z","shell.execute_reply.started":"2022-01-26T12:53:35.124952Z","shell.execute_reply":"2022-01-26T12:53:37.045741Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **CLEAN UP (REQUIRED FOR COMPETITION)**","metadata":{}},{"cell_type":"code","source":"!ls /kaggle/working\n%cd /kaggle/working\n!rm -rf /kaggle/working/mmclassification\n!ls /kaggle/working","metadata":{"execution":{"iopub.status.busy":"2021-12-20T14:53:55.0421Z","iopub.execute_input":"2021-12-20T14:53:55.042954Z","iopub.status.idle":"2021-12-20T14:53:57.271604Z","shell.execute_reply.started":"2021-12-20T14:53:55.042917Z","shell.execute_reply":"2021-12-20T14:53:57.270324Z"},"trusted":true},"execution_count":null,"outputs":[]}]}