#!/usr/bin/env python # coding: utf-8 #

Table of Contents

#
# In[1]: import pandas as pd import numpy as np import os import cv2 import random import matplotlib.pyplot as plt import torch from torch.utils.data import Dataset import albumentations # In[2]: # download data: https://www.kaggle.com/c/bengaliai-cv19/data data_dir = '../input/' files_train =[f'train_image_data_{fid}.parquet' for fid in range(4)] print(files_train) # In[3]: F = os.path.join(data_dir, files_train[0]) train0 = pd.read_parquet(F) # In[4]: train0.head() # In[5]: print('Train Image Data{} Shape is : {}'.format(0, train0.shape)) # 데이터가 크기 떄문에, 전체 데이터를 읽을 떄는 parquet으로 읽는것보다 feather형식으로 읽는 것이 30배 정도 더 빠릅니다. # # 하지만 일부의 데이터만 볼 것이기 때문에 parquet으로 읽어서 진행하겠습니다. # # 먼저 augmentation을 진행하기 앞서, Dataset을 만들것입니다. # # 사이즈는 **`137 * 236`** 입니다. # In[6]: class BengaliDataset(Dataset): def __init__(self, df, img_height, img_width): self.df = df self.img_height = img_height self.img_width = img_width def __len__(self): return len(self.df) def __getitem__(self, idx): img = self.df.iloc[idx][0:].values.astype(np.uint8) img = img.reshape(self.img_height, self.img_width) img = 255 - img img = (img*(255.0/img.max())).astype(np.uint8) return img # In[7]: HEIGHT = 137 WIDTH = 236 train0.set_index('image_id', inplace=True) image = BengaliDataset(train0, img_height=HEIGHT, img_width=WIDTH) # # Albumentation Tutorial # ## Original # In[8]: nrow, ncol = 1, 5 fig, axs = plt.subplots(nrow, ncol, figsize=(20, 10)) axs = axs.flatten() for i, ax in enumerate(axs): img = image[i] ax.imshow(img) ax.set_title(f'label: Original') ax.axis('off') plt.tight_layout() # ## Blur # Blur the input image using a random-sized kernel. # # 임의크기의 커널을 사용하여 이미지를 흐리게 만듭니다. # In[9]: import albumentations as A aug = A.Blur(p=0.5) nrow, ncol = 5, 2 fig, axs = plt.subplots(nrow, ncol, figsize=(20, 10)) for n in range(nrow): img = image[n] aug_image = aug(image=img)['image'] axs[n,0].imshow(img) axs[n,0].set_title(f'label: Original') axs[n,0].axis('off') axs[n,1].imshow(aug_image) axs[n,1].set_title(f'label: Blur Image') axs[n,1].axis('off') plt.tight_layout() # ## Noise # Apply gaussian noise to the input image. # # 이미지에 noise를 더하여, 좀 더 robust한 결과를 만들도록 합니다. # In[10]: import albumentations as A aug = A.GaussNoise(var_limit=5. / 255., p=1.0) nrow, ncol = 5, 2 fig, axs = plt.subplots(nrow, ncol, figsize=(20, 10)) for n in range(nrow): img = image[n] aug_image = aug(image=img)['image'] axs[n,0].imshow(img) axs[n,0].set_title(f'label: Original') axs[n,0].axis('off') axs[n,1].imshow(aug_image) axs[n,1].set_title(f'label: Gauss Noise') axs[n,1].axis('off') plt.tight_layout() # ## Cut Out # Course Drop out of the square regions in the image. # # 이미지에서 Dropout을 적용한다고 생각하시면 될 꺼 같습니다. # In[11]: import albumentations as A aug = A.Cutout(num_holes=8, max_h_size=20, max_w_size=20, p=1.0) nrow, ncol = 5, 2 fig, axs = plt.subplots(nrow, ncol, figsize=(20, 10)) for n in range(nrow): img = image[n] aug_image = aug(image=img)['image'] axs[n,0].imshow(img) axs[n,0].set_title(f'label: Original') axs[n,0].axis('off') axs[n,1].imshow(aug_image) axs[n,1].set_title(f'label: Cut Out') axs[n,1].axis('off') plt.tight_layout() # ## Brightness, Contrast # Randomly change brightness and contrast of the input image. # # 이미지의 밝기와 대비를 임의로 변경합니다. # In[12]: import albumentations as A aug = A.RandomBrightnessContrast(p=1.0) nrow, ncol = 5, 2 fig, axs = plt.subplots(nrow, ncol, figsize=(20, 10)) for n in range(nrow): img = image[n] aug_image = aug(image=img)['image'] axs[n,0].imshow(img) axs[n,0].set_title(f'label: Original') axs[n,0].axis('off') axs[n,1].imshow(aug_image) axs[n,1].set_title(f'label: RandomBrightnessContrast') axs[n,1].axis('off') plt.tight_layout() # ## Scale, Rotate # Randomly apply affine transforms: translate, scale and rotate the input # # 이미지의 크기나 회전을 임의로 변형시킵니다. # In[13]: import albumentations as A aug = A.ShiftScaleRotate( shift_limit=0.0625, scale_limit=0.1, rotate_limit=30, p=1.0) nrow, ncol = 5, 2 fig, axs = plt.subplots(nrow, ncol, figsize=(20, 10)) for n in range(nrow): img = image[n] aug_image = aug(image=img)['image'] axs[n,0].imshow(img) axs[n,0].set_title(f'label: Original') axs[n,0].axis('off') axs[n,1].imshow(aug_image) axs[n,1].set_title(f'label: ShiftSclaeRotate') axs[n,1].axis('off') plt.tight_layout() # ## Affine # Place a regular grid of points on the input and randomly move the neighbourhood of these point around via affine transformations. # # 이미지의 격자 내에서 점의 주변을 임의로 이동시킵니다. # In[14]: import albumentations as A aug = A.IAAPiecewiseAffine(p=1.0) nrow, ncol = 5, 2 fig, axs = plt.subplots(nrow, ncol, figsize=(20, 10)) for n in range(nrow): img = image[n] aug_image = aug(image=img)['image'] axs[n,0].imshow(img) axs[n,0].set_title(f'label: Original') axs[n,0].axis('off') axs[n,1].imshow(aug_image) axs[n,1].set_title(f'label: Affine') axs[n,1].axis('off') plt.tight_layout() # # AugMix # Alubumentiation을 기반으로 AugMix가 어떤것인지 알아보겠습니다. # # 먼저 아래의 사진 4장을 보면서, 대략적인 감을 잡으실 수 있을겁니다. # # CutOut - 이미지의 임의의 부분을 제거 # # MixUp - 이미지 간 확률적으로 두 이미지를 섞습니다. # # CutMix - CutOut + MixUp # # AugMix - 위에서 소개한 Augmentation기법들을 섞습니다. # # # CIFAR-10 실험결과, AugMix는 다른 기법들보다 우수하게 성적을 냈다고 합니다. # # Augmix: https://arxiv.org/abs/1912.02781 # # Official implementation: https://github.com/google-research/augmix # In[16]: from albumentations import HorizontalFlip from albumentations.core.transforms_interface import ImageOnlyTransform class AugMix(ImageOnlyTransform): """Augmentations mix to Improve Robustness and Uncertainty. Args: image (np.ndarray): Raw input image of shape (h, w, c) severity (int): Severity of underlying augmentation operators. width (int): Width of augmentation chain depth (int): Depth of augmentation chain. -1 enables stochastic depth uniformly from [1, 3] alpha (float): Probability coefficient for Beta and Dirichlet distributions. augmentations (list of augmentations): Augmentations that need to mix and perform. Targets: image Image types: uint8, float32 Reference: | https://arxiv.org/abs/1912.02781 | https://github.com/google-research/augmix """ def __init__(self, width=2, depth=2, alpha=0.5, augmentations=[HorizontalFlip()], always_apply=False, p=0.5): super(AugMix, self).__init__(always_apply, p) self.width = width self.depth = depth self.alpha = alpha self.augmentations = augmentations self.ws = np.float32(np.random.dirichlet([self.alpha] * self.width)) self.m = np.float32(np.random.beta(self.alpha, self.alpha)) def apply_op(self, image, op): image = op(image=image)["image"] return image def apply(self, img, **params): mix = np.zeros_like(img) for i in range(self.width): image_aug = img.copy() for _ in range(self.depth): op = np.random.choice(self.augmentations) image_aug = self.apply_op(image_aug, op) mix = np.add(mix, self.ws[i] * image_aug, out=mix, casting="unsafe") mixed = (1 - self.m) * img + self.m * mix if img.dtype in ["uint8", "uint16", "uint32", "uint64"]: mixed = np.clip((mixed), 0, 255).astype(np.uint8) return mixed def get_transform_init_args_names(self): return ("width", "depth", "alpha") # In[21]: augs = [A.HorizontalFlip(always_apply=True), A.Blur(always_apply=True), A.ShiftScaleRotate(always_apply=True), A.GaussNoise(always_apply=True), A.Cutout(always_apply=True), A.IAAPiecewiseAffine(always_apply=True)] transforms_train = albumentations.Compose([ AugMix(width=3, depth=2, alpha=.4, p=1., augmentations=augs), ]) # In[22]: class Aug_BengaliDataset(Dataset): def __init__(self, df, img_height, img_width, transform=None): self.df = df self.img_height = img_height self.img_width = img_width self.transform = transform def __len__(self): return len(self.df) def __getitem__(self, idx): img = self.df.iloc[idx][0:].values.astype(np.uint8) img = img.reshape(self.img_height, self.img_width) img = 255 - img img = (img*(255.0/img.max())).astype(np.uint8) if self.transform is not None: res = self.transform(image=img) img = res['image'] else: img = img return img # In[23]: aug_image = Aug_BengaliDataset(train0, img_height=HEIGHT, img_width=WIDTH, transform=transforms_train) # In[24]: nrow, ncol = 5, 2 fig, axs = plt.subplots(nrow, ncol, figsize=(15, 10)) for n in range(nrow): img = image[n] aug_img = aug_image[n] axs[n,0].imshow(img) axs[n,0].set_title(f'label: Original') axs[n,0].axis('off') axs[n,1].imshow(aug_img) axs[n,1].set_title(f'label: Augmix') axs[n,1].axis('off') plt.tight_layout() plt.show()