{"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_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"## 🚩 필요한 Libray Import","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport os\nimport random\nimport pandas as pd\nimport tensorflow as tf\nimport tensorflow_addons as tfa\nimport seaborn as sns\n\nfrom PIL import Image\nfrom matplotlib import pyplot as plt\nfrom sklearn.model_selection import StratifiedKFold\n\nfrom tensorflow.keras.preprocessing.image import load_img,img_to_array","metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","papermill":{"duration":8.09922,"end_time":"2022-05-03T03:04:07.871269","exception":false,"start_time":"2022-05-03T03:03:59.772049","status":"completed"},"tags":[],"pycharm":{"name":"#%%\n"},"execution":{"iopub.status.busy":"2022-06-06T12:38:44.886111Z","iopub.execute_input":"2022-06-06T12:38:44.886383Z","iopub.status.idle":"2022-06-06T12:38:44.891892Z","shell.execute_reply.started":"2022-06-06T12:38:44.886355Z","shell.execute_reply":"2022-06-06T12:38:44.891029Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 🚩 Train Data Load","metadata":{}},{"cell_type":"code","source":"train_data_path = '../input/sorghum-id-fgvc-9/train_cultivar_mapping.csv'\ntrain_data = pd.read_csv(train_data_path)\n\ntrain_data","metadata":{"papermill":{"duration":0.098258,"end_time":"2022-05-03T03:04:07.994426","exception":false,"start_time":"2022-05-03T03:04:07.896168","status":"completed"},"tags":[],"pycharm":{"name":"#%%\n"},"execution":{"iopub.status.busy":"2022-06-06T14:42:38.758465Z","iopub.execute_input":"2022-06-06T14:42:38.758784Z","iopub.status.idle":"2022-06-06T14:42:38.795994Z","shell.execute_reply.started":"2022-06-06T14:42:38.758750Z","shell.execute_reply":"2022-06-06T14:42:38.795226Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 🚩 각 class 별 Data 개수 확인 & Data 양 분포 확인","metadata":{}},{"cell_type":"code","source":"pd.value_counts(train_data['cultivar'])","metadata":{"papermill":{"duration":0.047155,"end_time":"2022-05-03T03:04:08.067231","exception":false,"start_time":"2022-05-03T03:04:08.020076","status":"completed"},"tags":[],"pycharm":{"name":"#%%\n"},"execution":{"iopub.status.busy":"2022-06-06T12:36:22.134336Z","iopub.execute_input":"2022-06-06T12:36:22.135093Z","iopub.status.idle":"2022-06-06T12:36:22.144267Z","shell.execute_reply.started":"2022-06-06T12:36:22.135059Z","shell.execute_reply":"2022-06-06T12:36:22.143354Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=[24, 6], dpi=200)\nsns.countplot(x=train_data['cultivar'])\nplt.xticks(rotation=60)\nplt.show()","metadata":{"papermill":{"duration":1.734237,"end_time":"2022-05-03T03:04:09.828024","exception":false,"start_time":"2022-05-03T03:04:08.093787","status":"completed"},"tags":[],"pycharm":{"name":"#%%\n"},"execution":{"iopub.status.busy":"2022-06-06T12:36:27.012081Z","iopub.execute_input":"2022-06-06T12:36:27.012555Z","iopub.status.idle":"2022-06-06T12:36:28.634384Z","shell.execute_reply.started":"2022-06-06T12:36:27.012524Z","shell.execute_reply":"2022-06-06T12:36:28.633773Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 🚩 CLAHE\n----\n* **Color Image 기준 -> R,G,B**\n* **CLAHE란, 이미지를 일정한 크기를 가진 작은 블록으로 구분하고, 블록별로 히스토그램 균일화를 시행하여 이미지 전체에 적용**\n* **cv.createCLAHE() 함수를 적용하여 Limit를 적용하여 히스토그램 균일화 진행**","metadata":{}},{"cell_type":"markdown","source":"### ➿ 원본 이미지 히스토 그램 확인","metadata":{}},{"cell_type":"code","source":"dir = '../input/sorghum-cultivar-identification-512512/train'\n\nfor fname in train_data['image'][:3]:\n    image  = load_img(os.path.join(dir, fname))\n    grayscale = load_img(os.path.join(dir, fname),color_mode = \"grayscale\")\n    gray_array=  img_to_array(grayscale)\n    image_array = img_to_array(image)\n\n    plt.imshow(image)\n    fig, (ax1, ax2, ax3, ax4) = plt.subplots(nrows=1,ncols=4, sharey=True, figsize=(24,5))\n\n    ax1.hist(image_array[:,:,0].ravel(),256,[0,256],color='red')\n    plt.ylim(0,20000)\n    ax2.hist(image_array[:,:,1].ravel(),256,[0,256], color='green')\n    ax3.hist(image_array[:,:,1].ravel(),256,[0,256], color='blue')\n    ax4.hist(gray_array.ravel(),256,[0,256])\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2022-06-06T14:33:39.828460Z","iopub.execute_input":"2022-06-06T14:33:39.829079Z","iopub.status.idle":"2022-06-06T14:33:47.152081Z","shell.execute_reply.started":"2022-06-06T14:33:39.829039Z","shell.execute_reply":"2022-06-06T14:33:47.151048Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### ➿ 원본 이미지에 CLAHE 적용","metadata":{}},{"cell_type":"code","source":"import cv2 as cv\nfrom PIL import Image as Img\n\nfor fname in train_data['image'][:3]:\n    image = load_img(os.path.join(dir, fname))\n    clahe = cv.createCLAHE(clipLimit=40, tileGridSize=(10,10))\n    t = np.asarray(image)\n    t = cv.cvtColor(t, cv.COLOR_BGR2HSV)\n    t[:,:,-1] = clahe.apply(t[:,:,-1])\n    t = cv.cvtColor(t, cv.COLOR_HSV2BGR)\n    t = Img.fromarray(t)\n\n    plt.imshow(t)\n    fig, (ax1, ax2, ax3, ax4) = plt.subplots(nrows=1,ncols=4, sharey=True, figsize=(24,5))\n\n    ax1.hist(image_array[:,:,0].ravel(),256,[0,256],color='red')\n    plt.ylim(0,20000)\n    ax2.hist(image_array[:,:,1].ravel(),256,[0,256], color='green')\n    ax3.hist(image_array[:,:,1].ravel(),256,[0,256], color='blue')\n    ax4.hist(gray_array.ravel(),256,[0,256])\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2022-06-06T14:36:55.615994Z","iopub.execute_input":"2022-06-06T14:36:55.616290Z","iopub.status.idle":"2022-06-06T14:37:02.262896Z","shell.execute_reply.started":"2022-06-06T14:36:55.616259Z","shell.execute_reply":"2022-06-06T14:37:02.262064Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 🚩 이미지를 원하는 크기로 자르거나 늘림\n----\n* **zoom 수행 -> 입력 : 이미지, 이미지 변형을 원하는 범위**\n* **이미지 확대, 축소 2가지 이미지 변형 수행**\n* **.resize_with_crop_or_pad() 함수 사용하여 target 이미지 크기를 0으로 채움**","metadata":{}},{"cell_type":"code","source":"def random_zoom(image, zoom_range):\n    # 난수 생성\n    factor = np.random.uniform(low =- zoom_range, high = zoom_range)\n    \n    # int형이 아닌 경우 image를 array로 변형\n    if not isinstance(image, np.ndarray):\n        arr = tf.keras.utils.img_to_array(image)\n\n        tf.image.resize_with_crop_or_pad(tf.image.resize(arr,\n                                                         (int(arr.shape[0] + arr.shape[0] * factor),\n                                                          int(arr.shape[1] + arr.shape[1] * factor))),\n                                         target_height=512,\n                                         target_width=512)\n\n    return tf.image.resize_with_crop_or_pad(tf.image.resize(image,\n                                                            (int(image.shape[0] + image.shape[0] * factor),\n                                                             int(image.shape[1] + image.shape[1] * factor))),\n                                            target_height=512,\n                                            target_width=512)","metadata":{"papermill":{"duration":0.04264,"end_time":"2022-05-03T03:04:09.901362","exception":false,"start_time":"2022-05-03T03:04:09.858722","status":"completed"},"tags":[],"pycharm":{"name":"#%%\n"},"execution":{"iopub.status.busy":"2022-06-06T12:36:39.005401Z","iopub.execute_input":"2022-06-06T12:36:39.006351Z","iopub.status.idle":"2022-06-06T12:36:39.013539Z","shell.execute_reply.started":"2022-06-06T12:36:39.006311Z","shell.execute_reply":"2022-06-06T12:36:39.012748Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, axes = plt.subplots(nrows=1, ncols=3, figsize=[12, 6], dpi=300)\n\nfor i in range(3):\n    zoomed_img = random_zoom(tf.keras.utils.img_to_array(Image.open(os.path.join(dir, train_data['image'][0]))), 0.5)\n    axes[i].imshow(tf.keras.utils.array_to_img(zoomed_img))\n\nplt.show()","metadata":{"papermill":{"duration":2.827644,"end_time":"2022-05-03T03:04:12.828751","exception":false,"start_time":"2022-05-03T03:04:10.001107","status":"completed"},"tags":[],"pycharm":{"name":"#%%\n"},"execution":{"iopub.status.busy":"2022-06-06T12:56:05.445639Z","iopub.execute_input":"2022-06-06T12:56:05.446756Z","iopub.status.idle":"2022-06-06T12:56:07.367128Z","shell.execute_reply.started":"2022-06-06T12:56:05.446715Z","shell.execute_reply":"2022-06-06T12:56:07.365918Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 🚩 이미지를 원하는 각도 만큼 회전\n----\n* **rotation 수행 -> 입력 : 이미지, 원하는 회전 각도 범위**\n* **.image.rotate() 함수 사용하여 radian 단위로 시계 반대 방향으로 회전**\n* **.fill_mode='nearest'를 이용하여 경계는 가장 가까운 픽셀만큼 확장**","metadata":{}},{"cell_type":"code","source":"def random_rotate(image, rotation_range):\n    factor = np.random.uniform(low = -rotation_range, high = rotation_range)\n\n    if not isinstance(image, np.ndarray):\n        arr = tf.keras.utils.img_to_array(image)\n\n        return tfa.image.rotate(arr, angles=factor, fill_mode='nearest')\n\n    else:\n        return tfa.image.rotate(image, angles=factor, fill_mode='nearest')\n","metadata":{"papermill":{"duration":0.039148,"end_time":"2022-05-03T03:04:09.97095","exception":false,"start_time":"2022-05-03T03:04:09.931802","status":"completed"},"tags":[],"pycharm":{"name":"#%%\n"},"execution":{"iopub.status.busy":"2022-06-06T10:14:39.074443Z","iopub.execute_input":"2022-06-06T10:14:39.074909Z","iopub.status.idle":"2022-06-06T10:14:39.084463Z","shell.execute_reply.started":"2022-06-06T10:14:39.074868Z","shell.execute_reply":"2022-06-06T10:14:39.083766Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, axes = plt.subplots(nrows=1, ncols=3, figsize=[12, 6], dpi=300)\n\nfor i in range(3):\n    rotated_img = random_rotate(Image.open(os.path.join(dir, train_data['image'][0])), 20)\n    axes[i].imshow(tf.keras.utils.array_to_img(rotated_img))\n\nplt.show()","metadata":{"papermill":{"duration":2.781779,"end_time":"2022-05-03T03:04:15.724211","exception":false,"start_time":"2022-05-03T03:04:12.942432","status":"completed"},"tags":[],"pycharm":{"name":"#%%\n"},"execution":{"iopub.status.busy":"2022-06-06T13:51:41.840456Z","iopub.execute_input":"2022-06-06T13:51:41.840782Z","iopub.status.idle":"2022-06-06T13:51:44.390899Z","shell.execute_reply.started":"2022-06-06T13:51:41.840750Z","shell.execute_reply":"2022-06-06T13:51:44.388785Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 🚩 zoom + rotaion","metadata":{}},{"cell_type":"code","source":"fig, axes = plt.subplots(nrows=1, ncols=3, figsize=[12, 6], dpi=300)\n\nfor i in range(3):\n    zoomed_img = random_zoom(tf.keras.utils.img_to_array(Image.open(os.path.join(dir, train_data['image'][0]))), 0.5)\n    rotated_img = random_rotate(zoomed_img, 20)\n    axes[i].imshow(tf.keras.utils.array_to_img(rotated_img))\n\nplt.show()","metadata":{"papermill":{"duration":2.835754,"end_time":"2022-05-03T03:04:18.763248","exception":false,"start_time":"2022-05-03T03:04:15.927494","status":"completed"},"tags":[],"pycharm":{"name":"#%%\n"},"execution":{"iopub.status.busy":"2022-06-06T13:53:28.248050Z","iopub.execute_input":"2022-06-06T13:53:28.248326Z","iopub.status.idle":"2022-06-06T13:53:30.341536Z","shell.execute_reply.started":"2022-06-06T13:53:28.248298Z","shell.execute_reply":"2022-06-06T13:53:30.340619Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 🚩 Image Crop\n----\n* **.image.random_crop() 함수 사용하여 주어진 크기로 텐서(이미지)를 무작위로 자르기**\n* **무작위로 자르기 때문에 자르는 위치를 알지 못함**\n* **자르고자 하는 이미지 크기 : 512 -> 128**\n* **Color Image 기준**","metadata":{}},{"cell_type":"code","source":"# color image이기 때문에 자르고자 하는 이미지가 총 3개\ncentral_crop_width = (0.35, 0.65, 0.75)\ncentral_crop_height = (0.35, 0.9, 0.75)\n\nfor w_factor, h_factor in zip(central_crop_width, central_crop_height):\n    h, w = tf.keras.utils.img_to_array(Image.open(os.path.join(dir, train_data['image'][0]))).shape[:2]\n    print(int(w * w_factor), int(h * h_factor))","metadata":{"papermill":{"duration":0.330012,"end_time":"2022-05-03T03:04:19.387301","exception":false,"start_time":"2022-05-03T03:04:19.057289","status":"completed"},"tags":[],"pycharm":{"name":"#%%\n"},"execution":{"iopub.status.busy":"2022-06-06T14:21:44.032611Z","iopub.execute_input":"2022-06-06T14:21:44.032929Z","iopub.status.idle":"2022-06-06T14:21:44.067992Z","shell.execute_reply.started":"2022-06-06T14:21:44.032898Z","shell.execute_reply":"2022-06-06T14:21:44.067379Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def resize_to_smaller_side(img,small_side_to=224, crop_window=(128, 128, 3), copies=3):\n    h, w = img.shape[:2]\n    crops = []\n\n    if h < w:\n        resized = tf.image.resize(img, size=(small_side_to, w))\n        \n    elif w < h:\n        resized = tf.image.resize(img, size=(h, small_side_to))\n        \n    else:\n        resized = tf.image.resize(img, (small_side_to, w))\n\n    # color 이미지이기 때문에 3번 반복\n    for _ in range(copies):\n        crops.append(tf.image.random_crop(resized, crop_window))\n\n    return crops","metadata":{"collapsed":false,"pycharm":{"name":"#%%\n"},"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-06-06T10:14:46.539429Z","iopub.execute_input":"2022-06-06T10:14:46.539660Z","iopub.status.idle":"2022-06-06T10:14:46.546269Z","shell.execute_reply.started":"2022-06-06T10:14:46.539632Z","shell.execute_reply":"2022-06-06T10:14:46.545394Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img = tf.keras.utils.img_to_array(Image.open(os.path.join(dir, train_data['image'][0])))\ncrops = resize_to_smaller_side(tf.image.resize(img, size=(512, 512)))\n\nfig, axes = plt.subplots(nrows=1, ncols=3, figsize=[12, 6], dpi=300)\n\nfor i, crop in enumerate(crops):\n    axes[i].imshow(tf.keras.utils.array_to_img(crop))\n\nplt.show()","metadata":{"collapsed":false,"pycharm":{"name":"#%%\n"},"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-06-06T14:04:25.522968Z","iopub.execute_input":"2022-06-06T14:04:25.523279Z","iopub.status.idle":"2022-06-06T14:04:26.205777Z","shell.execute_reply.started":"2022-06-06T14:04:25.523249Z","shell.execute_reply":"2022-06-06T14:04:26.204843Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 🚩 Image Zoom + Rotation + Crop\n----\n* **.image.crop_to_bounding_box()를 사용하여 image를 지정된 범위의 bounding box로 자름**\n* **zoom, rotation, crop 3가지 기능 수행 가능**\n* **Color Image 기준**","metadata":{}},{"cell_type":"code","source":"def cropping(filename, dir,\n             rotate_range=10,\n             flipping=True,\n             zoom_range=0.5,\n             central_crop_width=(0.35, 0.65, 0.75),central_crop_height=(0.35, 0.9, 0.45),\n             random_crop_window=(128, 128, 3),\n             small_side_to=224,\n             copies=3):\n    \n    arr = tf.keras.utils.img_to_array(Image.open(os.path.join(dir, filename)))\n    crops = []\n\n    if isinstance(central_crop_width, (list, tuple, np.ndarray)):\n\n        for w_factor, h_factor in zip(central_crop_width, central_crop_height):\n            h, w = arr.shape[:2]\n            offset_h = (h - h_factor * h) // 2\n            offset_w = (w - w_factor * w) // 2\n\n            crops.append(\n                tf.image.crop_to_bounding_box(arr, int(offset_h), int(offset_w), int(h * h_factor), int(w * w_factor))\n            )\n\n    return crops","metadata":{"papermill":{"duration":0.295162,"end_time":"2022-05-03T03:04:19.963399","exception":false,"start_time":"2022-05-03T03:04:19.668237","status":"completed"},"tags":[],"pycharm":{"name":"#%%\n"},"execution":{"iopub.status.busy":"2022-06-06T14:24:44.638946Z","iopub.execute_input":"2022-06-06T14:24:44.639241Z","iopub.status.idle":"2022-06-06T14:24:44.647640Z","shell.execute_reply.started":"2022-06-06T14:24:44.639212Z","shell.execute_reply":"2022-06-06T14:24:44.646612Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dir = '../input/sorghum-cultivar-identification-512512/train'\nfilename = train_data['image'][0]\n\ncrops = cropping(filename, dir)\n\nfig, axes = plt.subplots(nrows=1, ncols=3, figsize=[12, 10], dpi=300)\naxes = axes.ravel()\n\nfor i, crop in enumerate(crops):\n    axes[i].imshow(tf.keras.utils.array_to_img(crop))\n\nplt.show()","metadata":{"papermill":{"duration":2.309711,"end_time":"2022-05-03T03:04:22.557129","exception":false,"start_time":"2022-05-03T03:04:20.247418","status":"completed"},"tags":[],"pycharm":{"name":"#%%\n"},"execution":{"iopub.status.busy":"2022-06-06T14:25:01.232161Z","iopub.execute_input":"2022-06-06T14:25:01.232438Z","iopub.status.idle":"2022-06-06T14:25:03.032271Z","shell.execute_reply.started":"2022-06-06T14:25:01.232409Z","shell.execute_reply":"2022-06-06T14:25:03.030938Z"},"trusted":true},"execution_count":null,"outputs":[]}]}