{"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":"Hello fellow Kagglers,\n\nThis notebook is yet another implementation of a patched dataset generation.\n\nMost images are 3000x3000 images, which are split in 100 300x300 patches to preserve to full resolution.\n\nThe reason for patching the images is, first of all, to prevent out-of-memory errors. Using 3000x3000 images will, even in tiny models with small batch sizes, not fit in the 16GB Kaggle GPU's.\n\nSecondly, when resizing the images to a convenient size, say 224x224, a lot of information is lost by reducing the number of pixels from 9M to just ~50K.\n\nPatching the images is the solution! the full detail is preserved by using the full resolution, but the patches themselves are just 300x300 which will easily fit in the GPU memory.\n\nAnother advantage is the larger amount of training samples, increasing the number of samples from 351 to 35100, because each image is split in 100 patches.\n\n**V2**\n\nAfter many experiments non-patched 640x640 images turned out to give the best result.\n\nA training and inference notebook will follow soon.","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport tensorflow as tf\n\nfrom tqdm.notebook import tqdm\nfrom multiprocessing import cpu_count\n\nimport imageio\nimport tifffile\nimport cv2\nimport math\nimport sys\nimport glob\nimport os\nimport joblib","metadata":{"execution":{"iopub.status.busy":"2022-08-14T15:26:21.294820Z","iopub.execute_input":"2022-08-14T15:26:21.295379Z","iopub.status.idle":"2022-08-14T15:26:30.957203Z","shell.execute_reply.started":"2022-08-14T15:26:21.295268Z","shell.execute_reply":"2022-08-14T15:26:30.955909Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Load training DataFrame\ntrain = pd.read_csv('/kaggle/input/hubmap-organ-segmentation/train.csv')\n\ndisplay(train.head())\n\ndisplay(train.info())","metadata":{"execution":{"iopub.status.busy":"2022-08-14T15:26:30.959262Z","iopub.execute_input":"2022-08-14T15:26:30.959927Z","iopub.status.idle":"2022-08-14T15:26:31.377888Z","shell.execute_reply.started":"2022-08-14T15:26:30.959887Z","shell.execute_reply":"2022-08-14T15:26:31.376977Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"MAX_WIDTH = train['img_width'].max()\nMAX_HEIGHT = train['img_height'].max()\nN_CHANNELS = 3\nIMG_SIZE = 640\nPATCH_SIZE = 640\nN_PATCHES_PER_IMAGE = (IMG_SIZE // PATCH_SIZE) ** 2\nN_SAMPLES = len(train)\nN_PATCHES = N_SAMPLES * N_PATCHES_PER_IMAGE\n\nprint(f'N_SAMPLES: {N_SAMPLES}, N_PATCHES: {N_PATCHES}, MAX_WIDTH: {MAX_WIDTH}, MAX_HEIGHT: {MAX_HEIGHT}')\nprint(f'IMG_SIZE: {IMG_SIZE}, PATCH_SIZE: {PATCH_SIZE}, N_PATCHES_PER_IMAGE: {N_PATCHES_PER_IMAGE}')","metadata":{"execution":{"iopub.status.busy":"2022-08-14T15:26:31.379164Z","iopub.execute_input":"2022-08-14T15:26:31.379678Z","iopub.status.idle":"2022-08-14T15:26:31.386995Z","shell.execute_reply.started":"2022-08-14T15:26:31.379646Z","shell.execute_reply":"2022-08-14T15:26:31.385932Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Explorative Data Analysis","metadata":{}},{"cell_type":"code","source":"# Image Sizes, most images are 3000x3000 pixels\ntrain[['img_height', 'img_width']].value_counts().sort_values(ascending=False)","metadata":{"execution":{"iopub.status.busy":"2022-08-14T15:26:31.389897Z","iopub.execute_input":"2022-08-14T15:26:31.390270Z","iopub.status.idle":"2022-08-14T15:26:31.413146Z","shell.execute_reply.started":"2022-08-14T15:26:31.390236Z","shell.execute_reply":"2022-08-14T15:26:31.412107Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Data Source Distribution\ndisplay(train['data_source'].value_counts().to_frame())","metadata":{"execution":{"iopub.status.busy":"2022-08-14T15:26:31.414397Z","iopub.execute_input":"2022-08-14T15:26:31.415190Z","iopub.status.idle":"2022-08-14T15:26:31.426660Z","shell.execute_reply.started":"2022-08-14T15:26:31.415155Z","shell.execute_reply":"2022-08-14T15:26:31.425289Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Pixel Size Distribution\ndisplay(train['pixel_size'].value_counts().to_frame())","metadata":{"execution":{"iopub.status.busy":"2022-08-14T15:26:31.428230Z","iopub.execute_input":"2022-08-14T15:26:31.429277Z","iopub.status.idle":"2022-08-14T15:26:31.443602Z","shell.execute_reply.started":"2022-08-14T15:26:31.429229Z","shell.execute_reply":"2022-08-14T15:26:31.442386Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Tissue Thickness\ndisplay(train['tissue_thickness'].value_counts().to_frame())","metadata":{"execution":{"iopub.status.busy":"2022-08-14T15:26:31.445191Z","iopub.execute_input":"2022-08-14T15:26:31.445576Z","iopub.status.idle":"2022-08-14T15:26:31.459557Z","shell.execute_reply.started":"2022-08-14T15:26:31.445543Z","shell.execute_reply":"2022-08-14T15:26:31.458316Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(8,5))\ntrain['age'].plot(kind='hist')\nplt.title('Age Distribution', size=24)\nplt.xlim(0, 100)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-08-14T15:26:31.460934Z","iopub.execute_input":"2022-08-14T15:26:31.461687Z","iopub.status.idle":"2022-08-14T15:26:31.719347Z","shell.execute_reply.started":"2022-08-14T15:26:31.461640Z","shell.execute_reply":"2022-08-14T15:26:31.718125Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ax = plt.figure(figsize=(8, 8), facecolor='white')\ntrain['organ'].value_counts().plot(kind='pie', autopct='%1.1f%%', title='Organ Distribution')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-08-14T15:27:41.848112Z","iopub.execute_input":"2022-08-14T15:27:41.848554Z","iopub.status.idle":"2022-08-14T15:27:42.006898Z","shell.execute_reply.started":"2022-08-14T15:27:41.848519Z","shell.execute_reply":"2022-08-14T15:27:42.005312Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ax = plt.figure(figsize=(8, 8), facecolor='white')\ntrain['sex'].value_counts().plot(kind='pie', autopct='%1.1f%%', title='Sex Distribution')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-08-14T15:27:54.590537Z","iopub.execute_input":"2022-08-14T15:27:54.590935Z","iopub.status.idle":"2022-08-14T15:27:54.709756Z","shell.execute_reply.started":"2022-08-14T15:27:54.590900Z","shell.execute_reply":"2022-08-14T15:27:54.708531Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Plot Samples","metadata":{}},{"cell_type":"code","source":"# Resize all images to 3000x3000\ndef resize_tensor(tensor):\n    return cv2.resize(tensor, [IMG_SIZE, IMG_SIZE], interpolation=cv2.INTER_CUBIC).astype(np.uint8)","metadata":{"execution":{"iopub.status.busy":"2022-08-14T15:26:32.031673Z","iopub.execute_input":"2022-08-14T15:26:32.032506Z","iopub.status.idle":"2022-08-14T15:26:32.039293Z","shell.execute_reply.started":"2022-08-14T15:26:32.032458Z","shell.execute_reply":"2022-08-14T15:26:32.038055Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# ref: https://www.kaggle.com/paulorzp/run-length-encode-and-decode\ndef get_mask(image_id):\n    row = train.loc[train['id'] == image_id].squeeze()\n    h, w = row[['img_height', 'img_width']]\n    mask = np.zeros(shape=[h * w], dtype=np.uint8)\n    s = row['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    for lo, hi in zip(starts, ends):\n        mask[lo : hi] = 1\n        \n    mask = mask.reshape([h, w]).T\n        \n    mask = resize_tensor(mask)\n    \n    mask = np.expand_dims(mask, axis=2)\n        \n    return mask","metadata":{"execution":{"iopub.status.busy":"2022-08-14T15:26:32.040868Z","iopub.execute_input":"2022-08-14T15:26:32.041930Z","iopub.status.idle":"2022-08-14T15:26:32.054261Z","shell.execute_reply.started":"2022-08-14T15:26:32.041879Z","shell.execute_reply":"2022-08-14T15:26:32.052943Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Reads an image and makes a negative to make tissue colored and background black\ndef get_image(image_id, negative=False):\n    image = tifffile.imread(f'/kaggle/input/hubmap-organ-segmentation/train_images/{image_id}.tiff')\n    if len(image.shape) == 5:\n        image = image.squeeze().transpose(1, 2, 0)\n        \n    # Reverse pixels to make tissue colored and background black\n    if negative:\n        image = image - image.min()\n        image = image / (image.max() - image.min())\n        image = image * 255\n        image = 255 - image.astype(np.uint8)\n        \n    image = resize_tensor(image)\n        \n    return image\n\nimage = get_image(train.loc[0, 'id'], True)","metadata":{"execution":{"iopub.status.busy":"2022-08-14T15:26:32.056203Z","iopub.execute_input":"2022-08-14T15:26:32.057183Z","iopub.status.idle":"2022-08-14T15:26:32.874716Z","shell.execute_reply.started":"2022-08-14T15:26:32.056972Z","shell.execute_reply":"2022-08-14T15:26:32.873799Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Shows a batch of images\ndef show_image_and_masks(rows=4, cols=4):\n    # Figure\n    fig, axes = plt.subplots(nrows=rows, ncols=cols, figsize=(cols*8, rows*6))\n    # Unique Image Ids\n    image_ids = train['id'].unique()\n    \n    for r in range(rows):\n        image_id = image_ids[r]\n        df_row = train.loc[train['id'] == image_id].head(1).squeeze()\n        # Rad Image\n        image = get_image(image_id)\n        image_negative = get_image(image_id, negative=True)\n        \n        # Image Original\n        axes[r, 0].imshow(image)\n        axes[r, 0].set_title(f'Image {image_id} Raw', size=16)\n        axes[r, 0].axis(False)\n        \n        # Image Negative Original\n        axes[r, 1].imshow(image_negative)\n        axes[r, 1].set_title(f'Image {image_id} Negative min: {image_negative.min()} max: {image_negative.max()}', size=16)\n        axes[r, 1].axis(False)\n        \n        # Mask\n        mask = get_mask(image_id)\n        axes[r, 2].imshow(mask)\n        axes[r, 2].set_title('Mask', size=16)\n        axes[r, 2].axis(False)\n        \n        # Image with Mask\n        axes[r, 3].imshow(image)\n        axes[r, 3].imshow((mask * np.array([255, 0, 0])), alpha=0.50)\n        axes[r, 3].set_title('Image and Mask', size=16)\n        axes[r, 3].axis(False)\n            \n    # Adjust Vertical Space Between Subplots\n    fig.subplots_adjust(wspace=0.10)","metadata":{"execution":{"iopub.status.busy":"2022-08-14T15:26:32.877043Z","iopub.execute_input":"2022-08-14T15:26:32.877493Z","iopub.status.idle":"2022-08-14T15:26:32.890069Z","shell.execute_reply.started":"2022-08-14T15:26:32.877446Z","shell.execute_reply":"2022-08-14T15:26:32.888621Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"show_image_and_masks(rows=8)","metadata":{"execution":{"iopub.status.busy":"2022-08-14T15:26:32.891372Z","iopub.execute_input":"2022-08-14T15:26:32.892069Z","iopub.status.idle":"2022-08-14T15:26:43.565894Z","shell.execute_reply.started":"2022-08-14T15:26:32.892022Z","shell.execute_reply":"2022-08-14T15:26:43.564819Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Create Train Arrays","metadata":{}},{"cell_type":"code","source":"# Using build in Tensorflow functions, patches an images\ndef extract_patches(image):\n    _, _, c = image.shape\n    image = tf.expand_dims(image, 0)\n    image_patches = tf.image.extract_patches(image, [1,PATCH_SIZE,PATCH_SIZE,1], [1, PATCH_SIZE, PATCH_SIZE, 1], [1, 1, 1, 1], padding='SAME')\n    image_patches = tf.reshape(image_patches, [N_PATCHES_PER_IMAGE, PATCH_SIZE, PATCH_SIZE, c])\n    image_patches = image_patches.numpy()\n\n    return image_patches","metadata":{"execution":{"iopub.status.busy":"2022-08-14T15:26:43.567117Z","iopub.execute_input":"2022-08-14T15:26:43.567999Z","iopub.status.idle":"2022-08-14T15:26:43.575335Z","shell.execute_reply.started":"2022-08-14T15:26:43.567963Z","shell.execute_reply":"2022-08-14T15:26:43.574029Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Function to get both the image and mask for a given image_id\ndef get_image_mask(image_id):    \n    image = get_image(image_id, True)\n    image_patches = extract_patches(image)\n    \n    mask = get_mask(image_id)\n    mask_patches = extract_patches(mask)\n    \n    organ = str.encode(train.loc[train['id'] == image_id, 'organ'].squeeze())\n    \n    return image_patches, mask_patches, organ","metadata":{"execution":{"iopub.status.busy":"2022-08-14T15:26:43.576694Z","iopub.execute_input":"2022-08-14T15:26:43.577049Z","iopub.status.idle":"2022-08-14T15:26:43.606924Z","shell.execute_reply.started":"2022-08-14T15:26:43.577016Z","shell.execute_reply":"2022-08-14T15:26:43.605677Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Put every image in a seperate TFRecord file\nN_CHUNKS = len(train)\nCHUNKS = np.array_split(train['id'].values, N_CHUNKS)\n\nprint(f'N_CHUNKS: {N_CHUNKS}, CHUNK_SIZE: {len(CHUNKS[0])}')","metadata":{"execution":{"iopub.status.busy":"2022-08-14T15:29:01.147203Z","iopub.execute_input":"2022-08-14T15:29:01.147627Z","iopub.status.idle":"2022-08-14T15:29:01.154914Z","shell.execute_reply.started":"2022-08-14T15:29:01.147594Z","shell.execute_reply":"2022-08-14T15:29:01.153740Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def to_tf_records(chunks):\n    N_SAMPLES_PER_TFRECORD = []\n    ORGAN_PER_TFRECORD = []\n    for chunk_idx, image_id in enumerate(tqdm(chunks)):\n        # Get Image and Mask Patches\n        image_patches, mask_patches, organ = get_image_mask(image_id.squeeze())\n        tfrecord_name = f'batch_{chunk_idx}.tfrecords'\n        \n        # Create the actual TFRecords\n        with tf.io.TFRecordWriter(tfrecord_name) as file_writer:\n            sample_count = 0\n            for image, mask in zip(image_patches, mask_patches):\n                sample_count += 1\n\n                image_serialized = tf.io.serialize_tensor(image).numpy()\n                mask_serialized = tf.io.serialize_tensor(mask).numpy()\n\n                record_bytes = tf.train.Example(features=tf.train.Features(feature={\n                    # Image\n                    'image': tf.train.Feature(bytes_list=tf.train.BytesList(value=[image_serialized])),\n                    # Mask\n                    'mask': tf.train.Feature(bytes_list=tf.train.BytesList(value=[mask_serialized])),\n                    \n                    # Organ\n                    'organ': tf.train.Feature(bytes_list=tf.train.BytesList(value=[organ])),\n                })).SerializeToString()\n                file_writer.write(record_bytes)\n                    \n            # Add Sample Count\n            N_SAMPLES_PER_TFRECORD.append(sample_count)\n            # Add organ\n            ORGAN_PER_TFRECORD.append(organ)\n            \n    # Save Number of Samples per TFRecord to determine step count during training\n    np.save('N_SAMPLES_PER_TFRECORD.npy', np.array(N_SAMPLES_PER_TFRECORD, dtype=np.int16))\n    # Save organ per TFRecord for stratifying kfolds\n    np.save('ORGAN_PER_TFRECORD.npy', np.array(ORGAN_PER_TFRECORD, dtype=str))\n\n# Create TFRecords\nto_tf_records(CHUNKS)","metadata":{"execution":{"iopub.status.busy":"2022-08-14T15:29:01.377675Z","iopub.execute_input":"2022-08-14T15:29:01.378106Z","iopub.status.idle":"2022-08-14T15:29:04.667478Z","shell.execute_reply.started":"2022-08-14T15:29:01.378064Z","shell.execute_reply":"2022-08-14T15:29:04.666256Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Check TFRecord","metadata":{}},{"cell_type":"code","source":"# Function to decode the TFRecords\ndef decode_tfrecord(record_bytes):\n    features = tf.io.parse_single_example(record_bytes, {\n        'image': tf.io.FixedLenFeature([], tf.string),\n        'mask': tf.io.FixedLenFeature([], tf.string),\n        'organ': tf.io.FixedLenFeature([], tf.string),\n    })\n    \n    image = tf.io.parse_tensor(features['image'], out_type=tf.uint8)\n    image = tf.reshape(image, [PATCH_SIZE, PATCH_SIZE, N_CHANNELS])\n    \n    mask = tf.io.parse_tensor(features['mask'], out_type=tf.uint8)\n    mask = tf.reshape(mask, [PATCH_SIZE, PATCH_SIZE, 1])\n\n    organ = features['organ']\n    \n    # Explicit reshape needed for TPU, tell cimpiler dimensions of image\n    image = tf.reshape(image, [PATCH_SIZE, PATCH_SIZE, N_CHANNELS])\n    # Explicit reshape needed for TPU, tell cimpiler dimensions of image\n    mask = tf.reshape(mask, [PATCH_SIZE, PATCH_SIZE, 1])\n    \n    return image, mask, organ","metadata":{"execution":{"iopub.status.busy":"2022-08-14T15:29:04.670029Z","iopub.execute_input":"2022-08-14T15:29:04.670507Z","iopub.status.idle":"2022-08-14T15:29:04.682297Z","shell.execute_reply.started":"2022-08-14T15:29:04.670461Z","shell.execute_reply":"2022-08-14T15:29:04.680937Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Sample Dataset\ndef get_train_dataset(bs):\n    FNAMES_TRAIN_TFRECORDS = tf.io.gfile.glob('./*.tfrecords')\n    train_dataset = tf.data.TFRecordDataset(FNAMES_TRAIN_TFRECORDS, num_parallel_reads=1)\n    train_dataset = train_dataset.map(decode_tfrecord, num_parallel_calls=cpu_count())\n    train_dataset = train_dataset.batch(bs)\n    \n    return train_dataset","metadata":{"execution":{"iopub.status.busy":"2022-08-14T15:29:04.683484Z","iopub.execute_input":"2022-08-14T15:29:04.684612Z","iopub.status.idle":"2022-08-14T15:29:04.701319Z","shell.execute_reply.started":"2022-08-14T15:29:04.684573Z","shell.execute_reply":"2022-08-14T15:29:04.699874Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Plot Patches","metadata":{}},{"cell_type":"code","source":"# Shows a batch of images\ndef show_batch(dataset, rows=10, cols=2):\n    images, masks, organs = next(iter(dataset))\n    fig, axes = plt.subplots(nrows=rows, ncols=cols, figsize=(cols*6, rows*6))\n    for r in range(rows):\n        axes[r, 0].imshow(images[r])\n        organ = organs[r].numpy().decode(\"UTF-8\")\n        axes[r, 0].set_title(f'Organ: {organ}', size=16)\n        axes[r, 1].imshow(masks[r])\n        axes[r, 1].set_title('Mask', size=16)","metadata":{"execution":{"iopub.status.busy":"2022-08-14T15:29:08.525678Z","iopub.execute_input":"2022-08-14T15:29:08.526141Z","iopub.status.idle":"2022-08-14T15:29:08.535067Z","shell.execute_reply.started":"2022-08-14T15:29:08.526102Z","shell.execute_reply":"2022-08-14T15:29:08.533934Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dataset = get_train_dataset(10)\nshow_batch(train_dataset)","metadata":{"execution":{"iopub.status.busy":"2022-08-14T15:29:08.536943Z","iopub.execute_input":"2022-08-14T15:29:08.537965Z","iopub.status.idle":"2022-08-14T15:29:12.736648Z","shell.execute_reply.started":"2022-08-14T15:29:08.537923Z","shell.execute_reply":"2022-08-14T15:29:12.734980Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Reconstruct Image/Mask from Patches","metadata":{}},{"cell_type":"code","source":"# Reconstruct Images/Masks from patches to visualize dataset\ndef show_image_mask_from_patches(dataset, n_samples=10):\n    s = int(N_PATCHES_PER_IMAGE ** 0.50)\n    counter = 0\n    dataset_iter = iter(dataset)\n    \n    for _ in tqdm(range(n_samples)):\n        # Main plot\n        fig = plt.figure(figsize=(30, 10))\n        subfigs = fig.subfigures(1, 3)\n        plt.suptitle('Patched Image/Mask/Combined', fontsize=48, y=1.1)\n        images, masks, organs = next(dataset_iter)\n        o = organs[0].numpy().decode()\n        \n        # Make subplots\n        ax_images = subfigs[0].subplots(s, s)\n        subfigs[0].suptitle(f'Image ({o})', size=32)\n        ax_masks = subfigs[1].subplots(s, s)\n        subfigs[1].suptitle('Mask', size=32)\n        ax_combined = subfigs[2].subplots(s, s)\n        subfigs[2].suptitle('Combined', size=32)\n        \n        count = 0\n        for r in range(s):\n            for c in range(s):\n                idx = r * s + c\n                \n                if s > 1:\n                    # Image\n                    ax_images[r,c].imshow(images[idx].numpy())\n                    ax_images[r,c].set_title(f'σ{images[idx].numpy().std():.2f}', c='red')\n                    ax_images[r,c].axis(False)\n                    # Mask\n                    ax_masks[r,c].imshow(masks[idx].numpy() * [255,255,0])\n                    ax_masks[r,c].axis(False)\n                    # Combined\n                    ax_combined[r,c].imshow(images[idx].numpy())\n                    ax_combined[r,c].imshow((masks[idx] * np.array([255, 0, 0])), alpha=0.50)\n                    ax_combined[r,c].axis(False)\n                else:\n                    # Image\n                    ax_images.imshow(images[idx].numpy())\n                    ax_images.set_title(f'σ{images[idx].numpy().std():.2f}', c='red')\n                    ax_images.axis(False)\n                    # Mask\n                    ax_masks.imshow(masks[idx].numpy() * [255,255,0])\n                    ax_masks.axis(False)\n                    # Combined\n                    ax_combined.imshow(images[idx].numpy())\n                    ax_combined.imshow((masks[idx] * np.array([255, 0, 0])), alpha=0.50)\n                    ax_combined.axis(False)\n                \n                count += 1\n                \n        # Show plot\n        fig.subplots_adjust(wspace=0.05)\n        plt.show()","metadata":{"execution":{"iopub.status.busy":"2022-08-14T15:29:40.899838Z","iopub.execute_input":"2022-08-14T15:29:40.900289Z","iopub.status.idle":"2022-08-14T15:29:40.920760Z","shell.execute_reply.started":"2022-08-14T15:29:40.900254Z","shell.execute_reply":"2022-08-14T15:29:40.919387Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Reconstruct samples from patches\ntrain_dataset = get_train_dataset(N_PATCHES_PER_IMAGE)\nshow_image_mask_from_patches(train_dataset)","metadata":{"execution":{"iopub.status.busy":"2022-08-14T15:29:41.901972Z","iopub.execute_input":"2022-08-14T15:29:41.902741Z","iopub.status.idle":"2022-08-14T15:29:52.794528Z","shell.execute_reply.started":"2022-08-14T15:29:41.902703Z","shell.execute_reply":"2022-08-14T15:29:52.792963Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Mean/Standard Deviation Computation","metadata":{}},{"cell_type":"code","source":"# Mean/STD Samples\nMEAN = np.zeros(3, dtype=np.float32)\nSTD = np.zeros(3, dtype=np.float32)\n\nfor image, _, _ in tqdm(get_train_dataset(1), total=N_PATCHES):\n    # Update Mean and STD\n    image_np = image.numpy().squeeze()\n    MEAN += (image_np / 255).mean(axis=(0,1)) / N_PATCHES\n    STD += (image_np /  255).std(axis=(0,1)) / N_PATCHES\n\ndisplay(pd.Series(MEAN).to_frame('Mean'))\ndisplay(pd.Series(STD).to_frame('Standard Deviation'))","metadata":{"execution":{"iopub.status.busy":"2022-08-14T15:30:13.941881Z","iopub.execute_input":"2022-08-14T15:30:13.942406Z","iopub.status.idle":"2022-08-14T15:30:14.679630Z","shell.execute_reply.started":"2022-08-14T15:30:13.942358Z","shell.execute_reply":"2022-08-14T15:30:14.678413Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Save Mean and STD to Normalize Imagesm During Training\nnp.save('MEAN.npy', MEAN)\nnp.save('STD.npy', STD)","metadata":{"execution":{"iopub.status.busy":"2022-08-14T15:29:57.076460Z","iopub.execute_input":"2022-08-14T15:29:57.076787Z","iopub.status.idle":"2022-08-14T15:29:57.082803Z","shell.execute_reply.started":"2022-08-14T15:29:57.076756Z","shell.execute_reply":"2022-08-14T15:29:57.081571Z"},"trusted":true},"execution_count":null,"outputs":[]}]}