{"cells":[{"metadata":{},"cell_type":"markdown","source":"# RetinaNet for Global Wheat🌱 Head Detection\n\n> ### This Notebook is for Training of **Keras RetinaNet** for wheat head detection 🔍\n\n<hr>\n\n### For EDA and Image Data analysis📊 visit:\n### https://www.kaggle.com/akhileshdkapse/global-wheat-detection-comprehensive-eda\n\n### Table of contents\n* Data Loading\n* Mis-matched B.boxes fixection\n* Image Data Visulization\n* Data Per-Processing\n* Model Traning\n* Trained model Analysis/Visulization of test image data\n* Submission\n","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"## Data Loading","execution_count":null},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"import numpy as np \nimport pandas as pd \nimport os\nfrom glob import glob\nimport cv2\nimport ast\nfrom tqdm.notebook import tqdm\n\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n\nimport time\n\nimport random\nsns.set_style('whitegrid')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df= pd.read_csv('../input/global-wheat-detection/train.csv')\nprint('Totall Traning data: {} with {} unique images'.format(df.shape[0], len(df.image_id.unique())))\ndf.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def add_path(label):\n    path='../input/global-wheat-detection/train'\n    return os.path.join(path, label+'.jpg')\n\ndf['image_name']= df.image_id.apply(add_path)\ndf.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df.info()\n#bbox -- String","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df.bbox=df.bbox.apply(lambda x: ast.literal_eval(x))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df['x_min']= df.bbox.apply(lambda x: x[0])\ndf['y_min']= df.bbox.apply(lambda x: x[1])\ndf['x_max']= df.bbox.apply(lambda x: x[0]+ x[2])\ndf['y_max']= df.bbox.apply(lambda x: x[1]+ x[3])\ndf['prct_area_cov']= df.bbox.apply(lambda x: ((x[2]*x[3])/(1024.0*1024.0))*100)\ndf=df.drop('source', 1)\ndf.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Mis-matched B.boxes fixection\n### We have encountered with Mis-matched Large Bounding Boxes in certain images for our EDA NOTEBOOK...\n\n","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"![](https://www.kaggleusercontent.com/kf/41590794/eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0..wNU8w8SLUJMdER2nLmV0uA.bE7UWnqdhT5glaFaCMq4ReTOPK-XOCw2dZ_GRP_qdx-xLst2Df5bzmX3dvAiscihs5m0Dv8N5uZwVn_L8GPwXNfCliZgPsnBBxoJU2Ubxz0j7hdI1_H4BxpWM1aFKohGmuL7vh1kgunH3UDua8i_VHxmamOT3RE3ucyNAkH567mMcNIn3P-Nil4_5QuUtbZXzLh-ovee_nvMd1rPU_KDJqap8d5-gkixkxUMlX4oyb2j1qP3-9Dx5hM6RaaHo15eLUPevPZcNxdgNTj_xJbJ2fkxQzKfe8qaYAPoDwMh16qQUzKyq2eGf9o2MSWoF97F-pjOjHf_R8ONGrdnzD0vAVkCanJjOgUJ_uU8kfV83koFj63IpNld9SwO_OwBLQjANvdfA2ifq3Ek78UGfxPxh_cX6C0hYbZmB0GTpIYkhZjEBYQ3cq6M6GFoRzP6VcwU86ZnOa23KcFSGUnlV4DQxvfBaPf4e2dqEdyy80xLShyyP0PW7VgHXRVcIGKLiceLMMiW68pR4WaAEGFfDUHUF4tzVhD5-UU8cXKhCl5z--2q3bV2Hay5sZodpU61CS0UgdLkBqQjqcyH3F6HS_Iq2Xbso-IMHAdXtsk03yXNrN1ekn32tkulIGLA_PSd6f3S6zbgdIP1Hz7c8ZBSnSlXLyCWM-wOponEhFc7r1e_9rU.OQH__iA9D8ymBfeK7ornKg/__results___files/__results___38_2.png)\n\n\n> ### Let's fix it ","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.figure(figsize=(20,6))\nsns.kdeplot(df.prct_area_cov.values, shade=True)\nplt.xlabel('Percent Area covered by Bounding Box', size=15); plt.ylabel('Probability Density', size=15)\nplt.title('Area per BBox Distribution', size=20)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### B.B0x Area outliers:\n* We can see most of the **Bounding Boxes are coverd less than 3% of totall area** on Actuall Image.\n* **Outliers** are those BBoxes which have **coverd more than 5%** of tatall area of Image, as WHEAT HEAD covers less space in an image.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"print('Rows we lost:', (df[(df.prct_area_cov<8) & (df.prct_area_cov>0.4)].shape[0]))\ndf=df[(df.prct_area_cov<6) & (df.prct_area_cov>0.3)]\ndf=df.reset_index()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.figure(figsize=(20,6))\nsns.kdeplot(df.prct_area_cov.values, shade=True)\nplt.xlabel('Percent Area covered by Bounding Box', size=15); plt.ylabel('Probability Density', size=15)\nplt.title('Area per BBox Distribution', size=20)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Image Data Visulization","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"def load(path, resize=False, gray=False):\n    img= cv2.imread(path)\n    if resize:\n        img= cv2.resize(img, (500,500))\n    if gray:\n        img= cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\n    else:\n        img= cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n    return img\n\ndef draw_rec(img, boxes):\n    for box in boxes:\n        x,y,w,h= box\n        x=int(x); y=int(y); w=int(w); h= int(h)\n        img= cv2.rectangle(img, (x,y), (x+w, y+h), color=(16, 228, 214), thickness=3)\n    return img","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def draw_rand():\n    index= random.randint(0, (df.shape[0]))\n    label= df.image_id[index]\n    data= df[df.image_id== label]\n    path= '../input/global-wheat-detection/train'\n    path= os.path.join(path, (label+'.jpg'))\n    img= load(path)\n    img2= img.copy()\n    \n    img2= draw_rec(img2, data.bbox.values)\n    f, ax= plt.subplots(1,2, figsize=(25,12))\n    ax[0].imshow(img, aspect='auto'); ax[0].grid(False)\n    ax[1].imshow(img2, aspect='auto'); ax[1].grid(False)\n\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"draw_rand()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"draw_rand()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Data Per-Processing \n\n### Keras RetinaNet  https://github.com/fizyr/keras-retinanet","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"df['class_name']= 'wheat_head'\ndf.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print('Original dataframe shape',df.shape)\ntest=df.image_id.unique()[-10:]\ntest","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_test= pd.DataFrame([])\n\nfor _id in tqdm(test):\n    df_2=df[df.image_id==_id]\n    df_test= pd.concat([df_test, df_2])\n    \ndf_train= df\nfor _id in tqdm(test):\n    df_train=df_train[df_train.image_id!=_id]\n    \ndf_train=df_train.reset_index()\ndf_test=df_test.reset_index()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_test.shape, df_train.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_train= df_train[['image_name','x_min', 'y_min', 'x_max', 'y_max', 'class_name']]\nprint(df_train.shape)\ndf_train.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_train.iloc[:,1:-1]=df_train.iloc[:,1:-1].astype('int32')\ndf_train.image_name= df_train.image_name.apply(lambda x: '../'+x)\ndf_train.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Model Traning","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"!git clone https://github.com/fizyr/keras-retinanet.git","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"%cd keras-retinanet/\n!pip install .","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!python setup.py build_ext --inplace","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import tensorflow\nfrom keras_retinanet import models\nfrom keras_retinanet.utils.image import read_image_bgr ,preprocess_image, resize_image\nfrom keras_retinanet.utils.visualization import draw_box, draw_caption\nfrom keras_retinanet.utils.colors import label_color\n\nimport requests\nimport urllib","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_train.to_csv('annotations.csv', index=False, header=None)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"with open(\"classes.csv\",\"w\") as file:\n    file.write(\"wheat_head,0\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"PRETRAINED_MODEL = 'snapshots/_pretrained_model.h5'\n\nURL_MODEL = 'https://github.com/fizyr/keras-retinanet/releases/download/0.5.1/resnet50_coco_best_v2.1.0.h5'\nurllib.request.urlretrieve(URL_MODEL, PRETRAINED_MODEL)\n\nprint('Downloaded pretrained model to ' + PRETRAINED_MODEL)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!keras_retinanet/bin/train.py --freeze-backbone \\\n  --random-transform \\\n  --weights {PRETRAINED_MODEL} \\\n  --batch-size 8 \\\n  --steps 200 \\\n  --epochs 9 \\\n  csv annotations.csv classes.csv","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Trained model Analysis/Visulization of test image data","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"!ls snapshots","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model_path = os.path.join('snapshots', sorted(os.listdir('snapshots'), reverse=True)[0])\n\nmodel = models.load_model(model_path, backbone_name='resnet50')\nmodel = models.convert_model(model)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"%cd ../","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def perd_from_model(path, th=0.5, box_only=False):\n    # load image\n    image = read_image_bgr(path)\n\n    # copy to draw on\n    draw = image.copy()\n    draw = cv2.cvtColor(draw, cv2.COLOR_BGR2RGB)\n\n    # preprocess image for network\n    image = preprocess_image(image)\n    image, scale = resize_image(image)\n    print('scale', scale)\n\n    # process image\n    start = time.time()\n    boxes, scores, labels = model.predict_on_batch(np.expand_dims(image, axis=0))\n    print(\"processing time: \", time.time() - start)\n\n    # correct for image scale\n    boxes /= scale\n    \n    if box_only:\n        return scores, boxes\n\n    # visualize detections\n    for box, score, label in zip(boxes[0], scores[0], labels[0]):\n    # scores are sorted so we can break\n        if score < 0.5:\n            break\n\n        color = label_color(label)\n\n        b = box.astype(int)\n        draw_box(draw, b, color=color)\n    return draw\n        \n    ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def visu_test(df_test):\n    label=test[np.random.randint(0,9)]\n    data= df_test[df_test.image_id== label]\n    path= '../input/global-wheat-detection/train'\n    path= os.path.join(path, (label+'.jpg'))\n    img= load(path)\n    img2= img.copy()\n    \n    img2= draw_rec(img2, data.bbox.values)\n    perd= perd_from_model(path, 0.3)\n    \n    f, ax= plt.subplots(1,3, figsize=(35,12))\n    ax[0].imshow(img, aspect='auto'); ax[0].grid(False)\n    ax[1].imshow(img2, aspect='auto'); ax[1].grid(False)\n    ax[2].imshow(perd, aspect='auto'); ax[2].grid(False)\n    \n    ax[0].set_title('Original Image', size=24)\n    ax[1].set_title('Original Image with B.boxes', size=24)\n    ax[2].set_title('Predicted B.boxes with Image', size=24)\n    plt.show()\n    ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"visu_test(df_test)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"visu_test(df_test)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"visu_test(df_test)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"visu_test(df_test)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Submission","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"sub=pd.read_csv('../input/global-wheat-detection/sample_submission.csv')\nsub","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sub.PredictionString[0]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def perdict(label):\n    string= ''\n    path='../input/global-wheat-detection/test'\n    path= os.path.join(path, (label+'.jpg'))\n    score, boxes= perd_from_model(path, box_only=True, th=0.3)\n    \n    string=''\n    for s, b in zip(score[0], boxes[0]):\n        if s <0.3:\n            break\n        string+= '{} {} {} {} {} '.format(s, int(b[0]), int(b[1]), int(b[2]-b[0]), int(b[3]-b[1]))\n    return string\n    ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sub['PredictionString']= sub.image_id.apply(perdict)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sub","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sub.PredictionString= sub.PredictionString.apply(lambda x: x[:-1])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sub.to_csv('/kaggle/working/submission.csv',index=False)","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}