{"cells":[{"metadata":{},"cell_type":"markdown","source":"# Albumentationを用いたData Augmentation  \n\nDataset：  \nhttps://www.kaggle.com/iafoss/256x256-images  \niafoss氏の256クロップ済みデータを用いる。  \n\n実際にPytorchで学習を回すことを意識し、毎回Datasetクラスに載せて読み込む。(但し、いらない部分はひたすら削ってある)  \nなお、今回は可視化が目的のため、Normalizeを行わない。  \n\nAlbumentations Documentation :  \nhttps://albumentations.ai/docs/  \n分からない関数や引数があった場合は、このサイトの検索窓にそのまま入力すれば大体解決します。"},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"import os\nimport pandas as pd\nimport numpy as np\nimport random\nimport cv2\n\nimport matplotlib.pyplot as plt\n%matplotlib inline\n\nimport warnings\nwarnings.filterwarnings('ignore')\n\nfrom pylab import rcParams\nrcParams['figure.figsize'] = 20,10\n\nimport torch\nfrom torch.utils.data import Dataset,DataLoader\nimport albumentations as A","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#iafoss dataset\nTRAIN = '../input/hubmap-256x256/train/'\nMASKS = '../input/hubmap-256x256/masks/'\nLABELS = '../input/hubmap-kidney-segmentation/train.csv'","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Dataset  "},{"metadata":{"trusted":true},"cell_type":"code","source":"class HuBMAPDataset(Dataset):\n    def __init__(self,tfms=None):\n        ids = pd.read_csv(LABELS).id.values\n        self.fnames = [fname for fname in os.listdir(TRAIN) if fname.split('_')[0] in ids]\n        self.tfms = tfms\n        \n    def __len__(self):\n        return len(self.fnames)\n    \n    def __getitem__(self, idx):\n        fname = self.fnames[idx]\n        img = cv2.cvtColor(cv2.imread(os.path.join(TRAIN,fname)), cv2.COLOR_BGR2RGB)\n        mask = cv2.imread(os.path.join(MASKS,fname),cv2.IMREAD_GRAYSCALE)\n        if self.tfms is not None:\n            augmented = self.tfms(image=img,mask=mask)\n            img,mask = augmented['image'],augmented['mask']\n        return img,mask","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#画像表示のための関数\ngood_img_index = [1,5,7,8]\ndef show_images(tfms):\n    dataset_show = HuBMAPDataset(tfms)\n    for i in range(2):\n        f, axarr = plt.subplots(1,4)\n        for p in range(2):\n            idx = i*2+p\n            img, mask = dataset_show[good_img_index[idx]]\n            img = img.astype(np.uint8)\n            axarr[p*2].imshow(img)\n            axarr[p*2+1].imshow(mask)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#transformなし(元画像)\nshow_images(tfms=None)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Resize  \n基本的にはAugmentationの最後に行う。"},{"metadata":{"trusted":true},"cell_type":"code","source":"tfms = A.Compose([\n    A.Resize(512, 512),\n])\n\nshow_images(tfms=tfms)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Flip  "},{"metadata":{"trusted":true},"cell_type":"code","source":"#水平方向\ntfms = A.Compose([\n    A.HorizontalFlip(p=1.), #確か初期値は0.5\n])\n\nshow_images(tfms=tfms)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#垂直方向\ntfms = A.Compose([\n    A.VerticalFlip(p=1.),\n])\n\nshow_images(tfms=tfms)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Rotate"},{"metadata":{"trusted":true},"cell_type":"code","source":"tfms = A.Compose([\n    A.RandomRotate90(p=1.), #0,90,180,270°方向にランダムにRotate\n])\n\nshow_images(tfms=tfms)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Transpose  \n転置。  \n対角成分を基準にして鏡写しに入れ替わる。  "},{"metadata":{"trusted":true},"cell_type":"code","source":"tfms = A.Compose([\n    A.Transpose(p=1.),\n])\n\nshow_images(tfms=tfms)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# アフィン変換(Affine Transform)  \nAlbumentation内では、\"ShiftScaleRotate\"。  \n画像の拡大縮小、回転、平行移動などをまとめて行う。  \n\n参考：  \nhttps://imagingsolution.blog.fc2.com/blog-entry-284.html  "},{"metadata":{"trusted":true},"cell_type":"code","source":"tfms = A.Compose([\n    A.ShiftScaleRotate(shift_limit=0.0625, scale_limit=0.2, rotate_limit=15, p=0.9, \n                         border_mode=cv2.BORDER_REFLECT),\n])\n\nshow_images(tfms=tfms)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#ボーダー(外挿)なし\ntfms = A.Compose([\n    A.ShiftScaleRotate(shift_limit=0.1, scale_limit=0.1, rotate_limit=15, border_mode=0, p=0.85),\n])\n\nshow_images(tfms=tfms)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Brightness  "},{"metadata":{"trusted":true},"cell_type":"code","source":"tfms = A.Compose([\n    A.RandomBrightness(limit=0.2, p=0.75),\n])\n\nshow_images(tfms=tfms)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Contrast  "},{"metadata":{"trusted":true},"cell_type":"code","source":"tfms = A.Compose([\n    A.RandomContrast(limit=0.2, p=0.75),\n])\n\nshow_images(tfms=tfms)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Blur(ぼかし)系"},{"metadata":{"trusted":true},"cell_type":"code","source":"tfms = A.Compose([\n    A.MotionBlur(blur_limit=5),\n])\n\nshow_images(tfms=tfms)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"tfms = A.Compose([\n    A.MedianBlur(blur_limit=5),\n])\n\nshow_images(tfms=tfms)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"tfms = A.Compose([\n    A.GaussianBlur(blur_limit=5),\n])\n\nshow_images(tfms=tfms)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Noise系  "},{"metadata":{"trusted":true},"cell_type":"code","source":"tfms = A.Compose([\n    A.GaussNoise(var_limit=(5.0, 30.0),p=1.),\n])\n\nshow_images(tfms=tfms)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"tfms = A.Compose([\n    A.ISONoise(p=1.),\n])\n\nshow_images(tfms=tfms)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# 歪み系(Distortion)"},{"metadata":{"trusted":true},"cell_type":"code","source":"tfms = A.Compose([\n    A.OpticalDistortion(distort_limit=1.0),\n])\n\nshow_images(tfms=tfms)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"tfms = A.Compose([\n    A.GridDistortion(num_steps=5, distort_limit=1.),\n])\n\nshow_images(tfms=tfms)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"tfms = A.Compose([\n    A.ElasticTransform(alpha=3),\n])\n\nshow_images(tfms=tfms)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# ヒストグラム平坦化(Histogram Flattening)  \n\nhttp://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_imgproc/py_histograms/py_histogram_equalization/py_histogram_equalization.html"},{"metadata":{"trusted":true},"cell_type":"code","source":"tfms = A.Compose([\n    A.CLAHE(clip_limit=4.0, p=0.7),\n])\n\nshow_images(tfms=tfms)\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Cutout  \nAlbumentationsには2種類のカットアウトが実装されており、現在は\"Cutout\"関数ではなく、\"CoarseDropout\"関数を使用することが推奨されている。    \n前者ではマスク画像へのCutoutの適用ができないことに注意。  \nAlbumentations implements two types of Cutouts, and it is now recommended to use the \"CoarseDropout\" function instead of the \"Cutout\" function.      \nNote that the former does not allow you to apply Cutout to a masked image.  "},{"metadata":{"trusted":true},"cell_type":"code","source":"#従来のCutout,現在のバージョンではこの関数を使うことは推奨されていない(DeprecationWarning)\n#セグメント画像にCutoutは適用できない。(今回のコンペではこっちは使わない方が無難である)\n\"\"\"\nConventional Cutout function, in the current version it is not recommended to use this function (DeprecationWarning)\nCutout cannot be applied to mask images.\n\"\"\"\ntfms = A.Compose([\n    A.Cutout(max_h_size=50, max_w_size=50, num_holes=2, p=1.),\n])\n\nshow_images(tfms=tfms)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#そこで、現在推奨されているCutoutは、\"CoarseDropout\"関数で利用できる。\n#引数mask_fill_value=0とすれば、マスク画像にもカットアウトを適用できる。\n\"\"\"\nCutout, which is currently recommended, is available in the \"CoarseDropout\" function.\nIf you set the argument mask_fill_value=0, you can apply the cutout to the masked image as well.\n\"\"\"\ntfms = A.Compose([\n    A.CoarseDropout(max_holes=2,min_holes=1,max_height=50,max_width=50,min_height=20,min_width=20,mask_fill_value=0, p=1.),\n])\n\nshow_images(tfms=tfms)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# HSV色空間\n\nhttps://ja.wikipedia.org/wiki/HSV%E8%89%B2%E7%A9%BA%E9%96%93"},{"metadata":{"trusted":true},"cell_type":"code","source":"tfms = A.Compose([\n    A.HueSaturationValue(hue_shift_limit=10, sat_shift_limit=20, val_shift_limit=10, p=1.),\n])\n\nshow_images(tfms=tfms)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# どれか一つを適用する \"OneOf\"  \n似たような処理でまとめることが多い  "},{"metadata":{"trusted":true},"cell_type":"code","source":"tfms = A.Compose([\n    A.OneOf([\n        A.MotionBlur(blur_limit=5),\n        A.MedianBlur(blur_limit=5),\n        A.GaussianBlur(blur_limit=5),\n        A.GaussNoise(var_limit=(5.0, 30.0)),\n    ], p=0.7),\n])\n\nshow_images(tfms=tfms)\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# すごいやつ  \nMelanomaコンペ1st placeのData Augmentation.(今回のコンペに向いているというわけでは無いので注意)  \n処理にもすごい時間がかかるのでKaggle Notebookでは非現実的…(GPU上でAugmentationできるdaliやkorniaならあるいは…)  \nhttps://www.kaggle.com/haqishen/1st-place-soluiton-code-small-ver  "},{"metadata":{"trusted":true},"cell_type":"code","source":"tfms = A.Compose([\n    A.Transpose(p=0.5),\n    A.VerticalFlip(p=0.5),\n    A.HorizontalFlip(p=0.5),\n    A.RandomBrightness(limit=0.2, p=0.75),\n    A.RandomContrast(limit=0.2, p=0.75),\n    A.OneOf([\n        A.MotionBlur(blur_limit=5),\n        A.MedianBlur(blur_limit=5),\n        A.GaussianBlur(blur_limit=5),\n        A.GaussNoise(var_limit=(5.0, 30.0)),\n    ], p=0.7),\n\n    A.OneOf([\n        A.OpticalDistortion(distort_limit=1.0),\n        A.GridDistortion(num_steps=5, distort_limit=1.),\n        A.ElasticTransform(alpha=3),\n    ], p=0.7),\n\n    A.CLAHE(clip_limit=4.0, p=0.7),\n    A.HueSaturationValue(hue_shift_limit=10, sat_shift_limit=20, val_shift_limit=10, p=0.5),\n    A.ShiftScaleRotate(shift_limit=0.1, scale_limit=0.1, rotate_limit=15, border_mode=0, p=0.85),\n    A.Resize(256, 256),\n    A.Cutout(max_h_size=int(256 * 0.375), max_w_size=int(256 * 0.375), num_holes=1, p=0.7),    \n    #A.Normalize()\n])\n\nshow_images(tfms=tfms)","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}