{"cells":[{"metadata":{},"cell_type":"markdown","source":"This notebook offers two important utility functions used in most object detection problems. I have tried to keep the code succint, well documented and written in a very simple way so anyone can extend it the way they want. I am getting started on this problem and thought of sharing these methods hoping to save a few minutes for someone.\n\nIf you find this useful, please upvote :).\n\n# plot_images\n**Method doc**    \nPlots image_count random images in a subplot containing 3 columns. Note that before using this function generally,\nplease set the TRAIN_IMAGES_PATH global variable to the location where images are stored.\n    \n**Parameters**    \n**dataframe**: DataFrame containing just one column which contains image names found under TRAIN_IMAGES_PATH  \n**image_count**: Number of images to display. Will round of to nearest multiple of 3 since images are displayed in\n             3 columns.\n     \n# plot_images_with_bounding_boxes\n\n**Method doc**  \nDisplayes images with bounding boxes. Note that before using this function generally, please set the \nTRAIN_IMAGES_PATH global variable to the location where images are stored.\n    \n**Parameters**  \n**dataframe**: A Dataframe containing the following columns:  \n            image_id: name of the column containing the image file name including the extension. If the name is \n                      different than 'image_id', pass the name as image_label parameter.  \n            bbox: name of the column containing the bounding box as a string in the format \n                  '[xmin, ymin, width, height]'. If the name is different than bbox, pass the name as bbox_label \n                  parameter.  \n**image_indices**: A list containing the images to display  \n**image_label**: Column name containing the images  \n**bbox_label**: Column name containing the bounding box  ","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"import numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport cv2\nimport matplotlib.pyplot as plt\nimport matplotlib.patches as patches\nimport random\nimport math\n%matplotlib inline","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Data setup and basic Validation**\n\nThe input data loaded here is used subsequently for testing the functions.","execution_count":null},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"input_data = pd.read_csv('/kaggle/input/global-wheat-detection/train.csv')\ninput_data['image_id'] = input_data['image_id'].apply(lambda row : row + '.jpg')\ninput_data.drop(columns=['source'], inplace=True)\n\n# Basic sanity checking\ndef validate_data(data):\n    # Making sure all images have dimension 1024x1024\n    height_non_1024 = data[input_data['height'] != 1024]\n    width_non_1024 = data[input_data['width'] != 1024]\n    assert height_non_1024.shape[0] == 0\n    assert width_non_1024.shape[0] == 0\n\n    # Confirming that training images have only one bounding box in training\n    multiple_bb = data[input_data['bbox'].apply(lambda x: len(x.split(\",\"))) > 5]\n    assert multiple_bb.shape[0] == 0\n\ndef create_numeric_list(bbox):\n    \"\"\"\n    Takes a string bounding box as present in input data ie. '[xmin, ymin, width, height]' and returns\n    a float array of the numbers\n    \"\"\"\n    bbox = bbox.replace(\" \", \"\")\n    bbox = bbox.replace(\"[\", \"\")\n    bbox = bbox.replace(\"]\", \"\")\n    bbox = bbox.split(\",\")\n    return [float(bbox[0]), float(bbox[1]), float(bbox[2]), float(bbox[3])]\n\nvalidate_data(input_data)\ninput_data.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Global variables\n# This and any other notebook using the utility functions is going to need this.\nINPUT_ROOT = '/kaggle/input/global-wheat-detection/'\nTRAIN_IMAGES_PATH = INPUT_ROOT + 'train/'\nTOTAL_IMAGES_COUNT = len(input_data)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def plot_images(dataframe, image_count=6):\n    \"\"\"\n    Plots image_count random images in a subplot containing 3 columns. Note that before using this function generally,\n    please set the TRAIN_IMAGES_PATH global variable to the location where images are stored.\n    \n    Parameters\n    ----------\n    dataframe: DataFrame containing just one column which contains image names found under TRAIN_IMAGES_PATH\n    image_count: Minimum Number of images to display. Will round of to nearest multiple of 3 since images are \n                displayed in 3 columns and show those images.\n    \"\"\"\n    assert dataframe.shape[1] == 1\n    size = len(dataframe)\n    while image_count % 3 != 0:\n        image_count = image_count + 1 \n\n    image_column = dataframe.columns[0]\n    row_count = (int) (image_count/3)\n    fig, ax = plt.subplots(row_count, 3, figsize=(15,15))\n    for i in range(row_count):\n        for j in range(3):\n            index = random.randint(0, size-1)\n            tuple_index = (i, j) if row_count > 1 else j\n            ax[tuple_index].imshow(cv2.imread(\n                TRAIN_IMAGES_PATH + dataframe.iloc[index][image_column]))\n            ax[tuple_index].set_title('Image: {}'.format(index))\n    fig.show()\n    \n# Sample usage\nplot_images(input_data[['image_id']], 9)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def plot_images_with_bounding_boxes(dataframe, image_indices, image_label='image_id', bbox_label='bbox'):\n    \"\"\"\n    Displayes images with bounding boxes. Note that before using this function generally, please set the \n    TRAIN_IMAGES_PATH global variable to the location where images are stored. The images are displayed in\n    three columns so the last image may be repeated for filling up the columns.\n    \n    Parameters\n    ----------\n    dataframe: A Dataframe containing the following columns:\n                image_id: name of the column containing the image file name including the extension. If the name is \n                          different than 'image_id', pass the name as image_label parameter.\n                bbox: name of the column containing the bounding box as a string in the format \n                      '[xmin, ymin, width, height]'. If the name is different than bbox, pass the name as bbox_label \n                      parameter.\n    image_indices: A list containing the images to display\n    image_label: Column name containing the images\n    bbox_label: Column name containing the bounding box\n    \"\"\"\n    images_count = len(image_indices)\n    while images_count % 3 != 0:\n        image_indices.append(image_indices[-1] + 1)\n        images_count = len(image_indices)\n        \n    row_count = (int) (images_count / 3)\n    fig, ax = plt.subplots(row_count, 3, figsize=(20,20))\n    \n    for i in range(images_count):\n        x = (int)(i/3)\n        y = i%3    \n        tuple_index = (x,y) if row_count > 1 else y\n        ax[tuple_index].imshow(cv2.imread(TRAIN_IMAGES_PATH + dataframe.iloc[image_indices[i]][image_label]))\n        ax[tuple_index].set_title('Image {}'.format(image_indices[i]))\n        input_row = input_data.iloc[image_indices[i]]\n        all_rows_for_image_id = dataframe[dataframe.image_id == input_row[image_label]]\n        for index, row in all_rows_for_image_id.iterrows():    \n            bbox = create_numeric_list(row[bbox_label])\n            rect = patches.Rectangle((bbox[0],bbox[1]),bbox[2],bbox[3],linewidth=1,edgecolor='r',facecolor='none')\n            ax[tuple_index].add_patch(rect)\n\n# Example usage\nplot_images_with_bounding_boxes(input_data, [3, 376, 267, 33, 9984, 37, 844, 8947, 489])","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}