diff --git a/src/ptbench/engine/visualizer.py b/src/ptbench/engine/visualizer.py index 87ceca5998b5bba39a8e38c7cd2cdf42e2c7763f..46f22e02e0842c3073b99a7fba862ac0abd10c3f 100644 --- a/src/ptbench/engine/visualizer.py +++ b/src/ptbench/engine/visualizer.py @@ -9,11 +9,9 @@ import cv2 import numpy as np import pandas as pd -from PIL import Image +from torchvision.transforms.functional import to_pil_image from tqdm import tqdm -from torchvision.transforms.functional import to_pil_image, to_tensor - from ..utils.cam_utils import ( draw_boxes_on_image, draw_largest_component_bbox_on_image, diff --git a/src/ptbench/scripts/compare_vis.py b/src/ptbench/scripts/compare_vis.py index 6cee4b9366debc7ee46348b615bbcd484c76315e..bade26b87c4e53b2d18bfe1c9450b8937b8b6b08 100644 --- a/src/ptbench/scripts/compare_vis.py +++ b/src/ptbench/scripts/compare_vis.py @@ -26,6 +26,7 @@ def _sorting_rule(folder_name): else: # Everything else will be sorted alphabetically after fullgrad and before randomcam return (3, folder_name) + def _get_images_from_directory(dir_path): image_files = [] for root, _, files in os.walk(dir_path): @@ -34,6 +35,7 @@ def _get_images_from_directory(dir_path): image_files.append(os.path.join(root, file)) return image_files + @click.command( epilog="""Examples: @@ -133,13 +135,19 @@ def compare_vis(input_folder, output_folder) -> None: os.makedirs(output_directory, exist_ok=True) # Use a set (unordered collection of unique elements) for efficient membership tests - image_names = set([os.path.basename(img) for img in _get_images_from_directory(comparison_folders[0])]) + image_names = { + os.path.basename(img) + for img in _get_images_from_directory(comparison_folders[0]) + } # Only keep image names that exist in all folders for folder in comparison_folders[1:]: # This is basically an intersection-check of contents of different folders # Images that don't exist in all folders are removed from the set - image_names &= set([os.path.basename(img) for img in _get_images_from_directory(folder)]) + image_names &= { + os.path.basename(img) + for img in _get_images_from_directory(folder) + } if not image_names: raise ValueError("No common images found in the folders.") @@ -165,7 +173,11 @@ def compare_vis(input_folder, output_folder) -> None: ) axs = axs.ravel() for i, folder in enumerate(comparison_folders): - image_path = [img for img in _get_images_from_directory(folder) if os.path.basename(img) == image_name][0] + image_path = [ + img + for img in _get_images_from_directory(folder) + if os.path.basename(img) == image_name + ][0] try: img = cv2.imread(image_path) img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) diff --git a/tests/test_cam_utils.py b/tests/test_cam_utils.py index 1435d8ac9d3ec294e969dbae737884c079689027..2d3273d55c08aa9e5d7ba5da6293abae959553d6 100644 --- a/tests/test_cam_utils.py +++ b/tests/test_cam_utils.py @@ -217,8 +217,20 @@ def test_draw_boxes_on_image(): img_with_boxes2 = np.zeros((256, 256, 3), dtype=np.uint8) img_with_boxes3 = np.zeros((512, 512, 3), dtype=np.uint8) bboxes = [ - [torch.tensor(1),torch.tensor(10),torch.tensor(10),torch.tensor(20),torch.tensor(20)], - [torch.tensor(1),torch.tensor(30),torch.tensor(30),torch.tensor(40),torch.tensor(40)] + [ + torch.tensor(1), + torch.tensor(10), + torch.tensor(10), + torch.tensor(20), + torch.tensor(20), + ], + [ + torch.tensor(1), + torch.tensor(30), + torch.tensor(30), + torch.tensor(40), + torch.tensor(40), + ], ] result = draw_boxes_on_image(img_with_boxes, bboxes) diff --git a/tests/test_saliencymap_evaluator.py b/tests/test_saliencymap_evaluator.py index 1b32f283883130acee3c911e101656fdee800574..848812402405eaa9bf6e6bc86460c80b4ca12ba2 100644 --- a/tests/test_saliencymap_evaluator.py +++ b/tests/test_saliencymap_evaluator.py @@ -15,8 +15,20 @@ from ptbench.engine.saliencymap_evaluator import ( def test_compute_max_iou_and_ioda(): detected_box = (10, 10, 100, 100) - gt_box_dict = [torch.tensor(1),torch.tensor(50),torch.tensor(50),torch.tensor(50),torch.tensor(50)] - gt_box_dict2 = [torch.tensor(1),torch.tensor(20),torch.tensor(20),torch.tensor(60),torch.tensor(60)] + gt_box_dict = [ + torch.tensor(1), + torch.tensor(50), + torch.tensor(50), + torch.tensor(50), + torch.tensor(50), + ] + gt_box_dict2 = [ + torch.tensor(1), + torch.tensor(20), + torch.tensor(20), + torch.tensor(60), + torch.tensor(60), + ] gt_boxes = [gt_box_dict, gt_box_dict2] iou, ioda = _compute_max_iou_and_ioda(detected_box, gt_boxes) @@ -30,7 +42,13 @@ def test_compute_max_iou_and_ioda(): def test_compute_max_iou_and_ioda_zero_detected_area(): detected_box = (10, 10, 0, 0) - gt_box_dict = [torch.tensor(1),torch.tensor(50),torch.tensor(50),torch.tensor(50),torch.tensor(50)] + gt_box_dict = [ + torch.tensor(1), + torch.tensor(50), + torch.tensor(50), + torch.tensor(50), + torch.tensor(50), + ] gt_boxes = [gt_box_dict] iou, ioda = _compute_max_iou_and_ioda(detected_box, gt_boxes) @@ -42,7 +60,13 @@ def test_compute_max_iou_and_ioda_zero_detected_area(): def test_compute_max_iou_and_ioda_zero_gt_area(): detected_box = (10, 10, 100, 100) - gt_box_dict = [torch.tensor(1),torch.tensor(50),torch.tensor(50),torch.tensor(0),torch.tensor(0)] + gt_box_dict = [ + torch.tensor(1), + torch.tensor(50), + torch.tensor(50), + torch.tensor(0), + torch.tensor(0), + ] gt_boxes = [gt_box_dict] iou, ioda = _compute_max_iou_and_ioda(detected_box, gt_boxes) @@ -54,7 +78,13 @@ def test_compute_max_iou_and_ioda_zero_gt_area(): def test_compute_max_iou_and_ioda_zero_intersection(): detected_box = (10, 10, 100, 100) - gt_box_dict = [torch.tensor(1),torch.tensor(0),torch.tensor(0),torch.tensor(5),torch.tensor(5)] + gt_box_dict = [ + torch.tensor(1), + torch.tensor(0), + torch.tensor(0), + torch.tensor(5), + torch.tensor(5), + ] gt_boxes = [gt_box_dict] iou, ioda = _compute_max_iou_and_ioda(detected_box, gt_boxes) @@ -65,8 +95,20 @@ def test_compute_max_iou_and_ioda_zero_intersection(): def test_compute_simultaneous_iou_and_ioda(): detected_box = (10, 10, 100, 100) - gt_box_dict1 = [torch.tensor(1),torch.tensor(50),torch.tensor(50),torch.tensor(50),torch.tensor(50)] - gt_box_dict2 = [torch.tensor(1),torch.tensor(70),torch.tensor(70),torch.tensor(30),torch.tensor(30)] + gt_box_dict1 = [ + torch.tensor(1), + torch.tensor(50), + torch.tensor(50), + torch.tensor(50), + torch.tensor(50), + ] + gt_box_dict2 = [ + torch.tensor(1), + torch.tensor(70), + torch.tensor(70), + torch.tensor(30), + torch.tensor(30), + ] gt_boxes = [gt_box_dict1, gt_box_dict2] iou, ioda = _compute_simultaneous_iou_and_ioda(detected_box, gt_boxes) @@ -80,7 +122,13 @@ def test_compute_avg_saliency_focus(): grayscale_cams2 = np.full((512, 512), 0.5) grayscale_cams3 = np.zeros((256, 256)) grayscale_cams3[50:75, 50:100] = 1 - gt_box_dict = [torch.tensor(1),torch.tensor(50),torch.tensor(50),torch.tensor(50),torch.tensor(50)] + gt_box_dict = [ + torch.tensor(1), + torch.tensor(50), + torch.tensor(50), + torch.tensor(50), + torch.tensor(50), + ] gt_boxes = [gt_box_dict] avg_saliency_focus = _compute_avg_saliency_focus(gt_boxes, grayscale_cams) @@ -94,7 +142,13 @@ def test_compute_avg_saliency_focus(): def test_compute_avg_saliency_focus_no_activations(): grayscale_cams = np.zeros((200, 200)) - gt_box_dict = [torch.tensor(1),torch.tensor(50),torch.tensor(50),torch.tensor(50),torch.tensor(50)] + gt_box_dict = [ + torch.tensor(1), + torch.tensor(50), + torch.tensor(50), + torch.tensor(50), + torch.tensor(50), + ] gt_boxes = [gt_box_dict] avg_saliency_focus = _compute_avg_saliency_focus(gt_boxes, grayscale_cams) @@ -104,7 +158,13 @@ def test_compute_avg_saliency_focus_no_activations(): def test_compute_avg_saliency_focus_zero_gt_area(): grayscale_cams = np.ones((200, 200)) - gt_box_dict = [torch.tensor(1),torch.tensor(50),torch.tensor(50),torch.tensor(0),torch.tensor(0)] + gt_box_dict = [ + torch.tensor(1), + torch.tensor(50), + torch.tensor(50), + torch.tensor(0), + torch.tensor(0), + ] gt_boxes = [gt_box_dict] avg_saliency_focus = _compute_avg_saliency_focus(gt_boxes, grayscale_cams) @@ -117,7 +177,13 @@ def test_compute_proportional_energy(): grayscale_cams2 = np.full((512, 512), 0.5) grayscale_cams3 = np.zeros((512, 512)) grayscale_cams3[100:200, 100:200] = 1 - gt_box_dict = [torch.tensor(1),torch.tensor(50),torch.tensor(50),torch.tensor(100),torch.tensor(100)] + gt_box_dict = [ + torch.tensor(1), + torch.tensor(50), + torch.tensor(50), + torch.tensor(100), + torch.tensor(100), + ] gt_boxes = [gt_box_dict] proportional_energy = _compute_proportional_energy(gt_boxes, grayscale_cams) @@ -135,7 +201,13 @@ def test_compute_proportional_energy(): def test_compute_proportional_energy_no_activations(): grayscale_cams = np.zeros((200, 200)) - gt_box_dict = [torch.tensor(1),torch.tensor(50),torch.tensor(50),torch.tensor(50),torch.tensor(50)] + gt_box_dict = [ + torch.tensor(1), + torch.tensor(50), + torch.tensor(50), + torch.tensor(50), + torch.tensor(50), + ] gt_boxes = [gt_box_dict] proportional_energy = _compute_proportional_energy(gt_boxes, grayscale_cams) @@ -145,7 +217,13 @@ def test_compute_proportional_energy_no_activations(): def test_compute_proportional_energy_no_gt_box(): grayscale_cams = np.ones((200, 200)) - gt_box_dict = [torch.tensor(1),torch.tensor(0),torch.tensor(0),torch.tensor(0),torch.tensor(0)] + gt_box_dict = [ + torch.tensor(1), + torch.tensor(0), + torch.tensor(0), + torch.tensor(0), + torch.tensor(0), + ] gt_boxes = [gt_box_dict] proportional_energy = _compute_proportional_energy(gt_boxes, grayscale_cams) @@ -156,7 +234,13 @@ def test_compute_proportional_energy_no_gt_box(): def test_calculate_localization_metrics(): grayscale_cams = np.zeros((200, 200)) detected_box = (10, 10, 100, 100) - gt_box_dict = [torch.tensor(1),torch.tensor(50),torch.tensor(50),torch.tensor(50),torch.tensor(50)] + gt_box_dict = [ + torch.tensor(1), + torch.tensor(50), + torch.tensor(50), + torch.tensor(50), + torch.tensor(50), + ] ground_truth_box = [gt_box_dict] (