{"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":"code","source":"!pip install ensemble_boxes\n!pip install mmcv-full -f https://download.openmmlab.com/mmcv/dist/cu110/torch1.9.0/index.html\n!pip install mmdet\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#!pip list\n#!cd mmdetection-2.12.0 && python setup.py develop","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport shutil\nimport yaml\nimport time\nimport json\nimport cv2\nimport random\nimport numpy as np\nimport pandas as pd\nfrom glob import glob\nimport matplotlib.pyplot as plt\nfrom sklearn.model_selection import GroupKFold, StratifiedKFold\nfrom tqdm.notebook import tqdm\nimport seaborn as sns\nimport torch\nfrom IPython.display import Image, clear_output\nfrom collections import Counter\nfrom ensemble_boxes import *\nimport copy\nimport os.path as osp\nimport mmcv\nimport mmdet\nimport numpy as np\nimport albumentations as A\nfrom mmdet.datasets.builder import DATASETS\nfrom mmdet.datasets.custom import CustomDataset\nfrom mmcv import Config\nfrom mmdet.apis import set_random_seed\nfrom mmdet.apis import inference_detector, init_detector, show_result_pyplot\nfrom mmdet.datasets import build_dataset\nfrom mmdet.models import build_detector\nfrom mmdet.apis import train_detector\nprint(mmdet.__version__)\nos.environ['CUDA_VISIBLE_DEVICES'] = '0'","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"VER = 'v4_4'\nDEBUG = False\nPARAMS = {\n    'version': VER,\n    'folds': 5,\n    'val_fold': 4,\n    'img_size': 512,\n    'batch_size': 8,\n    'epochs': 16,\n    'seed': 2021,\n    'iou_th': .6,\n    'th': .4,\n    ### r50\n    'config': 'vfnet_r50_fpn_mdconv_c3-c5_mstrain_2x_coco.py',\n    'checkpoint': 'vfnet_r50_fpn_mdconv_c3-c5_mstrain_2x_coco_20201027pth-6879c318.pth',\n    ### r101\n    #'config': 'vfnet_r101_fpn_mdconv_c3-c5_mstrain_2x_coco.py',\n    #'checkpoint': 'vfnet_r101_fpn_mdconv_c3-c5_mstrain_2x_coco_20201027pth-7729adb5.pth',\n    'comments': ''\n}\n#../input/siim-covid19-detection/sample_submission.csv\n#../input/siimwxy\nDATA_PATH= '/kaggle/input/siim-covid19-detection'\nIMGS_PATH = f'/kaggle/input/siimwxy'\n#'/kaggle/input/siim-covid19-resized-to-512px-png'\n#../input/mmdetvfnetpretrained\nCHKP_PATH = '/kaggle/input/mmdetvfnetpretrained'\nMDLS_PATH = f'/kaggle/working/models_mmdet_{VER}'\nif not os.path.exists(MDLS_PATH):\n    os.mkdir(MDLS_PATH)\nwith open(f'{MDLS_PATH}/params.json', 'w') as file:\n    json.dump(PARAMS, file)\n    \ndef seed_all(seed):\n    random.seed(seed)\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    np.random.seed(seed)\n\nseed_all(PARAMS['seed'])\nstart_time = time.time()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df = pd.read_csv(f'{IMGS_PATH}/label.csv')\ntrain_df = train_df[train_df.split == 'train']\ndel train_df['split']\nif DEBUG:\n    train_df = train_df.loc[:100]\ndf_train_img = pd.read_csv(f'{DATA_PATH}/train_image_level.csv')\ndf_train_sty = pd.read_csv(f'{DATA_PATH}/train_study_level.csv')\n\ntrain_df['id'] = train_df['image_id'].apply(lambda x: ''.join([x.split('/')[-1], '_image']))\ndf_train_sty['StudyInstanceUID'] = df_train_sty['id'].apply(lambda x: x.replace('_study', ''))\ndel df_train_sty['id']\ndf_train_img = df_train_img.merge(df_train_sty, on='StudyInstanceUID')\ntrain_df = df_train_img.merge(train_df, on='id')\ntrain_df['img'] = train_df['image_id'] + '.png'\nprint(train_df.shape)\ndisplay(train_df.head())\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def bar_plot(train_df, variable):\n    var = train_df[variable]\n    varValue = var.value_counts()\n    plt.figure(figsize = (12, 3))\n    plt.bar(varValue.index, varValue)\n    plt.xticks(varValue.index, varValue.index.values)\n    plt.ylabel(\"Frequency\")\n    plt.title(variable)\n    plt.show()\n    print(\"{}: \\n{}\".format(variable, varValue))\n\ntrain_df['target'] = 'Negative for Pneumonia'\ntrain_df.loc[train_df['Typical Appearance']==1, 'target'] = 'Typical Appearance'\ntrain_df.loc[train_df['Indeterminate Appearance']==1, 'target'] = 'Indeterminate Appearance'\ntrain_df.loc[train_df['Atypical Appearance']==1, 'target'] = 'Atypical Appearance'\nbar_plot(train_df, 'target') ","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df = train_df[~train_df.boxes.isnull()] \ntrain_df.reset_index(inplace=True)\nclasses = [\n    'Typical Appearance', \n    'Indeterminate Appearance', \n    'Atypical Appearance'\n]\nprint('classes:\\n', classes,\n      '\\nclasses labels:\\n', np.unique(train_df[classes].values, axis=0))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"label2color = {\n    '[1, 0, 0]': [255, 0, 0], # Typical Appearance\n    '[0, 1, 0]': [0, 255, 0], # Indeterminate Appearance\n    '[0, 0, 1]': [0, 0, 255], # Atypical Appearance\n}\nlabel2classes = {\n    '[1, 0, 0]': classes[0],\n    '[0, 1, 0]': classes[1],\n    '[0, 0, 1]': classes[2]\n}\n\ndef plot_img(img, size=(18, 18), title='', cmap='gray'):\n    plt.figure(figsize=size)\n    plt.imshow(img, cmap=cmap)\n    plt.suptitle(title)\n    plt.show()\n\ndef plot_imgs(imgs, cols=2, size=10, is_rgb=True, title='', cmap='gray', img_size=None):\n    rows = len(imgs) // cols + 1\n    fig = plt.figure(figsize=(cols * size, rows * size))\n    for i, img in enumerate(imgs):\n        if img_size is not None:\n            img = cv2.resize(img, img_size)\n        fig.add_subplot(rows, cols, i + 1)\n        plt.axis('off')\n        plt.imshow(img, cmap=cmap)\n    plt.suptitle(title)\n    plt.axis('off')\n    \ndef draw_bbox(img, box, label, color, thickness=3):   \n    alpha = .1\n    alpha_box = .4\n    overlay_bbox = img.copy()\n    overlay_text = img.copy()\n    output = img.copy()\n    text_width, text_height = cv2.getTextSize(label.upper(), cv2.FONT_HERSHEY_SIMPLEX, .6, 1)[0]\n    cv2.rectangle(overlay_bbox, \n                  (box[0], box[1]), \n                  (box[2], box[3]), \n                  color, -1)\n    cv2.addWeighted(overlay_bbox, alpha, output, 1 - alpha, 0, output)\n    cv2.rectangle(overlay_text, \n                  (box[0], box[1] - 7 - text_height), \n                  (box[0] + text_width + 2, box[1]),\n                  (0, 0, 0), -1)\n    cv2.addWeighted(overlay_text, alpha_box, output, 1 - alpha_box, 0, output)\n    cv2.rectangle(output, \n                  (box[0], box[1]), \n                  (box[2], box[3]),\n                  color, thickness)\n    cv2.putText(output, \n                label.upper(), \n                (box[0], box[1]-5),\n                cv2.FONT_HERSHEY_SIMPLEX, \n                .6, (255, 255, 255), 1, \n                cv2.LINE_AA)\n    return output","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"imgs = []\nsample = train_df.sample(n=4)['img'].values\nprint(sample)\nfor img_name in sample:\n    ratio_x = PARAMS['img_size'] / train_df.loc[train_df['img'] == img_name, 'dim1'].values[0]\n    ratio_y = PARAMS['img_size'] / train_df.loc[train_df['img'] == img_name, 'dim0'].values[0]\n    boxes = train_df.loc[train_df['img'] == img_name, 'boxes'].values[0]\n    boxes = json.loads(boxes.replace('\\'', '\\\"'))\n    boxes = [[int(box['x'] * ratio_x), \n              int(box['y'] * ratio_y), \n              int((box['x'] + box['width']) * ratio_x), \n              int((box['y'] + box['height']) * ratio_y)]\n             for box in boxes]\n    img_labels = train_df.loc[train_df['img'] == img_name, classes].values[0]\n    img_labels = [str(img_labels.tolist())] * len(boxes)\n    img = cv2.imread(f'{IMGS_PATH}/train/{img_name}')\n    for label_id, box in zip(img_labels, boxes):\n        color = label2color[label_id]\n        img = draw_bbox(\n            img, \n            list(np.int_(box)), \n            label2classes[label_id], \n            label2color[label_id]\n        )\n    imgs.append(img)\nplot_imgs(imgs, size=8, cols=4, cmap=None)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"skf  = StratifiedKFold(n_splits=PARAMS['folds'])\ntrain_df['fold'] = -1\nfor fold, (train_idx, val_idx) in enumerate(skf.split(train_df, y=train_df.target)):\n    train_df.loc[val_idx, 'fold'] = fold\nsplit = PARAMS['val_fold']\nwith open(f'{MDLS_PATH}/train.txt', 'w') as file:\n    tr_ids = list(train_df[train_df['fold'] != split].img.unique())\n    print('train:', len(tr_ids))\n    file.write('\\n'.join(tr_ids))\nwith open(f'{MDLS_PATH}/val.txt', 'w') as file:\n    val_ids = list(train_df[train_df['fold'] == split].img.unique())\n    print('val:', len(val_ids))\n    file.write('\\n'.join(val_ids))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"@DATASETS.register_module()\nclass SIIMDataset(CustomDataset):\n    CLASSES = ('opacity', )\n    ANN_DF = train_df.copy()\n    def load_annotations(self, ann_file):\n        cat2label = {k: i for i, k in enumerate(self.CLASSES)}\n        image_list = mmcv.list_from_file(self.ann_file)\n        data_infos = []\n        for img_id in image_list:\n            img_anns = self.ANN_DF[self.ANN_DF.img == img_id]\n            filename = f'{self.img_prefix}/{img_anns[\"img\"].values[0]}'\n            data_info = dict(\n                filename=filename, \n                width=PARAMS['img_size'], \n                height=PARAMS['img_size']\n            )\n            ratio_x = PARAMS['img_size'] / img_anns['dim1'].values[0]\n            ratio_y = PARAMS['img_size'] / img_anns['dim0'].values[0]\n            boxes = img_anns['boxes'].values[0]\n            boxes = json.loads(boxes.replace('\\'', '\\\"'))\n            gt_bboxes = [\n                [int(box['x'] * ratio_x), \n                 int(box['y'] * ratio_y), \n                 int((box['x'] + box['width']) * ratio_x), \n                 int((box['y'] + box['height']) * ratio_y)]\n                for box in boxes]\n            img_labels = img_anns[classes].values[0]\n            gt_labels = [0] * len(boxes)\n            data_anno = dict(\n                bboxes=np.array(gt_bboxes, dtype=np.float32).reshape(-1, 4),\n                labels=np.array(gt_labels),\n            )\n            data_info.update(ann=data_anno)\n            data_infos.append(data_info)\n        return data_infos\ntrain_transforms = A.Compose([\n    A.OneOf([\n        A.RandomBrightness(limit=.2, p=1), \n        A.RandomContrast(limit=.2, p=1), \n        A.RandomGamma(p=1)\n    ], p=.5),\n    A.OneOf([\n        A.Blur(blur_limit=3, p=1),\n        A.MedianBlur(blur_limit=3, p=1)\n    ], p=.25),\n    A.OneOf([\n        A.GaussNoise(0.002, p=.5),\n        A.IAAAffine(p=.5),\n    ], p=.25),\n    A.VerticalFlip(p=.5),\n    A.HorizontalFlip(p=.5),\n    A.Transpose(p=.25),\n    A.RandomRotate90(p=.25),\n    A.Cutout(num_holes=10, max_h_size=20, max_w_size=20, p=.25),\n    A.ShiftScaleRotate(p=.5)\n])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#../input/mmdetection2120/mmdetection-2.12.0\ncfg = Config.fromfile(f'/kaggle/input/mmdetection2120/mmdetection-2.12.0/configs/vfnet/{PARAMS[\"config\"]}')\ncfg.device='cuda'\ncfg.load_from = f'{CHKP_PATH}/{PARAMS[\"checkpoint\"]}'\ncfg.model.bbox_head.num_classes = 1\ncfg.dump(f'{MDLS_PATH}/init_config.py')\ncfg.train_pipeline = [\n    dict(type='LoadImageFromFile'),\n    dict(type='LoadAnnotations', with_bbox=True),\n    dict(\n        type='Resize',\n        img_scale=[(1333, 640), (1333, 672), (1333, 704), (1333, 736),\n                   (1333, 768), (1333, 800)],\n        multiscale_mode='value',\n        keep_ratio=True),\n    ########################################\n    # Note that this key is part of bbox_params. \n    # Their difference is format='pascal_voc' means [x1, y1, x2, y2] style box encoding, \n    # while format='coco' means [x, y, w, h].\n    dict(\n        type='Albu',\n        transforms=train_transforms,\n        bbox_params=dict(\n            type='BboxParams',\n            format='pascal_voc',\n            label_fields=['gt_labels'],\n            min_visibility=0.0,\n            filter_lost_elements=True),\n        keymap={\n            'img': 'image',\n            'gt_bboxes': 'bboxes'},\n        update_pad_shape=False,\n        skip_img_without_anno=True),\n    #########################################\n    dict(\n        type='Normalize',\n        mean=[103.53, 116.28, 123.675],\n        std=[1.0, 1.0, 1.0],\n        to_rgb=False),\n    dict(type='Pad', size_divisor=32),\n    dict(type='DefaultFormatBundle'),\n    dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels'])\n]\ncfg.dataset_type = 'SIIMDataset'\ncfg.data_root = f'{IMGS_PATH}/train'\ncfg.data.test.type = 'SIIMDataset'\ncfg.data.test.data_root = IMGS_PATH\ncfg.data.test.ann_file = f'{MDLS_PATH}/train.txt'\ncfg.data.test.img_prefix = ''\n#cfg.data.test.extra_convs_on_inputs=False\ncfg.data.train.type = 'SIIMDataset'\ncfg.data.train.data_root = f'{IMGS_PATH}/train'\ncfg.data.train.ann_file = f'{MDLS_PATH}/train.txt'\ncfg.data.train.img_prefix = ''\n#cfg.data.train.extra_convs_on_inputs=False\ncfg.data.val.type = 'SIIMDataset'\ncfg.data.val.data_root = f'{IMGS_PATH}/train'\ncfg.data.val.ann_file = f'{MDLS_PATH}/val.txt'\n#cfg.data.val.extra_convs_on_inputs=False\ncfg.data.val.img_prefix = ''\ncfg.work_dir = MDLS_PATH\ncfg.optimizer.lr = .02 / (8 * 16 / PARAMS['batch_size'])\ncfg.log_config.interval = 128\ncfg.runner.max_epochs = PARAMS['epochs']\ncfg.checkpoint_config.interval = 1\ncfg.evaluation = dict(\n    interval=1, \n    start=2,\n    metric='mAP', \n    save_best='mAP')\ncfg.seed = PARAMS['seed']\nset_random_seed(0, deterministic=False)\ncfg.gpu_ids = range(1)\ncfg.data.samples_per_gpu = PARAMS['batch_size']\ncfg.data.workers_per_gpu = 2\ncfg.workflow = [('train', 1)]\ncfg.dump(f'{MDLS_PATH}/train_config.py')\ncfg.model.neck=dict(\n        type='FPN',\n        in_channels=[256, 512, 1024, 2048],\n        out_channels=256,\n        start_level=1,\n        add_extra_convs=True,\n        num_outs=5,\n        relu_before_extra_convs=True)\nprint(f'Config:\\n{cfg.pretty_text}')\n\nelapsed_time = time.time() - start_time\nprint(f'time elapsed: {elapsed_time // 60:.0f} min {elapsed_time % 60:.0f} sec')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"datasets = [build_dataset(cfg.data.train)]\nif len(cfg.workflow) == 2:\n    datasets.append(build_dataset(cfg.data.val))\nmodel = build_detector(\n    cfg.model, \n    train_cfg=cfg.get('train_cfg'), \n    test_cfg=cfg.get('test_cfg')\n)\nmodel.CLASSES = datasets[0].CLASSES\nmmcv.mkdir_or_exist(osp.abspath(cfg.work_dir))\ntrain_detector(model, datasets, cfg, distributed=False, validate=True)\n\nelapsed_time = time.time() - start_time\nprint(f'time elapsed: {elapsed_time // 60:.0f} min {elapsed_time % 60:.0f} sec')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"checkpoint = f'{MDLS_PATH}/epoch_{PARAMS[\"epochs\"]}.pth'\ncfg = f'{MDLS_PATH}/init_config.py'\nmodel_test = init_detector(cfg, checkpoint, device='cuda:0')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"imgs = []\nsplit = PARAMS['val_fold']\nsample = train_df[train_df['fold'] != split].sample(n=4)['img'].values\nfor img_name in sample:\n    ratio_x = PARAMS['img_size'] / train_df.loc[train_df['img'] == img_name, 'dim1'].values[0]\n    ratio_y = PARAMS['img_size'] / train_df.loc[train_df['img'] == img_name, 'dim0'].values[0]\n    boxes = train_df.loc[train_df['img'] == img_name, 'boxes'].values[0]\n    boxes = json.loads(boxes.replace('\\'', '\\\"'))\n    boxes = [[int(box['x'] * ratio_x), \n              int(box['y'] * ratio_y), \n              int((box['x'] + box['width']) * ratio_x), \n              int((box['y'] + box['height']) * ratio_y)]\n             for box in boxes]\n    img_labels = train_df.loc[train_df['img'] == img_name, classes].values[0]\n    img_labels = [str(img_labels.tolist())] * len(boxes)\n    img = cv2.imread(f'{IMGS_PATH}/train/{img_name}')\n    for label_id, box in zip(img_labels, boxes):\n        color = label2color[label_id]\n        img = draw_bbox(\n            img, \n            list(np.int_(box)), \n            label2classes[label_id], \n            label2color[label_id]\n        )\n    result = inference_detector(model_test, img)\n    boxes_list = [list(x[:, :4] / PARAMS['img_size']) for x in result if x.shape[0] != 0]\n    boxes_list =  [item for sublist in boxes_list for item in sublist]\n    scores_list = [x[:, 4].tolist() for x in result if x.shape[0] != 0]\n    scores_list =  [item for sublist in scores_list for item in sublist]\n    labels_list = [[i] * x.shape[0] for i, x in enumerate(result) if x.shape[0] != 0]\n    labels_list =  [item for sublist in labels_list for item in sublist]\n    boxes, scores, box_labels = nms(\n        boxes=[boxes_list], \n        scores=[scores_list], \n        labels=[labels_list], \n        weights=None,\n        iou_thr=PARAMS['iou_th']\n    )\n    boxes *= PARAMS['img_size']\n    for label_id, box, score in zip(box_labels, boxes, scores):\n        if score >= PARAMS['th']:\n            color = [255, 255, 255]\n            img = draw_bbox(\n                img, \n                list(np.int_(box)), \n                'predict', \n                color\n            )\n    imgs.append(img)\nplot_imgs(imgs, size=8, cols=4, cmap=None)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"elapsed_time = time.time() - start_time\nprint(f'time elapsed: {elapsed_time // 60:.0f} min {elapsed_time % 60:.0f} sec')","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}