{"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":"### Loading Data","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\n\nDIR_PATH = \"/kaggle/input/covid-segmentation/\"\nTRAIN_X_FILE = \"images_medseg.npy\"\nTRAIN_Y_FILE = \"masks_medseg.npy\"\n\nimgs_medseg = np.load(DIR_PATH+TRAIN_X_FILE).astype(np.float32)\nmsks_medseg = np.load(DIR_PATH+TRAIN_Y_FILE).astype(np.float32)","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-12-22T11:48:34.272384Z","iopub.execute_input":"2022-12-22T11:48:34.272777Z","iopub.status.idle":"2022-12-22T11:48:36.636523Z","shell.execute_reply.started":"2022-12-22T11:48:34.272691Z","shell.execute_reply":"2022-12-22T11:48:36.635712Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Visualise the Images","metadata":{}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport numpy as np\n\nplt.style.use(\"dark_background\")\n\ndef visualize(image_batch, mask_batch=None, pred_batch=None, num_samples=8):\n    num_classes = mask_batch.shape[-1] if mask_batch is not None else 0\n    fix, ax = plt.subplots(num_classes + 1, num_samples, figsize=(num_samples * 2, (num_classes + 1) * 2))\n    for i in range(num_samples):\n        ax_image = ax[0, i] if num_classes > 0 else ax[i]\n        ax_image.imshow(image_batch[i,:,:,0], cmap=\"Greys\")\n        ax_image.set_xticks([]) \n        ax_image.set_yticks([])\n        \n        if mask_batch is not None:\n            for j in range(num_classes):\n                if pred_batch is None:\n                    mask_to_show = mask_batch[i,:,:,j]\n                else:\n                    mask_to_show = np.zeros(shape=(*mask_batch.shape[1:-1], 3)) \n                    mask_to_show[..., 0] = pred_batch[i,:,:,j] > 0.5\n                    mask_to_show[..., 1] = mask_batch[i,:,:,j]\n                ax[j + 1, i].imshow(mask_to_show, vmin=0, vmax=1)\n                ax[j + 1, i].set_xticks([]) \n                ax[j + 1, i].set_yticks([]) \n\n    plt.tight_layout()\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2022-12-22T11:48:36.638226Z","iopub.execute_input":"2022-12-22T11:48:36.638569Z","iopub.status.idle":"2022-12-22T11:48:36.650509Z","shell.execute_reply.started":"2022-12-22T11:48:36.638532Z","shell.execute_reply":"2022-12-22T11:48:36.649548Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Description**\n1. Actual Input\n2. Mask for Ground Glass class\n3. Mask for Consolidation class\n4. Mask for Lungs Other class\n5. Mask for Background Class","metadata":{}},{"cell_type":"code","source":"visualize(imgs_medseg, msks_medseg)","metadata":{"execution":{"iopub.status.busy":"2022-12-22T11:48:36.652233Z","iopub.execute_input":"2022-12-22T11:48:36.652858Z","iopub.status.idle":"2022-12-22T11:48:38.833858Z","shell.execute_reply.started":"2022-12-22T11:48:36.652812Z","shell.execute_reply":"2022-12-22T11:48:38.833025Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Pixel Value Distribution Before Normalization","metadata":{}},{"cell_type":"code","source":"def plot_hists(images):\n    plt.hist(images.ravel(), bins=100, density=True, color='b', alpha=1)","metadata":{"execution":{"iopub.status.busy":"2022-12-22T11:48:38.835004Z","iopub.execute_input":"2022-12-22T11:48:38.835294Z","iopub.status.idle":"2022-12-22T11:48:38.841306Z","shell.execute_reply.started":"2022-12-22T11:48:38.835265Z","shell.execute_reply":"2022-12-22T11:48:38.840486Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_hists(imgs_medseg)","metadata":{"execution":{"iopub.status.busy":"2022-12-22T11:48:38.844355Z","iopub.execute_input":"2022-12-22T11:48:38.845023Z","iopub.status.idle":"2022-12-22T11:48:39.487753Z","shell.execute_reply.started":"2022-12-22T11:48:38.844963Z","shell.execute_reply":"2022-12-22T11:48:39.486709Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Normalizing Image Pixels","metadata":{}},{"cell_type":"code","source":"def normalize_img(img):\n    img = img.astype(\"float32\")\n    img[img > 500] = 500\n    img[img < -1500] = -1500\n    min_perc, max_perc = np.percentile(img, 5), np.percentile(img, 95)\n    img_valid = img[(img > min_perc) & (img < max_perc)]\n    mean, std = img_valid.mean(), img_valid.std()\n    img = (img-mean)/std\n    return img","metadata":{"execution":{"iopub.status.busy":"2022-12-22T11:48:39.489373Z","iopub.execute_input":"2022-12-22T11:48:39.489766Z","iopub.status.idle":"2022-12-22T11:48:39.496013Z","shell.execute_reply.started":"2022-12-22T11:48:39.489728Z","shell.execute_reply":"2022-12-22T11:48:39.494621Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Normalized Distribution of Pixels","metadata":{}},{"cell_type":"code","source":"imgs_medseg = normalize_img(imgs_medseg)\nplot_hists(imgs_medseg)","metadata":{"execution":{"iopub.status.busy":"2022-12-22T11:48:39.497421Z","iopub.execute_input":"2022-12-22T11:48:39.49779Z","iopub.status.idle":"2022-12-22T11:48:40.696073Z","shell.execute_reply.started":"2022-12-22T11:48:39.497747Z","shell.execute_reply":"2022-12-22T11:48:40.695175Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Split training and validation data","metadata":{}},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\ntrain_x, val_x, train_y, val_y = train_test_split(imgs_medseg, msks_medseg, test_size=0.1, random_state=42)","metadata":{"execution":{"iopub.status.busy":"2022-12-22T11:48:40.697363Z","iopub.execute_input":"2022-12-22T11:48:40.697725Z","iopub.status.idle":"2022-12-22T11:48:41.740781Z","shell.execute_reply.started":"2022-12-22T11:48:40.697686Z","shell.execute_reply":"2022-12-22T11:48:41.73984Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Building The UNET Architecture","metadata":{}},{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow.keras.layers import Conv2D, BatchNormalization, Activation, MaxPool2D, Conv2DTranspose, Concatenate, Input\nfrom tensorflow.keras.models import Model\n\ndef convolution(input, num_filters):\n  x = Conv2D(num_filters, 3, padding=\"same\")(input)\n  x = BatchNormalization()(x)\n  x = Activation(\"relu\")(x)\n\n  x = Conv2D(num_filters, 3, padding=\"same\")(x)\n  x = BatchNormalization()(x)\n  x = Activation(\"relu\")(x)\n  return x\n\ndef downsample(input, num_filters):\n  x = convolution(input, num_filters)\n  p = MaxPool2D((2,2))(x)\n  return x, p\n\ndef upsample(input, skip_connections, num_filters):\n  x = Conv2DTranspose(num_filters, (2, 2), strides=2, padding=\"same\")(input)\n  x = Concatenate()([x, skip_connections])\n  x = convolution(x, num_filters)\n  return x\n\ndef build_unet(input_shape):\n  inputs = Input(input_shape)\n  \n  sc1, p1 = downsample(inputs, 64)\n  sc2, p2 = downsample(p1, 128)\n  sc3, p3 = downsample(p2, 256)\n  sc4, p4 = downsample(p3, 512)\n\n  b1 = convolution(p4, 1024)\n\n  d1 = upsample(b1, sc4, 512)\n  d2 = upsample(d1, sc3, 256)\n  d3 = upsample(d2, sc2, 128)\n  d4 = upsample(d3, sc1, 64)\n\n  outputs = Conv2D(4,(1,1),padding=\"same\",activation=\"softmax\")(d4)\n\n  model = Model(inputs, outputs, name=\"U-Net\")\n  return model","metadata":{"execution":{"iopub.status.busy":"2022-12-22T11:48:41.7433Z","iopub.execute_input":"2022-12-22T11:48:41.743622Z","iopub.status.idle":"2022-12-22T11:48:46.650145Z","shell.execute_reply.started":"2022-12-22T11:48:41.743591Z","shell.execute_reply":"2022-12-22T11:48:46.649181Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### IoU Metric Definition","metadata":{}},{"cell_type":"code","source":"def iou(true_y, pred_y):\n    def f(true_y, pred_y):\n        intersection = (true_y * pred_y).sum()\n        union = true_y.sum() + pred_y.sum() - intersection\n        x = (intersection)/(union)\n        x = x.astype(np.float32)\n        return x\n    return tf.numpy_function(f, [true_y, pred_y], tf.float32)","metadata":{"execution":{"iopub.status.busy":"2022-12-22T11:48:46.651518Z","iopub.execute_input":"2022-12-22T11:48:46.65185Z","iopub.status.idle":"2022-12-22T11:48:46.657857Z","shell.execute_reply.started":"2022-12-22T11:48:46.651815Z","shell.execute_reply":"2022-12-22T11:48:46.657015Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Building Model","metadata":{}},{"cell_type":"code","source":"unet = build_unet(imgs_medseg.shape[1:])\nunet.compile(loss=\"binary_crossentropy\", optimizer=\"adam\", metrics=[\"acc\", iou])\nresults = unet.fit(train_x, train_y, validation_data=(val_x, val_y), epochs=100, batch_size=1, verbose=1)","metadata":{"execution":{"iopub.status.busy":"2022-12-22T11:48:46.659175Z","iopub.execute_input":"2022-12-22T11:48:46.659757Z","iopub.status.idle":"2022-12-22T12:12:43.416385Z","shell.execute_reply.started":"2022-12-22T11:48:46.659719Z","shell.execute_reply":"2022-12-22T12:12:43.415605Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Training Analytics","metadata":{}},{"cell_type":"code","source":"plt.figure(0)\nplt.plot(results.history[\"acc\"])\nplt.plot(results.history[\"val_acc\"])\nplt.title(\"Training vs Validation Accuracy\", color=\"white\")\n\nplt.xlabel(\"epoch\", color=\"white\")\nplt.ylabel(\"accuracy\", color=\"white\")\nplt.legend([\"train\", \"val\"])\nplt.show()\n\nplt.figure(1)\nplt.plot(results.history[\"iou\"])\nplt.plot(results.history[\"val_iou\"])\nplt.title(\"Training vs Validation IoU\", color=\"white\")\n\nplt.xlabel(\"epoch\", color=\"white\")\nplt.ylabel(\"IoU\", color=\"white\")\nplt.legend([\"train\", \"val\"])\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-12-22T12:12:43.418433Z","iopub.execute_input":"2022-12-22T12:12:43.418782Z","iopub.status.idle":"2022-12-22T12:12:43.713693Z","shell.execute_reply.started":"2022-12-22T12:12:43.418745Z","shell.execute_reply":"2022-12-22T12:12:43.712606Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Segmented Output for Ground Glass","metadata":{}},{"cell_type":"code","source":"pred_y = unet.predict(val_x)\nplot_hists(pred_y)\n\ndef filter_pixels(img):\n    for i in range(img.shape[0]):\n        for j in range(img.shape[3]):\n            for k in range(img.shape[1]):\n                for l in range(img.shape[2]):\n                    img[i,k,l,j] = 1 if (img[i,k,l,j] > 0.5) else 0;\n    return img\n\npred_y = filter_pixels(pred_y)\nplot_hists(pred_y)\n\nprint(pred_y.shape)\nfor i in range(0, 10):\n    plt.figure(i)\n    fig, ax = plt.subplots(1,2, figsize=(10,10))\n    ax[0].imshow(pred_y[i,:,:,0])\n    ax[0].title.set_text(\"Predicted Ground Class\")\n    ax[1].imshow(val_y[i,:,:,0])\n    ax[1].title.set_text(\"Actual Ground Class\")","metadata":{"execution":{"iopub.status.busy":"2022-12-22T12:12:43.714947Z","iopub.execute_input":"2022-12-22T12:12:43.715464Z","iopub.status.idle":"2022-12-22T12:13:09.104028Z","shell.execute_reply.started":"2022-12-22T12:12:43.715424Z","shell.execute_reply":"2022-12-22T12:13:09.102318Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}