{"cells":[{"metadata":{"_uuid":"a88ec878e33782bad4173ef959dfff2ff34edca4"},"cell_type":"markdown","source":"# Intro\nHere I will show a way to build a unified mask with borders between touching nuclei for the traning data.\nI am new to ML and from my understanding, making a one unified image of masks should make it easier to train the U-Net model. The problem with one unified image of masks is to distinguish between nuclei that are touching each other.\nOne way to get around that is by building a border between those nucleis and training the network.\n\nInsperation for this code I took from the Kjetil Åmdal-SævikKeras notebook \"U-Net starter - LB 0.277\": [https://www.kaggle.com/keegil/keras-u-net-starter-lb-0-277](https://www.kaggle.com/keegil/keras-u-net-starter-lb-0-277)"},{"metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","collapsed":true,"trusted":true},"cell_type":"code","source":"import os\nfrom tqdm import tqdm\nimport numpy as np\nimport random\nimport matplotlib as plt\n\nfrom skimage import feature\nfrom skimage.io import imread, imshow\nfrom skimage.transform import SimilarityTransform, warp\n\n%matplotlib inline","execution_count":7,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"TRAIN_PATH = '../input/stage1_train/'\n\ntrain_ids = next(os.walk(TRAIN_PATH))[1]","execution_count":4,"outputs":[]},{"metadata":{"_uuid":"333600a7ce5d0ffb42fa56962d7aaea0efdebd63"},"cell_type":"markdown","source":"Lets take a random image and see whats the problem:"},{"metadata":{"trusted":true,"collapsed":true,"_uuid":"40432ff96f63625dc3c0d5c079b3d107d5daac1f"},"cell_type":"code","source":"def create_unified_mask(image_path, mask_shape):\n    \n    final_mask = np.zeros(mask_shape)\n    \n    masks = next(os.walk(TRAIN_PATH + image_path + '/masks/'))[2]\n        \n    for mask in masks:\n        m = imread(TRAIN_PATH + image_path + '/masks/' + mask)        \n        final_mask = np.maximum(final_mask, m)\n    \n    return final_mask","execution_count":11,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"3d752481bc493f7a6f2f5ecea3b74150dd36b7c4"},"cell_type":"code","source":"image_path = train_ids[random.randint(0, len(train_ids))]\nimg = imread(TRAIN_PATH + image_path + '/images/' + image_path + '.png')\nunified_mask = create_unified_mask(image_path, img.shape[0:2])\n\nimshow(unified_mask)","execution_count":13,"outputs":[]},{"metadata":{"_uuid":"3be6189e4340828384ce96aa27ee4536625240f2"},"cell_type":"markdown","source":"We can clearly see the that there are nuclei that are touching each other with no easy way to separate them.\n\nA simple way to overcome this is by shifting each mask and comparing it to other masks and zero the pixels that overlap."},{"metadata":{"trusted":true,"collapsed":true,"_uuid":"ea4b7263bdd3aa73beae18dc1cf683757db82a33"},"cell_type":"code","source":"def create_unified_mask_with_borders(image_path, mask_shape):\n    \n    final_mask = np.zeros(mask_shape)\n    \n    masks = next(os.walk(TRAIN_PATH + image_path + '/masks/'))[2]\n        \n    for mask in masks:\n        m = imread(TRAIN_PATH + image_path + '/masks/' + mask) / 255\n        \n        image_left = warp(m, SimilarityTransform(translation=(2, 0)))\n        image_right = warp(m, SimilarityTransform(translation=(-2, 0)))\n        image_up = warp(m, SimilarityTransform(translation=(0, 2)))\n        image_down = warp(m, SimilarityTransform(translation=(0, -2)))\n        \n        border = final_mask + image_left == 2\n        border = np.logical_or(border, final_mask + image_right == 2)\n        border = np.logical_or(border, final_mask + image_up == 2)\n        border = np.logical_or(border, final_mask + image_down == 2)\n        \n        final_mask = np.maximum(final_mask, m)\n        final_mask[border] = 0\n    \n    return final_mask","execution_count":18,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"f91078da74cbad6a4ee78e1dd401839ad0e67ccf"},"cell_type":"code","source":"unified_mask_with_border = create_unified_mask_with_borders(image_path, img.shape[0:2])\n\nimshow(unified_mask_with_border)","execution_count":19,"outputs":[]},{"metadata":{"_uuid":"cbe10aec4d9c680f8cfdc297b1c55a73593feabe"},"cell_type":"markdown","source":"The problem in this solution is that we introduce an error to the training data which is generaly bad but on the other hand it is a fast and easy way to start working with U-Net."}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.4","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}