BhumikaMak commited on
Commit
d5e1bd6
·
1 Parent(s): b63af6d

Update: codebase

Browse files
Files changed (2) hide show
  1. app.py +14 -119
  2. yolov5.py +82 -0
app.py CHANGED
@@ -1,142 +1,37 @@
1
- import warnings
2
- warnings.filterwarnings('ignore')
3
- warnings.simplefilter('ignore')
4
-
5
- import torch
6
- import cv2
7
  import numpy as np
8
- import torchvision.transforms as transforms
9
- from pytorch_grad_cam import EigenCAM
10
- from pytorch_grad_cam.utils.image import show_cam_on_image, scale_cam_image
11
  from PIL import Image
 
12
  import gradio as gr
13
- from YOLOv8_Explainer import yolov8_heatmap, display_images # Import Explainer
14
-
15
- # Global Color Palette
16
- COLORS = np.random.uniform(0, 255, size=(80, 3))
17
-
18
- # Function to parse YOLO detections
19
- def parse_detections(results):
20
- detections = results.pandas().xyxy[0].to_dict()
21
- boxes, colors, names = [], [], []
22
- for i in range(len(detections["xmin"])):
23
- confidence = detections["confidence"][i]
24
- if confidence < 0.2:
25
- continue
26
- xmin, ymin = int(detections["xmin"][i]), int(detections["ymin"][i])
27
- xmax, ymax = int(detections["xmax"][i]), int(detections["ymax"][i])
28
- name, category = detections["name"][i], int(detections["class"][i])
29
- boxes.append((xmin, ymin, xmax, ymax))
30
- colors.append(COLORS[category])
31
- names.append(name)
32
- return boxes, colors, names
33
-
34
- # Draw bounding boxes and labels
35
- def draw_detections(boxes, colors, names, img):
36
- for box, color, name in zip(boxes, colors, names):
37
- xmin, ymin, xmax, ymax = box
38
- cv2.rectangle(img, (xmin, ymin), (xmax, ymax), color, 2)
39
- cv2.putText(img, name, (xmin, ymin - 5),
40
- cv2.FONT_HERSHEY_SIMPLEX, 0.8, color, 2,
41
- lineType=cv2.LINE_AA)
42
- return img
43
-
44
- # Load the appropriate YOLO model based on the version
45
- def load_yolo_model(version="yolov5"):
46
- if version == "yolov3":
47
- model = torch.hub.load('ultralytics/yolov3', 'yolov3', pretrained=True)
48
- elif version == "yolov5":
49
- model = torch.hub.load('ultralytics/yolov5', 'yolov5s', pretrained=True)
50
- elif version == "yolov7":
51
- model = torch.hub.load('WongKinYiu/yolov7', 'yolov7', pretrained=True)
52
- elif version == "yolov8":
53
- model = torch.hub.load('ultralytics/yolov5:v7.0', 'yolov5', pretrained=True)
54
- elif version == "yolov10":
55
- model = torch.hub.load('ultralytics/yolov5', 'yolov5m', pretrained=True)
56
- else:
57
- raise ValueError(f"Unsupported YOLO version: {version}")
58
-
59
- model.eval() # Set to evaluation mode
60
- model.cpu()
61
- return model
62
 
63
- # Main function for Grad-CAM visualization
64
- def process_image(image, yolo_versions=["yolov5"], use_explainer=False):
65
  image = np.array(image)
66
  image = cv2.resize(image, (640, 640))
67
- rgb_img = image.copy()
68
- img_float = np.float32(image) / 255
69
-
70
- # Image transformation
71
- transform = transforms.ToTensor()
72
- tensor = transform(img_float).unsqueeze(0)
73
 
74
- # Initialize list to store result images with captions
75
  result_images = []
76
-
77
- # Process each selected YOLO model
78
  for yolo_version in yolo_versions:
