{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# PIP Installs\n!/opt/conda/bin/python3.7 -m pip install -q --upgrade pip      # Upgrade PIP\n!pip install -q pylibjpeg pylibjpeg-libjpeg pylibjpeg-openjpeg # Install/Upgrade PyDicom Dependencies\n\n# Machine Learning and Data Science Imports\nimport tensorflow_probability as tfp\nimport tensorflow_datasets as tfds\nimport tensorflow_addons as tfa\nimport tensorflow_hub as hub\nfrom skimage import exposure\nimport pandas as pd; pd.options.mode.chained_assignment = None\nimport numpy as np\nimport scipy\n\n# Built In Imports\nfrom datetime import datetime\nfrom glob import glob\nimport warnings\nimport IPython\nimport urllib\nimport zipfile\nimport pickle\nimport shutil\nimport string\nimport math\nimport tqdm\nimport time\nimport os\nimport gc\nimport re\n\n# Visualization Imports\nfrom matplotlib.colors import ListedColormap\nimport matplotlib.patches as patches\nimport plotly.graph_objects as go\nimport matplotlib.pyplot as plt\nimport plotly.express as px\nimport seaborn as sns\nfrom PIL import Image\nimport matplotlib\nimport plotly\nimport PIL\nimport cv2\n\n# PRESETS\nFIG_FONT = dict(family=\"Helvetica, Arial\", size=14, color=\"#7f7f7f\")\nLABEL_COLORS = [px.colors.label_rgb(px.colors.convert_to_RGB_255(x)) for x in sns.color_palette(\"Spectral\", 15)]\nLABEL_COLORS_WOUT_NO_FINDING = LABEL_COLORS[:8]+LABEL_COLORS[9:]\n\n# Other Imports\nfrom pydicom.pixel_data_handlers.util import apply_voi_lut\nfrom tqdm.notebook import tqdm\nimport pydicom\n\nprint(\"\\n... IMPORTS COMPLETE ...\\n\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Define the root data directory\n# 定义数据根目录\nDATA_DIR = \"/kaggle/input/vinbigdata-chest-xray-abnormalities-detection\"\n\n# Define the paths to the training and testing dicom folders respectively\n# dicom数据\nTRAIN_DIR = os.path.join(DATA_DIR, \"train\")\nTEST_DIR = os.path.join(DATA_DIR, \"test\")\n\n# Capture all the relevant full train/test paths\n# 取所有dicom数据\nTRAIN_DICOM_PATHS = [os.path.join(TRAIN_DIR, f_name) for f_name in os.listdir(TRAIN_DIR)]\nTEST_DICOM_PATHS = [os.path.join(TEST_DIR, f_name) for f_name in os.listdir(TEST_DIR)]\nprint(f\"\\n... The number of training files is {len(TRAIN_DICOM_PATHS)} ...\")\nprint(f\"... The number of testing files is {len(TEST_DICOM_PATHS)} ...\")\n\n\n\n# Define paths to the relevant csv files\n# 取train.csv和submission.csv\nTRAIN_CSV = os.path.join(DATA_DIR, \"train.csv\")\nSS_CSV = os.path.join(DATA_DIR, \"sample_submission.csv\")\n# Create the relevant dataframe objects\ntrain_df = pd.read_csv(TRAIN_CSV)\nss_df = pd.read_csv(SS_CSV)\n\nprint(\"\\n\\nTRAIN DATAFRAME\\n\\n\")\ndisplay(train_df.head(3))\n\nprint(\"\\n\\nSAMPLE SUBMISSION DATAFRAME\\n\\n\")\ndisplay(ss_df.head(3))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"# dicom转np.array\ndef dicom2array(path, voi_lut=True, fix_monochrome=True):\n    \"\"\" Convert dicom file to numpy array \n    \n    Args:\n        path (str): Path to the dicom file to be converted\n        voi_lut (bool): Whether or not VOI LUT is available\n        fix_monochrome (bool): Whether or not to apply monochrome fix\n        \n    Returns:\n        Numpy array of the respective dicom file \n        \n    \"\"\"\n    # Use the pydicom library to read the dicom file\n    dicom = pydicom.read_file(path)\n    \n    # VOI LUT (if available by DICOM device) is used to \n    # transform raw DICOM data to \"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    # The XRAY may look inverted\n    #   - If we want to fix this we can\n    if fix_monochrome and dicom.PhotometricInterpretation == \"MONOCHROME1\":\n        data = np.amax(data) - data\n    \n    # Normalize the image array and return\n    data = data - np.min(data)\n    data = data / np.max(data)\n    data = (data * 255).astype(np.uint8)\n    return data\n\n# 画图\ndef plot_image(img, title=\"\", figsize=(8,8), cmap=None):\n    \"\"\" Function to plot an image to save a bit of time \"\"\"\n    plt.figure(figsize=figsize)\n    \n    if cmap:\n        plt.imshow(img, cmap=cmap)\n    else:\n        img\n        plt.imshow(img)\n        \n    plt.title(title, fontweight=\"bold\")\n    plt.axis(False)\n    plt.show()\n\n# 获得图片id    \ndef get_image_id(path):\n    \"\"\" Function to return the image-id from a path \"\"\"\n    return path.rsplit(\"/\", 1)[1].rsplit(\".\", 1)[0]\n\n# 计算坐标\ndef create_fractional_bbox_coordinates(row):\n    \"\"\" Function to return bbox coordiantes as fractions from DF row \"\"\"\n    frac_x_min = row[\"x_min\"]/row[\"img_width\"]\n    frac_x_max = row[\"x_max\"]/row[\"img_width\"]\n    frac_y_min = row[\"y_min\"]/row[\"img_height\"]\n    frac_y_max = row[\"y_max\"]/row[\"img_height\"]\n    return frac_x_min, frac_x_max, frac_y_min, frac_y_max\n\n# 画box\ndef draw_bboxes(img, tl, br, rgb, label=\"\", label_location=\"tl\", opacity=0.1, line_thickness=0):\n    \"\"\" TBD \n    \n    Args:\n        TBD\n        \n    Returns:\n        TBD \n    \"\"\"\n    rect = np.uint8(np.ones((br[1]-tl[1], br[0]-tl[0], 3))*rgb)\n    sub_combo = cv2.addWeighted(img[tl[1]:br[1],tl[0]:br[0],:], 1-opacity, rect, opacity, 1.0)    \n    img[tl[1]:br[1],tl[0]:br[0],:] = sub_combo\n\n    if line_thickness>0:\n        img = cv2.rectangle(img, tuple(tl), tuple(br), rgb, line_thickness)\n        \n    if label:\n        # DEFAULTS\n        FONT = cv2.FONT_HERSHEY_SIMPLEX\n        FONT_SCALE = 1.666\n        FONT_THICKNESS = 3\n        FONT_LINE_TYPE = cv2.LINE_AA\n        \n        if type(label)==str:\n            LABEL = label.upper().replace(\" \", \"_\")\n        else:\n            LABEL = f\"CLASS_{label:02}\"\n        \n        text_width, text_height = cv2.getTextSize(LABEL, FONT, FONT_SCALE, FONT_THICKNESS)[0]\n        \n        label_origin = {\"tl\":tl, \"br\":br, \"tr\":(br[0],tl[1]), \"bl\":(tl[0],br[1])}[label_location]\n        label_offset = {\n            \"tl\":np.array([0, -10]), \"br\":np.array([-text_width, text_height+10]), \n            \"tr\":np.array([-text_width, -10]), \"bl\":np.array([0, text_height+10])\n        }[label_location]\n        img = cv2.putText(img, LABEL, tuple(label_origin+label_offset), \n                          FONT, FONT_SCALE, rgb, FONT_THICKNESS, FONT_LINE_TYPE)\n    \n    return img","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Create dictionary mappings\n# 把病名改成数字表示\nint_2_str = {i:train_df[train_df[\"class_id\"]==i].iloc[0][\"class_name\"] for i in range(15)}\nstr_2_int = {v:k for k,v in int_2_str.items()}\nint_2_clr = {str_2_int[k]:LABEL_COLORS[i] for i,k in enumerate(sorted(str_2_int.keys()))}\n\nprint(\"\\n... Dictionary Mapping Class Integer to Class String Representation [int_2_str]...\\n\")\ndisplay(int_2_str)\n\nprint(\"\\n... Dictionary Mapping Class String to Class Integer Representation [str_2_int]...\\n\")\ndisplay(str_2_int)\n\nprint(\"\\n... Dictionary Mapping Class Integer to Color Representation [str_2_clr]...\\n\")\ndisplay(int_2_clr)\n\nprint(\"\\n... Head of Train Dataframe After Dropping The Class Name Column...\\n\")\ntrain_df.drop(columns=[\"class_name\"], inplace=True)\ndisplay(train_df.head(5))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"tmp_numpy = train_df.to_numpy()\nimage_ids = tmp_numpy[0]\nclass_ids = tmp_numpy[1]\nrad_ids = tmp_numpy[2]\nbboxes = tmp_numpy[3:]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"bboxes","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# TrainData是自定义的类，实现了很多功能\n\nclass TrainData():\n    def __init__(self, df, train_dir, cmap=\"Spectral\"):\n        # Initialize\n        self.df = df\n        self.train_dir = train_dir\n        \n        # Visualization\n        self.cmap = cmap\n        self.pal = [tuple([int(x) for x in np.array(c)*(255,255,255)]) for c in sns.color_palette(cmap, 15)]\n        self.pal.pop(8)\n        \n        # Store df components in individual numpy arrays for easy access based on index\n        tmp_numpy = self.df.to_numpy()\n        image_ids = tmp_numpy[0]\n        class_ids = tmp_numpy[1]\n        rad_ids = tmp_numpy[2]\n        bboxes = tmp_numpy[3:]\n        \n        self.img_annotations = self.get_annotations(get_all=True)\n        \n        # Clean-Up\n        del tmp_numpy; gc.collect();\n        \n    # 获取标记    \n    def get_annotations(self, get_all=False, image_ids=None, class_ids=None, rad_ids=None, index=None):\n        \"\"\" TBD \n        \n        Args:\n            get_all (bool, optional): TBD\n            image_ids (list of strs, optional): TBD\n            class_ids (list of ints, optional): TBD\n            rad_ids (list of strs, optional): TBD\n            index (int, optional):\n        \n        Returns:\n        \n        \n        \"\"\"\n        if not get_all and image_ids is None and class_ids is None and rad_ids is None and index is None:\n            raise ValueError(\"Expected one of the following arguments to be passed:\" \\\n                             \"\\n\\t\\t– `get_all`, `image_id`, `class_id`, `rad_id`, or `index`\")\n        # Initialize\n        tmp_df = self.df.copy()\n        \n        if not get_all:\n            if image_ids is not None:\n                tmp_df = tmp_df[tmp_df.image_id.isin(image_ids)]\n            if class_ids is not None:\n                tmp_df = tmp_df[tmp_df.class_id.isin(class_ids)]\n            if rad_ids is not None:\n                tmp_df = tmp_df[tmp_df.rad_id.isin(rad_ids)]\n            if index is not None:\n                tmp_df = tmp_df.iloc[index]\n            \n        annotations = {image_id:[] for image_id in tmp_df.image_id.to_list()}\n        for row in tmp_df.to_numpy():\n            \n            # Update annotations dictionary\n            annotations[row[0]].append(dict(\n                img_path=os.path.join(self.train_dir, row[0]+\".dicom\"),\n                image_id=row[0],\n                class_id=int(row[1]),\n                rad_id=int(row[2][1:]),\n            ))\n            \n            # Catch to convert float array to integer array\n            if row[1]==14:\n                annotations[row[0]][-1][\"bbox\"]=row[3:]\n            else:\n                annotations[row[0]][-1][\"bbox\"]=row[3:].astype(np.int32)\n        return annotations\n    \n    # 获取标记图\n    def get_annotated_image(self, image_id, annots=None, plot=False, plot_size=(18,25), plot_title=\"\"):\n        if annots is None:\n            annots = self.img_annotations.copy()\n        \n        if type(annots) != list:\n            image_annots = annots[image_id]\n        else:\n            image_annots = annots\n            \n        img = cv2.cvtColor(dicom2array(image_annots[0][\"img_path\"]),cv2.COLOR_GRAY2RGB)\n        for ann in image_annots:\n            if ann[\"class_id\"] != 14:\n                img = draw_bboxes(img, \n                                ann[\"bbox\"][:2], ann[\"bbox\"][-2:], \n                                rgb=self.pal[ann[\"class_id\"]], \n                                label=int_2_str[ann[\"class_id\"]], \n                                opacity=0.08, line_thickness=4)\n        if plot:\n            plot_image(img, title=plot_title, figsize=plot_size)\n        \n        return img\n    \n    # 利用id画出标记图\n    def plot_image_ids(self, image_id_list, height_multiplier=6, verbose=True):\n        annotations = self.get_annotations(image_ids=image_id_list)\n        annotated_imgs = []\n        n = len(image_id_list)\n        \n        plt.figure(figsize=(20, height_multiplier*n))\n        for i, (image_id, annots) in enumerate(annotations.items()):\n            if i >= n:\n                break\n            if verbose:\n                print(f\".\", end=\"\")\n            plt.subplot(n//2,2,i+1)\n            plt.imshow(self.get_annotated_image(image_id, annots))\n            plt.axis(False)\n            plt.title(f\"Image ID – {image_id}\")\n        plt.tight_layout(rect=[0, 0.03, 1, 0.97])\n        plt.show()\n        \n    # 利用类别画出标记图    \n    def plot_classes(self, class_list, n=4, height_multiplier=6, verbose=True):\n        annotations = self.get_annotations(class_ids=class_list)\n        annotated_imgs = []\n\n        plt.figure(figsize=(20, height_multiplier*n))\n        for i, (image_id, annots) in enumerate(annotations.items()):\n            if i >= n:\n                break\n            if verbose:\n                print(f\".\", end=\"\")\n            plt.subplot(n//2,2,i+1)\n            plt.imshow(self.get_annotated_image(image_id, annots))\n            plt.axis(False)\n            plt.title(f\"Image ID – {image_id}\")\n        plt.tight_layout(rect=[0, 0.03, 1, 0.97])\n        plt.show()\n        \n    # 利用医生画出标记图\n    def plot_radiologists(self, rad_id_list, n=4, height_multiplier=6, verbose=True):\n        annotations = self.get_annotations(rad_ids=rad_id_list)\n        annotated_imgs = []\n\n        plt.figure(figsize=(20, height_multiplier*n))\n        for i, (image_id, annots) in enumerate(annotations.items()):\n            if i >= n:\n                break\n            if verbose:\n                print(f\".\", end=\"\")\n            plt.subplot(n//2,2,i+1)\n            plt.imshow(self.get_annotated_image(image_id, annots))\n            plt.axis(False)\n            plt.title(f\"Image ID – {image_id}\")\n        plt.tight_layout(rect=[0, 0.03, 1, 0.97])\n        plt.show()\n        \n    # 输入的字符串与id画出标记图\n    def plot_str_image_ids(self, image_id_list, height_multiplier=6, verbose=True):\n        annotations = self.get_annotations(image_ids=image_id_list)\n        annotated_imgs = []\n        n = len(image_id_list)\n        \n        plt.figure(figsize=(20, height_multiplier*n))\n        for i, (image_id, annots) in enumerate(annotations.items()):\n            if i >= n:\n                break\n            if verbose:\n                print(f\".\", end=\"\")\n            plt.subplot(n//2,2,i+1)\n            plt.imshow(self.get_annotated_image(image_id, annots))\n            plt.axis(False)\n            plt.title(f\"Image ID – {image_id}\")\n        plt.tight_layout(rect=[0, 0.03, 1, 0.97])\n        plt.show()\n\ntrain_data = TrainData(train_df, TRAIN_DIR)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df.columns","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# 利用id画出标记\nIMAGE_ID_LIST=['4b56bc6d22b192f075f13231419dfcc8', '051132a778e61a86eb147c7c6f564dfe']\ntrain_data.plot_str_image_ids(image_id_list=IMAGE_ID_LIST, verbose=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#######","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_raw_high=pd.read_csv('../input/subtrain/submission_train.csv')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_raw_high","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import csv\ndf_raw_high=pd.read_csv('../input/subtrain-suit/submission_train.csv')\nwith open(\"model_high.csv\",\"w\") as csvfile: \n    writer = csv.writer(csvfile)\n\n    #先写入columns_name\n    writer.writerow(['image_id', 'class_id', 'rad_id', 'x_min', 'y_min', 'x_max', 'y_max'])\n    content_list=[]\n    for i in range(df_raw_high.shape[0]):\n        image_id_str=df_raw_high.iloc[i]['image_id']\n        prediction_str=df_raw_high.iloc[i]['PredictionString']\n        list_prediction_str=prediction_str.split(\" \")\n#         print(image_id_str,len(list_prediction_str))\n        for j in range(int(len(list_prediction_str)/6)):\n            if int(list_prediction_str[j*6+0])==14:\n#                 print('true')\n                continue\n            content_list.append([image_id_str,list_prediction_str[j*6+0],'R0',list_prediction_str[j*6+2],list_prediction_str[j*6+3],list_prediction_str[j*6+4],list_prediction_str[j*6+5]])\n#             if list_prediction_str[j*6+0]==14:\n#                 print('class_id',list_prediction_str[j*6+0])\n#             print('class_id',list_prediction_str[j*6+0])\n                \n            \n    \n    #写入多行用writerows\n    writer.writerows(content_list)\n\ndf_model_high=pd.read_csv('model_high.csv')\ndf_model_high","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# df_raw_high=pd.read_csv('../input/csv-store/highscore.csv')\n# df_raw_low=pd.read_csv('../input/csv-store/sub_3.18.csv')\n\n\n\n# # import csv\n\n# # with open(\"test.csv\",\"w\") as csvfile: \n# #     writer = csv.writer(csvfile)\n\n# #     #先写入columns_name\n# #     writer.writerow(['image_id', 'class_id', 'rad_id', 'x_min', 'y_min', 'x_max', 'y_max'])\n# #     #写入多行用writerows\n# #     writer.writerows([[0,1,3],[1,2,3],[2,3,4]])\n    \n# # writer\n\n# # dsaigh=pd.read_csv('test.csv')\n# # dsaigh\n\n\n\n# import csv\n\n# with open(\"model_high.csv\",\"w\") as csvfile: \n#     writer = csv.writer(csvfile)\n\n#     #先写入columns_name\n#     writer.writerow(['image_id', 'class_id', 'rad_id', 'x_min', 'y_min', 'x_max', 'y_max'])\n#     content_list=[]\n#     for i in range(df_raw_high.shape[0]):\n#         image_id_str=df_raw_high.iloc[i]['image_id']\n#         prediction_str=df_raw_high.iloc[i]['PredictionString']\n#         list_prediction_str=prediction_str.split(\" \")\n#         print(image_id_str,len(list_prediction_str))\n#         for j in range(int(len(list_prediction_str)/6)):\n#             if int(list_prediction_str[j*6+0])==14:\n# #                 print('true')\n#                 continue\n#             content_list.append([image_id_str,list_prediction_str[j*6+0],'R0',list_prediction_str[j*6+2],list_prediction_str[j*6+3],list_prediction_str[j*6+4],list_prediction_str[j*6+5]])\n# #             if list_prediction_str[j*6+0]==14:\n# #                 print('class_id',list_prediction_str[j*6+0])\n# #             print('class_id',list_prediction_str[j*6+0])\n                \n            \n    \n#     #写入多行用writerows\n#     writer.writerows(content_list)\n\n# df_model_high=pd.read_csv('model_high.csv')\n# df_model_high\n\n# import csv\n\n# with open(\"model_low.csv\",\"w\") as csvfile: \n#     writer = csv.writer(csvfile)\n\n#     #先写入columns_name\n#     writer.writerow(['image_id', 'class_id', 'rad_id', 'x_min', 'y_min', 'x_max', 'y_max'])\n#     content_list=[]\n#     for i in range(df_raw_low.shape[0]):\n#         image_id_str=df_raw_low.iloc[i]['image_id']\n#         prediction_str=df_raw_low.iloc[i]['PredictionString']\n#         list_prediction_str=prediction_str.split(\" \")\n#         print(image_id_str,len(list_prediction_str)/6)\n#         for j in range(int(len(list_prediction_str)/6)):\n#             if int(list_prediction_str[j*6+0])==14:\n# #                 print('true')\n#                 continue\n#             content_list.append([image_id_str,list_prediction_str[j*6+0],'R0',list_prediction_str[j*6+2],list_prediction_str[j*6+3],list_prediction_str[j*6+4],list_prediction_str[j*6+5]])\n# #             if list_prediction_str[j*6+0]==14:\n# #                 print('class_id',list_prediction_str[j*6+0])\n# #             print('class_id',list_prediction_str[j*6+0])\n                \n            \n    \n#     #写入多行用writerows\n#     writer.writerows(content_list)\n\n# df_model_low=pd.read_csv('model_low.csv')\n# df_model_low","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"high_test_data = TrainData(df_model_high, '/kaggle/input/vinbigdata-chest-xray-abnormalities-detection/train')\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# 利用id画出标记\nIMAGE_ID_LIST=['18ee9ef3baea468de2087e0edd85e919', '7eda1e28e4cee7d8016276c87b76259f']\n# use high score csv to create a datastruce(0.235)\nhigh_test_data.plot_image_ids(image_id_list=IMAGE_ID_LIST, verbose=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# 利用id画出标记\nIMAGE_ID_LIST=['4b56bc6d22b192f075f13231419dfcc8', '051132a778e61a86eb147c7c6f564dfe']\ntrain_data.plot_str_image_ids(image_id_list=IMAGE_ID_LIST, verbose=False)\nhigh_test_data.plot_image_ids(image_id_list=IMAGE_ID_LIST, verbose=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# IMAGE_ID_LIST=list(set(IMAGE_ID_LIST))\n# IMAGE_ID_LIST","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"IMAGE_ID_LIST=['01ded16689539deb30d0981fafd18465',\n '0291515f5d14c34180a15712a55bf7bd',\n '037503b94eb68a16587a78bce365e681',\n '03a395d9fc03a6f8c5a50e693c20ab15']","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# use low score csv to create a datastruce\nlow_test_data = TrainData(df_model_low, '/kaggle/input/vinbigdata-chest-xray-abnormalities-detection/test')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# IMAGE_ID_LIST=['008bdde2af2462e86fd373a445d0f4cd',\n#  '00a2145de1886cb9eb88869c85d74080']","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"low_test_data.plot_image_ids(image_id_list=IMAGE_ID_LIST, verbose=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# 利用id画出标记\nIMAGE_ID_LIST=['18ee9ef3baea468de2087e0edd85e919', '7eda1e28e4cee7d8016276c87b76259f']\ntrain_data.plot_str_image_ids(image_id_list=IMAGE_ID_LIST, verbose=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#######","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# 利用id画出标记\nIMAGE_ID_LIST = train_df[train_df.class_id!=14].image_id[25:29].to_list()\nIMAGE_ID_LIST=['18ee9ef3baea468de2087e0edd85e919', '7eda1e28e4cee7d8016276c87b76259f']\ntrain_data.plot_image_ids(image_id_list=IMAGE_ID_LIST, verbose=False)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<b style=\"text-decoration: underline; font-family: Verdana;\">PLOT IMAGES CONTAINING A SINGLE CLASS</b>\n\nSummary to be done later... \n\n**NOTE: Only the bounding boxes for the specified classes will be drawn... probably a TBD in the future as a possible arg**\n\n---\n\nMore detail to come later"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_data.plot_classes(class_list=[7,], n=2, verbose=False)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<b style=\"text-decoration: underline; font-family: Verdana;\">PLOT IMAGES CONTAINING ONE OR MORE CLASSES FROM A LIST</b>\n\nSummary to be done later... \n\n**NOTE: Images need not contain ALL the classes... potential future improvement or option.**\n\n---\n\nMore detail to come later"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_data.plot_classes(class_list=[5,8,11], n=4, verbose=False)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<b style=\"text-decoration: underline; font-family: Verdana;\">PLOT IMAGES ANNOTATED BY A SINGLE OR MULTIPLE RADIOLOGIST(S)</b>\n\nSummary to be done later... \n\n**NOTE: Same caveat as plotting based on class. Only bounding boxes annotated by the specified radiologist will be plotted**<br>\n**NOTE: As radiologists often annotate `No tissue`, images may not contain ANY bounding boxes**\n\n---\n\nMore detail to come later"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_data.plot_radiologists(rad_id_list=[\"R8\"], verbose=False)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<h3 style=\"text-align: font-family: Verdana; font-size: 20px; font-style: normal; font-weight: normal; text-decoration: none; text-transform: none; letter-spacing: 2px; color: navy; background-color: #ffffff;\">5.2  VISUALIZE EACH ABNORMALITY </h3>\n\n---\n\nWe will leverage our created class to visualize 4 examples of every class...\n\n\n* Aortic Enlargement <i><sub>(CLASS-ID: 0)</sub></i>\n* Atelectasis <i><sub>(CLASS-ID: 1)</sub></i>\n* Calcification <i><sub>(CLASS-ID: 2)</sub></i>\n* Cardiomegaly <i><sub>(CLASS-ID: 3)</sub></i>\n* Consolidation <i><sub>(CLASS-ID: 4)</sub></i>\n* ILD <i><sub>(CLASS-ID: 5)</sub></i>\n* Infiltration <i><sub>(CLASS-ID: 6)</sub></i>\n* Lung Opacity <i><sub>(CLASS-ID: 7)</sub></i>\n* Nodule/Mass <i><sub>(CLASS-ID: 8)</sub></i>\n* Other Lesion <i><sub>(CLASS-ID: 9)</sub></i>\n* Pleural Effusion <i><sub>(CLASS-ID: 10)</sub></i>\n* Pleural Thickening <i><sub>(CLASS-ID: 11)</sub></i>\n* Pneumothorax <i><sub>(CLASS-ID: 12)</sub></i>\n* Pulmonary Fibrosis <i><sub>(CLASS-ID: 13)</sub></i>\n* No Tissue Present <i><sub>(CLASS-ID: 14)</sub></i>"},{"metadata":{},"cell_type":"markdown","source":"<b style=\"text-decoration: underline; font-family: Verdana;\">AORTIC ENLARGMENT - (0)</b>\n\nSummary to be done later... \n\n---\n\nMore detail to come later"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_data.plot_classes(class_list=[0,], n=4, verbose=False)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<b style=\"text-decoration: underline; font-family: Verdana;\">ATELECTASIS - (1)</b>\n\nSummary to be done later... \n\n---\n\nMore detail to come later"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_data.plot_classes(class_list=[1,], n=4, verbose=False)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<b style=\"text-decoration: underline; font-family: Verdana;\">CALCIFICATION - (2)</b>\n\nSummary to be done later... \n\n---\n\nMore detail to come later"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_data.plot_classes(class_list=[2,], n=4, verbose=False)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<b style=\"text-decoration: underline; font-family: Verdana;\">CARDIOMEGALY - (3)</b>\n\nSummary to be done later... \n\n---\n\nMore detail to come later"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_data.plot_classes(class_list=[3,], n=4, verbose=False)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<b style=\"text-decoration: underline; font-family: Verdana;\">CONSOLIDATION - (4)</b>\n\nSummary to be done later... \n\n---\n\nMore detail to come later"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_data.plot_classes(class_list=[4,], n=4, verbose=False)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<b style=\"text-decoration: underline; font-family: Verdana;\">ILD - (5)</b>\n\nSummary to be done later... \n\n---\n\nMore detail to come later"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_data.plot_classes(class_list=[5,], n=4, verbose=False)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<b style=\"text-decoration: underline; font-family: Verdana;\">INFILTRATION - (6)</b>\n\nSummary to be done later... \n\n---\n\nMore detail to come later"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_data.plot_classes(class_list=[6,], n=4, verbose=False)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<b style=\"text-decoration: underline; font-family: Verdana;\">LUNG OPACITY - (7)</b>\n\nSummary to be done later... \n\n---\n\nMore detail to come later"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_data.plot_classes(class_list=[7,], n=4, verbose=False)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<b style=\"text-decoration: underline; font-family: Verdana;\">NODULE/MASS - (8)</b>\n\nSummary to be done later... \n\n---\n\nMore detail to come later"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_data.plot_classes(class_list=[8,], n=4, verbose=False)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<b style=\"text-decoration: underline; font-family: Verdana;\">OTHER LESION - (9)</b>\n\nSummary to be done later... \n\n---\n\nMore detail to come later"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_data.plot_classes(class_list=[9,], n=4, verbose=False)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<b style=\"text-decoration: underline; font-family: Verdana;\">PLEURAL EFFUSION - (10)</b>\n\nSummary to be done later... \n\n---\n\nMore detail to come later"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_data.plot_classes(class_list=[10,], n=4, verbose=False)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<b style=\"text-decoration: underline; font-family: Verdana;\">PLEURAL THICKENING - (11)</b>\n\nSummary to be done later... \n\n---\n\nMore detail to come later"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_data.plot_classes(class_list=[11,], n=4, verbose=False)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<b style=\"text-decoration: underline; font-family: Verdana;\">PNEUMOTHORAX - (12)</b>\n\nSummary to be done later... \n\n---\n\nMore detail to come later"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_data.plot_classes(class_list=[12,], n=4, verbose=False)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<b style=\"text-decoration: underline; font-family: Verdana;\">PULMONARY FIBROSIS - (13)</b>\n\nSummary to be done later... \n\n---\n\nMore detail to come later"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_data.plot_classes(class_list=[13,], n=4, verbose=False)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<b style=\"text-decoration: underline; font-family: Verdana;\">NO TISSUE - (14)</b>\n\nSummary to be done later... \n\n---\n\nMore detail to come later"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_data.plot_classes(class_list=[14,], n=4, verbose=False)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<a style=\"text-align: font-family: Verdana; font-size: 24px; font-style: normal; font-weight: bold; text-decoration: none; text-transform: none; letter-spacing: 3px; color: navy; background-color: #ffffff;\" id=\"combining_annotations\">6&nbsp;&nbsp;COMBINING/MERGING OVERLAPPING ANNOTATIONS (WIP)</a>\n\nEXPLANATION COMING SOON – NOT SURE ABOUT THE HANDELING OF NODULES AND OTHER SMALL BBOXES THAT GET ENGULFED BY LARGER SIMILAR ANNOTATIONS"},{"metadata":{},"cell_type":"markdown","source":"这里想要优化框的包含，大框包含众多小框的问题，具体没看懂"},{"metadata":{"trusted":true},"cell_type":"code","source":"def calc_iou(bbox_1, bbox_2):\n    # determine the coordinates of the intersection rectangle\n    x_left = max(bbox_1[0], bbox_2[0])\n    y_top = max(bbox_1[1], bbox_2[1])\n    x_right = min(bbox_1[2], bbox_2[2])\n    y_bottom = min(bbox_1[3], bbox_2[3])\n\n    # Check if bboxes overlap at all (if not return 0)\n    if x_right < x_left or y_bottom < y_top:\n        return 0.0\n    \n    # The intersection of two axis-aligned bounding boxes is always an\n    # axis-aligned bounding box\n    else:\n        intersection_area = (x_right - x_left) * (y_bottom - y_top)\n        \n        # compute the area of both AABBs\n        bbox_1_area = (bbox_1[2] - bbox_1[0]) * (bbox_1[3] - bbox_1[1])\n        bbox_2_area = (bbox_2[2] - bbox_2[0]) * (bbox_2[3] - bbox_2[1])\n\n        # compute the intersection over union by taking the intersection\n        # area and dividing it by the sum of prediction + ground-truth\n        # areas - the interesection area\n        iou = intersection_area / float(bbox_1_area + bbox_2_area - intersection_area)\n        return iou\n\ndef redux_bboxes(annots):\n    def _get_inner_box(bboxes):\n        xmin = max([box[0] for box in bboxes])\n        ymin = max([box[1] for box in bboxes])\n        xmax = min([box[2] for box in bboxes])\n        ymax = min([box[3] for box in bboxes])\n        if (xmax<=xmin) or (ymax<=ymin):\n            return None\n        else:\n            return [xmin, ymin, xmax, ymax]\n        \n    valid_list_indices = [] \n    new_bboxes = []\n    new_class_ids = []\n    new_rad_ids = []\n    \n    for i, (class_id, rad_id, bbox) in enumerate(zip(annots[\"class_id\"], annots[\"rad_id\"], annots[\"bbox\"])):\n        intersecting_boxes = [bbox,]\n        other_bboxes = [x for j,x in enumerate(annots[\"bbox\"]) if j!=i]\n        other_classes = [x for j,x in enumerate(annots[\"class_id\"]) if j!=i]\n        for j, (other_class_id, other_bbox) in enumerate(zip(other_classes, other_bboxes)):\n            if class_id==other_class_id:\n                iou = calc_iou(bbox, other_bbox)\n                if iou>0.:\n                    intersecting_boxes.append(other_bbox)\n\n        if len(intersecting_boxes)>1:\n            inner_box = _get_inner_box(intersecting_boxes)\n            if inner_box and inner_box not in new_bboxes:\n                new_bboxes.append(inner_box)\n                new_class_ids.append(class_id)\n                new_rad_ids.append(rad_id) \n\n    annots[\"bbox\"] = new_bboxes\n    annots[\"rad_id\"] = new_rad_ids\n    annots[\"class_id\"] = new_class_ids\n    \n    return annots\n\n# Make GT Dataframe\ngt_df = train_df[train_df.class_id!=14]\n\n# Apply Manipulations and Merger Functions\ngt_df[\"bbox\"] = gt_df.loc[:, [\"x_min\",\"y_min\",\"x_max\",\"y_max\"]].values.tolist()\ngt_df.drop(columns=[\"x_min\",\"y_min\",\"x_max\",\"y_max\"], inplace=True)\ngt_df = gt_df.groupby([\"image_id\"]).agg({k:list for k in gt_df.columns if k !=\"image_id\"}).reset_index()\ngt_df = gt_df.apply(redux_bboxes, axis=1)\n\n# Recreate the Original Dataframe Style\ngt_df = gt_df.apply(pd.Series.explode).reset_index(drop=True).dropna()\ngt_df[\"x_min\"] = gt_df[\"bbox\"].apply(lambda x: x[0])\ngt_df[\"y_min\"] = gt_df[\"bbox\"].apply(lambda x: x[1])\ngt_df[\"x_max\"] = gt_df[\"bbox\"].apply(lambda x: x[2])\ngt_df[\"y_max\"] = gt_df[\"bbox\"].apply(lambda x: x[3])\ngt_df.drop(columns=[\"bbox\"], inplace=True)\n\n# Add back in NaN Rows As A Single Annotation\ngt_df = pd.concat([\n    gt_df, train_df.loc[train_df['class_id'] == 14].drop_duplicates(subset=[\"image_id\"])\n]).reset_index(drop=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"gt_data = TrainData(gt_df, TRAIN_DIR)\nIMAGE_ID_LIST = gt_df[gt_df.class_id!=14].groupby(\"image_id\") \\\n                                         .count() \\\n                                         .sort_values(by=\"class_id\", ascending=False) \\\n                                         .index[0:100:20]\n\nfor i, IMAGE_ID in enumerate(IMAGE_ID_LIST):\n    train_data.get_annotated_image(IMAGE_ID, annots=None, plot=True, plot_size=(18,22), plot_title=f\"ORIGINAL – IMG #{i+1}\")\n    gt_data.get_annotated_image(IMAGE_ID, annots=None, plot=True, plot_size=(18,22), plot_title=f\"REDUX VERSION – IMG #{i+1}\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"gt_data = TrainData(gt_df, TRAIN_DIR)\nIMAGE_ID_LIST = gt_df[gt_df.class_id!=14].groupby(\"image_id\") \\\n                                         .count() \\\n                                         .sort_values(by=\"class_id\", ascending=False) \\\n                                         .index[0:100:20]\n\nfor i, IMAGE_ID in enumerate(IMAGE_ID_LIST):\n    train_data.get_annotated_image(IMAGE_ID, annots=None, plot=True, plot_size=(18,22), plot_title=f\"ORIGINAL – IMG #{i+1}\")\n    gt_data.get_annotated_image(IMAGE_ID, annots=None, plot=True, plot_size=(18,22), plot_title=f\"REDUX VERSION – IMG #{i+1}\")","execution_count":null,"outputs":[]}],"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":4,"nbformat_minor":4}