{"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_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# AIM: To Buind a a baseline model for Object Detectioon","metadata":{}},{"cell_type":"markdown","source":"I struggled a lot to learn how to make a pipeline for the object detection task. Though there are different framework available. First I have learned yolo, because it is easier to visualize the result in different style. We can also use youtube video for the inference and lot more features are available.\n\nIf you are struggling with building an object detection pipeline, this notebook will help you. If you still have some issue, you can reach out to me. ","metadata":{}},{"cell_type":"markdown","source":"**As per the competition guideline yolo is not alowed, however its good to know how to train a yolo model.**","metadata":{}},{"cell_type":"markdown","source":"### Step 1: Directory setup \n\nFirst of all we need an specific type of directory structure for the yolo, so I will create some new directory for the dataset**","metadata":{}},{"cell_type":"code","source":"%%bash\n\nmkdir data\nmkdir data/input\nmkdir data/preprocessed\nmkdir data/preprocessed/train\nmkdir data/preprocessed/valid\nmkdir data/preprocessed/train/images\nmkdir data/preprocessed/train/labels\nmkdir data/preprocessed/valid/images\nmkdir data/preprocessed/valid/labels","metadata":{"execution":{"iopub.status.busy":"2022-11-13T06:38:17.917608Z","iopub.execute_input":"2022-11-13T06:38:17.917941Z","iopub.status.idle":"2022-11-13T06:38:17.951667Z","shell.execute_reply.started":"2022-11-13T06:38:17.917905Z","shell.execute_reply":"2022-11-13T06:38:17.950513Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Step 2: Converting the label into YOLO format .\n\nProvided dataset is not in the format of yolo it has `x`, `y`, `w`, `h` but yolo require relative `x_center`, `y_center`, `w`, `h`. So below code will do that for us. Than we will move the files into training and validation directory.","metadata":{}},{"cell_type":"code","source":"# munge data\n\nimport pandas as pd \nimport os \nimport ast\nfrom sklearn import model_selection\nfrom tqdm import tqdm\nimport numpy as np\nimport shutil\n\n\ndata_path = '../input/global-wheat-detection'\noutput_path = 'data/preprocessed/'\n\ndef process_data(data, data_type='train'):\n    for _, row in tqdm(data.iterrows(), total=len(data)):\n        image_name = row['image_id']\n        bounding_boxes = row['bboxes']\n        yolo_data = []\n        for bbox in bounding_boxes:\n            x = bbox[0]\n            y = bbox[1]\n            w = bbox[2]\n            h = bbox[3]\n            x_center = x+w/2\n            y_center = y+h/2\n            x_center /= 1024\n            y_center /= 1024\n            w /= 1024\n            h /= 1024\n            yolo_data.append([0, x_center, y_center, w, h])\n        yolo_data = np.array(yolo_data)\n        np.savetxt(os.path.join(output_path, f\"{data_type}/labels/{image_name}.txt\"), yolo_data, fmt=[\"%d\", \"%f\", \"%f\" , \"%f\", \"%f\"])\n        shutil.copyfile(\n            os.path.join(data_path,f\"train/{image_name}.jpg\"),\n            os.path.join(output_path,f\"{data_type}/images/{image_name}.jpg\")\n        )\nif __name__==\"__main__\":    \n    df = pd.read_csv(os.path.join(data_path, 'train.csv'))\n    df.bbox = df.bbox.apply(ast.literal_eval)\n    df = df.groupby('image_id')['bbox'].apply(list).reset_index(name='bboxes')\n    df_train, df_valid = model_selection.train_test_split(df, test_size=0.1, random_state=42, shuffle=True)\n    df_train = df_train.reset_index(drop=True)\n    df_valid = df_valid.reset_index(drop=True)\n    process_data(df_train, data_type='train')\n    process_data(df_valid, data_type='valid')","metadata":{"execution":{"iopub.status.busy":"2022-11-13T06:38:17.953970Z","iopub.execute_input":"2022-11-13T06:38:17.954714Z","iopub.status.idle":"2022-11-13T06:38:43.386193Z","shell.execute_reply.started":"2022-11-13T06:38:17.954672Z","shell.execute_reply":"2022-11-13T06:38:43.384895Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Step3: Creating yaml file \n\nWe have to create a yaml file to specify where the dataset are. Later will will pass this file in the training script.**","metadata":{}},{"cell_type":"code","source":"wheat_text = \"\"\"train: ./data/preprocessed/train/images\nval: ./data/preprocessed/valid/images\n\nnc: 1\nnames: [\"wheat\"]\"\"\"","metadata":{"execution":{"iopub.status.busy":"2022-11-13T06:38:43.389235Z","iopub.execute_input":"2022-11-13T06:38:43.389538Z","iopub.status.idle":"2022-11-13T06:38:43.396227Z","shell.execute_reply.started":"2022-11-13T06:38:43.389509Z","shell.execute_reply":"2022-11-13T06:38:43.395366Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with open(\"wheat_text.yaml\", 'w') as f:\n    f.write(wheat_text)\n%cat wheat_text.yaml","metadata":{"execution":{"iopub.status.busy":"2022-11-13T06:38:43.397651Z","iopub.execute_input":"2022-11-13T06:38:43.398130Z","iopub.status.idle":"2022-11-13T06:38:44.559771Z","shell.execute_reply.started":"2022-11-13T06:38:43.398086Z","shell.execute_reply":"2022-11-13T06:38:44.558823Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**A checkup**","metadata":{}},{"cell_type":"code","source":"# current working directory\n!pwd","metadata":{"execution":{"iopub.status.busy":"2022-11-13T06:38:44.564276Z","iopub.execute_input":"2022-11-13T06:38:44.564584Z","iopub.status.idle":"2022-11-13T06:38:45.536033Z","shell.execute_reply.started":"2022-11-13T06:38:44.564553Z","shell.execute_reply":"2022-11-13T06:38:45.534724Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Let's check the directory once again**","metadata":{}},{"cell_type":"code","source":"!ls","metadata":{"execution":{"iopub.status.busy":"2022-11-13T06:38:45.539925Z","iopub.execute_input":"2022-11-13T06:38:45.540320Z","iopub.status.idle":"2022-11-13T06:38:46.565652Z","shell.execute_reply.started":"2022-11-13T06:38:45.540276Z","shell.execute_reply":"2022-11-13T06:38:46.564667Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# check the assigned GPU type\n!nvidia-smi","metadata":{"execution":{"iopub.status.busy":"2022-11-13T06:38:46.567565Z","iopub.execute_input":"2022-11-13T06:38:46.567881Z","iopub.status.idle":"2022-11-13T06:38:47.784292Z","shell.execute_reply.started":"2022-11-13T06:38:46.567846Z","shell.execute_reply":"2022-11-13T06:38:47.783132Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Step 4: Cloning the yolov5 repository and installing the requirements","metadata":{}},{"cell_type":"code","source":"# # YOLO \n!git clone https://github.com/ultralytics/yolov5  && cd yolov5 && pip install -r requirements.txt --use-feature=2020-resolver","metadata":{"execution":{"iopub.status.busy":"2022-11-13T06:38:47.786674Z","iopub.execute_input":"2022-11-13T06:38:47.787074Z","iopub.status.idle":"2022-11-13T06:41:45.758400Z","shell.execute_reply.started":"2022-11-13T06:38:47.787028Z","shell.execute_reply":"2022-11-13T06:41:45.757369Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**uninstalling wandb or it will try to login while training**","metadata":{}},{"cell_type":"code","source":"!pip3 uninstall wandb -y","metadata":{"execution":{"iopub.status.busy":"2022-11-13T06:41:45.760331Z","iopub.execute_input":"2022-11-13T06:41:45.760716Z","iopub.status.idle":"2022-11-13T06:41:49.579513Z","shell.execute_reply.started":"2022-11-13T06:41:45.760674Z","shell.execute_reply":"2022-11-13T06:41:49.578658Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Copy the dataset into yolov5 directory**","metadata":{}},{"cell_type":"code","source":"!cp -r data yolov5","metadata":{"execution":{"iopub.status.busy":"2022-11-13T06:41:49.581488Z","iopub.execute_input":"2022-11-13T06:41:49.581852Z","iopub.status.idle":"2022-11-13T06:41:53.874793Z","shell.execute_reply.started":"2022-11-13T06:41:49.581809Z","shell.execute_reply":"2022-11-13T06:41:53.873710Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install typing-extensions --upgrade --use-feature=2020-resolver","metadata":{"execution":{"iopub.status.busy":"2022-11-13T06:41:53.877762Z","iopub.execute_input":"2022-11-13T06:41:53.878084Z","iopub.status.idle":"2022-11-13T06:42:05.371841Z","shell.execute_reply.started":"2022-11-13T06:41:53.878049Z","shell.execute_reply":"2022-11-13T06:42:05.370865Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Step 5: Training the model\n\nyou can pass the argument depend on you requirements, Currently I am passing `--img` for image size `--batch` for batch size `--epochs` for numbers of epoch `--workers` number of workers `--cfg` for selecting yolo5s architecture `--name` will save the result in yolov5x-wheat directory --cache will catche the data","metadata":{}},{"cell_type":"code","source":"!python ./yolov5/train.py --img 512 --batch 16 --epochs 100 --workers 2 --data wheat_text.yaml --cfg \"./yolov5/models/yolov5s.yaml\" --name yolov5s_wheat --cache ","metadata":{"execution":{"iopub.status.busy":"2022-11-13T06:42:05.373553Z","iopub.execute_input":"2022-11-13T06:42:05.373907Z","iopub.status.idle":"2022-11-13T06:45:16.530248Z","shell.execute_reply.started":"2022-11-13T06:42:05.373866Z","shell.execute_reply":"2022-11-13T06:45:16.528894Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Training result is saved in folder `yolov5/runs/train/yolov5s_wheat`, lets look at this foler**","metadata":{}},{"cell_type":"code","source":"result_dir = \"yolov5/runs/train/yolov5s_wheat\"","metadata":{"execution":{"iopub.status.busy":"2022-11-13T06:45:16.532995Z","iopub.execute_input":"2022-11-13T06:45:16.533653Z","iopub.status.idle":"2022-11-13T06:45:16.538491Z","shell.execute_reply.started":"2022-11-13T06:45:16.533604Z","shell.execute_reply":"2022-11-13T06:45:16.537275Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"os.listdir(result_dir)","metadata":{"execution":{"iopub.status.busy":"2022-11-13T06:45:16.540021Z","iopub.execute_input":"2022-11-13T06:45:16.540631Z","iopub.status.idle":"2022-11-13T06:45:16.555509Z","shell.execute_reply.started":"2022-11-13T06:45:16.540553Z","shell.execute_reply":"2022-11-13T06:45:16.554767Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Lets check Precision Recall metrics\nfrom PIL import Image\nimg = Image.open(os.path.join(result_dir, \"PR_curve.png\")).resize((1000,500))\nimg","metadata":{"execution":{"iopub.status.busy":"2022-11-13T06:45:16.557194Z","iopub.execute_input":"2022-11-13T06:45:16.557631Z","iopub.status.idle":"2022-11-13T06:45:16.782908Z","shell.execute_reply.started":"2022-11-13T06:45:16.557562Z","shell.execute_reply":"2022-11-13T06:45:16.781720Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Lets check Confusion metrics\nimg = Image.open(os.path.join(result_dir, \"confusion_matrix.png\")).resize((1000, 1000))\nimg","metadata":{"execution":{"iopub.status.busy":"2022-11-13T06:45:16.784478Z","iopub.execute_input":"2022-11-13T06:45:16.784882Z","iopub.status.idle":"2022-11-13T06:45:17.158498Z","shell.execute_reply.started":"2022-11-13T06:45:16.784844Z","shell.execute_reply":"2022-11-13T06:45:17.157250Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# trained model path\nos.listdir(os.path.join(result_dir,'weights'))","metadata":{"execution":{"iopub.status.busy":"2022-11-13T06:45:17.159875Z","iopub.execute_input":"2022-11-13T06:45:17.160232Z","iopub.status.idle":"2022-11-13T06:45:17.168403Z","shell.execute_reply.started":"2022-11-13T06:45:17.160191Z","shell.execute_reply":"2022-11-13T06:45:17.167288Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Step 4: Prediction on Test Dataset\n\nI'll select the prediction whose confidence score is greater than 0.1 and save the result ","metadata":{}},{"cell_type":"code","source":"!python ./yolov5/detect.py --source ../input/global-wheat-detection/test --weights yolov5/runs/train/yolov5s_wheat/weights/best.pt --img 512 --conf 0.1 --save-txt --save-conf --exist-ok","metadata":{"execution":{"iopub.status.busy":"2022-11-13T06:45:17.170071Z","iopub.execute_input":"2022-11-13T06:45:17.170499Z","iopub.status.idle":"2022-11-13T06:45:28.415995Z","shell.execute_reply.started":"2022-11-13T06:45:17.170459Z","shell.execute_reply":"2022-11-13T06:45:28.415024Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!ls yolov5/runs/detect/exp/labels","metadata":{"execution":{"iopub.status.busy":"2022-11-13T06:45:28.419532Z","iopub.execute_input":"2022-11-13T06:45:28.419826Z","iopub.status.idle":"2022-11-13T06:45:29.409989Z","shell.execute_reply.started":"2022-11-13T06:45:28.419793Z","shell.execute_reply":"2022-11-13T06:45:29.408830Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Step 5:  Converting the YOLO result into the submission format","metadata":{}},{"cell_type":"code","source":"!pip uninstall pandas -y\n!pip install pandas==1.1.5 ","metadata":{"execution":{"iopub.status.busy":"2022-11-13T06:45:29.411714Z","iopub.execute_input":"2022-11-13T06:45:29.412086Z","iopub.status.idle":"2022-11-13T06:45:43.238026Z","shell.execute_reply.started":"2022-11-13T06:45:29.412052Z","shell.execute_reply":"2022-11-13T06:45:43.236987Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os \nimport pandas as pd","metadata":{"execution":{"iopub.status.busy":"2022-11-13T06:45:43.239752Z","iopub.execute_input":"2022-11-13T06:45:43.240132Z","iopub.status.idle":"2022-11-13T06:45:43.245840Z","shell.execute_reply.started":"2022-11-13T06:45:43.240092Z","shell.execute_reply":"2022-11-13T06:45:43.244523Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def convert(s):\n    x = int(1024 * (s[1] - s[3]/2))\n    y = int(1024 * (s[2] - s[4]/2))\n    w = int(1024 * s[3])\n    h = int(1024 * s[4])\n    \n    return(str(s[5]) + ' ' + str(x) + ' ' + str(y) + ' ' + str(w) + ' ' + str(h))","metadata":{"execution":{"iopub.status.busy":"2022-11-13T06:45:43.247050Z","iopub.execute_input":"2022-11-13T06:45:43.247752Z","iopub.status.idle":"2022-11-13T06:45:43.256534Z","shell.execute_reply.started":"2022-11-13T06:45:43.247660Z","shell.execute_reply":"2022-11-13T06:45:43.255758Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!cp ../input/global-wheat-detection/sample_submission.csv . ","metadata":{"execution":{"iopub.status.busy":"2022-11-13T06:45:43.259770Z","iopub.execute_input":"2022-11-13T06:45:43.260065Z","iopub.status.idle":"2022-11-13T06:45:44.247394Z","shell.execute_reply.started":"2022-11-13T06:45:43.260012Z","shell.execute_reply":"2022-11-13T06:45:44.246207Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test = pd.read_csv('sample_submission.csv')\nprint(test.head())","metadata":{"execution":{"iopub.status.busy":"2022-11-13T06:45:44.251475Z","iopub.execute_input":"2022-11-13T06:45:44.251778Z","iopub.status.idle":"2022-11-13T06:45:44.267758Z","shell.execute_reply.started":"2022-11-13T06:45:44.251745Z","shell.execute_reply":"2022-11-13T06:45:44.266948Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with open('sample_submission.csv', 'w') as myfile:\n\n    # prepare submission\n    wfolder = 'yolov5/runs/detect/exp/labels/'\n    for f in os.listdir(wfolder):\n        fname = wfolder + f\n        xdat = pd.read_csv(fname, sep = ' ', header = None)\n        outline = f[:-4] + ' ' + ' '.join(list(xdat.apply(lambda s: convert(s), axis = 1)))\n        myfile.write(outline + '\\n')\n        \nmyfile.close()","metadata":{"execution":{"iopub.status.busy":"2022-11-13T06:45:44.269235Z","iopub.execute_input":"2022-11-13T06:45:44.269580Z","iopub.status.idle":"2022-11-13T06:45:44.342688Z","shell.execute_reply.started":"2022-11-13T06:45:44.269544Z","shell.execute_reply":"2022-11-13T06:45:44.341808Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test = pd.read_csv('sample_submission.csv')\nprint(test.head())","metadata":{"execution":{"iopub.status.busy":"2022-11-13T06:45:44.344044Z","iopub.execute_input":"2022-11-13T06:45:44.344474Z","iopub.status.idle":"2022-11-13T06:45:44.356514Z","shell.execute_reply.started":"2022-11-13T06:45:44.344435Z","shell.execute_reply":"2022-11-13T06:45:44.355462Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}