{"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":"nvidiaTeslaT4","dataSources":[{"sourceId":61446,"databundleVersionId":6962461,"sourceType":"competition"}],"dockerImageVersionId":30587,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport matplotlib.animation as animation\nfrom IPython.display import display, HTML\nimport SimpleITK as sitk\n","metadata":{"execution":{"iopub.status.busy":"2023-12-03T10:49:58.341233Z","iopub.execute_input":"2023-12-03T10:49:58.342093Z","iopub.status.idle":"2023-12-03T10:49:59.029184Z","shell.execute_reply.started":"2023-12-03T10:49:58.342057Z","shell.execute_reply":"2023-12-03T10:49:59.028333Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Libraries for Display and Medical Image Processing\n\nIn this notebook, we are using two important libraries:\n\n### IPython.display\n\nThe `IPython.display` library provides tools for displaying rich content in the IPython environment.\n\n- **`display` Function:** Used for displaying various types of content, such as HTML, images, audio, videos, etc., directly within the Jupyter Notebook or IPython console.\n\n- **`HTML` Class:** A class within `IPython.display` that allows the generation and display of HTML content in the IPython environment.\n\n### SimpleITK (sitk)\n\n`SimpleITK` is a simplified layer built on top of the Insight Segmentation and Registration Toolkit (ITK), a library for medical image analysis.\n\n- **Functionality:** Provides a simplified interface for common tasks in medical image processing.\n  \n- **Alias `sitk`:** In this notebook, we've imported `SimpleITK` as `sitk` for brevity, allowing us to reference the library using the shorter name `sitk` in our code.\n","metadata":{}},{"cell_type":"markdown","source":"# Dataset Paths","metadata":{}},{"cell_type":"code","source":"kidney1 = \"/kaggle/input/blood-vessel-segmentation/train/kidney_1_dense/images\"\nkidney1_labels = \"/kaggle/input/blood-vessel-segmentation/train/kidney_1_dense/labels\"\nkidney1_voi = \"/kaggle/input/blood-vessel-segmentation/train/kidney_1_voi/images\"\nkidney1_voi_labels = \"/kaggle/input/blood-vessel-segmentation/train/kidney_1_voi/labels\"\n\nkidney2 = \"/kaggle/input/blood-vessel-segmentation/train/kidney_2/images\"\nkidney2_labels = \"/kaggle/input/blood-vessel-segmentation/train/kidney_2/labels\"\n\nkidney3sparse = \"/kaggle/input/blood-vessel-segmentation/train/kidney_3_sparse/images\"\nkidney3_labels = \"/kaggle/input/blood-vessel-segmentation/train/kidney_3_sparse/labels\"\nkidney3_dense = \"/kaggle/input/blood-vessel-segmentation/train/kidney_3_dense/labels\"","metadata":{"execution":{"iopub.status.busy":"2023-12-03T10:49:59.030913Z","iopub.execute_input":"2023-12-03T10:49:59.031205Z","iopub.status.idle":"2023-12-03T10:49:59.036101Z","shell.execute_reply.started":"2023-12-03T10:49:59.031181Z","shell.execute_reply":"2023-12-03T10:49:59.035275Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_data(ct_folder, label_folder):\n    ct_files = sorted(os.listdir(ct_folder))\n    label_files = sorted(os.listdir(label_folder))\n    \n    ct_images = [sitk.ReadImage(os.path.join(ct_folder, file)) for file in ct_files]\n    label_images = [sitk.ReadImage(os.path.join(label_folder, file)) for file in label_files]\n    \n    return ct_images, label_images","metadata":{"execution":{"iopub.status.busy":"2023-12-03T10:49:59.037213Z","iopub.execute_input":"2023-12-03T10:49:59.037507Z","iopub.status.idle":"2023-12-03T10:49:59.048796Z","shell.execute_reply.started":"2023-12-03T10:49:59.037451Z","shell.execute_reply":"2023-12-03T10:49:59.048004Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def display_images_with_overlay(ct_image, label_image):\n    ct_array = np.squeeze(np.array(ct_image))\n    label_array = np.squeeze(np.array(label_image))\n\n    plt.figure(figsize=(12, 6))\n    \n    # Display CT scan\n    plt.subplot(1, 3, 1)\n    plt.imshow(ct_array, cmap='gray')\n    plt.title('CT Scan')\n    \n    # Display segmentation mask\n    plt.subplot(1, 3, 2)\n    plt.imshow(label_array, cmap='viridis')\n    plt.title('Blood Vessel Labels')\n    \n    # Overlay\n    plt.subplot(1, 3, 3)\n    plt.imshow(ct_array, cmap='gray')\n    plt.imshow(label_array, alpha=0.5, cmap='viridis')\n    plt.title('Overlay')\n    \n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2023-12-03T10:49:59.051148Z","iopub.execute_input":"2023-12-03T10:49:59.051397Z","iopub.status.idle":"2023-12-03T10:49:59.061945Z","shell.execute_reply.started":"2023-12-03T10:49:59.051375Z","shell.execute_reply":"2023-12-03T10:49:59.061265Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def rle_encode(img):\n    '''\n    img: numpy array, 1 - mask, 0 - background\n    Returns run length as string formated\n    '''\n    pixels = img.flatten()\n    pixels = np.concatenate([[0], pixels, [0]])\n    runs = np.where(pixels[1:] != pixels[:-1])[0] + 1\n    runs[1::2] -= runs[::2]\n    return ' '.join(str(x) for x in runs)\n \ndef rle_decode(mask_rle, shape):\n    '''\n    mask_rle: run-length as string formated (start length)\n    shape: (height,width) of array to return \n    Returns numpy array, 1 - mask, 0 - background\n\n    '''\n    s = mask_rle.split()\n    starts, lengths = [np.asarray(x, dtype=int) for x in (s[0:][::2], s[1:][::2])]\n    starts -= 1\n    ends = starts + lengths\n    img = np.zeros(shape[0]*shape[1], dtype=np.uint8)\n    for lo, hi in zip(starts, ends):\n        img[lo:hi] = 1\n    return img.reshape(shape)","metadata":{"execution":{"iopub.status.busy":"2023-12-03T10:49:59.062945Z","iopub.execute_input":"2023-12-03T10:49:59.063231Z","iopub.status.idle":"2023-12-03T10:49:59.075259Z","shell.execute_reply.started":"2023-12-03T10:49:59.063208Z","shell.execute_reply":"2023-12-03T10:49:59.074495Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def preprocess_image(path):\n    \n    img = cv2.imread(path, cv2.IMREAD_UNCHANGED)\n    img = np.tile(img[...,None],[1, 1, 3]) \n    img = img.astype('float32') \n    mx = np.max(img)\n    if mx:\n        img/=mx \n        \n    img = np.transpose(img, (2, 0, 1))\n    img_ten = torch.tensor(img)\n    return img_ten\n\ndef preprocess_mask(path):\n    \n    msk = cv2.imread(path, cv2.IMREAD_UNCHANGED)\n    msk = msk.astype('float32')\n    msk/=255.0\n    msk_ten = torch.tensor(msk)\n    \n    return msk_ten","metadata":{"execution":{"iopub.status.busy":"2023-12-03T10:49:59.076380Z","iopub.execute_input":"2023-12-03T10:49:59.076668Z","iopub.status.idle":"2023-12-03T10:49:59.096618Z","shell.execute_reply.started":"2023-12-03T10:49:59.076647Z","shell.execute_reply":"2023-12-03T10:49:59.095920Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport imageio\nfrom PIL import Image\nimport torch\nfrom torchvision import transforms\nfrom torch.utils.data import Dataset\nfrom torch.utils.data import DataLoader\n\nclass CustomDataset(Dataset):\n    def __init__(self, image_files, mask_files, input_size=(256, 256)):\n        self.image_files = image_files\n        self.mask_files = mask_files\n        self.input_size = input_size\n\n    def __len__(self):\n        return len(self.image_files)\n\n    def __getitem__(self, idx):\n       \n        image_path = self.image_files[idx]\n        mask_path = self.mask_files[idx]\n\n        image = preprocess_image(image_path)\n        mask = preprocess_mask(mask_path)\n\n        return image, mask\n","metadata":{"execution":{"iopub.status.busy":"2023-12-03T10:49:59.097589Z","iopub.execute_input":"2023-12-03T10:49:59.097839Z","iopub.status.idle":"2023-12-03T10:50:01.177099Z","shell.execute_reply.started":"2023-12-03T10:49:59.097817Z","shell.execute_reply":"2023-12-03T10:50:01.176145Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def display_animation(images_dir, masks_dir, interval=25, figsize=(8, 8), cmap_mask='jet', alpha_mask=0.5):\n    \"\"\"Display animations of kidney slices.\"\"\"\n    \n    # List image ids\n    img_ids = os.listdir(masks_dir)\n    img_ids = sorted(img_ids)\n    print(f\"There are {len(img_ids)} images in the dataset.\")\n    \n    # Selection interval \n    select_ids = img_ids[::interval]\n\n    imgs = []\n    fig, ax = plt.subplots(figsize=figsize)\n    \n    for select_id in select_ids:\n        \n        image_file = os.path.join(images_dir, select_id)\n        mask_file = os.path.join(masks_dir, select_id)\n\n        image = sitk.ReadImage(image_file)\n        mask = sitk.ReadImage(mask_file)\n\n        title_str = f\"Scan from {select_id.replace('.tif', '')} slice\"\n        title = ax.text(x=0.5,\n                        y=1.00,\n                        s=title_str,\n                        size=12,\n                        ha=\"center\",\n                        transform=ax.transAxes\n                    )\n        \n        ct_array = sitk.GetArrayFromImage(image)\n        mask_array = sitk.GetArrayFromImage(mask)\n        \n        # Display CT scan\n        disp_img = ax.imshow(ct_array, cmap=\"gray\", animated=True)\n\n        # Display mask overlaid on CT scan\n        disp_mask = ax.imshow(mask_array, cmap=cmap_mask, alpha=alpha_mask, animated=True)\n\n        plt.axis(\"off\")\n        plt.close()\n\n        imgs.append([disp_img, disp_mask, title])\n\n    # Stitch animation object\n    ani = animation.ArtistAnimation(fig=fig,\n                                    artists=imgs,\n                                    interval=200,\n                                    blit=True,\n                                    repeat=True)\n    \n    return display(HTML(ani.to_jshtml()))","metadata":{"execution":{"iopub.status.busy":"2023-12-03T10:50:01.178416Z","iopub.execute_input":"2023-12-03T10:50:01.179246Z","iopub.status.idle":"2023-12-03T10:50:01.190080Z","shell.execute_reply.started":"2023-12-03T10:50:01.179211Z","shell.execute_reply":"2023-12-03T10:50:01.189010Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"display_animation(kidney1, kidney1_labels)","metadata":{"execution":{"iopub.status.busy":"2023-12-03T10:50:01.191494Z","iopub.execute_input":"2023-12-03T10:50:01.191820Z","iopub.status.idle":"2023-12-03T10:50:48.608445Z","shell.execute_reply.started":"2023-12-03T10:50:01.191785Z","shell.execute_reply":"2023-12-03T10:50:48.607399Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"display_animation(kidney1_voi,kidney1_voi_labels)","metadata":{"execution":{"iopub.status.busy":"2023-12-03T10:50:48.611214Z","iopub.execute_input":"2023-12-03T10:50:48.611528Z","iopub.status.idle":"2023-12-03T10:51:46.567722Z","shell.execute_reply.started":"2023-12-03T10:50:48.611501Z","shell.execute_reply":"2023-12-03T10:51:46.566743Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"display_animation(kidney2,kidney2_labels)","metadata":{"execution":{"iopub.status.busy":"2023-12-03T11:06:11.971826Z","iopub.execute_input":"2023-12-03T11:06:11.972652Z","iopub.status.idle":"2023-12-03T11:06:55.169810Z","shell.execute_reply.started":"2023-12-03T11:06:11.972614Z","shell.execute_reply":"2023-12-03T11:06:55.168243Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def countImages(folderpath):\n    files = os.listdir(folderpath)\n    tiff_files = [file for file in files if file.lower().endswith(('.tif'))]\n    return len(tiff_files)\n    ","metadata":{"execution":{"iopub.status.busy":"2023-12-03T11:24:22.920163Z","iopub.execute_input":"2023-12-03T11:24:22.920913Z","iopub.status.idle":"2023-12-03T11:24:22.925885Z","shell.execute_reply.started":"2023-12-03T11:24:22.920876Z","shell.execute_reply":"2023-12-03T11:24:22.925038Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"folders = [\n    \"/kaggle/input/blood-vessel-segmentation/train/kidney_1_dense/images\",\n    \"/kaggle/input/blood-vessel-segmentation/train/kidney_1_voi/images\",\n    \"/kaggle/input/blood-vessel-segmentation/train/kidney_2/images\",\n    \"/kaggle/input/blood-vessel-segmentation/train/kidney_3_sparse/images\",\n]","metadata":{"execution":{"iopub.status.busy":"2023-12-03T11:24:25.850302Z","iopub.execute_input":"2023-12-03T11:24:25.851191Z","iopub.status.idle":"2023-12-03T11:24:25.855497Z","shell.execute_reply.started":"2023-12-03T11:24:25.851159Z","shell.execute_reply":"2023-12-03T11:24:25.854437Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_counts = [countImages(folder) for folder in folders]\nplt.figure(figsize=(10, 6))\nplt.plot(range(len(folders)), image_counts)\nplt.xticks(range(len(folders)), folders, rotation='vertical')\nplt.xlabel('Datasets')\nplt.ylabel('Number of Images')\nplt.title('Number of Images in Each Dataset')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-12-03T11:24:57.040414Z","iopub.execute_input":"2023-12-03T11:24:57.041121Z","iopub.status.idle":"2023-12-03T11:24:57.366823Z","shell.execute_reply.started":"2023-12-03T11:24:57.041085Z","shell.execute_reply":"2023-12-03T11:24:57.365839Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pandas as pd\nsample_submissionDF = pd.read_csv(\"/kaggle/input/blood-vessel-segmentation/sample_submission.csv\")","metadata":{"execution":{"iopub.status.busy":"2023-12-03T11:25:04.301490Z","iopub.execute_input":"2023-12-03T11:25:04.302360Z","iopub.status.idle":"2023-12-03T11:25:04.311857Z","shell.execute_reply.started":"2023-12-03T11:25:04.302316Z","shell.execute_reply":"2023-12-03T11:25:04.311001Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample_submissionDF.head()","metadata":{"execution":{"iopub.status.busy":"2023-12-03T11:25:05.869687Z","iopub.execute_input":"2023-12-03T11:25:05.870317Z","iopub.status.idle":"2023-12-03T11:25:05.879631Z","shell.execute_reply.started":"2023-12-03T11:25:05.870283Z","shell.execute_reply":"2023-12-03T11:25:05.878681Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_rlesDF = pd.read_csv(\"/kaggle/input/blood-vessel-segmentation/train_rles.csv\")\ntrain_rlesDF.head()","metadata":{"execution":{"iopub.status.busy":"2023-12-03T11:25:06.921004Z","iopub.execute_input":"2023-12-03T11:25:06.921676Z","iopub.status.idle":"2023-12-03T11:25:07.437377Z","shell.execute_reply.started":"2023-12-03T11:25:06.921643Z","shell.execute_reply":"2023-12-03T11:25:07.436443Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Model","metadata":{}},{"cell_type":"code","source":"class DoubleConv(nn.Module):\n    \"\"\"(convolution => [BN] => ReLU) * 2\"\"\"\n\n    def __init__(self, in_channels, out_channels, mid_channels=None):\n        super().__init__()\n        if not mid_channels:\n            mid_channels = out_channels\n        self.double_conv = nn.Sequential(\n            nn.Conv2d(in_channels, mid_channels, kernel_size=3, padding=1),\n            nn.BatchNorm2d(mid_channels),\n            nn.ReLU(inplace=True),\n            nn.Conv2d(mid_channels, out_channels, kernel_size=3, padding=1),\n            nn.BatchNorm2d(out_channels),\n            nn.ReLU(inplace=True)\n        )\n\n    def forward(self, x):\n        return self.double_conv(x)\n\n\nclass Down(nn.Module):\n    \"\"\"Downscaling with maxpool then double conv\"\"\"\n\n    def __init__(self, in_channels, out_channels):\n        super().__init__()\n        self.maxpool_conv = nn.Sequential(\n            nn.MaxPool2d(2),\n            DoubleConv(in_channels, out_channels)\n        )\n\n    def forward(self, x):\n        return self.maxpool_conv(x)\n\n\nclass Up(nn.Module):\n    \"\"\"Upscaling then double conv\"\"\"\n\n    def __init__(self, in_channels, out_channels, bilinear=True):\n        super().__init__()\n\n        # if bilinear, use the normal convolutions to reduce the number of channels\n        if bilinear:\n            self.up = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True)\n            self.conv = DoubleConv(in_channels, out_channels, in_channels // 2)\n        else:\n            self.up = nn.ConvTranspose2d(in_channels , in_channels // 2, kernel_size=2, stride=2)\n            self.conv = DoubleConv(in_channels, out_channels)\n\n\n    def forward(self, x1, x2):\n        x1 = self.up(x1)\n        # input is CHW\n        diffY = x2.size()[2] - x1.size()[2]\n        diffX = x2.size()[3] - x1.size()[3]\n\n        x1 = F.pad(x1, [diffX // 2, diffX - diffX // 2,\n                        diffY // 2, diffY - diffY // 2])\n        # if you have padding issues, see\n        # https://github.com/HaiyongJiang/U-Net-Pytorch-Unstructured-Buggy/commit/0e854509c2cea854e247a9c615f175f76fbb2e3a\n        # https://github.com/xiaopeng-liao/Pytorch-UNet/commit/8ebac70e633bac59fc22bb5195e513d5832fb3bd\n        x = torch.cat([x2, x1], dim=1)\n        return self.conv(x)\n\n\nclass OutConv(nn.Module):\n    def __init__(self, in_channels, out_channels):\n        super(OutConv, self).__init__()\n        self.conv = nn.Conv2d(in_channels, out_channels, kernel_size=1)\n\n    def forward(self, x):\n        return self.conv(x)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch.nn.functional as F\n\nclass UNet(nn.Module):\n    def __init__(self, n_channels, n_classes, bilinear=True):\n        super(UNet, self).__init__()\n        self.n_channels = n_channels\n        self.n_classes = n_classes\n        self.bilinear = bilinear\n\n        self.inc = DoubleConv(n_channels, 64)\n        self.down1 = Down(64, 128)\n        self.down2 = Down(128, 256)\n        self.down3 = Down(256, 512)\n        factor = 2 if bilinear else 1\n        self.down4 = Down(512, 1024 // factor)\n        self.up1 = Up(1024, 512 // factor, bilinear)\n        self.up2 = Up(512, 256 // factor, bilinear)\n        self.up3 = Up(256, 128 // factor, bilinear)\n        self.up4 = Up(128, 64, bilinear)\n        self.outc = OutConv(64, n_classes)\n\n    def forward(self, x):\n        x1 = self.inc(x)\n        x2 = self.down1(x1)\n        x3 = self.down2(x2)\n        x4 = self.down3(x3)\n        x5 = self.down4(x4)\n        x = self.up1(x5, x4)\n        x = self.up2(x, x3)\n        x = self.up3(x, x2)\n        x = self.up4(x, x1)\n        logits = self.outc(x)\n        return logits","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}