{"cells":[{"metadata":{},"cell_type":"markdown","source":"Link to the training notebook <a href = \"https://www.kaggle.com/daenys2000/fasterrcnn-pytorch\">Faster RCNN</a>","execution_count":null},{"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\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport os\nfrom skimage import color\nimport matplotlib.image as mpimg\nimport matplotlib.patches as patches\nimport albumentations as alb","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"train_path = '/kaggle/input/global-wheat-detection/train.csv'\ntrain_img_path = '/kaggle/input/global-wheat-detection/train'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#read the csv file\ntrain = pd.read_csv(train_path)\ntrain.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Sources","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"sns.countplot(train['source'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#separating x,y,w,h into separate columns for convenience\nbboxes = np.stack(train['bbox'].apply(lambda x: np.fromstring(x[1:-1], sep = ',')))\nfor i, col in enumerate(['x_min', 'y_min', 'w', 'h']):\n    train[col] = bboxes[:,i]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#dropping the bbox column as it is not needed now\ntrain.drop(columns = ['bbox'], inplace = True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#calculate box areas to check for anomaly boxes\ntrain['box_area'] = train['w']*train['h']","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#display head of new dataframe\ntrain.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#number of unique images in the dataframe\nlen(train['image_id'].unique())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#number of images in the training directory\nlen(os.listdir(train_img_path))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"markdown","source":"this implies that images with no objects are not in the dataframe","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"#obtaining a list of all images which have no wheat heads in them\nunique_imgs_wbox = list(train['image_id'].unique())\nall_unique_imgs = os.listdir(train_img_path)\nno_wheat_imgs = [img_id for img_id in all_unique_imgs if img_id not in unique_imgs_wbox]\nlen(no_wheat_imgs)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#append .jpg to image ids for easier handling\ntrain['image_id'] = train['image_id'].apply(lambda x: str(x) + '.jpg')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Plotting some training images...","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_all_bboxes(df, image_id, count = False):\n    '''function that gets all bboxes for a given image id'''\n    bboxes = []\n    for _,row in df[df.image_id == image_id].iterrows():\n        bboxes.append([row.x_min, row.y_min, row.w, row.h])\n    if count:\n        return bboxes, len(bboxes)\n    else:\n        return bboxes\n\ndef select_img(n, wheat = True):\n    '''function to randomly select image ids from the dataframe and return it as a list'''\n    if wheat:\n        img_ids = train.sample(n = n, random_state = 0)['image_id']\n        return list(img_ids)\n    else:\n        img_ids = np.random.choice(no_wheat_imgs, n)\n        return list(img_ids)\n        \n\ndef plot_imgs(df, ids, bbox = False):\n    '''function to plot an even number of images'''\n    n = len(ids)\n    fig, ax = plt.subplots(2, n//2, figsize = (40,30))\n    for i, im_id in enumerate(ids):\n        img = mpimg.imread(os.path.join(train_img_path, im_id))\n        ax[i//(n//2)][i%(n//2)].imshow(img)\n        ax[i//(n//2)][i%(n//2)].axis('off')\n        if bbox:\n            bboxes = get_all_bboxes(df, im_id)\n            for bbox in bboxes:\n                rect = patches.Rectangle((bbox[0],bbox[1]),bbox[2],bbox[3],linewidth=2,edgecolor='r',facecolor='none')\n                ax[i//(n//2)][i%(n//2)].add_patch(rect)\n        else:\n            pass        \n    plt.tight_layout()\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plot_imgs(train, select_img(6))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Plotting images which don't have wheat heads in them","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"plot_imgs(train, select_img(6, wheat = False))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Plotting training images with bounding boxes","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"plot_imgs(train, select_img(6), bbox = True)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Visualising the differences in box sizes\nThe difference in the maximum box are and minimum box area is huge! There are definitely some anomaly boxes which must be removed during training","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"print('Mean box area is: ', train['box_area'].mean())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print('Max box area is: ', train['box_area'].max())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print('Min box area is: ', train['box_area'].min())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#large ids\nlarge_ids = train[train['box_area'] > 170000].image_id\nplot_imgs(train, large_ids, bbox = True)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Some of these boxes are huge and aren't correct, they must be removed while training","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"#small ids\nsmall_ids = train[train['box_area']<15].image_id\nplot_imgs(train, small_ids, bbox = True)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Most of these boxes look alright :), however a small fraction of them are nothing but tiny specks. ","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"## Visualising the difference in brightness of the image\nSome images are quite dark, and some are quite bright. Let's see how extreme these ends go.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_brightness(image):\n    image = color.rgb2gray(image)\n    return np.mean(image)*255","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#get brightness of each image and append to dataframe\nbrightness_array = []\nimage_list = list(train['image_id'].unique())\nfor img in image_list:\n    image = mpimg.imread(os.path.join(train_img_path, img))\n    brightness = get_brightness(image)\n    brightness_array.append(brightness)\n\ndf = pd.DataFrame({'image_id': image_list,\n                         'brightness': brightness_array})","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#bright ids\nbright_ids = df[df['brightness'] > 130].image_id\nplot_imgs(train, bright_ids[0:6], bbox = True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#dark ids\ndark_ids = df[df['brightness'] < 24].image_id\nplot_imgs(train, dark_ids, bbox = True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print('Mean Brightness is: ', df['brightness'].mean())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print('Max Brightness is: ', df['brightness'].max())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print('Min Brightness is: ', df['brightness'].min())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.hist(df['brightness'])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Number of boxes on an image?","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"#getting boxes per image\nbox_count = []\nfor img in image_list:\n    _, count = get_all_bboxes(train, img, count = True)\n    box_count.append(count)\n    \ndf['count'] = box_count","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#more boxes\nmore_ids = df[df['count'] > 95].image_id\nplot_imgs(train, more_ids[0:8], bbox = True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#less ids \nless_ids = df[df['count']<10].image_id\nplot_imgs(train, less_ids[0:8], bbox = True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print('Mean box count is: ', df['count'].mean())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print('Max box count is: ', df['count'].max())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print('Min box count is: ', df['count'].min())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.hist(df['count'])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Data Augmentation is needed because the dataset is small, data augmentation would enable us to train a more robust model.Using the albumentations library, it is easy to augment data for object detection tasks","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"#describing transforms and the probability of their application \ntransforms = alb.Compose([\n    alb.HorizontalFlip(p = 0.5),\n    alb.VerticalFlip(p = 0.5),\n    alb.RandomBrightness(p = 0.2),\n    alb.RandomContrast(p = 0.2),\n    alb.CLAHE(p = 0.5),\n    alb.RandomSizedBBoxSafeCrop(512, 512, erosion_rate = 0.0, interpolation = 1, p = 0.5),\n], p=1.0, bbox_params=alb.BboxParams(format='coco', label_fields=['category']))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def apply(transforms, df, n_transforms = 5):\n    '''function to apply and view transforms'''\n    #randomly choose an image\n    img_id = select_img(4) \n    bboxes = get_all_bboxes(df, img_id[3])\n    fig,ax = plt.subplots(1, n_transforms + 1, figsize = (40,30))\n    image = mpimg.imread(os.path.join(train_img_path, img_id[3]))\n    ax[0].imshow(image)\n    ax[0].set_title('Original')\n    ax[0].axis('off')\n    for bbox in bboxes:\n        rect = patches.Rectangle((bbox[0],bbox[1]),bbox[2],bbox[3],linewidth=2,edgecolor='r',facecolor='none')\n        ax[0].add_patch(rect)\n    \n    #apply transforms one by one and plot\n    for i in range(n_transforms):\n        parameters = {\n            'image': np.asarray(image),\n            'bboxes': bboxes,\n            'category': np.ones(len(bboxes))\n        }\n        augmented = transforms(**parameters)\n        boxes_aug = augmented['bboxes']\n        image_aug = augmented['image']\n        ax[i+1].imshow(image_aug)\n        ax[i+1].axis('off')\n        ax[i+1].set_title('augmented ' + str(i + 1))\n        for bbox in boxes_aug:\n            rect = patches.Rectangle((bbox[0],bbox[1]),bbox[2],bbox[3],linewidth=2,edgecolor='r',facecolor='none')\n            ax[i+1].add_patch(rect)\n    plt.tight_layout()\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"apply(transforms, train)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"apply(transforms, train, 4)","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}