{"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":"# StainNet: make stain normalized image\n\nThe images in this competition were captured at several hospitals, resulting in notable variations in the tissue staining.   As indicated in the data description section of this competition, it is said,\n\n>**The test set contains images from different source hospitals than the train set, with the >largest area images almost 100,000 x 50,000 pixels. We strongly recommend taking an expansive >approach to thinking about the scenarios your error handling should manage, including >differences in image dimensions, quality, slide staining techniques, and more.** Expect roughly >2,000 images in the test set, the majority of which are TMAs. The total size is 550 GB so simply loading the data will be time consuming. Be warned that the test set was specifically constructed to assess how well models generalize.\n\nAs you can see, he intensity of the staining of the slides in each dataset is different. <br>\n\nTherefore, stain normalization is necessary.  <br>\n\n In this notebook, we will introduce one of the methods of stain normalization, StainNet\n（https://www.frontiersin.org/articles/10.3389/fmed.2021.746307/full）. <br>\n\n## Please Upvote if you Find this Useful :)","metadata":{}},{"cell_type":"code","source":"import os\nimport sys\nimport glob\nimport random\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport torch\nfrom PIL import Image\nfrom tqdm.notebook import tqdm\n\nsys.path.append('../input/stainnet/')\nfrom models import StainNet, ResnetGenerator","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-10-10T09:26:24.116007Z","iopub.execute_input":"2023-10-10T09:26:24.116532Z","iopub.status.idle":"2023-10-10T09:26:24.128198Z","shell.execute_reply.started":"2023-10-10T09:26:24.116475Z","shell.execute_reply":"2023-10-10T09:26:24.127426Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# preparation for StainNet\nmodel_Net = StainNet().cuda()\nmodel_Net.load_state_dict(torch.load(\"../input/stainnet/checkpoints/aligned_histopathology_dataset/StainNet-Public_layer3_ch32.pth\"))\nmodel_Net.eval()\n\ndef norm(image):\n    image = np.array(image).astype(np.float32)\n    image = image.transpose((2, 0, 1))\n    image = ((image / 255) - 0.5) / 0.5\n    image=image[np.newaxis, ...]\n    image=torch.from_numpy(image)\n    return image\n\ndef un_norm(image):\n    image = image.cpu().detach().numpy()[0]\n    image = ((image * 0.5 + 0.5) * 255).astype(np.uint8).transpose((1,2,0))\n    return image\n\ndef stain_normalize(source, verbose=False):\n    with torch.no_grad():\n        img_net=model_Net(norm(source).cuda())\n        img_net=un_norm(img_net)\n        if verbose: plt.imshow(img_net); plt.show()\n        return img_net","metadata":{"execution":{"iopub.status.busy":"2023-10-10T09:08:33.398884Z","iopub.execute_input":"2023-10-10T09:08:33.399437Z","iopub.status.idle":"2023-10-10T09:08:36.494773Z","shell.execute_reply.started":"2023-10-10T09:08:33.399407Z","shell.execute_reply":"2023-10-10T09:08:36.493892Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_imgs_root_path = \"/kaggle/input/UBC-OCEAN/train_thumbnails/\"\nsave_dir = \"/kaggle/working/stain_normalized_image\"\ntrain_imgs_path = glob.glob(train_imgs_root_path+\"*\")","metadata":{"execution":{"iopub.status.busy":"2023-10-10T09:08:38.437662Z","iopub.execute_input":"2023-10-10T09:08:38.438667Z","iopub.status.idle":"2023-10-10T09:08:38.52285Z","shell.execute_reply.started":"2023-10-10T09:08:38.438634Z","shell.execute_reply":"2023-10-10T09:08:38.522051Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#create the directory to save normalized image\nos.mkdir(save_dir)\n\nfor img_path in tqdm(train_imgs_path):\n    #load image\n    img = np.array(Image.open(img_path))\n    img = np.where(img==0, 255, img)\n    #apply stain_normalization\n    img = stain_normalize(img)\n\n    #save image\n    img = Image.fromarray(img)\n    img.save(save_dir+\"/\"+img_path.split(\"/\")[-1])\n","metadata":{"execution":{"iopub.status.busy":"2023-10-10T10:00:34.013251Z","iopub.execute_input":"2023-10-10T10:00:34.013614Z","iopub.status.idle":"2023-10-10T10:12:15.464054Z","shell.execute_reply.started":"2023-10-10T10:00:34.013587Z","shell.execute_reply":"2023-10-10T10:12:15.463136Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"normalized_img_path = glob.glob(save_dir+\"/*\")\n\nrandom.seed(7)\nvis_paths = random.sample(train_imgs_path, k=3)\nprint(vis_paths)\n\nfig, axes = plt.subplots(2,3, figsize=(15, 10))\nfor j in range(3):\n    img = np.array(Image.open(vis_paths[j]))\n    img_name = vis_paths[j].split(\"/\")[-1]\n    img = np.where(img==0, 255, img)\n    axes[0][j].imshow(img)\n    axes[0][j].tick_params(labelbottom=False, labelleft=False, labelright=False, labeltop=False)\n    axes[0][j].set_title(f\"{img_name}: \\n Befor normalization\")\nfor j in range(3):\n    img = np.array(Image.open(save_dir+\"/\"+vis_paths[j].split(\"/\")[-1]))\n    img_name = vis_paths[j].split(\"/\")[-1]\n    axes[1][j].imshow(img)\n    axes[1][j].tick_params(labelbottom=False, labelleft=False, labelright=False, labeltop=False)\n    axes[1][j].set_title(f\"{img_name}: \\n After normalization\")\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-10-10T10:29:37.906853Z","iopub.execute_input":"2023-10-10T10:29:37.907933Z","iopub.status.idle":"2023-10-10T10:29:42.426844Z","shell.execute_reply.started":"2023-10-10T10:29:37.907888Z","shell.execute_reply":"2023-10-10T10:29:42.42609Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}