79
- if use_explainer and yolo_version == "yolov8":
80
- # Use YOLOv8 Explainer for EigenCAM heatmap
81
- explainer_model = yolov8_heatmap(
82
- weight="yolov8n.pt",
83
- conf_threshold=0.4,
84
- device="cpu",
85
- method="EigenCAM",
86
- layer=[10, 12, 14, 16, 18, -3],
87
- backward_type="all",
88
- ratio=0.02,
89
- show_box=True,
90
- renormalize=False,
91
- )
92
- imagelist = explainer_model(img_path=image)
93
- display_images(imagelist)
94
- continue # Skip Grad-CAM for this case
95
-
96
- # Load the model based on YOLO version
97
- model = load_yolo_model(yolo_version)
98
- target_layers = [model.model.model.model[-2]] # Assumes last layer is used for Grad-CAM
99
-
100
- # Run YOLO detection
101
- results = model([rgb_img])
102
- boxes, colors, names = parse_detections(results)
103
- detections_img = draw_detections(boxes, colors, names, rgb_img.copy())
104
-
105
- # Grad-CAM visualization
106
- cam = EigenCAM(model, target_layers)
107
- grayscale_cam = cam(tensor)[0, :, :]
108
- cam_image = show_cam_on_image(img_float, grayscale_cam, use_rgb=True)
109
-
110
- # Renormalize Grad-CAM inside bounding boxes
111
- renormalized_cam = np.zeros(grayscale_cam.shape, dtype=np.float32)
112
- for x1, y1, x2, y2 in boxes:
113
- renormalized_cam[y1:y2, x1:x2] = scale_cam_image(grayscale_cam[y1:y2, x1:x2].copy())
114
- renormalized_cam = scale_cam_image(renormalized_cam)
115
- renormalized_cam_image = show_cam_on_image(img_float, renormalized_cam, use_rgb=True)
116
-
117
- # Concatenate images and prepare the caption
118
- final_image = np.hstack((rgb_img, cam_image, renormalized_cam_image))
119
- caption = f"Results using {yolo_version}"
120
- result_images.append((Image.fromarray(final_image), caption))
121
-
122
  return result_images
123
 
124
- # Gradio Interface
125
  interface = gr.Interface(
126
  fn=process_image,
127
  inputs=[
128
  gr.Image(type="pil", label="Upload an Image"),
129
  gr.CheckboxGroup(
130
  choices=["yolov3", "yolov5", "yolov7", "yolov8", "yolov10"],
131
- value=["yolov5"], # Default to YOLOv5
132
  label="Select Model(s)",
133
- ),
134
- gr.Checkbox(label="Use YOLOv8 Explainer?", value=False)
135
  ],
136
  outputs=gr.Gallery(label="Results", elem_id="gallery", rows=2, height=500),
137
- title="Visualising the key image features that drive decisions with our explainable AI tool.",
138
- description="XAI: Upload an image to visualize object detection of your models."
139
  )
140
 
141
  if __name__ == "__main__":
142
- interface.launch()
 
 
 
 
 
 
 
1
  import numpy as np
2
+ import cv2
 
 
3
  from PIL import Image
4
+ import torchvision.transforms as transforms
5
  import gradio as gr
6
+ from yolov5 import xai_yolov5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
 
8
+ def process_image(image, yolo_versions=["yolov5"]):
 
9
  image = np.array(image)
10
  image = cv2.resize(image, (640, 640))
 
 
 
 
 
 
11
 
 
12
  result_images = []
 
 
13
  for yolo_version in yolo_versions:
14
+ if yolo_version == "yolov5":
15
+ result_images.append(xai_yolov5(image))
16
+ else:
17
+ result_images.append((Image.fromarray(image), f"{yolo_version} not yet implemented."))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  return result_images
19
 
20
+
21
  interface = gr.Interface(
22
  fn=process_image,
23
  inputs=[
24
  gr.Image(type="pil", label="Upload an Image"),
25
  gr.CheckboxGroup(
26
  choices=["yolov3", "yolov5", "yolov7", "yolov8", "yolov10"],
27
+ value=["yolov5"], # Set default selection to YOLOv5
28
  label="Select Model(s)",
29
+ )
 
30
  ],
31
  outputs=gr.Gallery(label="Results", elem_id="gallery", rows=2, height=500),
32
+ title="Explainable AI for YOLO Models",
33
+ description="Upload an image to visualize YOLO object detection with Grad-CAM."
34
  )
