Keras gradCAM
#######a
加载有权重的模型
model = resnet_18_res2net(input_shape=(256, 256, 1), nclass=2)
print(model.summary())
model.compile(keras.optimizers.Adam(lr=0.0001), loss='categorical_crossentropy', metrics=['accuracy'])
model_path = "train_weights/"
model.load_weights(os.path.join(model_path, "resnet_18_res2net.h5"))#resnet18_se
#####输入图像
image = np.array(Image.open('C:/Users/xian/Desktop/grad_CAM/2.bmp').convert("L"))#RGB
image = np.expand_dims(image, axis=0)
image = np.expand_dims(image, axis=-1)
image = image.astype('float32') / 255
print(image.shape)
###调用函数
cam,heatmap=grad_cam(model,image,1,'concatenate_5')# conv5_block16_concat concatenate_5
#叠加在原图上
print(cam.shape)
image_s = np.array(Image.open('C:/Users/xian/Desktop/grad_CAM/2.bmp').convert("RGB"))#RGB
print(image_s.shape)
img_add = cv2.addWeighted(image_s, 0.7, cam, 0.3, 0)
plt.figure("cam")
plt.imshow(cam)
plt.show()
cv2.imwrite('C:/Users/xian/Desktop/grad_CAM/2_cam.jpg', cam)
####计算CAM的函数
def grad_cam(model, x, category_index, layer_name):
"""
Args:
model: model
x: image input
category_index: category index
layer_name: last convolution layer name
"""
# 取得目标分类的CNN输出值,也就是loss
class_output = model.output[:, category_index]
print(class_output)
# 取得想要算出梯度的层的输出
convolution_output = model.get_layer(layer_name).output
print(convolution_output)
# 利用gradients函数,算出梯度公式
grads = K.gradients(class_output, convolution_output)[0]
print(grads)
# 定义计算函数(tensorflow的常见做法,与一般开发语言不同,先定义计算逻辑图,之后一起计算。)
gradient_function = K.function([model.input], [convolution_output, grads])
print("开始问题")
print(x.shape)
# 根据实际的输入图像得出梯度张量(返回是一个tensor张量,VGG16 是一个7X7X512的三维张量)
output, grads_val = gradient_function([x])
print("输出")
print(output)
print("梯度")
print(grads_val)
output, grads_val = output[0], grads_val[0]
# 取得所有梯度的平均值(维度降低:7X7X512 -> 512)
weights = np.mean(grads_val, axis=(0, 1))
# 把所有平面的平均梯度乘到最后卷积层(vgg16最后一层是池化层)上,得到一个影响输出的梯度权重图
cam = np.dot(output, weights)
# 把梯度权重图RGB化
cam = cv2.resize(cam, (x.shape[1], x.shape[2]), cv2.INTER_LINEAR)
cam = np.maximum(cam, 0)
heatmap = cam / np.max(cam)
# Return to BGR [0..255] from the preprocessed image
image_rgb = x[0, :]
image_rgb -= np.min(image_rgb)
image_rgb = np.minimum(image_rgb, 255)
cam = cv2.applyColorMap(np.uint8(255 * heatmap), cv2.COLORMAP_JET)
cam = np.float32(cam) + np.float32(image_rgb)
cam = 255 * cam / np.max(cam)
return np.uint8(cam), heatmap