File size: 4,652 Bytes
ddf40f2
f16f975
ddf40f2
 
 
719da84
ddf40f2
 
 
 
4a7b7f4
 
ddf40f2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f16f975
ddf40f2
 
 
 
 
 
f16f975
ddf40f2
 
 
 
 
f16f975
ddf40f2
 
f16f975
ddf40f2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f16f975
ddf40f2
 
 
f16f975
ddf40f2
 
 
 
 
 
 
f16f975
 
 
c32aaf3
 
f16f975
 
ddf40f2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import numpy as np
import tensorflow as tf
from tensorflow import keras
from keras.layers import Input , Lambda , Dense , Flatten , Rescaling
from keras.models import Model
import gradio as gr
# Display
from IPython.display import Image, display
import matplotlib.pyplot as plt
import matplotlib.cm as cm


##### Configureable variabels ###########
model_weights_path = "./model_weights.h5"

####################################################################
############       Creating new model  #############################
####################################################################
base_model = keras.applications.Xception(input_shape=(160,160,3) , include_top=False)
base_model.trainable = False

def create_model():
  input_layer = keras.Input(shape=(160,160,3))
  R1 = Rescaling(scale=1/255)(input_layer)
  B = base_model(R1 , training=False)
  P1 = keras.layers.GlobalAveragePooling2D()(B)
  output_layer = Dense(1 , activation="sigmoid")(P1)
  model = keras.Model(input_layer , output_layer)
  model.compile(optimizer=keras.optimizers.Adam(0.001) , loss=keras.losses.BinaryCrossentropy() , metrics=["accuracy"])
  return model , input_layer, R1 , B , P1 , output_layer
  
print("Creating new model ...")
model , input_layer , R1 , B , P1 , output_layer = create_model()
print("Loading weights ....")
model.load_weights(model_weights_path)

####################################################################
############     Creating gradcam model    #########################
####################################################################
def make_gradcam_heatmap(img_array, model):

    # we compute the gradient of the top predicted class for our input image
    # with respect to the activations of the last conv layer
    preds = None
    with tf.GradientTape() as tape:
        preds , last_conv_layer_output = grad_model(img_array)

    # This is the gradient of the output neuron (top predicted or chosen)
    # with regard to the output feature map of the last conv layer
    grads = tape.gradient(preds, last_conv_layer_output)

    # This is a vector where each entry is the mean intensity of the gradient
    # over a specific feature map channel
    pooled_grads = tf.reduce_mean(grads, axis=(0, 1, 2))

    # We multiply each channel in the feature map array
    # by "how important this channel is" with regard to the top predicted class
    # then sum all the channels to obtain the heatmap class activation
    last_conv_layer_output = last_conv_layer_output[0]
    heatmap = last_conv_layer_output @ pooled_grads[..., tf.newaxis]
    heatmap = tf.squeeze(heatmap)

    # For visualization purpose, we will also normalize the heatmap between 0 & 1
    heatmap = tf.maximum(heatmap, 0) / tf.math.reduce_max(heatmap)
    return preds , heatmap.numpy()
	
def get_gradcam(img, heatmap , alpha=0.4):

    # Rescale heatmap to a range 0-255
    heatmap = np.uint8(255 * heatmap)

    # Use jet colormap to colorize heatmap
    jet = cm.get_cmap("jet")

    # Use RGB values of the colormap
    jet_colors = jet(np.arange(256))[:, :3]
    jet_heatmap = jet_colors[heatmap]

    # Create an image with RGB colorized heatmap
    jet_heatmap = keras.utils.array_to_img(jet_heatmap)
    jet_heatmap = jet_heatmap.resize((img.shape[1], img.shape[0]))
    jet_heatmap = keras.utils.img_to_array(jet_heatmap)

    # Superimpose the heatmap on original image
    superimposed_img = jet_heatmap * alpha + img
    superimposed_img = keras.utils.array_to_img(superimposed_img)

    return superimposed_img

print("Creating Gradcam model ....")
grad_model = keras.Model(
        input_layer , [output_layer , B]
    )
grad_model.layers[-1].activation = None
grad_model.summary()

######################################################
def sigmoid(x):
    return 1 / (1 + np.exp(-x))
#######################################################
def predict_image(image):

    try:
      pred , heatmap = make_gradcam_heatmap(image.reshape((1, 160, 160, 3)) , grad_model)
      gradcam_image = get_gradcam(image , heatmap)

      pred = sigmoid(pred)
      predicted_label = f"{(1-pred[0][0])*100:.2f}% Dog \n{pred[0][0]*100:.2f}% Cat \nFinal Prediction : {'Dog' if pred[0][0] < 0.5 else 'Cat'}"
      
      # Return the predicted label
      return predicted_label , gradcam_image
    except Exception as error:
      return str(error)


image_input = gr.inputs.Image(shape=(160,160))
label_output = gr.outputs.Textbox(label="Prediction")
image_output = gr.outputs.Image(type="pil" , label="Heatmap")

# Create the Gradio interface
gr.Interface(fn=predict_image, inputs=image_input, outputs=[label_output , image_output]).launch()