{"cells":[{"metadata":{},"cell_type":"markdown","source":"# Introduction\n\nHi everyone, in this notebook we will elicit some insights from the data given in the pre-print. To find the pre-print please refer to this [link](https://arxiv.org/ftp/arxiv/papers/2005/2005.02162.pdf).\nAfter analysis of pre-print we will move to light data-preprocessing and end with some important augmentations....\n\nLets start with a funny meme... Although this is already used by my teammate @Yash Choudhary in his notebook, I could not stop myself from not using it... Do checkout his awesome notebook [here](https://www.kaggle.com/yashchoudhary/gwd-eda-and-starter-code-beginner-friendly)\n\n![IMG](http://www.global-wheat.com/wp-content/uploads/2020/04/ILLU_01_EN.jpg)","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"<a class=\"anchor\" id=\"toc\"></a>\n<div style=\"background: #f9f9f9 none repeat scroll 0 0;border: 1px solid #aaa;display: table;font-size: 95%;margin-bottom: 1em;padding: 20px;width: 600px;\">\n<h1>Contents</h1>\n<ul style=\"font-weight: 700;text-align: left;list-style: outside none none !important;\">\n<li style=\"list-style: outside none none !important;font-size:17px\"><a href=\"#1\">1 Preparing the ground</a></li>\n<li style=\"list-style: outside none none !important;font-size:17px\"><a href=\"#2\">2 Pre-print Analysis</a></li>\n<li style=\"list-style: outside none none !important;font-size:17px\"><a href=\"#3\">3 EDA</a></li>\n<li style=\"list-style: outside none none !important;font-size:17px\"><a href=\"#4\">4 Acknowledgements</a></li>\n</ul>\n</div>","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"# Preparing the ground \n<a class=\"anchor\" id=\"1\"></a>\n<a href=\"#toc\"><img src= \"https://upload.wikimedia.org/wikipedia/commons/thumb/2/20/Circle-icons-arrow-up.svg/1200px-Circle-icons-arrow-up.svg.png\" style=\"width:20px;hight:20px;float:left\" >        Back to the table of contents</a>","execution_count":null},{"metadata":{"_kg_hide-output":true,"trusted":true},"cell_type":"code","source":"!pip install pandas-profiling","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import pandas as pd\nimport numpy as np \nimport cv2\nimport os\nimport seaborn as sns\nimport folium\nfrom PIL import Image\nimport albumentations as A\nimport matplotlib.pyplot as plt\nimport matplotlib.image as mpimg\nfrom pandas_profiling import ProfileReport\nimport plotly.express as px\nimport plotly.graph_objs as go\nfrom plotly.subplots import make_subplots\nfrom plotly.offline import download_plotlyjs,init_notebook_mode,plot,iplot\nimport warnings\n\nwarnings.filterwarnings(\"ignore\")\ninit_notebook_mode(connected=True)\nsns.set_style('whitegrid')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Firstly, there are 3 tables in the pre-print out of which two give a lot of important insights so I will make tables forboth and later we will analyze it","execution_count":null},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"df = pd.DataFrame()\ndf['Sub_Dataset_name'] =  ['UTokyo_1','UTokyo_2','Arvalis_1','Arvalis_2','Arvalis_3',\n                           'INRAE_1','USask_1','RRes_1','ETHZ_1','NAU_1','UQ_1']\n\ndf['Institution'] = ['NARO & UTokyo','NARO & UTokyo','Arvalis','Arvalis','Arvalis',\n                     'INRAE','University of Saskatchewan','Rothamsted Research','ETHZ',\n                     'Nanjing Agric.University','UQueensland']\n\ndf['Country'] = ['Japan','Japan','France','France','France',\n                 'France','Canada','UK','Switzerland','China','Australia']\n\ndf['Lat'] = ['36.0N', '42.8N','43.7N','43.7N','49.7N',\n             '43.5N','52.1N','51.8N','47.4N','31.6N','27.5S']\n\ndf['Long'] = ['140.0E','143.0', '5.8E','5.8E', '3.0E', '1.5E',\n             '106.W', '0.36W','8.6E','119.4E','152.3E']\n\ndf['Year'] = [2018,2016,2017,2019,2019,2019,\n              2019,2016,2018,2018,2016]\n\ndf['Nb_Of_Dates'] = [3,6,3,1,3,1,1,1,1,1,1]\n\ndf['Targeted_stages'] = ['Post-flowering','Flowering','Post-flowering-Ripening',\n                         'Post-flowering','Post-flowering-Ripening','Post-flowering',\n                         '','','',\"Flowering\",'Flowering-Ripening']\n\ndf['Row_Spacing'] = [15,12.5,17.5,17.5,17.5,\n                     16,30.5,0,12.5,20,22]\n\ndf['Sowing_density'] = [186,200,300,300,300,300,\n                       250,350,400,300,150]\n\ndf['Nb_of_Genotypes'] = [66,1,20,20,4,7,16,6,354,5,8]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"stats = pd.DataFrame()\nstats['Sub_Dataset_name_'] = df['Sub_Dataset_name']\n\nstats['Nb_of_acquired_images'] = [994,30,239,51,152,\n                                  44,100,72,375,20,142]\n\nstats['Nb_patch_per_image'] = [1,4,6,4,4,4,2,6,2,1,1]\n\nstats['Original_GSD'] = [0.43,0.6,0.23,0.56,0.56,\n                         0.56,0.45,0.33,0.55,0.21,0.2]\n\nstats['Sampling_factor'] = [1,2,0.5,2,2,2,1,1,1,1,0.5]\n\nstats['Used_GSD'] = [0.43,0.3,0.46,0.28,0.28,0.28,\n                    0.45,0.33,0.55,0.21,0.4]\n\nstats['Nb_labelled_images'] = [994,120,1055,204,608,176,\n                               200,432,747,20,142]\n\nstats['Nb_labelled_heads'] = [29174,3263,45716,4179,\n                             16665,3701,5737,20236,\n                             51489,1250,7035]\n\nstats['Average_heads_per_image'] = [29,27,43,20,27,21,\n                                   29,47,69,63,50]","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Pre-print Analysis\n<a class=\"anchor\" id=\"2\"></a>\n<a href=\"#toc\"><img src= \"https://upload.wikimedia.org/wikipedia/commons/thumb/2/20/Circle-icons-arrow-up.svg/1200px-Circle-icons-arrow-up.svg.png\" style=\"width:20px;hight:20px;float:left\" >        Back to the table of contents</a>","execution_count":null},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"img = mpimg.imread('../input/sources-image/sources_image.png')\nplt.figure(figsize=(20,10))\nplt.imshow(img)\nplt.axis('off')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Before going into analysis we can see image from each source in the above picture \n\n**NOTE: Arvalis3** is missing from the above image","execution_count":null},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"train = pd.read_csv('../input/global-wheat-detection/train.csv')\nprint(\"Sources of train data\",train['source'].unique())\nprint(\"\\nSources of test data ['UTokyo1','UTolyo2','NAU_1','UQ_1']\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Now we will have a glimpse of both the tables","execution_count":null},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"df.head(6).T","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"stats.head(8).T","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Now we will see some get some important inferences from the both the tables.\n\nFor convinience I will combine both the tables into one","execution_count":null},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"print('First table shape ', df.shape)\nprint('Second table shape ',stats.shape)\n\ndf = pd.concat([df, stats], axis=1, sort=False)\ndf.head()\ndf.drop(['Sub_Dataset_name_'],axis=1,inplace=True)\nprint('Merged table shape ', df.shape)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"df.head().T","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Let us understand what some of the important columns are: \n\n* **Lat and Long-** This tells us about the lattitude and longitude where the pictures are taken.\n* **Targeted Stages-** There are 4 stages given in the paper and some are left blank (we will look into this later)\n* **Row Spacing-** The gap present between each row of the crop the range being 12.5 cm (ETHZ_1) to 30.5 cm (USask_1) \n* **Sowing Density-** The density of seeds per m^2 they are classified into low-medium-high\n* **Genotypes-** The different types of genetic constitution (no much details are given in the paper)\n* **Patch_per_image-** Each image originally was of higher resolution which went through a series of transformations and cropped to 1024x1024. The number of cuts made at the end to the original image is patches_per_image\n* **GSD-** GSD stands for Ground Sampling distance. The ground sample distance is the distance between center points of each sample taken of the ground. Since we’re talking about digital photos, each sample is a pixel.\n* **Used_GSD-** divide original GSD by sampling factor\n","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"Now we will make a report of all the data then we will dive deep into each column to understand in depth","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"df.profile_report()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"The pandas profiling gives a detailed analysis of the whole dataframe...\n\nFurther, we will dive deep into each column of the dataframe and see how it can help us understand things better","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"# EDA\n<a class=\"anchor\" id=\"3\"></a>\n<a href=\"#toc\"><img src= \"https://upload.wikimedia.org/wikipedia/commons/thumb/2/20/Circle-icons-arrow-up.svg/1200px-Circle-icons-arrow-up.svg.png\" style=\"width:20px;hight:20px;float:left\" >        Back to the table of contents</a>","execution_count":null},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"wheat_count = df.groupby(['Country']).sum().reset_index()\ndata = dict(type ='choropleth',\n            locations = wheat_count['Country'],\n            locationmode = 'country names',\n            colorscale='sunsetdark',\n            text = wheat_count['Country'],\n            z = wheat_count['Nb_labelled_heads'],\n            zmin=1250,\n            colorbar = {'title':'Wheathead Count'}\n           )\nlayout = dict(title ='Wheatheads per country',title_x=0.45, \n              geo = dict(landcolor = 'rgb(250, 250, 250)',projection={'type':\"natural earth\"},\n                   oceancolor='rgb(0,191,255)',showocean=True,showcountries=True))\nchoromap = go.Figure(data=[data],layout=layout)\niplot(choromap)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"To get more detailed information please hover over the map","execution_count":null},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"wheat_cont = df[['Sub_Dataset_name','Row_Spacing','Sowing_density','Nb_labelled_heads','Nb_labelled_images','Country','Year']]\nwheat_cont['continent'] = ['Asia','Asia','Europe','Europe','Europe','Europe',\n                           'North America','Europe','Europe','Asia','Australia']\nwheat_cont = wheat_cont.sort_values(by=['continent'])\n\nfig, ax = plt.subplots(1,1, figsize=(14, 7), dpi=100)\nax.set_ylim(0, 52000)\nheight = 40000\nax.bar(wheat_cont['Sub_Dataset_name'], wheat_cont['Nb_labelled_heads'],  color=\"#e0e0e0\", width=0.52, edgecolor='black')\ncolor =  ['green',  'blue',  'orange',  'red']\nspan_range = [[0, 2], [3,3], [4, 9], [10,11]]\nfor idx, sub_title in enumerate(['Asia', 'Aus', 'Europe', 'N America']):\n    ax.annotate(sub_title,xy=(sum(span_range[idx])/2 ,height),\n                    xytext=(0,0), textcoords='offset points',\n                    va=\"center\", ha=\"center\",\n                    color=\"w\", fontsize=16, fontweight='bold',\n                    bbox=dict(boxstyle='round4', pad=0.4, color=color[idx], alpha=0.6))\n    ax.axvspan(span_range[idx][0]-0.4,span_range[idx][1]+0.4,  color=color[idx], alpha=0.07)\n    ax.set_title(f'Continent wise wheatheads', fontsize=15, fontweight='bold', position=(0.50, 1.0+0.03))\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"The above plot shows us clearly that most of the data is from Europe and `ETHZ_1` has most number of wheat heads which is Switzerland\n\nNow let us do the same analysis for `No. of Images`","execution_count":null},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"data = dict(type ='choropleth',\n            locations = df['Country'],\n            locationmode = 'country names',\n            colorscale = 'hsv',\n            text = df['Country'],\n            z = df['Nb_labelled_images'],\n            zmin=20,\n            colorbar = {'title':'Number of Images'}\n           )\nlayout = dict(title ='Images produced per country',title_x=0.45, \n              geo = dict(landcolor = 'rgb(250, 250, 250)',projection={'type':\"natural earth\"},\n                   oceancolor='rgb(85, 173, 240)',showocean=True,showcountries=True))\nchoromap = go.Figure(data=[data],layout=layout)\niplot(choromap)","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"fig, ax = plt.subplots(1,1, figsize=(14, 7), dpi=100)\nax.set_ylim(0, 1100)\nheight = 900\nax.bar(wheat_cont['Sub_Dataset_name'], wheat_cont['Nb_labelled_images'],  color=\"#e0e0e0\", width=0.52, edgecolor='black')\ncolor =  ['green',  'blue',  'orange',  'red']\nspan_range = [[0, 2], [3,3], [4, 9], [10,11]]\nfor idx, sub_title in enumerate(['Asia', 'Aus', 'Europe', 'N America']):\n    ax.annotate(sub_title,xy=(sum(span_range[idx])/2 ,height),\n                    xytext=(0,0), textcoords='offset points',\n                    va=\"center\", ha=\"center\",\n                    color=\"w\", fontsize=16, fontweight='bold',\n                    bbox=dict(boxstyle='round4', pad=0.4, color=color[idx], alpha=0.6))\n    ax.axvspan(span_range[idx][0]-0.4,span_range[idx][1]+0.4,  color=color[idx], alpha=0.07)\n    ax.set_title(f'Continent wise Images', fontsize=15, fontweight='bold', position=(0.50, 1.0+0.03))\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"This plot shows us there are lot of images from `Arvalis_1`...\nAlthough the previous plot told us that there were a lot of wheat heads from Switzerland the number of Images are less","execution_count":null},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"corr = df.corr()\nmask = np.zeros_like(corr)\nmask[np.triu_indices_from(mask)] = True\nwith sns.axes_style(\"white\"):\n    f, ax = plt.subplots(figsize=(12, 12))\n    ax = sns.heatmap(corr,mask=mask,square=True,annot=True,fmt='0.2f',linewidths=.8,cmap=\"viridis\",robust=True)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"There are many inferences that can be drawn the above heatmap. Some of them are:\n* `GSD` and `Genotypes` both have high positive correlation which says higher `GSD` increases `Genotypes`\n* `Used_GSD` and `Number_of_labelled_images` are positively corellated which gives an indication that the distance from ground increases when the wheat heads are in a larger number.\n* labelled_heads with labelled_images are obvious to understand why they are highly corellated","execution_count":null},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"fig = px.scatter_matrix(df, dimensions=[\"Row_Spacing\", \"Sowing_density\",\"Average_heads_per_image\"], color='Country',\n                        size='Nb_labelled_heads')\nfig.update_layout(height=800, width=800)\nfig.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Some inferences from above plot:\n**NOTE:** We can see `row_spacing` as 0 in one case there was no data for this so I added it as 0\n* Switzerland has `high_sowing_density` but relatively low `row_spacing` so we can see a large bubble with lot of wheat heads\n* Bubble size increases from low to high with average heads per image.\n* `Sowing_density` has somewhat linear correlation with `Average_heads_per_image`","execution_count":null},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"import plotly.express as px\nfig = px.scatter(wheat_cont, x='Row_Spacing', y=\"Nb_labelled_heads\",size='Sowing_density'\n           , color=\"continent\", hover_name=\"Country\", facet_col=\"continent\")\nfig.update_layout( width=850)\nfig.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"From the above plots we can see that Europe has highest`Row_spacing` followed by `Asia`\n### Most of the test data is from Asia and `Row_spacing` is also comparitive to Europe","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"fig = px.scatter(df, y=\"Row_Spacing\", x=\"Average_heads_per_image\", color=\"Sub_Dataset_name\",\n                  size='Sowing_density', hover_data=['Country'])\nfig.update_layout( title_text=\"Row_spacing vs Average_heads_per_image\")\nfig.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Please hover over the plot for additional information\n\nSome observations from the above interactive plot is that most of the `average_heads_per_image` are between 20-30. Also, as the `average_heads_per_image` increases the `sowing_density` also increases with one exception of **Australia**","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"Now we will find the top 5 RGB distributions in each of the 10 test images.","execution_count":null},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"TEST_DIR = '/kaggle/input/global-wheat-detection/test/'\nfor i,img in enumerate(os.listdir(TEST_DIR)):\n    print('Image Number:',i,\"---Image Name:\",img)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from sklearn.cluster import KMeans\n\ndef visualize_colors(cluster, centroids):\n    # Get the number of different clusters, create histogram, and normalize\n    labels = np.arange(0, len(np.unique(cluster.labels_)) + 1)\n    (hist, _) = np.histogram(cluster.labels_, bins = labels)\n    hist = hist.astype(\"float\")\n    hist /= hist.sum()\n\n    # Create frequency rect and iterate through each cluster's color and percentage\n    rect = np.zeros((50, 300, 3), dtype=np.uint8)\n    colors = sorted([(percent, color) for (percent, color) in zip(hist, centroids)])\n    start = 0\n    for (percent, color) in colors:\n        print(color, \"{:0.2f}%\".format(percent * 100))\n        end = start + (percent * 300)\n        cv2.rectangle(rect, (int(start), 0), (int(end), 50), \\\n                      color.astype(\"uint8\").tolist(), -1)\n        start = end\n    return rect","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"# Load image and convert to a list of pixels\nfor img in os.listdir(TEST_DIR):\n    ax = [None for _ in range(2)]\n    fig = plt.figure(figsize=(16, 8))\n    image = cv2.imread(TEST_DIR+img)\n#     print(TEST_DIR+img)\n    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n    reshape = image.reshape((image.shape[0] * image.shape[1], 3))\n    print('Image_name is :',img)\n    # Find and display most dominant colors\n    cluster = KMeans(n_clusters=5).fit(reshape)\n    visualize = visualize_colors(cluster, cluster.cluster_centers_)\n#     plt.imshow(image)\n    ax[0] = plt.subplot2grid((5,10), (1,4), colspan=5,rowspan=2)\n    plt.imshow(visualize)\n    plt.axis('off')\n    ax[1] = plt.subplot2grid((5,10), (0,0), colspan=4,rowspan=4)\n    plt.imshow(image)\n    plt.axis('off')\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"One might ask how is this helpful?\nLet me explain how. Using this we can find which source the Image belongs to. Once again how is that helpful?\nAs we know a lot of our test-data belongs to UTokyo1 we can simply use the probable RGB values as augmentations in our training and check if there is any improvements in our results.\n\nLets see Albumentations' RGBShift on a training image...","execution_count":null},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"TRAIN_PATH = '/kaggle/input/global-wheat-detection/train/'\ndef show(img1, img2):\n    plt.figure(figsize=(18,18))\n    plt.subplot(1, 2, 1)\n    plt.title('Augmented Image')\n    plt.imshow(img1)\n    plt.axis('off')\n    plt.subplot(1, 2, 2)\n    plt.title('Original Image')\n    plt.imshow(img2)\n    plt.axis('off')\n\ndef augment(aug, image):\n    return aug(image=image)['image']\n\ndef strong_aug_():\n    return A.Compose([A.RGBShift(r_shift_limit=29.71366007, g_shift_limit=34.93698225, b_shift_limit=13.99685498,p=1)])\naug = strong_aug_()\nimage= Image.open(TRAIN_PATH+'00333207f.jpg')\nimg= Image.fromarray(augment(aug,np.array(image)))\nshow(img, image)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Acknowledgements\n<a class=\"anchor\" id=\"4\"></a>\n<a href=\"#toc\"><img src= \"https://upload.wikimedia.org/wikipedia/commons/thumb/2/20/Circle-icons-arrow-up.svg/1200px-Circle-icons-arrow-up.svg.png\" style=\"width:20px;hight:20px;float:left\" >        Back to the table of contents</a>\n* [Yash's notebook for the meme](https://www.kaggle.com/yashchoudhary/gwd-eda-and-starter-code-beginner-friendly)\n* [Paper by GWD hosts](https://arxiv.org/ftp/arxiv/papers/2005/2005.02162.pdf)\n* [Plotly](https://plotly.com/)","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"## There will be more updates on this notebook. So please stay tuned.","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}