From 472f372d1d0eecfb5ac993b7a793c401a7544fa1 Mon Sep 17 00:00:00 2001 From: Huy Nguyen <77764356+huynguyentran@users.noreply.github.com> Date: Mon, 27 Jan 2025 11:08:51 -0800 Subject: [PATCH 1/4] Updated create_cropped_images tto create_images_directory Updated create_cropped_images to create_images_directory. Now, the function would split the images into folders of classes. Crop function has been turned into optional for ease of use. --- eye_ai/eye_ai.py | 61 +++++++++++++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 24 deletions(-) diff --git a/eye_ai/eye_ai.py b/eye_ai/eye_ai.py index e8a2003..b94fb27 100644 --- a/eye_ai/eye_ai.py +++ b/eye_ai/eye_ai.py @@ -210,10 +210,10 @@ def get_bounding_box(svg_path: Path) -> tuple: bbox = (x_min, y_min, x_min + width, y_min + height) return bbox - def create_cropped_images(self, bag_path: Path, ds_bag: DatasetBag, output_dir: Path, crop_to_eye: bool, + def create_images_directory(self, bag_path: Path, ds_bag: DatasetBag, output_dir: Path, crop_to_eye: bool, exclude_list: Optional[list] = None) -> tuple: """ - Retrieves cropped images and saves them to the specified directory and seperated in two folders by class. + Retrieves images and saves them to the specified directory and separated into two folders by class. Optionally choose to crop the images or not. Parameters: - bag_path (str): Path to the bag directory. @@ -225,36 +225,49 @@ def create_cropped_images(self, bag_path: Path, ds_bag: DatasetBag, output_dir: if not exclude_list: exclude_list = [] - cropped_path = output_dir / "Image_cropped" - cropped_path_no_glaucoma = cropped_path / "No_Glaucoma" - cropped_path_no_glaucoma.mkdir(parents=True, exist_ok=True) - cropped_path_glaucoma = cropped_path / "Suspected_Glaucoma" - cropped_path_glaucoma.mkdir(parents=True, exist_ok=True) + + out_path = output_dir / ds_bag.dataset_rid + out_path = out_path / 'Images_Cropped' if crop_to_eye else out_path / 'Images' + out_path_no_glaucoma = out_path / 'No_Glaucoma' + out_path_no_glaucoma.mkdir(parents=True, exist_ok=True) + out_path_glaucoma = out_path / 'Suspected_Glaucoma' + out_path_glaucoma.mkdir(parents=True, exist_ok=True) + svg_root_path = bag_path / 'data/asset/Fundus_Bounding_Box' image_annot_df = ds_bag.get_table_as_dataframe('Annotation') image_df = ds_bag.get_table_as_dataframe('Image') diagnosis = ds_bag.get_table_as_dataframe('Image_Diagnosis') for index, row in image_annot_df.iterrows(): - if row['Annotation_Function'] != 'Raw_Cropped_to_Eye' or crop_to_eye: - image_rid = row['Image'] - if image_rid not in exclude_list: - svg_path = svg_root_path / f'Cropped_{image_rid}.svg' - bbox = self.get_bounding_box(svg_path) - image_file_name = image_df[image_df['RID'] == image_rid]['Filename'].values[0] - image_file_path = bag_path / image_file_name - image = Image.open(str(image_file_path)) - cropped_image = image.crop(bbox) - diag = diagnosis[(diagnosis['Diagnosis_Tag'] == 'Initial Diagnosis') + image_rid = row['Image'] + + if image_rid in exclude_list: + continue + + image_file_name = image_df[image_df['RID'] == image_rid]['Filename'].values[0] + image_file_path = bag_path / image_file_name + image = Image.open(str(image_file_path)) + diag = diagnosis[(diagnosis['Diagnosis_Tag'] == 'Initial Diagnosis') & (diagnosis['Image'] == image_rid)]['Diagnosis_Image'].iloc[0] - if diag == 'No Glaucoma': - cropped_image.save(f'{str(cropped_path_no_glaucoma)}/Cropped_{image_rid}.JPG') - else: - cropped_image.save(f'{str(cropped_path_glaucoma)}/Cropped_{image_rid}.JPG') - image_annot_df.loc[index, 'Cropped Filename'] = 'Cropped_' + image_file_name - output_csv = PurePath(self.working_dir, 'Cropped_Image.csv') + + out_path_dir = str(out_path_no_glaucoma) if diag == 'No Glaucoma' else str(out_path_glaucoma) + + if crop_to_eye and row['Annotation_Function'] != 'Raw_Cropped_to_Eye': + svg_path = svg_root_path / f'Cropped_{image_rid}.svg' + bbox = self.get_bounding_box(svg_path) + cropped_image = image.crop(bbox) + cropped_image.save(f'{out_path_dir}/Cropped_{image_rid}.JPG') + image_annot_df.loc[index, 'Cropped Filename'] = 'Cropped_' + image_file_name + + else: + image.save(f'{str(out_path_dir)}/{image_rid}.JPG') + image_annot_df.loc[index, 'Filename'] = image_file_name + + image_csv = 'Cropped_Image.csv' if crop_to_eye else 'Image.csv' + output_csv = PurePath(output_dir / ds_bag.dataset_rid, image_csv) image_annot_df.to_csv(output_csv) - return cropped_path, output_csv + + return out_path, output_csv def plot_roc(self, configuration_record, data: pd.DataFrame) -> Path: """ From 90fdd4efe56564013f61e226c37aa5ef36063d7b Mon Sep 17 00:00:00 2001 From: Huy Nguyen <77764356+huynguyentran@users.noreply.github.com> Date: Mon, 27 Jan 2025 11:19:19 -0800 Subject: [PATCH 2/4] Update create_images_directory Updated the function to handle the logic if the image is already cropped. --- eye_ai/eye_ai.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/eye_ai/eye_ai.py b/eye_ai/eye_ai.py index b94fb27..3843623 100644 --- a/eye_ai/eye_ai.py +++ b/eye_ai/eye_ai.py @@ -252,13 +252,15 @@ def create_images_directory(self, bag_path: Path, ds_bag: DatasetBag, output_dir out_path_dir = str(out_path_no_glaucoma) if diag == 'No Glaucoma' else str(out_path_glaucoma) - if crop_to_eye and row['Annotation_Function'] != 'Raw_Cropped_to_Eye': - svg_path = svg_root_path / f'Cropped_{image_rid}.svg' - bbox = self.get_bounding_box(svg_path) - cropped_image = image.crop(bbox) - cropped_image.save(f'{out_path_dir}/Cropped_{image_rid}.JPG') + if crop_to_eye: + if row['Annotation_Function'] != 'Raw_Cropped_to_Eye': + svg_path = svg_root_path / f'Cropped_{image_rid}.svg' + bbox = self.get_bounding_box(svg_path) + cropped_image = image.crop(bbox) + cropped_image.save(f'{out_path_dir}/Cropped_{image_rid}.JPG') + else: + image.save(f'{out_path_dir}/Cropped_{image_rid}.JPG') image_annot_df.loc[index, 'Cropped Filename'] = 'Cropped_' + image_file_name - else: image.save(f'{str(out_path_dir)}/{image_rid}.JPG') image_annot_df.loc[index, 'Filename'] = image_file_name From e8ac6fdf7bf35122f139b15e0a7a9298ef4337e1 Mon Sep 17 00:00:00 2001 From: Huy Nguyen <77764356+huynguyentran@users.noreply.github.com> Date: Mon, 27 Jan 2025 20:55:25 -0800 Subject: [PATCH 3/4] Update Remove the if logic, forcing cropping even if Raw_Cropped_to_Eye set to True --- eye_ai/eye_ai.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/eye_ai/eye_ai.py b/eye_ai/eye_ai.py index 3843623..7e40600 100644 --- a/eye_ai/eye_ai.py +++ b/eye_ai/eye_ai.py @@ -253,13 +253,10 @@ def create_images_directory(self, bag_path: Path, ds_bag: DatasetBag, output_dir out_path_dir = str(out_path_no_glaucoma) if diag == 'No Glaucoma' else str(out_path_glaucoma) if crop_to_eye: - if row['Annotation_Function'] != 'Raw_Cropped_to_Eye': - svg_path = svg_root_path / f'Cropped_{image_rid}.svg' - bbox = self.get_bounding_box(svg_path) - cropped_image = image.crop(bbox) - cropped_image.save(f'{out_path_dir}/Cropped_{image_rid}.JPG') - else: - image.save(f'{out_path_dir}/Cropped_{image_rid}.JPG') + svg_path = svg_root_path / f'Cropped_{image_rid}.svg' + bbox = self.get_bounding_box(svg_path) + cropped_image = image.crop(bbox) + cropped_image.save(f'{out_path_dir}/Cropped_{image_rid}.JPG') image_annot_df.loc[index, 'Cropped Filename'] = 'Cropped_' + image_file_name else: image.save(f'{str(out_path_dir)}/{image_rid}.JPG') From d4d7753c9032ba0bdcd5f898b0006e4c4d697ef9 Mon Sep 17 00:00:00 2001 From: Huy Nguyen <77764356+huynguyentran@users.noreply.github.com> Date: Tue, 28 Jan 2025 16:02:49 -0800 Subject: [PATCH 4/4] Revert the name Revert the name back to create_cropped_images to ensure this method works with other templates. --- eye_ai/eye_ai.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eye_ai/eye_ai.py b/eye_ai/eye_ai.py index 7e40600..7e6b498 100644 --- a/eye_ai/eye_ai.py +++ b/eye_ai/eye_ai.py @@ -210,7 +210,7 @@ def get_bounding_box(svg_path: Path) -> tuple: bbox = (x_min, y_min, x_min + width, y_min + height) return bbox - def create_images_directory(self, bag_path: Path, ds_bag: DatasetBag, output_dir: Path, crop_to_eye: bool, + def create_cropped_images(self, bag_path: Path, ds_bag: DatasetBag, output_dir: Path, crop_to_eye: bool, exclude_list: Optional[list] = None) -> tuple: """ Retrieves images and saves them to the specified directory and separated into two folders by class. Optionally choose to crop the images or not.