import matplotlib.pyplot as plt
%matplotlib inline
%config InlineBackend.figure_formats ={'png','retina'}
plt.rcParams["figure.figsize"]=(20,20)from tensorflow.keras.utils import load_img, img_to_array
from keras.applications.vgg16 import VGG16, preprocess_input, decode_predictions
from keras import backend as K
from scipy.ndimage import zoom
import numpy as np
import os
import tensorflow as tf
import keras
tf.compat.v1.disable_eager_execution()
model = VGG16(include_top=True, weights='imagenet',input_shape=(224,224,3))
defgenerate_cam(input_model, image, layer_name='block5_conv3', H=224, W=224):
cls = np.argmax(input_model.predict(image))# Obtain the predicted class
conv_output = input_model.get_layer(layer_name).output #Get the weights of the last output layer
last_conv_layer_model = keras.Model(input_model.inputs, conv_output)#Create a model with the last output layer
class_weights = input_model.get_layer(layer_name).get_weights()[0]# Get the weights of the output layer\
class_weights = class_weights[0,:,:,:]
class_weights = np.mean(class_weights, axis=(0,1))
last_conv_output = last_conv_layer_model.predict(image)#The feature map output from last output layer
last_conv_output = last_conv_output[0,:]
cam = np.dot(last_conv_output, class_weights)
cam = zoom(cam, H/cam.shape[0])#Spatial Interpolation/zooming to image size
cam = cam / np.max(cam)#Normalizing the gradcamreturn cam
defgrad_cam(input_model, image, layer_name='block5_conv3',H=224,W=224):
cls = np.argmax(input_model.predict(image))#Get the predicted class
y_c = input_model.output[0, cls]#Probability Score
conv_output = input_model.get_layer(layer_name).output #Tensor of the last layer of cnn
grads = K.gradients(y_c, conv_output)[0]#Gradients of the predicted class wrt conv_output layer
get_output = K.function([input_model.input],[conv_output, grads])
output, grads_val = get_output([image])#Gives output of image till conv_output layer and the gradient values at that level
output, grads_val = output[0,:], grads_val[0,:,:,:]
weights = np.mean(grads_val, axis=(0,1))#Mean of gradients which acts as our weights
cam = np.dot(output, weights)#Grad-CAM output
cam = np.maximum(cam,0)#Applying Relu
cam = zoom(cam,H/cam.shape[0])#Spatial Interpolation/zooming to image size
cam = cam / cam.max()#Normalizing the gradcamreturn cam
defgrad_cam_plus(input_model, image, layer_name='block5_conv3',H=224,W=224):
cls = np.argmax(input_model.predict(image))
y_c = input_model.output[0, cls]
conv_output = input_model.get_layer(layer_name).output
grads = K.gradients(y_c, conv_output)[0]
first = K.exp(y_c)*grads #Variables used to calculate first second and third gradients
second = K.exp(y_c)*grads*grads
third = K.exp(y_c)*grads*grads*grads
#Gradient calculation
get_output = K.function([input_model.input],[y_c,first,second,third, conv_output, grads])
y_c, conv_first_grad, conv_second_grad,conv_third_grad, conv_output, grads_val = get_output([img])
global_sum = np.sum(conv_output[0].reshape((-1,conv_first_grad[0].shape[2])), axis=0)#Used to calculate the alpha values for each spatial location
alpha_num = conv_second_grad[0]
alpha_denom = conv_second_grad[0]*2.0+ conv_third_grad[0]*global_sum.reshape((1,1,conv_first_grad[0].shape[2]))
alpha_denom = np.where(alpha_denom !=0.0, alpha_denom, np.ones(alpha_denom.shape))
alphas = alpha_num/alpha_denom
#Calculating the weights and alpha's which is the scale at which we multiply the weights with more importance
weights = np.maximum(conv_first_grad[0],0.0)
alpha_normalization_constant = np.sum(np.sum(alphas, axis=0),axis=0)
alphas /= alpha_normalization_constant.reshape((1,1,conv_first_grad[0].shape[2]))#Normalizing alpha#Weights with alpha multiplied to get spatial importance
deep_linearization_weights = np.sum((weights*alphas).reshape((-1,conv_first_grad[0].shape[2])),axis=0)
grad_CAM_map = np.sum(deep_linearization_weights*conv_output[0], axis=2)#Grad-CAM++ map
cam = np.maximum(grad_CAM_map,0)
cam = zoom(cam,H/cam.shape[0])
cam = cam / np.max(cam)return cam