{"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":"# Import Tools & Libraries","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-08-05T10:25:07.154924Z","iopub.execute_input":"2022-08-05T10:25:07.155488Z","iopub.status.idle":"2022-08-05T10:25:08.110310Z","shell.execute_reply.started":"2022-08-05T10:25:07.155355Z","shell.execute_reply":"2022-08-05T10:25:08.109124Z"}}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport os\nfrom enum import Enum\nimport ast\nfrom tqdm import tqdm\nfrom sklearn import model_selection\nimport shutil\nfrom glob import glob","metadata":{"execution":{"iopub.status.busy":"2022-08-08T13:52:13.232092Z","iopub.execute_input":"2022-08-08T13:52:13.232531Z","iopub.status.idle":"2022-08-08T13:52:13.732951Z","shell.execute_reply.started":"2022-08-08T13:52:13.232419Z","shell.execute_reply":"2022-08-08T13:52:13.732003Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# clone yolov5 github repo\nos.system(\"git clone https://github.com/ultralytics/yolov5.git\")","metadata":{"execution":{"iopub.status.busy":"2022-08-08T13:52:13.735212Z","iopub.execute_input":"2022-08-08T13:52:13.736707Z","iopub.status.idle":"2022-08-08T13:52:15.753184Z","shell.execute_reply.started":"2022-08-08T13:52:13.736667Z","shell.execute_reply":"2022-08-08T13:52:15.752209Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# load train.csv\ntrain = pd.read_csv(\"../input/global-wheat-detection/train.csv\")\ntrain.head()","metadata":{"execution":{"iopub.status.busy":"2022-08-08T13:52:15.754798Z","iopub.execute_input":"2022-08-08T13:52:15.755487Z","iopub.status.idle":"2022-08-08T13:52:15.985326Z","shell.execute_reply.started":"2022-08-08T13:52:15.755432Z","shell.execute_reply":"2022-08-08T13:52:15.984425Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# check the size of the dataset\ntrain.shape","metadata":{"execution":{"iopub.status.busy":"2022-08-08T13:52:15.987855Z","iopub.execute_input":"2022-08-08T13:52:15.988313Z","iopub.status.idle":"2022-08-08T13:52:15.994850Z","shell.execute_reply.started":"2022-08-08T13:52:15.988274Z","shell.execute_reply":"2022-08-08T13:52:15.993780Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# check no. of unique values for width, height,source and image_ids\ntrain.width.nunique(),train.height.nunique(),train.source.nunique(),train.image_id.nunique()","metadata":{"execution":{"iopub.status.busy":"2022-08-08T13:52:15.996604Z","iopub.execute_input":"2022-08-08T13:52:15.997342Z","iopub.status.idle":"2022-08-08T13:52:16.029147Z","shell.execute_reply.started":"2022-08-08T13:52:15.997296Z","shell.execute_reply":"2022-08-08T13:52:16.028136Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- All the images have same width and height i.e. all the images are of shape 1024 by 1024\n\n- We have 147793 no. of rows in the train.csv file\n\n- There are 3373 unique image ids, which means object(wheat) is present more than once in a single image","metadata":{}},{"cell_type":"code","source":"# plot the first image\nimport cv2\n\nimage = train.loc[0,'image_id']\n\nimage = os.path.join(\"../input/global-wheat-detection/train\",image + \".jpg\")\n\nplt.figure(figsize=(10,15))\nimg = cv2.imread(image)   \nimg = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\nplt.imshow(img)    \n","metadata":{"execution":{"iopub.status.busy":"2022-08-08T13:52:16.030574Z","iopub.execute_input":"2022-08-08T13:52:16.030878Z","iopub.status.idle":"2022-08-08T13:52:16.811747Z","shell.execute_reply.started":"2022-08-08T13:52:16.030847Z","shell.execute_reply":"2022-08-08T13:52:16.810450Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- We can see clearly, wheat is present multiple times in the image","metadata":{}},{"cell_type":"code","source":"# check the size of the image\nfrom PIL import Image\n\nimg=Image.open(image)\nw,h=img.size    # w=Width and h=Height\nprint(\"Width =\",w,end=\"\\t\")\nprint(\"Height =\",h)","metadata":{"execution":{"iopub.status.busy":"2022-08-08T13:52:16.812734Z","iopub.execute_input":"2022-08-08T13:52:16.813049Z","iopub.status.idle":"2022-08-08T13:52:16.821209Z","shell.execute_reply.started":"2022-08-08T13:52:16.813019Z","shell.execute_reply":"2022-08-08T13:52:16.820095Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- This is something we had checked earlier also, all the images are of size 1024 by 1024","metadata":{}},{"cell_type":"code","source":"# bounding boxes are given as a string, convert them into list\ntrain.bbox = train.bbox.apply(ast.literal_eval)\ntrain.bbox.head()","metadata":{"execution":{"iopub.status.busy":"2022-08-08T13:52:16.822911Z","iopub.execute_input":"2022-08-08T13:52:16.823703Z","iopub.status.idle":"2022-08-08T13:52:18.612179Z","shell.execute_reply.started":"2022-08-08T13:52:16.823664Z","shell.execute_reply":"2022-08-08T13:52:18.611128Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# group the records by image id, so that we have cordinates of all the objects present in an image \n# as list of lists, name the new colum as bboxes\ntrain = train.groupby(\"image_id\")[\"bbox\"].apply(list).reset_index(name=\"bboxes\")","metadata":{"execution":{"iopub.status.busy":"2022-08-08T13:52:18.613911Z","iopub.execute_input":"2022-08-08T13:52:18.614343Z","iopub.status.idle":"2022-08-08T13:52:18.708730Z","shell.execute_reply.started":"2022-08-08T13:52:18.614302Z","shell.execute_reply":"2022-08-08T13:52:18.707807Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# check the updated dataset\ntrain.head()","metadata":{"execution":{"iopub.status.busy":"2022-08-08T13:52:18.713213Z","iopub.execute_input":"2022-08-08T13:52:18.713506Z","iopub.status.idle":"2022-08-08T13:52:18.768823Z","shell.execute_reply.started":"2022-08-08T13:52:18.713478Z","shell.execute_reply":"2022-08-08T13:52:18.768007Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# train test split\ndf_train,df_valid = model_selection.train_test_split(\n    train,\n    test_size=0.1,\n    random_state=42,\n    shuffle=True\n)","metadata":{"execution":{"iopub.status.busy":"2022-08-08T13:52:18.771909Z","iopub.execute_input":"2022-08-08T13:52:18.772170Z","iopub.status.idle":"2022-08-08T13:52:18.779132Z","shell.execute_reply.started":"2022-08-08T13:52:18.772145Z","shell.execute_reply":"2022-08-08T13:52:18.778189Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# drop the index\ndf_train = df_train.reset_index(drop=True)\ndf_valid = df_valid.reset_index(drop=True)","metadata":{"execution":{"iopub.status.busy":"2022-08-08T13:52:18.780850Z","iopub.execute_input":"2022-08-08T13:52:18.781680Z","iopub.status.idle":"2022-08-08T13:52:18.787360Z","shell.execute_reply.started":"2022-08-08T13:52:18.781635Z","shell.execute_reply":"2022-08-08T13:52:18.786509Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# create folders to meet yolo requirement\nos.system(\n            f'''\n                cd ./yolov5\n                mkdir output \n                cd output\n                mkdir images\n                mkdir labels\n                cd images\n                mkdir train\n                mkdir validation\n                cd ..\n                cd labels\n                mkdir train\n                mkdir validation\n                cd ../\n            ''')","metadata":{"execution":{"iopub.status.busy":"2022-08-08T13:52:18.788689Z","iopub.execute_input":"2022-08-08T13:52:18.789439Z","iopub.status.idle":"2022-08-08T13:52:18.814321Z","shell.execute_reply.started":"2022-08-08T13:52:18.789400Z","shell.execute_reply":"2022-08-08T13:52:18.813418Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# plot the folder structure created above\n!tree -d yolov5/output","metadata":{"execution":{"iopub.status.busy":"2022-08-08T13:52:18.815615Z","iopub.execute_input":"2022-08-08T13:52:18.815937Z","iopub.status.idle":"2022-08-08T13:52:19.815290Z","shell.execute_reply.started":"2022-08-08T13:52:18.815904Z","shell.execute_reply":"2022-08-08T13:52:19.814152Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Define path\nDATA_PATH =\"../input/global-wheat-detection/\" # this is where training and test images are saved\nOUTPUT_PATH = \"./yolov5/output/\" \nIMG_SIZE = 1024\nlabel = 0\nEPOCHS = 20\nBATCH_SIZE = 8","metadata":{"execution":{"iopub.status.busy":"2022-08-08T13:52:19.817060Z","iopub.execute_input":"2022-08-08T13:52:19.817967Z","iopub.status.idle":"2022-08-08T13:52:19.826194Z","shell.execute_reply.started":"2022-08-08T13:52:19.817927Z","shell.execute_reply":"2022-08-08T13:52:19.823963Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# helper function to convert the data into yolo format\n# also copy images from train/test folder to yolov5 folder\n\ndef process_data(data,data_type=train):\n    for _,row in tqdm(data.iterrows()):\n        image_name = row.image_id\n        bounding_boxes = row.bboxes\n        \n        yolo_data = []\n\n        for bbox in bounding_boxes:\n            x = bbox[0]\n            y = bbox[1]\n            w = bbox[2]\n            h = bbox[3]\n            \n            x_center = x + w/2\n            y_center = y + h/2\n            \n            x_center, y_center, w, h = tuple(map(lambda x: x/IMG_SIZE, (x_center, y_center, w, h)))\n            yolo_data.append([label,x_center,y_center,w,h])\n            \n        yolo_data = np.array(yolo_data)\n        np.savetxt(\n        os.path.join(OUTPUT_PATH,f\"labels/{data_type}/{image_name}.txt\"),\n            yolo_data,\n            fmt=[\"%d\",\"%f\",\"%f\",\"%f\",\"%f\"]\n        )\n            \n        shutil.copyfile(\n        os.path.join(DATA_PATH,f\"train/{image_name}.jpg\"),\n        os.path.join(OUTPUT_PATH,f\"images/{data_type}/{image_name}.jpg\"),\n        )","metadata":{"execution":{"iopub.status.busy":"2022-08-08T13:52:19.829087Z","iopub.execute_input":"2022-08-08T13:52:19.829350Z","iopub.status.idle":"2022-08-08T13:52:19.852069Z","shell.execute_reply.started":"2022-08-08T13:52:19.829324Z","shell.execute_reply":"2022-08-08T13:52:19.851160Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# execute above function\nprocess_data(df_train,data_type=\"train\")\nprocess_data(df_valid,data_type=\"validation\")","metadata":{"execution":{"iopub.status.busy":"2022-08-08T13:52:19.853615Z","iopub.execute_input":"2022-08-08T13:52:19.854324Z","iopub.status.idle":"2022-08-08T13:52:41.655820Z","shell.execute_reply.started":"2022-08-08T13:52:19.854286Z","shell.execute_reply":"2022-08-08T13:52:41.654837Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# verify whether images copied correctly or not\ntrain_images= glob(\"./yolov5/output/images/train/*.jpg\")\nvalidation_images= glob(\"./yolov5/output/images/validation/*.jpg\")\nprint(\"no. of training images copied:{},\\nno. of test images copied:{}\".format(len(train_images),len(validation_images)))","metadata":{"execution":{"iopub.status.busy":"2022-08-08T13:52:41.657138Z","iopub.execute_input":"2022-08-08T13:52:41.659094Z","iopub.status.idle":"2022-08-08T13:52:41.677797Z","shell.execute_reply.started":"2022-08-08T13:52:41.659054Z","shell.execute_reply":"2022-08-08T13:52:41.676935Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# verify whether labels are saved correctly or not\ntrain_labels= glob(\"./yolov5/output/labels/train/*.txt\")\nvalidation_labels= glob(\"./yolov5/output/labels/validation/*.txt\")\nprint(\"no. of training labels saved:{},\\nno. of test labels copied:{}\".format(len(train_labels),len(validation_labels)))","metadata":{"execution":{"iopub.status.busy":"2022-08-08T13:52:41.678963Z","iopub.execute_input":"2022-08-08T13:52:41.679279Z","iopub.status.idle":"2022-08-08T13:52:41.697855Z","shell.execute_reply.started":"2022-08-08T13:52:41.679246Z","shell.execute_reply":"2022-08-08T13:52:41.697014Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# check the first image saved in the yolov5 folder\nimport cv2\n\nimage = train_images[0]\n\nplt.figure(figsize=(10,15))\nimg = cv2.imread(image)   \nimg = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\nplt.imshow(img)    \n","metadata":{"execution":{"iopub.status.busy":"2022-08-08T13:52:41.700731Z","iopub.execute_input":"2022-08-08T13:52:41.701601Z","iopub.status.idle":"2022-08-08T13:52:42.243124Z","shell.execute_reply.started":"2022-08-08T13:52:41.701566Z","shell.execute_reply":"2022-08-08T13:52:42.242345Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- So far so good, We have coppied the images to yolov5 folder","metadata":{}},{"cell_type":"code","source":"# verify the text file saved\n!head -10 \"./yolov5/output/labels/train/00333207f.txt\" ","metadata":{"execution":{"iopub.status.busy":"2022-08-08T13:52:42.244750Z","iopub.execute_input":"2022-08-08T13:52:42.245330Z","iopub.status.idle":"2022-08-08T13:52:43.231428Z","shell.execute_reply.started":"2022-08-08T13:52:42.245295Z","shell.execute_reply":"2022-08-08T13:52:43.230339Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- We have correctly saved the labels to the yolov5 folder\n- Now we need to create yaml file","metadata":{}},{"cell_type":"code","source":"# Create yaml file, mention the path where training and validation data resides\n# Also mention the no. of classes\n# And Name the label to predict\n\nOUTPUT_PATH = \"./output\"\nwith open(f\"./yolov5/ws_data.yaml\", \"w+\") as file_:\n        file_.write(\n            f\"\"\"\n            \n            train: {OUTPUT_PATH}/images/train\n            val: {OUTPUT_PATH}/images/validation\n            nc: 1\n            names: [\"wheat\"]\n            \n            \"\"\"\n        )","metadata":{"execution":{"iopub.status.busy":"2022-08-08T13:52:43.233704Z","iopub.execute_input":"2022-08-08T13:52:43.234105Z","iopub.status.idle":"2022-08-08T13:52:43.240962Z","shell.execute_reply.started":"2022-08-08T13:52:43.234062Z","shell.execute_reply":"2022-08-08T13:52:43.239807Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# verify yaml file\n!cat \"./yolov5/ws_data.yaml\"","metadata":{"execution":{"iopub.status.busy":"2022-08-08T13:52:43.242740Z","iopub.execute_input":"2022-08-08T13:52:43.243572Z","iopub.status.idle":"2022-08-08T13:52:44.220111Z","shell.execute_reply.started":"2022-08-08T13:52:43.243536Z","shell.execute_reply":"2022-08-08T13:52:44.218974Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# helper function to train the yolo v5 model\ndef trainYoloModel(model_name: str,preTrainedWeights_path = None):\n    \"\"\"\n    Helper function to train YOLO v5 models\n    \n    \"\"\"\n    mapper = {}\n    for idx, model_ in enumerate(glob(\"yolov5/models/*yaml\")):\n        mapper[idx + 1] = model_\n        print(f\"{idx + 1} =>  {model_.split('/')[-1].split('.')[0]}\")\n\n    model = mapper[2]\n    \n    if preTrainedWeights_path is not None:\n        os.system(\n            f\"\"\"\n                python yolov5/train.py --img {IMG_SIZE} --batch {BATCH_SIZE} --epochs {EPOCHS} --data yolov5/ws_data.yaml --cfg {model} --name {model_name} --weights {preTrainedweights_path}\n            \n            \"\"\"\n        )\n    else:\n        os.system(\n            f\"\"\"\n                python yolov5/train.py --img {IMG_SIZE} --batch {BATCH_SIZE} --epochs {EPOCHS} --data yolov5/ws_data.yaml --cfg {model} --name {model_name}\n            \"\"\"\n        )","metadata":{"execution":{"iopub.status.busy":"2022-08-08T13:52:44.222253Z","iopub.execute_input":"2022-08-08T13:52:44.222697Z","iopub.status.idle":"2022-08-08T13:52:44.230370Z","shell.execute_reply.started":"2022-08-08T13:52:44.222644Z","shell.execute_reply":"2022-08-08T13:52:44.229295Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"trainYoloModel(model_name = \"ws_yolov5\",preTrainedWeights_path = None)","metadata":{"execution":{"iopub.status.busy":"2022-08-08T13:52:44.232109Z","iopub.execute_input":"2022-08-08T13:52:44.232527Z","iopub.status.idle":"2022-08-08T14:00:29.722485Z","shell.execute_reply.started":"2022-08-08T13:52:44.232491Z","shell.execute_reply":"2022-08-08T14:00:29.721372Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!tree -f yolov5/runs","metadata":{"execution":{"iopub.status.busy":"2022-08-08T14:00:29.725284Z","iopub.execute_input":"2022-08-08T14:00:29.725599Z","iopub.status.idle":"2022-08-08T14:00:30.728620Z","shell.execute_reply.started":"2022-08-08T14:00:29.725571Z","shell.execute_reply":"2022-08-08T14:00:30.727431Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# helper function to make predictions\ndef predict(images_path:\"path to the test images\", weights_path: \"path to the weights folder\"):\n    \"\"\"\n    Helper function to make predictions over images using Yolo\n    \"\"\"\n    os.system(\n        f\"\"\"\n            python yolov5/detect.py --source {images_path} --weights {weights_path}\n        \"\"\")\n\npredict(images_path = \"../input/global-wheat-detection/test\",\n       weights_path = \"yolov5/runs/train/ws_yolov5/weights/best.pt\")","metadata":{"execution":{"iopub.status.busy":"2022-08-08T14:00:30.730856Z","iopub.execute_input":"2022-08-08T14:00:30.731194Z","iopub.status.idle":"2022-08-08T14:00:38.109042Z","shell.execute_reply.started":"2022-08-08T14:00:30.731164Z","shell.execute_reply":"2022-08-08T14:00:38.108036Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# images with bounding box boundaries saved in exp folder\n!tree -f yolov5/runs/detect/exp","metadata":{"execution":{"iopub.status.busy":"2022-08-08T14:00:38.114306Z","iopub.execute_input":"2022-08-08T14:00:38.114620Z","iopub.status.idle":"2022-08-08T14:00:39.258974Z","shell.execute_reply.started":"2022-08-08T14:00:38.114591Z","shell.execute_reply":"2022-08-08T14:00:39.257801Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# plot images with objects detected\nfrom skimage import io\nimport plotly.express as px\nimport plotly.graph_objs as go\n\ndef showImages(image_dir: \"path to image directory\"):\n    \"\"\"\n    Helper function to visualize images in a directory\n    \n    \"\"\"\n    imgs_paths = glob(image_dir + \"/*jpg\")\n    numImgs = len(imgs_paths)\n   \n    for i in range(numImgs):\n        img = io.imread(imgs_paths[i])\n        fig = px.imshow(img)\n        fig.show()\n\n    \nshowImages(image_dir = \"yolov5/runs/detect/exp\")","metadata":{"execution":{"iopub.status.busy":"2022-08-08T14:00:39.262128Z","iopub.execute_input":"2022-08-08T14:00:39.262495Z","iopub.status.idle":"2022-08-08T14:00:46.016988Z","shell.execute_reply.started":"2022-08-08T14:00:39.262446Z","shell.execute_reply":"2022-08-08T14:00:46.012546Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}