{"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":"Credits:\n* https://www.kaggle.com/rdizzl3/hpa-segmentation-masks-no-internet\n* https://www.kaggle.com/frlemarchand/generate-masks-from-weak-image-level-labels/\n","metadata":{}},{"cell_type":"markdown","source":"# Installation","metadata":{}},{"cell_type":"code","source":"!pip install -q \"../input/pycocotools/pycocotools-2.0-cp37-cp37m-linux_x86_64.whl\"\n!pip install -q \"../input/hpapytorchzoozip/pytorch_zoo-master\"\n!pip install -q \"../input/hpacellsegmentatormaster/HPA-Cell-Segmentation-master\"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\n# Making pretrained weights work without needing to find the default filename\nif not os.path.exists('/root/.cache/torch/hub/checkpoints/'):\n        os.makedirs('/root/.cache/torch/hub/checkpoints/')\n# !cp '../input/resnet50/resnet50.pth' '/root/.cache/torch/hub/checkpoints/resnet50-19c8e357.pth'\n!cp '../input/resnet34/resnet34.pth' '/root/.cache/torch/hub/checkpoints/resnet34-333f7ec4.pth'\n\nfrom fastai.vision.all import *\nimport pandas as pd\nimport numpy as np\nfrom tqdm.autonotebook import tqdm\nimport imageio\nfrom matplotlib import pyplot as plt\n\nimport sys\n\nimport os\nfrom PIL import Image\nimport tensorflow as tf\nimport cv2\n\nimport hpacellseg.cellsegmentator as cellsegmentator\nfrom hpacellseg.utils import label_cell, label_nuclei","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Helper functions","metadata":{}},{"cell_type":"code","source":"def build_image_names(image_id: str) -> list:\n    mitchondria = f'../input/hpa-single-cell-image-classification/test/{image_id}_red.png'\n    nuclei = f'../input/hpa-single-cell-image-classification/test/{image_id}_blue.png'\n    # er is the endoplasmic reticulum\n    er = f'../input/hpa-single-cell-image-classification/test/{image_id}_yellow.png'    \n    cell = f'../input/hpa-single-cell-image-classification/test/{image_id}_green.png' \n    \n    return [[mitchondria], [nuclei], [er], [cell]]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import base64\nimport numpy as np\nfrom pycocotools import _mask as coco_mask\nimport typing as t\nimport zlib\n\n\ndef encode_binary_mask(mask: np.ndarray) -> t.Text:\n  \"\"\"Converts a binary mask into OID challenge encoding ascii text.\"\"\"\n\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('ascii')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Input: list of image filters as png\n# Output: list of image filters as np.arrays\ndef image_name_to_numpy(path):\n    \n    image_arrays = list()\n    for image in path:\n        array = np.asarray(Image.open(image[0]))\n        image_arrays.append(array)\n        \n    return image_arrays\n\n\n# Get single image that blends all RGBY into RGB\n# Introduce the images as arrays. Can use the function above.\n\ndef get_blended_image(images): \n    # get rgby images for sample\n\n    # blend rgby images into single array\n    blended_array = np.stack(images[:-1], 2)\n\n    # Create PIL Image\n    blended_image = Image.fromarray( np.uint8(blended_array) )\n    return blended_image\n\n\ndef get_contour_from_mask(raw_mask):\n    contours, _ = cv2.findContours(raw_mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)\n    contours = (contours[0]).reshape(contours[0].shape[0], 2)\n    #print(contours)\n    x_min, y_min = list(np.amin(contours, axis=0))\n    x_max, y_max = list(np.amax(contours, axis=0))\n    return x_min, y_min, x_max, y_max","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Inference","metadata":{}},{"cell_type":"code","source":"tpath = Path('../input/hpa-single-cell-image-classification')\nsub = pd.read_csv(tpath/'sample_submission.csv')\n\n# sub = sub.sample(frac=0.03)\nsub.ImageWidth.value_counts()\n\nsub_dfs = []\nfor dim in sub.ImageWidth.unique():\n    df = sub[sub['ImageWidth'] == dim].copy().reset_index(drop=True)\n    sub_dfs.append(df)\n    \nNUC_MODEL = '../input/hpacellsegmentatormodelweights/dpn_unet_nuclei_v1.pth'\nCELL_MODEL = '../input/hpacellsegmentatormodelweights/dpn_unet_cell_3ch_v1.pth'\n\nsegmentator = cellsegmentator.CellSegmentator(\n    NUC_MODEL,\n    CELL_MODEL,\n    scale_factor=0.25,\n    device=\"cuda\",\n    padding=False,\n    multi_channel_model=True,\n)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"bs = 8\nfor sub in sub_dfs:\n    print(f'Starting prediction for image size: {sub.ImageWidth.loc[0]}')\n    for start in range(0, len(sub), bs):\n        if start + bs > len(sub): end = len(sub)\n        else: end = start + bs\n\n        images = []\n        images_green = []\n        for row in range(start, end):\n            image_id = sub['ID'].loc[row]\n            img = build_image_names(image_id=image_id)\n            img, img_green = img[:-1], img[-1]\n            images.append(img)\n            images_green.append(img_green)\n\n        cell_images = []\n        for img in images_green:\n            arrays = image_name_to_numpy([img])\n            cell_images.append(arrays[0])\n\n\n        images = np.stack(images).squeeze()\n        images = np.transpose(images).tolist()\n\n\n        try: \n            nuc_segmentations = segmentator.pred_nuclei(images[1])\n            cell_segmentations = segmentator.pred_cells(images)\n\n#                 plt.imshow(cell_segmentations[0])\n#                 plt.show()\n\n            predstrings = []\n            for i in tqdm(range(len(cell_segmentations))):\n                _, cell_mask = label_cell(nuc_segmentations[i], cell_segmentations[i])\n\n                # Unique vector of cell_mask numbers\n                numbers = set(np.ravel(cell_mask))\n                numbers.remove(0)\n\n                predstring = ''\n                for number in numbers:\n                    isolated_cell = np.where(cell_mask==number, cell_mask, 0)\n                    x = (cell_mask==number).astype(np.uint8)\n                    x_min, y_min, x_max, y_max = get_contour_from_mask(x)\n                    isolated_cell = cell_images[i][y_min:y_max, x_min:x_max]\n                    \n#                     plt.imshow(isolated_cell)\n#                     plt.show()\n                    \n                    label = 0\n                    confidence = 1\n\n                    bmask = (cell_mask == number)\n                    enc = encode_binary_mask(bmask)\n                    predstring += str(label) + ' ' + str(confidence) + ' ' + enc + ' '\n                predstrings.append(predstring)\n\n                sys.exit()\n\n            assert len(predstrings) == len(sub.loc[start:end-1])\n            sub['PredictionString'].loc[start:end-1] = predstrings\n\n        except: continue","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"all_subs = pd.concat(sub_dfs, ignore_index=True, sort=False)\nall_subs.to_csv('submission.csv', index=False)\n# all_subs.head()\n# all_subs.tail()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Visualisations","metadata":{}},{"cell_type":"code","source":"# image_id = sub_dfs[0]['ID'].loc[2]\n# image = build_image_names(image_id=image_id)\n# arrays = image_name_to_numpy(image)\n# nuclei = arrays[1]\n# cell = arrays[:-1]\n\n# # Nuclei segmentation\n# nuc_segmentations = segmentator.pred_nuclei(image[1])\n\n# f, ax = plt.subplots(1, 2, figsize=(16,16))\n# ax[0].imshow(arrays[1])\n# ax[0].set_title('Original Nucleis', size=20)\n# ax[1].imshow(nuc_segmentations[0])\n# ax[1].set_title('Segmented Nucleis', size=20)\n# plt.show()\n\n# # Cell segmentation\n# inter_step = [i for i in image[:-1]]\n# print(inter_step)\n# cell_segmentations = segmentator.pred_cells(inter_step)\n\n# f, ax = plt.subplots(1, 2, figsize=(16,16))\n# ax[0].imshow(get_blended_image(arrays))\n# ax[0].set_title('Original Cells', size=20)\n# ax[1].imshow(cell_segmentations[0])\n# ax[1].set_title('Segmented Cells', size=20)\n# plt.show()\n\n# # Nuclei mask\n# nuclei_mask = label_nuclei(nuc_segmentations[0])\n# # Cell masks\n# cell_nuclei_mask, cell_mask = label_cell(nuc_segmentations[0], cell_segmentations[0])\n\n# # Unique vector of cell_mask numbers\n# numbers = set(np.ravel(cell_mask))\n# numbers.remove(0)\n\n# fig = plt.figure(figsize=(25,6*len(numbers)/4))\n# index = 1\n\n# ax = fig.add_subplot(len(numbers)//4+1, 4, index)\n# ax.set_title(\"Complete Cell Mask\", size=20)\n# plt.imshow(cell_mask)\n\n# index += 1\n# for number in numbers:\n#     isolated_cell = np.where(cell_mask==number, cell_mask, 0)\n#     ax = fig.add_subplot(len(numbers)//4+1, 4, index)\n#     ax.set_title(\"Segment {number}\", size=20)\n#     plt.imshow(isolated_cell)\n#     index += 1\n    \n# for number in numbers:\n#     isolated_cell = np.where(cell_mask==number, cell_mask, 0)\n#     x = (cell_mask==number).astype(np.uint8)\n#     x_min, y_min, x_max, y_max = get_contour_from_mask(x)\n#     isolated_cell = isolated_cell[y_min:y_max, x_min:x_max]\n#     plt.imshow(isolated_cell)\n#     plt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}