{"cells":[{"metadata":{},"cell_type":"markdown","source":"This is the first competition that I have begun my Kaggle journey with. Also, the first time that I am working on an object-detection problem statement. \nI present here a very basic EDA for the given wheat head dataset hoping that other beginners like me would find it easy to understand the data and get started with this intriguing competition.\nIn addition to the EDA, I have also added a few augmentations that I tried on the images in the second half of the kernel.","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"Import dependencies.","execution_count":null},{"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 matplotlib.pyplot as plt\nimport matplotlib.patches as patches\nimport cv2\nimport re\nimport albumentations as A\n%matplotlib inline","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Save necessary paths to the data.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"INPUT_DIR = '../input/global-wheat-detection'\nTRAIN_DIR = f'{INPUT_DIR}/train'","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Understand the basic image characteristics.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"sample = cv2.imread(TRAIN_DIR+'/01189a3c3.jpg', cv2.IMREAD_UNCHANGED)\n\ndimensions = sample.shape\nheight = sample.shape[0]\nwidth = sample.shape[1]\nn_of_channels = sample.shape[2]\n\nprint('Image characteristics:\\n')\nprint('Dimensions: {}\\nHeight: {}, Width:{}, Number of channels: {}'.format(dimensions, height, width, n_of_channels))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Load the train csv file.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df = pd.read_csv(INPUT_DIR+'/train.csv')\ntrain_df.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Check if all the image dimensions are same.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"print(train_df['height'].unique(), train_df['width'].unique())","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Understanding the csv file.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"# No of unique images in the csv file\n\nprint('Unique images: ',len(train_df['image_id'].unique()))\n\n# Different regions for which data is collected\n\nprint('Regions: ',train_df['source'].unique())\n\n# No of unique images for each region\nregion_list = []\nunique_images = []\nfor region in train_df['source'].unique():\n    region_list.append(region)\n    unique_images.append(len(train_df[train_df['source']== region]['image_id'].unique()))\n    print('Region: {}, Number of Images: {}'.format(str(region), len(train_df[train_df['source']== region]['image_id'].unique())))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fig, ax = plt.subplots()\nax.pie(unique_images, labels = region_list, autopct='%1.1f%%')\nax.axis('equal')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Extracting bounding boxes data from the csv file. Function taken from Peter's [notebook](http://www.kaggle.com/pestipeti/global-wheat-detection-eda).","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"The 'coco' format for the bounding boxes is (x_min, y_min, width, height) which has been originally provided in the dataframe. However, for my convenience, I have converted this to the 'pascal_voc' format i.e. (x_min, y_min, x_max, y_max). Note: all the functions can be modified using minor changes if you wish to use the 'coco' format.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df['x_min'] = -1\ntrain_df['y_min'] = -1\ntrain_df['w'] = -1\ntrain_df['h'] = -1\n\ndef expand_bbox(x):\n    r = np.array(re.findall('([0-9]+[.]?[0-9]*)', x))\n    if len(r) == 0:\n        r = [-1, -1, -1, -1]\n    return r\n\ntrain_df[['x_min', 'y_min', 'w', 'h']] = np.stack(train_df['bbox'].apply(lambda x: expand_bbox(x)))\ntrain_df.drop(columns = ['bbox'], inplace = True)\ntrain_df['x_min'] = train_df['x_min'].astype(np.float)\ntrain_df['y_min'] = train_df['y_min'].astype(np.float)\ntrain_df['w'] = train_df['w'].astype(np.float)\ntrain_df['h'] = train_df['h'].astype(np.float)\n\ntrain_df['x_max'] = train_df['x_min'] + train_df['w']\ntrain_df['y_max'] = train_df['y_min'] + train_df['h']\n\ntrain_df.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Drop the unecessary columns.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df.drop(columns = ['width', 'height'], inplace=True)\ntrain_df.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Display an image with and without the bounding boxes.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"def show_sample_images(image_data):\n    \n    fig, ax = plt.subplots(1, 2, figsize = (12, 8))\n    ax = ax.flatten()\n    \n    image = cv2.imread(os.path.join(TRAIN_DIR + '/{}.jpg').format(image_data.iloc[0]['image_id']), cv2.IMREAD_COLOR)\n    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB).astype(np.uint8)\n    \n    ax[0].set_title('Original Image')\n    ax[0].imshow(image)\n    \n    for i, row in image_data.iterrows():\n        cv2.rectangle(image,\n                      (int(row['x_min']), int(row['y_min'])),\n                      (int(row['x_max']), int(row['y_max'])),\n                      (220, 0, 0), 3)\n    \n    ax[1].set_title('Image with Bounding Boxes')\n    ax[1].imshow(image)\n    \n    plt.show()\n        ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"show_sample_images(train_df[train_df['image_id'] == 'b6ab77fd7'])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Apply a few basic augmentations.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_bboxes(bboxes, col, bbox_format = 'pascal_voc', color='white'):\n    for i in range(len(bboxes)):\n        x_min = bboxes[i][0]\n        y_min = bboxes[i][1]\n        x_max = bboxes[i][2]\n        y_max = bboxes[i][3]\n        width = x_max - x_min\n        height = y_max - y_min\n        rect = patches.Rectangle((x_min, y_min), width, height, linewidth=2, edgecolor=color, facecolor='none')\n        col.add_patch(rect)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def show_augmented_images(aug_result, image_data):\n    \n    fig, ax = plt.subplots(1, 2, figsize = (12, 8))\n    ax = ax.flatten()\n    \n    image = cv2.imread(os.path.join(TRAIN_DIR + '/{}.jpg').format(image_data.iloc[0]['image_id']), cv2.IMREAD_COLOR)\n    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB).astype(np.uint8)\n    \n    aug_image = aug_result['image']\n\n    get_bboxes(pascal_voc_boxes, ax[0], color='red')\n    orig_bboxes = pascal_voc_boxes\n    ax[0].set_title('Original Image with Bounding Boxes')\n    ax[0].imshow(image)\n\n    get_bboxes(aug_result['bboxes'], ax[1], color='red')\n    aug_bboxes = aug_result['bboxes']\n    ax[1].set_title('Augmented Image with Bounding Boxes')\n    ax[1].imshow(aug_image)\n    \n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"image = cv2.imread(os.path.join(TRAIN_DIR + '/b6ab77fd7.jpg'), cv2.IMREAD_COLOR)\nimage = cv2.cvtColor(image, cv2.COLOR_BGR2RGB).astype(np.uint8)\nimage_id = 'b6ab77fd7'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"pascal_voc_boxes = train_df[train_df['image_id'] == image_id][['x_min', 'y_min', 'x_max', 'y_max']].astype(np.int32).values\nlabels = np.ones((len(pascal_voc_boxes), ))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"a. CLAHE augmentation","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"aug = A.Compose([\n    A.CLAHE(p=1)\n], bbox_params={'format': 'pascal_voc', 'label_fields':['labels']})\n\naug_result = aug(image=image, bboxes=pascal_voc_boxes, labels=labels)\n\nshow_augmented_images(aug_result, train_df[train_df['image_id'] == 'b6ab77fd7'])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"b. EQUALIZE augmentation","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"aug = A.Compose([\n    A.Equalize(p=1)\n], bbox_params={'format': 'pascal_voc', 'label_fields':['labels']})\n\naug_result = aug(image=image, bboxes=pascal_voc_boxes, labels=labels)\n\nshow_augmented_images(aug_result, train_df[train_df['image_id'] == 'b6ab77fd7'])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"c. BLUR augmentation","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"aug = A.Compose([\n    A.Blur(blur_limit=15, p=1)\n], bbox_params={'format': 'pascal_voc', 'label_fields':['labels']})\n\naug_result = aug(image=image, bboxes=pascal_voc_boxes, labels=labels)\n\nshow_augmented_images(aug_result, train_df[train_df['image_id'] == 'b6ab77fd7'])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"d. RANDOM CROP augmentation","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"aug = A.Compose([\n    A.RandomCrop(512, 512, p=1)\n], bbox_params={'format': 'pascal_voc', 'label_fields':['labels']})\n\naug_result = aug(image=image, bboxes=pascal_voc_boxes, labels=labels)\n\nshow_augmented_images(aug_result, train_df[train_df['image_id'] == 'b6ab77fd7'])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"e. RESIZE augmentation","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"aug = A.Compose([\n    A.Resize(512,512, p=1)\n], bbox_params={'format': 'pascal_voc', 'label_fields':['labels']})\n\naug_result = aug(image=image, bboxes=pascal_voc_boxes, labels=labels)\n\nshow_augmented_images(aug_result, train_df[train_df['image_id'] == 'b6ab77fd7'])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"f. RANDOM GAMMA augmentation","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"aug = A.Compose([\n    A.RandomGamma(p=1)\n], bbox_params={'format': 'pascal_voc', 'label_fields':['labels']})\n\naug_result = aug(image=image, bboxes=pascal_voc_boxes, labels=labels)\n\nshow_augmented_images(aug_result, train_df[train_df['image_id'] == 'b6ab77fd7'])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"g. RANDOM AFFINE augmentation","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"aug = A.Compose([\n    A.ShiftScaleRotate(p=1)\n], bbox_params={'format': 'pascal_voc', 'label_fields':['labels']})\n\naug_result = aug(image=image, bboxes=pascal_voc_boxes, labels=labels)\n\nshow_augmented_images(aug_result, train_df[train_df['image_id'] == 'b6ab77fd7'])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"h. RANDOM BRIGHTNESS & CONTRAST augmentation","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"aug = A.Compose([\n    A.RandomBrightnessContrast(p=1)\n], bbox_params={'format': 'pascal_voc', 'label_fields':['labels']})\n\naug_result = aug(image=image, bboxes=pascal_voc_boxes, labels=labels)\n\nshow_augmented_images(aug_result, train_df[train_df['image_id'] == 'b6ab77fd7'])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"i. RANDOM SIZED BBOX SAFE CROP augmentation","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"aug = A.Compose([\n    A.RandomSizedBBoxSafeCrop(height=512, width = 512, p=1)\n], bbox_params={'format': 'pascal_voc', 'label_fields':['labels']})\n\naug_result = aug(image=image, bboxes=pascal_voc_boxes, labels=labels)\n\nshow_augmented_images(aug_result, train_df[train_df['image_id'] == 'b6ab77fd7'])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"j. RANDOM RAIN augmentation","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"aug = A.Compose([\n    A.RandomRain(p=1)\n], bbox_params={'format': 'pascal_voc', 'label_fields':['labels']})\n\naug_result = aug(image=image, bboxes=pascal_voc_boxes, labels=labels)\n\nshow_augmented_images(aug_result, train_df[train_df['image_id'] == 'b6ab77fd7'])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"k. RANDOM FOG augmentation","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"aug = A.Compose([\n    A.RandomFog(p=1)\n], bbox_params={'format': 'pascal_voc', 'label_fields':['labels']})\n\naug_result = aug(image=image, bboxes=pascal_voc_boxes, labels=labels)\n\nshow_augmented_images(aug_result, train_df[train_df['image_id'] == 'b6ab77fd7'])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"l. RANDOM SOLAR FLARE augmentation","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"aug = A.Compose([\n    A.RandomSunFlare(p=1)\n], bbox_params={'format': 'pascal_voc', 'label_fields':['labels']})\n\naug_result = aug(image=image, bboxes=pascal_voc_boxes, labels=labels)\n\nshow_augmented_images(aug_result, train_df[train_df['image_id'] == 'b6ab77fd7'])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"m. ISO NOISE augmentation","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"aug = A.Compose([\n    A.ISONoise(p=1)\n], bbox_params={'format': 'pascal_voc', 'label_fields':['labels']})\n\naug_result = aug(image=image, bboxes=pascal_voc_boxes, labels=labels)\n\nshow_augmented_images(aug_result, train_df[train_df['image_id'] == 'b6ab77fd7'])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"I would highly appreciate if you could let me know how I can improve my kernels with the objective of making them really simple and easy to understand.","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"Also, if you liked the kernel or found it useful, please upvote it so that I will be motivated further to share my work with everyone. Cheers!","execution_count":null}],"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}