{"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":"# Environment","metadata":{}},{"cell_type":"code","source":"%cd /kaggle/\n%ls","metadata":{"execution":{"iopub.status.busy":"2021-08-07T00:41:18.804144Z","iopub.execute_input":"2021-08-07T00:41:18.804542Z","iopub.status.idle":"2021-08-07T00:41:19.455598Z","shell.execute_reply.started":"2021-08-07T00:41:18.804456Z","shell.execute_reply":"2021-08-07T00:41:19.454729Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!mkdir training\n%cd training","metadata":{"execution":{"iopub.status.busy":"2021-08-07T00:41:20.224299Z","iopub.execute_input":"2021-08-07T00:41:20.224663Z","iopub.status.idle":"2021-08-07T00:41:20.895091Z","shell.execute_reply.started":"2021-08-07T00:41:20.224630Z","shell.execute_reply":"2021-08-07T00:41:20.893963Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Download YOLOv5\n!git clone https://github.com/ultralytics/yolov5  # clone repo\n%cd yolov5\n# Install dependencies\n%pip install -qr requirements.txt  # install dependencies\n\n%cd ../\n\n%pip install --upgrade torch\n%pip install --upgrade torchvision\nimport torch\nprint(f\"Setup complete. Using torch {torch.__version__} ({torch.cuda.get_device_properties(0).name if torch.cuda.is_available() else 'CPU'})\")","metadata":{"execution":{"iopub.status.busy":"2021-08-07T00:41:22.315341Z","iopub.execute_input":"2021-08-07T00:41:22.315702Z","iopub.status.idle":"2021-08-07T00:43:15.511964Z","shell.execute_reply.started":"2021-08-07T00:41:22.315669Z","shell.execute_reply":"2021-08-07T00:43:15.511116Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Install W&B \n%pip install -q --upgrade wandb\n# Login with token, follow with the guide\nimport wandb\nwandb.login()","metadata":{"execution":{"iopub.status.busy":"2021-08-07T00:43:42.004617Z","iopub.execute_input":"2021-08-07T00:43:42.005098Z","iopub.status.idle":"2021-08-07T00:44:04.422598Z","shell.execute_reply.started":"2021-08-07T00:43:42.005060Z","shell.execute_reply":"2021-08-07T00:44:04.421715Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Import lib\nimport os\nimport gc\nimport cv2\nimport numpy as np\nimport pandas as pd\nfrom tqdm import tqdm\nimport json\nimport yaml\nfrom shutil import copyfile\nimport matplotlib.pyplot as plt\nfrom sklearn.model_selection import StratifiedKFold","metadata":{"execution":{"iopub.status.busy":"2021-08-07T00:44:06.841192Z","iopub.execute_input":"2021-08-07T00:44:06.841573Z","iopub.status.idle":"2021-08-07T00:44:07.799495Z","shell.execute_reply.started":"2021-08-07T00:44:06.841537Z","shell.execute_reply":"2021-08-07T00:44:07.794441Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# DATA PROCESSING","metadata":{}},{"cell_type":"code","source":"#load json file\njson_file_path = '/kaggle/input/cowboyoutfits/train.json'\ndata = json.load(open(json_file_path, 'r'))","metadata":{"execution":{"iopub.status.busy":"2021-08-07T00:44:10.074725Z","iopub.execute_input":"2021-08-07T00:44:10.075087Z","iopub.status.idle":"2021-08-07T00:44:10.143293Z","shell.execute_reply.started":"2021-08-07T00:44:10.075054Z","shell.execute_reply":"2021-08-07T00:44:10.142480Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Display the labels vs. numbers\ncount = 0\nla = [87, 1034, 131, 318, 588]\n\nfor x in la:\n    for i in range(len(data['annotations'])):\n        if data['annotations'][i]['category_id'] == x:\n            count+=1\n    print(x, count)","metadata":{"execution":{"iopub.status.busy":"2021-08-07T00:44:12.463858Z","iopub.execute_input":"2021-08-07T00:44:12.464180Z","iopub.status.idle":"2021-08-07T00:44:12.479259Z","shell.execute_reply.started":"2021-08-07T00:44:12.464151Z","shell.execute_reply":"2021-08-07T00:44:12.478196Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# convert the bounding box from COCO to YOLO format.\n\ndef cc2yolo_bbox(img_width, img_height, bbox):\n    dw = 1. / img_width\n    dh = 1. / img_height\n    x = bbox[0] + bbox[2] / 2.0\n    y = bbox[1] + bbox[3] / 2.0\n    w = bbox[2]\n    h = bbox[3]\n \n    x = x * dw\n    w = w * dw\n    y = y * dh\n    h = h * dh\n    return (x, y, w, h)","metadata":{"execution":{"iopub.status.busy":"2021-08-07T00:44:14.706835Z","iopub.execute_input":"2021-08-07T00:44:14.707551Z","iopub.status.idle":"2021-08-07T00:44:14.717818Z","shell.execute_reply.started":"2021-08-07T00:44:14.707508Z","shell.execute_reply":"2021-08-07T00:44:14.717054Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 需要注意下因为我们的annotation lable是不连续的,会导致后面报错,所以这里生成一个map映射\ncate_id_map = {}\nnum = 0\nfor cate in data['categories']:\n    cate_id_map[cate['id']] = num\n    num+=1\n    \nprint(cate_id_map)","metadata":{"execution":{"iopub.status.busy":"2021-08-07T00:44:16.869884Z","iopub.execute_input":"2021-08-07T00:44:16.870216Z","iopub.status.idle":"2021-08-07T00:44:16.876019Z","shell.execute_reply.started":"2021-08-07T00:44:16.870186Z","shell.execute_reply":"2021-08-07T00:44:16.875031Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# transfer the format of annotation and generated a custom train dataframe for further analysis\n\ntrain_pd = pd.DataFrame(columns=['id','file_name','annotation','box_count','object_count', 'object_id', 'image_width','image_height'])\n\nfor i in tqdm(range(len(data['images']))):\n    filename = data['images'][i]['file_name']\n    image_width = data['images'][i]['width']\n    image_height = data['images'][i]['height']\n    image_id = data['images'][i]['id']\n    \n    annotation = []\n    box_count = 0\n    object_count = 0\n    object_id = []\n    \n    for anno in data['annotations']:\n        if anno['image_id'] == image_id:\n            box_count+=1\n            yolo_bbox = cc2yolo_bbox(image_width, image_height, anno['bbox']) # \"bbox\": [x,y,width,height]\n            temp_annotation = '{} {} {} {} {}'.format(cate_id_map[anno['category_id']], yolo_bbox[0], yolo_bbox[1], yolo_bbox[2], yolo_bbox[3])\n            \n            annotation.append(temp_annotation)\n            \n            if cate_id_map[anno['category_id']] not in object_id:\n                object_count+=1\n                object_id.append(cate_id_map[anno['category_id']])\n            \n    train_pd.loc[i] = image_id, filename, annotation, box_count, object_count, object_id, image_width, image_height","metadata":{"execution":{"iopub.status.busy":"2021-08-07T00:44:19.110201Z","iopub.execute_input":"2021-08-07T00:44:19.110665Z","iopub.status.idle":"2021-08-07T00:44:36.786340Z","shell.execute_reply.started":"2021-08-07T00:44:19.110620Z","shell.execute_reply":"2021-08-07T00:44:36.785190Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_pd.sample(10)\n\n#主要说明2点，新增了\n# box_count,目标框数量\n# object_count, 目标种类数量\n# object_id, 目标种类","metadata":{"execution":{"iopub.status.busy":"2021-08-07T00:44:36.788000Z","iopub.execute_input":"2021-08-07T00:44:36.788424Z","iopub.status.idle":"2021-08-07T00:44:36.817300Z","shell.execute_reply.started":"2021-08-07T00:44:36.788370Z","shell.execute_reply":"2021-08-07T00:44:36.816350Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# prepare the k-fold data\nNUM_FOLD = 5\n\nFold = StratifiedKFold(n_splits=NUM_FOLD, shuffle=True, random_state=233)\n\ndf_folds = train_pd.copy()\n\ndf_folds.loc[:, 'stratify_group'] = np.char.add(\n    df_folds['object_count'].values.astype(str),\n    df_folds['box_count'].apply(lambda x: f'_{x // 5}').values.astype(str)\n)\n\nfor fold_number,(train_index, val_index) in enumerate(Fold.split(X=df_folds.index, y=df_folds['stratify_group'])):\n    df_folds.loc[df_folds.iloc[val_index].index, 'fold'] = fold_number","metadata":{"execution":{"iopub.status.busy":"2021-08-07T00:44:36.819064Z","iopub.execute_input":"2021-08-07T00:44:36.819405Z","iopub.status.idle":"2021-08-07T00:44:36.855277Z","shell.execute_reply.started":"2021-08-07T00:44:36.819369Z","shell.execute_reply":"2021-08-07T00:44:36.854156Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_pd['box_count'].value_counts()","metadata":{"execution":{"iopub.status.busy":"2021-08-07T01:29:01.768350Z","iopub.execute_input":"2021-08-07T01:29:01.768754Z","iopub.status.idle":"2021-08-07T01:29:01.782443Z","shell.execute_reply.started":"2021-08-07T01:29:01.768720Z","shell.execute_reply":"2021-08-07T01:29:01.781614Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"📌📌\n这里简单说明一下，分组思路是基于`StractifiedKfold`, 但是因为对于目标检测，除了label balance 还有很多因素需要考虑，比如说目标检测框的数量分布，种类分布，甚至面积大小分布，所以这边参考了一下stackoverflow 上一个[讨论](https://stackoverflow.com/questions/64164932/stratified-k-fold-for-multi-class-object-detection)。 使用了floor division `//5` 是因为，根据观察框的数量分布，大部分都在5以内了，所以使用了5 对数据进行分级，同时和objec_number一起生成一个新的子类, 包含框和目标类的数据。 然后再进行k-fold分组。 同时和这边应该还不是最优解,也许还有很多问题，可以讨论一下。","metadata":{}},{"cell_type":"code","source":"df_folds.sample(5)","metadata":{"execution":{"iopub.status.busy":"2021-08-07T00:44:36.857184Z","iopub.execute_input":"2021-08-07T00:44:36.857641Z","iopub.status.idle":"2021-08-07T00:44:36.880881Z","shell.execute_reply.started":"2021-08-07T00:44:36.857601Z","shell.execute_reply":"2021-08-07T00:44:36.879687Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 看看刚刚的新类分布\ndf_folds['stratify_group'].value_counts()","metadata":{"execution":{"iopub.status.busy":"2021-08-07T00:44:36.882611Z","iopub.execute_input":"2021-08-07T00:44:36.883103Z","iopub.status.idle":"2021-08-07T00:44:36.899484Z","shell.execute_reply.started":"2021-08-07T00:44:36.883061Z","shell.execute_reply":"2021-08-07T00:44:36.898617Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#查看 fold 分布数量\ndf_folds['fold'].value_counts()","metadata":{"execution":{"iopub.status.busy":"2021-08-07T00:44:36.900760Z","iopub.execute_input":"2021-08-07T00:44:36.901330Z","iopub.status.idle":"2021-08-07T00:44:36.910643Z","shell.execute_reply.started":"2021-08-07T00:44:36.901293Z","shell.execute_reply":"2021-08-07T00:44:36.909562Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#这里再写一个 检查函数，来double check我们分组是否合理。\n\ndef list_class_number(fold_number):\n    pd_tmp = df_folds.loc[df_folds['fold'] == fold_number]\n\n    belt = 0\n    sunglasses = 0\n    boot = 0\n    cowboy_hat = 0\n    jacket = 0\n\n    for i in range(len(pd_tmp)):\n        for x in pd_tmp.iloc[i]['object_id']:\n            if x == 0:\n                belt+=1\n            if x == 1:\n                sunglasses+=1\n            if x == 2:\n                boot+=1\n            if x == 3:\n                cowboy_hat+=1\n            if x == 4:\n                jacket+=1\n\n    print(f'fold_{fold_number}, belt:{belt}, sunglasses:{sunglasses}, boot:{boot}, cowboy_bat:{cowboy_hat}, jacket:{jacket}\\n')\n    print(pd_tmp['box_count'].value_counts())\n    print(pd_tmp['object_count'].value_counts())","metadata":{"execution":{"iopub.status.busy":"2021-08-07T00:44:54.074912Z","iopub.execute_input":"2021-08-07T00:44:54.075273Z","iopub.status.idle":"2021-08-07T00:44:54.083817Z","shell.execute_reply.started":"2021-08-07T00:44:54.075244Z","shell.execute_reply":"2021-08-07T00:44:54.082806Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 第一个分组\nlist_class_number(0)\n\n# 0 2 300 39 57 236","metadata":{"execution":{"iopub.status.busy":"2021-08-07T00:44:56.884272Z","iopub.execute_input":"2021-08-07T00:44:56.884667Z","iopub.status.idle":"2021-08-07T00:44:56.978573Z","shell.execute_reply.started":"2021-08-07T00:44:56.884636Z","shell.execute_reply":"2021-08-07T00:44:56.977509Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#第二个分组\nlist_class_number(1)\n\n# 1 2 293 46 76 219","metadata":{"execution":{"iopub.status.busy":"2021-08-07T00:44:59.000493Z","iopub.execute_input":"2021-08-07T00:44:59.000854Z","iopub.status.idle":"2021-08-07T00:44:59.086785Z","shell.execute_reply.started":"2021-08-07T00:44:59.000825Z","shell.execute_reply":"2021-08-07T00:44:59.085545Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# PREPARE DATA FOLDERS","metadata":{}},{"cell_type":"code","source":"NUM_FOLD = 5\ndf = df_folds.copy()","metadata":{"execution":{"iopub.status.busy":"2021-08-07T00:45:07.739490Z","iopub.execute_input":"2021-08-07T00:45:07.739818Z","iopub.status.idle":"2021-08-07T00:45:07.744327Z","shell.execute_reply.started":"2021-08-07T00:45:07.739791Z","shell.execute_reply":"2021-08-07T00:45:07.743380Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for fold in range(NUM_FOLD):\n        print(fold)\n        # Prepare train and valid df\n        train_df = df.loc[df.fold != fold].reset_index(drop=True)\n        valid_df = df.loc[df.fold == fold].reset_index(drop=True)\n\n        # Make dirs\n        os.makedirs(f'/kaggle/training/dataset_folds_{fold}/images/train', exist_ok=True)\n        os.makedirs(f'/kaggle/training/dataset_folds_{fold}/images/valid', exist_ok=True)\n        os.makedirs(f'/kaggle/training/dataset_folds_{fold}/labels/train', exist_ok=True)\n        os.makedirs(f'/kaggle/training/dataset_folds_{fold}/labels/valid', exist_ok=True)\n\n        # Move image and annotations to relevant split folder.\n        \n        for i in tqdm(range(len(train_df))):\n            train_row = train_df.loc[i]\n            train_name = train_row.file_name.split('.')[0]\n            copyfile(f'/kaggle/input/cowboyoutfits/images/{train_name}.jpg', f'/kaggle/training/dataset_folds_{fold}/images/train/{train_name}.jpg')\n            yolo_txt_file = open(f'/kaggle/training/dataset_folds_{fold}/labels/train/{train_name}.txt', 'w')\n            for ann in train_row['annotation']:\n                yolo_txt_file.write(f'{ann}\\n')\n            \n        yolo_txt_file.close()\n        \n        for i in tqdm(range(len(valid_df))):\n            valid_row = valid_df.loc[i]\n            valid_name = valid_row.file_name.split('.')[0]\n            copyfile(f'/kaggle/input/cowboyoutfits/images/{valid_name}.jpg', f'/kaggle/training/dataset_folds_{fold}/images/valid/{valid_name}.jpg')\n            yolo_txt_file = open(f'/kaggle/training/dataset_folds_{fold}/labels/valid/{valid_name}.txt', 'w')\n            for ann in valid_row['annotation']:\n                yolo_txt_file.write(f'{ann}\\n')\n            \n        yolo_txt_file.close()","metadata":{"execution":{"iopub.status.busy":"2021-08-07T00:45:10.828126Z","iopub.execute_input":"2021-08-07T00:45:10.828463Z","iopub.status.idle":"2021-08-07T00:46:17.070261Z","shell.execute_reply.started":"2021-08-07T00:45:10.828431Z","shell.execute_reply":"2021-08-07T00:46:17.069003Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# CHECK OUR DATA FOLDER STRUCTURE\n%ls /kaggle/training/","metadata":{"execution":{"iopub.status.busy":"2021-08-07T00:46:38.050566Z","iopub.execute_input":"2021-08-07T00:46:38.050906Z","iopub.status.idle":"2021-08-07T00:46:38.721557Z","shell.execute_reply.started":"2021-08-07T00:46:38.050878Z","shell.execute_reply":"2021-08-07T00:46:38.720464Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%cat /kaggle/training/dataset_folds_0/labels/train/21f1961c263887ad.txt","metadata":{"execution":{"iopub.status.busy":"2021-08-07T00:46:41.740544Z","iopub.execute_input":"2021-08-07T00:46:41.740983Z","iopub.status.idle":"2021-08-07T00:46:42.499009Z","shell.execute_reply.started":"2021-08-07T00:46:41.740943Z","shell.execute_reply":"2021-08-07T00:46:42.497973Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create  yaml file\n\nfor fold in range(NUM_FOLD):\n    data_yaml = dict(\n        train = f'../dataset_folds_{fold}/images/train/',\n        val = f'../dataset_folds_{fold}/images/valid',\n        nc = 5,\n        names = ['belt', 'sunglasses', 'boot', 'cowboy_hat', 'jacket']\n    )\n\n    # we will make the file under the yolov5/data/ directory.\n    with open(f'/kaggle/training/yolov5/data/data_folds_{fold}.yaml', 'w') as outfile:\n        yaml.dump(data_yaml, outfile, default_flow_style=True)\n    \n%cat /kaggle/training/yolov5/data/data_folds_0.yaml # show your YAML file","metadata":{"execution":{"iopub.status.busy":"2021-08-07T00:46:47.636316Z","iopub.execute_input":"2021-08-07T00:46:47.636693Z","iopub.status.idle":"2021-08-07T00:46:48.354007Z","shell.execute_reply.started":"2021-08-07T00:46:47.636659Z","shell.execute_reply":"2021-08-07T00:46:48.353074Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# CHECK OUR DATA FOLDER STRUCTURE\n%ls /kaggle/training/yolov5/data/","metadata":{"execution":{"iopub.status.busy":"2021-08-07T00:47:11.478820Z","iopub.execute_input":"2021-08-07T00:47:11.479182Z","iopub.status.idle":"2021-08-07T00:47:12.124121Z","shell.execute_reply.started":"2021-08-07T00:47:11.479148Z","shell.execute_reply":"2021-08-07T00:47:12.123140Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# TRAINING","metadata":{}},{"cell_type":"code","source":"%cd yolov5/","metadata":{"execution":{"iopub.status.busy":"2021-08-07T00:47:15.075461Z","iopub.execute_input":"2021-08-07T00:47:15.075821Z","iopub.status.idle":"2021-08-07T00:47:15.085130Z","shell.execute_reply.started":"2021-08-07T00:47:15.075787Z","shell.execute_reply":"2021-08-07T00:47:15.084187Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"IMG_SIZE = 640\nBATCH_SIZE = 64 # wisely choose, please check my W&B page for differencet performance with size [16,32,64]\nEPOCHS = 20\nMODEL = 'yolov5s.pt'  #\nname = f'{MODEL}_BS_{BATCH_SIZE}_EP_{EPOCHS}_fold_'","metadata":{"execution":{"iopub.status.busy":"2021-08-07T00:51:54.136171Z","iopub.execute_input":"2021-08-07T00:51:54.136560Z","iopub.status.idle":"2021-08-07T00:51:54.142781Z","shell.execute_reply.started":"2021-08-07T00:51:54.136522Z","shell.execute_reply":"2021-08-07T00:51:54.140700Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for fold in range(NUM_FOLD):    \n    print('FOLD NUMBER: ', fold)\n    print('<---------------------------------------------------------------->\\n')\n    \n    \n    if fold > 1:\n        break;\n    \n    !python train.py --img {IMG_SIZE} \\\n                     --batch {BATCH_SIZE} \\\n                     --epochs {EPOCHS} \\\n                     --data data_folds_{fold}.yaml \\\n                     --weights {MODEL} \\\n                     --save_period 2\\\n                     --project /kaggle/working/kaggle-cwoboy \\\n                     --name {name}-{fold} \\\n                     --cache\n    print('<---------------------------------------------------------------->\\n')","metadata":{"execution":{"iopub.status.busy":"2021-08-07T00:51:56.969605Z","iopub.execute_input":"2021-08-07T00:51:56.969988Z","iopub.status.idle":"2021-08-07T01:23:59.970574Z","shell.execute_reply.started":"2021-08-07T00:51:56.969948Z","shell.execute_reply":"2021-08-07T01:23:59.969609Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%ls /kaggle/working/kaggle-cwoboy/","metadata":{"execution":{"iopub.status.busy":"2021-08-07T01:38:03.762933Z","iopub.execute_input":"2021-08-07T01:38:03.763299Z","iopub.status.idle":"2021-08-07T01:38:04.450185Z","shell.execute_reply.started":"2021-08-07T01:38:03.763265Z","shell.execute_reply":"2021-08-07T01:38:04.449210Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# zip our result for loacl analysis\n\n!zip -r /kaggle/working/training_result.zip /kaggle/working/kaggle-cwoboy/","metadata":{"execution":{"iopub.status.busy":"2021-08-07T01:39:29.514717Z","iopub.execute_input":"2021-08-07T01:39:29.515128Z","iopub.status.idle":"2021-08-07T01:39:34.193726Z","shell.execute_reply.started":"2021-08-07T01:39:29.515090Z","shell.execute_reply":"2021-08-07T01:39:34.192527Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# INFERENCE","metadata":{}},{"cell_type":"code","source":"test_df = pd.read_csv('/kaggle/input/cowboyoutfits/test.csv')","metadata":{"execution":{"iopub.status.busy":"2021-08-07T01:41:14.602108Z","iopub.execute_input":"2021-08-07T01:41:14.602482Z","iopub.status.idle":"2021-08-07T01:41:14.623712Z","shell.execute_reply.started":"2021-08-07T01:41:14.602431Z","shell.execute_reply":"2021-08-07T01:41:14.622869Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"os.makedirs('/kaggle/training/inference/test', exist_ok=True)","metadata":{"execution":{"iopub.status.busy":"2021-08-07T01:41:15.787273Z","iopub.execute_input":"2021-08-07T01:41:15.787699Z","iopub.status.idle":"2021-08-07T01:41:15.793845Z","shell.execute_reply.started":"2021-08-07T01:41:15.787654Z","shell.execute_reply":"2021-08-07T01:41:15.792766Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for i in tqdm(range(len(test_df))):\n    test_row = test_df.loc[i]\n    test_name = test_row.file_name.split('.')[0]\n    copyfile(f'/kaggle/input/cowboyoutfits/images/{test_name}.jpg', f'/kaggle/training/inference/test/{test_name}.jpg')","metadata":{"execution":{"iopub.status.busy":"2021-08-07T01:41:16.947762Z","iopub.execute_input":"2021-08-07T01:41:16.948109Z","iopub.status.idle":"2021-08-07T01:41:25.784774Z","shell.execute_reply.started":"2021-08-07T01:41:16.948078Z","shell.execute_reply":"2021-08-07T01:41:25.783862Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"TEST_PATH = '../inference/test/'\n\nMODEL_PATH = [\n    '/kaggle/working/kaggle-cwoboy/yolov5s.pt_BS_64_EP_20_fold_-0/weights/best.pt',\n    '/kaggle/working/kaggle-cwoboy/yolov5s.pt_BS_64_EP_20_fold_-1/weights/best.pt',\n    #'/kaggle/working/kaggle-cwoboy/yolov5s.pt_BS_64_EP_20_fold_-2/weights/best.pt',\n    #'/kaggle/working/kaggle-cwoboy/yolov5s.pt_BS_64_EP_20_fold_-3/weights/best.pt',\n    #'/kaggle/working/kaggle-cwoboy/yolov5s.pt_BS_64_EP_20_fold_-4/weights/best.pt',\n    \n]\n#IMAGE_PATH = '../cowboyoutfits/images/'\n\n#fold 0   CONF 0.680","metadata":{"execution":{"iopub.status.busy":"2021-08-07T01:42:58.293225Z","iopub.execute_input":"2021-08-07T01:42:58.293627Z","iopub.status.idle":"2021-08-07T01:42:58.299207Z","shell.execute_reply.started":"2021-08-07T01:42:58.293588Z","shell.execute_reply":"2021-08-07T01:42:58.297771Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# GO DETECT\n%cd /kaggle/training/yolov5/","metadata":{"execution":{"iopub.status.busy":"2021-08-07T01:43:01.082244Z","iopub.execute_input":"2021-08-07T01:43:01.082668Z","iopub.status.idle":"2021-08-07T01:43:01.090502Z","shell.execute_reply.started":"2021-08-07T01:43:01.082636Z","shell.execute_reply":"2021-08-07T01:43:01.088128Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!python detect.py --weights {MODEL_PATH[0]} {MODEL_PATH[1]} \\\n                  --source {TEST_PATH} \\\n                  --conf 0.25 \\\n                  --iou-thres 0.5 \\\n                  --save-txt \\\n                  --save-conf \\\n                  --max-det 50 \\\n                  --augment \\\n                  --half","metadata":{"execution":{"iopub.status.busy":"2021-08-07T01:44:21.896651Z","iopub.execute_input":"2021-08-07T01:44:21.897002Z","iopub.status.idle":"2021-08-07T01:45:45.834561Z","shell.execute_reply.started":"2021-08-07T01:44:21.896969Z","shell.execute_reply":"2021-08-07T01:45:45.833432Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#GET THE RIGHT PRED PATH\nPRED_PATH = '/kaggle/training/yolov5/runs/detect/exp3/labels/'\n\nprediction_files = os.listdir(PRED_PATH)\nprint('Number of test images predicted as opaque: ', len(prediction_files))","metadata":{"execution":{"iopub.status.busy":"2021-08-07T01:46:41.636193Z","iopub.execute_input":"2021-08-07T01:46:41.636622Z","iopub.status.idle":"2021-08-07T01:46:41.644140Z","shell.execute_reply.started":"2021-08-07T01:46:41.636580Z","shell.execute_reply":"2021-08-07T01:46:41.643031Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# MAKE SUBMISSION","metadata":{}},{"cell_type":"code","source":"from PIL import Image","metadata":{"execution":{"iopub.status.busy":"2021-08-07T01:46:44.397896Z","iopub.execute_input":"2021-08-07T01:46:44.398280Z","iopub.status.idle":"2021-08-07T01:46:44.403366Z","shell.execute_reply.started":"2021-08-07T01:46:44.398246Z","shell.execute_reply":"2021-08-07T01:46:44.402400Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def yolo2cc_bbox(img_width, img_height, bbox):\n    x = (bbox[0] - bbox[2] * 0.5) * img_width\n    y = (bbox[1] - bbox[3] * 0.5) * img_height\n    w = bbox[2] * img_width\n    h = bbox[3] * img_height\n    \n    return (x, y, w, h)","metadata":{"execution":{"iopub.status.busy":"2021-08-07T01:46:46.129146Z","iopub.execute_input":"2021-08-07T01:46:46.129553Z","iopub.status.idle":"2021-08-07T01:46:46.135881Z","shell.execute_reply.started":"2021-08-07T01:46:46.129516Z","shell.execute_reply":"2021-08-07T01:46:46.134311Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cate_id_map = {87: 0, 1034: 1, 131: 2, 318: 3, 588: 4}\n\nre_cate_id_map = dict(zip(cate_id_map.values(), cate_id_map.keys()))\n\nre_cate_id_map","metadata":{"execution":{"iopub.status.busy":"2021-08-07T01:46:48.065227Z","iopub.execute_input":"2021-08-07T01:46:48.065626Z","iopub.status.idle":"2021-08-07T01:46:48.072792Z","shell.execute_reply.started":"2021-08-07T01:46:48.065591Z","shell.execute_reply":"2021-08-07T01:46:48.071808Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def make_submission(df, PRED_PATH, IMAGE_PATH):\n    output = []\n    for i in tqdm(range(len(df))):\n        row = df.loc[i] #根据目标df，选择行\n        image_id = row['id'] #找到图片的id\n        file_name = row['file_name'].split('.')[0] #去掉文件名字的后缀'.jpg'， 方便后面读取annotation文件，因为是一样的.\n        prediction_files = os.listdir(PRED_PATH)\n        \n        if f'{file_name}.txt' in prediction_files: # 根据文件名字，检索annotation文件夹下的文件, 如果找到的话：\n            img = Image.open(f'{IMAGE_PATH}/{file_name}.jpg') #这里是为了后面转换yolo to coco 格式时候，要得到图片的size\n            width, height = img.size\n            with open(f'{PRED_PATH}/{file_name}.txt', 'r') as file: #根据前面判断找到有annotation的，准备读取文件。\n                for line in file: #因为annotaion是按照行存的，一个文件下面有多个annotation 就是多个猫框。\n                    preds = line.strip('\\n').split(' ')  #把每行转换成list保存\n                    preds = list(map(float, preds)) #conver string to float\n                    cc_bbox = yolo2cc_bbox(width, height, preds[1:-1]) # 转换 锚框格式.\n                    result = {\n                        'image_id': image_id,\n                        'category_id': re_cate_id_map[preds[0]],\n                        'bbox': cc_bbox,\n                        'score': preds[-1]\n                    }\n\n                    output.append(result)\n    return output","metadata":{"execution":{"iopub.status.busy":"2021-08-07T01:46:52.373122Z","iopub.execute_input":"2021-08-07T01:46:52.373522Z","iopub.status.idle":"2021-08-07T01:46:52.384451Z","shell.execute_reply.started":"2021-08-07T01:46:52.373486Z","shell.execute_reply":"2021-08-07T01:46:52.383103Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"out_sub = make_submission(test_df, PRED_PATH, TEST_PATH)","metadata":{"execution":{"iopub.status.busy":"2021-08-07T01:46:54.482034Z","iopub.execute_input":"2021-08-07T01:46:54.482423Z","iopub.status.idle":"2021-08-07T01:46:55.256023Z","shell.execute_reply.started":"2021-08-07T01:46:54.482373Z","shell.execute_reply":"2021-08-07T01:46:55.254973Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"op_pd = pd.DataFrame(out_sub)\n\nop_pd","metadata":{"execution":{"iopub.status.busy":"2021-08-07T01:46:56.819181Z","iopub.execute_input":"2021-08-07T01:46:56.819535Z","iopub.status.idle":"2021-08-07T01:46:56.849874Z","shell.execute_reply.started":"2021-08-07T01:46:56.819502Z","shell.execute_reply":"2021-08-07T01:46:56.847992Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import zipfile \n\nname = f'{MODEL}_BS_{BATCH_SIZE}_EP_{EPOCHS}_fold_CONF_0.25_IOU_0.5'\n\nop_pd.to_json('/kaggle/working/answer.json',orient='records')\nzf = zipfile.ZipFile(f'/kaggle/working/{name}.zip', 'w')\nzf.write('/kaggle/working/answer.json', f'answer.json')\nzf.close()","metadata":{"execution":{"iopub.status.busy":"2021-08-07T01:54:58.373540Z","iopub.execute_input":"2021-08-07T01:54:58.373918Z","iopub.status.idle":"2021-08-07T01:54:58.386998Z","shell.execute_reply.started":"2021-08-07T01:54:58.373884Z","shell.execute_reply":"2021-08-07T01:54:58.386172Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#delete the result directory，save space :D\n\n!rm -rf /kaggle/working/kaggle-cwoboy/","metadata":{"execution":{"iopub.status.busy":"2021-08-07T01:54:59.705135Z","iopub.execute_input":"2021-08-07T01:54:59.705492Z","iopub.status.idle":"2021-08-07T01:55:00.342207Z","shell.execute_reply.started":"2021-08-07T01:54:59.705459Z","shell.execute_reply":"2021-08-07T01:55:00.341044Z"},"trusted":true},"execution_count":null,"outputs":[]}]}