{"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":"\n","metadata":{}},{"cell_type":"markdown","source":"* This note book is designed to perform some exploratory data analysis and to convert the images in dicom format into Png fromat using thrid party python libraries named dicomsdl","metadata":{}},{"cell_type":"markdown","source":"\n# <span style=\"color:teal\">1. Install Libraries <a class=\"anchor\"  id=\"Libraries\"></a></span>","metadata":{}},{"cell_type":"markdown","source":"## <span style=\"color:teal\">1.1 dicomsdl is a third-party python library that we used to convert dicom images into png <a class=\"anchor\"  id=\"dicomsdl\"></a></span>","metadata":{}},{"cell_type":"code","source":"from IPython.display import clear_output\n!pip -q install dicomsdl\n!pip install pylibjpeg\n!pip install python-gdcm\n!pip install plotly==5.11.0\nclear_output()","metadata":{"execution":{"iopub.status.busy":"2023-05-04T20:36:15.441178Z","iopub.execute_input":"2023-05-04T20:36:15.441605Z","iopub.status.idle":"2023-05-04T20:37:34.392262Z","shell.execute_reply.started":"2023-05-04T20:36:15.441569Z","shell.execute_reply":"2023-05-04T20:37:34.390705Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## <span style=\"color:teal\">1.2 Imporing pre installed libraries <a class=\"anchor\"  id=\"additionalLibraries\"></a></span>","metadata":{}},{"cell_type":"code","source":"import os, random, cv2, dicomsdl\nimport numpy as np\nimport pandas as pd\nfrom pandas_profiling import ProfileReport\n\nfrom tqdm import tqdm\nfrom joblib import Parallel, delayed\nfrom matplotlib import pyplot as plt\nfrom mpl_toolkits.axes_grid1 import ImageGrid\n\nfrom collections import Counter\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport plotly.express as px\nfrom mpl_toolkits.axes_grid1 import ImageGrid\nimport pydicom\nimport pylibjpeg\nfrom pathlib import Path\nsns.set_style(\"darkgrid\")","metadata":{"_kg_hide-input":true,"scrolled":true,"execution":{"iopub.status.busy":"2023-05-04T20:37:34.394792Z","iopub.execute_input":"2023-05-04T20:37:34.39516Z","iopub.status.idle":"2023-05-04T20:37:39.699293Z","shell.execute_reply.started":"2023-05-04T20:37:34.395113Z","shell.execute_reply":"2023-05-04T20:37:39.697887Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# <span style=\"color:teal\"> 2. Create basic configuration class <a class=\"anchor\"  id=\"configuration\"></a></span>\n * Configuration class consisting of information about project","metadata":{}},{"cell_type":"code","source":"class Config:\n    def __init__(self):\n\n        self.path = '/kaggle/input/rsna-breast-cancer-detection/'\n        self.train_path = self.path + 'train_images/'\n        self.test_path = self.path + 'test_images/'\n        self.train_csv = self.path + 'train.csv'\n        self.test_csv = self.path + 'test.csv'\n        self.sample_submission = self.path + 'sample_submission.csv'\n        \n        self.output_path = '/kaggle/working/'\n        self.train_output_path = self.output_path + 'train_images/'\n        self.test_output_path = self.output_path + 'test_images/'\n\n        self.img_size =1024\n        self.resize_dim = (1024,512)\n\nconfig = Config()","metadata":{"execution":{"iopub.status.busy":"2023-05-04T20:37:39.700764Z","iopub.execute_input":"2023-05-04T20:37:39.701121Z","iopub.status.idle":"2023-05-04T20:37:39.709546Z","shell.execute_reply.started":"2023-05-04T20:37:39.701084Z","shell.execute_reply":"2023-05-04T20:37:39.70818Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# <span style=\"color:teal\"> 3. Exploratory Data Analysis  <a class=\"anchor\"  id=\"trainingdatainfo\"></a></span>","metadata":{}},{"cell_type":"markdown","source":"## <span style=\"color:teal\"> 3.1 Training dataframe info  <a class=\"anchor\"  id=\"trainingdatainfo\"></a></span>","metadata":{}},{"cell_type":"code","source":"train_df = pd.read_csv(config.train_csv)\ntrain_df.describe()","metadata":{"execution":{"iopub.status.busy":"2023-05-04T20:37:39.71237Z","iopub.execute_input":"2023-05-04T20:37:39.71274Z","iopub.status.idle":"2023-05-04T20:37:39.921406Z","shell.execute_reply.started":"2023-05-04T20:37:39.712705Z","shell.execute_reply":"2023-05-04T20:37:39.919974Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.shape","metadata":{"execution":{"iopub.status.busy":"2023-05-04T20:37:39.922779Z","iopub.execute_input":"2023-05-04T20:37:39.923124Z","iopub.status.idle":"2023-05-04T20:37:39.931099Z","shell.execute_reply.started":"2023-05-04T20:37:39.923091Z","shell.execute_reply":"2023-05-04T20:37:39.929857Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.head()","metadata":{"execution":{"iopub.status.busy":"2023-05-04T20:37:39.932997Z","iopub.execute_input":"2023-05-04T20:37:39.933364Z","iopub.status.idle":"2023-05-04T20:37:39.955596Z","shell.execute_reply.started":"2023-05-04T20:37:39.933329Z","shell.execute_reply":"2023-05-04T20:37:39.954279Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.info()","metadata":{"execution":{"iopub.status.busy":"2023-05-04T20:37:39.95765Z","iopub.execute_input":"2023-05-04T20:37:39.958469Z","iopub.status.idle":"2023-05-04T20:37:39.987818Z","shell.execute_reply.started":"2023-05-04T20:37:39.958425Z","shell.execute_reply":"2023-05-04T20:37:39.986507Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### <span style=\"color:teal\"> Profiling Report  <a class=\"anchor\"  id=\"profile\"></a></span>\n * Pandas Profiling is a powerful library to access all the exploratory information about the data**","metadata":{}},{"cell_type":"code","source":"profile=ProfileReport(train_df,title=\"RSNA Train data profiling\", explorative=True)\nprofile.to_notebook_iframe()","metadata":{"execution":{"iopub.status.busy":"2023-05-04T20:37:39.989619Z","iopub.execute_input":"2023-05-04T20:37:39.990126Z","iopub.status.idle":"2023-05-04T20:37:59.488315Z","shell.execute_reply.started":"2023-05-04T20:37:39.99009Z","shell.execute_reply":"2023-05-04T20:37:59.486482Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"---\n#### <span style=\"color:teal\"> Early Observations  <a class=\"anchor\"  id=\"profile1\"></a></span>\n\n- **image_id** is the unique key present in the training data\n- The training data has observations for **54,706** images (no duplicates present)\n- This information is for **11,913** patients\n- The training data has observations from two sites\n- Images are of 6 views. However, **MLO** and **CC **views account for >99% images\n- **age** ranges from 26 years to 89 years. For 0.1% (37) images Age is missing\n- **cancer**, the dependent or target variable has a rate of 2.1% amongst 54,706 images\n- 5.4% of the images warranted a biopsy\n- 1.5% of the images showed an invasive cancer. For all positive cancer images 70.6% showed invasive cancer\n- **BIRADS** information is missing for a majority of images\n- Less than 2.7% images were done on breasts with implants\n- A large proportion of density information is missing\n- 10 different machines were used across the two sites\n- 15% of all image scans were difficult to infer as negative for cancer\n---","metadata":{}},{"cell_type":"markdown","source":"### <span style=\"color:teal\"> Patient Level Profiles  <a class=\"anchor\"  id=\"profile2\"></a></span>\n","metadata":{}},{"cell_type":"code","source":"total_patients=train_df['patient_id'].nunique()\nunique_cancer_patients=np.where(train_df.groupby(['patient_id'])['cancer'].sum().reset_index()['cancer']>0,1,0).sum()\nprint(\"\\nThe total number of patients diagnosed with cancer is \" + str(unique_cancer_patients))\nprint(\"This indicates a prevalence rate of \" + str(round(unique_cancer_patients/total_patients*100,2)) + \"%\" + \" in \" + str(total_patients)+\" patients.\")","metadata":{"execution":{"iopub.status.busy":"2023-05-04T20:39:36.806061Z","iopub.execute_input":"2023-05-04T20:39:36.806578Z","iopub.status.idle":"2023-05-04T20:39:36.822063Z","shell.execute_reply.started":"2023-05-04T20:39:36.806531Z","shell.execute_reply":"2023-05-04T20:39:36.820453Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## <span style=\"color:teal\"> 3.2 Testing dataframe info  <a class=\"anchor\"  id=\"test\"></a></span>","metadata":{}},{"cell_type":"code","source":"test_df = pd.read_csv(config.test_csv)\ntest_df.head()","metadata":{"execution":{"iopub.status.busy":"2023-05-04T20:39:41.409913Z","iopub.execute_input":"2023-05-04T20:39:41.410345Z","iopub.status.idle":"2023-05-04T20:39:41.432773Z","shell.execute_reply.started":"2023-05-04T20:39:41.410306Z","shell.execute_reply":"2023-05-04T20:39:41.431501Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df.shape","metadata":{"execution":{"iopub.status.busy":"2023-05-04T20:39:44.512932Z","iopub.execute_input":"2023-05-04T20:39:44.513399Z","iopub.status.idle":"2023-05-04T20:39:44.521465Z","shell.execute_reply.started":"2023-05-04T20:39:44.513359Z","shell.execute_reply":"2023-05-04T20:39:44.520113Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df.info()","metadata":{"execution":{"iopub.status.busy":"2023-05-04T20:39:47.012711Z","iopub.execute_input":"2023-05-04T20:39:47.013114Z","iopub.status.idle":"2023-05-04T20:39:47.029554Z","shell.execute_reply.started":"2023-05-04T20:39:47.013079Z","shell.execute_reply":"2023-05-04T20:39:47.028043Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## <span style=\"color:teal\"> 3.3 Sample submission datafram info <a class=\"anchor\"  id=\"test\"></a></span>","metadata":{}},{"cell_type":"code","source":"sample_submission_df = pd.read_csv(config.sample_submission)\nsample_submission_df","metadata":{"execution":{"iopub.status.busy":"2023-05-04T20:39:50.627983Z","iopub.execute_input":"2023-05-04T20:39:50.628434Z","iopub.status.idle":"2023-05-04T20:39:50.645373Z","shell.execute_reply.started":"2023-05-04T20:39:50.628393Z","shell.execute_reply":"2023-05-04T20:39:50.644465Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## <span style=\"color:teal\"> 3.4 Number of images per patient <a class=\"anchor\"  id=\"test\"></a></span>","metadata":{}},{"cell_type":"code","source":"images_counter = train_df[\"patient_id\"].value_counts().sort_index()\n\nfig = px.histogram(images_counter, text_auto=True, title=\"Number of images per patient\")\nfig.update_layout(bargap=0.2)\nfig.show()\n","metadata":{"execution":{"iopub.status.busy":"2023-05-04T20:39:56.177483Z","iopub.execute_input":"2023-05-04T20:39:56.17865Z","iopub.status.idle":"2023-05-04T20:39:56.524119Z","shell.execute_reply.started":"2023-05-04T20:39:56.178604Z","shell.execute_reply":"2023-05-04T20:39:56.522794Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## <span style=\"color:teal\"> 3.5 Distribution of patients' age <a class=\"anchor\"  id=\"age\"></a></span>","metadata":{}},{"cell_type":"code","source":"person_age = train_df.groupby(\"patient_id\")['age'].max().sort_index().fillna(0).astype('int64')\n\nfig = px.histogram(person_age, title=\"Distribution of patients' age\")\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2023-05-04T20:40:03.0914Z","iopub.execute_input":"2023-05-04T20:40:03.091843Z","iopub.status.idle":"2023-05-04T20:40:03.163209Z","shell.execute_reply.started":"2023-05-04T20:40:03.091803Z","shell.execute_reply":"2023-05-04T20:40:03.161896Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# <span style=\"color:teal\"> 3.6. Sample image data <a class=\"anchor\"  id=\"sampleimagedata\"></a></span>","metadata":{}},{"cell_type":"code","source":"sample_image = config.train_path+\"10006/1459541791.dcm\"\npydicom.dcmread(sample_image)","metadata":{"execution":{"iopub.status.busy":"2023-05-04T20:40:10.903603Z","iopub.execute_input":"2023-05-04T20:40:10.904814Z","iopub.status.idle":"2023-05-04T20:40:10.982296Z","shell.execute_reply.started":"2023-05-04T20:40:10.904769Z","shell.execute_reply":"2023-05-04T20:40:10.981039Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# <span style=\"color:teal\"> 3.7 Handle missing values <a class=\"anchor\"  id=\"missingData\"></a></span>","metadata":{}},{"cell_type":"code","source":"def filter_missing_Features(df):\n    total_missing_data = [df[col].isnull().sum() for col in df.columns]\n    percentage_of_missing = [df[col].isnull().mean() for col in df.columns]\n    result = pd.DataFrame(zip(total_missing_data, percentage_of_missing), columns=['total_missing_data', 'percentage_of_missing'], index=df.columns)\n    result = result.sort_values('total_missing_data', ascending=False)\n    return result\nfilter_missing_Features(train_df)","metadata":{"execution":{"iopub.status.busy":"2023-05-04T20:40:19.774222Z","iopub.execute_input":"2023-05-04T20:40:19.77466Z","iopub.status.idle":"2023-05-04T20:40:19.817602Z","shell.execute_reply.started":"2023-05-04T20:40:19.77462Z","shell.execute_reply":"2023-05-04T20:40:19.816239Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"* **BIRADS** Columun have almost half missing and we don't know how to fill it so we decided better to remove this feature\n* The **Age**Columun also have very few missing values and we decided to fill these missing with average age value of the others\n\n* **Density** Columun have also almost half of missing data and we decided to fill it with other category labeld 'E'","metadata":{}},{"cell_type":"code","source":"train_df = train_df.drop(['BIRADS'], axis=1)\ntrain_df['age'] = train_df['age'].fillna(train_df['age'].mean())\ntrain_df['density'] = train_df['density'].fillna('E')\n\nfilter_missing_Features(train_df)","metadata":{"execution":{"iopub.status.busy":"2023-05-04T20:40:23.734178Z","iopub.execute_input":"2023-05-04T20:40:23.734646Z","iopub.status.idle":"2023-05-04T20:40:23.787135Z","shell.execute_reply.started":"2023-05-04T20:40:23.734607Z","shell.execute_reply":"2023-05-04T20:40:23.785945Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"\n# <span style=\"color:teal\">3.8 Fix Data Types <a class=\"anchor\"  id=\"FixingDataType\"></a></span>","metadata":{}},{"cell_type":"code","source":"train_df['laterality'] = train_df['laterality'].astype('category')\ntrain_df['view'] = train_df['view'].astype('category')\ntrain_df['age'] = train_df['age'].astype('int64')\ntrain_df['density'] = train_df['density'].astype('category')\ntrain_df['cancer'] = train_df['cancer'].astype('float32')\n\ntrain_df.info()","metadata":{"execution":{"iopub.status.busy":"2023-05-04T20:40:27.23624Z","iopub.execute_input":"2023-05-04T20:40:27.236654Z","iopub.status.idle":"2023-05-04T20:40:27.276919Z","shell.execute_reply.started":"2023-05-04T20:40:27.236619Z","shell.execute_reply":"2023-05-04T20:40:27.275471Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# <span style=\"color:teal\">3.9 Numerical Categorization of Age feature <a class=\"anchor\"  id=\"FixingDataType\"></a></span>","metadata":{}},{"cell_type":"code","source":"train_df[\"age_bin\"] = pd.cut(train_df['age'].values.reshape(-1), bins=5, labels=False)","metadata":{"execution":{"iopub.status.busy":"2023-05-04T20:40:30.499224Z","iopub.execute_input":"2023-05-04T20:40:30.50004Z","iopub.status.idle":"2023-05-04T20:40:30.508723Z","shell.execute_reply.started":"2023-05-04T20:40:30.499989Z","shell.execute_reply":"2023-05-04T20:40:30.507223Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# <span style=\"color:teal\">3.10 Generate dummy variables for the categorical columns <a class=\"anchor\"  id=\"FixingDataType\"></a></span>","metadata":{}},{"cell_type":"code","source":"cat_cols = ['laterality', 'view', 'density', 'difficult_negative_case']\ntrain_df = pd.get_dummies(train_df, columns=cat_cols)\ntrain_df.info()","metadata":{"execution":{"iopub.status.busy":"2023-05-04T20:40:33.602914Z","iopub.execute_input":"2023-05-04T20:40:33.603379Z","iopub.status.idle":"2023-05-04T20:40:33.636634Z","shell.execute_reply.started":"2023-05-04T20:40:33.603333Z","shell.execute_reply":"2023-05-04T20:40:33.635261Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# <span style=\"color:teal\">3.11 Adding new features to hold dicom image path and processed image pathes <a class=\"anchor\"  id=\"FixingDataType\"></a></span>\n","metadata":{}},{"cell_type":"code","source":"train_df['dicom_path'] = config.train_path + train_df['patient_id'].astype(str) + '/' + train_df['image_id'].astype(str) + '.dcm'\ntrain_df['image_path'] = config.train_output_path + train_df['patient_id'].astype(str) + '/' + train_df['image_id'].astype(str) + '.png'\n\ntest_df['dicom_path'] = config.test_path + test_df['patient_id'].astype(str) + '/' + test_df['image_id'].astype(str) + '.dcm'\ntest_df['image_path'] = config.test_output_path + test_df['patient_id'].astype(str) + '/' + test_df['image_id'].astype(str) + '.png'","metadata":{"execution":{"iopub.status.busy":"2023-05-04T20:40:36.45234Z","iopub.execute_input":"2023-05-04T20:40:36.452744Z","iopub.status.idle":"2023-05-04T20:40:36.677573Z","shell.execute_reply.started":"2023-05-04T20:40:36.45271Z","shell.execute_reply":"2023-05-04T20:40:36.676258Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.head()","metadata":{"execution":{"iopub.status.busy":"2023-05-04T20:40:41.388094Z","iopub.execute_input":"2023-05-04T20:40:41.388649Z","iopub.status.idle":"2023-05-04T20:40:41.421528Z","shell.execute_reply.started":"2023-05-04T20:40:41.388601Z","shell.execute_reply":"2023-05-04T20:40:41.420636Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df.head()","metadata":{"execution":{"iopub.status.busy":"2023-05-04T20:40:44.208681Z","iopub.execute_input":"2023-05-04T20:40:44.209132Z","iopub.status.idle":"2023-05-04T20:40:44.225743Z","shell.execute_reply.started":"2023-05-04T20:40:44.209094Z","shell.execute_reply":"2023-05-04T20:40:44.224242Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# <span style=\"color:teal\">3.12 Save the prepared training dataframe into csv <a class=\"anchor\"  id=\"FixingDataType\"></a></span>","metadata":{}},{"cell_type":"code","source":"train_df.to_csv(\"train_df_processed.csv\", sep=',',index=False)","metadata":{"execution":{"iopub.status.busy":"2023-05-04T20:40:46.870304Z","iopub.execute_input":"2023-05-04T20:40:46.870984Z","iopub.status.idle":"2023-05-04T20:40:47.322017Z","shell.execute_reply.started":"2023-05-04T20:40:46.870943Z","shell.execute_reply":"2023-05-04T20:40:47.320565Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# <span style=\"color:teal\"> 4.Functions to convert ,extract ROI and save dicom images <a class=\"anchor\"  id=\"UtilityFunction\"></a></span>","metadata":{}},{"cell_type":"markdown","source":"## <span style=\"color:teal\"> 4.1 Dicom to png : <a class=\"anchor\"  id=\"dicomtopng\"></a></span>\n\n  * The dicom.pixelData(storedvalue=False) line of code in the below function **dicom_to_png()**   extracts the pixel data from the DICOM file using the pixelData method provided by the dicomsdl library and the **storedvalue=False** argument ensures that the pixel data is returned as floating point values between 0 and 1.\n\n* The if **dicom.PhotometricInterpretation == 'MONOCHROME1'**: line of checks the photometric interpretation of the DICOM file and inverts the image data if it is **MONOCHROME1** because **MONOCHROME1** images have higher pixel values for darker areas of the image, whereas **MONOCHROME2** images have higher pixel values for brighter areas of the image.","metadata":{}},{"cell_type":"code","source":"def dicom_to_png(dicom_path):\n    dicom = dicomsdl.open(dicom_path)\n    image = dicom.pixelData(storedvalue=False)\n    image = image - np.min(image)\n    image = image / np.max(image)\n\n    if dicom.PhotometricInterpretation == 'MONOCHROME1':\n        image = 1.0 - image\n    \n    image = cv2.resize(image, (config.img_size, config.img_size), interpolation=cv2.INTER_LINEAR)\n    image = (image * 255).astype(np.uint8)\n    return image","metadata":{"execution":{"iopub.status.busy":"2023-05-04T20:40:50.409322Z","iopub.execute_input":"2023-05-04T20:40:50.410776Z","iopub.status.idle":"2023-05-04T20:40:50.418926Z","shell.execute_reply.started":"2023-05-04T20:40:50.410709Z","shell.execute_reply":"2023-05-04T20:40:50.417674Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## <span style=\"color:teal\"> 4.2 Region of Interest (ROI): <a class=\"anchor\"  id=\"regionOfInterest\"></a></span>\n * In image processing and computer vision, a Region of Interest (ROI) is a portion of an image that is selected for further processing or analysis. An ROI can be defined as a rectangular, circular, or polygonal area that contains the object or region of interest.\n * It is an important step in many image processing and computer vision applications because it allows us to focus on the most relevant parts of an image and reduce the amount of data that needs to be processed.\n * **Contours** are simply the boundaries of objects or shapes in an image. In image processing, contours are defined as the curves joining all the continuous points (along the boundary), having same color or intensity.","metadata":{}},{"cell_type":"code","source":"def png_to_roi(image, image_path):\n    bin_image = cv2.threshold(image, 20, 255, cv2.THRESH_BINARY)[1]\n    contours, _ = cv2.findContours(bin_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)\n    contour = max(contours, key=cv2.contourArea)\n    ys = contour.squeeze()[:, 0]\n    xs = contour.squeeze()[:, 1]\n    roi = image[np.min(xs):np.max(xs), np.min(ys):np.max(ys)]\n    return cv2.resize(roi, config.resize_dim[::-1], interpolation=cv2.INTER_LINEAR)\n","metadata":{"execution":{"iopub.status.busy":"2023-05-04T20:40:53.822461Z","iopub.execute_input":"2023-05-04T20:40:53.822938Z","iopub.status.idle":"2023-05-04T20:40:53.832238Z","shell.execute_reply.started":"2023-05-04T20:40:53.822894Z","shell.execute_reply":"2023-05-04T20:40:53.830546Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## <span style=\"color:teal\"> 4.3 Process and save images into ouput directory: <a class=\"anchor\"  id=\"process\"></a></span>","metadata":{}},{"cell_type":"code","source":"def process(dicom_path, image_path):\n    image = dicom_to_png(dicom_path)\n    os.makedirs(os.path.dirname(image_path), exist_ok=True)\n    image = png_to_roi(image, image_path)\n    cv2.imwrite(image_path, image)","metadata":{"execution":{"iopub.status.busy":"2023-05-04T20:40:57.048748Z","iopub.execute_input":"2023-05-04T20:40:57.049159Z","iopub.status.idle":"2023-05-04T20:40:57.055994Z","shell.execute_reply.started":"2023-05-04T20:40:57.049124Z","shell.execute_reply":"2023-05-04T20:40:57.054318Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Parallel(n_jobs=4, backend='threading')(delayed(process)(dicom_path, image_path) \n                   for dicom_path, image_path in tqdm(zip(test_df['dicom_path'], \n                                                          test_df['image_path'])))\nclear_output()","metadata":{"execution":{"iopub.status.busy":"2023-05-04T20:41:02.651443Z","iopub.execute_input":"2023-05-04T20:41:02.651858Z","iopub.status.idle":"2023-05-04T20:41:06.019539Z","shell.execute_reply.started":"2023-05-04T20:41:02.651823Z","shell.execute_reply":"2023-05-04T20:41:06.018227Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Parallel(n_jobs=4, backend='threading')(delayed(process)(dicom_path, image_path) \n                   for dicom_path, image_path in tqdm(zip(train_df['dicom_path'], \n                                                          train_df['image_path'])))\nclear_output()","metadata":{"execution":{"iopub.status.busy":"2023-05-04T20:37:59.808005Z","iopub.status.idle":"2023-05-04T20:37:59.809Z","shell.execute_reply.started":"2023-05-04T20:37:59.808265Z","shell.execute_reply":"2023-05-04T20:37:59.808293Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!cp /kaggle/input/rsna-breast-cancer-detection/train.csv /kaggle/working/\n!cp /kaggle/input/rsna-breast-cancer-detection/test.csv /kaggle/working/\n!cp /kaggle/input/rsna-breast-cancer-detection/sample_submission.csv /kaggle/working/","metadata":{"execution":{"iopub.status.busy":"2023-05-04T20:41:14.703037Z","iopub.execute_input":"2023-05-04T20:41:14.703493Z","iopub.status.idle":"2023-05-04T20:41:18.043651Z","shell.execute_reply.started":"2023-05-04T20:41:14.703453Z","shell.execute_reply":"2023-05-04T20:41:18.041757Z"},"trusted":true},"execution_count":null,"outputs":[]}]}