{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","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\nimport random\nfrom PIL import Image\nfrom matplotlib import pyplot as plt\nimport xml.etree.ElementTree as ET\n\nimport torch \nimport torchvision\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\nimport os\nprint(os.listdir(\"../input\"))\n\n# Any results you write to the current directory are saved as output.","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"img_base_path = \"../input/all-dogs/all-dogs\"\n# Files\nimages = os.listdir(img_base_path)\nprint(\"Number of Images: \", len(images))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# View Samples from Data"},{"metadata":{"trusted":true},"cell_type":"code","source":"# choose 16 random images to display\nimages_to_display = random.choices(images, k=64)\n\nfig = plt.figure(figsize=(25, 16))\nfor ii, img in enumerate(images_to_display):\n    ax = fig.add_subplot(8, 8, ii + 1, xticks=[], yticks=[])\n    \n    img = Image.open(os.path.join(img_base_path, img))\n    plt.imshow(img)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"images_to_display[18]","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"##### Try re running above cell again and again to view more samples. \n#### It can be observed that images contains significant backgrounds(Noise in our case). Some images contains trees, persons, objects and even some have multiple dogs in them too. This could create problem while training our model.\nWe have given annotations for all images, which can be used to pre-process(crop) these images "},{"metadata":{},"cell_type":"markdown","source":"### Annotations\n#### The structure of the annotations are classic XML with the bbox at \"annotation/object/bndbox\".\nStructure of XML is as follows"},{"metadata":{"trusted":true},"cell_type":"code","source":"!cat ../input/annotation/Annotation/n02091244-Ibizan_hound/n02091244_2934","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Using annotations to crop ROI"},{"metadata":{"trusted":true},"cell_type":"code","source":"# choose image\nimage_name = 'n02105641_169.jpg'\n\n# read image\nimg = Image.open(os.path.join(img_base_path, image_name))\n\n# display image\nfig = plt.figure(figsize=(8, 12))\nplt.imshow(img)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### Noise(extra features) can be observed in image. These will lead to poor generation as model will get confused what to produce"},{"metadata":{"trusted":true},"cell_type":"code","source":"# finding annotation of this particular image\n# image_name == dogBreed_number\n\nannotation_folders = os.listdir('../input/annotation/Annotation')\nbreed_folder = [x for x in annotation_folders if image_name.split('_')[0] in x]\nassert len(breed_folder) == 1, \"Multiple Folders Found\"\n\nbreed_folder = breed_folder[0]\nprint(\"Image Folder: \", breed_folder)\nannotation_path = os.path.join('../input/annotation/Annotation', breed_folder, image_name[:-4])\nprint(\"Annotation Path: \", annotation_path)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# View annotations\n!cat ../input/annotation/Annotation/n02105641-Old_English_sheepdog/n02105641_169","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"### Getting Bounding Box of dog (ROI) in Image\ntree = ET.parse(annotation_path)\nroot = tree.getroot()\nobjects = root.findall('object')\nfor obj in objects:\n    bndbox = obj.find('bndbox')\n    xmin = int(bndbox.find('xmin').text)\n    ymin = int(bndbox.find('ymin').text)\n    xmax = int(bndbox.find('xmax').text)\n    ymax = int(bndbox.find('ymax').text)\nbbox = (xmin, ymin, xmax, ymax)\nprint(\"Bounding Box: \", bbox)\n\n# crop image\nimg = img.crop(bbox)\n\n# display crop image\nfig = plt.figure(figsize=(8, 12))\nplt.imshow(img)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Crops will give be having only dogs in them, so model will be able to learn better and easier.\n### A point to remember is that images may contain more than one dogs in which case annotations will have more than one bounding boxes in them (image: 'n02088364_3752.jpg'). \nTry \"!cat ../input/annotation/Annotation/n02088364-beagle/n02088364_3752\""},{"metadata":{},"cell_type":"markdown","source":"# Loading Data\n### Creating PyTorch DataLoader with Data Augmentation\n#### Data Augmentation help in training model better. Its like increasing size of your Dataset and prevents overfitting. "},{"metadata":{"trusted":true},"cell_type":"code","source":"# This loader will use the underlying loader plus crop the image based on the annotation\nfrom torchvision import transforms, datasets\nfrom torch.utils.data import DataLoader, Dataset\n\nannotation_folders = os.listdir('../input/annotation/Annotation')\ndef ImageLoader(path):\n    img = datasets.folder.default_loader(path) # default loader\n    # Get bounding box\n    breed_folder = [x for x in annotation_folders if path.split('/')[-1].split('_')[0] in x][0]\n    annotation_path = os.path.join('../input/annotation/Annotation', breed_folder, path.split('/')[-1][:-4])\n\n    tree = ET.parse(annotation_path)\n    root = tree.getroot()\n    objects = root.findall('object')\n    for obj in objects:\n        bndbox = obj.find('bndbox')\n        xmin = int(bndbox.find('xmin').text)\n        ymin = int(bndbox.find('ymin').text)\n        xmax = int(bndbox.find('xmax').text)\n        ymax = int(bndbox.find('ymax').text)\n    bbox = (xmin, ymin, xmax, ymax)\n    \n    # return cropped image\n    img = img.crop(bbox)\n    img = img.resize((64, 64), Image.ANTIALIAS)\n    return img\n\n\n\n# Data Pre-procesing and Augmentation (Experiment on your own)\nrandom_transforms = [transforms.ColorJitter(), transforms.RandomRotation(degrees=20)]\n\ntransform = transforms.Compose([\n                                transforms.CenterCrop(64),\n                                transforms.RandomHorizontalFlip(p=0.5),\n                                transforms.RandomApply(random_transforms, p=0.3),\n                                transforms.ToTensor(),\n                                transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])\n\n# The dataset (example)\ndataset = torchvision.datasets.ImageFolder(\n    '../input/all-dogs/',\n    loader=ImageLoader, # THE CUSTOM LOADER\n    transform=transform\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"_, axes = plt.subplots(figsize=(32, 32), ncols=8, nrows=8)\nfor i, ax in enumerate(axes.flatten()):\n    ax.imshow(dataset[i][0].permute(1, 2, 0).detach().numpy())\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### Try commenting crop line from above code to see the difference.\n#### Also code is considering only one dog per image.\n#### Like if it helps you :)"},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.4","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}