{"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":"# Instance Segmentation Fix_Overlap Before/After","metadata":{"papermill":{"duration":0.029749,"end_time":"2021-11-30T03:03:46.604865","exception":false,"start_time":"2021-11-30T03:03:46.575116","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"This notebook referred to the following notebook.<br/>\nhttps://www.kaggle.com/arunamenon/cell-instance-segmentation-unet-eda<br/>\nhttps://www.kaggle.com/karan23258/cell-instance-segmentation-unetfromscratch<br/>\nhttps://www.kaggle.com/evangelou/sartorius-unet-pytorch-from-scratch<br/>\nhttps://www.kaggle.com/awsaf49/sartorius-fix-overlap","metadata":{"papermill":{"duration":0.027191,"end_time":"2021-11-30T03:03:46.660664","exception":false,"start_time":"2021-11-30T03:03:46.633473","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"# Import packages","metadata":{"papermill":{"duration":0.027093,"end_time":"2021-11-30T03:03:46.71519","exception":false,"start_time":"2021-11-30T03:03:46.688097","status":"completed"},"tags":[]}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport imageio\nimport matplotlib.pyplot as plt\nimport cv2\nimport seaborn as sns\nfrom skimage.io import imread, imshow, imread_collection, concatenate_images\nfrom skimage.transform import resize\nfrom skimage.morphology import label\nfrom tqdm import tqdm\nimport random\nimport tensorflow as tf","metadata":{"papermill":{"duration":6.312835,"end_time":"2021-11-30T03:03:53.05595","exception":false,"start_time":"2021-11-30T03:03:46.743115","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-11-30T12:06:08.59248Z","iopub.execute_input":"2021-11-30T12:06:08.593448Z","iopub.status.idle":"2021-11-30T12:06:08.599191Z","shell.execute_reply.started":"2021-11-30T12:06:08.593401Z","shell.execute_reply":"2021-11-30T12:06:08.598136Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Load input files","metadata":{"papermill":{"duration":0.02742,"end_time":"2021-11-30T03:03:53.111181","exception":false,"start_time":"2021-11-30T03:03:53.083761","status":"completed"},"tags":[]}},{"cell_type":"code","source":"train_data = pd.read_csv('../input/sartorius-cell-instance-segmentation/train.csv')","metadata":{"papermill":{"duration":0.555974,"end_time":"2021-11-30T03:03:53.694578","exception":false,"start_time":"2021-11-30T03:03:53.138604","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-11-30T12:06:08.601029Z","iopub.execute_input":"2021-11-30T12:06:08.601875Z","iopub.status.idle":"2021-11-30T12:06:08.94526Z","shell.execute_reply.started":"2021-11-30T12:06:08.601825Z","shell.execute_reply":"2021-11-30T12:06:08.944414Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(train_data.shape)\ntrain_data.head()","metadata":{"papermill":{"duration":0.051584,"end_time":"2021-11-30T03:03:53.774701","exception":false,"start_time":"2021-11-30T03:03:53.723117","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-11-30T12:06:08.947181Z","iopub.execute_input":"2021-11-30T12:06:08.94752Z","iopub.status.idle":"2021-11-30T12:06:08.969845Z","shell.execute_reply.started":"2021-11-30T12:06:08.947473Z","shell.execute_reply":"2021-11-30T12:06:08.968903Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(train_data['cell_type'].unique().tolist())","metadata":{"papermill":{"duration":0.045534,"end_time":"2021-11-30T03:03:53.848863","exception":false,"start_time":"2021-11-30T03:03:53.803329","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-11-30T12:06:08.971597Z","iopub.execute_input":"2021-11-30T12:06:08.971892Z","iopub.status.idle":"2021-11-30T12:06:08.990506Z","shell.execute_reply.started":"2021-11-30T12:06:08.971851Z","shell.execute_reply":"2021-11-30T12:06:08.98947Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# these 3 ids used as representatives of train data.\nprint(train_data[train_data['cell_type']=='shsy5y']['id'].tolist()[0])\nprint(train_data[train_data['cell_type']=='astro']['id'].tolist()[0])\nprint(train_data[train_data['cell_type']=='cort']['id'].tolist()[0])","metadata":{"papermill":{"duration":0.078007,"end_time":"2021-11-30T03:03:53.955907","exception":false,"start_time":"2021-11-30T03:03:53.8779","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-11-30T12:06:08.992265Z","iopub.execute_input":"2021-11-30T12:06:08.992537Z","iopub.status.idle":"2021-11-30T12:06:09.028218Z","shell.execute_reply.started":"2021-11-30T12:06:08.992505Z","shell.execute_reply":"2021-11-30T12:06:09.027548Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## rle_decode : mask_rle data (=label data) to mask image data","metadata":{"papermill":{"duration":0.02859,"end_time":"2021-11-30T03:03:54.013179","exception":false,"start_time":"2021-11-30T03:03:53.984589","status":"completed"},"tags":[]}},{"cell_type":"code","source":"# Reference: https://www.kaggle.com/ihelon/cell-segmentation-run-length-decoding\n\ndef rle_decode(mask_rle, shape, color=1):\n    '''\n    mask_rle: run-length as string formated (start length)\n    shape: (height, width, channels) of array to return \n    color: color for the mask\n    Returns numpy array (mask)\n    '''\n    s = mask_rle.split()\n    \n    starts = list(map(lambda x: int(x)-1, s[0::2]))\n    lengths = list(map(int, s[1::2]))\n    ends = [x + y for x, y in zip(starts, lengths)]\n    \n    img = np.zeros((shape[0] * shape[1], shape[2]), dtype=np.float32)\n            \n    for start, end in zip(starts, ends):\n        img[start : end] = color\n    \n    return img.reshape(shape)\n","metadata":{"papermill":{"duration":0.038947,"end_time":"2021-11-30T03:03:54.081448","exception":false,"start_time":"2021-11-30T03:03:54.042501","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-11-30T12:06:09.029199Z","iopub.execute_input":"2021-11-30T12:06:09.029782Z","iopub.status.idle":"2021-11-30T12:06:09.03581Z","shell.execute_reply.started":"2021-11-30T12:06:09.029748Z","shell.execute_reply":"2021-11-30T12:06:09.034984Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## plot_masks : show original and mask images","metadata":{"papermill":{"duration":0.028394,"end_time":"2021-11-30T03:03:54.138394","exception":false,"start_time":"2021-11-30T03:03:54.11","status":"completed"},"tags":[]}},{"cell_type":"code","source":"def plot_masks(image_id, colors=True):\n    labels = train_data[train_data[\"id\"] == image_id][\"annotation\"].tolist()\n\n    if colors:\n        mask = np.zeros((520, 704, 3))\n        for label in labels:\n            mask += rle_decode(label, shape=(520, 704, 3), color=np.random.rand(3))\n    else:\n        mask = np.zeros((520, 704, 1))\n        for label in labels:\n            mask += rle_decode(label, shape=(520, 704, 1))\n            \n    mask = mask.clip(0, 1)\n\n    image = cv2.imread(f\"../input/sartorius-cell-instance-segmentation/train/{image_id}.png\")\n    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n\n    plt.figure(figsize=(18,6))\n    plt.subplot(1, 3, 1)\n    plt.imshow(image)\n    plt.title('Input image')\n    plt.axis(\"off\")\n    \n    plt.subplot(1, 3, 2)\n    plt.imshow(image)\n    plt.imshow(mask, alpha=0.1)\n    plt.title('Input image with mask')\n    plt.axis(\"off\")\n    \n    plt.subplot(1, 3, 3)\n    plt.imshow(mask)\n    plt.title('Only mask')\n    plt.axis(\"off\")\n    \n    plt.show();","metadata":{"papermill":{"duration":0.040806,"end_time":"2021-11-30T03:03:54.207679","exception":false,"start_time":"2021-11-30T03:03:54.166873","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-11-30T12:06:09.03711Z","iopub.execute_input":"2021-11-30T12:06:09.037508Z","iopub.status.idle":"2021-11-30T12:06:09.05139Z","shell.execute_reply.started":"2021-11-30T12:06:09.037476Z","shell.execute_reply":"2021-11-30T12:06:09.050508Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### ret_mask_img creates mask image data","metadata":{}},{"cell_type":"code","source":"def ret_mask_img(image_id, colors=True):\n    \n    labels = train_data[train_data[\"id\"] == image_id][\"annotation\"].tolist()\n\n    if colors:\n        mask = np.zeros((520, 704, 3))\n        for label in labels:\n            mask += rle_decode(label,shape=(520,704,3),color=np.random.rand(3))\n    else:\n        mask = np.zeros((520, 704, 1))\n        for label in labels:\n            mask += rle_decode(label,shape=(520,704,1))\n            \n    mask = mask.clip(0, 1)\n    \n    return mask","metadata":{"execution":{"iopub.status.busy":"2021-11-30T12:06:09.052741Z","iopub.execute_input":"2021-11-30T12:06:09.052975Z","iopub.status.idle":"2021-11-30T12:06:09.066267Z","shell.execute_reply.started":"2021-11-30T12:06:09.052944Z","shell.execute_reply":"2021-11-30T12:06:09.065373Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### show input and mask image","metadata":{}},{"cell_type":"code","source":"sample_ids = ['0030fd0e6378','0140b3c8f445','01ae5a43a2ab']\n\nfor sample_id in sample_ids:\n    celltype=train_data[train_data['id']==sample_id]['cell_type'].tolist()[0]\n    file_path = '../input/sartorius-cell-instance-segmentation/train/' + sample_id + '.png'\n    image_df = imageio.imread(file_path)\n    \n    print('ID:', sample_id, ', CellType:',celltype)\n    plot_masks(sample_id, colors=True)","metadata":{"papermill":{"duration":1.648328,"end_time":"2021-11-30T03:03:55.884775","exception":false,"start_time":"2021-11-30T03:03:54.236447","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-11-30T12:06:09.067435Z","iopub.execute_input":"2021-11-30T12:06:09.0679Z","iopub.status.idle":"2021-11-30T12:06:11.701434Z","shell.execute_reply.started":"2021-11-30T12:06:09.067854Z","shell.execute_reply":"2021-11-30T12:06:11.700449Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Label before fix_overlap","metadata":{}},{"cell_type":"code","source":"LABEL2=[]\nfor sample_id in sample_ids:\n    labels = train_data[train_data[\"id\"] == sample_id][\"annotation\"].tolist()\n    LABEL=''\n    for label in labels:\n        LABEL+=label\n    LABEL2+=[LABEL]\n    \nprint(LABEL2[0])","metadata":{"execution":{"iopub.status.busy":"2021-11-30T12:07:22.139107Z","iopub.execute_input":"2021-11-30T12:07:22.139437Z","iopub.status.idle":"2021-11-30T12:07:22.166369Z","shell.execute_reply.started":"2021-11-30T12:07:22.139401Z","shell.execute_reply":"2021-11-30T12:07:22.165585Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"MASK=[]\nfor sample_id in sample_ids:\n    labels = train_data[train_data[\"id\"] == sample_id][\"annotation\"].tolist()\n    mask = np.zeros((520,704,3))\n    for label in labels:\n        mask += rle_decode(label, shape=(520,704,3))\n\n    MASK += [mask.clip(0,1)]\n    \nprint(MASK[0].shape)\nprint()\nprint(MASK[0])","metadata":{"execution":{"iopub.status.busy":"2021-11-30T12:06:11.73798Z","iopub.execute_input":"2021-11-30T12:06:11.738258Z","iopub.status.idle":"2021-11-30T12:06:12.650814Z","shell.execute_reply.started":"2021-11-30T12:06:11.738218Z","shell.execute_reply":"2021-11-30T12:06:12.64977Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# values are 0 or 1\nfig, ax = plt.subplots(figsize=(12,4)) \nsns.histplot(MASK[0].flatten(), label='MASK[0].flatten()', ax=ax, color='C1',bins=20) \nax.legend() \nax.grid()","metadata":{"execution":{"iopub.status.busy":"2021-11-30T12:06:12.65241Z","iopub.execute_input":"2021-11-30T12:06:12.652665Z","iopub.status.idle":"2021-11-30T12:06:13.786292Z","shell.execute_reply.started":"2021-11-30T12:06:12.652632Z","shell.execute_reply":"2021-11-30T12:06:13.785302Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### check_overlap ","metadata":{}},{"cell_type":"code","source":"def check_overlap(msk):\n    msk = msk.astype(np.bool).astype(np.uint8)\n    return np.any(np.sum(msk, axis=-1)>1)","metadata":{"execution":{"iopub.status.busy":"2021-11-30T12:06:13.787826Z","iopub.execute_input":"2021-11-30T12:06:13.788288Z","iopub.status.idle":"2021-11-30T12:06:13.79341Z","shell.execute_reply.started":"2021-11-30T12:06:13.788253Z","shell.execute_reply":"2021-11-30T12:06:13.792527Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# surprisingly, original labels have overlaps\nprint(check_overlap(MASK[0]))\nprint(check_overlap(MASK[1]))\nprint(check_overlap(MASK[2]))","metadata":{"execution":{"iopub.status.busy":"2021-11-30T12:06:13.795033Z","iopub.execute_input":"2021-11-30T12:06:13.795569Z","iopub.status.idle":"2021-11-30T12:06:13.838382Z","shell.execute_reply.started":"2021-11-30T12:06:13.795533Z","shell.execute_reply":"2021-11-30T12:06:13.837682Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def fix_overlap(msk):\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 = np.array(msk)\n    msk = np.pad(msk, [[0,0],[0,0],[1,0]])\n    ins_len = msk.shape[-1]\n    msk = np.argmax(msk,axis=-1)\n    msk = tf.keras.utils.to_categorical(msk, num_classes=ins_len)\n    msk = msk[...,1:]\n    msk = msk[...,np.any(msk, axis=(0,1))]\n    \n    return msk","metadata":{"execution":{"iopub.status.busy":"2021-11-30T12:06:13.839612Z","iopub.execute_input":"2021-11-30T12:06:13.83994Z","iopub.status.idle":"2021-11-30T12:06:13.846278Z","shell.execute_reply.started":"2021-11-30T12:06:13.839904Z","shell.execute_reply":"2021-11-30T12:06:13.845537Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# fixed mask data\nMASK0b=fix_overlap(MASK[0])\nMASK1b=fix_overlap(MASK[1])\nMASK2b=fix_overlap(MASK[2])","metadata":{"execution":{"iopub.status.busy":"2021-11-30T12:06:13.847747Z","iopub.execute_input":"2021-11-30T12:06:13.847989Z","iopub.status.idle":"2021-11-30T12:06:13.937403Z","shell.execute_reply.started":"2021-11-30T12:06:13.847956Z","shell.execute_reply":"2021-11-30T12:06:13.936665Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# values are 0 or 1\nfig, ax = plt.subplots(figsize=(12,4)) \nsns.histplot(MASK0b.flatten(), label='MASK0b.flatten()', ax=ax, color='C1',bins=20) \nax.legend() \nax.grid()","metadata":{"execution":{"iopub.status.busy":"2021-11-30T12:06:13.938943Z","iopub.execute_input":"2021-11-30T12:06:13.939212Z","iopub.status.idle":"2021-11-30T12:06:14.460235Z","shell.execute_reply.started":"2021-11-30T12:06:13.939175Z","shell.execute_reply":"2021-11-30T12:06:14.459237Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# no overlaps detected\nprint(check_overlap(MASK0b))\nprint(check_overlap(MASK1b))\nprint(check_overlap(MASK2b))","metadata":{"execution":{"iopub.status.busy":"2021-11-30T12:06:14.462327Z","iopub.execute_input":"2021-11-30T12:06:14.462662Z","iopub.status.idle":"2021-11-30T12:06:14.472214Z","shell.execute_reply.started":"2021-11-30T12:06:14.462617Z","shell.execute_reply":"2021-11-30T12:06:14.471205Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(MASK[0].shape)\nprint(MASK0b.shape)","metadata":{"execution":{"iopub.status.busy":"2021-11-30T12:06:14.473566Z","iopub.execute_input":"2021-11-30T12:06:14.474721Z","iopub.status.idle":"2021-11-30T12:06:14.482096Z","shell.execute_reply.started":"2021-11-30T12:06:14.474673Z","shell.execute_reply":"2021-11-30T12:06:14.481226Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.imshow(MASK[0])\nplt.title('original mask')\nplt.axis(\"off\")\nplt.show()\n\nplt.imshow(MASK0b)\nplt.title('fix_overlapped mask')\nplt.axis(\"off\")\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-11-30T12:06:14.483736Z","iopub.execute_input":"2021-11-30T12:06:14.483971Z","iopub.status.idle":"2021-11-30T12:06:15.128217Z","shell.execute_reply.started":"2021-11-30T12:06:14.48394Z","shell.execute_reply":"2021-11-30T12:06:15.127357Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## show mask image (beofre fix_overlapping)","metadata":{}},{"cell_type":"code","source":"for sample_id in sample_ids:\n    celltype=train_data[train_data['id']==sample_id]['cell_type'].tolist()[0]\n    file_path = '../input/sartorius-cell-instance-segmentation/train/' + sample_id + '.png'\n    image_df = imageio.imread(file_path)\n    print('ID:', sample_id, ', CellType:',celltype)\n    mask=ret_mask_img(sample_id, colors=True)\n    print(mask.shape)\n    \n    plt.imshow(mask)\n    plt.title('mask before fix_overlapping')\n    plt.axis(\"off\")\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2021-11-30T12:06:15.129574Z","iopub.execute_input":"2021-11-30T12:06:15.129812Z","iopub.status.idle":"2021-11-30T12:06:16.552617Z","shell.execute_reply.started":"2021-11-30T12:06:15.129781Z","shell.execute_reply":"2021-11-30T12:06:16.55167Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## show mask image (after fix_overlapping)","metadata":{}},{"cell_type":"code","source":"for mask in [MASK0b,MASK1b,MASK2b]:\n    print(mask.shape)\n    plt.imshow(mask)\n    plt.title('mask after fix_overlapping')\n    plt.axis(\"off\")\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2021-11-30T12:06:16.553704Z","iopub.execute_input":"2021-11-30T12:06:16.55398Z","iopub.status.idle":"2021-11-30T12:06:17.027902Z","shell.execute_reply.started":"2021-11-30T12:06:16.553946Z","shell.execute_reply":"2021-11-30T12:06:17.02696Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# rle_encoding: mask image data to rle data (=label data)","metadata":{}},{"cell_type":"code","source":"def 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))","metadata":{"execution":{"iopub.status.busy":"2021-11-30T12:06:17.029117Z","iopub.execute_input":"2021-11-30T12:06:17.029462Z","iopub.status.idle":"2021-11-30T12:06:17.03517Z","shell.execute_reply.started":"2021-11-30T12:06:17.029426Z","shell.execute_reply":"2021-11-30T12:06:17.034245Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Label after fix_overlap","metadata":{}},{"cell_type":"code","source":"FIXED_LABEL=[]\nfor mask in [MASK0b,MASK1b,MASK2b]:\n    FIXED_LABEL+=[rle_encoding(mask)]\nprint(FIXED_LABEL[0])","metadata":{"execution":{"iopub.status.busy":"2021-11-30T12:06:17.037345Z","iopub.execute_input":"2021-11-30T12:06:17.038285Z","iopub.status.idle":"2021-11-30T12:06:17.184215Z","shell.execute_reply.started":"2021-11-30T12:06:17.038231Z","shell.execute_reply":"2021-11-30T12:06:17.183067Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"papermill":{"duration":0.982026,"end_time":"2021-11-30T03:08:25.651202","exception":false,"start_time":"2021-11-30T03:08:24.669176","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"papermill":{"duration":0.720349,"end_time":"2021-11-30T03:08:27.096144","exception":false,"start_time":"2021-11-30T03:08:26.375795","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]}]}