{"cells":[{"metadata":{},"cell_type":"markdown","source":"# Simple Tile Visualizer and Subplot Modules\n\nI, like many in this competition, am taking strong notes from [@iafoss](https://www.kaggle.com/iafoss) and his series of [Tiling Notebooks](https://www.kaggle.com/iafoss/panda-concat-tile-pooling-starter-inference) and [Discussions](https://www.kaggle.com/c/prostate-cancer-grade-assessment/discussion/146855). \n\nI wanted to make a quick module that visulizes where the tiles are coming from in an image in order to help with further analysis I am doing. In this process I also wanted to make a quick mayplotlib module that would show the tiles selected.\n\nHopefully this is helpful for others as well!\n\nAs I had my head down working on this I did not get a chance to look at the amazing work done by [@harupy](https://www.kaggle.com/harupy) in the notebook: [Visualization: PANDA 16x128x128 tiles](https://www.kaggle.com/harupy/visualization-panda-16x128x128-tiles). It goes into great deatil on each of the steps in this process and is definitely worth looking at!"},{"metadata":{},"cell_type":"markdown","source":"# Base Image"},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"# All imports\nimport matplotlib.pyplot as plt\nplt.rcParams[\"figure.figsize\"] = (10,7)\nimport numpy as np\nimport skimage.io\n\n#Set up base levels\nslide_dir = \"../input/prostate-cancer-grade-assessment/train_images/\"\nannotation_dir = \"../input/prostate-cancer-grade-assessment/train_label_masks/\"\nexample_id = \"0032bfa835ce0f43a92ae0bbab6871cb\"\nexample_slide = f\"{slide_dir}{example_id}.tiff\"\n\n# Open slide on lowest resolution\nlow_res_lvl = -1\nimg_low = skimage.io.MultiImage(example_slide)[low_res_lvl]\nplt.imshow(img_low)\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Basic Subplot Module to Show Selected Slides"},{"metadata":{"trusted":true},"cell_type":"code","source":"def plot_tiles(tile_list):\n    \"\"\"\n    Description\n    ----------\n    Plot a list of tissue tiles four wide\n    Credit: https://stackoverflow.com/a/11172032\n\n    Parameters\n    ----------\n    tile_list: list \n        List of tiles to be ploted\n    Returns(0)\n    ----------\n    \"\"\"\n    \n    nrows = -(-len(tile_list)//4)\n    ncols = 4\n    figures = {f\"Tile: {i+1}\":tile for i,tile in enumerate(tile_list)}\n    \n    fig, axeslist = plt.subplots(ncols=ncols, nrows=nrows)\n    for ind, title in enumerate(figures):\n        axeslist.ravel()[ind].imshow(figures[title], aspect=\"auto\")\n        axeslist.ravel()[ind].set_title(title)\n    plt.tight_layout()\n    plt.show()\n    return ","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"def tile(img):\n    shape = img.shape\n    pad0,pad1 = (sz - shape[0]%sz)%sz, (sz - shape[1]%sz)%sz\n    img = np.pad(img,[[pad0//2,pad0-pad0//2],[pad1//2,pad1-pad1//2],[0,0]],\n                 constant_values=255)\n    img = img.reshape(img.shape[0]//sz,sz,img.shape[1]//sz,sz,3)\n    img = img.transpose(0,2,1,3,4).reshape(-1,sz,sz,3)\n    if len(img) < N:\n        img = np.pad(img,[[0,N-len(img)],[0,0],[0,0],[0,0]],constant_values=255)\n    idxs = np.argsort(img.reshape(img.shape[0],-1).sum(-1))[:N]\n    img = img[idxs]\n    return img\n\nN=12\nsz=128\ntiles = tile(img_low)\nplot_tiles(tiles)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Tile Vizualizer Module with Plot Option\n\nI also added some of my own notes to the base module in order to help clarify the steps and wonderful wizardry done by @iafoss."},{"metadata":{"trusted":true},"cell_type":"code","source":"def tile_plot(base_image, N=12, sz=128, plot=True):\n    \"\"\"\n    Description\n    __________\n    Tilizer module made by @iafoss that can be found in the notebook:\n    https://www.kaggle.com/iafoss/panda-concat-tile-pooling-starter-inference\n    Takes a base image and returns the N tiles with the largest differnce\n    from a white backgound each with a given square size of input-sz.\n    \n    Parameters\n    __________\n    base_image: numpy array\n        Image array to split into tiles and plot\n    N: int\n        This is the number of tiles to split the image into\n    sz: int\n        This is the size for each side of the square tiles\n    plot: bool\n        True to show plot of choosen tiles, False for silent return\n    \n    Returns\n    __________\n    - List of size N with each item being a numpy array tile.\n    \"\"\"\n    \n    #Get the shape of the input image\n    shape = base_image.shape\n    \n    #Find the padding such that the image divides evenly by the desired size\n    pad0,pad1 = (sz - shape[0]%sz)%sz, (sz - shape[1]%sz)%sz\n    \n    #Pad the image with blank space to reach the above found tagrgets\n    base_img = np.pad(base_image,[[pad0//2,pad0-pad0//2],\n                                  [pad1//2,pad1-pad1//2],[0,0]],\n                                     constant_values=255)\n    \n    #Reshape and Transpose to get the images into tiles\n    all_tiles = base_img.reshape(base_img.shape[0]//sz,sz,base_img.shape[1]//sz,sz,3)\n    all_tiles = all_tiles.transpose(0,2,1,3,4).reshape(-1,sz,sz,3)\n    \n    #If there are not enough tiles to meet desired N pad again\n    if len(all_tiles) < N:\n        all_tiles = np.pad(all_tiles,[[0,N-len(all_tiles)],[0,0],[0,0],[0,0]],\n                                       constant_values=255) \n    \n    #Sort the images by those with the lowest sum (i.e the least white)\n    #Return indexes to the lowest N \n    idxs = np.argsort(all_tiles.reshape(all_tiles.shape[0],-1).sum(-1))[:N]\n    \n    #Slect by index those returned from the above funtion\n    tissue_tiles = all_tiles[idxs]\n    \n    if plot:\n        #Funciton for plotting\n        line_color=[0,255,255]\n        line_sz=5\n        #Get the deminsions in terms of slides\n        tile_cnt_size = [base_img.shape[0]//sz, base_img.shape[1]//sz]\n        \n        #Iterate through all images and change the boarder on the slected images\n        prod_tiles = []\n        for i,img in enumerate(all_tiles):\n            if i in idxs:\n                #If image is in the slected slides change the..\n                #Left\n                img[:,:line_sz,:] =  [[line_color]*line_sz]*sz\n                #Right\n                img[:,-line_sz:,:] =  [[line_color]*line_sz]*sz\n                #Top\n                img[:line_sz] =  [[line_color]*sz]*line_sz\n                #Bottom\n                img[-line_sz:] =  [[line_color]*sz]*line_sz\n                #... boarders to the specified color\n            prod_tiles.append(img)\n            \n        #Piece the tiles back into one image\n        #Split the array of tiles into a list of rows\n        rows = np.array_split(prod_tiles,tile_cnt_size[0])\n        #Horizontally combine rows\n        row_combine = [np.hstack(tiles) for tiles in rows]\n        #Vertically stack rows back into base image\n        prod_image = np.vstack(row_combine)\n        #Display image\n        plt.imshow(prod_image)\n        plt.show()\n    return tissue_tiles\n\ntiles = tile_plot(img_low, plot=True)","execution_count":null,"outputs":[]}],"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":4,"nbformat_minor":4}