我们用的model是vgg16
vgg16的下载地址:
其结构如下,可以看到我们input这个模型中的图片大小应该为224*224的:
这是我们要用到的原图:
运行代码如下:
from keras.applications.vgg16 import VGG16
from keras import backend as K
K.clear_session()
model = VGG16(weights='./vgg16_weights_tf_dim_ordering_tf_kernels.h5')
model.summary()
from keras.preprocessing import image
from keras.applications.vgg16 import preprocess_input, decode_predictions
import numpy as np
# 此处是导入你想处理的照片的地址(如果照片和vgg16文件还有你写的代码文件在同一个存储路径的话,此处只需要写照片的名称)
img_path = 'creative_commons_elephant.jpg'
# 此处的target_size只能是224*224的,因为vgg16模型的结构中,规定的导入图片的大小就是224*224的
img = image.load_img(img_path, target_size=(224, 224))
# 将图片信息转换为数组的形式
x = image.img_to_array(img)
# 为数组添加维度
x = np.expand_dims(x, axis=0)
x = preprocess_input(x)
#调用vgg16模型
preds = model.predict(x)
print('Predicted:', decode_predictions(preds, top=3)[0])
print(np.argmax(preds[0]))
#这行代码的解释是:大象这个图像分类位于vgg16这个模型中的第386个索引位置上
#也就是说如果你input的图像是其他的动物,这个386这个值你是需要自己去改的,就按照上面print(np.argmax(preds[0]))代码输出的值去改就可以了
african_elephant_output = model.output[:, 386]
# 看我上面的vgg16模型的结构图,这行代码意思是获取最后一个卷积层的信息(经过验证,获取最后一个卷积层的信息是最好的)
last_conv_layer = model.get_layer('block5_conv3')
grads = K.gradients(african_elephant_output, last_conv_layer.output)[0]
pooled_grads = K.mean(grads, axis=(0, 1, 2))
iterate = K.function([model.input], [pooled_grads, last_conv_layer.output[0]])
pooled_grads_value, conv_layer_output_value = iterate([x])
#这行代码我们可以理解为:获取最后一个卷积层的512个通道的信息,并把这些信息存储在一个列表里
for i in range(512):
conv_layer_output_value[:, :, i] *= pooled_grads_value[i]
#此处是导入matplotlib模块如果不成功的话,你可以按照这三行代码来import matpotlib
import matplotlib
matplotlib.use('Agg')
from matplotlib import pyplot as plt
#这里你可以理解为是取倒数第二层的那512个通道信息的均值
heatmap = np.mean(conv_layer_output_value, axis=-1)
#这里你可以print一下heatmap,会输出14个数组,每个数组有14个元素
print(heatmap)
输出应该是这样的:
#这三行代码你运行出来,应该是能看到一张14*14的图片
plt.matshow(heatmap)
plt.savefig('bob1.png')
plt.show()
由此我们可以得知:倒数第二层的那512个通道的信息取均值,输出14个数组,每个数组有14个元素,就代表一个14*14的图片,图片的每一个小格子代表数组中的每一个元素
#这两行代码的意思是:取14*14 这192个数字中的最大值,然后每个数字除以这个最大值。
heatmap = np.maximum(heatmap, 0)
heatmap /= np.max(heatmap)
#这三行代码的意思是把数组转换为图片输出,图片的名字你自己定
plt.matshow(heatmap)
plt.savefig('bob.png')
plt.show()
import cv2
# 用cv2导入我们上面的热图
img = cv2.imread(img_path)
# 将热图变成和原图一样的大小
heatmap = cv2.resize(heatmap, (img.shape[1], img.shape[0]))
heatmap = np.uint8(255 * heatmap)
# 将热图和原图重叠在一起
heatmap = cv2.applyColorMap(heatmap, cv2.COLORMAP_JET)
superimposed_img = heatmap * 0.4 + img
# 保存最后的结果图,图片名字你自己定
cv2.imwrite('23.jpg', superimposed_img)
最后的结果图,应该是这样:
希望你能做出这张好看的热力图。
P.S.推荐阅读,这里面有制作热力图的详细英文介绍
下面是一篇相关文献,推荐阅读