Last active
July 18, 2019 15:10
-
-
Save RaphaelMeudec/20aeacdfca4853789f0204252fee0664 to your computer and use it in GitHub Desktop.
Grad CAM (without Guided Backpropagation) with Tensorflow 2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import cv2 | |
import numpy as np | |
import tensorflow as tf | |
IMAGE_PATH = './cat.jpg' | |
LAYER_NAME = 'block5_conv3' | |
CAT_CLASS_INDEX = 281 | |
img = tf.keras.preprocessing.image.load_img(IMAGE_PATH, target_size=(224, 224)) | |
img = tf.keras.preprocessing.image.img_to_array(img) | |
# Load initial model | |
model = tf.keras.applications.vgg16.VGG16(weights='imagenet', include_top=True) | |
# Create a graph that outputs target convolution and output | |
grad_model = tf.keras.models.Model([model.inputs], [model.get_layer(LAYER_NAME).output, model.output]) | |
# Get the score for target class | |
with tf.GradientTape() as tape: | |
conv_outputs, predictions = grad_model(np.array([img])) | |
loss = predictions[:, CAT_CLASS_INDEX] | |
# Extract filters and gradients | |
output = conv_outputs[0] | |
grads = tape.gradient(loss, conv_outputs)[0] | |
# Average gradients spatially | |
weights = tf.reduce_mean(grads, axis=(0, 1)) | |
# Build a ponderated map of filters according to gradients importance | |
cam = np.ones(output.shape[0:2], dtype=np.float32) | |
for index, w in enumerate(weights): | |
cam += w * output[:, :, index] | |
# Heatmap visualization | |
cam = cv2.resize(cam.numpy(), (224, 224)) | |
cam = np.maximum(cam, 0) | |
heatmap = (cam - cam.min()) / (cam.max() - cam.min()) | |
cam = cv2.applyColorMap(np.uint8(255*heatmap), cv2.COLORMAP_JET) | |
output_image = cv2.addWeighted(cv2.cvtColor(img.astype('uint8'), cv2.COLOR_RGB2BGR), 0.5, cam, 1, 0) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment