{"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":"I use 4 sets of mammography datasets, including: `RSNA`, `mini-ddsm`, `mias`, `inbreast`.\n\nI ROI crop by image segmentation and yolov8 model.\n\nmodel yolov8: https://colab.research.google.com/drive/1WFSiMeTixqm4anSMNUY_FdzK8TdHB_W5?usp=sharing","metadata":{}},{"cell_type":"code","source":"!pip install ultralytics\n!pip install xlrd\n!pip install /kaggle/input/rsnawhl/{pydicom-2.3.0-py3-none-any.whl,pylibjpeg-1.4.0-py3-none-any.whl,python_gdcm-3.0.15-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl}","metadata":{"execution":{"iopub.status.busy":"2023-04-08T10:56:00.341696Z","iopub.execute_input":"2023-04-08T10:56:00.342094Z","iopub.status.idle":"2023-04-08T10:56:26.04266Z","shell.execute_reply.started":"2023-04-08T10:56:00.342062Z","shell.execute_reply":"2023-04-08T10:56:26.041486Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# import libraries\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport plotly.express as px\nfrom glob import glob\nimport cv2\nimport pydicom\nfrom pydicom.pixel_data_handlers.util import apply_voi_lut, apply_windowing\nfrom tqdm.notebook import tqdm\nimport time\nfrom datetime import datetime\nfrom IPython import display\nimport os\nimport torch\nfrom ultralytics import YOLO\nimport multiprocessing as mp\nimport warnings\nwarnings.filterwarnings('ignore')\n\n\n%matplotlib inline\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\ncores = mp.cpu_count()\n\nplt.rcParams.update({'font.size': 10})\nplt.rcParams['figure.figsize'] = (8, 6)\n\nprint('Cores:', cores)\nprint('Device:', device)\nprint('Day: ', datetime.now())","metadata":{"execution":{"iopub.status.busy":"2023-04-08T10:56:26.044255Z","iopub.execute_input":"2023-04-08T10:56:26.044557Z","iopub.status.idle":"2023-04-08T10:56:26.057206Z","shell.execute_reply.started":"2023-04-08T10:56:26.044529Z","shell.execute_reply":"2023-04-08T10:56:26.056253Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# EDA rsna","metadata":{}},{"cell_type":"code","source":"%cd '/kaggle'\n%pwd","metadata":{"execution":{"iopub.status.busy":"2023-04-08T10:56:26.058397Z","iopub.execute_input":"2023-04-08T10:56:26.058658Z","iopub.status.idle":"2023-04-08T10:56:26.075175Z","shell.execute_reply.started":"2023-04-08T10:56:26.058635Z","shell.execute_reply":"2023-04-08T10:56:26.074198Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"input_path = \"input/rsna-breast-cancer-detection/\"\n# df_samp = pd.read_csv(input_path+'sample_submission.csv')\ndf_train = pd.read_csv(input_path+'train.csv')\ndf_test = pd.read_csv(input_path+'test.csv')","metadata":{"execution":{"iopub.status.busy":"2023-04-08T10:56:26.078355Z","iopub.execute_input":"2023-04-08T10:56:26.078657Z","iopub.status.idle":"2023-04-08T10:56:26.132329Z","shell.execute_reply.started":"2023-04-08T10:56:26.078632Z","shell.execute_reply":"2023-04-08T10:56:26.131482Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"count_cancer=df_train.groupby(by=\"cancer\").count()[\"patient_id\"]\nfig = px.pie(values = count_cancer.values, names = count_cancer.index)\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2023-04-08T10:56:26.133477Z","iopub.execute_input":"2023-04-08T10:56:26.1337Z","iopub.status.idle":"2023-04-08T10:56:26.194199Z","shell.execute_reply.started":"2023-04-08T10:56:26.13367Z","shell.execute_reply":"2023-04-08T10:56:26.193225Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"> Data cancer and normal are imbalance","metadata":{}},{"cell_type":"markdown","source":"# all dataset","metadata":{}},{"cell_type":"code","source":"# Custom colors\nclass clr:\n    S = '\\033[1m' + '\\033[91m'\n    E = '\\033[0m'","metadata":{"execution":{"iopub.status.busy":"2023-04-08T10:56:26.196159Z","iopub.execute_input":"2023-04-08T10:56:26.196626Z","iopub.status.idle":"2023-04-08T10:56:26.202369Z","shell.execute_reply.started":"2023-04-08T10:56:26.196585Z","shell.execute_reply":"2023-04-08T10:56:26.200886Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_df(name_dataset):\n    df = None\n    if name_dataset == \"RSNA\":\n        df = pd.read_csv(f\"input/rsna-breast-cancer-detection/train.csv\")\n        df.columns = df.columns.str.capitalize()\n        df['Path'] = df[['Patient_id', 'Image_id']].apply(lambda x: '/kaggle/input/rsna-breast-cancer-detection/train_images/'+\\\n                                    str(x['Patient_id']) + \"/\" + str(x['Image_id']) + \".dcm\", axis=1)\n        for i in tqdm(range(len(df)), desc=\"Loading RSNA dataset\"):\n            i + 1\n\n    elif name_dataset == \"DDSM\":\n        is_cancer = {'Benign': 1, 'Cancer': 1, 'Normal': 0}\n        data = {'Filename': [], 'Age':[], 'Density': [], 'Cancer':[], 'View': [], 'Laterality': [], 'Path': []}\n        # extract the path and view\n        paths = glob(f\"input/miniddsm2/MINI-DDSM-Complete-PNG-16/*/*\")\n        for head in tqdm(paths, desc=\"Loading MINI-DDSM dataset\"):\n            path = glob(f\"{head}/*\")\n            path_ics = [x for x in path if \"ics\" in x][0]\n            path_img = [x for x in path if (\"png\" in x and 'Mask' not in x)]\n            if len(path_img) >= 1:\n                # get information from file *.png\n                for txt in path_img:\n                    view = txt.split('.')[-2].split('_')[1]\n                    laterality = txt.split('.')[-2].split('_')[0]\n                    data['View'].append(view)\n                    data['Laterality'].append('L' if laterality=='LEFT' else 'R')\n                    data['Path'].append(txt)\n                    data['Cancer'].append(is_cancer[head.split('/')[-2]])\n\n                    # get information from file *.ics\n                    f = open(path_ics, \"r\")\n                    ics_text = f.read().strip().split(\"\\n\")\n                    for txt in ics_text:\n                        if txt.split()[0].upper() == 'FILENAME':\n                            data['Filename'].append(txt.split()[1] if len(txt.split()) > 1 else 'NaN')\n                        if txt.split()[0].upper() == 'PATIENT_AGE':\n                            data['Age'].append(txt.split()[1] if len(txt.split()) > 1 else 'NaN')\n                        if txt.split()[0].upper() == 'DENSITY':\n                            data['Density'].append(txt.split()[1] if len(txt.split()) > 1 else 'NaN')\n        df = pd.DataFrame(data)\n\n    elif name_dataset == \"MIAS\":\n        df = pd.read_csv(f'input/mias-mammography/Info.txt', sep=\" \").drop('Unnamed: 7',axis=1)\n        df.columns = df.columns.str.capitalize()\n        df['Path'] = df['Refnum'].apply(lambda x: '/kaggle/input/mias-mammography' + \"/\" + \"all-mias\" + \"/\" + x + \".pgm\")\n        df['Cancer'] = df['Class'].apply(lambda x: 0 if x.upper() == 'NORM' else 1)\n        for i in tqdm(range(len(df)), desc=\"Loading MIAS dataset\"):\n            i+1\n    elif name_dataset == \"INBREAST\":\n        df = pd.read_excel(f'input/inbreast-2023/INbreast.xls', skipfooter=2)\n        df.columns = df.columns.str.capitalize()\n        paths = glob(f\"input/inbreast-2023/ALL-IMGS/*.dcm\")\n        df['Path'] = df['File name'].apply(lambda x: [path for path in paths if path.split('/')[-1].split('_')[0] == str(x)][0])\n        df['Lesion annotation status'].fillna('cancer', inplace=True)\n        df['Lesion annotation status'] = df['Lesion annotation status'].str.upper()\n        df['Cancer'] = df['Lesion annotation status'].apply(lambda x: 0 if x == 'NO ANNOTATION (NORMAL)' else 1)\n        for i in tqdm(range(len(df)), desc=\"Loading INBREAST dataset\"):\n            i+1\n    else:\n        print(\"Dataset not found\")\n    return df\n\ndata_breast = [\"RSNA\", \"DDSM\", \"MIAS\", 'INBREAST']\nrsna = get_df(data_breast[0])[['Path', 'Cancer', 'View', 'Laterality']]\nddsm = get_df(data_breast[1])[['Path', 'Cancer', 'View', 'Laterality']]\nmias = get_df(data_breast[2])[['Path', 'Cancer']]\ninbreast = get_df(data_breast[3])[['Path', 'Cancer', 'View', 'Laterality']]","metadata":{"execution":{"iopub.status.busy":"2023-04-08T10:56:26.20413Z","iopub.execute_input":"2023-04-08T10:56:26.204587Z","iopub.status.idle":"2023-04-08T10:56:32.7591Z","shell.execute_reply.started":"2023-04-08T10:56:26.20455Z","shell.execute_reply":"2023-04-08T10:56:32.757751Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"total_cancer = {'RSNA': rsna['Cancer'].value_counts(), 'MINI-DDSM': ddsm['Cancer'].value_counts(), 'MIAS': mias['Cancer'].value_counts(), 'INBREAST': inbreast['Cancer'].value_counts()}\nframe_cancer = pd.DataFrame(total_cancer).T\n\n# total data for each dataset\ndataset_sum = frame_cancer.sum(axis=1)\nfor name_dataset, total in dataset_sum.to_dict().items():\n    print(f'- {name_dataset}: {clr.S}{total}{clr.E}')\n\nplt.pie(dataset_sum, labels=dataset_sum.index, autopct='%1.1f%%', startangle=90)\nplt.title(\"Percent dataset\")\nplt.legend()\nplt.show()\n\ncancer_sum = frame_cancer.sum(axis=0)\nplt.pie(cancer_sum, labels=cancer_sum.index, autopct='%1.1f%%', startangle=90)\nplt.title(\"Percent cancer and non-cancer\")\nplt.legend(['non-cancer', 'cancer'])\nplt.show()\n\nframe_cancer.reset_index(inplace=True)\nframe_cancer.rename(columns={'index': 'dataset', 1: 'cancer', 0: 'non-cancer'}, inplace=True)\n# plot double bar chart \nx = np.arange(len(frame_cancer.dataset))\nw = 0.4\nplt.bar(x, frame_cancer.cancer, label='cancer', width=w)\nplt.bar(x+w, frame_cancer['non-cancer'], label='non-cancer', width=w)\nplt.xticks(x+w/2, frame_cancer.dataset)\n\nplt.title(\"Number of cancer and non-cancer\")\nplt.legend()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-04-08T10:56:32.761108Z","iopub.execute_input":"2023-04-08T10:56:32.761504Z","iopub.status.idle":"2023-04-08T10:56:33.269665Z","shell.execute_reply.started":"2023-04-08T10:56:32.761474Z","shell.execute_reply":"2023-04-08T10:56:33.268723Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# ROI crop with process basic","metadata":{}},{"cell_type":"code","source":"class Process_Image():\n    def __init__(self, df, head = 'train_images'):\n        self.df = df\n        self.path = None\n        self.head = head\n    \n    def set_path(self, src):\n        if isinstance(src, int):\n            desc = self.df.iloc[src]\n            src = input_path+self.head+\"/\"+str(desc.patient_id)+\"/\"+str(desc.image_id)+\".dcm\"\n        self.path = src\n        \n    def get_target(self):\n        x = self.path.split(\"/\")[-2:] #'input/rsna-breast-cancer-detection/train_images/10589/195400299.dcm'\n        pat_id = x[0]\n        img_id = x[1][:-4]\n        target = self.df.loc[(self.df.patient_id==int(pat_id)) & (self.df.image_id==int(img_id))].cancer.values\n        return target[0]\n    \n    def load_image(self, img_path, voi_lut=False, noInterpretation=False):\n        dataset = pydicom.dcmread(img_path)\n        img = dataset.pixel_array\n        if voi_lut:\n            img = apply_voi_lut(img, dataset)\n        if noInterpretation:\n            return img\n        if dataset.PhotometricInterpretation == \"MONOCHROME1\":\n            img = np.amax(img) - img\n        return img\n\n    def cvtRGB_image(self, img):\n        img = img-np.amin(img)\n        img = (img/np.amax(img))*255\n        return img\n\n    def crop_image(self, img):\n        # threshold image\n        threshold = ((img > np.mean(img))*255).astype(np.uint8)\n        # bounding box\n        contours, hierarchy = cv2.findContours(threshold, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)\n        c = max(contours, key = cv2.contourArea)\n        x,y,w,h = cv2.boundingRect(c)\n        # crop\n        return img[y:y+h, x:x+w]\n    \n    def process(self, src, voi_lut = True, aug = 'clahe,2,8', sz_size=(512, 512)):\n        self.set_path(src)\n        img = self.load_image(self.path, voi_lut=voi_lut)\n        img = self.cvtRGB_image(img)\n        img = self.crop_image(img)\n        if aug[:5]=='clahe':\n            x = aug.split(',')\n            clm = float(x[1])\n            tgs = int(x[2])\n            clahe = cv2.createCLAHE(clipLimit=clm, tileGridSize=(tgs, tgs))\n            img = clahe.apply(img.astype('uint8'))\n        img = cv2.resize(img, sz_size)\n        return img\n        \n    def __show__(self, cm='gray', voi_lut = True, aug='clahe,2,8'):\n        fig, ax = plt.subplots(1, 2)\n        origin_img = self.load_image(self.path, noInterpretation = True)\n        start = time.time()\n        processed = self.process(self.path, voi_lut, aug)\n        end = time.time()\n        target = {0:'no-cancer', 1:'cancer'}\n        fig.suptitle(\"Path: \"+self.path.split(\"/\", 2)[-1]+\"\\n\"+f\"Time processed: {end-start}\"+\"\\n\"+f\"Target: {target[self.get_target()]}\")\n        ax[0].imshow(origin_img, cmap=cm)\n        ax[0].set_title(f'origin, shape: {origin_img.shape}')\n        ax[0].axis('off')\n        ax[1].imshow(processed, cmap=cm)\n        ax[1].set_title(f'processed, shape: {processed.shape}')\n        ax[1].axis('off')\n        fig.tight_layout()\n        plt.show()","metadata":{"execution":{"iopub.status.busy":"2023-04-08T10:56:33.270972Z","iopub.execute_input":"2023-04-08T10:56:33.272232Z","iopub.status.idle":"2023-04-08T10:56:33.293455Z","shell.execute_reply.started":"2023-04-08T10:56:33.272195Z","shell.execute_reply":"2023-04-08T10:56:33.29262Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pI = Process_Image(df_train, head='train_images')\npI.set_path(4)\npI.__show__()","metadata":{"execution":{"iopub.status.busy":"2023-04-08T10:56:33.297023Z","iopub.execute_input":"2023-04-08T10:56:33.29765Z","iopub.status.idle":"2023-04-08T10:56:34.502712Z","shell.execute_reply.started":"2023-04-08T10:56:33.297611Z","shell.execute_reply":"2023-04-08T10:56:34.501855Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cancer = df_train.loc[df_train.cancer==1][10:15]\nno_cancer = df_train.loc[df_train.cancer==0][10:15]\ntest = pd.concat([cancer, no_cancer])","metadata":{"execution":{"iopub.status.busy":"2023-04-08T10:56:34.503969Z","iopub.execute_input":"2023-04-08T10:56:34.504591Z","iopub.status.idle":"2023-04-08T10:56:34.519476Z","shell.execute_reply.started":"2023-04-08T10:56:34.504535Z","shell.execute_reply":"2023-04-08T10:56:34.518511Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# ROI crop with yolo","metadata":{}},{"cell_type":"code","source":"yolo_model = YOLO(\"/kaggle/input/checkpoint-yolov8l/best.pt\")","metadata":{"execution":{"iopub.status.busy":"2023-04-08T11:23:05.702856Z","iopub.execute_input":"2023-04-08T11:23:05.703213Z","iopub.status.idle":"2023-04-08T11:23:07.155962Z","shell.execute_reply.started":"2023-04-08T11:23:05.703184Z","shell.execute_reply":"2023-04-08T11:23:07.154653Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class extract_ROI():\n    def __init__(self, df):\n        self.df = df\n        self.detect_model = yolo_model\n        self.folder = None\n        self.df_loc = None\n        self.count_access = 0\n        self.count_error = 0\n\n    def __len__(self):\n        return len(self.df)\n\n    def load_image(self, idx=0):\n        '''\n        Method to load the image\n        Parameter:\n            - path (int or str): index or path of the image\n        Return (numpy.ndarray): image 8-bit 3-channel\n        '''\n        path = idx\n        if isinstance(idx, int):\n            self.df_loc = self.df.iloc[idx]\n            path = self.df_loc.Path\n            \n        else:\n            self.df_loc = self.df[self.df['Path']==idx]\n        mode = path.split('.')[-1]\n        img = None\n        if mode == 'dcm':\n            ds = pydicom.dcmread(path)\n            img2d = ds.pixel_array\n            # apply voi_lut\n            voi_lut = apply_voi_lut(img2d, ds)\n            if np.sum(voi_lut) > 0:\n                img2d = voi_lut\n            # min-max scale\n            img2d = (img2d - img2d.min()) / (img2d.max() - img2d.min())\n            # convert to uint8\n            img2d = (img2d * 255).astype(np.uint8)\n            # convert to float to avoid overflow or underflow losses.\n            if ds.PhotometricInterpretation == 'MONOCHROME1':\n                img2d = np.invert(img2d)\n            # convert to 3-channel\n            img = cv2.cvtColor(img2d, cv2.COLOR_GRAY2BGR)\n        else:\n            img = cv2.imread(path)\n        return img\n    \n    \n    def crop(self, img):\n        results = self.detect_model(img)\n        boxes = results[0].boxes\n        box = boxes[0]\n        xy = box.xyxy\n        x1 = int(xy[0][0].item())\n        y1 = int(xy[0][1].item())\n        x2 = int(xy[0][2].item())\n        y2 = int(xy[0][3].item())\n        img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\n        img = img[y1: y2, x1:x2]\n        return img\n\n    def plot_image(self, idx=0):\n        img = self.load_image(idx)\n        # convert to grayscale\n        img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\n        # plot\n        fig, ax = plt.subplots(1, 1)\n        fig.suptitle(f\"Path: {self.df_loc.Path}\")\n        ax.imshow(img, cmap=plt.cm.gray)\n        ax.set_title(f'Image, shape: {img.shape}')\n        ax.axis('off')\n        fig.tight_layout()\n        plt.show()\n\n    def plot(self, idx=0):\n        img = self.load_image(idx)\n        cropped = self.crop(img)\n        # convert to grayscale\n        img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\n        # plot\n        fig, ax = plt.subplots(1, 2)\n        fig.suptitle(f\"Path: {self.df_loc.Path}\")\n        ax[0].imshow(img, cmap=plt.cm.gray)\n        ax[0].set_title(f'Image, shape: {img.shape}')\n        ax[0].axis('off')\n        ax[1].imshow(cropped, cmap=plt.cm.gray)\n        ax[1].set_title(f'Cropped, shape: {cropped.shape}')\n        ax[1].axis('off')\n        fig.tight_layout()\n        plt.show()\n        \n    def plot_sample(self, resize=256):\n        '''\n        Method to plot a sample of the images\n        Parameter:\n            - cropped (bool): True is origin image, False is cropped image\n            - resize (int): resize the image\n        '''\n        imgs = []\n        df_sample = self.df.sample(100, random_state=42)\n        for path in tqdm(df_sample.Path.values):\n            print(path)\n            img = self.load_image(path)\n            cropped = self.crop(img)\n            display.clear_output(wait=True)\n            imgs.append(cropped)\n        if resize:\n            imgs = [cv2.resize(img, (resize, resize)) for img in imgs]\n        # plot\n        n_cols = 10\n        n_rows = 10\n        fig, ax = plt.subplots(n_rows, n_cols, figsize=(n_cols*5,n_rows*5))\n        i = 0\n        for r in tqdm(range(0,n_rows)):\n            for c in range(0,n_cols):\n                idx = r*n_cols + c\n                ax_idx = ax[r,c]\n                ax_idx.imshow(imgs[i],cmap=plt.cm.gray)\n                i+=1\n                ax_idx.axis('off')\n        plt.tight_layout()\n        plt.show()\n\n#         fig, ax = plt.subplots(n_rows, n_cols, figsize=(n_cols*5,n_rows*5))\n#         i = 0\n#         for r in tqdm(range(0,n_rows)):\n#             for c in range(0,n_cols):\n#                 idx = r*n_cols + c\n#                 ax_idx = ax[r,c]\n#                 ax_idx.imshow(imgs[i],cmap=plt.cm.gray)\n#                 i+=1\n#                 ax_idx.axis('off')\n#         plt.tight_layout()\n#         plt.show()\n\n#     def init_folder_save(self, folder_struc):\n#         self.folder = folder_struc[0]\n#         for path in folder_struc:\n#             os.makedirs(f'{path}', exist_ok=True)\n#         print(\"--- Created folder structure successfully!\")\n#         df_save = self.df.copy()\n#         df_save['Path'] = df_save['Path'].apply(lambda x: x.split('\\\\')[-1][:-3]+'png')\n#         df_save.to_csv(f'{self.folder}/description.csv', index=False)\n#         print('--- Saved description.csv successfully!')\n        \n\n#     def save_image(self, idx):\n#         img = self.load_image(idx)\n#         label_dict = {1:'Cancer', 0:'Normal'}\n#         try:\n#             crop = self.crop(img)\n#             # resize\n#             percent = 1280 / max(crop.shape)\n#             crop = cv2.resize(crop, (int(crop.shape[1]*percent), int(crop.shape[0]*percent)))\n#             # save\n#             path_save = f'RSNA-ROI-Mammography\\\\{label_dict[self.df_loc.Cancer]}\\\\{self.df_loc.Path_save}'\n#             cv2.imwrite(path_save, crop)\n#             self.count_access += 1\n#         except:\n#             # path_save = f'{self.folder}\\\\No_detect\\\\{self.df_loc.Path_save}'\n#             path_save = f'RSNA-ROI-Mammography\\\\No_detect\\\\{self.df_loc.Path_save}'\n#             cv2.imwrite(path_save, img)\n#             self.count_error += 1\n        \n#         display.clear_output(wait=True)\n    \n#     def save_all(self):\n#         for i in tqdm(range(self.__len__()), desc=\"Extracting ROI\"):\n#             self.save_image(i)\n#             print(f'--- Saved: {self.count_access+self.count_error}/{self.__len__()}')\n#             print(f'--- Detected: {self.count_access}')\n#             print(f'--- No detected: {self.count_error}')","metadata":{"execution":{"iopub.status.busy":"2023-04-08T11:29:20.903509Z","iopub.execute_input":"2023-04-08T11:29:20.903887Z","iopub.status.idle":"2023-04-08T11:29:20.928076Z","shell.execute_reply.started":"2023-04-08T11:29:20.903855Z","shell.execute_reply":"2023-04-08T11:29:20.927227Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"roi = extract_ROI(rsna)\nprint(roi.__len__())\nroi.df.head()","metadata":{"execution":{"iopub.status.busy":"2023-04-08T11:29:21.096798Z","iopub.execute_input":"2023-04-08T11:29:21.097375Z","iopub.status.idle":"2023-04-08T11:29:21.110482Z","shell.execute_reply.started":"2023-04-08T11:29:21.097337Z","shell.execute_reply":"2023-04-08T11:29:21.109757Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"execution":{"iopub.status.busy":"2023-04-08T11:29:37.800187Z","iopub.execute_input":"2023-04-08T11:29:37.80058Z","iopub.status.idle":"2023-04-08T11:29:41.711587Z","shell.execute_reply.started":"2023-04-08T11:29:37.800551Z","shell.execute_reply":"2023-04-08T11:29:41.710253Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for i in range (10):\n    roi.plot(i)","metadata":{"execution":{"iopub.status.busy":"2023-04-08T11:30:19.604178Z","iopub.execute_input":"2023-04-08T11:30:19.604561Z","iopub.status.idle":"2023-04-08T11:30:48.762143Z","shell.execute_reply.started":"2023-04-08T11:30:19.604531Z","shell.execute_reply":"2023-04-08T11:30:48.761465Z"},"trusted":true},"execution_count":null,"outputs":[]}]}