{"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":"# **Train and Inference Notebooks**","metadata":{}},{"cell_type":"markdown","source":"https://www.kaggle.com/vexxingbanana/sartorius-mmdetection-training\n\nhttps://www.kaggle.com/vexxingbanana/mmdetection-neuron-inference","metadata":{}},{"cell_type":"markdown","source":"# **References**","metadata":{}},{"cell_type":"markdown","source":"https://www.kaggle.com/dschettler8845/sartorius-segmentation-eda-and-baseline\n\nhttps://www.kaggle.com/ihelon/cell-segmentation-run-length-decoding\n\nhttps://www.kaggle.com/stainsby/fast-tested-rle\n\nhttps://www.kaggle.com/paulorzp/run-length-encode-and-decode\n\nhttps://www.kaggle.com/awsaf49/sartorius-mmdetection-infer\n\nhttps://www.kaggle.com/awsaf49/sartorius-mmdetection-train\n\nhttps://www.kaggle.com/evancofsky/sartorius-torch-lightning-mask-r-cnn/notebook","metadata":{}},{"cell_type":"markdown","source":"# **Install PyCocoTools**","metadata":{}},{"cell_type":"code","source":"!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","metadata":{"execution":{"iopub.status.busy":"2021-11-23T00:56:49.213809Z","iopub.execute_input":"2021-11-23T00:56:49.214153Z","iopub.status.idle":"2021-11-23T00:57:47.410923Z","shell.execute_reply.started":"2021-11-23T00:56:49.214064Z","shell.execute_reply":"2021-11-23T00:57:47.410090Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import sklearn\nfrom sklearn.model_selection import train_test_split\nimport numpy as np\nimport pandas as pd\nimport os\nimport matplotlib.pyplot as plt\nimport json\nimport glob\nimport pycocotools\nfrom pycocotools import mask\nimport random\nimport cv2\nimport re","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-11-23T00:57:47.412392Z","iopub.execute_input":"2021-11-23T00:57:47.412600Z","iopub.status.idle":"2021-11-23T00:57:47.756724Z","shell.execute_reply.started":"2021-11-23T00:57:47.412573Z","shell.execute_reply":"2021-11-23T00:57:47.755701Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Helper Functions**","metadata":{}},{"cell_type":"code","source":"IMG_WIDTH = 704\nIMG_HEIGHT = 520","metadata":{"execution":{"iopub.status.busy":"2021-11-23T00:59:22.054794Z","iopub.execute_input":"2021-11-23T00:59:22.055074Z","iopub.status.idle":"2021-11-23T00:59:22.058824Z","shell.execute_reply.started":"2021-11-23T00:59:22.055042Z","shell.execute_reply":"2021-11-23T00:59:22.058074Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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)\n\n\ndef flatten_l_o_l(nested_list):\n    \"\"\" Flatten a list of lists \"\"\"\n    return [item for sublist in nested_list for item in sublist]\n\n\ndef load_json_to_dict(json_path):\n    \"\"\" tbd \"\"\"\n    with open(json_path) as json_file:\n        data = json.load(json_file)\n    return data","metadata":{"execution":{"iopub.status.busy":"2021-11-23T00:59:23.737693Z","iopub.execute_input":"2021-11-23T00:59:23.737998Z","iopub.status.idle":"2021-11-23T00:59:23.748150Z","shell.execute_reply.started":"2021-11-23T00:59:23.737965Z","shell.execute_reply":"2021-11-23T00:59:23.747465Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def 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":{"execution":{"iopub.status.busy":"2021-11-23T00:59:26.376186Z","iopub.execute_input":"2021-11-23T00:59:26.377022Z","iopub.status.idle":"2021-11-23T00:59:26.388855Z","shell.execute_reply.started":"2021-11-23T00:59:26.376980Z","shell.execute_reply":"2021-11-23T00:59:26.387906Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def polygonFromMask(maskedArr, idx):\n  # adapted from https://github.com/hazirbas/coco-json-converter/blob/master/generate_coco_json.py\n  contours, _ = cv2.findContours(maskedArr, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)\n  segmentation = []\n  valid_poly = 0\n  for contour in contours:\n  # Valid polygons have >= 6 coordinates (3 points)\n     if contour.size >= 6:\n        segmentation.append(contour.astype(float).flatten().tolist())\n        valid_poly += 1\n  if valid_poly == 0:\n     raise ValueError(idx)\n  return [segmentation]","metadata":{"execution":{"iopub.status.busy":"2021-11-23T00:59:27.596619Z","iopub.execute_input":"2021-11-23T00:59:27.596910Z","iopub.status.idle":"2021-11-23T00:59:27.602908Z","shell.execute_reply.started":"2021-11-23T00:59:27.596879Z","shell.execute_reply":"2021-11-23T00:59:27.601974Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Create Coco Json File**","metadata":{}},{"cell_type":"code","source":"train_df = pd.read_csv('../input/sartorius-cell-instance-segmentation/train.csv')","metadata":{"execution":{"iopub.status.busy":"2021-11-23T00:59:29.734103Z","iopub.execute_input":"2021-11-23T00:59:29.734385Z","iopub.status.idle":"2021-11-23T00:59:30.085168Z","shell.execute_reply.started":"2021-11-23T00:59:29.734356Z","shell.execute_reply":"2021-11-23T00:59:30.084094Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"lines = []\nfor f in train_df.itertuples():\n    lines.append('../input/sartorius-cell-instance-segmentation/train/' + f[1] + '.png')\nlins = pd.Series(lines, name='img_path')\ntrain_df = pd.concat([train_df, lins], axis=1)","metadata":{"execution":{"iopub.status.busy":"2021-11-23T00:59:30.443130Z","iopub.execute_input":"2021-11-23T00:59:30.444315Z","iopub.status.idle":"2021-11-23T00:59:30.591964Z","shell.execute_reply.started":"2021-11-23T00:59:30.444229Z","shell.execute_reply":"2021-11-23T00:59:30.591009Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tmp_df = train_df.drop_duplicates(subset=[\"id\", \"img_path\"]).reset_index(drop=True)\ntmp_df[\"annotation\"] = train_df.groupby(\"id\")[\"annotation\"].agg(list).reset_index(drop=True)\ntrain_df = tmp_df.copy()","metadata":{"execution":{"iopub.status.busy":"2021-11-23T00:59:31.358228Z","iopub.execute_input":"2021-11-23T00:59:31.358511Z","iopub.status.idle":"2021-11-23T00:59:31.458218Z","shell.execute_reply.started":"2021-11-23T00:59:31.358483Z","shell.execute_reply":"2021-11-23T00:59:31.457131Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df, val_df = train_test_split(train_df, train_size=0.95, random_state=0)\ntrain_df = train_df.reset_index(drop=True)\nval_df = val_df.reset_index(drop=True)","metadata":{"execution":{"iopub.status.busy":"2021-11-23T00:59:32.333037Z","iopub.execute_input":"2021-11-23T00:59:32.333393Z","iopub.status.idle":"2021-11-23T00:59:32.340839Z","shell.execute_reply.started":"2021-11-23T00:59:32.333355Z","shell.execute_reply":"2021-11-23T00:59:32.340108Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"categories = {\"cort\": 2, \"shsy5y\": 1, \"astro\": 3}","metadata":{"execution":{"iopub.status.busy":"2021-11-23T00:59:34.224403Z","iopub.execute_input":"2021-11-23T00:59:34.224713Z","iopub.status.idle":"2021-11-23T00:59:34.229982Z","shell.execute_reply.started":"2021-11-23T00:59:34.224666Z","shell.execute_reply":"2021-11-23T00:59:34.228979Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"output_json_dict = {\n    \"images\": [],\n    \"annotations\": [],\n    \"categories\": []\n}","metadata":{"execution":{"iopub.status.busy":"2021-11-23T00:59:35.760061Z","iopub.execute_input":"2021-11-23T00:59:35.760336Z","iopub.status.idle":"2021-11-23T00:59:35.764456Z","shell.execute_reply.started":"2021-11-23T00:59:35.760304Z","shell.execute_reply":"2021-11-23T00:59:35.763658Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"category_dict = {\"id\": 1, \"name\": \"shsy5y\", \"supercategory\": \"none\"}\noutput_json_dict[\"categories\"].append(category_dict)\ncategory_dict = {\"id\": 2, \"name\": \"cort\", \"supercategory\": \"none\"}\noutput_json_dict[\"categories\"].append(category_dict)\ncategory_dict = {\"id\": 3, \"name\": \"astro\", \"supercategory\": \"none\"}\noutput_json_dict[\"categories\"].append(category_dict)","metadata":{"execution":{"iopub.status.busy":"2021-11-23T00:59:37.079546Z","iopub.execute_input":"2021-11-23T00:59:37.079829Z","iopub.status.idle":"2021-11-23T00:59:37.087687Z","shell.execute_reply.started":"2021-11-23T00:59:37.079801Z","shell.execute_reply":"2021-11-23T00:59:37.086976Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_img_and_annot_info(df, annot_id_start=1):\n    for f in df.itertuples():\n        image_id = f[0]\n        file_path = f[-1]\n        width = f[3]\n        height = f[4]\n        category = categories[f[5]]\n#         img, mk = get_img_and_mask(file_path, f[2], width, height)\n        image_info = {\n            \"id\": image_id,\n            \"width\": width,\n            \"height\": height,\n            \"file_name\": file_path,\n        }\n        output_json_dict['images'].append(image_info)\n        for annot in np.unique(f[2]):\n#             print(annot)\n#             img, annotation = get_img_and_mask(file_path, annot, width, height)\n            annotation = rle_decode(annot, (IMG_HEIGHT, IMG_WIDTH))\n#             print(np.unique(annotation))\n            _, count = np.unique(annotation, return_counts=True)\n#             print(annotation.shape)\n            annot_mask = annotation.astype(np.bool)\n#             print(annot_mask)\n            annot_mask = np.asfortranarray(annot_mask)\n#             print(np.unique(annot_mask))\n            Rs = mask.encode(annot_mask)\n            Rs['counts'] = Rs['counts'].decode('utf-8')\n#             print(Rs)\n            bbox = mask.toBbox(Rs)\n            bbox_list = []\n            for element in bbox:\n                bbox_list.append(int(element))\n#             print(bbox_list)\n#             print(Rs)\n            annot_dict = {\n                \"category_id\": category,\n                \"segmentation\": Rs,\n                \"area\": int(mask.area(Rs)),\n                \"bbox\": bbox_list,\n                \"id\": annot_id_start,\n                \"image_id\": image_id,\n                \"iscrowd\": 0}\n            output_json_dict[\"annotations\"].append(annot_dict)\n            annot_id_start += 1","metadata":{"execution":{"iopub.status.busy":"2021-11-23T00:59:39.255624Z","iopub.execute_input":"2021-11-23T00:59:39.256450Z","iopub.status.idle":"2021-11-23T00:59:39.267705Z","shell.execute_reply.started":"2021-11-23T00:59:39.256409Z","shell.execute_reply":"2021-11-23T00:59:39.266729Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# def get_img_and_annot_info(df, annot_id_start=1):\n#     for f in df.itertuples():\n#         image_id = f[0]\n#         file_path = f[-1]\n#         width = f[3]\n#         height = f[4]\n#         category = categories[f[5]]\n#         img, mk = get_img_and_mask(file_path, f[2], width, height)\n#         image_info = {\n#             \"id\": image_id,\n#             \"width\": width,\n#             \"height\": height,\n#             \"file_name\": file_path,\n#         }\n#         output_json_dict['images'].append(image_info)\n#         for annot in np.unique(mk):\n#             annotation = []\n#             if annot != 0:\n#                 annot_mask = mk == annot\n#                 _, count = np.unique(annot_mask, return_counts=True)\n#                 if count[1] >= 6 and (image_id != 270 and annot != 220) and (image_id!= 300 and annot != 16): #Doesn't give valid annotation otherwise\n#                     annot_mask = np.expand_dims(annot_mask, axis=2)\n#                     annot_mask = np.asfortranarray(annot_mask)\n#                     Rs = mask.encode(annot_mask)\n#                     assert len(Rs) == 1\n#                     coco_seg = Rs[0]\n#                     bbox = mask.toBbox(coco_seg)\n#                     bbox_list = []\n#                     for element in bbox:\n#                         bbox_list.append(int(element))\n#                     polygon_seg = mask.decode(coco_seg)\n#                     polygon_segm = polygonFromMask(polygon_seg, image_id)\n#                     annot_dict = {\n#                         \"category_id\": category,\n#                         \"segmentation\": polygon_segm[0],\n#                         \"area\": int(mask.area(coco_seg)),\n#                         \"bbox\": bbox_list,\n#                         \"id\": annot_id_start,\n#                         \"image_id\": image_id,\n#                         \"iscrowd\": 0}\n#                     output_json_dict[\"annotations\"].append(annot_dict)\n#                     annot_id_start += 1","metadata":{"execution":{"iopub.status.busy":"2021-11-23T00:59:41.698167Z","iopub.execute_input":"2021-11-23T00:59:41.698568Z","iopub.status.idle":"2021-11-23T00:59:41.704389Z","shell.execute_reply.started":"2021-11-23T00:59:41.698521Z","shell.execute_reply":"2021-11-23T00:59:41.703661Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"get_img_and_annot_info(train_df)\nwith open('train_dataset.json', 'w') as f:\n    output_json = json.dumps(output_json_dict)\n    f.write(output_json)","metadata":{"execution":{"iopub.status.busy":"2021-11-23T00:59:42.789688Z","iopub.execute_input":"2021-11-23T00:59:42.789983Z","iopub.status.idle":"2021-11-23T00:59:49.313618Z","shell.execute_reply.started":"2021-11-23T00:59:42.789952Z","shell.execute_reply":"2021-11-23T00:59:49.312402Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"output_json_dict = {\n    \"images\": [],\n    \"annotations\": [], \n    \"categories\": []\n}\n\ncategory_dict = {\"id\": 1, \"name\": \"shsy5y\", \"supercategory\": \"none\"}\noutput_json_dict[\"categories\"].append(category_dict)\ncategory_dict = {\"id\": 2, \"name\": \"cort\", \"supercategory\": \"none\"}\noutput_json_dict[\"categories\"].append(category_dict)\ncategory_dict = {\"id\": 3, \"name\": \"astro\", \"supercategory\": \"none\"}\noutput_json_dict[\"categories\"].append(category_dict)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"get_img_and_annot_info(val_df)\nwith open('val_dataset.json', 'w') as f:\n    output_json = json.dumps(output_json_dict)\n    f.write(output_json)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}