{"cells":[{"metadata":{},"cell_type":"markdown","source":"# Global Wheat Detection\n\nIn this challenge, we explore the detection of wheat heads in various pictures. Predictions take the form of BBoxes.\nIn this notebook, we will explore data, by visualizing a few training examples with the corresponding bboxed images.\n\n## Imports","execution_count":null},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"import matplotlib.pyplot as plt\nfrom matplotlib import patches\nimport numpy as np\nimport pandas as pd\nimport cv2\nimport os\nimport ast\nfrom scipy.stats import norm, kstest, describe\n\nIMG_PATH = \"/kaggle/input/global-wheat-detection/train\"\nSEED = 42\n\n\ntrain_df = pd.read_csv(\"/kaggle/input/global-wheat-detection/train.csv\")\nnp.random.seed(SEED)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"We randomly display multiple pictures without the bboxes.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"indexes = [np.random.randint(0, len(train_df)) for _ in range(8)]\n\nfig, ax = plt.subplots(2, 4, figsize=(20,10))\n\nfor i, idx in enumerate(indexes):\n    idx_row = int(i / 4)\n    idx_col = i % 4\n    \n    filename = train_df.iloc[idx, 0]\n    \n    ax[idx_row][idx_col].imshow(\n        cv2.imread(os.path.join(IMG_PATH, filename+\".jpg\"))\n    )\n    \n    for _, row in train_df[train_df[\"image_id\"] == filename].iterrows():\n        bbox = ast.literal_eval(row[\"bbox\"])\n        rect = patches.Rectangle((bbox[0],bbox[1]),bbox[2],bbox[3],linewidth=1,edgecolor='r',facecolor='none')\n        \n        ax[idx_row][idx_col].add_patch(rect)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Distribution of number of bbox per image\n\nWe will now study the statistics behind how many bboxes are found per image.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"val_count = train_df[\"image_id\"].value_counts()\nnp_val_count = val_count.to_numpy() # we obtain here an array that maps, for each image, how many bbox they have.\n#we now need to count how often a number of bbox/image is ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"empirical_mu = np.mean(np_val_count)\nempirical_sigma = np.std(np_val_count)\n\nunique_elements, count_elements = np.unique(np_val_count, return_counts=True)\nx_all = np.arange(-10, 120, 0.001) # entire range of x, both in and out of spec\ny2 = norm.pdf(x_all, empirical_mu, empirical_sigma)*len(np_val_count)\n\nfig = plt.figure(figsize=(20, 7))\nplt.xlabel(\"Count of the number of bbox\")\nplt.ylabel(\"Frequency of apparition of bbox count\")\n\nline = plt.plot(unique_elements, count_elements)\nline[0].set_label(f\"Frequency of bbox count per image (mean: {np.round(empirical_mu,2)}, std:{np.round(empirical_sigma, 2)})\")\nline = plt.plot(x_all, y2)\nline[0].set_label(f\"Normal approximation of the BBox distribution\")\n\nplt.legend()\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"kstest(count_elements, 'norm')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"We have an extremely small Pvalue for this Kolmogorov Smirnov Test, meaning that the number of bbox is **NOT** following Normal distribution at all.","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"## Explore images with the most and less boxes","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"max_filenames = val_count.index[0:4]\nmax_bboxes = val_count[0:4]\n\nmin_filenames = val_count.index[-5:-1]\nmin_bboxes = val_count[-5:-1]\n\nprint(f\"The file with the biggest amount of bbox is '{max_filenames[0]}' with {max_bboxes[0]} bboxes \\nwhile the file with the least amount of bbox is '{min_filenames[0]}' with {min_bboxes[0]} bbox\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fig_max, ax_max = plt.subplots(1, 4, figsize=(20,5))\nfig_min, ax_min = plt.subplots(1, 4, figsize=(20,5))\n\nfig_max.suptitle(\"Plots of images with the most BBoxes\")\nfig_min.suptitle(\"Plots of images with the least BBoxes\")\n\nfor i in range(len(max_filenames)):\n    \n    ax_max[i].imshow(\n        cv2.imread(os.path.join(IMG_PATH, max_filenames[i]+\".jpg\"))\n    ) # plotting image with the more bboxes\n    \n    ax_max[i].set_title(f\"'{max_filenames[i]+'.jpg'}' with {max_bboxes[i]} bboxes\")\n    \n    for _, row in train_df[train_df[\"image_id\"] == max_filenames[i]].iterrows():\n        bbox = ast.literal_eval(row[\"bbox\"])\n        rect = patches.Rectangle((bbox[0],bbox[1]),bbox[2],bbox[3],linewidth=1,edgecolor='r',facecolor='none')\n        \n        ax_max[i].add_patch(rect)\n    \n    ax_min[i].imshow(\n        cv2.imread(os.path.join(IMG_PATH, min_filenames[i]+\".jpg\"))\n    ) # plotting image with the more bboxes\n        \n    ax_min[i].set_title(f\"'{min_filenames[i]+'.jpg'}' with {min_bboxes[i]} bbox\")\n    \n    for _, row in train_df[train_df[\"image_id\"] == min_filenames[i]].iterrows():\n        bbox = ast.literal_eval(row[\"bbox\"])\n        rect = patches.Rectangle((bbox[0],bbox[1]),bbox[2],bbox[3],linewidth=1,edgecolor='r',facecolor='none')\n        \n        ax_min[i].add_patch(rect)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Distribution of BBox area\nWe will now explore the bboxes area and plot an approximated distribution","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"def list_to_area(l):\n    return l[2]*l[3]\n    \nareas = train_df[\"bbox\"].apply(lambda l: list_to_area(ast.literal_eval(l))).to_numpy()\ndescribe(areas)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"We see here multiple things:\n - **Min** and **max** values **far from each other** (*2* and *529788* respectively)\n - A very **high variance** of *34531214*\n - a **positive skewness**, meaning that most values are closer to the minimum of the areas' distribution than to the maximum\n \nWe will now scatter plot the areas width against the area height to see if we find any clusters/patterns.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"bboxes = train_df[\"bbox\"].apply(lambda l: ast.literal_eval(l)).to_numpy()\nbboxes","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"widths = [bbox[2] for bbox in bboxes]\nheights = [bbox[3] for bbox in bboxes]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.figure(figsize=(15,10))\nplt.xlabel(\"Width of a BBox\")\nplt.ylabel(\"Height of a BBox\")\nplt.title(\"Scatter plot of WIdth to Height ration of BBoxes\")\nplt.scatter(widths, heights)\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"We see here that BBoxes have very similar shapes, only a few outliers are to be found. We will now find and study these outliers.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"outliers = [(idx, bbox) for idx, bbox in enumerate(bboxes) if (bbox[2] > 600 or bbox[3] > 600)]\noutliers","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"outliers_idx, outliers_bboxes = list(zip(*outliers))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"outliers_idx, outliers_bboxes = list(outliers_idx), list(outliers_bboxes)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Plotting outliers with bigger boxes","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"fig, axs = plt.subplots(2,3, figsize=(15,10))\n\nfor i, idx in enumerate(outliers_idx):\n    \n    x = int(i/3)\n    y = i % 3\n    \n    bbox = outliers_bboxes[i]\n\n    filename = str(train_df.iloc[idx, 0])+\".jpg\"\n    \n    axs[x][y].imshow(\n        cv2.imread(\n            os.path.join(IMG_PATH,filename)\n        )\n    )\n    \n    rect = patches.Rectangle((bbox[0],bbox[1]),bbox[2],bbox[3],linewidth=1,edgecolor='r',facecolor='none')\n    axs[x][y].add_patch(rect)","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}