{"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":"# Brain Tumour Segmentation in MRI slices","metadata":{}},{"cell_type":"markdown","source":"This notebook is using an existing model for brain tumour segmentation in T1w MRI scans. This allows to detect the MRI slices with the largest tumourous areas, which could help to build solutions using attention or focus the training process on the right MRI slices. \nThe dataset is available [here](https://www.kaggle.com/frlemarchand/rsna-miccai-brain-tumour-mask) in case you want to use it. It contains the masks produced in the notebook, for all the studies that contained T1w MRIs scans.","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport math\nimport random\nimport os\nfrom PIL import Image\nimport cv2 as cv\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport tensorflow as tf\nfrom tensorflow import keras\nfrom keras.models import Model, load_model\nfrom keras.layers import Input ,BatchNormalization , Activation \nfrom keras.layers.convolutional import Conv2D, UpSampling2D\nfrom keras.layers.pooling import MaxPooling2D\nfrom keras.layers.merge import concatenate\nfrom keras.callbacks import EarlyStopping, ModelCheckpoint\nfrom keras import optimizers \nfrom keras import backend as K\nfrom sklearn.model_selection import train_test_split","metadata":{"execution":{"iopub.status.busy":"2021-08-09T17:18:34.068153Z","iopub.execute_input":"2021-08-09T17:18:34.068765Z","iopub.status.idle":"2021-08-09T17:18:41.204769Z","shell.execute_reply.started":"2021-08-09T17:18:34.068680Z","shell.execute_reply":"2021-08-09T17:18:41.203605Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Build the U-Net model trained by [arashmehrzadi](https://www.kaggle.com/arashmehrzadi) in this [notebook](https://www.kaggle.com/arashmehrzadi/brain-tumor-segmentation-unet)","metadata":{}},{"cell_type":"markdown","source":"The code is the cell below is taken from arashmehrzadi's notebook.","metadata":{}},{"cell_type":"code","source":"def Convolution(input_tensor,filters):\n    x = Conv2D(filters=filters,kernel_size=(3, 3),padding = 'same',strides=(1, 1))(input_tensor)\n    x = BatchNormalization()(x)\n    x = Activation('relu')(x) \n    return x\n\ndef model(input_shape):\n    \n    inputs = Input((input_shape))\n    \n    conv_1 = Convolution(inputs,32)\n    maxp_1 = MaxPooling2D(pool_size = (2, 2), strides = (2, 2), padding = 'same') (conv_1)\n    \n    conv_2 = Convolution(maxp_1,64)\n    maxp_2 = MaxPooling2D(pool_size = (2, 2), strides = (2, 2), padding = 'same') (conv_2)\n    \n    conv_3 = Convolution(maxp_2,128)\n    maxp_3 = MaxPooling2D(pool_size = (2, 2), strides = (2, 2), padding = 'same') (conv_3)\n    \n    conv_4 = Convolution(maxp_3,256)\n    maxp_4 = MaxPooling2D(pool_size = (2, 2), strides = (2, 2), padding = 'same') (conv_4)\n    \n    conv_5 = Convolution(maxp_4,512)\n    upsample_6 = UpSampling2D((2, 2)) (conv_5)\n    \n    conv_6 = Convolution(upsample_6,256)\n    upsample_7 = UpSampling2D((2, 2)) (conv_6)\n    \n    upsample_7 = concatenate([upsample_7, conv_3])\n    \n    conv_7 = Convolution(upsample_7,128)\n    upsample_8 = UpSampling2D((2, 2)) (conv_7)\n    \n    conv_8 = Convolution(upsample_8,64)\n    upsample_9 = UpSampling2D((2, 2)) (conv_8)\n    \n    upsample_9 = concatenate([upsample_9, conv_1])\n    \n    conv_9 = Convolution(upsample_9,32)\n    outputs = Conv2D(1, (1, 1), activation='sigmoid') (conv_9)\n    \n    model = Model(inputs=[inputs], outputs=[outputs]) \n    \n    return model","metadata":{"execution":{"iopub.status.busy":"2021-08-09T17:18:41.206653Z","iopub.execute_input":"2021-08-09T17:18:41.207123Z","iopub.status.idle":"2021-08-09T17:18:41.221385Z","shell.execute_reply.started":"2021-08-09T17:18:41.207058Z","shell.execute_reply":"2021-08-09T17:18:41.220272Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"input_size = 240\nmodel = model(input_shape = (input_size, input_size, 1))\nmodel.load_weights(\"../input/brain-tumour-segmentation/BraTs2020.h5\")\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2021-08-09T17:18:41.224118Z","iopub.execute_input":"2021-08-09T17:18:41.224404Z","iopub.status.idle":"2021-08-09T17:18:42.166880Z","shell.execute_reply.started":"2021-08-09T17:18:41.224377Z","shell.execute_reply":"2021-08-09T17:18:42.165787Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Try the model on a few T1w MRI slices ","metadata":{}},{"cell_type":"code","source":"path_to_training_studies = \"../input/rsna-miccai-png/train/\"\ntraining_studies = os.listdir(path_to_training_studies)\nrandom.seed(24)\nstudies_to_view = random.choices(training_studies, k=3)","metadata":{"execution":{"iopub.status.busy":"2021-08-09T17:42:37.529591Z","iopub.execute_input":"2021-08-09T17:42:37.529979Z","iopub.status.idle":"2021-08-09T17:42:37.540443Z","shell.execute_reply.started":"2021-08-09T17:42:37.529948Z","shell.execute_reply":"2021-08-09T17:42:37.539631Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def prediction(img_path, save_folder=\"\"):\n    '''\n    resize the input image and run the prediction\n    while removing some noise and saving the mask if required\n    '''\n    \n    test_img = Image.open(img_path)\n    resized_img = np.array(test_img.resize((input_size, input_size)))\n    \n    result = model.predict(np.array([resized_img]))[0].transpose(2,0,1)[0]\n\n    #Remove some of the noise in the predicted mask\n    kernel = np.ones((10,10),np.uint8)\n    result = cv.morphologyEx(result, cv.MORPH_OPEN, kernel)\n    result = np.where(result > 0.9, 1, 0)\n    \n    if save_folder!=\"\":\n        save_path = img_path.replace(\"../input/rsna-miccai-png\", save_folder)\n        save_path = save_path.replace(\".png\",\"-tumour-mask.png\").replace(\"/T1w\",\"\")\n        save_folder = save_path.replace(save_path.split(\"/\")[-1],\"\")\n        if not os.path.exists(save_folder):\n            os.mkdir(save_folder)\n        \n        resized_result = cv.resize(result.astype(\"float32\"), (512,512), interpolation = cv.INTER_AREA)\n        cv.imwrite(save_path, resized_result)\n    \n    return resized_img, result","metadata":{"execution":{"iopub.status.busy":"2021-08-09T17:42:37.702400Z","iopub.execute_input":"2021-08-09T17:42:37.703006Z","iopub.status.idle":"2021-08-09T17:42:37.713694Z","shell.execute_reply.started":"2021-08-09T17:42:37.702957Z","shell.execute_reply":"2021-08-09T17:42:37.712447Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def find_tumour(study_filename, save_folder=\"\", dataset=path_to_training_studies):\n    '''\n    Apply the model on all MRI slices and return the \n    slice with the greatest amount of pixels with tumour\n    '''\n    \n    max_detected = 0\n    tumour_slice = \"\"\n    MRI_slices = os.listdir(\"{}{}/T1w/\".format(dataset, study_filename))\n    \n    for MRI_slice_filename in MRI_slices:\n        path_to_slice = \"{}{}/T1w/{}\".format(dataset, study_filename, MRI_slice_filename)\n        formatted_img, result = prediction(path_to_slice, save_folder)\n        \n        tumour_pixel = len(result[result>0.5])\n        \n        if max_detected < tumour_pixel:\n            max_detected = tumour_pixel\n            tumour_slice = path_to_slice\n    return tumour_slice\n\ndef display(img, result):\n    plt.imshow(np.squeeze(img),cmap='gray')\n    plt.imshow(np.squeeze(result),alpha=0.6,cmap='Reds')\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2021-08-09T17:42:37.863841Z","iopub.execute_input":"2021-08-09T17:42:37.864222Z","iopub.status.idle":"2021-08-09T17:42:37.872598Z","shell.execute_reply.started":"2021-08-09T17:42:37.864186Z","shell.execute_reply":"2021-08-09T17:42:37.871252Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We can now easily scan through the MRIs and highlight the MRI slice with the highest presence of tumour.","metadata":{}},{"cell_type":"code","source":"%%time\nMRI_slice_filename = find_tumour(studies_to_view[0])\nimg, result = prediction(MRI_slice_filename)\ndisplay(img, result)","metadata":{"execution":{"iopub.status.busy":"2021-08-09T17:42:38.243432Z","iopub.execute_input":"2021-08-09T17:42:38.243832Z","iopub.status.idle":"2021-08-09T17:43:03.879521Z","shell.execute_reply.started":"2021-08-09T17:42:38.243800Z","shell.execute_reply":"2021-08-09T17:43:03.878436Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\nMRI_slice_filename = find_tumour(studies_to_view[1])\nimg, result = prediction(MRI_slice_filename)\ndisplay(img, result)","metadata":{"execution":{"iopub.status.busy":"2021-08-09T17:43:03.881294Z","iopub.execute_input":"2021-08-09T17:43:03.881582Z","iopub.status.idle":"2021-08-09T17:43:08.293886Z","shell.execute_reply.started":"2021-08-09T17:43:03.881554Z","shell.execute_reply":"2021-08-09T17:43:08.292926Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\nMRI_slice_filename = find_tumour(studies_to_view[2])\nimg, result = prediction(MRI_slice_filename)\ndisplay(img, result)","metadata":{"execution":{"iopub.status.busy":"2021-08-09T17:43:08.295470Z","iopub.execute_input":"2021-08-09T17:43:08.295777Z","iopub.status.idle":"2021-08-09T17:43:13.467881Z","shell.execute_reply.started":"2021-08-09T17:43:08.295745Z","shell.execute_reply":"2021-08-09T17:43:13.467117Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Let's create the masks for the training set and save them.","metadata":{}},{"cell_type":"code","source":"train_folder_content = os.listdir(path_to_training_studies)\nos.mkdir('../working/rsna-miccai-tumour-mask')\nos.mkdir('../working/rsna-miccai-tumour-mask/train')\nos.mkdir('../working/rsna-miccai-tumour-mask/test')\nfor study_folder in train_folder_content:\n    if os.path.exists(\"{}{}/T1w\".format(path_to_training_studies, study_folder)):\n        MRI_slice_filename = find_tumour(study_folder, save_folder=\"../working/rsna-miccai-tumour-mask\", dataset=path_to_training_studies)","metadata":{"execution":{"iopub.status.busy":"2021-08-08T17:32:36.1538Z","iopub.execute_input":"2021-08-08T17:32:36.15429Z","iopub.status.idle":"2021-08-08T17:32:59.13344Z","shell.execute_reply.started":"2021-08-08T17:32:36.154247Z","shell.execute_reply":"2021-08-08T17:32:59.13224Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"And now, time to create the masks for the test set!","metadata":{}},{"cell_type":"code","source":"path_to_test_studies = \"../input/rsna-miccai-png/test/\"\ntest_folder_content = os.listdir(path_to_test_studies)\nfor study_folder in test_folder_content:\n    if os.path.exists(\"{}{}/T1w\".format(path_to_test_studies, study_folder)):\n        MRI_slice_filename = find_tumour(study_folder, save_folder=\"../working/rsna-miccai-tumour-mask\", dataset=path_to_test_studies)","metadata":{"execution":{"iopub.status.busy":"2021-08-08T14:36:15.312072Z","iopub.execute_input":"2021-08-08T14:36:15.312586Z","iopub.status.idle":"2021-08-08T14:36:18.835477Z","shell.execute_reply.started":"2021-08-08T14:36:15.312543Z","shell.execute_reply":"2021-08-08T14:36:18.834551Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Just a quick check to make sure the masks are correctly saved.","metadata":{}},{"cell_type":"code","source":"im = Image.open(\"../working/rsna-miccai-tumour-mask/test/00114/Image-13-tumour-mask.png\")\nplt.imshow(im)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-08-08T14:37:05.439231Z","iopub.execute_input":"2021-08-08T14:37:05.439607Z","iopub.status.idle":"2021-08-08T14:37:05.601703Z","shell.execute_reply.started":"2021-08-08T14:37:05.439574Z","shell.execute_reply":"2021-08-08T14:37:05.600978Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Just zipping all the images into a compressed folder so we can download the output easily\n!zip -r -qq rsna-miccai-tumour-mask.zip \"../working/rsna-miccai-tumour-mask/\"\n!rm -rf \"../working/rsna-miccai-tumour-mask/\"","metadata":{"execution":{"iopub.status.busy":"2021-08-08T17:40:26.687562Z","iopub.execute_input":"2021-08-08T17:40:26.688155Z","iopub.status.idle":"2021-08-08T17:40:28.177279Z","shell.execute_reply.started":"2021-08-08T17:40:26.688097Z","shell.execute_reply":"2021-08-08T17:40:28.176122Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Thanks for reading this notebook! If you found this notebook helpful, please give it an upvote. It is always greatly appreciated!","metadata":{}}]}