{"cells":[{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"bde7cae1-1a97-985a-d8ef-67b527c98f79"},"outputs":[],"source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load in \n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the \"../input/\" directory.\n# For example, running this (by clicking run or pressing Shift+Enter) will list the files in the input directory\n\nfrom subprocess import check_output\nprint(check_output([\"ls\", \"../input\"]).decode(\"utf8\"))\n\n# Any results you write to the current directory are saved as output."},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"9a44a721-7a4b-da2f-5ed4-bf327da07691"},"outputs":[],"source":"Preprocess Images\nNormalize the luminance values and resize the images to a standard shape. This is done because the training and test images come in a variety of shapes, sizes, and lighting.\nIn [1]:\n%matplotlib inline\n\nimport glob\nimport os\nimport re\n\nimport matplotlib.image as mpimg\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport pandas as pd\nimport PIL\nfrom PIL import Image\nSort numerically\nThis is not really necessary but when you're exploring it's nice to have the images sorted numerically so that cat.100.jpg comes before cat.1000.jpg, etc.\nIn [2]:\ndef natural_key(string_):\n    \"\"\"\n    Define sort key that is integer-aware\n    \"\"\"\n    return [int(s) if s.isdigit() else s for s in re.split(r'(\\d+)', string_)]\nNormalize the image luminance\nit is common in image analysis to normalize the luminance (brightness) values to have mean 0 and standard deviation 1. We do that here and apply a slight contrast stretch, which also ensures the brightness values stay within the bounds of the image encoding.\nThe normalization is applied to the luminance, not to the RGB channels individually. We first convert to YCbCr space, operate on the Y channel, and then convert back to RGB.\nIn [3]:\ndef norm_image(img):\n    \"\"\"\n    Normalize PIL image\n    \n    Normalizes luminance to (mean,std)=(0,1), and applies a [1%, 99%] contrast stretch\n    \"\"\"\n    img_y, img_b, img_r = img.convert('YCbCr').split()\n    \n    img_y_np = np.asarray(img_y).astype(float)\n\n    img_y_np /= 255\n    img_y_np -= img_y_np.mean()\n    img_y_np /= img_y_np.std()\n    scale = np.max([np.abs(np.percentile(img_y_np, 1.0)),\n                    np.abs(np.percentile(img_y_np, 99.0))])\n    img_y_np = img_y_np / scale\n    img_y_np = np.clip(img_y_np, -1.0, 1.0)\n    img_y_np = (img_y_np + 1.0) / 2.0\n    \n    img_y_np = (img_y_np * 255 + 0.5).astype(np.uint8)\n\n    img_y = Image.fromarray(img_y_np)\n\n    img_ybr = Image.merge('YCbCr', (img_y, img_b, img_r))\n    \n    img_nrm = img_ybr.convert('RGB')\n    \n    return img_nrm\nResize the image\nWe resize the images to be square with a default side length of 224 to be compatible with models trained on ImageNet. The aspect ratio is preserved and gray bars are added as necessary to make the image square.\nIn [4]:\ndef resize_image(img, size):\n    \"\"\"\n    Resize PIL image\n    \n    Resizes image to be square with sidelength size. Pads with black if needed.\n    \"\"\"\n    # Resize\n    n_x, n_y = img.size\n    if n_y > n_x:\n        n_y_new = size\n        n_x_new = int(size * n_x / n_y + 0.5)\n    else:\n        n_x_new = size\n        n_y_new = int(size * n_y / n_x + 0.5)\n\n    img_res = img.resize((n_x_new, n_y_new), resample=PIL.Image.BICUBIC)\n\n    # Pad the borders to create a square image\n    img_pad = Image.new('RGB', (size, size), (128, 128, 128))\n    ulc = ((size - n_x_new) // 2, (size - n_y_new) // 2)\n    img_pad.paste(img_res, ulc)\n\n    return img_pad\nAccumulate the image names\nIn [5]:\nTRAIN_DIR = '../input/train/'\nTEST_DIR = '../input/test/'\n\ntrain_cats = sorted(glob.glob(os.path.join(TRAIN_DIR, 'cat*.jpg')), key=natural_key)\ntrain_dogs = sorted(glob.glob(os.path.join(TRAIN_DIR, 'dog*.jpg')), key=natural_key)\ntrain_all = train_cats + train_dogs\n\ntest_all = sorted(glob.glob(os.path.join(TEST_DIR, '*.jpg')), key=natural_key)\nPreprocess a single image\nThis cell will preprocess a specified or random image and display the before and after versions.\nIn [6]:\nSIZE = 224  # for ImageNet models compatibility\n\n# Read the image\nchoose_random_image = True\nif choose_random_image:\n    idx = np.random.randint(0, len(train_all))\nelse:\n    idx = 24486\nprint(idx)\npath = train_all[idx]\nimg = Image.open(path)\n\n# Normalize it\nimg_nrm = norm_image(img)\n\n\n# Resize it\nimg_res = resize_image(img_nrm, SIZE)\n\n# Show it\nplt.figure(figsize=(8,4))\nplt.subplot(131)\nplt.title('Original')\nplt.imshow(img)\n\nplt.subplot(132)\nplt.title('Normalized')\nplt.imshow(img_nrm)\n\nplt.subplot(133)\nplt.title('Resized')\nplt.imshow(img_res)\n\nplt.tight_layout()\nplt.show()\n20011\n\nIn [7]:\n "}],"metadata":{"_change_revision":0,"_is_fork":false,"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.5.2"}},"nbformat":4,"nbformat_minor":0}