{"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":"## 🦄 Acknowledgement\n- Title...................: [Train] COVID-19 Detection using YOLOv5\n- Link....................: https://www.kaggle.com/ayuraj/train-covid-19-detection-using-yolov5#%E2%98%80%EF%B8%8F-Imports-and-Setup\n- Author..............: Ayush Thakur (https://www.kaggle.com/ayuraj)\n- Version.............: 10","metadata":{}},{"cell_type":"markdown","source":"This is the inferring version of above [notebook](https://www.kaggle.com/ayuraj/train-covid-19-detection-using-yolov5#%E2%98%80%EF%B8%8F-Imports-and-Setup). Since our inferring code needs to be run with hidden dataset in a disconnected state, so we need to process test data from scratch in this code, at the same time introduce the pre-trained model and yolov5 repository. \n\n**Notice:**\n- This code is only for image level samples, and keep the \"PredictionString\" of study level samples same as submission.csv.\n- This notebook use yolov5s which trained 20 epochs as pretrained model, you could train your own yolov5 model with [this notebook](https://www.kaggle.com/ayuraj/train-covid-19-detection-using-yolov5#%E2%98%80%EF%B8%8F-Imports-and-Setup). If you want to improve your accuracy, consider using 5x instead of 5s. But please notice that it would take more time in training and prediction.\n\n![img](https://user-images.githubusercontent.com/26833433/114313216-f0a5e100-9af5-11eb-8445-c682b60da2e3.png)","metadata":{}},{"cell_type":"markdown","source":"## ⌨️ Unzip YOLOv5","metadata":{}},{"cell_type":"code","source":"%cd /kaggle\n!mkdir YOLO\n!unzip -o input/github-yolov5/yolov5.zip -d YOLO/","metadata":{"scrolled":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2021-06-11T09:44:25.841503Z","iopub.execute_input":"2021-06-11T09:44:25.84189Z","iopub.status.idle":"2021-06-11T09:44:27.331191Z","shell.execute_reply.started":"2021-06-11T09:44:25.841811Z","shell.execute_reply":"2021-06-11T09:44:27.330311Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%ls YOLO/yolov5","metadata":{"execution":{"iopub.status.busy":"2021-06-11T09:44:27.334259Z","iopub.execute_input":"2021-06-11T09:44:27.33452Z","iopub.status.idle":"2021-06-11T09:44:27.963516Z","shell.execute_reply.started":"2021-06-11T09:44:27.334491Z","shell.execute_reply":"2021-06-11T09:44:27.962597Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 📷 Transform test data","metadata":{}},{"cell_type":"code","source":"!conda install '/kaggle/input/pydicom-conda-helper/libjpeg-turbo-2.1.0-h7f98852_0.tar.bz2' -c conda-forge -y\n!conda install '/kaggle/input/pydicom-conda-helper/libgcc-ng-9.3.0-h2828fa1_19.tar.bz2' -c conda-forge -y\n!conda install '/kaggle/input/pydicom-conda-helper/gdcm-2.8.9-py37h500ead1_1.tar.bz2' -c conda-forge -y\n!conda install '/kaggle/input/pydicom-conda-helper/conda-4.10.1-py37h89c1867_0.tar.bz2' -c conda-forge -y\n!conda install '/kaggle/input/pydicom-conda-helper/certifi-2020.12.5-py37h89c1867_1.tar.bz2' -c conda-forge -y\n!conda install '/kaggle/input/pydicom-conda-helper/openssl-1.1.1k-h7f98852_0.tar.bz2' -c conda-forge -y","metadata":{"_kg_hide-output":true,"scrolled":true,"execution":{"iopub.status.busy":"2021-06-11T09:44:27.966976Z","iopub.execute_input":"2021-06-11T09:44:27.96724Z","iopub.status.idle":"2021-06-11T09:45:36.098709Z","shell.execute_reply.started":"2021-06-11T09:44:27.967211Z","shell.execute_reply":"2021-06-11T09:45:36.097729Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport os\nfrom PIL import Image\nfrom tqdm.auto import tqdm\nimport pydicom\nfrom pydicom.pixel_data_handlers.util import apply_voi_lut","metadata":{"execution":{"iopub.status.busy":"2021-06-11T09:45:36.102203Z","iopub.execute_input":"2021-06-11T09:45:36.102483Z","iopub.status.idle":"2021-06-11T09:45:36.356157Z","shell.execute_reply.started":"2021-06-11T09:45:36.102452Z","shell.execute_reply":"2021-06-11T09:45:36.355296Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# reference: https://www.kaggle.com/xhlulu/siim-covid-19-convert-to-jpg-256px/notebook?scriptVersionId=63196459\ndef read_xray(path, voi_lut = True, fix_monochrome = True):\n    # Original from: https://www.kaggle.com/raddar/convert-dicom-to-np-array-the-correct-way\n    dicom = pydicom.read_file(path)\n    \n    # VOI LUT (if available by DICOM device) is used to transform raw DICOM data to \n    # \"human-friendly\" view\n    if voi_lut:\n        data = apply_voi_lut(dicom.pixel_array, dicom)\n    else:\n        data = dicom.pixel_array\n               \n    # depending on this value, X-ray may look inverted - fix that:\n    if fix_monochrome and dicom.PhotometricInterpretation == \"MONOCHROME1\":\n        data = np.amax(data) - data\n        \n    data = data - np.min(data)\n    data = data / np.max(data)\n    data = (data * 255).astype(np.uint8)\n        \n    return data\n\n\ndef resize(array, size, keep_ratio=False, resample=Image.LANCZOS):\n    # Original from: https://www.kaggle.com/xhlulu/vinbigdata-process-and-resize-to-image\n    im = Image.fromarray(array)\n    \n    if keep_ratio:\n        im.thumbnail((size, size), resample)\n    else:\n        im = im.resize((size, size), resample)\n    \n    return im","metadata":{"execution":{"iopub.status.busy":"2021-06-11T09:45:36.358209Z","iopub.execute_input":"2021-06-11T09:45:36.358476Z","iopub.status.idle":"2021-06-11T09:45:36.368994Z","shell.execute_reply.started":"2021-06-11T09:45:36.35845Z","shell.execute_reply":"2021-06-11T09:45:36.368087Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"TEST_PATH = '/kaggle/tmp/test_data/'\nos.makedirs(TEST_PATH, exist_ok=True)\ndims_mapping = dict()\n\nfor dirname, _, filenames in tqdm(os.walk(f'/kaggle/input/siim-covid19-detection/test')):\n    for file in filenames:\n        # set keep_ratio=True to have original aspect ratio\n        xray = read_xray(os.path.join(dirname, file))\n        im = resize(xray, size=256)\n        im.save(os.path.join(TEST_PATH, file.replace('dcm', 'jpg')))\n        dims_mapping[file.replace('.dcm', '')] = xray.shape","metadata":{"execution":{"iopub.status.busy":"2021-06-11T09:45:36.372541Z","iopub.execute_input":"2021-06-11T09:45:36.372854Z","iopub.status.idle":"2021-06-11T09:52:16.205274Z","shell.execute_reply.started":"2021-06-11T09:45:36.372815Z","shell.execute_reply":"2021-06-11T09:52:16.20442Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 🎨 Predict","metadata":{}},{"cell_type":"code","source":"MODEL_PATH = '/kaggle/input/yolov5s-20epochs/best.pt'\nIMG_SIZE = 256","metadata":{"execution":{"iopub.status.busy":"2021-06-11T09:52:16.206628Z","iopub.execute_input":"2021-06-11T09:52:16.206975Z","iopub.status.idle":"2021-06-11T09:52:16.211092Z","shell.execute_reply.started":"2021-06-11T09:52:16.206936Z","shell.execute_reply":"2021-06-11T09:52:16.210223Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%cd /kaggle/YOLO/yolov5\n!python detect.py --weights {MODEL_PATH} \\\n                  --source {TEST_PATH} \\\n                  --img {IMG_SIZE} \\\n                  --conf 0.281 \\\n                  --iou-thres 0.5 \\\n                  --max-det 3 \\\n                  --save-txt \\\n                  --save-conf","metadata":{"_kg_hide-output":true,"scrolled":true,"execution":{"iopub.status.busy":"2021-06-11T09:52:16.213618Z","iopub.execute_input":"2021-06-11T09:52:16.213967Z","iopub.status.idle":"2021-06-11T09:52:55.922372Z","shell.execute_reply.started":"2021-06-11T09:52:16.213931Z","shell.execute_reply":"2021-06-11T09:52:55.921403Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"PRED_PATH = 'runs/detect/exp/labels'\nprediction_files = os.listdir(PRED_PATH)\nprint('Number of test images predicted as opacity: ', len(prediction_files))","metadata":{"execution":{"iopub.status.busy":"2021-06-11T09:52:55.924247Z","iopub.execute_input":"2021-06-11T09:52:55.924606Z","iopub.status.idle":"2021-06-11T09:52:55.932829Z","shell.execute_reply.started":"2021-06-11T09:52:55.924563Z","shell.execute_reply":"2021-06-11T09:52:55.93181Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 💾 Submit","metadata":{}},{"cell_type":"code","source":"# The submisison requires xmin, ymin, xmax, ymax format. \n# YOLOv5 returns x_center, y_center, width, height\ndef correct_bbox_format(bboxes, id_name):\n    correct_bboxes = []\n    H, W = dims_mapping[id_name]\n    for b in bboxes:\n        xc, yc = int(np.round(b[0] * W)), int(np.round(b[1] * H))\n        w, h = int(np.round(b[2] * W)), int(np.round(b[3] * H))\n\n        xmin = xc - int(np.round(w/2))\n        xmax = xc + int(np.round(w/2))\n        ymin = yc - int(np.round(h/2))\n        ymax = yc + int(np.round(h/2))\n        \n        correct_bboxes.append([xmin, ymin, xmax, ymax])\n        \n    return correct_bboxes\n\n# Read the txt file generated by YOLOv5 during inference and extract \n# confidence and bounding box coordinates.\ndef get_conf_bboxes(file_path):\n    confidence = []\n    bboxes = []\n    with open(file_path, 'r') as file:\n        for line in file:\n            preds = line.strip('\\n').split(' ')\n            preds = list(map(float, preds))\n            confidence.append(preds[-1])\n            bboxes.append(preds[1:-1])\n    return confidence, bboxes","metadata":{"execution":{"iopub.status.busy":"2021-06-11T09:52:55.934297Z","iopub.execute_input":"2021-06-11T09:52:55.934785Z","iopub.status.idle":"2021-06-11T09:52:55.946555Z","shell.execute_reply.started":"2021-06-11T09:52:55.934748Z","shell.execute_reply":"2021-06-11T09:52:55.945512Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub_df = pd.read_csv('/kaggle/input/siim-covid19-detection/sample_submission.csv')\nsub_df.tail()","metadata":{"execution":{"iopub.status.busy":"2021-06-11T09:52:55.949278Z","iopub.execute_input":"2021-06-11T09:52:55.949572Z","iopub.status.idle":"2021-06-11T09:52:55.990862Z","shell.execute_reply.started":"2021-06-11T09:52:55.949544Z","shell.execute_reply":"2021-06-11T09:52:55.990094Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Prediction loop for submission\npredictions = []\n\nfor i in tqdm(range(len(sub_df))):\n    row = sub_df.loc[i]\n    id_name = row.id.split('_')[0]\n    id_level = row.id.split('_')[-1]\n    \n    if id_level == 'study':\n        # do study-level classification\n        predictions.append(\"negative 1 0 0 1 1\") # dummy prediction\n        \n    elif id_level == 'image':\n        # we can do image-level classification here.\n        # also we can rely on the object detector's classification head.\n        # for this example submisison we will use YOLO's classification head. \n        # since we already ran the inference we know which test images belong to opacity.\n        if f'{id_name}.txt' in prediction_files:\n            # opacity label\n            confidence, bboxes = get_conf_bboxes(f'{PRED_PATH}/{id_name}.txt')\n            bboxes = correct_bbox_format(bboxes, id_name)\n            pred_string = ''\n            for j, conf in enumerate(confidence):\n                pred_string += f'opacity {conf} ' + ' '.join(map(str, bboxes[j])) + ' '\n            predictions.append(pred_string[:-1]) \n        else:\n            predictions.append(\"none 1 0 0 1 1\")","metadata":{"execution":{"iopub.status.busy":"2021-06-11T09:52:55.992071Z","iopub.execute_input":"2021-06-11T09:52:55.992392Z","iopub.status.idle":"2021-06-11T09:52:56.402133Z","shell.execute_reply.started":"2021-06-11T09:52:55.992358Z","shell.execute_reply":"2021-06-11T09:52:56.401178Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub_df['PredictionString'] = predictions\nsub_df.to_csv('/kaggle/working/submission.csv', index=False)\nsub_df.tail()","metadata":{"execution":{"iopub.status.busy":"2021-06-11T09:52:56.403574Z","iopub.execute_input":"2021-06-11T09:52:56.403954Z","iopub.status.idle":"2021-06-11T09:52:56.637023Z","shell.execute_reply.started":"2021-06-11T09:52:56.403912Z","shell.execute_reply":"2021-06-11T09:52:56.636237Z"},"trusted":true},"execution_count":null,"outputs":[]}]}