{"cells":[{"metadata":{},"cell_type":"markdown","source":"# Simple Data Augmentation with ImgAug\nThis notebook is based on a few of the most upvoted notebooks already in the competitions, but I adjusted the code to make data augmentation simple.\n\nLet me know if you have any suggestions or feedback!\n\n**This is my first public kernel, have mercy!**\n"},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"_kg_hide-output":true},"cell_type":"code","source":"!pip install --upgrade imgaug\n\nimport matplotlib.pyplot as plt\nfrom PIL import Image\nimport pandas as pd\nimport numpy as np\nimport random\nimport cv2\nimport os\n        \ndata_path = '/kaggle/input/understanding_cloud_organization'\ntrain_csv_path = os.path.join(data_path,'train.csv')\ntrain_image_path = os.path.join(data_path,'train_images')\ndf = pd.read_csv(train_csv_path)\ndf.head()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"# drop the rows where at least one element is missing. \ndf.dropna(inplace=True)\n\n#  split Image_Label in Image_id and Label\ndf['Image'] = df['Image_Label'].apply(lambda x: x.split('_')[0])\ndf['Label'] = df['Image_Label'].apply(lambda x: x.split('_')[1])\n\n# drop Image_Label column\ndf.drop(columns='Image_Label', inplace=True)\n\ndf.head()","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true,"_kg_hide-output":true},"cell_type":"code","source":"# credit https://www.kaggle.com/ekhtiar/eda-find-me-in-the-clouds\ndef rle2mask(rle_string, height, width):\n    '''\n    convert RLE(run length encoding) string to numpy array\n\n    Parameters: \n    rle_string (str): string of rle encoded mask\n    height (int): height of the mask\n    width (int): width of the mask \n\n    Returns: \n    numpy.array: numpy array of the mask\n    '''\n    \n    rows, cols = height, width\n    \n    rle_numbers = [int(num_string) for num_string in rle_string.split(' ')]\n    rle_pairs = np.array(rle_numbers).reshape(-1,2)\n    img = np.zeros(rows*cols, dtype=np.uint8)\n    for index, length in rle_pairs:\n        index -= 1\n        img[index:index+length] = 255\n    img = img.reshape(cols,rows)\n    img = img.T\n    return img\n\n# credits: https://www.kaggle.com/artgor/segmentation-in-pytorch-using-convenient-tools\ndef mask2rle(img):\n    '''\n    Convert mask to rle.\n    img: numpy array, 1 - mask, 0 - background\n    Returns run length as string formated\n    '''\n    pixels= img.T.flatten()\n    pixels = np.concatenate([[0], pixels, [0]])\n    runs = np.where(pixels[1:] != pixels[:-1])[0] + 1\n    runs[1::2] -= runs[::2]\n    return ' '.join(str(x) for x in runs)\n\n\nfrom imgaug.augmentables.segmaps import SegmentationMapsOnImage\n# credit: https://www.kaggle.com/aleksandradeis/understanding-clouds-eda\ndef create_segmap(row_id):\n    '''\n    Helper function to create a segmentation map for an image by row identifier\n    '''\n    # open the image\n    path = os.path.join(train_image_path, df.loc[row_id, : ]['Image'])\n    image = cv2.imread(path)\n    \n    # get mask\n    mask = get_mask(row_id)\n    \n    # label numpy map with 4 classes\n    segmap = np.zeros((image.shape[0], image.shape[1]), dtype=np.int32)\n    segmap = np.where(mask == 1, 1, segmap)\n    \n    # create a segmantation map\n    segmap = SegmentationMapsOnImage(segmap, shape=image.shape, nb_classes=5)\n    \n    return segmap\n\ndef get_mask(row_id):\n    '''\n    Function to get the mask of a image from a single rle\n    INPUT:\n        row_id - identifier of datagrame\n    RETURNS:\n        np_mask - numpy segmentation map\n    '''\n    path = os.path.join(train_image_path, df.loc[row_id, : ]['Image'])\n    image = cv2.imread(path)\n\n    rle = df['EncodedPixels'].values[0]\n    if rle != '-1':\n        np_mask = rle2mask(rle, np.asarray(image).shape[0], np.asarray(image).shape[1])\n        np_mask = np.clip(np_mask, 0, 1)\n    else:\n        # empty mask\n        np_mask = np.zeros((np.asarray(image).shape[0], np.asarray(image).shape[1]))\n        \n    return np_mask\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true,"_kg_hide-output":true},"cell_type":"code","source":"# Just a simple function to plot 2 images with their respective masks \ndef plt_image(img1, mask1, img2, mask2):\n    fig, (ax1, ax2) = plt.subplots(1, 2,figsize=(30,30))\n\n    ax1.imshow(img1)\n    mask1 = np.ma.masked_where(mask1 == 0, mask1)\n    ax1.imshow(mask1, alpha=0.75)\n\n    ax2.imshow(img2)\n    mask2 = np.ma.masked_where(mask2 == 0, mask2)\n    ax2.imshow(mask2, alpha=0.75)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Data augmentation"},{"metadata":{"trusted":true},"cell_type":"code","source":"import imgaug.augmenters as iaa\nimport imgaug.imgaug\n\ndef augment(image_id, seq):\n    image_path = os.path.join(train_image_path, df['Image'][cloud_img_id])\n    image = cv2.imread(image_path)\n    segmap = create_segmap(cloud_img_id)\n    \n    # apply augmentation for image and mask\n    image_aug, segmap_aug = seq(image=image, segmentation_maps=segmap)\n     \n    mask = segmap_aug.get_arr()\n    augmented_rle = mask2rle(mask)\n\n    return (image_aug, augmented_rle, mask, segmap_aug)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"cloud_img_id = df.sample().index[0] # get a random index\n\nimage_path = os.path.join(train_image_path, df['Image'][cloud_img_id])\nclouds_img = cv2.imread(image_path)\n\n# Define our augmentation pipeline.\n# You can find more augmenters here: https://imgaug.readthedocs.io/en/latest/source/overview_of_augmenters.html\nseq = iaa.Sequential([\n    iaa.Fliplr(0.5),\n    iaa.Crop(percent=(0, 0.1)),\n    iaa.Sometimes(0.5,\n        iaa.GaussianBlur(sigma=(0, 0.5))\n    ),\n    iaa.LinearContrast((0.75, 1.5)),\n    iaa.AdditiveGaussianNoise(loc=0, scale=(0.0, 0.05*255), per_channel=0.5),\n    iaa.Multiply((0.8, 1.2), per_channel=0.2),\n    iaa.Affine(\n        scale={\"x\": (0.8, 1.2), \"y\": (0.8, 1.2)},\n        translate_percent={\"x\": (-0.2, 0.2), \"y\": (-0.2, 0.2)},\n        rotate=(-25, 25),\n        shear=(-8, 8)\n    )\n], random_order=True)\n\n(image_aug, augmented_rle, augmented_mask, augmented_segmap) = augment(cloud_img_id, seq)\n\nplt_image(img1=clouds_img, mask1=get_mask(cloud_img_id), img2=image_aug, mask2=augmented_mask)","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":1}