{"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":"<h1><center>Simple YoloX Dataset Generator (COCO-JSON)</center></h1>     \n\n<center><img src = \"https://i.imgur.com/iatgdo5.jpg\" width = \"635\" height = \"235\"/></center>         \n\nThis dataset was built to be compatible with the train (train.py) script that can be found [HERE](https://github.com/Megvii-BaseDetection/YOLOX). I also have a training notebook that you can find [HERE](https://www.kaggle.com/coldfir3/yolox). The inference notebook is still WIP. The resulting kaggle Dataset cand be found [HERE](https://www.kaggle.com/coldfir3/cots-yolox-dataset)\n\nThe tree main tasks into converting this dataset to YoloX format are:\n1. Splitting into train and test\n1. Converting the bboxes to COCO format\n1. Saving the annotations to a .json file\n\nI took inspiration on [this](https://www.kaggle.com/remekkinas/yolox-training-pipeline-cots-dataset-lb-0-507) amazing notebook\n\n<h3 style='background:orange; color:black'><center>Consider upvoting this notebook if you found it helpful.</center></h3>","metadata":{}},{"cell_type":"markdown","source":"## Loading the DataFrame and spliting into train/test\n\nI have a whole discussion topic ([here](https://www.kaggle.com/c/tensorflow-great-barrier-reef/discussion/293723)) where I explain why I think spliting by video is the best approach, but feel free to change the train/val split strategy","metadata":{}},{"cell_type":"code","source":"from ast import literal_eval\nimport pandas as pd\nfrom tqdm.notebook import tqdm\n\nTRAIN_PATH = '/kaggle/input/tensorflow-great-barrier-reef/train_images'\nN_SAMP = 6000\n\ndf = pd.read_csv('/kaggle/input/tensorflow-great-barrier-reef/train.csv')\nn_with_annotations = (df['annotations'] != '[]').sum()\n\ndf = pd.concat([\n    df[df['annotations'] != '[]'],\n    df[df['annotations'] == '[]'].sample(N_SAMP - n_with_annotations)\n]).sample(frac=1).reset_index(drop = True)\n\ndf['is_valid'] = df['video_id'] == 2\ndf['annotations'] = df['annotations'].apply(literal_eval)\ndf['path'] = df.apply(lambda row: f\"{TRAIN_PATH}/video_{row['video_id']}/{row['video_frame']}.jpg\", axis = 1)\n\ndf.tail()","metadata":{"execution":{"iopub.status.busy":"2021-12-10T19:09:37.192934Z","iopub.execute_input":"2021-12-10T19:09:37.193304Z","iopub.status.idle":"2021-12-10T19:09:37.943781Z","shell.execute_reply.started":"2021-12-10T19:09:37.193177Z","shell.execute_reply":"2021-12-10T19:09:37.941619Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Converting to COCO","metadata":{}},{"cell_type":"code","source":"def coco(df):\n    \n    annotion_id = 0\n    images = []\n    annotations = []\n\n    categories = [{'id': 0, 'name': 'cots'}]\n\n    for i, row in tqdm(df.iterrows(), total = len(df)):\n\n        images.append({\n            \"id\": i,\n            \"file_name\": f\"{row['image_id']}.jpg\",\n            \"height\": 720,\n            \"width\": 1280,\n        })\n        for bbox in row['annotations']:\n            annotations.append({\n                \"id\": annotion_id,\n                \"image_id\": i,\n                \"category_id\": 0,\n                \"bbox\": list(bbox.values()),\n                \"area\": bbox['width'] * bbox['height'],\n                \"segmentation\": [],\n                \"iscrowd\": 0\n            })\n            annotion_id += 1\n\n    json_file = {'categories':categories, 'images':images, 'annotations':annotations}\n    return json_file","metadata":{"execution":{"iopub.status.busy":"2021-12-10T19:09:37.945761Z","iopub.execute_input":"2021-12-10T19:09:37.946084Z","iopub.status.idle":"2021-12-10T19:09:37.954659Z","shell.execute_reply.started":"2021-12-10T19:09:37.946043Z","shell.execute_reply":"2021-12-10T19:09:37.954079Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"json_train = coco(df[~df['is_valid']])\njson_valid = coco(df[ df['is_valid']])","metadata":{"execution":{"iopub.status.busy":"2021-12-10T19:09:37.955698Z","iopub.execute_input":"2021-12-10T19:09:37.955953Z","iopub.status.idle":"2021-12-10T19:09:38.499733Z","shell.execute_reply.started":"2021-12-10T19:09:37.955923Z","shell.execute_reply":"2021-12-10T19:09:38.498931Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Saving into a json file","metadata":{}},{"cell_type":"code","source":"import json\n\nwith open('/kaggle/working/annotations_train.json', 'w', encoding='utf-8') as f:\n    json.dump(json_train, f, ensure_ascii=True, indent=4)\n    \nwith open('/kaggle/working/annotations_valid.json', 'w', encoding='utf-8') as f:\n    json.dump(json_valid, f, ensure_ascii=True, indent=4)","metadata":{"execution":{"iopub.status.busy":"2021-12-10T19:09:38.501471Z","iopub.execute_input":"2021-12-10T19:09:38.501774Z","iopub.status.idle":"2021-12-10T19:09:38.949195Z","shell.execute_reply.started":"2021-12-10T19:09:38.501731Z","shell.execute_reply":"2021-12-10T19:09:38.948557Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nos.makedirs('/kaggle/working/train2017', exist_ok=True)\nos.makedirs('/kaggle/working/val2017', exist_ok=True)","metadata":{"execution":{"iopub.status.busy":"2021-12-10T19:09:38.950776Z","iopub.execute_input":"2021-12-10T19:09:38.951464Z","iopub.status.idle":"2021-12-10T19:09:38.957767Z","shell.execute_reply.started":"2021-12-10T19:09:38.951413Z","shell.execute_reply":"2021-12-10T19:09:38.956747Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import shutil\nfor i, row in tqdm(df.iterrows(), total = len(df)):\n    base_dir = 'val2017' if row['is_valid'] else 'train2017'\n    fname = f\"{row['image_id']}.jpg\"\n    shutil.copyfile(row['path'], f\"/kaggle/working/{base_dir}/{fname}\")","metadata":{"execution":{"iopub.status.busy":"2021-12-10T19:09:38.95926Z","iopub.execute_input":"2021-12-10T19:09:38.959556Z","iopub.status.idle":"2021-12-10T19:10:47.714603Z","shell.execute_reply.started":"2021-12-10T19:09:38.959523Z","shell.execute_reply":"2021-12-10T19:10:47.713633Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Sanity check","metadata":{}},{"cell_type":"code","source":"!pip install -Uqqq 'git+https://github.com/cocodataset/cocoapi.git#subdirectory=PythonAPI'","metadata":{"execution":{"iopub.status.busy":"2021-12-10T19:12:51.980453Z","iopub.execute_input":"2021-12-10T19:12:51.981061Z","iopub.status.idle":"2021-12-10T19:13:17.59021Z","shell.execute_reply.started":"2021-12-10T19:12:51.981016Z","shell.execute_reply":"2021-12-10T19:13:17.589011Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from pycocotools.coco import COCO\nimport matplotlib.pyplot as plt\nfrom PIL import Image\nfrom random import sample","metadata":{"execution":{"iopub.status.busy":"2021-12-10T19:13:23.244879Z","iopub.execute_input":"2021-12-10T19:13:23.24579Z","iopub.status.idle":"2021-12-10T19:13:23.257394Z","shell.execute_reply.started":"2021-12-10T19:13:23.245736Z","shell.execute_reply":"2021-12-10T19:13:23.256503Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_dir = '/kaggle/working/train2017'\nann_file = '/kaggle/working/annotations_train.json'\ncoco = COCO(ann_file)\nimg_ids = coco.getImgIds()","metadata":{"execution":{"iopub.status.busy":"2021-12-10T19:13:25.147138Z","iopub.execute_input":"2021-12-10T19:13:25.147943Z","iopub.status.idle":"2021-12-10T19:13:25.428697Z","shell.execute_reply.started":"2021-12-10T19:13:25.147868Z","shell.execute_reply":"2021-12-10T19:13:25.427652Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"n_row = 3\nn_col = 2\nimgs = coco.loadImgs(sample(img_ids, n_row * n_col))\n_, axs = plt.subplots(n_row, n_col, figsize=(12 * n_col, 8 * n_row))\naxs = axs.flatten()\nfor img, ax in zip(imgs, axs):\n    img_img = Image.open(f\"{data_dir}/{img['file_name']}\")\n    anns = coco.loadAnns(coco.getAnnIds(imgIds=[img['id']]))\n    ax.imshow(img_img)\n    plt.sca(ax)\n    coco.showAnns(anns, draw_bbox=True)\n    plt.axis('off')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-12-10T19:13:26.98883Z","iopub.execute_input":"2021-12-10T19:13:26.989433Z","iopub.status.idle":"2021-12-10T19:13:29.069423Z","shell.execute_reply.started":"2021-12-10T19:13:26.989384Z","shell.execute_reply":"2021-12-10T19:13:29.068161Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Ziping the files so kaggle can assemble a dataset\n\nthe final dataset can be found [HERE](https://www.kaggle.com/coldfir3/great-barrier-reef-yolov5)","metadata":{}},{"cell_type":"code","source":"shutil.make_archive('val2017', 'zip', 'val2017')\nshutil.make_archive('train2017', 'zip', 'train2017')","metadata":{"execution":{"iopub.status.busy":"2021-12-10T19:13:29.626367Z","iopub.execute_input":"2021-12-10T19:13:29.626949Z","iopub.status.idle":"2021-12-10T19:16:06.963824Z","shell.execute_reply.started":"2021-12-10T19:13:29.626883Z","shell.execute_reply":"2021-12-10T19:16:06.962065Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"shutil.rmtree('val2017') \nshutil.rmtree('train2017') ","metadata":{"execution":{"iopub.status.busy":"2021-12-10T19:16:06.965362Z","iopub.execute_input":"2021-12-10T19:16:06.965654Z","iopub.status.idle":"2021-12-10T19:16:07.611025Z","shell.execute_reply.started":"2021-12-10T19:16:06.965623Z","shell.execute_reply":"2021-12-10T19:16:07.610199Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}