{"cells":[{"metadata":{"_uuid":"29a81f23e5817d2e6c626729def0dcfddc5708a8"},"cell_type":"markdown","source":"# Introduction\n\nNuclei are distinctive in every image and spotting each of them manually with human eye is tedious and time consuming. Not to mention the fact that manual spotting can also lead to errors. \nThough the task here is to  identify a range of nuclei across varied conditions, this notebook is an introductory approach for detecting nuclei in a nuclus. We only see analyse the data (using opencv and scipy-image).  "},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport os\nfrom os.path import join\nimport glob\nimport cv2\nimport random \n\nimport matplotlib.pyplot as plt","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"train_path = '../input/stage1_train/'\ntest_path = '../input/stage1_test/'\n\nseed = 42\nrandom.seed = seed\nnp.random.seed = seed\n\nimport pathlib\ntrain_path = pathlib.Path(train_path).glob('*/images/*.png')\nprint(train_path)\n\ntrain_sorted = sorted([i for i in train_path])\nprint(len(train_sorted))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"36bc29d9492ea6eebc7920b5df769c94697eaa85","scrolled":false},"cell_type":"code","source":"# show a random image by converting it to grayscale\nim = np.random.choice(train_sorted)\nim = cv2.imread(str(im), cv2.IMREAD_GRAYSCALE)\nplt.imshow(im)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"85bbfcee90e5f0fbb4f353fa52c3a1202d025463"},"cell_type":"markdown","source":"## Image masking\n\nWe perform image masking by applying a threshold function to the grayscale image. This can be performed through OTSU threshoulding where the background is zeroed. \n\n#### Alternative approach. \nAlternatively thresholding can be done using cv2.threshold. \ncv2.threshold : First argument is the source image, which should be a grayscale image. Second argument is the threshold value which is used to classify the pixel values. Third argument is the maxVal which represents the value to be given if pixel value is more than (sometimes less than) the threshold value.\n"},{"metadata":{"trusted":true,"_uuid":"ed1e027667a1058db2de1c66e0ec0807ec018eb1"},"cell_type":"code","source":"# using opencv otsu\n# ret, thresh_val = cv2.threshold(im,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)\nret, thresh_val = cv2.threshold(im, 100, 255, cv2.THRESH_OTSU)\nprint(ret)\nprint(thresh_val)\n\n# # show the original image and the image after threshoulding\n# fig, ax = plt.subplots(1, 2, figsize=(10,10))\n# ax[0].imshow(im)\n# ax[1].imshow(thresh_val)\n\nfrom skimage.filters import threshold_otsu\n# alternative threshoulding \nthresh_val_1 = threshold_otsu(im)\nprint('Otsu Threshold',thresh_val_1)\n\n# Compute masks using threshould\nmask = np.where(im > thresh_val_1, 1, 0) # masks are encoded as 1 and others as 0\nprint('Original image shape',im.shape)\nprint('Mast shape', mask.shape)\n\n# show original and masked images\nfig, ax = plt.subplots(1, 2, figsize=(10,10))\nax[0].imshow(im)\nax[1].imshow(mask)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"40fa90097365d78272f16d9046c1bee5d7a04068"},"cell_type":"code","source":"display_mask = np.where(mask, mask, np.nan)\nprint('Display mask shape:', display_mask.shape)\n\nif np.sum(mask==0) < np.sum(mask==1):\n    mask = np.where(mask, 0, 1)\n\n# Plot images \nplt.figure(figsize=(10,4))\nplt.subplot(1,2,2)\nplt.imshow(im, cmap='gray')\nplt.imshow(mask, cmap='rainbow', alpha=0.5)\nplt.axis('off')\nplt.title('Image with Mask')\n\n# image without mask\nplt.figure(figsize=(10,4))\nplt.subplot(1,2,2)\nplt.imshow(im, cmap='gray')\nplt.imshow(display_mask, cmap='rainbow', alpha=0.5)\nplt.axis('off')\nplt.title('Image without Mask')\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"402d416be2e17d32d734579eab17c7b323c438ad"},"cell_type":"markdown","source":"## Assigning labels to masks "},{"metadata":{"trusted":true,"scrolled":true,"_uuid":"6be9cd31fa5974f417b26432b1a70ee55cadf9e8"},"cell_type":"code","source":"from scipy import ndimage\nlabels, nlabels = ndimage.label(mask)\n\nprint('No of labels found = ', nlabels)\n\nlabel_arrays = []\nfor label_num in range(1, nlabels+1):\n    label_mask = np.where(labels == label_num, 1, 0)\n    label_arrays.append(label_mask)\n\nprint('{} separate objects detected.'.format(nlabels))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"6d4e0be6659573d983a22c06039ffcdad278cff5"},"cell_type":"markdown","source":"## Flatten masks and run line encode it\n\nEncode each label mask into a run line code. "},{"metadata":{"trusted":true,"scrolled":true,"_uuid":"cffb3a3be4f104b5e611ea50505f8780903b4f1c"},"cell_type":"code","source":"# flatten masks \nlabel_mask.T.flatten()\n\ndef rle_encoding(x):\n    dots = np.where(x.T.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([str(i) for i in run_lengths])\n\nprint('RLE Encoding for the current mask : {}'.format(rle_encoding(label_mask)))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"356112b33c95219c11f05d87feeccc1099ff66a5","scrolled":true},"cell_type":"code","source":"# example of a flattened mask image\nx = np.where(label_mask.T.flatten()==1)[0]\nx = np.array(x)\nx.shape","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"cf4b55f3d76909a3c8b53e0e32a9393bfddba626"},"cell_type":"markdown","source":"What remains now is to combine all this to read all the images and generate an RLE for each of the image, such that the RLE are saved into a dataframe. \n\n\n### Reference\n* A big shout out to [Stephen](https://www.kaggle.com/stkbailey) for his amazing work on this topic. \n"},{"metadata":{"trusted":true,"_uuid":"0450e2de64934417f5e18efe401af72820c8a46a"},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.6","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}