-
Notifications
You must be signed in to change notification settings - Fork 2
/
gradSeg.py
166 lines (139 loc) · 5.87 KB
/
gradSeg.py
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
import tensorflow as tf
from PIL import Image
from keras_applications import imagenet_utils
from base_models.ICAU_5_5_edge import *
from base_models.ICAU import *
import PIL.Image
import numpy as np
import cv2
from keras_applications import imagenet_utils
import glob
import os
# Display
from IPython.display import Image, display
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import argparse
def self_balanced_focal_loss(alpha=3, gamma=2.0):
"""
Originally Implemented by @luyanger1799 [GitHub]
"""
def loss(y_true, y_pred):
y_pred = backend.softmax(y_pred, -1)
cross_entropy = backend.categorical_crossentropy(y_true, y_pred)
sample_weights = backend.max(backend.pow(1.0 - y_pred, gamma) * y_true, axis=-1)
# class weights
pixel_rate = backend.sum(y_true, axis=[1, 2], keepdims=True) / backend.sum(backend.ones_like(y_true),
axis=[1, 2], keepdims=True)
class_weights = backend.max(backend.pow(backend.ones_like(y_true) * alpha, pixel_rate) * y_true, axis=-1)
# final loss
final_loss = class_weights * sample_weights * cross_entropy
return backend.mean(backend.sum(final_loss, axis=[1, 2]))
return loss
def get_img_array(img_path, size):
img = tf.keras.utils.load_img(img_path, target_size=size)
# `array` is a float32 Numpy array of shape (299, 299, 3)
array = tf.keras.utils.img_to_array(img)
# We add a dimension to transform our array into a "batch"
array = np.expand_dims(array, axis=0)
return array
def make_gradcam_heatmap(img_array, model, last_conv_layer_name,idx1,idx2):
grad_model = tf.keras.models.Model(
[model.inputs], [model.get_layer(last_conv_layer_name).output, model.output])
with tf.GradientTape() as tape:
last_conv_layer_output, preds = grad_model(img_array)
class_channel = preds[0][idx1][idx2][1]
grads = tape.gradient(class_channel, last_conv_layer_output)
pooled_grads = tf.reduce_mean(grads, axis=(0, 1, 2))
last_conv_layer_output = last_conv_layer_output[0]
heatmap = last_conv_layer_output @ pooled_grads[..., tf.newaxis]
heatmap = tf.squeeze(heatmap)
heatmap = tf.maximum(heatmap, 0) / tf.math.reduce_max(heatmap)
return heatmap.numpy()
def save_and_display_gradcam(img_path, heatmap, cam_path="cam.jpg", alpha=1):
# Load the original image
img = tf.keras.utils.load_img(img_path)
img = tf.keras.utils.img_to_array(img)
# 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 = tf.keras.utils.array_to_img(jet_heatmap)
jet_heatmap = jet_heatmap.resize((img.shape[1], img.shape[0]))
jet_heatmap = tf.keras.utils.img_to_array(jet_heatmap)
# Superimpose the heatmap on original image
superimposed_img = jet_heatmap * alpha + img
superimposed_img = tf.keras.utils.array_to_img(superimposed_img)
# Save the superimposed image
superimposed_img.save(cam_path)
def get_cord(img):
"""
#Identifying the centroid coordinates.
"""
points = []
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 100, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
cont, hier = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
for c in cont:
extLeft = tuple(c[c[:, :, 0].argmin()][0])
extRight = tuple(c[c[:, :, 0].argmax()][0])
extTop = tuple(c[c[:, :, 1].argmin()][0])
extBot = tuple(c[c[:, :, 1].argmax()][0])
output = cv2.connectedComponentsWithStats(thresh, 4, cv2.CV_32S)
(numLabels, labels, stats, centroids) = output
for i in range(1, numLabels):
(cX, cY) = centroids[i]
points.append((cX,cY))
return points
parser = argparse.ArgumentParser()
parser.add_argument("-m", "--model_dir", help="Path to the h5 model file")
parser.add_argument("-i", "--img_dir", help="path to image data")
args = parser.parse_args()
model = keras.models.load_model(args.model_dir,
custom_objects={'loss':self_balanced_focal_loss(alpha=3, gamma=2.0),
'InpaintContextAttentionUnit':InpaintContextAttentionUnit,
'InpaintContextAttentionUnit5edge':InpaintContextAttentionUnit5edge})
def load_img(name):
img = PIL.Image.open(name)
return np.array(img)
def decode_one_hot(one_hot_map):
return np.argmax(one_hot_map, axis=-1)
#image directory
path = args.img_dir
images = list(glob.glob(path+"*.png"))
img_size = (256, 448)
last_conv_layer_name = "block5_conv4"
if not os.path.exists("outSegGrad/"):
os.mkdir("outSegGrad/")
for file in images:
image = cv2.resize(load_img(file), dsize=(448,256))
image = imagenet_utils.preprocess_input(image.astype(np.float32), data_format='channels_last', mode='torch')
if np.ndim(image) == 3:
image = np.expand_dims(image, axis=0)
assert np.ndim(image) == 4
prediction = model.predict(image)
if np.ndim(prediction) == 4:
pred_norm = np.squeeze(prediction, axis=0)
pred_norm = decode_one_hot(pred_norm)
rows, cols = np.where(pred_norm==1)
if(len(rows)!=0):
p1 = (rows[0],cols[0])
p2 = (rows[len(rows)-1],cols[len(cols)-1])
p3 = (round((rows[0]+rows[len(rows)-1])/2),round((cols[0]+cols[len(cols)-1])/2))
pairs = [p1,p2,p3]
img_array = image
model = model
netmap = np.zeros((16,28))
# Generate class activation heatmap
for pair in pairs:
heatmap = make_gradcam_heatmap(img_array, model, last_conv_layer_name,pair[0],pair[1])
netmap+=heatmap
netmap/=len(pairs)
save_and_display_gradcam(file,netmap, cam_path = "outSegGrad/"+os.path.basename(file))
else:
#No predictions generated
continue