{"cells":[{"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 glob\nimport gc\nfrom pathlib import Path\nfrom openslide import OpenSlide\nfrom tqdm import tqdm","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"TRAIN_DIR = Path('/kaggle/input/prostate-cancer-grade-assessment/train_images/')\nwsis_subset = glob.glob(f'{str(TRAIN_DIR)}/*.tiff')[:10]\npatch_size = 128","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"def extract_non_white_positions(slide_file, patch_size, cuts=2):\n    \"\"\"\n        Method used to extract the non white patch positions of a WSI, ignore the patch_size margins at the right and bottom of the WSI\n    :param slide_file: The slide file\n    :param patch_size: patch size\n    :param cuts: Lower number = faster process but require more RAM/Higher number = slower but require less RAM. \n        Play with that setting if you get an OOM on the Kaggle kernel on the test set. \n        If you train on your own machine and you have enough RAM you probably want to set that parameter to 1\n    :return: Patches positions\n    \"\"\"\n    slide_img = OpenSlide(str(slide_file))\n    slide_width, slide_height = slide_img.dimensions\n\n    # Make sure x_cuts is a multiple of patch_size\n    x_cuts = np.arange(0, slide_width, step=patch_size)\n    x_cuts = [x_cuts[i] for i in range(0, len(x_cuts), len(x_cuts) // cuts)]\n\n    # The patch_size on the right and at the bottom of the WSI will be cropped out, not a big deal\n    x_cuts.append(slide_width)\n    patches_pos = None\n    for cut_idx in range(1, cuts + 1):  # Horizontal sliding window\n        start = (x_cuts[cut_idx - 1], 0)\n        stop_size = (x_cuts[cut_idx] - x_cuts[cut_idx - 1], slide_height)\n        # Always open at lvl 0 because of a bug with Openslide with white patches and always using lvl 0 pos\n        pil_img = slide_img.read_region(start, 0, stop_size)\n        img = np.array(pil_img)\n\n        # If there is only 1 color (we assume it's either all black or all white)\n        if len(set(np.array(pil_img.getextrema()).flatten())) <= 1:\n            continue\n\n        imsize = (img.shape[0], img.shape[1])\n        nx, ny = (int(dim / patch_size) for dim in imsize)\n        img = img[:nx * patch_size, :ny * patch_size, :]\n\n        # reshape padded image according to patches; doesn't copy memory\n        patched = img.reshape(nx, patch_size, ny, patch_size, img.shape[2]).transpose(0, 2, 1, 3, 4)\n        # check for white patches\n        filt = ~(patched == 255).all((2, 3, 4))\n        patch_x, patch_y = filt.nonzero()  # patch indices of non-whites from 0 to nx-1, 0 to ny-1\n        patch_pixel_x = patch_x * patch_size  # proper pixel indices of each pixel\n        patch_pixel_y = patch_y * patch_size\n        transposed_pos = np.array([patch_pixel_y, patch_pixel_x]).T\n        if patches_pos is None:\n            patches_pos = transposed_pos\n        else:\n            patches_pos = np.concatenate([patches_pos, transposed_pos])\n        del img\n        gc.collect()\n    return patches_pos","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"wsi_patches = {}\nfor wsi in tqdm(wsis_subset, desc=\"Filtering out white patches\"):\n    wsi_file = TRAIN_DIR / wsi\n    patch_pos = extract_non_white_positions(wsi_file, patch_size, cuts=4)\n    wsi_patches[wsi] = patch_pos\n    print(f\"Size of {wsi} patches = {len(patch_pos)}\")\n    \nprint(f\"Done! Do something with your patches :)\")","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}