35
 
36
  if __name__ == "__main__":
37
+ interface.launch()
yolov5.py ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import cv2
3
+ import numpy as np
4
+ from PIL import Image
5
+ import torchvision.transforms as transforms
6
+ from pytorch_grad_cam import EigenCAM
7
+ from pytorch_grad_cam.utils.image import show_cam_on_image, scale_cam_image
8
+ import gradio as gr
9
+
10
+ # Global Color Palette
11
+ COLORS = np.random.uniform(0, 255, size=(80, 3))
12
+
13
+
14
+ def parse_detections(results):
15
+ detections = results.pandas().xyxy[0].to_dict()
16
+ boxes, colors, names = [], [], []
17
+ for i in range(len(detections["xmin"])):
18
+ confidence = detections["confidence"][i]
19
+ if confidence < 0.2:
20
+ continue
21
+ xmin, ymin = int(detections["xmin"][i]), int(detections["ymin"][i])
22
+ xmax, ymax = int(detections["xmax"][i]), int(detections["ymax"][i])
23
+ name, category = detections["name"][i], int(detections["class"][i])
24
+ boxes.append((xmin, ymin, xmax, ymax))
25
+ colors.append(COLORS[category])
26
+ names.append(name)
27
+ return boxes, colors, names
28
+
29
+
30
+ def draw_detections(boxes, colors, names, img):
31
+ for box, color, name in zip(boxes, colors, names):
32
+ xmin, ymin, xmax, ymax = box
33
+ cv2.rectangle(img, (xmin, ymin), (xmax, ymax), color, 2)
34
+ cv2.putText(img, name, (xmin, ymin - 5),
35
+ cv2.FONT_HERSHEY_SIMPLEX, 0.8, color, 2,
36
+ lineType=cv2.LINE_AA)
37
+ return img
38
+
39
+
40
+ def generate_cam_image(model, target_layers, tensor, rgb_img, boxes):
41
+ cam = EigenCAM(model, target_layers)
42
+ grayscale_cam = cam(tensor)[0, :, :]
43
+ img_float = np.float32(rgb_img) / 255
44
+
45
+ # Generate Grad-CAM
46
+ cam_image = show_cam_on_image(img_float, grayscale_cam, use_rgb=True)
47
+
48
+ # Renormalize Grad-CAM inside bounding boxes
49
+ renormalized_cam = np.zeros(grayscale_cam.shape, dtype=np.float32)
50
+ for x1, y1, x2, y2 in boxes:
51
+ renormalized_cam[y1:y2, x1:x2] = scale_cam_image(grayscale_cam[y1:y2, x1:x2].copy())
52
+ renormalized_cam = scale_cam_image(renormalized_cam)
53
+ renormalized_cam_image = show_cam_on_image(img_float, renormalized_cam, use_rgb=True)
54
+
55
+ return cam_image, renormalized_cam_image
56
+
57
+
58
+ def xai_yolov5(image):
59
+ # Load YOLOv5 model
60
+ model = torch.hub.load('ultralytics/yolov5', 'yolov5s', pretrained=True)
61
+ model.eval()
62
+ model.cpu()
63
+
64
+ target_layers = [model.model.model.model[-2]] # Grad-CAM target layer
65
+
66
+ # Run YOLO detection
67
+ results = model([image])
68
+ boxes, colors, names = parse_detections(results)
69
+ detections_img = draw_detections(boxes, colors, names, image.copy())
70
+
71
+ # Prepare input tensor for Grad-CAM
72
+ img_float = np.float32(image) / 255
73
+ transform = transforms.ToTensor()
74
+ tensor = transform(img_float).unsqueeze(0)
75
+
76
+ # Grad-CAM visualization
77
+ cam_image, renormalized_cam_image = generate_cam_image(model, target_layers, tensor, image, boxes)
78
+
79
+ # Combine results
80
+ final_image = np.hstack((image, cam_image, renormalized_cam_image))
81
+ caption = "Results using YOLOv5"
82
+ return Image.fromarray(final_image), caption