{"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":"## Mayo Clinic - STRIP AI -  Understanding image processing \n\nuse `PIL` (pillow package) and `torchvision` to load and process images.\n\n- Get image metadata\n    - get file size and create/update timestamps via `pathlib`\n    - get image metadata via `PIL` package\n        - image lenght, width, mode, and so on\n- resize images `PIL` package\n    - use `PIL` thumbnail to resize images while keeping the original image height/width ratio\n    - note that when converting `PIL` object to numpy, the data is in `[0, 255]` not `[0, 1]`\n- crop and pad images by `torchvision` tranforms\n    - use `torchvision` to crop and pad images\n    - **crop** image: \n        - when the original size is 512*480, and by cropping the image to 512, the new image will be 512*512, and the additional area is filled with 0 (shown as black)\n        - when the original size is 512*480 and by cropping the image to 480, the new image will be 480*480\n    - **pad** image: \n        - when the original size is 512*480, and by padding the image by 10, the new image will be 522*490, the addtional area is filled with 0 (shown as black)\n- add guassion blur to images by `torchvision` tranforms\n- normalize images via `torchvisaion` transforms normalize function: \n    - first convert the `PIL` image object into numpy array (the data range is `0, 255]`)\n    - then reshape the numpy array from height*width*channels (for rgb images, the number of channels is 3) to channels*height*width\n    - make the data range from `[0, 255]` to `[0. 1]`\n    - normalize the data using `torchvision` *transforms.functional.normalize*\n    - reshape the numpy back to height*width*channels\n- remove white space\n    ","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport os\nfrom pathlib import Path\n\nfrom datetime import datetime, timedelta\nimport time\n\nimport gc\nimport copy\n\nimport pyarrow.parquet as pq\nimport pyarrow as pa\n\n \nfrom dateutil.relativedelta import relativedelta\nfrom sklearn.preprocessing import StandardScaler, MinMaxScaler\n\nfrom sklearn.metrics import mean_squared_error, roc_auc_score\nfrom sklearn.model_selection import StratifiedKFold, KFold\n\npd.options.display.max_rows = 100\npd.options.display.max_columns = 100\n\nimport warnings\nwarnings.filterwarnings(\"ignore\")\n\nimport pytorch_lightning as pl\nrandom_seed=1234\npl.seed_everything(random_seed)\n\n\n\nimport torch\nfrom torch import nn\nimport numpy as np\n\n\nimport torch\nfrom torch.utils.data import (Dataset, DataLoader)\n\n\n#basic libs\n\nimport pandas as pd\nimport numpy as np\nimport os\nfrom pathlib import Path\n\nfrom datetime import datetime, timedelta\nimport time\nfrom dateutil.relativedelta import relativedelta\n\nimport gc\nimport copy\n\n#additional data processing\n\nimport pyarrow.parquet as pq\nimport pyarrow as pa\n\nfrom sklearn.preprocessing import StandardScaler, MinMaxScaler\n\n\n#visualization\nimport seaborn as sns\nimport matplotlib.pyplot as plt\n\n#load images\nimport matplotlib.image as mpimg\nimport PIL\nfrom PIL import Image\n\n\n\n\n#settings\npd.options.display.max_rows = 100\npd.options.display.max_columns = 100\n\nImage.MAX_IMAGE_PIXELS = None\n\nimport warnings\nwarnings.filterwarnings(\"ignore\")\n\nimport pytorch_lightning as pl\nrandom_seed=1234\npl.seed_everything(random_seed)","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-08-02T13:06:17.272739Z","iopub.execute_input":"2022-08-02T13:06:17.273241Z","iopub.status.idle":"2022-08-02T13:06:19.489733Z","shell.execute_reply.started":"2022-08-02T13:06:17.273135Z","shell.execute_reply":"2022-08-02T13:06:19.488279Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torch.optim import lr_scheduler\nimport torch.backends.cudnn as cudnn\nimport numpy as np\nimport torchvision\nfrom torchvision import datasets, models, transforms\nimport matplotlib.pyplot as plt","metadata":{"execution":{"iopub.status.busy":"2022-08-02T13:06:19.491291Z","iopub.execute_input":"2022-08-02T13:06:19.492205Z","iopub.status.idle":"2022-08-02T13:06:19.498623Z","shell.execute_reply.started":"2022-08-02T13:06:19.492166Z","shell.execute_reply":"2022-08-02T13:06:19.497766Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"next(os.walk(\"../input\"))[1]","metadata":{"execution":{"iopub.status.busy":"2022-08-02T13:06:19.500365Z","iopub.execute_input":"2022-08-02T13:06:19.500761Z","iopub.status.idle":"2022-08-02T13:06:19.513678Z","shell.execute_reply.started":"2022-08-02T13:06:19.500729Z","shell.execute_reply":"2022-08-02T13:06:19.512344Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img_folder = '../input/mayo-clinic-strip-ai/train'\nimg_path = f'{img_folder}/777311_0.tif' \n# img_path = f'{img_folder}/006388_0.png'","metadata":{"execution":{"iopub.status.busy":"2022-08-02T13:06:19.516708Z","iopub.execute_input":"2022-08-02T13:06:19.517079Z","iopub.status.idle":"2022-08-02T13:06:19.525134Z","shell.execute_reply.started":"2022-08-02T13:06:19.517046Z","shell.execute_reply":"2022-08-02T13:06:19.523912Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Get image metadata","metadata":{}},{"cell_type":"code","source":"#check the file info\nPath(img_path).stat()","metadata":{"execution":{"iopub.status.busy":"2022-08-02T13:06:20.217868Z","iopub.execute_input":"2022-08-02T13:06:20.218261Z","iopub.status.idle":"2022-08-02T13:06:20.226634Z","shell.execute_reply.started":"2022-08-02T13:06:20.21823Z","shell.execute_reply":"2022-08-02T13:06:20.225479Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#get image meta data using pillow\n#https://pillow.readthedocs.io/en/stable/reference/Image.html?highlight=attributes#image-attributes\n\nimg = Image.open(img_path)\n\nmeta_dict = {    \n            'filename': img.filename,\n            'format': img.format, \n            'mode': img.mode,  \n            'size': img.size,  #2-tuple (width, height).\n            'width': img.width, \n            'height': img.height, \n            'palette': img.palette, \n            'info': img.info, \n            'is_animated': img.is_animated, \n            'n_frames': img.n_frames, \n}\n\n# img.close()\n# del img\n# gc.collect()\n\nmeta_dict","metadata":{"execution":{"iopub.status.busy":"2022-08-02T13:08:24.021607Z","iopub.execute_input":"2022-08-02T13:08:24.0221Z","iopub.status.idle":"2022-08-02T13:08:24.032728Z","shell.execute_reply.started":"2022-08-02T13:08:24.022068Z","shell.execute_reply":"2022-08-02T13:08:24.031624Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Load and resize images","metadata":{}},{"cell_type":"code","source":"#get the image size (width, height)\n# img = Image.open(img_path)\nprint(img.size, img.height, img.width)\n# img = np.asarray(img)","metadata":{"execution":{"iopub.status.busy":"2022-08-02T13:09:41.512864Z","iopub.execute_input":"2022-08-02T13:09:41.513851Z","iopub.status.idle":"2022-08-02T13:09:41.519537Z","shell.execute_reply.started":"2022-08-02T13:09:41.513815Z","shell.execute_reply":"2022-08-02T13:09:41.518001Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\n#display the original image\nplt.figure(figsize=(8, 8))\nplt.imshow(img)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-08-02T13:08:53.18201Z","iopub.execute_input":"2022-08-02T13:08:53.182826Z","iopub.status.idle":"2022-08-02T13:09:39.856275Z","shell.execute_reply.started":"2022-08-02T13:08:53.18277Z","shell.execute_reply":"2022-08-02T13:09:39.8554Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#https://stackoverflow.com/questions/71738218/module-pil-has-not-attribute-resampling\n#dealing with pillow version differences\nprint(PIL.__version__)","metadata":{"execution":{"iopub.status.busy":"2022-08-02T13:10:28.757867Z","iopub.execute_input":"2022-08-02T13:10:28.758359Z","iopub.status.idle":"2022-08-02T13:10:28.765088Z","shell.execute_reply.started":"2022-08-02T13:10:28.7583Z","shell.execute_reply":"2022-08-02T13:10:28.764037Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#create the thumbnail of the image\n\nif hasattr(Image, 'Resampling'):  # Pillow<8.4.0\n    img.thumbnail((1024, 1024), resample=Image.Resampling.LANCZOS, reducing_gap=10)\n    if (img.height> img.width):\n        img = img.transpose(PIL.Image.Transpose.ROTATE_90)\nelse:\n    img.thumbnail((1024, 1024), resample=Image.LANCZOS, reducing_gap=10)\n    if (img.height> img.width):\n        img = img.transpose(PIL.Image.ROTATE_90)\n    \nplt.figure(figsize=(8, 8))\nplt.imshow(img)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-08-02T13:10:44.70375Z","iopub.execute_input":"2022-08-02T13:10:44.704617Z","iopub.status.idle":"2022-08-02T13:10:48.395862Z","shell.execute_reply.started":"2022-08-02T13:10:44.704573Z","shell.execute_reply":"2022-08-02T13:10:48.394611Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(img.size)\nnp.asarray(img, np.uint8).min(), np.asarray(img, np.uint8).max()","metadata":{"execution":{"iopub.status.busy":"2022-08-02T13:11:12.108092Z","iopub.execute_input":"2022-08-02T13:11:12.108815Z","iopub.status.idle":"2022-08-02T13:11:12.12486Z","shell.execute_reply.started":"2022-08-02T13:11:12.108775Z","shell.execute_reply":"2022-08-02T13:11:12.123599Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Crop and pad images by torchvisaion tranforms","metadata":{}},{"cell_type":"code","source":"#https://stackoverflow.com/questions/10965417/how-to-convert-a-numpy-array-to-pil-image-applying-matplotlib-colormap\n\n#use torchvision to center crop the image\nimg2 = transforms.functional.center_crop(img, 1024)\nprint(img2.size)\nplt.figure(figsize=(8, 8))\nplt.imshow(img2)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-08-02T13:14:37.246509Z","iopub.execute_input":"2022-08-02T13:14:37.246942Z","iopub.status.idle":"2022-08-02T13:14:37.61112Z","shell.execute_reply.started":"2022-08-02T13:14:37.246905Z","shell.execute_reply":"2022-08-02T13:14:37.610004Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"np.asarray(img2, np.uint8).min(), np.asarray(img2, np.uint8).max()","metadata":{"execution":{"iopub.status.busy":"2022-08-02T13:14:42.758989Z","iopub.execute_input":"2022-08-02T13:14:42.759456Z","iopub.status.idle":"2022-08-02T13:14:42.777709Z","shell.execute_reply.started":"2022-08-02T13:14:42.759411Z","shell.execute_reply":"2022-08-02T13:14:42.776431Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img3 = transforms.functional.pad(img, 10)\nprint(img3.size)\nplt.figure(figsize=(8, 8))\nplt.imshow(img3)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-08-02T13:14:48.897598Z","iopub.execute_input":"2022-08-02T13:14:48.898184Z","iopub.status.idle":"2022-08-02T13:14:49.175569Z","shell.execute_reply.started":"2022-08-02T13:14:48.898151Z","shell.execute_reply":"2022-08-02T13:14:49.174233Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"np.asarray(img3, np.uint8).min(), np.asarray(img3, np.uint8).max()","metadata":{"execution":{"iopub.status.busy":"2022-08-02T13:14:53.607488Z","iopub.execute_input":"2022-08-02T13:14:53.607878Z","iopub.status.idle":"2022-08-02T13:14:53.621144Z","shell.execute_reply.started":"2022-08-02T13:14:53.607845Z","shell.execute_reply":"2022-08-02T13:14:53.620023Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Add Gaussian Blur to images","metadata":{}},{"cell_type":"code","source":"img4 = transforms.functional.gaussian_blur(img, kernel_size=(5, 9), sigma=(0.1, 5))\nprint(img4.size)\nplt.figure(figsize=(8, 8))\nplt.imshow(img4)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-08-02T13:15:04.529204Z","iopub.execute_input":"2022-08-02T13:15:04.529652Z","iopub.status.idle":"2022-08-02T13:15:04.941828Z","shell.execute_reply.started":"2022-08-02T13:15:04.529617Z","shell.execute_reply":"2022-08-02T13:15:04.940521Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#not that before adding the gaussian blur, the data range is [0, 255]\n#after the guassian blur, the range is [1, 254]\nnp.asarray(img4, np.uint8).min(), np.asarray(img4, np.uint8).max()","metadata":{"execution":{"iopub.status.busy":"2022-08-02T13:17:43.914053Z","iopub.execute_input":"2022-08-02T13:17:43.914475Z","iopub.status.idle":"2022-08-02T13:17:43.928089Z","shell.execute_reply.started":"2022-08-02T13:17:43.914442Z","shell.execute_reply":"2022-08-02T13:17:43.927172Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#https://dsp.stackexchange.com/questions/10057/gaussian-blur-standard-deviation-radius-and-kernel-size\n#try different kernal sizes\n\nfig, axes = plt.subplots(nrows=2, ncols=2, figsize=(16, 8))\n\nfor i, k_sizes  in enumerate([(5, 5), (5, 9),(15, 15), (25, 45)]):\n    img4 = transforms.functional.gaussian_blur(img, kernel_size=k_sizes, sigma=(0.1, 5))\n    print(i, k_sizes, img4.size, np.asarray(img4, np.uint8).min(), np.asarray(img4, np.uint8).max())\n    axes[i%2, i//2].imshow(img4)\n    axes[i%2, i//2].set_title(f'{k_sizes}')\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-08-02T13:46:43.211703Z","iopub.execute_input":"2022-08-02T13:46:43.212133Z","iopub.status.idle":"2022-08-02T13:46:44.484716Z","shell.execute_reply.started":"2022-08-02T13:46:43.212096Z","shell.execute_reply":"2022-08-02T13:46:44.483503Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#try different sigma\n\nfig, axes = plt.subplots(nrows=2, ncols=2, figsize=(16, 8))\n\nfor i, sigma  in enumerate([(0.1, 5), (0.05, 1),(0.01, 1), (0.8, 10)]):\n    img4 = transforms.functional.gaussian_blur(img, kernel_size=(5, 9), sigma=sigma)\n    print(i, k_sizes, img4.size, np.asarray(img4, np.uint8).min(), np.asarray(img4, np.uint8).max())\n    axes[i%2, i//2].imshow(img4)\n    axes[i%2, i//2].set_title(f'{sigma}')\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-08-02T13:50:19.26512Z","iopub.execute_input":"2022-08-02T13:50:19.265532Z","iopub.status.idle":"2022-08-02T13:50:20.261148Z","shell.execute_reply.started":"2022-08-02T13:50:19.265499Z","shell.execute_reply":"2022-08-02T13:50:20.260276Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#try different sigma and kernel_size\n\nfig, axes = plt.subplots(nrows=2, ncols=2, figsize=(16, 8))\n\nfor i, (sigma, k_sizes) in enumerate([[(0.1, 5), (5, 9)], [(0.1, 5), (35, 65)],\n                                     [(0.8, 10), (5, 9)], [(0.8, 10), (35, 65)]]):\n    img4 = transforms.functional.gaussian_blur(img, kernel_size=k_sizes, sigma=sigma)\n    print(i, k_sizes, img4.size, np.asarray(img4, np.uint8).min(), np.asarray(img4, np.uint8).max())\n    axes[i%2, i//2].imshow(img4)\n    axes[i%2, i//2].set_title(f'kernel_size={k_sizes}, sigma={sigma}')\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-08-02T13:54:56.611636Z","iopub.execute_input":"2022-08-02T13:54:56.612022Z","iopub.status.idle":"2022-08-02T13:55:00.531366Z","shell.execute_reply.started":"2022-08-02T13:54:56.611992Z","shell.execute_reply":"2022-08-02T13:55:00.530131Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img4 = transforms.functional.gaussian_blur(img2, kernel_size=(5, 9), sigma=(0.1, 5))\nprint(img4.size)\nplt.figure(figsize=(8, 8))\nplt.imshow(img4)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-08-02T13:56:31.446748Z","iopub.execute_input":"2022-08-02T13:56:31.447235Z","iopub.status.idle":"2022-08-02T13:56:31.984352Z","shell.execute_reply.started":"2022-08-02T13:56:31.447198Z","shell.execute_reply":"2022-08-02T13:56:31.983509Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"np.asarray(img4, np.uint8).min(), np.asarray(img4, np.uint8).max()","metadata":{"execution":{"iopub.status.busy":"2022-08-02T13:56:33.113259Z","iopub.execute_input":"2022-08-02T13:56:33.113694Z","iopub.status.idle":"2022-08-02T13:56:33.133254Z","shell.execute_reply.started":"2022-08-02T13:56:33.113659Z","shell.execute_reply":"2022-08-02T13:56:33.13242Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Normalize image\n\n- to apply the `torchvisaion` transforms normalize function:\n    - first convert the `PIL` image object into numpy array (the data range is `0, 255]`)\n    - then reshape the numpy array from height*width*channels (for rgb images, the number of channels is 3) to channels*height*width\n    - make the data range from `[0, 255]` to `[0. 1]`\n    - normalize the data using `torchvision` *transforms.functional.normalize*\n    - reshape the numpy back to height*width*channels\n    ","metadata":{}},{"cell_type":"code","source":"img5 = np.asarray(img)\nprint(img5.shape)\nprint(img5.min(), img5.max())\nimg5 = img5.transpose((2,0,1))\nprint(img5.shape)\nimg5 = img5/255\nprint(img5.min(), img5.max())\n#make sure the array is normalized to 0-1 before applying normalize\nimg5 = transforms.functional.normalize(torch.Tensor(img5), [0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\nimg5 = img5.numpy().transpose((1,2,0))\nprint(img5.min(), img5.max())","metadata":{"execution":{"iopub.status.busy":"2022-08-02T14:01:15.513335Z","iopub.execute_input":"2022-08-02T14:01:15.513786Z","iopub.status.idle":"2022-08-02T14:01:15.544081Z","shell.execute_reply.started":"2022-08-02T14:01:15.51375Z","shell.execute_reply":"2022-08-02T14:01:15.543088Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(16, 8))\n\naxes[0, 0].imshow(img)\naxes[0, 1].imshow(img5)\naxes[1, 0].imshow(np.clip(img5, 0, 1))\n\n\nimg5_1 = img/np.amax(img5) # if float\nimg5_1 = np.array(img5_1/np.amax(img5_1)*255, np.int32) # if int\naxes[1, 1].imshow(img5_1)\n\nplt.show()\n\n","metadata":{"execution":{"iopub.status.busy":"2022-08-02T14:05:24.923677Z","iopub.execute_input":"2022-08-02T14:05:24.924093Z","iopub.status.idle":"2022-08-02T14:05:25.799866Z","shell.execute_reply.started":"2022-08-02T14:05:24.924059Z","shell.execute_reply":"2022-08-02T14:05:25.79897Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"(np.uint8(img5)*255).min(), (np.uint8(img5)*255).max()","metadata":{"execution":{"iopub.status.busy":"2022-08-02T14:05:42.265695Z","iopub.execute_input":"2022-08-02T14:05:42.266092Z","iopub.status.idle":"2022-08-02T14:05:42.278946Z","shell.execute_reply.started":"2022-08-02T14:05:42.266062Z","shell.execute_reply":"2022-08-02T14:05:42.277389Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img5_1.min(), img5_1.max()","metadata":{"execution":{"iopub.status.busy":"2022-08-02T14:06:19.755132Z","iopub.execute_input":"2022-08-02T14:06:19.7561Z","iopub.status.idle":"2022-08-02T14:06:19.765717Z","shell.execute_reply.started":"2022-08-02T14:06:19.756053Z","shell.execute_reply":"2022-08-02T14:06:19.764376Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img5 = np.asarray(img2)\nprint(img5.shape)\n\nimg5 = img5.transpose((2,0,1))\nimg5 = img5/255\nimg5 = transforms.functional.normalize(torch.Tensor(img5), [0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\nimg5 = img5.numpy().transpose((1,2,0))\nplt.figure(figsize=(8, 8))\nplt.imshow(img5)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-08-02T14:06:37.435409Z","iopub.execute_input":"2022-08-02T14:06:37.435822Z","iopub.status.idle":"2022-08-02T14:06:37.911449Z","shell.execute_reply.started":"2022-08-02T14:06:37.435792Z","shell.execute_reply":"2022-08-02T14:06:37.910266Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(img5.min(), img5.max())","metadata":{"execution":{"iopub.status.busy":"2022-08-02T14:28:48.591025Z","iopub.execute_input":"2022-08-02T14:28:48.591446Z","iopub.status.idle":"2022-08-02T14:28:48.600665Z","shell.execute_reply.started":"2022-08-02T14:28:48.591411Z","shell.execute_reply":"2022-08-02T14:28:48.59944Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### remove empty space\n\nthe following is base on this [notebook](https://www.kaggle.com/code/jirkaborovec/bloodclots-eda-load-wsi-prune-background?scriptVersionId=101797769)","metadata":{}},{"cell_type":"code","source":"#https://www.kaggle.com/code/jirkaborovec/bloodclots-eda-load-wsi-prune-background?scriptVersionId=101797769\n\ndef prune_image_rows_cols(im, mask, thr=0.990):\n    # delete empty columns\n    for l in reversed(range(im.shape[1])):\n        if (np.sum(mask[:, l]) / float(mask.shape[0])) > thr:\n            im = np.delete(im, l, 1)\n    # delete empty rows\n    for l in reversed(range(im.shape[0])):\n        if (np.sum(mask[l, :]) / float(mask.shape[1])) > thr:\n            im = np.delete(im, l, 0)\n    return im\n\n\ndef mask_median(im, val=255):\n    masks = [None] * 3\n    for c in range(3):\n        masks[c] = im[..., c] >= np.median(im[:, :, c]) - 5\n    mask = np.logical_and(*masks)\n    im[mask, :] = val\n    return im, mask\n","metadata":{"execution":{"iopub.status.busy":"2022-08-02T14:28:58.308547Z","iopub.execute_input":"2022-08-02T14:28:58.309833Z","iopub.status.idle":"2022-08-02T14:28:58.319928Z","shell.execute_reply.started":"2022-08-02T14:28:58.309781Z","shell.execute_reply":"2022-08-02T14:28:58.318732Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img6, mask6 = mask_median(np.array(img))\nimg6 = prune_image_rows_cols(img6, mask6)\n\n\nfig, axes = plt.subplots(nrows=1, ncols=2, figsize=(16, 8))\n\nprint(img.size, img6.shape)\nprint(np.asarray(img).min(),np.asarray(img).max())\nprint(img6.min(),img6.max())\naxes[0].imshow(img)\naxes[1].imshow(img6)\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-08-02T14:31:31.393409Z","iopub.execute_input":"2022-08-02T14:31:31.394138Z","iopub.status.idle":"2022-08-02T14:31:31.935196Z","shell.execute_reply.started":"2022-08-02T14:31:31.394098Z","shell.execute_reply":"2022-08-02T14:31:31.933426Z"},"trusted":true},"execution_count":null,"outputs":[]}]}