{"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":"# [SIIM-FISABIO-RSNA COVID-19 Detection](https://www.kaggle.com/c/siim-covid19-detection)\n> Identify and localize COVID-19 abnormalities on chest radiographs\n\n![](https://storage.googleapis.com/kaggle-competitions/kaggle/26680/logos/header.png)","metadata":{}},{"cell_type":"markdown","source":"# COMMIT or not","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nfrom glob import glob\n\nfilepaths = glob('/kaggle/input/siim-covid19-detection/test/**/*dcm',recursive=True)\ntest_df = pd.DataFrame({'filepath':filepaths,})\ntest_df['image_id'] = test_df.filepath.map(lambda x: x.split('/')[-1].replace('.dcm', '')+'_image')\ntest_df['study_id'] = test_df.filepath.map(lambda x: x.split('/')[-3].replace('.dcm', '')+'_study')\ntest_df.to_csv('test-raw.csv',index=False)\ntest_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-08-14T07:05:10.551991Z","iopub.execute_input":"2021-08-14T07:05:10.552377Z","iopub.status.idle":"2021-08-14T07:05:15.467138Z","shell.execute_reply.started":"2021-08-14T07:05:10.552292Z","shell.execute_reply":"2021-08-14T07:05:15.466386Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Submission Mode","metadata":{}},{"cell_type":"code","source":"debug=True\n\nif test_df.shape[0]==1263:\n    commit=False\nelse:\n    commit=True\n    debug=False\n    \ncommit = True\n    \n# debug  = True  \n# commit = True ","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-14T07:05:15.469886Z","iopub.execute_input":"2021-08-14T07:05:15.470143Z","iopub.status.idle":"2021-08-14T07:05:15.476276Z","shell.execute_reply.started":"2021-08-14T07:05:15.470117Z","shell.execute_reply":"2021-08-14T07:05:15.475437Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Install **gdcm** & **libjpeg** without internet","metadata":{}},{"cell_type":"code","source":"if commit:\n    !pip install /kaggle/input/scd-repo-dataset/pycocotools-2.0.2/dist/pycocotools-2.0.2.tar -q\n    !pip install /kaggle/input/scd-repo-dataset/thop-0.0.31.post2005241907-py3-none-any.whl -q\n    !pip install /kaggle/input/scd-repo-dataset/seaborn-0.11.1-py3-none-any.whl -q\n    !pip install /kaggle/input/scd-repo-dataset/albumentations-1.0.0-py3-none-any.whl -q\n    !pip install /kaggle/input/scd-repo-dataset/addict-2.4.0-py3-none-any.whl -q\n    !pip install /kaggle/input/scd-repo-dataset/timm-0.4.12-py3-none-any.whl -q","metadata":{"execution":{"iopub.status.busy":"2021-08-14T07:05:15.479643Z","iopub.execute_input":"2021-08-14T07:05:15.479925Z","iopub.status.idle":"2021-08-14T07:08:01.10655Z","shell.execute_reply.started":"2021-08-14T07:05:15.479902Z","shell.execute_reply":"2021-08-14T07:08:01.105584Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if commit:\n    !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":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Install **WBF**","metadata":{}},{"cell_type":"code","source":"if commit:\n    !pip install -q /kaggle/input/siimcovid19detection-scripts-dataset/wbf","metadata":{"execution":{"iopub.status.busy":"2021-08-14T07:08:01.108442Z","iopub.execute_input":"2021-08-14T07:08:01.108806Z","iopub.status.idle":"2021-08-14T07:08:28.714833Z","shell.execute_reply.started":"2021-08-14T07:08:01.108765Z","shell.execute_reply":"2021-08-14T07:08:28.7138Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Packages","metadata":{}},{"cell_type":"code","source":"import os\nfrom glob import glob\nimport shutil\nfrom tqdm.notebook import tqdm\ntqdm.pandas()\nimport numpy as np\nimport pandas as pd\nimport math\nimport cv2\nimport matplotlib.pyplot as plt","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-08-14T07:08:28.718819Z","iopub.execute_input":"2021-08-14T07:08:28.719216Z","iopub.status.idle":"2021-08-14T07:08:28.984287Z","shell.execute_reply.started":"2021-08-14T07:08:28.719174Z","shell.execute_reply":"2021-08-14T07:08:28.983132Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Args","metadata":{}},{"cell_type":"code","source":"TTA = 1 # cls\ndim = 512 # det\naspect_ratio = False\n\n# params for geometric mean\n## bbox\nALPHA = 0.7 # det\nBETA  = 0.2 # 4cls\nGAMMA = 0.1 # 2cls\n\n## none\nBETA2  = 0.8 # 4cls\nGAMMA2 = 0.2 # 2cls\n\n## negative\nBETA3  = 1.0 # 4cls\nGAMMA3 = 0.0 # 2cls\n\n## bbox-filter\nBBOX_FILTER = True\n\n## detection args\nNMS_CONF = 0.001 # 0.001 - chris\nNMS_IOU  = 0.5\nMAX_DET  = 1000 # max bbox per img","metadata":{"execution":{"iopub.status.busy":"2021-08-14T07:08:28.988514Z","iopub.execute_input":"2021-08-14T07:08:28.988864Z","iopub.status.idle":"2021-08-14T07:08:28.998171Z","shell.execute_reply.started":"2021-08-14T07:08:28.988828Z","shell.execute_reply":"2021-08-14T07:08:28.997406Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Writing Images","metadata":{}},{"cell_type":"code","source":"if commit:\n    !python /kaggle/input/siimcovid19detection-scripts-dataset/dicom2image.py --debug {int(debug)}\\\n                                                                              --img 768 640 512","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2021-08-14T07:10:10.090659Z","iopub.execute_input":"2021-08-14T07:10:10.090971Z","iopub.status.idle":"2021-08-14T07:11:21.772172Z","shell.execute_reply.started":"2021-08-14T07:10:10.090944Z","shell.execute_reply":"2021-08-14T07:11:21.771249Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Inference **Study-Level**","metadata":{}},{"cell_type":"code","source":"if commit:\n    !python /kaggle/input/siimcovid19detection-scripts-dataset/infer_study.py --debug {int(debug)}","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2021-08-14T07:12:03.5161Z","iopub.execute_input":"2021-08-14T07:12:03.516461Z","iopub.status.idle":"2021-08-14T07:20:01.952088Z","shell.execute_reply.started":"2021-08-14T07:12:03.516428Z","shell.execute_reply":"2021-08-14T07:20:01.95081Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if commit:\n    img_cls_df = pd.read_csv('/kaggle/working/image_cls.csv')\n    display(img_cls_df.head(2))\n    display(img_cls_df[[\"0\",\"1\",\"2\",\"3\",\"opacity\"]].iloc[:100].mean(0))","metadata":{"execution":{"iopub.status.busy":"2021-08-14T07:21:15.676941Z","iopub.execute_input":"2021-08-14T07:21:15.677315Z","iopub.status.idle":"2021-08-14T07:21:15.71319Z","shell.execute_reply.started":"2021-08-14T07:21:15.677279Z","shell.execute_reply":"2021-08-14T07:21:15.712451Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# YOLOv5 Repo","metadata":{}},{"cell_type":"code","source":"# !rm -r /kaggle/working/yolov5\n# %cd /kaggle/working","metadata":{"execution":{"iopub.status.busy":"2021-08-14T07:21:18.054096Z","iopub.execute_input":"2021-08-14T07:21:18.054482Z","iopub.status.idle":"2021-08-14T07:21:18.059171Z","shell.execute_reply.started":"2021-08-14T07:21:18.054452Z","shell.execute_reply":"2021-08-14T07:21:18.058125Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if commit:\n    %cp -r /kaggle/input/siimcovid19detection-scripts-dataset/yolov5 /kaggle/working/yolov5\n    %cd /kaggle/working/yolov5","metadata":{"execution":{"iopub.status.busy":"2021-08-14T07:21:19.008432Z","iopub.execute_input":"2021-08-14T07:21:19.008831Z","iopub.status.idle":"2021-08-14T07:21:20.196961Z","shell.execute_reply.started":"2021-08-14T07:21:19.008793Z","shell.execute_reply":"2021-08-14T07:21:20.1961Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Inference **Image-Level**","metadata":{}},{"cell_type":"markdown","source":"## WBF","metadata":{}},{"cell_type":"code","source":"backbones = sorted(glob('/kaggle/input/siimcovid19detection-checkpoint-dataset/det/*/'))\nfolds = [0,1,2,3,4] \n%cd /kaggle/working/yolov5\nfor k,backbone in enumerate(backbones):\n    \n    for fold in folds:\n        \n        print('#'*25)\n        print('### Backbone =',k,', Fold =',fold)\n        print('#'*25)\n        \n        model = backbone + f'/fold-{fold}'\n\n        if commit:\n            !python detect.py --weights_dirs $model\\\n            --img $dim\\\n            --conf $NMS_CONF\\\n            --iou $NMS_IOU\\\n            --source /tmp/Dataset/test/{dim}\\\n            --save-txt\\\n            --save-conf\\\n            --exist-ok\\\n            --save-img 0\\\n            --augment\\\n            --project runs/detect_b{k}_f{fold}\\\n            --max-det $MAX_DET","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2021-08-14T07:21:23.773511Z","iopub.execute_input":"2021-08-14T07:21:23.773829Z","iopub.status.idle":"2021-08-14T07:28:37.68089Z","shell.execute_reply.started":"2021-08-14T07:21:23.773799Z","shell.execute_reply":"2021-08-14T07:28:37.679971Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%cd /kaggle/working","metadata":{"execution":{"iopub.status.busy":"2021-08-14T07:28:58.533987Z","iopub.execute_input":"2021-08-14T07:28:58.534355Z","iopub.status.idle":"2021-08-14T07:28:58.540798Z","shell.execute_reply.started":"2021-08-14T07:28:58.53432Z","shell.execute_reply":"2021-08-14T07:28:58.539851Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Detection Helper","metadata":{}},{"cell_type":"code","source":"def voc2yolo(image_height, image_width, bboxes):\n    \"\"\"\n    voc  => [x1, y1, x2, y1]\n    yolo => [xmid, ymid, w, h] (normalized)\n    \"\"\"\n    \n    bboxes = bboxes.copy().astype(float) # otherwise all value will be 0 as voc_pascal dtype is np.int\n    \n    bboxes[..., [0, 2]] = bboxes[..., [0, 2]]/ image_width\n    bboxes[..., [1, 3]] = bboxes[..., [1, 3]]/ image_height\n    \n    w = bboxes[..., 2] - bboxes[..., 0]\n    h = bboxes[..., 3] - bboxes[..., 1]\n    \n    bboxes[..., 0] = bboxes[..., 0] + w/2\n    bboxes[..., 1] = bboxes[..., 1] + h/2\n    bboxes[..., 2] = w\n    bboxes[..., 3] = h\n    \n    return bboxes\n\ndef yolo2voc(image_height, image_width, bboxes):\n    \"\"\"\n    yolo => [xmid, ymid, w, h] (normalized)\n    voc  => [x1, y1, x2, y1]\n    \n    \"\"\" \n    bboxes = bboxes.copy().astype(float) # otherwise all value will be 0 as voc_pascal dtype is np.int\n    \n    bboxes[..., [0, 2]] = bboxes[..., [0, 2]]* image_width\n    bboxes[..., [1, 3]] = bboxes[..., [1, 3]]* image_height\n    \n    bboxes[..., [0, 1]] = bboxes[..., [0, 1]] - bboxes[..., [2, 3]]/2\n    bboxes[..., [2, 3]] = bboxes[..., [0, 1]] + bboxes[..., [2, 3]]\n    \n    return bboxes\n\ndef coco2yolo(image_height, image_width, bboxes):\n    \"\"\"\n    coco => [xmin, ymin, w, h]\n    yolo => [xmid, ymid, w, h] (normalized)\n    \"\"\"\n    \n    bboxes = bboxes.copy().astype(float) # otherwise all value will be 0 as voc_pascal dtype is np.int\n    \n    # normolizinig\n    bboxes[..., [0, 2]]= bboxes[..., [0, 2]]/ image_width\n    bboxes[..., [1, 3]]= bboxes[..., [1, 3]]/ image_height\n    \n    # converstion (xmin, ymin) => (xmid, ymid)\n    bboxes[..., [0, 1]] = bboxes[..., [0, 1]] + bboxes[..., [2, 3]]/2\n    \n    return bboxes\n\ndef yolo2coco(image_height, image_width, bboxes):\n    \"\"\"\n    yolo => [xmid, ymid, w, h] (normalized)\n    coco => [xmin, ymin, w, h]\n    \n    \"\"\" \n    bboxes = bboxes.copy().astype(float) # otherwise all value will be 0 as voc_pascal dtype is np.int\n    \n    # denormalizing\n    bboxes[..., [0, 2]]= bboxes[..., [0, 2]]* image_width\n    bboxes[..., [1, 3]]= bboxes[..., [1, 3]]* image_height\n    \n    # converstion (xmid, ymid) => (xmin, ymin) \n    bboxes[..., [0, 1]] = bboxes[..., [0, 1]] - bboxes[..., [2, 3]]/2\n    \n    return bboxes\n\ndef load_image(image_path):\n    return cv2.cvtColor(cv2.imread(image_path), cv2.COLOR_BGR2RGB)\n\n\ndef plot_one_box(x, img, color=None, label=None, line_thickness=None):\n    # Plots one bounding box on image img\n    tl = line_thickness or round(0.002 * (img.shape[0] + img.shape[1]) / 2) + 1  # line/font thickness\n    color = color or [random.randint(0, 255) for _ in range(3)]\n    c1, c2 = (int(x[0]), int(x[1])), (int(x[2]), int(x[3]))\n    cv2.rectangle(img, c1, c2, color, thickness=tl, lineType=cv2.LINE_AA)\n    if label:\n        tf = max(tl - 1, 1)  # font thickness\n        t_size = cv2.getTextSize(label, 0, fontScale=tl / 3, thickness=tf)[0]\n        c2 = c1[0] + t_size[0], c1[1] - t_size[1] - 3\n        cv2.rectangle(img, c1, c2, color, -1, cv2.LINE_AA)  # filled\n        cv2.putText(img, label, (c1[0], c1[1] - 2), 0, tl / 3, [225, 255, 255], thickness=tf, lineType=cv2.LINE_AA)\n\ndef draw_bboxes(img, bboxes, classes, class_ids, confs, colors = None, show_classes = None, bbox_format = 'yolo', class_name = False, line_thickness = 2):  \n     \n    image = img.copy()\n    show_classes = classes if show_classes is None else show_classes\n    colors = (0, 255 ,0) if colors is None else colors\n    \n    if bbox_format == 'yolo':\n        \n        for idx in range(len(bboxes)):  \n            \n            bbox  = bboxes[idx]\n            cls   = classes[idx]\n            cls_id = class_ids[idx]\n            color = colors[cls_id] if type(colors) is list else colors\n            conf  = confs[idx]\n            \n            if cls in show_classes:\n            \n                x1 = round(float(bbox[0])*image.shape[1])\n                y1 = round(float(bbox[1])*image.shape[0])\n                w  = round(float(bbox[2])*image.shape[1]/2) #w/2 \n                h  = round(float(bbox[3])*image.shape[0]/2)\n\n                voc_bbox = (x1-w, y1-h, x1+w, y1+h)\n                label = cls if class_name else str(get_label(cls))\n                label +=f'-{conf:0.2f}'\n                plot_one_box(voc_bbox, \n                             image,\n                             color = color,\n                             label = label ,\n                             line_thickness = line_thickness)\n            \n    elif bbox_format == 'coco':\n        \n        for idx in range(len(bboxes)):  \n            \n            bbox  = bboxes[idx]\n            cls   = classes[idx]\n            cls_id = class_ids[idx]\n            color = colors[cls_id] if type(colors) is list else colors\n            \n            if cls in show_classes:            \n                x1 = int(round(bbox[0]))\n                y1 = int(round(bbox[1]))\n                w  = int(round(bbox[2]))\n                h  = int(round(bbox[3]))\n\n                voc_bbox = (x1, y1, x1+w, y1+h)\n                label = cls if class_name else str(cls_id)\n                label +=f'-{conf:0.2f}'\n                plot_one_box(voc_bbox, \n                             image,\n                             color = color,\n                             label = label,\n                             line_thickness = line_thickness)\n\n    elif bbox_format == 'voc_pascal':\n        \n        for idx in range(len(bboxes)):  \n            \n            bbox  = bboxes[idx]\n            cls   = classes[idx]\n            cls_id = class_ids[idx]\n            color = colors[cls_id] if type(colors) is list else colors\n            \n            if cls in show_classes: \n                x1 = int(round(bbox[0]))\n                y1 = int(round(bbox[1]))\n                x2 = int(round(bbox[2]))\n                y2 = int(round(bbox[3]))\n                voc_bbox = (x1, y1, x2, y2)\n                label = cls if class_name else str(cls_id)\n                label +=f'-{conf:0.2f}'\n                plot_one_box(voc_bbox, \n                             image,\n                             color = color,\n                             label = label,\n                             line_thickness = line_thickness)\n    else:\n        raise ValueError('wrong bbox format')\n\n    return image\n\n# Random Color\nnp.random.seed(10)\ncolors = [(np.random.randint(255), np.random.randint(255), np.random.randint(255)) for idx in range(1)]","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-14T07:28:59.641757Z","iopub.execute_input":"2021-08-14T07:28:59.642078Z","iopub.status.idle":"2021-08-14T07:28:59.679905Z","shell.execute_reply.started":"2021-08-14T07:28:59.64205Z","shell.execute_reply":"2021-08-14T07:28:59.679122Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Sanity Check","metadata":{}},{"cell_type":"markdown","source":"## WBF","metadata":{}},{"cell_type":"code","source":"if commit:\n    for bb in range(len(backbones)):\n        for ff in range(len(folds)):\n            print('#'*25)\n            print('### Backbone =',bb,'Fold =',ff)\n            print('#'*25)\n            \n            idx = 0\n            test_df = pd.read_csv('test.csv')\n            test_df['label_path'] = f'/kaggle/working/yolov5/runs/detect_b{bb}_f{ff}/exp/labels/'+test_df.image_id.map(lambda x: x.replace('_image',''))+'.txt'\n            test_df['image_path'] = f'/tmp/Dataset/test/{dim}/'+test_df.image_id.map(lambda x: x.replace('_image',''))+'.png'\n            def viz(idx=10):\n                df = test_df\n                row = df.iloc[idx]\n                img           = load_image(row.image_path)\n                # img           = cv2.cvtColor(img, cv2.COLOR_GRAY2RGB)\n                # img          = cv2.resize(img, dsize = (1024, 1024))\n                image_height  = row.height\n                image_width   = row.width\n                print('image shape:', img.shape)\n                # bboxes_voc    = np.array(row.bboxes)\n                # bboxes_yolo   = voc2yolo(image_height, image_width, bboxes_voc)\n                bboxes_yolo = []\n                confs = []\n                f = open(row.label_path, 'r')\n                while True:\n                    line = f.readline().strip(' \\n')\n            #         print('bbox:\\n',line)\n                    if line==None or len(line)==0:\n                        break\n                    bboxes_yolo.append(list(np.array(line.split(' ')).astype(np.float32))[1:-1])\n                    confs.append(list(np.array(line.split(' ')).astype(np.float32))[-1])\n                clsses        = ['opacity']*len(bboxes_yolo)\n                class_ids     = [0]*len(bboxes_yolo)\n\n                plt.figure(figsize = (5, 5))\n                plt.imshow(draw_bboxes(img = img,\n                               bboxes = bboxes_yolo, \n                               classes = clsses,\n                               class_ids = class_ids,\n                               confs=confs,\n                               class_name = True, \n                               colors = colors, \n                               bbox_format = 'yolo',\n                               line_thickness = 2))\n                plt.show()\n            viz(23);  ","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-08-14T07:29:00.958505Z","iopub.execute_input":"2021-08-14T07:29:00.958957Z","iopub.status.idle":"2021-08-14T07:29:04.287737Z","shell.execute_reply.started":"2021-08-14T07:29:00.958916Z","shell.execute_reply":"2021-08-14T07:29:04.286882Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 2cls Model","metadata":{}},{"cell_type":"markdown","source":"## Detection","metadata":{}},{"cell_type":"code","source":"POST_PROCESS = False\n# WE DON'T DO DETECTION POST PROCESS HERE. WE DO BELOW AFTER WBF\nfiles_to_remove = []\n\nif commit:\n    for bb in range(len(backbones)):\n        for ff in range(len(folds)):\n            total = 0\n            image_ids = []\n            PredictionStrings = []\n            if POST_PROCESS:\n                img_cls_df = pd.read_csv('/kaggle/working/image_cls.csv')\n            for file_path in tqdm(glob(f'/kaggle/working/yolov5/runs/detect_b{bb}_f{ff}/exp/labels/*txt')):\n                image_id = file_path.split('/')[-1].split('.')[0]+'_image'\n                w, h = test_df.loc[test_df.image_id==image_id,['width', 'height']].values[0]\n                f = open(file_path, 'r')\n                data = np.array(f.read().replace('\\n', ' ').strip().split(' ')).astype(np.float32).reshape(-1, 6)\n                data = data[:, [0, 5, 1, 2, 3, 4]]\n                total+=data.shape[0]\n                bboxes = list(np.concatenate((data[:, :2], np.round(yolo2voc(h, w, data[:, 2:]))), axis =1).reshape(-1).astype(str))\n                if POST_PROCESS:\n                    prob_b = 1-img_cls_df.query(\"image_id==@image_id\")[\"0\"].values[0]\n                    prob_g = img_cls_df.query(\"image_id==@image_id\")[\"opacity\"].values[0]\n                for idx in range(len(bboxes)):\n                    bboxes[idx] = str(int(float(bboxes[idx]))) if idx%6!=1 else bboxes[idx]\n                    bboxes[idx] = 'opacity' if idx%6==0 else bboxes[idx]\n                    if (idx%6==1)&(POST_PROCESS):\n                        bboxes[idx] = str(np.power(float(bboxes[idx]), ALPHA)*np.power(prob_b, BETA)*np.power(prob_g, GAMMA)) # geometric mean (x^alpha)*(y^beta)\n                    elif (idx%6==1):\n                        bboxes[idx] = f'{float(bboxes[idx]):.9}'\n                image_ids.append(image_id)\n                PredictionStrings.append((' '.join(bboxes)))\n            print('Total BBox:',total)\n            pred_img_df = pd.DataFrame({'image_id':image_ids,\n                                       'PredictionString':PredictionStrings})\n            pred_img_df.to_csv(f'test_b{bb}_f{ff}.csv',index=False)\n            files_to_remove.append(f'test_b{bb}_f{ff}.csv')","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2021-08-14T07:29:10.17127Z","iopub.execute_input":"2021-08-14T07:29:10.171605Z","iopub.status.idle":"2021-08-14T07:29:14.877589Z","shell.execute_reply.started":"2021-08-14T07:29:10.171577Z","shell.execute_reply":"2021-08-14T07:29:14.876569Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if commit:\n    print('Example pred_img_df dataframe')\n    display(pred_img_df.head())","metadata":{"execution":{"iopub.status.busy":"2021-08-14T07:30:30.899559Z","iopub.execute_input":"2021-08-14T07:30:30.899968Z","iopub.status.idle":"2021-08-14T07:30:30.91334Z","shell.execute_reply.started":"2021-08-14T07:30:30.899923Z","shell.execute_reply":"2021-08-14T07:30:30.912228Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if commit:\n    iou_thr = 0.625\n\n    wbf_files = []; final = []\n    for bb in range(len(backbones)):\n        model = []\n        for ff in range(len(folds)):\n            model.append(f'test_b{bb}_f{ff}.csv')\n        wbf_files.append(model)\n        final.append(f'test_b{bb}.csv')\n    wbf_files.append(final)\n    display(wbf_files)","metadata":{"execution":{"iopub.status.busy":"2021-08-14T07:30:31.117313Z","iopub.execute_input":"2021-08-14T07:30:31.117588Z","iopub.status.idle":"2021-08-14T07:30:31.12458Z","shell.execute_reply.started":"2021-08-14T07:30:31.117561Z","shell.execute_reply":"2021-08-14T07:30:31.123743Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Fusing Boxes","metadata":{}},{"cell_type":"code","source":"import warnings\nwarnings.filterwarnings(\"ignore\") #wbf\nif commit:\n    for wbf_num,files in enumerate(wbf_files):\n        print('#'*25)\n        print('### Backbone',wbf_num)\n        print('#'*25)\n        print()\n\n        # FILLNA, REMOVE WORD OPACITY, REMOVE WORD IMAGE FROM ID, REMOVE NONE PREDICTIONS\n        preds = [pd.read_csv(file).fillna('').rename({'id':'image_id'},axis=1) for file in files]\n        for p in preds:\n            p.PredictionString = p.PredictionString.str.replace('opacity','0')\n            p.image_id = p.image_id.map(lambda x: x.split('_')[0])\n            for index,row in p.iterrows():\n                text = ''\n                s = row.PredictionString.split(' ')\n                if len(s)%6!=0: print('ERROR')\n                for k in range(len(s)//6):\n                    if s[k*6]=='none': continue\n                    text += f'{s[k*6]} {s[k*6+1]} {s[k*6+2]} {s[k*6+3]} {s[k*6+4]} {s[k*6+5]} '\n                row.PredictionString = text[:-1]\n\n        # GET TEST WIDTHS AND HEIGHTS\n        df_test = test_df.copy()\n        df_test['image_id'] = df_test['image_id'].map(lambda x: x.split('_')[0])\n        df_test = df_test[['image_id','width','height']].set_index('image_id')\n        if debug:\n            df_test = df_test.iloc[:100]\n        df_test.width = df_test.width.astype('int32')\n        df_test.height = df_test.height.astype('int32')\n\n        # CONVERT PREDS AS STRING TO DATAFRAME\n        print('Converting',len(preds),'dataframe of string to dataframe of numbers...')\n        for i, pred in enumerate(preds):\n            print(i,', ',end='')\n            new_pred = []\n            for index, row in pred.iterrows():\n                #if index%50==0: print(index,', ',end='')\n                if row.PredictionString == '': continue\n                try:\n                    data_flat = np.array(row.PredictionString.split(' '))\n                except:\n                    print('###',row.PredictionString,'###')\n                data_matrix = data_flat[:len(data_flat) // 6 * 6].reshape(-1, 6)\n\n                df = pd.DataFrame( {\n                    'image_id' : np.repeat(row.image_id,len(data_matrix)), \n                    'score' : data_matrix[:,1].astype(float),\n                    'x_min' : data_matrix[:,2].astype(int),\n                    'y_min' : data_matrix[:,3].astype(int),\n                    'x_max' : data_matrix[:,4].astype(int),\n                    'y_max' : data_matrix[:,5].astype(int),\n                    'class_id' : data_matrix[:,0].astype(int)})\n                new_pred.append(df)\n            preds[i] = pd.concat(new_pred).join(df_test, on=['image_id'])\n        print(); print()\n\n        for i, sub_name in enumerate(files):\n            print(sub_name,'has box count', len(preds[i]))\n        print()\n\n        # NORMALIZE BOXES\n        for i, pred in enumerate(preds):\n            pred['x_min'] = pred['x_min'] / pred['width']\n            pred['y_min'] = pred['y_min'] / pred['height']\n            pred['x_max'] = pred['x_max'] / pred['width']\n            pred['y_max'] = pred['y_max'] / pred['height']\n\n        print('Here are preds',files[0],'preds...')\n        display( preds[0].sort_values(['score']).head() )\n        print()\n\n        from ensemble_boxes import weighted_boxes_fusion, non_maximum_weighted, soft_nms, nms\n\n        sub_results = []\n        label_dict = {0: 'opacity'}\n\n        # processing of other classes\n        print('Processing boxes with WBF...')\n        for jj,image_id in enumerate(preds[0].image_id.unique()):\n            if jj%100==0: print(jj,', ',end='')\n\n            boxes_list, labels_list, scores_list = [], [], []\n\n            for i in range(len(preds)):\n                sub_df = preds[i][preds[i].image_id == image_id].sort_values(['score'])\n                boxes_list.append(sub_df[['x_min', 'y_min', 'x_max', 'y_max']].values)\n                labels_list.append(sub_df['class_id'].values)\n                scores_list.append(sub_df['score'].values)\n\n            boxes, scores, labels = weighted_boxes_fusion(boxes_list, scores_list, labels_list, iou_thr=iou_thr)\n\n            sub_df_weighted = pd.DataFrame(boxes, columns=['x_min', 'y_min', 'x_max', 'y_max'])\n            if len(sub_df)>0:\n                sub_df_weighted['image_id'] = image_id\n                sub_df_weighted['x_min'] = (sub_df_weighted['x_min'] * sub_df.width.values[0]).astype(int)\n                sub_df_weighted['x_max'] = (sub_df_weighted['x_max'] * sub_df.width.values[0]).astype(int)\n                sub_df_weighted['y_min'] = (sub_df_weighted['y_min'] * sub_df.height.values[0]).astype(int)\n                sub_df_weighted['y_max'] = (sub_df_weighted['y_max'] * sub_df.height.values[0]).astype(int)\n                sub_df_weighted['height'] = (sub_df.height.values[0]).astype(int)\n                sub_df_weighted['width'] = (sub_df.width.values[0]).astype(int)\n                sub_df_weighted['score'] = scores\n                sub_df_weighted['class_id'] = labels.astype(int)\n                sub_df_weighted['class_name'] = sub_df_weighted['class_id'].apply(lambda s : label_dict[s])\n\n                sub_results.append(sub_df_weighted.copy(deep=True))\n\n        preds_test_weight = pd.concat(sub_results)\n        preds_test_weight = preds_test_weight[preds[0].columns]\n        print(); print()\n\n        print('Done. We now have',len(preds_test_weight),'bboxes\\n')\n\n        subs = pd.DataFrame(columns=['image_id','PredictionString'])\n\n        print('Converting dataframe of numbers to dataframe of strings...')\n        for jj,(image_id, sub_df) in enumerate(preds_test_weight.groupby('image_id')):\n            if jj%50==0: print(jj,', ',end='')\n\n            predsxx = ''\n            for index, row in sub_df.iterrows():\n                predsxx += f'{int(row.class_id)} {row.score} {int(row.x_min)} {int(row.y_min)} {int(row.x_max)} {int(row.y_max)} '\n\n            subs.loc[len(subs)] = (image_id, predsxx[:-1])\n\n        display( subs.head() )\n\n        if (wbf_num+1) != len(wbf_files):\n            subs.to_csv(f'test_b{wbf_num}.csv',index=False)\n            print('Wrote to',f'test_b{wbf_num}.csv\\n')\n            files_to_remove.append(f'test_b{wbf_num}.csv')\n        else:\n            subs.to_csv('test_wbf.csv',index=False)\n            print('Wrote to','test_wbf.csv\\n')\n            files_to_remove.append('test_wbf.csv')","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2021-08-14T07:30:34.659703Z","iopub.execute_input":"2021-08-14T07:30:34.660027Z","iopub.status.idle":"2021-08-14T07:31:21.543238Z","shell.execute_reply.started":"2021-08-14T07:30:34.659997Z","shell.execute_reply":"2021-08-14T07:31:21.542238Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# CREATE DETECTION PREDICTION STRINGS\nif commit:\n    pred_img_df = pd.read_csv('test_wbf.csv')\n    for f in files_to_remove: os.system(f'rm {f}')\n    img_cls_df = pd.read_csv('/kaggle/working/image_cls.csv')\n\n    for index,row in pred_img_df.iterrows():\n        row.image_id = row.image_id+'_image'\n\n        # DETECTION SCORE POST PROCESS\n        image_id = row.image_id\n        prob_b = 1-img_cls_df.query(\"image_id==@image_id\")[\"0\"].values[0]\n        prob_g = img_cls_df.query(\"image_id==@image_id\")[\"opacity\"].values[0]\n\n        # WRITE DETECTION PREDICTION STRINGS\n        p = row.PredictionString.split(' ')\n        if len(p)%6!=0: print('ERROR')\n        text = ''\n        for k in range(len(p)//6):\n            pr = str(np.power(float(p[k*6+1]), ALPHA)*np.power(prob_b, BETA)*np.power(prob_g, GAMMA)) # geometric mean (x^alpha)*(y^beta)\n            text += f'opacity {pr} {p[k*6+2]} {p[k*6+3]} {p[k*6+4]} {p[k*6+5]} '\n        row.PredictionString = text[:-1]\n\n    pred_img_df.head()","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2021-08-14T07:32:33.627788Z","iopub.execute_input":"2021-08-14T07:32:33.628114Z","iopub.status.idle":"2021-08-14T07:32:34.3818Z","shell.execute_reply.started":"2021-08-14T07:32:33.628085Z","shell.execute_reply":"2021-08-14T07:32:34.380814Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if commit:\n#     pred_img_df = pd.read_csv('test_wbf.csv') # dummy\n    image_df = pd.merge(test_df[['image_id']], pred_img_df, on='image_id', how='left').fillna(\"none 1 0 0 1 1\")\n    image_df = image_df.rename(columns={'image_id':'id'})\n    print(image_df.PredictionString.value_counts().iloc[0:1])\n    display(image_df.head())","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2021-08-14T07:32:35.445567Z","iopub.execute_input":"2021-08-14T07:32:35.445896Z","iopub.status.idle":"2021-08-14T07:32:35.469988Z","shell.execute_reply.started":"2021-08-14T07:32:35.445866Z","shell.execute_reply":"2021-08-14T07:32:35.469005Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Utilize 4cls & 2cls for `none`","metadata":{}},{"cell_type":"code","source":"if commit:\n    img_cls_df = pd.read_csv('/kaggle/working/image_cls.csv')\n    def fix_labels(row):\n        image_id = row['id']\n        prob_b = img_cls_df.query(\"image_id==@image_id\")[\"0\"].values[0] # study-level classifier\n        prob_g = 1-img_cls_df.query(\"image_id==@image_id\")[\"opacity\"].values[0] # 2cls opacity classifier\n        prob   = np.power(prob_b, BETA2)*np.power(prob_g, GAMMA2)\n        if row['PredictionString']!=\"none 1 0 0 1 1\":\n            row['PredictionString'] = (row['PredictionString']+' '+f\"none {prob} 0 0 1 1\").strip(' ')\n        return row\n    image_df = image_df.progress_apply(fix_labels, axis=1)\n    print('max: ',image_df.PredictionString.value_counts()[:1])","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2021-08-14T07:32:36.891628Z","iopub.execute_input":"2021-08-14T07:32:36.891955Z","iopub.status.idle":"2021-08-14T07:32:42.920851Z","shell.execute_reply.started":"2021-08-14T07:32:36.891926Z","shell.execute_reply":"2021-08-14T07:32:42.919891Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# BBox Filter","metadata":{}},{"cell_type":"code","source":"if BBOX_FILTER & commit:\n    image_df = image_df.merge(test_df.rename(columns={'image_id':'id',\n                                                     'width':'Width',\n                                                     'height':'Height'})[['id', 'Width', 'Height']])\n    image_df.to_csv('/kaggle/working/image-lvl-nofilter.csv',index=False)\n    print(image_df.head(2))","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2021-08-14T07:32:46.82634Z","iopub.execute_input":"2021-08-14T07:32:46.826726Z","iopub.status.idle":"2021-08-14T07:32:46.873983Z","shell.execute_reply.started":"2021-08-14T07:32:46.826697Z","shell.execute_reply":"2021-08-14T07:32:46.872899Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if BBOX_FILTER & commit:\n    %cd /kaggle/working\n    %cp -r /kaggle/input/siimcovid19detection-scripts-dataset/bbox /kaggle/working\n    %cd /kaggle/working/bbox","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2021-08-14T07:32:50.083036Z","iopub.execute_input":"2021-08-14T07:32:50.083394Z","iopub.status.idle":"2021-08-14T07:32:51.17413Z","shell.execute_reply.started":"2021-08-14T07:32:50.083364Z","shell.execute_reply":"2021-08-14T07:32:51.172374Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if BBOX_FILTER & commit:\n    !python3 bbox_filter.py --sub-csv /kaggle/working/image-lvl-nofilter.csv\\\n    --save-csv /kaggle/working/image-lvl-filter.csv","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2021-08-14T07:32:52.657559Z","iopub.execute_input":"2021-08-14T07:32:52.657908Z","iopub.status.idle":"2021-08-14T07:33:26.281624Z","shell.execute_reply.started":"2021-08-14T07:32:52.657874Z","shell.execute_reply":"2021-08-14T07:33:26.280551Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if BBOX_FILTER & commit:\n    image_df = pd.read_csv('/kaggle/working/image-lvl-filter.csv')\n    %cd /kaggle/working","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2021-08-14T07:33:31.93407Z","iopub.execute_input":"2021-08-14T07:33:31.93453Z","iopub.status.idle":"2021-08-14T07:33:31.955878Z","shell.execute_reply.started":"2021-08-14T07:33:31.934494Z","shell.execute_reply":"2021-08-14T07:33:31.954906Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Utilize **2cls** for `negative`","metadata":{}},{"cell_type":"code","source":"if commit:\n    CLASS_LABELS  = ['0', '1', '2', '3']\n    img_cls_df = pd.read_csv('/kaggle/working/image_cls.csv')\n    \n    prob_g = 1-img_cls_df[\"opacity\"].values[:, None] # 2cls-opacity\n\n    prob_0  = img_cls_df[CLASS_LABELS[0:1]].values # none\n    prob_0  = np.power(prob_0, BETA3)*np.power(prob_g, GAMMA3)\n\n    prob_1  = img_cls_df[CLASS_LABELS[1:]].values # typical,atypical,indeterminate\n    prob_1  = np.power(prob_1, BETA3)*np.power(1-prob_g, GAMMA3)\n\n    img_cls_df.loc[:, CLASS_LABELS] = np.concatenate([prob_0, prob_1], axis=1).tolist()","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2021-08-14T07:33:34.41107Z","iopub.execute_input":"2021-08-14T07:33:34.411433Z","iopub.status.idle":"2021-08-14T07:33:34.437201Z","shell.execute_reply.started":"2021-08-14T07:33:34.411403Z","shell.execute_reply":"2021-08-14T07:33:34.436405Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if commit:\n    name2label = { \n        'negative': 0,\n        'indeterminate': 1,\n        'atypical': 2,\n        'typical': 3}\n    label2name  = {v:k for k, v in name2label.items()}\n    \n    study_df = img_cls_df.groupby(['study_id'])[CLASS_LABELS].max().reset_index()\n    study_df.rename(columns={'study_id':'id'}, inplace=True)\n\n    def get_PredictionString(row, thr=0):\n        string = ''\n        for idx in range(4):\n            conf =  row[str(idx)]\n            if conf>thr:\n                string+=f'{label2name[idx]} {conf} 0 0 1 1 '\n        if len(string)==0:\n            string = 'negative 1.0 0 0 1 1'\n        string = string.strip()\n        return string\n\n    #------------------------\n    # Submission csv  \n    #------------------------\n    study_df['PredictionString'] = study_df.progress_apply(get_PredictionString, axis=1)\n    study_df = study_df.drop(CLASS_LABELS, axis=1)\n\n    print('study head:\\n',study_df.head())\n    print('study max:\\n', study_df.value_counts()[0:1])\n\n    print('study_df size:',study_df.shape[0])","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2021-08-14T07:33:38.554722Z","iopub.execute_input":"2021-08-14T07:33:38.555048Z","iopub.status.idle":"2021-08-14T07:33:38.665378Z","shell.execute_reply.started":"2021-08-14T07:33:38.555016Z","shell.execute_reply":"2021-08-14T07:33:38.664395Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Image + Study","metadata":{}},{"cell_type":"code","source":"sub_df = pd.read_csv('/kaggle/input/siim-covid19-detection/sample_submission.csv')\nif commit:\n    del sub_df['PredictionString']\n    pred_df = pd.concat([image_df, study_df])\n    sub_df  = sub_df.merge(pred_df, on='id',how='left')\nsub_df.to_csv('/kaggle/working/submission.csv',index=False)\nsub_df.head()","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2021-08-14T07:33:40.377573Z","iopub.execute_input":"2021-08-14T07:33:40.378046Z","iopub.status.idle":"2021-08-14T07:33:40.433517Z","shell.execute_reply.started":"2021-08-14T07:33:40.378Z","shell.execute_reply":"2021-08-14T07:33:40.432525Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Check None","metadata":{}},{"cell_type":"code","source":"sub_df.PredictionString.value_counts()[0:2]","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2021-08-14T07:33:42.204465Z","iopub.execute_input":"2021-08-14T07:33:42.204791Z","iopub.status.idle":"2021-08-14T07:33:42.213026Z","shell.execute_reply.started":"2021-08-14T07:33:42.204762Z","shell.execute_reply":"2021-08-14T07:33:42.212117Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Remove Unncessary Files","metadata":{}},{"cell_type":"code","source":"!rm -r /kaggle/working/image_cls.csv\n!rm -r /kaggle/working/yolov5\nif BBOX_FILTER:\n    !rm -r /kaggle/working/image-lvl-filter.csv\n    !rm -r /kaggle/working/image-lvl-nofilter.csv\n    !rm -r /kaggle/working/bbox\n!rm -r /kaggle/working/test.csv\n!rm -r /kaggle/working/test-raw.csv","metadata":{"execution":{"iopub.status.busy":"2021-08-14T07:33:43.507325Z","iopub.execute_input":"2021-08-14T07:33:43.507643Z","iopub.status.idle":"2021-08-14T07:33:48.141782Z","shell.execute_reply.started":"2021-08-14T07:33:43.507616Z","shell.execute_reply":"2021-08-14T07:33:48.140681Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}