{"cells":[{"metadata":{},"cell_type":"markdown","source":"# <center> You Only Look Once</center>\n\n<center><img src='https://lh3.googleusercontent.com/jakaa8Y2SL36NE0eEXsRTtxiyj-zEdaAUA2UTnu3hrVVnSDfnBOJvOz2VXTQVHbHeA'/></center>","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"# What has inspired me to write this notebook?\n\n- Since the time i participated in Global [Wheat Detection](kaggle.com/c/global-wheat-detection) challenge which is about ```Identify wheat heads using image analysis```.One Algorithms/Model @YOLOv5 stand out among other models. So i decide to give my shot to model, One thing to mention here before this notebook i never actually used __YOLOv5__. \n\n- So this notebook is suits to every beginner who are planing to learn about ```YOLOv5```.\n\n- Here my approach to just ease out their initial journey.[](http://)","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"# First and Foremost","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"Before we deep dive in to coding and analysis part first you have to understand **what is this YOLO Series of models actually is**. \n\n__Question__: What is YOLO?\n\n__Answer__: You only look once (YOLO) is a state-of-the-art, real-time object detection system.The biggest advantage of using YOLO is its superb speed – it’s incredibly fast and can process 45+ frames per second(```The number of consecutive full-screen images that are displayed each second```). \n\n<center>FPS</center>\n<img src=\"https://helpx.adobe.com/in/animate/using/time/_jcr_content/main-pars/image_1268876148.img.jpg/FPS.jpg\" height=300 width=500/>\n<center>________________________________________________________________________________________________</center>\n\n<img src=\"https://miro.medium.com/max/1300/1*uMlkXIMNF4VIZoi85NZ3aQ.png\" height=300 width=500/>\n\n<br>\n\n- YOLOv5: State-of-the-art object detection at ~__140 FPS__.\n\nWhen we are talking about real-time object detection speed is very important factor. For the sake of understanding a frame rate of __24 FPS__ is commonly used for __film__ since it creates a smooth appearance. Many video cameras record in __30 or 60 FPS__, which provides even smoother motion.\n\n[Read more about FPS](https://techterms.com/definition/fps#:~:text=Stands%20for%20%22Frames%20Per%20Second,that%20are%20displayed%20each%20second.&text=A%20frame%20rate%20of%2024,which%20provides%20even%20smoother%20motion.)","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"# How It Works","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"Here i am not gonna get in to every nity-grity functionality of yolo let's understand it very simply. \n\n\nIf you want to read more about functionality of yolo i highly recommend going through these three blogs of Analytics Vidhya.\n\n- > (1) [A Step-by-Step Introduction to the Basic Object Detection Algorithms (Part 1)](https://www.analyticsvidhya.com/blog/2018/10/a-step-by-step-introduction-to-the-basic-object-detection-algorithms-part-1/)\n\n- > (2) [A Practical Implementation of the Faster R-CNN Algorithm for Object Detection (Part 2)](https://www.analyticsvidhya.com/blog/2018/11/implementation-faster-r-cnn-python-object-detection/)\n\n- > (3) [A Practical Guide to Object Detection using the Popular YOLO Framework](https://www.analyticsvidhya.com/blog/2018/12/practical-guide-object-detection-yolo-framewor-python/)\n\n\n```Let's understand working in very simple terms.```\n\nPrior detection systems repurpose __classifiers or localizers__ to perform detection. They apply the model to an image at multiple locations and scales. High scoring regions of the image are considered detections.\n\nYolo use a totally different approach. It apply a single neural network to the full image. This network divides the image into regions and predicts bounding boxes and probabilities for each region. These bounding boxes are weighted by the predicted probabilities.\n\n<img src='https://pjreddie.com/media/image/sayit.jpg' height=300 width=350/>\n\n__YOLO model__ has several advantages over classifier-based systems. It looks at the whole image at test time so its predictions are informed by global context in the image. It also makes predictions with a single network evaluation unlike systems like ```R-CNN which require thousands for a single image```. This makes it extremely fast, more than __1000x faster than R-CNN and 100x faster than Fast R-CNN__. \n\n- See the paper of [YOLOv3(version 3)](https://pjreddie.com/media/files/papers/YOLOv3.pdf) for more details on the full system.","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"# What's New in Version 5 ?\n\n- Ultralytics has released YOLOv5, with comparable AP and faster inference times than YOLOv4.early results show it runs inference extremely fast, weights can be exported to mobile, and it achieves state of the art on COCO.\n\n- YOLOv5 uses a few tricks to improve training and increase performance, including: multi-scale predictions, a better backbone classifier, and more. See YOLOv5 paper for more details on the full system.\n\n-  YOLOv5 is written in the Ultralytics PyTorch framework, which is very intuitive to use and inferences very fast.YOLOv5 is certainly easier to use and it is very performant on custom data  \n\n- [Ultralytics YOLOv5 Repo](https://github.com/ultralytics/yolov5)\n\n- [Writeup: YOLOv5 is Here: State-of-the-Art Object Detection at 140 FPS](https://blog.roboflow.ai/yolov5-is-here/)\n\n- [Tutorial: Training YOLOv5 on a Custom Dataset](https://blog.roboflow.ai/how-to-train-yolov5-on-a-custom-dataset/)\n\n- [YOLOv5 Colab Notebook](https://colab.research.google.com/drive/1gDZ2xcTOgR39tGGs-EZ6i3RTs16wmzZQ)","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"# Practical Implementation of YOLOv5","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"Enough for the theoritical portion let's come to the practical implementation of YOLOv5 and lean how come we implement it to [Wheat Detection challenge](kaggle.com/c/global-wheat-detection).","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"This implementation of YOLOv5 is inspried from [Venelin Valkov](https://www.youtube.com/watch?v=XNRzZkZ-Byg) work( one of the best explaination of YOLOv5 available on internet).\n- Subscribe his youtube channel\n","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"## Here’s what we’ll go over:\n\n- Install required libraries\n- Build a custom dataset in YOLO format\n- Learn about YOLO model family history\n- Fine-tune the YOLOv5 model\n- Evaluate the model\n- Look at some predictions","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"## YOLOv5","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"YOLOv5 is doing good job in the leaderboard so i decide to give it a try, And as i am applying YOLO for object detection for the first time, After reading multiple notebooks still i struggle a lot to make something of my own using Pretrained weights of YOLOv5.\n\n- So i decide to takedown a naive approach to  every signle step for training a YOLOv5 model for 'Wheat Head Detection Competition.\n\n- This notebook is insprired and multiple kernels all are mentiond in the notebook. Check them too.","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"# Let's Get Started","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"_(Remember to choose GPU in Runtime if not already selected. Runtime --> Change Runtime Type --> Hardware accelerator --> GPU)_","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"from IPython.display import Image, clear_output  # to display images","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# import required dependencies\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport os\nfrom tqdm.auto import tqdm\nimport shutil as sh\n\nimport matplotlib.pyplot as plt\n\n%matplotlib inline","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Clone the github repo\n\n\n- \nThis repository represents Ultralytics open-source research into future object detection methods.All code and models are created by Ultralytics. \n\n- Here i used little modified version of to just avoid Pytorch version error. ","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"- <font color='red'>Before you clone this repo make sure you turn the ```INTERNET``` of you kaggle notebook.</font>\n\nIn your notebook, see:\n\n1. 👌 Settings > Internet (set on)","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"!git clone https://github.com/AIVenture0/yolov5.git\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# check for the cloned repo\n!ls -R","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# move all the files of YOLOv5 to current working directory\n!mv yolov5/* ./\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# check for all the files in the current working directory\n!ls","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Install Dependencies\n\n- All the required dependencies are saved in requirements.txt file to install all of then once run ","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"!pip install -r requirements.txt","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# 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":{"trusted":true},"cell_type":"code","source":"# read the training data.\n\n\ndf = pd.read_csv('../input/global-wheat-detection/train.csv')\nbboxs = np.stack(df['bbox'].apply(lambda x: np.fromstring(x[1:-1], sep=',')))\nfor i, column in enumerate(['x', 'y', 'w', 'h']):\n    df[column] = bboxs[:,i]\ndf.drop(columns=['bbox'], inplace=True)\ndf['x_center'] = df['x'] + df['w']/2\ndf['y_center'] = df['y'] + df['h']/2\ndf['classes'] = 0\nfrom tqdm.auto import tqdm\nimport shutil as sh\ndf = df[['image_id','x', 'y', 'w', 'h','x_center','y_center','classes']]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"index = list(set(df.image_id))\nlen(index)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Data set consist of ```image_id```, ```width```, ```height``` and ```bbox``` around the images capturing the wheat head.\n\n- Let's see a sample of image.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"Image(filename='/kaggle/input/global-wheat-detection/train/b902a5132.jpg',width=600)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"- Image represents all the wheat heads.\n- And through YOLOv5 model our aim is to detect thes wheat heads.","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"## Data Creation","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"Code is taken from this [Notebook](kaggle.com/orkatz2/yolov5-train) ","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"Using below code cell, we create a folder convertor and all files are stored in that converter folder in the given format.\n\n\n    - converter(main directory)\n        - val2017\n            - labels (contains all the box dimensions)\n            - images (contains images)\n        - train2017\n            - labels\n            - images\n            \n**Question**: Why this particular formate is requried?\n    - Answer: Because YOLO demands file structure in such a format.\n    \nAnd when create a ```.yaml``` file for data(i.e __wheat0.yaml__) within this file we define this particular file structure.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"source = 'train'\nif True:\n    for fold in [0]:\n        val_index = index[len(index)*fold//5:len(index)*(fold+1)//5]\n        for name,mini in tqdm(df.groupby('image_id')):\n            if name in val_index:\n                path2save = 'val2017/'\n            else:\n                path2save = 'train2017/'\n            if not os.path.exists('convertor/fold{}/labels/'.format(fold)+path2save):\n                os.makedirs('convertor/fold{}/labels/'.format(fold)+path2save)\n            with open('convertor/fold{}/labels/'.format(fold)+path2save+name+\".txt\", 'w+') as f:\n                row = mini[['classes','x_center','y_center','w','h']].astype(float).values\n                row = row/1024\n                row = row.astype(str)\n                for j in range(len(row)):\n                    text = ' '.join(row[j])\n                    f.write(text)\n                    f.write(\"\\n\")\n            if not os.path.exists('convertor/fold{}/images/{}'.format(fold,path2save)):\n                os.makedirs('convertor/fold{}/images/{}'.format(fold,path2save))\n            sh.copy(\"../input/global-wheat-detection/{}/{}.jpg\".format(source,name),'convertor/fold{}/images/{}/{}.jpg'.format(fold,path2save,name))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(os.listdir(\"../input\"))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Define YOLOv5 Model Configuration and Architecture in .yaml file","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"Before training you first need to define the complete model structure in a ```.yaml``` file.\n\n- data format(we already created in the above code line)\n- YOLOv5 model\n","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"> You have the option to pick from other YOLOv5 models including:\n> \n> - YOLOv5s\n> - YOLOv5m\n> - YOLOv5l\n> - YOLOv5x","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"## Training Custom YOLOv5 Detector for Wheat Head Detection","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"With our __data.yaml__ and __custom_yolov5s.yaml__ files ready to go we are ready to train!\n\nTo kick off training we running the training command with the following options:\n\n- ```img```: define input image size\n- ```batch```: determine batch size\n- ```epochs```: define the number of training epochs. (Note: often, 3000+ are common here!)\n- ```data```: set the path to our yaml file\n- ```cfg```: specify our model configuration\n- ```weights```: specify a custom path to weights. (Note: you can download weights from the Ultralytics Google Drive folder)\n- ```name```: result names\n- ```nosave```: only save the final checkpoint\n- ```cache```: cache images for faster training","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"# As i am running it for just trial(To save training time and GPU ) \n# So i am considering all the training factors to a limited extent.\n\n# Play with all featuers and see their performance.\n\n\n# !python train.py --img 1024 --batch 20 --epochs 10 --data ../input/yaml-file-for-data-model/wheat0.yaml --cfg ../input/yaml-file-for-data-model/yolov5x.yaml --name yolov5x_fold0_new\n\n\n\n!python train.py --img 640 --batch 2 --epochs 1 --data ../input/yaml-file-for-data-model/wheat0.yaml --cfg ../input/yaml-file-for-data-model/yolov5x.yaml --name yolov5x_fold0_new\n\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"- Run this and all your weights are saved in weights folder.\n- Need to save the model using commit.\n\n- Here i will give you two pretrained models that run for around 5 hours on my system..","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"# ! pip install tree","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Model Performance evaluation","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"# Start tensorboard\n# Launch after you have started training\n# logs save in the folder \"runs\"\n# %load_ext tensorboard\n# %tensorboard --logdir runs","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Run Inference With Trained Weights","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"# trained weights are saved by default in the weights folder\n%ls weights/","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!ls ./convertor","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# create a prediction on validation data\n\n!python ./detect.py --weights ./weights/last_yolov5x_fold0_new.pt --img 640 --conf 0.4 --source ./convertor/fold0/images/val2017","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Results are saved in the following directory : ```/kaggle/working/inference/output```","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"## Check the predicted one images.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"!ls /kaggle/working/inference/output/","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Choose any of the single image from above.","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"Output will look something like this.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"# This will work from your end when you edit this notebook and run it.\n# Image(filename='/kaggle/working/inference/output/42099cf54.jpg', width=400)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Output image like this\n\n\n<img src=\"https://raw.githubusercontent.com/AIVenture0/Global-Wheat-Detection-kaggle-challenge/master/wheat1.jpg\" height=300 width=550/>","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"# This will work from your end when you edit this notebook and run it.\n# Image(filename='/kaggle/working/inference/output/ad6e9eea2.jpg', width=400)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Output image like this\n\n\n<img src=\"https://raw.githubusercontent.com/AIVenture0/Global-Wheat-Detection-kaggle-challenge/master/wheat2.jpg\" height=300 width=550/>","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"## Note: \n\nI know this model is not accuractly detecting all wheat heads but when you trained for more epochs it will give better results. \n\n- Here i choose very less number of epochs to showcase all the thing to you how things are really working with  YOLOv5.\n\n- Do you guys want saved weight for a YOLOv5 model which i trained for around 5 hours if so let me know in the comment section. \n\n## <center>Hope you like it..........</center>","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"If you feel this kernel can be further simplified,  please put all your suggestions in the comment section.\n\nAnd if you lear something out here.\n\n\n> - Do Follow\n\n> - Do Upvote ","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}