{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.7.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":34547,"databundleVersionId":3897958,"sourceType":"competition"},{"sourceId":4063718,"sourceType":"datasetVersion","datasetId":2405943},{"sourceId":4064209,"sourceType":"datasetVersion","datasetId":2406171},{"sourceId":6774400,"sourceType":"datasetVersion","datasetId":3895136}],"dockerImageVersionId":30203,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!ls /kaggle/input/pyvips-python-and-deb-package\n# intall the deb packages\n!dpkg -i --force-depends /kaggle/input/pyvips-python-and-deb-package/linux_packages/archives/*.deb\n# install the python wrapper\n!pip install pyvips -f /kaggle/input/pyvips-python-and-deb-package/python_packages/ --no-index\n!pip list | grep pyvips","metadata":{"_kg_hide-output":true,"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-11-23T07:32:51.785062Z","iopub.execute_input":"2023-11-23T07:32:51.786215Z","iopub.status.idle":"2023-11-23T07:34:07.845497Z","shell.execute_reply.started":"2023-11-23T07:32:51.786101Z","shell.execute_reply":"2023-11-23T07:34:07.843849Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Decompose image to tiles/grid 🖽","metadata":{}},{"cell_type":"code","source":"import os\nimport pyvips\nimport numpy as np\nfrom PIL import Image\n\nos.environ['VIPS_DISC_THRESHOLD'] = '7gb'\n\ndef extract_image_tiles(p_img, folder, size: int = 768) -> list:\n    w = h = size\n    name, _ = os.path.splitext(os.path.basename(p_img))\n    im = pyvips.Image.new_from_file(p_img)\n    # https://stackoverflow.com/a/47581978/4521646\n    idxs = [(y, y + h, x, x + w) for y in range(0, im.height, h) for x in range(0, im.width, w)]\n    files = []\n    for k, (y, _, x, _) in enumerate(idxs):\n        # https://libvips.github.io/pyvips/vimage.html#pyvips.Image.crop\n        tile = im.crop(x, y, min(w, im.width - x), min(h, im.height - y)).numpy()\n        if tile.shape[:2] != (h, w):\n            tile_ = tile\n            tile_size = (h, w) if tile.ndim == 2 else (h, w, tile.shape[2])\n            tile = np.zeros(tile_size, dtype=tile.dtype)\n            tile[:tile_.shape[0], :tile_.shape[1], ...] = tile_\n        p_img = os.path.join(folder, f\"{name}_{k:06}.png\")\n        # print(tile.shape, tile.dtype, tile.min(), tile.max())\n        Image.fromarray(tile).save(p_img)\n        files.append(p_img)\n    return files, idxs","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-11-23T07:34:07.848248Z","iopub.execute_input":"2023-11-23T07:34:07.848626Z","iopub.status.idle":"2023-11-23T07:34:08.304053Z","shell.execute_reply.started":"2023-11-23T07:34:07.848591Z","shell.execute_reply":"2023-11-23T07:34:08.302637Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"DATASET_IMAGES = \"../input/hubmap-organ-segmentation/train_images\"\nDATASET_MASKS = \"../input/hacking-the-human-body-masks-png-images/train_binary_masks\"\n\n!mkdir -p /kaggle/temp/images\n!mkdir -p /kaggle/temp/masks\n\ntiles_img, _ = extract_image_tiles(\n    os.path.join(DATASET_IMAGES, \"12233.tiff\"),\n    \"/kaggle/temp/images\", size=512\n)\ntiles_seg, idxs = extract_image_tiles(\n    os.path.join(DATASET_MASKS, \"12233.png\"),\n    \"/kaggle/temp/masks\", size=512\n)\n\n!ls -lh /kaggle/temp/images\n!ls -lh /kaggle/temp/masks","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2023-11-23T07:34:08.305691Z","iopub.execute_input":"2023-11-23T07:34:08.306277Z","iopub.status.idle":"2023-11-23T07:34:18.066577Z","shell.execute_reply.started":"2023-11-23T07:34:08.306181Z","shell.execute_reply":"2023-11-23T07:34:18.064907Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Show the image tiles with segmentations","metadata":{}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nfrom skimage import color\n\nnb_tiles_sqrt = int(np.sqrt(len(tiles_img)))\n\nfig, axes = plt.subplots(nrows=nb_tiles_sqrt, ncols=nb_tiles_sqrt, figsize=(9, 9))\nfor i, (p_img, p_seg) in enumerate(zip(tiles_img, tiles_seg)):\n    img = plt.imread(p_img)\n    mask = np.array(Image.open(p_seg))\n    im = color.label2rgb(mask, img, bg_label=0, bg_color=(1.,1.,1.), alpha=0.25)\n    axes[i // nb_tiles_sqrt, i % nb_tiles_sqrt].imshow(im)\n    axes[i // nb_tiles_sqrt, i % nb_tiles_sqrt].set_axis_off()\nfig.tight_layout()","metadata":{"execution":{"iopub.status.busy":"2023-11-23T07:34:18.069973Z","iopub.execute_input":"2023-11-23T07:34:18.070423Z","iopub.status.idle":"2023-11-23T07:34:24.166991Z","shell.execute_reply.started":"2023-11-23T07:34:18.070383Z","shell.execute_reply":"2023-11-23T07:34:24.166037Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Back recosntruction 🖼️","metadata":{}},{"cell_type":"code","source":"tiles = [np.array(Image.open(p_seg)) for p_seg in tiles_seg]\nim = plt.imread(os.path.join(DATASET_IMAGES, \"12233.tiff\"))\nseg = np.zeros(im.shape[:2], dtype=np.uint8)\nfor tile, (y, y2, x, x2) in zip(tiles, idxs):\n    y2 = min(y2, im.shape[0])\n    x2 = min(x2, im.shape[1])\n    seg[y:y2, x:x2] = tile[:(y2 - y), :(x2 - x)]\nplt.imshow(seg)\n\nprint(im.shape, seg.shape)\ndel im, seg","metadata":{"execution":{"iopub.status.busy":"2023-11-23T07:34:24.168180Z","iopub.execute_input":"2023-11-23T07:34:24.169176Z","iopub.status.idle":"2023-11-23T07:34:25.549632Z","shell.execute_reply.started":"2023-11-23T07:34:24.169137Z","shell.execute_reply":"2023-11-23T07:34:25.548132Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Even larger image","metadata":{}},{"cell_type":"code","source":"DATASET_IMAGES = \"../input/hacking-the-kidney-annotation-masks-png-images/train_images\"\nDATASET_MASKS = \"../input/hacking-the-kidney-annotation-masks-png-images/train_masks\"\n\nimg_name = \"aaa6a05cc\"\n\n_ = plt.imshow(plt.imread(os.path.join(DATASET_IMAGES, f\"{img_name}.png\")))","metadata":{"execution":{"iopub.status.busy":"2023-11-23T07:34:25.551235Z","iopub.execute_input":"2023-11-23T07:34:25.551585Z","iopub.status.idle":"2023-11-23T07:35:29.663054Z","shell.execute_reply.started":"2023-11-23T07:34:25.551553Z","shell.execute_reply":"2023-11-23T07:35:29.661053Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!rm /kaggle/temp/images/*\n!rm /kaggle/temp/masks/*\n\ntiles_img, _ = extract_image_tiles(\n    os.path.join(DATASET_IMAGES, f\"{img_name}.png\"),\n    \"/kaggle/temp/images\", size=2048\n)\ntiles_seg, idxs = extract_image_tiles(\n    os.path.join(DATASET_MASKS, f\"{img_name}.png\"),\n    \"/kaggle/temp/masks\", size=2048\n)","metadata":{"execution":{"iopub.status.busy":"2023-11-23T07:35:29.666366Z","iopub.execute_input":"2023-11-23T07:35:29.667205Z","iopub.status.idle":"2023-11-23T07:37:01.315406Z","shell.execute_reply.started":"2023-11-23T07:35:29.667150Z","shell.execute_reply":"2023-11-23T07:37:01.313523Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, axes = plt.subplots(nrows=10, ncols=7, figsize=(9, 12))\nfor i, (p_img, p_seg) in enumerate(zip(tiles_img, tiles_seg)):\n    img = plt.imread(p_img)\n    mask = np.array(Image.open(p_seg))\n    im = color.label2rgb(mask, img, bg_label=0, bg_color=(1.,1.,1.), alpha=0.25)\n    axes[i // 7, i % 7].imshow(im)\n    axes[i // 7, i % 7].set_axis_off()\nfig.tight_layout()","metadata":{"execution":{"iopub.status.busy":"2023-11-23T07:37:01.317416Z","iopub.execute_input":"2023-11-23T07:37:01.317808Z","iopub.status.idle":"2023-11-23T07:39:13.103606Z","shell.execute_reply.started":"2023-11-23T07:37:01.317773Z","shell.execute_reply":"2023-11-23T07:39:13.102295Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Export all image tiles","metadata":{}},{"cell_type":"code","source":"import glob\nfrom tqdm.auto import tqdm\nfrom joblib import Parallel, delayed\n\nTILE_SIZE = 1024\nDATASET_HPA = \"/kaggle/input/hacking-the-human-body-masks-png-images\"\nDATASET_HBMAP = \"/kaggle/input/hacking-the-kidney-annotation-masks-png-images\"\n\n!rm /kaggle/temp/images/*\n!rm /kaggle/temp/masks/*\n\nfor dir_source, dir_target in [\n    (os.path.join(DATASET_HBMAP, 'train_images'), \"/kaggle/temp/images\"),\n    (os.path.join(DATASET_HBMAP, 'train_masks'), \"/kaggle/temp/masks\"),\n    (os.path.join(DATASET_HPA, 'train_images'), \"/kaggle/temp/images\"),\n    (os.path.join(DATASET_HPA, 'train_binary_masks'), \"/kaggle/temp/masks\"),\n]:\n    ls = glob.glob(os.path.join(dir_source, '*'))\n    for p_img in tqdm(ls):\n        extract_image_tiles(p_img, dir_target, size=TILE_SIZE)\n#     _= Parallel(n_jobs=1)(\n#         delayed(extract_image_tiles)(p_img, dir_target, size=TILE_SIZE)\n#         for p_img in tqdm(ls)\n#     )","metadata":{"execution":{"iopub.status.busy":"2023-11-23T07:39:13.105301Z","iopub.execute_input":"2023-11-23T07:39:13.105680Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Prune tiles without segmentations","metadata":{}},{"cell_type":"code","source":"ls_masks = glob.glob(\"/kaggle/temp/masks/*.png\")\n\nremoved = []\nfor p_seg in tqdm(ls_masks):\n    seg = np.array(Image.open(p_seg))\n    img_name = os.path.basename(p_seg)\n    if seg.sum() > 0:\n        continue\n    removed.append(img_name)\n    os.remove(p_seg)\n    os.remove(os.path.join(\"/kaggle/temp/images\", img_name))\nprint(f\"pruned: {len(removed)} out of {len(ls_masks)}\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!mkdir train_images\n!cp /kaggle/temp/images/*.png train_images/\n!mkdir train_masks\n!cp /kaggle/temp/masks/*.png train_masks/","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Show some samples","metadata":{}},{"cell_type":"code","source":"ls_masks = glob.glob(\"train_masks/*.png\")\n\nfig, axes = plt.subplots(nrows=7, ncols=2, figsize=(9, 30))\nfor i, p_seg in enumerate(ls_masks[:14]):\n    mask = np.array(Image.open(p_seg))\n    fname = os.path.basename(p_seg)\n    img = plt.imread(os.path.join(\"train_images\", fname))\n    axes[i // 2, i % 2].imshow(color.label2rgb(\n        mask, img, bg_label=0, bg_color=(1.,1.,1.), alpha=0.25))\n    axes[i // 2, i % 2].set_axis_off()\n    axes[i // 2, i % 2].set_title(f\"img: {fname}, labels: {np.unique(mask)}\")\nfig.tight_layout()","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}