|
a |
|
b/grad_cam.py |
|
|
1 |
# -*- coding: utf-8 -*- |
|
|
2 |
"""grad_cam.ipynb |
|
|
3 |
|
|
|
4 |
** |
|
|
5 |
* This file is part of Hybrid CNN-LSTM for COVID-19 Severity Score Prediction paper. |
|
|
6 |
* |
|
|
7 |
* Written by Ankan Ghosh Dastider and Farhan Sadik. |
|
|
8 |
* |
|
|
9 |
* Copyright (c) by the authors under Apache-2.0 License. Some rights reserved, see LICENSE. |
|
|
10 |
*/ |
|
|
11 |
|
|
|
12 |
""" |
|
|
13 |
import tensorflow as tf |
|
|
14 |
import keras |
|
|
15 |
print('tensorflow version: ', tf.__version__) |
|
|
16 |
print('keras version: ', keras.__version__) |
|
|
17 |
import numpy as np |
|
|
18 |
import cv2 |
|
|
19 |
|
|
|
20 |
#For images |
|
|
21 |
from keras.preprocessing.image import array_to_img, img_to_array, load_img |
|
|
22 |
#For model loading |
|
|
23 |
from keras.models import load_model |
|
|
24 |
#For Grad-CAM calculation |
|
|
25 |
from tensorflow.keras import models |
|
|
26 |
import tensorflow as tf |
|
|
27 |
|
|
|
28 |
IMAGE_SIZE = (128, 128) |
|
|
29 |
|
|
|
30 |
def grad_cam(input_model, x, layer_name): |
|
|
31 |
""" |
|
|
32 |
Args: |
|
|
33 |
input_model(object):Model object |
|
|
34 |
x(ndarray):image |
|
|
35 |
layer_name(string):The name of the convolution layer |
|
|
36 |
Returns: |
|
|
37 |
output_image(ndarray):Colored image of the original image |
|
|
38 |
""" |
|
|
39 |
|
|
|
40 |
#Image preprocessing |
|
|
41 |
#Since there is only one image to read, mode must be increased..I can't predict |
|
|
42 |
X = np.expand_dims(x, axis=0) |
|
|
43 |
preprocessed_input = X.astype('float32') |
|
|
44 |
# / 255.0 |
|
|
45 |
|
|
|
46 |
grad_model = models.Model([input_model.inputs], [input_model.get_layer(layer_name).output, input_model.output]) |
|
|
47 |
|
|
|
48 |
with tf.GradientTape() as tape: |
|
|
49 |
conv_outputs, predictions = grad_model(preprocessed_input) |
|
|
50 |
class_idx = np.argmax(predictions[0]) |
|
|
51 |
loss = predictions[:, class_idx] |
|
|
52 |
|
|
|
53 |
#Calculate the gradient |
|
|
54 |
output = conv_outputs[0] |
|
|
55 |
grads = tape.gradient(loss, conv_outputs)[0] |
|
|
56 |
|
|
|
57 |
gate_f = tf.cast(output > 0, 'float32') |
|
|
58 |
gate_r = tf.cast(grads > 0, 'float32') |
|
|
59 |
|
|
|
60 |
guided_grads = gate_f * gate_r * grads |
|
|
61 |
|
|
|
62 |
#Average the weights and multiply by the output of the layer |
|
|
63 |
weights = np.mean(guided_grads, axis=(0, 1)) |
|
|
64 |
cam = np.dot(output, weights) |
|
|
65 |
|
|
|
66 |
#Scale the image to the same size as the original image |
|
|
67 |
cam = cv2.resize(cam, IMAGE_SIZE, cv2.INTER_LINEAR) |
|
|
68 |
#Instead of ReLU |
|
|
69 |
cam = np.maximum(cam, 0) |
|
|
70 |
#Calculate heatmap |
|
|
71 |
heatmap = cam / cam.max() |
|
|
72 |
|
|
|
73 |
#Pseudo-color monochrome images |
|
|
74 |
jet_cam = cv2.applyColorMap(np.uint8(255.0*heatmap), cv2.COLORMAP_JET) |
|
|
75 |
#Convert to RGB |
|
|
76 |
rgb_cam = cv2.cvtColor(jet_cam, cv2.COLOR_BGR2RGB) |
|
|
77 |
#Combined with the original image |
|
|
78 |
output_image = (np.float32(rgb_cam) + x / 2) |
|
|
79 |
|
|
|
80 |
return output_image |
|
|
81 |
|
|
|
82 |
target_layer = 'concatenate_5' |
|
|
83 |
cam = grad_cam(model, x, target_layer) |
|
|
84 |
out_1=rgb2gray(z)*cam[:,:,0] |
|
|
85 |
out_2=rgb2gray(z)*cam[:,:,1] |
|
|
86 |
out_3=rgb2gray(z)*cam[:,:,2] |
|
|
87 |
out=np.stack((out_1,out_2,out_3),axis=2) |
|
|
88 |
out=out/255. |
|
|
89 |
|