{"cells":[{"metadata":{},"cell_type":"markdown","source":"# VinBigData Chest X-ray Abnormalities Detection"},{"metadata":{},"cell_type":"markdown","source":"![](https://static.theprint.in/wp-content/uploads/2020/03/qureai-696x392.jpg)"},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"from datetime import datetime\ndt_string = datetime.now().strftime(\"%d/%m/%Y %H:%M:%S\")\nprint(f\"Updated {dt_string} (GMT)\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Prepare the data analysis\n## Load packages"},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"import pandas as pd \nimport numpy as np\nimport matplotlib\nimport matplotlib.pyplot as plt\nfrom tqdm import tqdm_notebook\nfrom matplotlib.patches import Rectangle\nimport seaborn as sns\nimport pydicom as dcm\n%matplotlib inline \nIS_LOCAL = False\nimport os \nimport sys\nimport random\nimport math\nimport numpy as np\nimport cv2\nimport matplotlib.pyplot as plt\nimport json\nimport pydicom\nfrom imgaug import augmenters as iaa\nfrom tqdm import tqdm\nimport pandas as pd \nimport glob\nfrom sklearn.model_selection import KFold\nfrom pydicom.pixel_data_handlers.util import apply_voi_lut","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"DATA_DIR = '/kaggle/input/vinbigdata-chest-xray-abnormalities-detection'\n\n# Directory to save logs and trained model\nROOT_DIR = '/kaggle/working'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!git clone https://www.github.com/matterport/Mask_RCNN.git\nos.chdir('Mask_RCNN')\n#!python setup.py -q install","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Import Mask RCNN\nsys.path.append(os.path.join(ROOT_DIR, 'Mask_RCNN'))  # To find local version of the library\nfrom mrcnn.config import Config\nfrom mrcnn import utils\nimport mrcnn.model as modellib\nfrom mrcnn import visualize\nfrom mrcnn.model import log","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_dicom_dir = os.path.join(DATA_DIR, 'train')\ntest_dicom_dir = os.path.join(DATA_DIR, 'test')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!wget --quiet https://github.com/matterport/Mask_RCNN/releases/download/v2.0/mask_rcnn_coco.h5\n!ls -lh mask_rcnn_coco.h5\n\nCOCO_WEIGHTS_PATH = \"mask_rcnn_coco.h5\"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_dicom_fps(dicom_dir):\n    dicom_fps = glob.glob(dicom_dir+'/'+'*.dicom')\n    return list(set(dicom_fps))\n\ndef parse_dataset(dicom_dir, anns): \n    image_fps = get_dicom_fps(dicom_dir)\n    image_annotations = {fp: [] for fp in image_fps}\n    for index, row in anns.iterrows(): \n        if dicom_dir+'/'+row['image_id']+'.dicom' in image_fps:\n            fp = os.path.join(dicom_dir, row['image_id']+'.dicom')\n            image_annotations[fp].append(row)\n        else: continue\n    return image_fps, image_annotations ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# The following parameters have been selected to reduce running time for demonstration purposes \n# These are not optimal \n\nclass DetectorConfig(Config):\n    \"\"\"Configuration for training Chest X-ray Abnormalities dataset.\n    Overrides values in the base Config class.\n    \"\"\"\n    \n    # Give the configuration a recognizable name  \n    NAME = 'Abnormalities'\n    \n    # Train on 1 GPU and 8 images per GPU. We can put multiple images on each\n    # GPU because the images are small. Batch size is 8 (GPUs * images/GPU).\n    GPU_COUNT = 1\n    IMAGES_PER_GPU = 8\n    \n    BACKBONE = 'resnet50'\n    \n    NUM_CLASSES = 2  # background + 1 pneumonia classes\n    \n    IMAGE_MIN_DIM = 256\n    IMAGE_MAX_DIM = 256\n    RPN_ANCHOR_SCALES = (16, 32, 64, 128)\n    TRAIN_ROIS_PER_IMAGE = 32\n    MAX_GT_INSTANCES = 4\n    DETECTION_MAX_INSTANCES = 3\n    DETECTION_MIN_CONFIDENCE = 0.78  ## match target distribution\n    DETECTION_NMS_THRESHOLD = 0.01\n\n    STEPS_PER_EPOCH = 200\n\nconfig = DetectorConfig()\nconfig.display()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class DetectorDataset(utils.Dataset):\n    \"\"\"Dataset class for training Chest X-ray Abnormalities dataset.\n    \"\"\"\n\n    def __init__(self, image_fps, image_annotations, orig_height, orig_width):\n        super().__init__(self)\n        \n        # Add classes\n        self.add_class(\"Abnormalities\", 0, \"Aortic enlargement\")\n        self.add_class(\"Abnormalities\", 1, \"Atelectasis\")\n        self.add_class(\"Abnormalities\", 2, \"Calcification\")\n        self.add_class(\"Abnormalities\", 3, \"Cardiomegaly\")\n        self.add_class(\"Abnormalities\", 4, \"Consolidation\")\n        self.add_class(\"Abnormalities\", 5, \"ILD\")\n        self.add_class(\"Abnormalities\", 6, \"Infiltration\")\n        self.add_class(\"Abnormalities\", 7, \"Lung Opacity\")\n        self.add_class(\"Abnormalities\", 8, \"Nodule/Mass\")\n        self.add_class(\"Abnormalities\", 9, \"Other lesion\")\n        self.add_class(\"Abnormalities\", 10, \"Pleural effusion\")\n        self.add_class(\"Abnormalities\", 11, \"Pleural thickening\")\n        self.add_class(\"Abnormalities\", 12, \"Pneumothorax\")\n        self.add_class(\"Abnormalities\", 13, \"Pulmonary fibrosis\")\n        self.add_class(\"Abnormalities\", 14, \"No finding\")\n        # add images \n        for i, fp in enumerate(image_fps):\n            annotations = image_annotations[fp]\n            self.add_image('Abnormalities', image_id=i, path=fp, \n                           annotations=annotations, orig_height=orig_height, orig_width=orig_width)\n            \n    def image_reference(self, image_id):\n        info = self.image_info[image_id]\n        return info['path']\n\n    def load_image(self, image_id):\n        info = self.image_info[image_id]\n        fp = info['path']\n        ds = pydicom.read_file(fp)\n        image = ds.pixel_array\n        # If grayscale. Convert to RGB for consistency.\n        if len(image.shape) != 3 or image.shape[2] != 3:\n            image = np.stack((image,) * 3, -1)\n        return image\n\n    def load_mask(self, image_id):\n        info = self.image_info[image_id]\n        annotations = info['annotations']\n        count = len(annotations)\n        if count == 0:\n            mask = np.zeros((info['orig_height'], info['orig_width'], 1), dtype=np.uint8)\n            class_ids = np.zeros((1,), dtype=np.int32)\n        else:\n            mask = np.zeros((info['orig_height'], info['orig_width'], count), dtype=np.uint8)\n            class_ids = np.zeros((count,), dtype=np.int32)\n            for i, a in enumerate(annotations):\n                if a['class_id'] == 0:\n                    x = int(a['x_min'])\n                    y = int(a['y_min'])\n                    w = int(a['x_max'])\n                    h = int(a['y_max'])\n                    mask_instance = mask[:, :, i].copy()\n                    cv2.rectangle(mask_instance, (x, y), (x+w, y+h), 255, -1)\n                    mask[:, :, i] = mask_instance\n                    class_ids[i] = 1\n        return mask.astype(np.bool), class_ids.astype(np.int32)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train = pd.read_csv('/kaggle/input/vinbigdata-chest-xray-abnormalities-detection/train.csv')\ntrain = train[train['class_name']!='No finding']\ntrain.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def missing_data(data):\n    total = data.isnull().sum().sort_values(ascending = False)\n    percent = (data.isnull().sum()/data.isnull().count()*100).sort_values(ascending = False)\n    return np.transpose(pd.concat([total, percent], axis=1, keys=['Total', 'Percent']))\nmissing_data(train)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"f, ax = plt.subplots(1,1, figsize=(10,8))\ntotal = float(len(train))\nsns.countplot(train['class_name'],order = train['class_name'].value_counts().index, palette='Set3')\nfor p in ax.patches:\n    height = p.get_height()\n    ax.text(p.get_x()+p.get_width()/2.,\n            height + 3,\n            '{:1.2f}%'.format(100*height/total),\n            ha=\"center\") \nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Let's look into more details to the classes."},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_feature_distribution(data, feature):\n    # Get the count for each label\n    label_counts = data[feature].value_counts()\n\n    # Get total number of samples\n    total_samples = len(data)\n\n    # Count the number of items in each class\n    print(\"Feature: {}\".format(feature))\n    for i in range(len(label_counts)):\n        label = label_counts.index[i]\n        count = label_counts.values[i]\n        percent = int((count / total_samples) * 10000) / 100\n        print(\"{:<30s}:   {} or {}%\".format(label, count, percent))\n\nget_feature_distribution(train, 'class_name')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Detected Chest Opacity window\n### For the class Chest Opacity, corresponding to class Aortic enlargement, we plot the density of y_max, x_max, y_min and x_min"},{"metadata":{"trusted":true},"cell_type":"code","source":"target1 = train[train['class_name']=='Aortic enlargement']\nsns.set_style('whitegrid')\nplt.figure()\nfig, ax = plt.subplots(2,2,figsize=(12,12))\nsns.distplot(target1['x_max'],kde=True,bins=50, color=\"red\", ax=ax[0,0])\nsns.distplot(target1['y_max'],kde=True,bins=50, color=\"blue\", ax=ax[0,1])\nsns.distplot(target1['x_min'],kde=True,bins=50, color=\"green\", ax=ax[1,0])\nsns.distplot(target1['y_min'],kde=True,bins=50, color=\"magenta\", ax=ax[1,1])\nlocs, labels = plt.xticks()\nplt.tick_params(axis='both', which='major', labelsize=12)\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## The centers of the rectangles like points"},{"metadata":{"trusted":true},"cell_type":"code","source":"fig, ax = plt.subplots(1,1,figsize=(7,7))\ntarget_sample = target1\ntarget_sample['xc'] = target_sample['y_min'] + target_sample['y_max'] / 2\ntarget_sample['yc'] = target_sample['x_min'] + target_sample['x_max'] / 2\nplt.title(\"Centers of Chest Opacity rectangles (brown) over rectangles (yellow)\")\ntarget_sample.plot.scatter(x='xc', y='yc', xlim=(0,1024), ylim=(0,1024), ax=ax, alpha=0.2, marker=\".\", color=\"brown\")\nfor i, crt_sample in target_sample.iterrows():\n    ax.add_patch(Rectangle(xy=(crt_sample['x_min'], crt_sample['y_min']),\n                width=crt_sample['x_max'],height=crt_sample['y_max'],alpha=3.5e-3, color=\"yellow\"))\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Explore DICOM data\n#### Let's read now the DICOM data in the train set. The image path is as following:"},{"metadata":{"trusted":true},"cell_type":"code","source":"image_sample_path = os.listdir('/kaggle/input/vinbigdata-chest-xray-abnormalities-detection/train')[:5]\nprint(image_sample_path)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"The files names are the patients IDs.\n\nLet's check how many images are in the train and test folders."},{"metadata":{"trusted":true},"cell_type":"code","source":"image_train_path = os.listdir('/kaggle/input/vinbigdata-chest-xray-abnormalities-detection/train')\nimage_test_path = os.listdir('/kaggle/input/vinbigdata-chest-xray-abnormalities-detection/test')\nprint(\"Number of images in train set:\", len(image_train_path),\"\\nNumber of images in test set:\", len(image_test_path))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Only a reduced number of images are present in the training set (15000), compared with the number of images in the train_df data (67914).\n\n### It might be that we do have duplicated entries in the train and class datasets. Let's check this.\n\n### Check duplicates in train dataset"},{"metadata":{"trusted":true},"cell_type":"code","source":"print(\"Unique image_id in  train: \", train['image_id'].nunique()) ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"tmp = train.groupby(['image_id','class_name'])['image_id'].count()\ndf = pd.DataFrame(data={'Exams': tmp.values}, index=tmp.index).reset_index()\ntmp = df.groupby(['Exams','class_name']).count()\ndf2 = pd.DataFrame(data=tmp.values, index=tmp.index).reset_index()\ndf2.columns = ['Exams', 'class_name', 'Entries']\ndf2","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fig, ax = plt.subplots(nrows=1,figsize=(12,6))\nsns.barplot(ax=ax,x = 'class_name', y='Entries', hue='Exams',data=df2, palette='Set2')\nplt.title(\"Chest exams class and class_name\")\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"dicom_file_dataset = dcm.read_file('/kaggle/input/vinbigdata-chest-xray-abnormalities-detection/train/000434271f63a053c4128a0ba6352c7f.dicom')\ndicom_file_dataset","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def show_dicom_images(data):\n    img_data = data\n    f, ax = plt.subplots(3,3, figsize=(16,18))\n    for i,data_row in enumerate(img_data):\n        imagePath = data_row\n        data_row_img_data = dcm.read_file(imagePath)\n        data_row_img = dcm.dcmread(imagePath)\n        ax[i//3, i%3].imshow(data_row_img.pixel_array, cmap=plt.cm.bone) \n        ax[i//3, i%3].axis('off')\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"data = ['/kaggle/input/vinbigdata-chest-xray-abnormalities-detection/train/000434271f63a053c4128a0ba6352c7f.dicom',\n       '/kaggle/input/vinbigdata-chest-xray-abnormalities-detection/train/00053190460d56c53cc3e57321387478.dicom',\n       '/kaggle/input/vinbigdata-chest-xray-abnormalities-detection/train/0005e8e3701dfb1dd93d53e2ff537b6e.dicom',\n       '/kaggle/input/vinbigdata-chest-xray-abnormalities-detection/train/0006e0a85696f6bb578e84fafa9a5607.dicom',\n       '/kaggle/input/vinbigdata-chest-xray-abnormalities-detection/train/0007d316f756b3fa0baea2ff514ce945.dicom',\n       '/kaggle/input/vinbigdata-chest-xray-abnormalities-detection/train/000ae00eb3942d27e0b97903dd563a6e.dicom',\n       '/kaggle/input/vinbigdata-chest-xray-abnormalities-detection/train/000d68e42b71d3eac10ccc077aba07c1.dicom',\n       '/kaggle/input/vinbigdata-chest-xray-abnormalities-detection/train/00150343289f317a0ad5629d5b7d9ef9.dicom',\n       '/kaggle/input/vinbigdata-chest-xray-abnormalities-detection/train/00176f7e1b1cb835123f95960b9a9efd.dicom']","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"show_dicom_images(data)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Plot bounding box"},{"metadata":{"trusted":true},"cell_type":"code","source":"def dicom2array(path, voi_lut=True, fix_monochrome=True):\n    dicom = pydicom.read_file(path)\n    # VOI LUT (if available by DICOM device) is used to transform raw DICOM data to \"human-friendly\" view\n    if voi_lut:\n        data = apply_voi_lut(dicom.pixel_array, dicom)\n    else:\n        data = dicom.pixel_array\n    # depending on this value, X-ray may look inverted - fix that:\n    if fix_monochrome and dicom.PhotometricInterpretation == \"MONOCHROME1\":\n        data = np.amax(data) - data\n    data = data - np.min(data)\n    data = data / np.max(data)\n    data = (data * 255).astype(np.uint8)\n    return data\n        \n    \ndef plot_img(img, size=(7, 7), is_rgb=True, title=\"\", cmap='gray'):\n    plt.figure(figsize=size)\n    plt.imshow(img, cmap=cmap)\n    plt.suptitle(title)\n    plt.show()\n\n\ndef plot_imgs(imgs, cols=4, size=7, is_rgb=True, title=\"\", cmap='gray', img_size=(500,500)):\n    rows = len(imgs)//cols + 1\n    fig = plt.figure(figsize=(cols*size, rows*size))\n    for i, img in enumerate(imgs):\n        if img_size is not None:\n            img = cv2.resize(img, img_size)\n        fig.add_subplot(rows, cols, i+1)\n        plt.imshow(img, cmap=cmap)\n    plt.suptitle(title)\n    plt.show()\n    \ndef draw_bboxes(img, boxes, thickness=10, color=(255, 0, 0), img_size=(500,500)):\n    img_copy = img.copy()\n    if len(img_copy.shape) == 2:\n        img_copy = np.stack([img_copy, img_copy, img_copy], axis=-1)\n    for box in boxes:\n        img_copy = cv2.rectangle(\n            img_copy,\n            (int(box[0]), int(box[1])),\n            (int(box[2]), int(box[3])),\n            color, thickness)\n    if img_size is not None:\n        img_copy = cv2.resize(img_copy, img_size)\n    return img_copy","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import random\nfrom random import randint\n\nimgs = []\nimg_ids = train['image_id'].values\nclass_ids = train['class_id'].unique()\n\n# map label_id to specify color\nlabel2color = {class_id:[randint(0,255) for i in range(3)] for class_id in class_ids}\nthickness = 3\nscale = 5\n\n\nfor i in range(8):\n    img_id = random.choice(img_ids)\n    img_path = f'{train_dicom_dir}/{img_id}.dicom'\n    img = dicom2array(path=img_path)\n    img = cv2.resize(img, None, fx=1/scale, fy=1/scale)\n    img = np.stack([img, img, img], axis=-1)\n    \n    boxes = train.loc[train['image_id'] == img_id, ['x_min', 'y_min', 'x_max', 'y_max']].values/scale\n    labels = train.loc[train['image_id'] == img_id, ['class_id']].values.squeeze()\n    \n    for label_id, box in zip(labels, boxes):\n        color = label2color[label_id]\n        img = cv2.rectangle(\n            img,\n            (int(box[0]), int(box[1])),\n            (int(box[2]), int(box[3])),\n            color, thickness\n    )\n    img = cv2.resize(img, (500,500))\n    imgs.append(img)\n    \nplot_imgs(imgs, cmap=None)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# training dataset\nfeatures = ['image_id' ,'class_id', 'rad_id', 'x_min', 'y_min', 'x_max', 'y_max']\nanns = pd.read_csv('/kaggle/input/vinbigdata-chest-xray-abnormalities-detection/train.csv')\nanns = anns[features]\nanns.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"image_fps, image_annotations = parse_dataset(train_dicom_dir, anns=anns)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"ds = pydicom.read_file(image_fps[0]) # read dicom image from filepath \nimage = ds.pixel_array # get image array","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# show dicom fields \nds","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Original DICOM image size: 3072 x 2540\nWIDTH_SIZE = 3072\nHIGH_SIZE = 2540","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"image_fps_list = list(image_fps)\nrandom.seed(42)\nrandom.shuffle(image_fps_list)\nval_size = 1500\nimage_fps_val = image_fps_list[:val_size]\nimage_fps_train = image_fps_list[val_size:]\n\nprint(len(image_fps_train), len(image_fps_val))\n# print(image_fps_val[:6])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# prepare the training dataset\ndataset_train = DetectorDataset(image_fps_train, image_annotations, WIDTH_SIZE, HIGH_SIZE)\ndataset_train.prepare()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Show annotation(s) for a DICOM image \ntest_fp = random.choice(image_fps_train)\nimage_annotations[test_fp]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# prepare the validation dataset\ndataset_val = DetectorDataset(image_fps_val, image_annotations, WIDTH_SIZE, HIGH_SIZE)\ndataset_val.prepare()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Load and display random sample and their bounding boxes\n\nclass_ids = [0]\nwhile class_ids[0] == 0:  ## look for a mask\n    image_id = random.choice(dataset_train.image_ids)\n    image_fp = dataset_train.image_reference(image_id)\n    image = dataset_train.load_image(image_id)\n    mask, class_ids = dataset_train.load_mask(image_id)\n\nprint(image.shape)\n\nplt.figure(figsize=(10, 10))\nplt.subplot(1, 2, 1)\nplt.imshow(image)\nplt.axis('off')\n\nplt.subplot(1, 2, 2)\nmasked = np.zeros(image.shape[:2])\nfor i in range(mask.shape[2]):\n    masked += image[:, :, 0] * mask[:, :, i]\nplt.imshow(masked, cmap='gray')\nplt.axis('off')\n\nprint(image_fp)\nprint(class_ids)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Image augmentation (light but constant)\naugmentation = iaa.Sequential([\n    iaa.OneOf([ ## geometric transform\n        iaa.Affine(\n            scale={\"x\": (0.98, 1.02), \"y\": (0.98, 1.04)},\n            translate_percent={\"x\": (-0.02, 0.02), \"y\": (-0.04, 0.04)},\n            rotate=(-2, 2),\n            shear=(-1, 1),\n        ),\n        iaa.PiecewiseAffine(scale=(0.001, 0.025)),\n    ]),\n    iaa.OneOf([ ## brightness or contrast\n        iaa.Multiply((0.9, 1.1)),\n        iaa.ContrastNormalization((0.9, 1.1)),\n    ]),\n    iaa.OneOf([ ## blur or sharpen\n        iaa.GaussianBlur(sigma=(0.0, 0.1)),\n        iaa.Sharpen(alpha=(0.0, 0.1)),\n    ]),\n])\n\n# test on the same image as above\nimggrid = augmentation.draw_grid(image[:, :, 0], cols=5, rows=2)\nplt.figure(figsize=(30, 12))\n_ = plt.imshow(imggrid[:, :, 0], cmap='gray')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Reference: [Notebook 1](https://www.kaggle.com/gpreda/rsna-pneumonia-detection-eda)\n[Notebook 2](https://www.kaggle.com/hmendonca/mask-rcnn-and-medical-transfer-learning-siim-acr)"}],"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}