{"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\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 read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 5GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df = pd.read_csv(r'/kaggle/input/global-wheat-detection/train.csv')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df.shape","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"This csv file contain image_id, width, height, bbox, source. There are total of 147793 data-entry in file.but most of data is releted to single image. which contains number of wheat in image.It also given bounding box for each wheat. and image height and width is given.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"df.info()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(df['source'].isnull().sum())\nprint(df['source'].unique())","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"There are total 7 sources of data.\n1. usask_1\n2. arvalis_1\n3. inrae_1\n4. ethz_1\n5. arvalis_3\n6. rres_1\n7. arvalis_2","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"df['source'].value_counts()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Above are the total number of observations per source. but in single image there are multipal bounding boxes for wheats. so its not much usefull.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"len(df['image_id'].unique())","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Traning dataset contain total of 3373 images.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"print(df['width'].unique())\nprint(df['height'].unique())","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"\n\nEach image size is 1024* 1024","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)\n\n# import useful tools\nfrom glob import glob\nfrom PIL import Image\nimport cv2\n\n# import data visualization\nimport matplotlib.pyplot as plt\nimport matplotlib.patches as patches\nimport seaborn as sns\n\nfrom bokeh.plotting import figure\nfrom bokeh.io import output_notebook, show, output_file\nfrom bokeh.models import ColumnDataSource, HoverTool, Panel\nfrom bokeh.models.widgets import Tabs\n\n# import data augmentation\nimport albumentations as albu","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Global Wheat Detection Competition EDA","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"Detection of wheat spikes with computer vision opens a lot of opportunity for the farmers and breeders like:\n\ncontrolling the growth stage of the plants on the field: the number oand the area of spikes is raising closer to the harvest date;\ncontrolling the heatlth of the plants: unusually small number or small size of plants might be a signal of deceased plants;\nspikes density characteristic and approximate yield estimation for different varieties of wheat.\nIn this notebook I am exploring the data and giving some thoughts on what to pay attention when making and validating the models.","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"# General Dataset Information","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"Let's just look at the numbers first. Those numbers will give us a hint which images might be interesting to look at.\n1 The number of train and test images:","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"# Setup the paths to train and test images\nTRAIN_DIR = '/kaggle/input/global-wheat-detection/train/'\nTEST_DIR = '/kaggle/input/global-wheat-detection/test/'\nTRAIN_CSV_PATH = '/kaggle/input/global-wheat-detection/train.csv'\n\n# Glob the directories and get the lists of train and test images\ntrain_fns = glob(TRAIN_DIR + '*')\ntest_fns = glob(TEST_DIR + '*')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Compute at the number of train and test images:","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"print('Number of train images is {}'.format(len(train_fns)))\nprint('Number of test images is {}'.format(len(test_fns)))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"We have only 10 test images here, other test images will be used to evaluate the prediction models during the submission.\n\nJust 3422 images for the training seems to be not much at all. Data augmentation techniques will be definetely required in this competition.","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"2. The number of bounding boxes (wheat spikes) per image:","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"Construct dataframe with all images (images with no bboxes will have nan values in all columns except image_id):","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"# Load the dataframe with the bounding boxes\ntrain = pd.read_csv(TRAIN_CSV_PATH)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Create a dataframe with all train images\nall_train_images = pd.DataFrame([fns.split('/')[-1][:-4] for fns in train_fns])\nall_train_images.columns=['image_id']\nprint(all_train_images.head())\nprint(all_train_images.shape)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Merge all train images with the bounding boxes dataframe\nall_train_images = all_train_images.merge(train, on='image_id', how='left')\n#print(all_train_images.shape)\nprint(all_train_images.head())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# replace nan values with zeros\nall_train_images['bbox'] = all_train_images.bbox.fillna('[0,0,0,0]')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# split bbox column\nbbox_items = all_train_images.bbox.str.split(',', expand=True)\nall_train_images['bbox_xmin'] = bbox_items[0].str.strip('[ ').astype(float)\nall_train_images['bbox_ymin'] = bbox_items[1].str.strip(' ').astype(float)\nall_train_images['bbox_width'] = bbox_items[2].str.strip(' ').astype(float)\nall_train_images['bbox_height'] = bbox_items[3].str.strip(' ]').astype(float)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"all_train_images.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print('{} images without wheat heads.'.format(len(all_train_images) - len(train)))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"bbox_items","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Let's plot some image examples:\n","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_all_bboxes(df, image_id):\n    image_bboxes = df[df.image_id == image_id]\n    \n    bboxes = []\n    for _,row in image_bboxes.iterrows():\n        bboxes.append((row.bbox_xmin, row.bbox_ymin, row.bbox_width, row.bbox_height))\n        \n    return bboxes\n\ndef plot_image_examples(df, rows=3, cols=3, title='Image examples'):\n    fig, axs = plt.subplots(rows, cols, figsize=(10,10))\n    for row in range(rows):\n        for col in range(cols):\n            idx = np.random.randint(len(df), size=1)[0]\n            img_id = df.iloc[idx].image_id\n            \n            img = Image.open(TRAIN_DIR + img_id + '.jpg')\n            axs[row, col].imshow(img)\n            \n            bboxes = get_all_bboxes(df, img_id)\n            \n            for bbox in bboxes:\n                rect = patches.Rectangle((bbox[0],bbox[1]),bbox[2],bbox[3],linewidth=1,edgecolor='r',facecolor='none')\n                axs[row, col].add_patch(rect)\n            \n            axs[row, col].axis('off')\n            \n    plt.suptitle(title)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plot_image_examples(all_train_images)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"We can see images taken at different lighting conditions and plant maturity stages!\n\nCount number of bounding boxes per image:","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"# compute the number of bounding boxes per train image\nall_train_images['count'] = all_train_images.apply(lambda row: 1 if np.isfinite(row.width) else 0, axis=1)\ntrain_images_count = all_train_images.groupby('image_id').sum().reset_index()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"all_train_images.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_images_count.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def hist_hover(dataframe, column, colors=[\"#94c8d8\", \"#ea5e51\"], bins=30, title=''):\n    hist, edges = np.histogram(dataframe[column], bins = bins)\n    \n    hist_df = pd.DataFrame({column: hist,\n                             \"left\": edges[:-1],\n                             \"right\": edges[1:]})\n    hist_df[\"interval\"] = [\"%d to %d\" % (left, right) for left, \n                           right in zip(hist_df[\"left\"], hist_df[\"right\"])]\n\n    src = ColumnDataSource(hist_df)\n    plot = figure(plot_height = 400, plot_width = 600,\n          title = title,\n          x_axis_label = column,\n          y_axis_label = \"Count\")    \n    plot.quad(bottom = 0, top = column,left = \"left\", \n        right = \"right\", source = src, fill_color = colors[0], \n        line_color = \"#35838d\", fill_alpha = 0.7,\n        hover_fill_alpha = 0.7, hover_fill_color = colors[1])\n        \n    hover = HoverTool(tooltips = [('Interval', '@interval'),\n                              ('Count', str(\"@\" + column))])\n    plot.add_tools(hover)\n    \n    output_notebook()\n    show(plot)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"hist_hover(train_images_count, 'count', title='Number of wheat spikes per image')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Most of the images have 20-50 wheat spikes on them.\n\nLet's plot some examples with small number of spikes per image:","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"less_spikes_ids = train_images_count[train_images_count['count'] < 10].image_id\nplot_image_examples(all_train_images[all_train_images.image_id.isin(less_spikes_ids)], title='Example images with small number of spikes')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"These are some very strange examples:\n\n1. on some of the images all we see is the ground;\n2. some of the images are just zoomed in a lot.\n","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"Plot the images with many spikes:","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"many_spikes_ids = train_images_count[train_images_count['count'] > 100].image_id\nplot_image_examples(all_train_images[all_train_images.image_id.isin(many_spikes_ids)], title='Example images with large number of spikes')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"3. Area of bounding boxes:","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"# compute bounding box areas\nall_train_images['bbox_area'] = all_train_images['bbox_width'] * all_train_images['bbox_height']","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# plot a histogram of bounding box areas\nhist_hover(all_train_images, 'bbox_area', title='Area of a single bounding box')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"The maximum area of bounding box:","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"all_train_images.bbox_area.max()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"The distribution of individual areas of bounding boxes has a very long tail. It would be interesting to look at the images with those large bounding boxes.\n\nLet's plot some examples of large bounding boxes:","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"large_boxes_ids = all_train_images[all_train_images['bbox_area'] > 200000].image_id\nplot_image_examples(all_train_images[all_train_images.image_id.isin(large_boxes_ids)], title='Example images with large bbox area')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"What are these anomally large bounding boxes?? I think those should be removed while training!!!\n\nSimilarly, let's look at very small bounding boxes:","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"min_area = all_train_images[all_train_images['bbox_area']> 0].bbox_area.min()\nprint('The smallest bounding box area is {}'.format(min_area))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"small_boxes_ids = all_train_images[(all_train_images['bbox_area'] < 50) & (all_train_images['bbox_area'] > 0)].image_id\nplot_image_examples(all_train_images[all_train_images.image_id.isin(small_boxes_ids)], title='Example images with large bbox area')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"If you look very close, you can probably see those tinyest bounding boxes near the corners and borders of the images. Probably, the boundries were drawn first, than the images were cut into several ones. That is why we see those strange small bounsing boxes in the corners.\n\nIt is not necessary to clean these, because they won't have much effect on the IOU metric.\n\n4. Area of bounding boxes per image:","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"from PIL import Image\nimport numpy as np\nfrom skimage import io","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"img = io.imread('/kaggle/input/global-wheat-detection/train/a1ecd6a63.jpg')\nplt.imshow(img)\n#b6ab77fd7[834.0, 222.0, 56.0, 36.0]\t\n#826.0\t371.0\t102.0\t132.0\n#765.0\t580.0\t121.0\t129.0\t","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#print(img)\nimg1 = img[580:580+129, 765:765+121, :]\n#img11 = img1.resize((28,28))\nplt.imshow(img1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"img2 = img[371:371+132, 826:826+102, :]\n#gray_img2 = img2.convart('L')\nplt.imshow(img2)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"img3 = img[312:312+118,465:465+119,:]\nplt.imshow(img3)\n#465.0\t312.0\t119.0\t118.0","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","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}