{"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":"# <p style=\"background-color:#07041c;font-family:newtimeroman;color:#d3d1e6;font-size:120%;text-align:center;border-radius:40px 40px;\">UNet Using TensorFlow and Keras Starter Notebook</p>\n<img src=\"https://production-media.paperswithcode.com/methods/Screen_Shot_2020-07-07_at_9.08.00_PM_rpNArED.png\">\n<div style=\"text-align: center;\">\n  <a href=\"https://paperswithcode.com/method/u-net\" style=\"color:#1a05ad;display:inline-block;\">Source</a>\n</div>\n<p style=\"font-family:newtimeroman;font-size:120%;color:#302f36;\">U-Net is a convolutional neural network architecture that was developed for and has since become widely adopted in the field of biomedical image segmentation. It was first introduced in a paper by Olaf Ronneberger, Philipp Fischer, and Thomas Brox in 2015, titled <a href=\"https://arxiv.org/abs/1505.04597\" style=\"color:#1a05ad;\">U-Net: Convolutional Networks for Biomedical Image Segmentation</a>. The architecture is designed to work with a very limited number of images and to yield more precise segmentations.\n    \n### <p style=\"background-color:#07041c;font-family:newtimeroman;color:#d3d1e6;font-size:120%;text-align:center;border-radius:40px 40px;\">Key Features of U-Net</p>   \n\n\n| Feature           | Description |\n| ----------------- | ----------- |\n| Symmetric Architecture | U-Net has a U-shaped architecture, with a contracting path for context capture and an expanding path for precise localization. |\n| Contracting Path | Composed of convolutional and max pooling layers, it down-samples the input image to capture context while reducing dimensions. |\n| Expanding Path | Includes up-convolutions and concatenations with features from the contracting path for precise localization. |\n| Skip Connections | Feature maps from the contracting path are concatenated with the expanding path to retain image details during upsampling. |\n| Fewer Training Samples | Designed to learn from a small dataset, using data augmentation to increase sample diversity. |\n| Final Layer | Uses a 1x1 convolution to map feature vectors to the number of classes per pixel. |\n\n### <p style=\"background-color:#07041c;font-family:newtimeroman;color:#d3d1e6;font-size:120%;text-align:center;border-radius:40px 40px;\">Applications of U-Net</p>   \n\n| Application      | Description |\n| ---------------- | ----------- |\n| Medical Image Segmentation | Used for segmenting cells or tissues in medical scans. |\n| General Image Segmentation | Applicable to tasks like satellite image analysis and scene understanding. |\n\n### <p style=\"background-color:#07041c;font-family:newtimeroman;color:#d3d1e6;font-size:120%;text-align:center;border-radius:40px 40px;\">Performance of U-Net</p>   \n\n| Aspect            | Description |\n| ----------------- | ----------- |\n| Small Dataset Performance | Known for its effectiveness with small datasets, which is common in medical imaging. |\n| Precise Localization | Its architecture enables precise localization of structures within images. |\n| Inspirational Design | Has inspired variations and improvements for specific tasks, including 3D segmentation. |\n\n# <p style=\"background-color:#07041c;font-family:newtimeroman;color:#d3d1e6;font-size:120%;text-align:center;border-radius:40px 40px;\">TABLE OF CONTENTS</p> \n    \n* [1. Importing Libraries](#1)\n    \n* [2. Data Loading & Visualizing Images](#2)\n    \n* [3. Visualizing Distribution of Pixel Values](#3)\n        \n* [4. Preprocessing the Images and Masks](#4)  \n    \n* [5. Splitting the Dataset](#5) \n      \n* [6. Building the UNet Model](#6)\n    \n* [7. Instantiating The UNet Model and Visualizing the Architechture](#7)\n\n* [8. Model Training](#8)\n\n* [9. Model Evaluation](#9)\n\n* [10. Conclusion and Future Directions](#10)","metadata":{}},{"cell_type":"markdown","source":"<a id='1'></a>\n# <p style=\"background-color:#07041c;font-family:newtimeroman;color:#d3d1e6;font-size:120%;text-align:center;border-radius:40px 40px;\">Importing Libraries</p> ","metadata":{}},{"cell_type":"code","source":"import tensorflow as tf\nimport matplotlib.pyplot as plt\nimport tifffile as tiff\nfrom tensorflow import keras\nfrom tensorflow.keras import layers\nfrom tensorflow.keras.utils import plot_model\nfrom sklearn.model_selection import train_test_split\nimport os\nimport numpy as np\n\nimport warnings\nwarnings.filterwarnings('ignore')","metadata":{"execution":{"iopub.status.busy":"2023-11-14T01:51:57.091540Z","iopub.execute_input":"2023-11-14T01:51:57.092476Z","iopub.status.idle":"2023-11-14T01:52:06.992593Z","shell.execute_reply.started":"2023-11-14T01:51:57.092442Z","shell.execute_reply":"2023-11-14T01:52:06.991433Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Checking if GPU is available","metadata":{}},{"cell_type":"code","source":"# Check if GPU is available and output the device name\ngpu_devices = tf.config.experimental.list_physical_devices('GPU')\nif gpu_devices:\n    print(\"GPU is available:\", gpu_devices)\n    for device in gpu_devices:\n        tf.config.experimental.set_memory_growth(device, True)\nelse:\n    print(\"GPU is not available, using CPU instead.\")\n","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2023-11-14T01:52:06.994742Z","iopub.execute_input":"2023-11-14T01:52:06.995611Z","iopub.status.idle":"2023-11-14T01:52:07.416421Z","shell.execute_reply.started":"2023-11-14T01:52:06.995566Z","shell.execute_reply":"2023-11-14T01:52:07.415413Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id='2'></a>\n# <p style=\"background-color:#07041c;font-family:newtimeroman;color:#d3d1e6;font-size:120%;text-align:center;border-radius:40px 40px;\">Visualizing Samples</p> ","metadata":{}},{"cell_type":"code","source":"# Set the base path\nbase_path = '/kaggle/input/blood-vessel-segmentation/train'  \n\n# Replace 'kidney_1_dense' with the dataset you want to explore\ndataset = 'kidney_1_voi'\n\n# Paths to images and labels\nimages_path = os.path.join(base_path, dataset, 'images')\nlabels_path = os.path.join(base_path, dataset, 'labels')\n\n# List the files in the directories\nimage_files = sorted([os.path.join(images_path, f) for f in os.listdir(images_path) if f.endswith('.tif')])\nlabel_files = sorted([os.path.join(labels_path, f) for f in os.listdir(labels_path) if f.endswith('.tif')])\n\n# Function to display a set of images\ndef show_images(images, titles=None, cmap='gray'):\n    n = len(images)\n    fig, axes = plt.subplots(1, n, figsize=(20, 10))\n    if not isinstance(axes, np.ndarray):\n        axes = [axes]\n    for idx, ax in enumerate(axes):\n        ax.imshow(images[idx], cmap=cmap)\n        if titles:\n            ax.set_title(titles[idx])\n        ax.axis('off')\n    plt.tight_layout()\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2023-11-14T01:52:07.417834Z","iopub.execute_input":"2023-11-14T01:52:07.418192Z","iopub.status.idle":"2023-11-14T01:52:07.877592Z","shell.execute_reply.started":"2023-11-14T01:52:07.418160Z","shell.execute_reply":"2023-11-14T01:52:07.876761Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Load and display the first image and its mask\nfirst_image = tiff.imread(image_files[0])\nfirst_label = tiff.imread(label_files[0])\n\nshow_images([first_image, first_label], titles=['First Image', 'First Label'])\n\n# Basic statistics about the images\nimage_shapes = [tiff.imread(file).shape for file in image_files]\n\nprint(f\"Number of images: {len(image_files)}\")\nprint(f\"Image shapes: {set(image_shapes)}\")","metadata":{"execution":{"iopub.status.busy":"2023-11-14T01:52:07.880323Z","iopub.execute_input":"2023-11-14T01:52:07.880613Z","iopub.status.idle":"2023-11-14T01:53:39.698658Z","shell.execute_reply.started":"2023-11-14T01:52:07.880587Z","shell.execute_reply":"2023-11-14T01:53:39.697674Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id='3'></a>\n# <p style=\"background-color:#07041c;font-family:newtimeroman;color:#d3d1e6;font-size:120%;text-align:center;border-radius:40px 40px;\">Visualizing Distribution of Pixel Values</p> ","metadata":{}},{"cell_type":"code","source":"# It's useful to see the distribution of pixel values\npixel_values = first_image.flatten()\nplt.hist(pixel_values, bins=50, color='blue', alpha=0.7)\nplt.title('Pixel Value Distribution')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-11-14T01:53:39.699908Z","iopub.execute_input":"2023-11-14T01:53:39.700186Z","iopub.status.idle":"2023-11-14T01:53:40.108800Z","shell.execute_reply.started":"2023-11-14T01:53:39.700160Z","shell.execute_reply":"2023-11-14T01:53:40.107803Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id='4'></a>\n# <p style=\"background-color:#07041c;font-family:newtimeroman;color:#d3d1e6;font-size:120%;text-align:center;border-radius:40px 40px;\">Preprocessing the Images AND Masks</p> ","metadata":{}},{"cell_type":"code","source":"def preprocess_image(path):\n    # Load the image using tifffile\n    image = tiff.imread(path)\n    \n    # If the image has more than one channel, extract just one channel\n    if image.ndim > 2 and image.shape[2] > 1:\n        image = image[..., 0]\n    \n    # Normalize the image to [0, 1] range\n    image = image / 255.0\n    \n    # Convert image to a TensorFlow tensor\n    image_tensor = tf.convert_to_tensor(image, dtype=tf.float32)\n    \n    # Add a channel dimension if it does not exist\n    if image_tensor.ndim == 2:\n        image_tensor = image_tensor[..., tf.newaxis]\n    \n    # Ensure image tensor is 3D at this point\n    if image_tensor.ndim != 3:\n        raise ValueError('Image tensor must be 3 dimensions [height, width, channels]')\n    \n    # Resize the image to the desired size\n    image_tensor = tf.image.resize(image_tensor, [256, 256])\n    \n    return image_tensor","metadata":{"execution":{"iopub.status.busy":"2023-11-14T01:53:40.110053Z","iopub.execute_input":"2023-11-14T01:53:40.110371Z","iopub.status.idle":"2023-11-14T01:53:40.117481Z","shell.execute_reply.started":"2023-11-14T01:53:40.110345Z","shell.execute_reply":"2023-11-14T01:53:40.116390Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def preprocess_mask(path):\n    # Load the mask using tifffile\n    mask = tiff.imread(path)\n    \n    # If the mask has more than one channel, extract just one channel\n    if mask.ndim > 2 and mask.shape[2] > 1:\n        mask = mask[..., 0]\n    \n    # Normalize the mask to be in [0, 1]\n    mask = mask / 255.0 if mask.max() > 1 else mask\n    \n    # Convert mask to a TensorFlow tensor\n    mask_tensor = tf.convert_to_tensor(mask, dtype=tf.float32)\n    \n    # Add a channel dimension if it does not exist\n    if mask_tensor.ndim == 2:\n        mask_tensor = mask_tensor[..., tf.newaxis]\n    \n    # Ensure mask tensor is 3D at this point\n    if mask_tensor.ndim != 3:\n        raise ValueError('Mask tensor must be 3 dimensions [height, width, channels]')\n    \n    # Resize the mask to the desired size\n    mask_tensor = tf.image.resize(mask_tensor, [256, 256], method=tf.image.ResizeMethod.NEAREST_NEIGHBOR)\n    \n    # The resize operation could push the values away from 0 and 1, we threshold to ensure it's a proper mask\n    mask_tensor = tf.where(mask_tensor > 0.5, 1, 0)\n    \n    return mask_tensor","metadata":{"execution":{"iopub.status.busy":"2023-11-14T01:53:40.118653Z","iopub.execute_input":"2023-11-14T01:53:40.118935Z","iopub.status.idle":"2023-11-14T01:53:40.128363Z","shell.execute_reply.started":"2023-11-14T01:53:40.118911Z","shell.execute_reply":"2023-11-14T01:53:40.127541Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id='5'></a>\n# <p style=\"background-color:#07041c;font-family:newtimeroman;color:#d3d1e6;font-size:120%;text-align:center;border-radius:40px 40px;\">Splitting the Dataset</p> ","metadata":{}},{"cell_type":"code","source":"# Subset 20% of the dataset for quick experiments\nsubset_size = int(0.2 * len(image_files))\nimage_files_subset = image_files[:subset_size]\nlabel_files_subset = label_files[:subset_size]\n\n# Preprocess and load images into memory (This might take a lot of RAM, be careful with large datasets)\nimages = np.array([preprocess_image(f) for f in image_files_subset])\nmasks = np.array([preprocess_mask(f) for f in label_files_subset])\n\n# Split into train and validation sets\nX_train, X_val, y_train, y_val = train_test_split(images, masks, test_size=0.1, random_state=42)","metadata":{"execution":{"iopub.status.busy":"2023-11-14T01:53:40.129282Z","iopub.execute_input":"2023-11-14T01:53:40.129564Z","iopub.status.idle":"2023-11-14T01:54:00.429968Z","shell.execute_reply.started":"2023-11-14T01:53:40.129540Z","shell.execute_reply":"2023-11-14T01:54:00.429165Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id='6'></a>\n# <p style=\"background-color:#07041c;font-family:newtimeroman;color:#d3d1e6;font-size:120%;text-align:center;border-radius:40px 40px;\">Building the UNet Model</p> ","metadata":{}},{"cell_type":"code","source":"# Define the U-Net model\ndef get_unet_model(input_shape=(256, 256, 1)):\n    inputs = keras.Input(shape=input_shape)\n\n    # Contraction path\n    c1 = layers.Conv2D(16, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(inputs)\n    c1 = layers.Dropout(0.1)(c1)\n    c1 = layers.Conv2D(16, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c1)\n    p1 = layers.MaxPooling2D((2, 2))(c1)\n\n    c2 = layers.Conv2D(32, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(p1)\n    c2 = layers.Dropout(0.1)(c2)\n    c2 = layers.Conv2D(32, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c2)\n    p2 = layers.MaxPooling2D((2, 2))(c2)\n\n    c3 = layers.Conv2D(64, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(p2)\n    c3 = layers.Dropout(0.2)(c3)\n    c3 = layers.Conv2D(64, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c3)\n    p3 = layers.MaxPooling2D((2, 2))(c3)\n\n    c4 = layers.Conv2D(128, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(p3)\n    c4 = layers.Dropout(0.2)(c4)\n    c4 = layers.Conv2D(128, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c4)\n    p4 = layers.MaxPooling2D(pool_size=(2, 2))(c4)\n\n    # Middle\n    c5 = layers.Conv2D(256, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(p4)\n    c5 = layers.Dropout(0.3)(c5)\n    c5 = layers.Conv2D(256, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c5)\n\n    # Expansive path \n    u6 = layers.Conv2DTranspose(128, (2, 2), strides=(2, 2), padding='same')(c5)\n    u6 = layers.concatenate([u6, c4])\n    c6 = layers.Conv2D(128, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(u6)\n    c6 = layers.Dropout(0.2)(c6)\n    c6 = layers.Conv2D(128, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c6)\n\n    u7 = layers.Conv2DTranspose(64, (2, 2), strides=(2, 2), padding='same')(c6)\n    u7 = layers.concatenate([u7, c3])\n    c7 = layers.Conv2D(64, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(u7)\n    c7 = layers.Dropout(0.2)(c7)\n    c7 = layers.Conv2D(64, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c7)\n\n    u8 = layers.Conv2DTranspose(32, (2, 2), strides=(2, 2), padding='same')(c7)\n    u8 = layers.concatenate([u8, c2])\n    c8 = layers.Conv2D(32, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(u8)\n    c8 = layers.Dropout(0.1)(c8)\n    c8 = layers.Conv2D(32, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c8)\n\n    u9 = layers.Conv2DTranspose(16, (2, 2), strides=(2, 2), padding='same')(c8)\n    u9 = layers.concatenate([u9, c1], axis=3)\n    c9 = layers.Conv2D(16, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(u9)\n    c9 = layers.Dropout(0.1)(c9)\n    c9 = layers.Conv2D(16, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c9)\n\n    # Output layer\n    outputs = layers.Conv2D(1, (1, 1), activation='sigmoid')(c9)\n\n    model = keras.Model(inputs=[inputs], outputs=[outputs])\n    return model","metadata":{"execution":{"iopub.status.busy":"2023-11-14T01:54:00.431064Z","iopub.execute_input":"2023-11-14T01:54:00.431349Z","iopub.status.idle":"2023-11-14T01:54:00.452892Z","shell.execute_reply.started":"2023-11-14T01:54:00.431324Z","shell.execute_reply":"2023-11-14T01:54:00.451845Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id='7'></a>\n# <p style=\"background-color:#07041c;font-family:newtimeroman;color:#d3d1e6;font-size:120%;text-align:center;border-radius:40px 40px;\">Instantiating The UNet Model and Visualizing the Architechture</p> ","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport tensorflow as tf\nfrom tensorflow.keras import backend as K\n\n\ndef dice_coef(y_true, y_pred):\n    smooth = 100\n    y_true_f = K.flatten(y_true)\n    y_pred_f = K.flatten(y_pred)\n    intersection = K.sum(y_true_f * y_pred_f)\n    dice = (2. * intersection + smooth) / (K.sum(y_true_f) + K.sum(y_pred_f) + smooth)\n    return dice\n\n\ndef dice_coef_loss(y_true, y_pred):\n    return 1 - dice_coef(y_true, y_pred)","metadata":{"execution":{"iopub.status.busy":"2023-11-14T01:54:00.456423Z","iopub.execute_input":"2023-11-14T01:54:00.457214Z","iopub.status.idle":"2023-11-14T01:54:00.468640Z","shell.execute_reply.started":"2023-11-14T01:54:00.457179Z","shell.execute_reply":"2023-11-14T01:54:00.467703Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Instantiate the model\nunet_model = get_unet_model()\n\n# Compile the model\nunet_model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])\n\n# Summary of the model\nunet_model.summary()","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2023-11-14T01:57:56.607005Z","iopub.execute_input":"2023-11-14T01:57:56.607414Z","iopub.status.idle":"2023-11-14T01:57:57.071300Z","shell.execute_reply.started":"2023-11-14T01:57:56.607380Z","shell.execute_reply":"2023-11-14T01:57:57.070073Z"},"collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Plot the model\nplot_model(unet_model, to_file='model.png', show_shapes=True, show_layer_names=True)","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2023-11-14T01:54:00.983358Z","iopub.execute_input":"2023-11-14T01:54:00.983658Z","iopub.status.idle":"2023-11-14T01:54:01.700809Z","shell.execute_reply.started":"2023-11-14T01:54:00.983624Z","shell.execute_reply":"2023-11-14T01:54:01.699907Z"},"collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id='8'></a>\n# <p style=\"background-color:#07041c;font-family:newtimeroman;color:#d3d1e6;font-size:120%;text-align:center;border-radius:40px 40px;\">Model Training</p> ","metadata":{}},{"cell_type":"code","source":"# Train the model\nhistory = unet_model.fit(\n    X_train, y_train,\n    validation_data=(X_val, y_val),\n    batch_size=32,\n    epochs=10  # For a real model, you might need many more epochs\n)","metadata":{"execution":{"iopub.status.busy":"2023-11-14T01:58:04.441347Z","iopub.execute_input":"2023-11-14T01:58:04.441791Z","iopub.status.idle":"2023-11-14T01:58:43.064884Z","shell.execute_reply.started":"2023-11-14T01:58:04.441745Z","shell.execute_reply":"2023-11-14T01:58:43.063984Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id='9'></a>\n# <p style=\"background-color:#07041c;font-family:newtimeroman;color:#d3d1e6;font-size:120%;text-align:center;border-radius:40px 40px;\">Evaluating the Trained UNet Model</p> ","metadata":{}},{"cell_type":"code","source":"# Evaluate the model\nval_loss, val_acc = unet_model.evaluate(X_val, y_val)\nprint(f\"Validation Accuracy: {val_acc}\")","metadata":{"execution":{"iopub.status.busy":"2023-11-14T01:54:03.214156Z","iopub.status.idle":"2023-11-14T01:54:03.214525Z","shell.execute_reply.started":"2023-11-14T01:54:03.214332Z","shell.execute_reply":"2023-11-14T01:54:03.214348Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Load test images (assuming similar folder structure as training)\ntest_base_path = '/kaggle/input/blood-vessel-segmentation/test'\ntest_image_files = []\n\nfor dataset in os.listdir(test_base_path):\n    images_path = os.path.join(test_base_path, dataset, 'images')\n    if os.path.isdir(images_path):\n        test_image_files += sorted([os.path.join(images_path, f) for f in os.listdir(images_path) if f.endswith('.tif')])\n\n# Preprocess test images (similar to training images preprocessing)\ntest_images = np.array([preprocess_image(f) for f in test_image_files])\n","metadata":{"execution":{"iopub.status.busy":"2023-11-14T02:00:37.872833Z","iopub.execute_input":"2023-11-14T02:00:37.873706Z","iopub.status.idle":"2023-11-14T02:00:38.113180Z","shell.execute_reply.started":"2023-11-14T02:00:37.873673Z","shell.execute_reply":"2023-11-14T02:00:38.112376Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Predict masks\npredicted_masks = unet_model.predict(test_images)\n\n# Post-process masks: threshold and resize to original size\nthresholded_masks = (predicted_masks > 0.5).astype(np.uint8)","metadata":{"execution":{"iopub.status.busy":"2023-11-14T02:01:07.469708Z","iopub.execute_input":"2023-11-14T02:01:07.470119Z","iopub.status.idle":"2023-11-14T02:01:08.249371Z","shell.execute_reply.started":"2023-11-14T02:01:07.470079Z","shell.execute_reply":"2023-11-14T02:01:08.248292Z"},"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    rle = ' '.join(str(x) for x in runs)\n    if rle=='':\n        rle = '1 0'\n    return rle","metadata":{"execution":{"iopub.status.busy":"2023-11-14T02:01:20.620369Z","iopub.execute_input":"2023-11-14T02:01:20.621351Z","iopub.status.idle":"2023-11-14T02:01:20.629736Z","shell.execute_reply.started":"2023-11-14T02:01:20.621290Z","shell.execute_reply":"2023-11-14T02:01:20.628293Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pandas as pd\n\nrles = [rle_encode(mask.reshape(256, 256)) for mask in thresholded_masks]\nids = [f'{p.split(\"/\")[-3]}_{os.path.basename(p).split(\".\")[0]}' for p in test_image_files]\n\nsubmission = pd.DataFrame({\n    \"id\": ids,\n    \"rle\": rles\n})","metadata":{"execution":{"iopub.status.busy":"2023-11-14T02:01:31.014647Z","iopub.execute_input":"2023-11-14T02:01:31.015000Z","iopub.status.idle":"2023-11-14T02:01:31.037629Z","shell.execute_reply.started":"2023-11-14T02:01:31.014974Z","shell.execute_reply":"2023-11-14T02:01:31.036657Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission.head(10)","metadata":{"execution":{"iopub.status.busy":"2023-11-14T02:02:28.752091Z","iopub.execute_input":"2023-11-14T02:02:28.752459Z","iopub.status.idle":"2023-11-14T02:02:28.763062Z","shell.execute_reply.started":"2023-11-14T02:02:28.752430Z","shell.execute_reply":"2023-11-14T02:02:28.762028Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission.to_csv(\"submission.csv\", index=False)","metadata":{"execution":{"iopub.status.busy":"2023-11-14T02:01:45.245306Z","iopub.execute_input":"2023-11-14T02:01:45.245692Z","iopub.status.idle":"2023-11-14T02:01:45.253699Z","shell.execute_reply.started":"2023-11-14T02:01:45.245662Z","shell.execute_reply":"2023-11-14T02:01:45.252681Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id='10'></a>\n# <p style=\"background-color:#07041c;font-family:newtimeroman;color:#d3d1e6;font-size:120%;text-align:center;border-radius:40px 40px;\">Conclusion and Future Directions</p> \n\nThe UNET model is the simplest model for Biomedical Image Segmentation and here you can see overfitting is happening. You would have to use alot of tuning, preprocessing, maybe transfer learning, and several other hit and trials to improve the performance.\n\nCheckout my SegNet and Attention UNet models in the following respective notebooks, which are not overfitting and gives better results out of the box:\n\n* [SegNet](https://www.kaggle.com/code/salmankhaliq22/sennet-hoa-segnet-tensorflow-starter)\n* [Attention UNet](https://www.kaggle.com/code/salmankhaliq22/sennet-hoa-attention-unet-tensorflow-starter)\n* [Comparing Denoising Techniques using OpenCV and skimage](https://www.kaggle.com/code/salmankhaliq22/opencv-skimage-denoising-techniques)","metadata":{}},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}