ErnestBeckham commited on
Commit
98a42a0
·
verified ·
1 Parent(s): 7c0ac7f
Files changed (1) hide show
  1. grad_cam.py +82 -0
grad_cam.py ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import tensorflow as tf
2
+ from tensorflow.keras.models import load_model, Model
3
+ import cv2
4
+ import matplotlib.pyplot as plt
5
+ import numpy as np
6
+ import matplotlib.cm as cm
7
+
8
+ class GradCam:
9
+ def __init__(self, model, img, size:tuple, last_conv_layer_name, pred_index=None):
10
+ self.model = model
11
+ self.img_path = img
12
+ self.size = size
13
+ self.last_conv_layer_name = last_conv_layer_name
14
+
15
+
16
+ def make_gradcam_heatmap(self, pred_index=None):
17
+ # First, we create a model that maps the input image to the activations
18
+ # of the last conv layer as well as the output predictions
19
+ img_array= self.img_path
20
+ grad_model = tf.keras.models.Model(
21
+ [self.model.inputs], [self.model.get_layer(self.last_conv_layer_name).output, self.model.output]
22
+ )
23
+
24
+ # Compute the gradient of the top predicted class for our input image
25
+ # with respect to the activations of the last conv layer
26
+ with tf.GradientTape() as tape:
27
+ last_conv_layer_output, preds = grad_model(img_array)
28
+ if pred_index is None:
29
+ pred_index = tf.argmax(preds[0])
30
+ class_channel = preds[:, pred_index]
31
+
32
+ # This is the gradient of the output neuron (top predicted or chosen)
33
+ # with regard to the output feature map of the last conv layer
34
+ grads = tape.gradient(class_channel, last_conv_layer_output)
35
+
36
+ # This is a vector where each entry is the mean intensity of the gradient
37
+ # over a specific feature map channel
38
+ pooled_grads = tf.reduce_mean(grads, axis=(0, 1, 2))
39
+
40
+ # We multiply each channel in the feature map array
41
+ # by "how important this channel is" with regard to the top predicted class
42
+ last_conv_layer_output = last_conv_layer_output[0]
43
+ heatmap = last_conv_layer_output @ pooled_grads[..., tf.newaxis]
44
+ heatmap = tf.squeeze(heatmap)
45
+
46
+ # For visualization purpose, we will also normalize the heatmap between 0 & 1
47
+ heatmap = tf.maximum(heatmap, 0) / tf.math.reduce_max(heatmap)
48
+ return heatmap.numpy()
49
+
50
+
51
+ def save_and_display_gradcam(self, cam_path="cam.jpg", alpha=0.4):
52
+ heatmap = self.make_gradcam_heatmap()
53
+ # Load the original image
54
+
55
+ img = self.img_path
56
+
57
+ # Rescale the heatmap to a range 0-255
58
+ heatmap = np.uint8(255 * heatmap)
59
+
60
+ # Use the jet colormap to colorize the heatmap
61
+ jet = cm.get_cmap("jet")
62
+ jet_colors = jet(np.arange(512))[:, :3]
63
+ jet_heatmap = jet_colors[heatmap]
64
+
65
+ # Create an image with the RGB heatmap
66
+ jet_heatmap = tf.keras.preprocessing.image.array_to_img(jet_heatmap)
67
+ jet_heatmap = jet_heatmap.resize((img.shape[1], img.shape[0]))
68
+ jet_heatmap = tf.keras.preprocessing.image.img_to_array(jet_heatmap)
69
+
70
+ # Superimpose the heatmap on the original image
71
+ superimposed_img = jet_heatmap * alpha + img
72
+ superimposed_img = tf.keras.preprocessing.image.array_to_img(superimposed_img)
73
+
74
+ # Save and display the image
75
+ superimposed_img.save(cam_path)
76
+ plt.imshow(superimposed_img)
77
+ plt.axis('off')
78
+ plt.show()
79
+ plt.savefig(path)
80
+
81
+
82
+