{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.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":45867,"databundleVersionId":6924515,"sourceType":"competition"},{"sourceId":6774400,"sourceType":"datasetVersion","datasetId":3895136},{"sourceId":6984590,"sourceType":"datasetVersion","datasetId":4014175}],"dockerImageVersionId":30587,"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","metadata":{"_kg_hide-output":true,"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-12-20T14:19:19.014249Z","iopub.execute_input":"2023-12-20T14:19:19.014646Z","iopub.status.idle":"2023-12-20T14:20:32.769767Z","shell.execute_reply.started":"2023-12-20T14:19:19.014617Z","shell.execute_reply":"2023-12-20T14:20:32.768322Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os, glob\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport pyvips\nfrom PIL import Image\nimport warnings\nwarnings.filterwarnings('ignore')\n\nos.environ['VIPS_DISC_THRESHOLD'] = '9gb'\n\nDATASET_FOLDER = \"/kaggle/input/UBC-OCEAN/\"\nMASK_FOLDER = '/kaggle/input/ubc-ovarian-cancer-competition-supplemental-masks'\nIMAGE_FOLDER = '/kaggle/input/UBC-OCEAN/train_images'","metadata":{"execution":{"iopub.status.busy":"2023-12-20T14:20:32.77225Z","iopub.execute_input":"2023-12-20T14:20:32.772627Z","iopub.status.idle":"2023-12-20T14:20:33.537988Z","shell.execute_reply.started":"2023-12-20T14:20:32.77259Z","shell.execute_reply":"2023-12-20T14:20:33.53706Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_data = pd.read_csv('/kaggle/input/UBC-OCEAN/train.csv')\ndf_data","metadata":{"execution":{"iopub.status.busy":"2023-12-20T14:20:33.539277Z","iopub.execute_input":"2023-12-20T14:20:33.539703Z","iopub.status.idle":"2023-12-20T14:20:33.594913Z","shell.execute_reply.started":"2023-12-20T14:20:33.539666Z","shell.execute_reply":"2023-12-20T14:20:33.594154Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_data.describe()","metadata":{"execution":{"iopub.status.busy":"2023-12-20T14:20:33.597085Z","iopub.execute_input":"2023-12-20T14:20:33.597493Z","iopub.status.idle":"2023-12-20T14:20:33.623076Z","shell.execute_reply.started":"2023-12-20T14:20:33.597444Z","shell.execute_reply":"2023-12-20T14:20:33.621995Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mask_data_list = sorted(os.listdir(MASK_FOLDER))\nmask_data_list  = [int(os.path.splitext(mask_path)[0]) for mask_path in mask_data_list]\ndf_mask = df_data[ df_data['image_id'].isin(mask_data_list) ].reset_index(drop=True).sort_values('label')\ndf_mask","metadata":{"execution":{"iopub.status.busy":"2023-12-20T14:20:33.624444Z","iopub.execute_input":"2023-12-20T14:20:33.624869Z","iopub.status.idle":"2023-12-20T14:20:33.684942Z","shell.execute_reply.started":"2023-12-20T14:20:33.624822Z","shell.execute_reply":"2023-12-20T14:20:33.684094Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"_ = df_mask[['label']].value_counts().plot.pie(autopct=\"%1.1f%%\", ylabel='label', figsize=(3,3))","metadata":{"execution":{"iopub.status.busy":"2023-12-20T14:20:33.686232Z","iopub.execute_input":"2023-12-20T14:20:33.687214Z","iopub.status.idle":"2023-12-20T14:20:33.908786Z","shell.execute_reply.started":"2023-12-20T14:20:33.68718Z","shell.execute_reply":"2023-12-20T14:20:33.907565Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_mask.describe()","metadata":{"execution":{"iopub.status.busy":"2023-12-20T14:20:33.910671Z","iopub.execute_input":"2023-12-20T14:20:33.911422Z","iopub.status.idle":"2023-12-20T14:20:33.948203Z","shell.execute_reply.started":"2023-12-20T14:20:33.91138Z","shell.execute_reply":"2023-12-20T14:20:33.947028Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_mask_MC = df_mask[ df_mask['label'] == 'MC']\ndf_mask_EC = df_mask[ df_mask['label'] == 'EC']\ndf_mask_LGSC = df_mask[ df_mask['label'] == 'LGSC']\ndf_mask_CC = df_mask[ df_mask['label'] == 'CC']\ndf_mask_HGSC = df_mask[ df_mask['label'] == 'HGSC']","metadata":{"execution":{"iopub.status.busy":"2023-12-20T14:20:33.955394Z","iopub.execute_input":"2023-12-20T14:20:33.959388Z","iopub.status.idle":"2023-12-20T14:20:33.974179Z","shell.execute_reply.started":"2023-12-20T14:20:33.959316Z","shell.execute_reply":"2023-12-20T14:20:33.972909Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!mkdir -p /kaggle/temp/images\n!mkdir -p /kaggle/temp/annotations\n!mkdir -p /kaggle/temp/masks","metadata":{"execution":{"iopub.status.busy":"2023-12-20T14:20:33.978565Z","iopub.execute_input":"2023-12-20T14:20:33.980454Z","iopub.status.idle":"2023-12-20T14:20:37.023473Z","shell.execute_reply.started":"2023-12-20T14:20:33.980416Z","shell.execute_reply":"2023-12-20T14:20:37.022202Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def convert_rgb_to_labels(img_path: str, folder: str):\n    name = os.path.basename(img_path)\n    img = np.array(Image.open(img_path))\n    #plt.imshow(img)\n    bg = np.ones((img.shape[0], img.shape[1], 1)) * 128\n    stack = np.concatenate((bg, img), axis=2)\n    mask = np.argmax(stack, axis=2).astype(np.uint8)\n    #print(np.unique(mask))\n    #plt.imshow(mask)\n    img_path = os.path.join(folder, name)\n    Image.fromarray(mask).save(img_path) \n    return img_path\n","metadata":{"execution":{"iopub.status.busy":"2023-12-20T14:20:37.028281Z","iopub.execute_input":"2023-12-20T14:20:37.029396Z","iopub.status.idle":"2023-12-20T14:20:37.036629Z","shell.execute_reply.started":"2023-12-20T14:20:37.029346Z","shell.execute_reply":"2023-12-20T14:20:37.03553Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def mask2label(mask: np.ndarray):\n    \"\"\"\n    modify the color mask to label mask in place.\n\n    Args:\n        mask: (H, W), np.uint8\n\n    Returns:\n        mask: (H, W), np.uint8, value: {'background': 0, 'tumor': 1, 'stroma': 2, 'necrosis': 3}\n    \"\"\"\n    bg = (mask.sum(axis=-1) == 0)\n    mask = mask.argmax(axis=-1).astype(np.uint8) + 1\n    mask[bg] = 0\n    return mask\n","metadata":{"execution":{"iopub.status.busy":"2023-12-20T14:20:37.038073Z","iopub.execute_input":"2023-12-20T14:20:37.038558Z","iopub.status.idle":"2023-12-20T14:20:37.052727Z","shell.execute_reply.started":"2023-12-20T14:20:37.038519Z","shell.execute_reply":"2023-12-20T14:20:37.051791Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_blend_img(img_name):\n    mask = pyvips.Image.new_from_file(os.path.join(MASK_FOLDER, str(img_name) + '.png'), access='sequential')\n    mask = mask.resize(0.2, interpolate=pyvips.Interpolate.new(\"bilinear\")).numpy().astype(np.uint8)\n    img = pyvips.Image.new_from_file(os.path.join(IMAGE_FOLDER, str(img_name) + '.png'), access='sequential')\n    img = img.resize(0.2, interpolate=pyvips.Interpolate.new(\"bilinear\")).numpy().astype(np.uint8)\n    tumor_mask = mask2label(mask)\n    blend_img = img * (tumor_mask.reshape(tumor_mask.shape[0], tumor_mask.shape[1], 1) == 1)\n    blend_img = pyvips.Image.new_from_memory(blend_img.tobytes(),\n                                             blend_img.shape[1],  # 宽度\n                                             blend_img.shape[0],  # 高度\n                                             blend_img.shape[2],  # 通道数\n                                             'uchar')\n    return blend_img\nblend_img = get_blend_img(1020)\nplt.figure()\nplt.imshow(blend_img)","metadata":{"execution":{"iopub.status.busy":"2023-12-20T14:20:37.054116Z","iopub.execute_input":"2023-12-20T14:20:37.054487Z","iopub.status.idle":"2023-12-20T14:22:40.452531Z","shell.execute_reply.started":"2023-12-20T14:20:37.054459Z","shell.execute_reply":"2023-12-20T14:22:40.451652Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!mkdir -p HGSC\n!mkdir -p CC\n!mkdir -p EC\n!mkdir -p MC\n!mkdir -p LGSC","metadata":{"execution":{"iopub.status.busy":"2023-12-20T14:22:40.454009Z","iopub.execute_input":"2023-12-20T14:22:40.454654Z","iopub.status.idle":"2023-12-20T14:22:45.66097Z","shell.execute_reply.started":"2023-12-20T14:22:40.454613Z","shell.execute_reply":"2023-12-20T14:22:45.659463Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def extract_image_tiles(\n    p_img, folder, size: int = 1024, stride: int = 2, rescale: float = 0.3, scale=0.25,\n    drop_thr: float = 0.85, inds = None\n) -> list:\n    name, _ = os.path.splitext(os.path.basename(p_img))\n    im = get_blend_img(int(name))\n    w = h = size\n    if not inds:\n        # https://stackoverflow.com/a/47581978/4521646\n        inds = [(y, y + h, x, x + w)\n                for y in range(0, im.height, h//stride)\n                for x in range(0, im.width, w//stride)]\n    files, idxs, k = [], [], 0\n    for idx in inds:\n        y, y_, x, x_ = idx\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()[..., :3]\n        if drop_thr is not None:\n            mask_bg = (np.sum(tile, axis=2) <= 10) | (np.max(tile, axis=2) >= 230)\n            if np.sum(mask_bg) >= (np.prod(mask_bg.shape) * drop_thr):\n                #print(f\"skip almost empty tile: {k:06}_{int(x_ / w)}-{int(y_ / h)}\")\n                continue\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\"{k:05}_{int(x_ / w)}-{int(y_ / h)}.png\")\n        # print(tile.shape, tile.dtype, tile.min(), tile.max())\n        new_size = int(size*scale), int(size*scale)\n        Image.fromarray(tile.astype(np.uint8)).resize(new_size, Image.BICUBIC).save(p_img)\n        files.append(p_img)\n        idxs.append(idx)\n        k += 1\n    return files, idxs","metadata":{"execution":{"iopub.status.busy":"2023-12-20T14:22:45.663532Z","iopub.execute_input":"2023-12-20T14:22:45.664037Z","iopub.status.idle":"2023-12-20T14:22:45.67767Z","shell.execute_reply.started":"2023-12-20T14:22:45.663985Z","shell.execute_reply":"2023-12-20T14:22:45.676505Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def extract_tiles_masks(\n    idx_name,\n    folder_img: str,\n    size: int = 1024, stride: int = 2, rescale: float = 0.3, scale: float = 0.25,\n    drop_thr: float = 0.9, drop_annos_ratio: float = 0.1\n) -> None:\n    idx, name = idx_name[0], str(idx_name[1])\n    print(f\"processing #{idx}: {name}\")\n    \n    folder_img = os.path.join(folder_img, name)\n    os.makedirs(folder_img, exist_ok=True)\n    \n    _, idxs = extract_image_tiles(\n        os.path.join(IMAGE_FOLDER, f\"{name}.png\"),\n        folder_img, size=size, stride=stride, rescale = rescale, scale=scale,\n        drop_thr=drop_thr\n    )\n\n    \n# extract_tiles_masks((0, 1020), size=1024, stride=2, rescale=0.3, scale=0.5, drop_thr=0.85, drop_annos_ratio=0.1, \n#                    folder_img='HGSC')","metadata":{"execution":{"iopub.status.busy":"2023-12-20T14:25:50.884876Z","iopub.execute_input":"2023-12-20T14:25:50.885327Z","iopub.status.idle":"2023-12-20T14:27:55.503371Z","shell.execute_reply.started":"2023-12-20T14:25:50.885293Z","shell.execute_reply":"2023-12-20T14:27:55.502232Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# import random\n\n# ls = [p for p in glob.glob('HGSC*') if os.path.isdir(p)]\n# print(f\"found folders: {len(ls)}\")\n# ls_imgs = sorted(glob.glob('HGSC/*/*.png'))\n# # ls_segs = sorted(glob.glob('/kaggle/temp/annotations/*/*.png'))\n# # ls_masks = sorted(glob.glob('/kaggle/temp/masks/*/*.png'))\n# ls_samples = ls_imgs\n# random.shuffle(ls_samples)\n# print(f\"found images: {len(ls)}\")\n\n# for i, p_img in enumerate(ls_samples[:10]):\n#     fig, axarr = plt.subplots(ncols=1, figsize=(4, 4))\n#     axarr.imshow(Image.open(p_img))","metadata":{"execution":{"iopub.status.busy":"2023-12-20T14:30:44.640204Z","iopub.execute_input":"2023-12-20T14:30:44.640579Z","iopub.status.idle":"2023-12-20T14:30:47.753903Z","shell.execute_reply.started":"2023-12-20T14:30:44.64055Z","shell.execute_reply":"2023-12-20T14:30:47.752706Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tqdm.auto import tqdm\nfrom joblib import Parallel, delayed\n\n\n_= Parallel(n_jobs=3)(\n    delayed(extract_tiles_masks)\n    (id_name, size=1024, stride=2, rescale=0.3, scale=0.5, drop_thr=0.85, drop_annos_ratio=0.1, folder_img='HGSC') \n    for id_name in tqdm(enumerate(df_mask_HGSC['image_id']), total=len(df_mask_HGSC['image_id'])))","metadata":{"execution":{"iopub.status.busy":"2023-12-20T14:34:32.244518Z","iopub.execute_input":"2023-12-20T14:34:32.245086Z","iopub.status.idle":"2023-12-20T14:38:46.930658Z","shell.execute_reply.started":"2023-12-20T14:34:32.245041Z","shell.execute_reply":"2023-12-20T14:38:46.928438Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"_= Parallel(n_jobs=3)(\n    delayed(extract_tiles_masks)\n    (id_name, size=1024, stride=2, rescale=0.3, scale=0.5, drop_thr=0.85, drop_annos_ratio=0.1, folder_img='LGSC') \n    for id_name in tqdm(enumerate(df_mask_LGSC['image_id']), total=len(df_mask_LGSC['image_id'])))","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"_= Parallel(n_jobs=3)(\n    delayed(extract_tiles_masks)\n    (id_name, size=1024, stride=2, rescale=0.3, scale=0.5, drop_thr=0.85, drop_annos_ratio=0.1, folder_img='MC') \n    for id_name in tqdm(enumerate(df_mask_MC['image_id']), total=len(df_mask_MC['image_id'])))","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"_= Parallel(n_jobs=3)(\n    delayed(extract_tiles_masks)\n    (id_name, size=1024, stride=2, rescale=0.3, scale=0.5, drop_thr=0.85, drop_annos_ratio=0.1, folder_img='EC') \n    for id_name in tqdm(enumerate(df_mask_EC['image_id']), total=len(df_mask_EC['image_id'])))","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"_= Parallel(n_jobs=3)(\n    delayed(extract_tiles_masks)\n    (id_name, size=1024, stride=2, rescale=0.3, scale=0.5, drop_thr=0.85, drop_annos_ratio=0.1, folder_img='CC') \n    for id_name in tqdm(enumerate(df_mask_CC['image_id']), total=len(df_mask_CC['image_id'])))","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import random\n\nls = [p for p in glob.glob('HGSC/*') if os.path.isdir(p)]\nprint(f\"found folders: {len(ls)}\")\nls_imgs = sorted(glob.glob('HGSC/*/*.png'))\nls_samples = ls_imgs\nrandom.shuffle(ls_samples)\nprint(f\"found images: {len(ls)}\")\n\nfor i, p_img in enumerate(ls_samples[:10]):\n    fig, axarr = plt.subplots(ncols=1, figsize=(4, 4))\n    axarr.set_title(\"tissue image\")\n    axarr.imshow(plt.imread(p_img))","metadata":{"execution":{"iopub.status.busy":"2023-12-20T14:40:06.246972Z","iopub.execute_input":"2023-12-20T14:40:06.248526Z","iopub.status.idle":"2023-12-20T14:40:10.11204Z","shell.execute_reply.started":"2023-12-20T14:40:06.248431Z","shell.execute_reply":"2023-12-20T14:40:10.110828Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}