{"cells":[{"metadata":{"trusted":true},"cell_type":"code","source":"!pip install imutils\n!pip install efficientnet\n!pip install iterative-stratification\n!pip install albumentations > /dev/null\n!pip install image-classifiers==1.0.0b1","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"import os\nimport gc\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport pydicom\nimport os\nimport random\nimport imutils\nimport matplotlib.pyplot as plt\nimport collections\nfrom tqdm import tqdm_notebook as tqdm\nfrom datetime import datetime\n\nfrom math import ceil, floor, log\nimport cv2\nfrom scipy import ndimage\nimport sys\n\nimport tensorflow as tf\nfrom tensorflow.keras.regularizers import l2\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.layers import Conv2D, MaxPooling2D\nfrom tensorflow.keras.layers import Dense, Dropout, Flatten, Activation, Input, BatchNormalization, Add, GlobalAveragePooling2D,AveragePooling2D,GlobalMaxPooling2D,concatenate\nfrom tensorflow.keras.layers import Lambda, Reshape, DepthwiseConv2D, ZeroPadding2D, Add, MaxPooling2D,Activation, Flatten, Conv2D, Dense, Input, Dropout, Concatenate, GlobalMaxPooling2D, GlobalAveragePooling2D, BatchNormalization\n\nfrom tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau, ModelCheckpoint,TensorBoard,TerminateOnNaN, LearningRateScheduler\nfrom tensorflow.keras.optimizers import Adam,RMSprop\nfrom tensorflow.keras.models import Model,load_model\n\nfrom sklearn.model_selection import ShuffleSplit\nfrom albumentations import (\n    Compose, HorizontalFlip, CLAHE, HueSaturationValue,\n    RandomBrightness, RandomContrast, RandomGamma,OneOf,\n    ToFloat, ShiftScaleRotate,GridDistortion, ElasticTransform, JpegCompression, HueSaturationValue, VerticalFlip,\n    RGBShift, RandomBrightness, RandomContrast, Blur, MotionBlur, MedianBlur, GaussNoise,CenterCrop,Normalize,\n    IAAAdditiveGaussianNoise,GaussNoise,OpticalDistortion,RandomSizedCrop,RandomCrop,RandomResizedCrop,RandomRotate90,Transpose\n)\n\nimport efficientnet.tfkeras as efn\nfrom iterstrat.ml_stratifiers import MultilabelStratifiedShuffleSplit, MultilabelStratifiedKFold\nfrom classification_models.tfkeras import Classifiers\n# Input data files are available in the \"../input/\" directory.\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input d","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df = pd.read_csv('../input/rsna-intracranial-hemorrhage-detection/rsna-intracranial-hemorrhage-detection/stage_2_train.csv')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_images_path = '../input/rsna-intracranial-hemorrhage-detection/rsna-intracranial-hemorrhage-detection/stage_2_train/'\ntest_images_path = '../input/rsna-intracranial-hemorrhage-detection/rsna-intracranial-hemorrhage-detection/stage_2_test/'\ntrain_files = os.listdir(train_images_path)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"hem_df = pd.read_csv('../input/rsna-intracranial-hemorrhage-detection/rsna-intracranial-hemorrhage-detection/stage_2_train.csv')\nhem_df['sub_type'] = hem_df['ID'].str.split('_',expand = True)[2]\nhem_df['image'] = 'ID_' + hem_df['ID'].str.split('_',expand = True)[1] + '.dcm'\nhem_df = hem_df.pivot_table(index = 'image', columns = 'sub_type')\nhem_df","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def correct_dcm(dcm):\n    x = dcm.pixel_array + 1000\n    px_mode = 4096\n    x[x>=px_mode] = x[x>=px_mode] - px_mode\n    dcm.PixelData = x.tobytes()\n    dcm.RescaleIntercept = -1000\n    \ndef sigmoid_window(img, window_center, window_width, U=1.0, eps=(1.0 / 255.0)):\n    img = window_image(img, window_center, window_width)\n    ue = np.log((U / eps) - 1.0)\n    W = (2 / window_width) * ue\n    b = ((-2 * window_center) / window_width) * ue\n    z = W * img + b\n    img = U / (1 + np.power(np.e, -1.0 * z))\n    img = (img - np.min(img)) / (np.max(img) - np.min(img))\n    return img\n\n\ndef window_image(dcm, window_center, window_width, desired_size):\n    \n    if (dcm.BitsStored == 12) and (dcm.PixelRepresentation == 0) and (int(dcm.RescaleIntercept) > -100):\n        correct_dcm(dcm)\n    \n    img = dcm.pixel_array * dcm.RescaleSlope + dcm.RescaleIntercept\n    img = cv2.resize(img, desired_size[:2], interpolation = cv2.INTER_AREA)  # resize image\n    img_min = window_center - window_width // 2\n    img_max = window_center + window_width // 2\n    img = np.clip(img, img_min, img_max)\n\n    return img\n\ndef bsb_window(dcm, desired_size):\n    brain_img = window_image(dcm, 40, 80, desired_size)\n    subdural_img = window_image(dcm, 80, 200, desired_size)\n    soft_img = window_image(dcm, 40, 380, desired_size)\n    \n    brain_img = (brain_img - 0) / 80\n    subdural_img = (subdural_img - (-20)) / 200\n    soft_img = (soft_img - (-150)) / 380\n    bsb_img = np.array([brain_img, subdural_img, soft_img]).transpose(1,2,0)\n    return bsb_img","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def read_img_val(path, desired_size):\n    dcm = pydicom.dcmread(path)\n    try:\n        img = bsb_window(dcm, desired_size)\n    except:\n        img = np.zeros(desired_size)\n        \n    return img","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class GradCAM:\n\tdef __init__(self, model, classIdx, layerName=None):\n\n\t\tself.model = model\n\t\tself.classIdx = classIdx\n\t\tself.layerName = layerName\n\n\t\t\n\t\tif self.layerName is None:\n\t\t\tself.layerName = self.find_target_layer()\n\n\tdef find_target_layer(self):\n\n\t\tfor layer in reversed(self.model.layers):\n\t\t\tif len(layer.output_shape) == 4:\n\t\t\t\treturn layer.name\n\n\t\n\t\traise ValueError(\"Could not find 4D layer. Cannot apply GradCAM.\")\n\n\tdef compute_heatmap(self, image, eps=1e-8):\n\n\t\tgradModel = Model(\n\t\t\tinputs=[self.model.inputs],\n\t\t\toutputs=[self.model.get_layer(self.layerName).output, \n                     \n\t\t\t\tself.model.output])\n\n\t\twith tf.GradientTape() as tape:\n\t\t\n\t\t\tinputs = tf.cast(image, tf.float32)\n\t\t\t(convOutputs, predictions) = gradModel(inputs)\n\t\t\tloss = predictions[:, self.classIdx]\n\n\t\tgrads = tape.gradient(loss, convOutputs)\n\n\t\tcastConvOutputs = tf.cast(convOutputs > 0, \"float32\")\n\t\tcastGrads = tf.cast(grads > 0, \"float32\")\n\t\tguidedGrads = castConvOutputs * castGrads * grads\n\n\n\t\tconvOutputs = convOutputs[0]\n\t\tguidedGrads = guidedGrads[0]\n\n\t\n\t\tweights = tf.reduce_mean(guidedGrads, axis=(0, 1))\n\t\tcam = tf.reduce_sum(tf.multiply(weights, convOutputs), axis=-1)\n\n\n\t\t(w, h) = (image.shape[2], image.shape[1])\n\t\theatmap = cv2.resize(cam.numpy(), (w, h))\n\n\t\n\t\tnumer = heatmap - np.min(heatmap)\n\t\tdenom = (heatmap.max() - heatmap.min()) + eps\n\t\theatmap = numer / denom\n\t\theatmap = (heatmap * 255).astype(\"uint8\")\n\n\t\treturn heatmap\n\n\tdef overlay_heatmap(self, heatmap, image, alpha=0.5,\n\t\tcolormap=cv2.COLORMAP_JET):\n\n\t\theatmap = cv2.applyColorMap(heatmap, colormap)\n\t\toutput = cv2.addWeighted(image, alpha, heatmap, 1 - alpha, 0)\n\n\t\n\t\treturn (heatmap, output)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def create_model():\n    \n    base_model =  efn.EfficientNetB4(weights = 'imagenet', include_top = False, pooling = 'avg', input_shape = (256,256,3))\n    x = base_model.output\n    x = Dropout(0.15)(x)\n    y_pred = Dense(6, activation = 'sigmoid')(x)\n\n    return Model(inputs = base_model.input, outputs = y_pred)\nmodel = create_model()\nmodel.load_weights('../input/efficientnetb4-hemorrhage/efficientnetb4_model.h5')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# random_integer = random.randint(0,len(hem_df) - 1)\n# random_img = img_ids[-3]\n# image = read_img_val(train_images_path + random_img,(256, 256))\n# label = hem_df.iloc[-3].Label.values","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"hem_df[hem_df.Label.subarachnoid.values == 1].sample(20)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"subdural_img = 'ID_29c9c2ee8.dcm'\t\nintraventricular_img = 'ID_004780f8e.dcm'\nintraparenchymal_img = 'ID_000d69988.dcm'\nsubarachnoid_img = 'ID_00058bb06.dcm'\nepidural_img = 'ID_00f1e66e1.dcm'\nepidural_img2 = 'ID_ff0afaa64.dcm'\nsubdural_img2 = 'ID_47f130bfa.dcm'\t\nsubarachnoid_img2 = 'ID_526b45786.dcm'\n\ntype_list = [subdural_img, intraventricular_img, intraparenchymal_img, subarachnoid_img, epidural_img2]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"img_id = subarachnoid_img2\nimg = hem_df.loc[hem_df.index == img_id].index[0]\nimage = read_img_val(train_images_path + img,(256, 256))\nlabel = hem_df.loc[hem_df.index == img_id].Label.values","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.imshow(image)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class_label = ['any', 'EPH', 'IPH','IVH', 'SAH', 'SDH']","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"preds = model.predict(image[np.newaxis,...])\ni = np.argmax(preds[0])\n\n# decode the ImageNet predictions to obtain the human-readable label\n\n# # initialize our gradient class activation map and build the heatmap\ncam = GradCAM(model, i)\nheatmap = cam.compute_heatmap(image[np.newaxis,...])\n\nimg_copy = np.copy(image)\nimg_copy -= img_copy.min((0,1))\nimg_copy = (255*img_copy).astype(np.uint8)\n# resize the resulting heatmap to the original input image dimensions\n# and then overlay heatmap on top of the image\nheatmap = cv2.resize(heatmap, (image.shape[1], image.shape[0]))\n(heatmap, output) = cam.overlay_heatmap(heatmap, img_copy, alpha=0.5)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(\"Hemorrhage type: {}\".format(class_label))\nprint(\"actual label: {}\".format(label))\nprint(\"predicted label: {}\".format(preds))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.imshow(output)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"img_label_list = []\nfor img_type in type_list:\n    img_id = img_type\n    img = hem_df.loc[hem_df.index == img_id].index[0]\n    image = read_img_val(train_images_path + img,(256, 256))\n    label = hem_df.loc[hem_df.index == img_id].Label.values\n    img_label_list.append((image, label))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\ndef plot_map(img_label_list):\n    fig, axes = plt.subplots(5, 2, figsize=(15, 15))\n    fig.suptitle('Grad-CAM\\nPredicted / Actual / Probability',fontsize=20)\n    \n    for i, img_label in enumerate(img_label_list):\n        img, label = img_label\n        preds = model.predict(img[np.newaxis,...])\n        axes[i,0].imshow(img, cmap = 'bone')\n        axes[i,0].set_xticks([])\n        axes[i,0].set_yticks([])\n        axes[i,0].set_title(f'{class_label[np.argmax(preds[:, 1:]) + 1]} / {class_label[np.argmax(label[:, 1:]) + 1]} / {np.max(preds[:, 1:]):.4f}')\n        heatmap = cam.compute_heatmap(img[np.newaxis,...])\n        img_copy = np.copy(img)\n        img_copy -= img_copy.min((0,1))\n        img_copy = (255*img_copy).astype(np.uint8)\n        # resize the resulting heatmap to the original input image dimensions\n        # and then overlay heatmap on top of the image\n        heatmap = cv2.resize(heatmap, (img_copy.shape[1], img_copy.shape[0]))\n        (heatmap, output) = cam.overlay_heatmap(heatmap, img_copy, alpha=0.5)\n        axes[i,1].imshow(output)\n        axes[i,1].set_xticks([])\n        axes[i,1].set_yticks([])\n        axes[i,1].set_title(\"heatmap showing hemorrhage location\")\n    plt.subplots_adjust(wspace=1, hspace=0.2)\n    plt.savefig('hemorrhageGradCAM.png')\nplot_map(img_label_list)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"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":4,"nbformat_minor":4}