{"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":"#  *VinBigData Detectron2*\n![](https://images.medicinenet.com/images/article/main_image/chest-x-ray.jpg)","metadata":{}},{"cell_type":"markdown","source":"* This competition can be classified as object detaction task to Automatically localize and  classify thoracic abnormalities from chest x-ray image and find a class and location of thoracic abnormalities from chest x-ray image (radiographs).\n\n* The model i used in this notebook is Detectron2 \n  Detectron2 is pytorch object detection library by Facebook AI Research next generation . \n  It   is a ground-up rewrite of the previous version, Detectron, and it originates from  maskrcnn- benchmark.\nThe link for there github repository : [https://github.com/facebookresearch/detectron2](http://)\n\n* Detectron2 gave me better results than yolov5 ,you can check my other notebook that uses yolov5 :\n[https://www.kaggle.com/khaledmgamal/vinbigdata-yolov5](http://)\n* I learned a lot about detectron2 from this kernal   : [https://www.kaggle.com/corochann/vinbigdata-detectron2-train](http://)","metadata":{}},{"cell_type":"code","source":"!nvidia-smi","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!nvcc --version","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\n\ntorch.__version__","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Installing Detectron2 \nrefer to this link to learn more :[https://detectron2.readthedocs.io/en/latest/tutorials/install.html](http://)","metadata":{}},{"cell_type":"code","source":"!pip install detectron2 -f \\\n  https://dl.fbaipublicfiles.com/detectron2/wheels/cu102/torch1.7/index.html","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Train Detectron2 on custom dataset\nyou can follow this tutorial to learn more about that :\nhttps://colab.research.google.com/drive/16jcaJoc6bCFAQ96jDe2HwtXj7BMD_-m5","metadata":{}},{"cell_type":"code","source":"import pickle\nfrom pathlib import Path\nfrom typing import Optional\nimport cv2\nimport numpy as np\nimport pandas as pd\nfrom detectron2.structures import BoxMode\nfrom tqdm import tqdm\n\n\ndef get_vinbigdata_dicts(\n    imgdir: Path,\n    train_df: pd.DataFrame,\n    train_meta:pd.DataFrame,\n    train_data_type: str = \"original\",\n    use_cache: bool = True,\n    debug: bool = True,\n    target_indices: Optional[np.ndarray] = None,\n    use_class14: bool = False,\n):\n    '''\n    parameters: \n              imgdir: the path to image directory \n              train_df: the dataframe that contians the images id and the bounding boxes\n              train_meta: the dataframe that contians the images id and the original image size\n    Returns           \n               list of dict (dataset_dicts) where each dict contains following:\n\n               -file_name: file name of the image.\n               -image_id: id of the image, index is used here.\n               -height: height of the image.\n               -width: width of the image.\n               -annotation: This is the ground truth annotation data for object detection, which contains following\n               -bbox: bounding box pixel location with shape (n_boxes, 4)\n               -bbox_mode: BoxMode.XYXY_ABS is used here, meaning that absolute value of (xmin, ymin, xmax, ymax) annotation is used in the bbox.\n               -category_id: class label id for each bounding box, with shape (n_boxes,)\n    '''   \n    debug_str = f\"_debug{int(debug)}\"\n    train_data_type_str = f\"_{train_data_type}\"\n    class14_str = f\"_14class{int(use_class14)}\"\n    cache_path = Path(\".\") / f\"dataset_dicts_cache{train_data_type_str}{class14_str}{debug_str}.pkl\"\n    if not use_cache or not cache_path.exists():\n        print(\"Creating data...\")\n        #train_meta = pd.read_csv(imgdir+'/'+\"train_meta.csv\")\n        if debug:\n            train_meta = train_meta.iloc[:500]  # For debug....\n\n        # Load 1 image to get image size.\n        image_id = train_meta.loc[0, \"image_id\"]\n        image_path = str(imgdir+'/'+\"train\"+'/'+ f\"{image_id}.png\")\n        image = cv2.imread(image_path)\n        resized_height, resized_width, ch = image.shape\n        print(f\"image shape: {image.shape}\")\n\n        dataset_dicts = []\n        for index, train_meta_row in tqdm(train_meta.iterrows(), total=len(train_meta)):\n            record = {}\n\n            image_id, height, width = train_meta_row.values\n            filename = str(imgdir+'/'+\"train\"+'/'+ f\"{image_id}.png\")\n            record[\"file_name\"] = filename\n            record[\"image_id\"] = image_id\n            record[\"height\"] = resized_height\n            record[\"width\"] = resized_width\n            objs = []\n            for index2, row in train_df.query(\"image_id == @image_id\").iterrows():\n                # print(row)\n                # print(row[\"class_name\"])\n                # class_name = row[\"class_name\"]\n                class_id = row[\"class_id\"]\n                if class_id == 14:\n                    # It is \"No finding\"\n                    if use_class14:\n                        # Use this No finding class with the bbox covering all image area.\n                        bbox_resized = [0, 0, resized_width, resized_height]\n                        obj = {\n                            \"bbox\": bbox_resized,\n                            \"bbox_mode\": BoxMode.XYXY_ABS,\n                            \"category_id\": class_id,\n                        }\n                        objs.append(obj)\n                    else:\n                        # This annotator does not find anything, skip.\n                        pass\n                else:\n                    # bbox_original = [int(row[\"x_min\"]), int(row[\"y_min\"]), int(row[\"x_max\"]), int(row[\"y_max\"])]\n                    h_ratio = resized_height / height\n                    w_ratio = resized_width / width\n                    bbox_resized = [\n                        float(row[\"x_min\"]) * w_ratio,\n                        float(row[\"y_min\"]) * h_ratio,\n                        float(row[\"x_max\"]) * w_ratio,\n                        float(row[\"y_max\"]) * h_ratio,\n                    ]\n                    obj = {\n                        \"bbox\": bbox_resized,\n                        \"bbox_mode\": BoxMode.XYXY_ABS,\n                        \"category_id\": class_id,\n                    }\n                    objs.append(obj)\n            record[\"annotations\"] = objs\n            dataset_dicts.append(record)\n        with open(cache_path, mode=\"wb\") as f:\n            pickle.dump(dataset_dicts, f)\n\n    print(f\"Load from cache {cache_path}\")\n    with open(cache_path, mode=\"rb\") as f:\n        dataset_dicts = pickle.load(f)\n    if target_indices is not None:\n        dataset_dicts = [dataset_dicts[i] for i in target_indices]\n    return dataset_dicts\n\n##############################################################################################################\n\ndef get_vinbigdata_dicts_test(\n    imgdir: Path, test_meta: pd.DataFrame, use_cache: bool = True, debug: bool = True,\n):\n    '''\n    parameters: \n              imgdir: the path to image directory \n              test_meta: the dataframe that contians the images id and the original image size\n    Returns           \n               list of dict (dataset_dicts) where each dict contains following:\n\n               -file_name: file name of the image.\n               -image_id: id of the image, index is used here.\n               -height: height of the image.\n               -width: width of the image.\n\n    '''       \n    debug_str = f\"_debug{int(debug)}\"\n    cache_path = Path(\".\") / f\"dataset_dicts_cache_test{debug_str}.pkl\"\n    if not use_cache or not cache_path.exists():\n        print(\"Creating data...\")\n        # test_meta = pd.read_csv(imgdir / \"test_meta.csv\")\n        if debug:\n            test_meta = test_meta.iloc[:500]  # For debug....\n\n        # Load 1 image to get image size.\n        image_id = test_meta.loc[0, \"image_id\"]\n        image_path = str(imgdir+'/'+ \"test\"+'/'+ f\"{image_id}.png\")\n        print(image_path)\n        image = cv2.imread(image_path)\n        resized_height, resized_width, ch = image.shape\n        print(f\"image shape: {image.shape}\")\n\n        dataset_dicts = []\n        for index, test_meta_row in tqdm(test_meta.iterrows(), total=len(test_meta)):\n            record = {}\n\n            image_id, height, width = test_meta_row.values\n            filename = str(imgdir+'/'+\"test\"+'/'+ f\"{image_id}.png\")\n            record[\"file_name\"] = filename\n            # record[\"image_id\"] = index\n            record[\"image_id\"] = image_id\n            record[\"height\"] = resized_height\n            record[\"width\"] = resized_width\n            # objs = []\n            # record[\"annotations\"] = objs\n            dataset_dicts.append(record)\n        with open(cache_path, mode=\"wb\") as f:\n            pickle.dump(dataset_dicts, f)\n\n    print(f\"Load from cache {cache_path}\")\n    with open(cache_path, mode=\"rb\") as f:\n        dataset_dicts = pickle.load(f)\n    return dataset_dicts\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"* When training this model i did not use the original images in the dataset provided by the competition ,i used the resized images which resized all the images to 256X256 to speed up the training . \n* link for the dataset: [https://www.kaggle.com/xhlulu/vinbigdata-chest-xray-resized-png-256x256](http://)","metadata":{}},{"cell_type":"code","source":"#read train.csv that contians the train image id and the bounding boxes of the detected thoracic abnormalities\ntrain_df=pd.read_csv('/kaggle/input/vinbigdata-chest-xray-abnormalities-detection/train.csv')\n#read train_meta.csv that contians the train image id and the original image size of the resized image\ntrain_meta_df_ = pd.read_csv('../input/vinbigdata-chest-xray-resized-png-256x256/train_meta.csv')\n#read train_meta.csv that contians the test image id and the original image size of the resized image\ntest_meta_df=pd.read_csv('../input/vinbigdata-testmeta/test_meta.csv')\n\nimgdir='../input/vinbigdata-chest-xray-resized-png-256x256'\ntest_imgdir='../input/vinbigdata-chest-xray-resized-png-256x256'\n\n#spliting the data to train validation and test sets\nfrom sklearn.model_selection import train_test_split\n\ntrain_meta_df,val_meta_df=train_test_split(train_meta_df_, test_size=0.2, random_state=42)\n\ntrain_meta_df.reset_index(drop=True, inplace=True)\nval_meta_df.reset_index(drop=True, inplace=True)\n#Creating the trainig and validation and test list of dicts \ntrain_dict_list=get_vinbigdata_dicts(imgdir,train_df,train_meta_df,train_data_type='train',debug=False)\nval_dict_list=get_vinbigdata_dicts(imgdir,train_df,val_meta_df,train_data_type='val',debug=False)\n\ntest_dict_list=get_vinbigdata_dicts_test(test_imgdir,test_meta_df,debug=False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"thing_classes = [\n    \"Aortic enlargement\",\n    \"Atelectasis\",\n    \"Calcification\",\n    \"Cardiomegaly\",\n    \"Consolidation\",\n    \"ILD\",\n    \"Infiltration\",\n    \"Lung Opacity\",\n    \"Nodule/Mass\",\n    \"Other lesion\",\n    \"Pleural effusion\",\n    \"Pleural thickening\",\n    \"Pneumothorax\",\n    \"Pulmonary fibrosis\"\n]\ncategory_name_to_id = {class_name: index for index, class_name in enumerate(thing_classes)}\n\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Register a Dataset\nrefer to this tutorial :[https://detectron2.readthedocs.io/en/latest/tutorials/datasets.html#](http://)","metadata":{}},{"cell_type":"code","source":"from detectron2.utils.visualizer import Visualizer\nfrom detectron2.data import MetadataCatalog, DatasetCatalog\n\nDatasetCatalog.register(\"vinbigdata_train\",lambda: get_vinbigdata_dicts(imgdir,train_df,train_meta_df,train_data_type='train',debug=False),)\ntrain_metadata=MetadataCatalog.get(\"vinbigdata_train\").set(thing_classes=thing_classes)\n\nDatasetCatalog.register(\"vinbigdata_val\",lambda: get_vinbigdata_dicts(imgdir,train_df,val_meta_df,train_data_type='val',debug=False),)\nval_metadata=MetadataCatalog.get(\"vinbigdata_val\").set(thing_classes=thing_classes)\n\nDatasetCatalog.register(\"vinbigdata_test\",lambda: get_vinbigdata_dicts_test(test_imgdir,test_meta_df,debug=False),)\ntest_metadata=MetadataCatalog.get(\"vinbigdata_test\").set(thing_classes=thing_classes)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import random\nimport matplotlib.pyplot as plt\n\nanomaly_image_ids = train_df.query(\"class_id != 14\")[\"image_id\"].unique()#[0:500]\nanomaly_inds = np.argwhere(train_meta_df[:][\"image_id\"].isin(anomaly_image_ids).values)[:, 0]\n\nfor index in random.sample(anomaly_inds.tolist(), 3):\n    d=train_dict_list[index]\n    img = cv2.imread(d[\"file_name\"])\n    visualizer = Visualizer(img[:, :, ::-1], metadata=train_metadata, scale=1.0)\n    out = visualizer.draw_dataset_dict(d)\n    fig, axes = plt.subplots(1, 2, figsize=(20,20))\n    axes[0].imshow(img)    \n    axes[1].imshow(out.get_image()[:, :, ::-1])\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Adding image augmentation to the training pipline\nrefer to this link for more info :[https://detectron2.readthedocs.io/en/latest/tutorials/augmentation.html](http://)\na great kernel about adding  image augmentation in detectron2 :[https://www.kaggle.com/dhiiyaur/detectron-2-compare-models-augmentation](http://)","metadata":{}},{"cell_type":"code","source":"import albumentations as A\nimport copy\nimport numpy as np\n\nimport torch\nfrom detectron2.data import detection_utils as utils\n\n\nclass AlbumentationsMapper:\n    \"\"\"Mapper which uses `albumentations` augmentations\"\"\"\n    def __init__(self, cfg, is_train: bool = True):\n        aug_kwargs = cfg.aug_kwargs\n        aug_list = [\n        ]\n        if is_train:\n            aug_list.extend([getattr(A, name)(**kwargs) for name, kwargs in aug_kwargs.items()])\n        self.transform = A.Compose(#[\n                         #A.Resize(256,256),\n                         #A.RandomCrop(width=256, height=256,p=0.0),\n                         #A.HorizontalFlip(p=0.0),\n                         #A.RandomBrightnessContrast(p=0.0)\n                        #]\n                        aug_list ,\n                        bbox_params=A.BboxParams(format=\"pascal_voc\", label_fields=[\"category_ids\"])\n                        )\n        self.is_train = is_train\n\n        mode = \"training\" if is_train else \"inference\"\n        print(f\"[AlbumentationsMapper] Augmentations used in {mode}: {self.transform}\")\n\n    def __call__(self, dataset_dict):\n        dataset_dict = copy.deepcopy(dataset_dict)  # it will be modified by code below\n        image = utils.read_image(dataset_dict[\"file_name\"], format=\"BGR\")\n        #image=cv2.imread(dataset_dict[\"file_name\"])\n        #image = cv2.cvtColor(image,cv2.COLOR_GRAY2RGB)\n\n\n        prev_anno = dataset_dict[\"annotations\"]\n        bboxes = np.array([obj[\"bbox\"] for obj in prev_anno], dtype=np.float32)\n        # category_id = np.array([obj[\"category_id\"] for obj in dataset_dict[\"annotations\"]], dtype=np.int64)\n        category_id = np.arange(len(dataset_dict[\"annotations\"]))\n\n        transformed = self.transform(image=image, bboxes=bboxes, category_ids=category_id)\n        image = transformed[\"image\"]\n        annos = []\n        for i, j in enumerate(transformed[\"category_ids\"]):\n            d = prev_anno[j]\n            d[\"bbox\"] = transformed[\"bboxes\"][i]\n            annos.append(d)\n        dataset_dict.pop(\"annotations\", None)  # Remove unnecessary field.\n\n        # if not self.is_train:\n        #     # USER: Modify this if you want to keep them for some reason.\n        #     dataset_dict.pop(\"annotations\", None)\n        #     dataset_dict.pop(\"sem_seg_file_name\", None)\n        #     return dataset_dict\n\n        image_shape = image.shape[:2]  # h, w\n        dataset_dict[\"image\"] = torch.as_tensor(image.transpose(2, 0, 1).astype(\"float32\"))\n        instances = utils.annotations_to_instances(annos, image_shape)\n        #dataset_dict[\"instances\"]=instances\n        dataset_dict[\"instances\"] = utils.filter_empty_instances(instances)\n        return dataset_dict","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import detectron2.data.transforms as T\nfrom detectron2.engine import DefaultTrainer\nfrom detectron2.data import DatasetCatalog, MetadataCatalog, build_detection_test_loader, build_detection_train_loader\nfrom detectron2.data import detection_utils as utils\nimport torch\n\ndef custom_mapper(dataset_dict):\n    # Implement a mapper, similar to the default DatasetMapper, but with your own customizations\n    dataset_dict = copy.deepcopy(dataset_dict)  # it will be modified by code below\n    image = utils.read_image(dataset_dict[\"file_name\"], format=\"BGR\")\n    transform_list = [#T.Resize((800,800)),\n                      #T.RandomFlip(prob=0.0, horizontal=False, vertical=True),\n                      #T.RandomFlip(prob=0.0, horizontal=True, vertical=False), \n                      ]\n    image, transforms = T.apply_transform_gens(transform_list, image)\n    dataset_dict[\"image\"] = torch.as_tensor(image.transpose(2, 0, 1).astype(\"float32\"))\n\n    annos = [\n        utils.transform_instance_annotations(obj, transforms, image.shape[:2])\n        for obj in dataset_dict.pop(\"annotations\")\n        if obj.get(\"iscrowd\", 0) == 0\n    ]\n    instances = utils.annotations_to_instances(annos, image.shape[:2])\n    dataset_dict[\"instances\"] = utils.filter_empty_instances(instances)\n    return dataset_dict\n\nclass Trainer_(DefaultTrainer):\n    \n    @classmethod\n    def build_train_loader(cls, cfg):\n        return build_detection_train_loader(cfg, mapper=AlbumentationsMapper(cfg, True))\n        #return build_detection_train_loader(cfg, mapper=custom_mapper)\n    \n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from dataclasses import dataclass, field\nfrom typing import Dict\n\n\n@dataclass\nclass Flags:\n    # General\n    debug: bool = True\n    outdir: str = \"results/det\"\n\n    # Data config\n    imgdir_name: str = \"vinbigdata-chest-xray-resized-png-256x256\"\n    split_mode: str = \"all_train\"  # all_train or valid20\n    seed: int = 111\n    train_data_type: str = \"original\"  # original or wbf\n    use_class14: bool = False\n    # Training config\n    iter: int = 10000\n    ims_per_batch: int = 2  # images per batch, this corresponds to \"total batch size\"\n    num_workers: int = 4\n    lr_scheduler_name: str = \"WarmupMultiStepLR\"  # WarmupMultiStepLR (default) or WarmupCosineLR\n    base_lr: float = 0.00025\n    roi_batch_size_per_image: int = 512\n    #eval_period: int = 10000\n    aug_kwargs: Dict = field(default_factory=lambda: {})\n\n    def update(self, param_dict: Dict) -> \"Flags\":\n        # Overwrite by `param_dict`\n        for key, value in param_dict.items():\n            if not hasattr(self, key):\n                raise ValueError(f\"[ERROR] Unexpected key for flag = {key}\")\n            setattr(self, key, value)\n        return self","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"flags_dict = {\n    \"debug\": False,\n    \"outdir\": \"results\", \n    \"imgdir_name\": \"vinbigdata-chest-xray-resized-png-256x256\",\n    #\"split_mode\": \"valid20\",\n    \"iter\": 50000,\n    \"roi_batch_size_per_image\": 512,\n    #\"eval_period\": 5000,\n    \"lr_scheduler_name\": \"WarmupCosineLR\",\n    \"base_lr\": 0.001,\n    \"num_workers\": 4,\n    \"aug_kwargs\": {\n        \"HorizontalFlip\": {\"p\": 0.5},\n        \"ShiftScaleRotate\": {\"scale_limit\": 0.15, \"rotate_limit\": 10, \"p\": 0.5},\n        \"RandomBrightnessContrast\": {\"p\": 0.5}\n    }\n}","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from detectron2.engine import DefaultTrainer\nfrom detectron2 import model_zoo\nfrom detectron2.engine import DefaultPredictor\nfrom detectron2.config import get_cfg\nfrom detectron2.utils.visualizer import Visualizer\nfrom detectron2.data import MetadataCatalog, DatasetCatalog\nfrom detectron2.utils.logger import setup_logger\nimport copy\nsetup_logger()\nimport os\n\nflags = Flags().update(flags_dict)\nfrom detectron2.config.config import CfgNode as CN\n\ncfg = get_cfg()\ncfg.aug_kwargs = CN(flags.aug_kwargs)  # pass aug_kwargs to cfg\n\noriginal_output_dir = cfg.OUTPUT_DIR\n#cfg.OUTPUT_DIR = str(outdir)\nprint(f\"cfg.OUTPUT_DIR {original_output_dir} -> {cfg.OUTPUT_DIR}\")\n\nconfig_name = \"COCO-Detection/faster_rcnn_R_50_FPN_3x.yaml\"\ncfg.merge_from_file(model_zoo.get_config_file(config_name))\ncfg.DATASETS.TRAIN = (\"vinbigdata_train\",)\ncfg.DATASETS.TEST=()\ncfg.DATALOADER.NUM_WORKERS = flags.num_workers\n# Let training initialize from model zoo\ncfg.MODEL.WEIGHTS = model_zoo.get_checkpoint_url(config_name)\ncfg.SOLVER.IMS_PER_BATCH = flags.ims_per_batch\ncfg.SOLVER.LR_SCHEDULER_NAME = flags.lr_scheduler_name\ncfg.SOLVER.BASE_LR = flags.base_lr  # pick a good LR\ncfg.SOLVER.MAX_ITER = flags.iter\ncfg.SOLVER.CHECKPOINT_PERIOD = 100000  # Small value=Frequent save need a lot of storage.\ncfg.MODEL.ROI_HEADS.BATCH_SIZE_PER_IMAGE = flags.roi_batch_size_per_image\ncfg.MODEL.ROI_HEADS.NUM_CLASSES = len(thing_classes)\n# NOTE: this config means the number of classes,\n# but a few popular unofficial tutorials incorrect uses num_classes+1 here.\n\nos.makedirs(cfg.OUTPUT_DIR, exist_ok=True)\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"trainer_=Trainer_(cfg)\ntrain_data_loader = trainer_.build_train_loader(cfg)\ndata_iter = iter(train_data_loader)\nbatch = next(data_iter)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# visualization\n\n#rows, cols = 1, 2\n#plt.figure(figsize=(20,20))\n\nfor i, per_image in enumerate(batch[:4]):\n    \n    image_id=per_image['image_id']\n    for dict_ in train_dict_list:\n        if dict_['image_id']==image_id:\n           d=dict_\n        \n    #plt.subplot(rows, cols, i+1)\n    # Pytorch tensor is in (C, H, W) format\n\n    \n    \n    image=cv2.imread(d[\"file_name\"])\n    visualizer_ = Visualizer(image, metadata=train_metadata, scale=1.0)\n    out = visualizer_.draw_dataset_dict(d)\n    \n    \n    img_aug = per_image[\"image\"].permute(1, 2, 0).cpu().detach().numpy()\n    img_aug = utils.convert_image_to_rgb(img_aug, cfg.INPUT.FORMAT)\n    \n    visualizer = Visualizer(img_aug, metadata=train_metadata, scale=1.0)\n\n    target_fields = per_image[\"instances\"].get_fields()\n    labels = [\n                train_metadata.thing_classes[i] for i in target_fields[\"gt_classes\"]\n            ]\n\n    out_aug = visualizer.overlay_instances(\n        labels=labels,\n        boxes=target_fields.get(\"gt_boxes\", None),\n        masks=target_fields.get(\"gt_masks\", None),\n        keypoints=target_fields.get(\"gt_keypoints\", None),\n    )  \n    \n    fig, axes = plt.subplots(1, 4, figsize=(40,40))\n    axes[0].imshow(image)    \n    axes[1].imshow(out.get_image()[:, :, ::-1])\n    axes[2].imshow(img_aug.astype(\"int\"))    \n    axes[3].imshow(out_aug.get_image()[:, :, ::-1])\n    ","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Training the model","metadata":{}},{"cell_type":"code","source":"#trainer_=Trainer_(cfg)\n#trainer_.resume_or_load(resume=False)\n#trainer_.train()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# load the trained model","metadata":{}},{"cell_type":"code","source":"import os\ncfg.MODEL.WEIGHTS = '../input/detectron2-vinbigdata-model-final-weights/model_final.pth'#os.path.join(cfg.OUTPUT_DIR, \"model_final.pth\")  # path to the model we just trained\ncfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.4   # set a custom testing threshold\npredictor = DefaultPredictor(cfg)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# The evaluation on the validation dataset ","metadata":{}},{"cell_type":"markdown","source":"* the evaluation metric for this competition is like any other object detection problem is Mean Average Precision (mAP) but at IoU > 0.4.\n* to learn more about mAP refer to this links\n* [https://towardsdatascience.com/breaking-down-mean-average-precision-map-ae462f623a52](http://)\n* [https://www.youtube.com/watch?v=FppOzcDvaDI&t=1s](http://)","metadata":{}},{"cell_type":"code","source":"from detectron2.evaluation import COCOEvaluator, inference_on_dataset\n\nevaluator = COCOEvaluator(\"vinbigdata_val\", cfg, False, output_dir=cfg.OUTPUT_DIR)\nval_loader = build_detection_test_loader(cfg, \"vinbigdata_val\")\ninference_on_dataset(predictor.model, val_loader, evaluator)#trainer_.model","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# The visualization of the output of the trained model","metadata":{}},{"cell_type":"code","source":"from typing import Any, Union\n\nfrom typing import Any, Dict, List\nfrom numpy import ndarray\n\ndef predict_batch(predictor: DefaultPredictor, im_list: List[ndarray]) -> List:\n    with torch.no_grad():  # https://github.com/sphinx-doc/sphinx/issues/4258\n        inputs_list = []\n        for original_image in im_list:\n            # Apply pre-processing to image.\n            if predictor.input_format == \"RGB\":\n                # whether the model expects BGR inputs or RGB\n                original_image = original_image[:, :, ::-1]\n            height, width = original_image.shape[:2]\n            # Do not apply original augmentation, which is resize.\n            # image = predictor.aug.get_transform(original_image).apply_image(original_image)\n            image = original_image\n            image = torch.as_tensor(image.astype(\"float32\").transpose(2, 0, 1))\n            inputs = {\"image\": image, \"height\": height, \"width\": width}\n            inputs_list.append(inputs)\n        predictions = predictor.model(inputs_list)\n        return predictions\n    \nanomaly_image_ids = train_df.query(\"class_id != 14\")[\"image_id\"].unique()\ntrain_meta = pd.read_csv(imgdir+\"/train_meta.csv\")\nanomaly_inds = np.argwhere(train_meta[\"image_id\"].isin(anomaly_image_ids).values)[:, 0]\nanomaly_inds=[index for index in anomaly_inds if index < len(train_dict_list)]\nindex_list=[1999, 8190, 1544, 9247, 9521, 10621]#random.sample(anomaly_inds, 6)\ndicts_=[train_dict_list[index] for index in index_list]\n\nim_list=[cv2.imread(train_dict_list[index][\"file_name\"]) for index in index_list]\n\noutputs_list = predict_batch(predictor, im_list)    \n    \n\nfor img,d,output in zip(im_list,dicts_,outputs_list):\n    visualizer = Visualizer(img[:, :, ::-1], metadata=train_metadata, scale=1.0)\n    out = visualizer.draw_dataset_dict(d)\n    \n    v = Visualizer(img[:, :, ::-1],\n                   metadata=train_metadata, \n                   scale=1.0, )\n\n\n    out_ = v.draw_instance_predictions(output[\"instances\"].to(\"cpu\"))\n    \n    fig, axes = plt.subplots(1, 3, figsize=(40,40))\n    axes[0].imshow(img)    \n    axes[1].imshow(out.get_image()[:, :, ::-1])\n    axes[2].imshow(out_.get_image()[:, :, ::-1])\n    ","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_list=os.listdir('../input/vinbigdata-chest-xray-resized-png-256x256/test')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(test_meta_df)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Making the submission file","metadata":{}},{"cell_type":"code","source":"from tqdm import tqdm\nfrom math import ceil\nbatch_size=4\nresults_list=[]\n\ndef format_pred(labels: ndarray, boxes: ndarray, scores: ndarray) -> str:\n    pred_strings = []\n    for label, score, bbox in zip(labels, scores, boxes):\n        xmin, ymin, xmax, ymax = bbox.astype(np.int64)\n        pred_strings.append(f\"{label} {score} {xmin} {ymin} {xmax} {ymax}\")\n    return \" \".join(pred_strings)\nindex=0\n\nfor i in tqdm(range(ceil(len(test_dict_list) / batch_size))):\n    inds = list(range(batch_size * i, min(batch_size * (i + 1), len(test_dict_list))))\n    dataset_dicts_batch = [test_dict_list[i] for i in inds]\n    im_list = [cv2.imread(d[\"file_name\"]) for d in dataset_dicts_batch]\n    outputs_list = predict_batch(predictor, im_list)\n\n    for im, outputs, d in zip(im_list, outputs_list, dataset_dicts_batch):\n        resized_height, resized_width, ch = im.shape\n\n        image_id, dim0, dim1 = test_meta_df.iloc[index].values\n\n        instances = outputs[\"instances\"]\n        if len(instances) == 0:\n            # No finding, let's set 14 1 0 0 1 1x.\n            result = {\"image_id\": image_id, \"PredictionString\": \"14 1.0 0 0 1 1\"}\n        else:\n            # Find some bbox...\n            # print(f\"index={index}, find {len(instances)} bbox.\")\n            fields: Dict[str, Any] = instances.get_fields()\n            pred_classes = fields[\"pred_classes\"]  # (n_boxes,)\n            pred_scores = fields[\"scores\"]\n            # shape (n_boxes, 4). (xmin, ymin, xmax, ymax)\n            pred_boxes = fields[\"pred_boxes\"].tensor\n\n            h_ratio = dim0 / resized_height\n            w_ratio = dim1 / resized_width\n            pred_boxes[:, [0, 2]] *= w_ratio\n            pred_boxes[:, [1, 3]] *= h_ratio\n\n            pred_classes_array = pred_classes.cpu().numpy()\n            pred_boxes_array = pred_boxes.cpu().numpy()\n            pred_scores_array = pred_scores.cpu().numpy()\n\n            result = {\n                \"image_id\": image_id,\n                \"PredictionString\": format_pred(\n                    pred_classes_array, pred_boxes_array, pred_scores_array\n                ),\n            }\n        results_list.append(result)\n        index += 1","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission_det = pd.DataFrame(results_list, columns=['image_id', 'PredictionString'])\nsubmission_det.to_csv(\"./submission.csv\", index=False)\n#submission_det","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from IPython.display import FileLink\nFileLink(r'./submission.csv')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}