Deep Learning with python中Grad-CAM代码详解

Deep Learning with python中Grad-CAM代码详解

#关于CAM与Grad-CAM原理性内容可参考``https://bindog.github.io/blog/2018/02/10/model-explanation/我觉得这篇文章写的非常仔细,也很好理解,在这里就不再啰嗦,直接上代码。

from keras.applications.vgg16 import VGG16
from keras.preprocessing import image
from keras.applications.vgg16 import preprocess_input, decode_predictions
from keras import backend as K
import numpy as np
import cv2
model = VGG16(weights='imagenet')#这个网络比较大,下载需要花费些时间
model.summary()
 
img_path = '21.png'
 
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)  
 
african_elephant_output = model.output[:, 386] 
#print(model.output[:,386])
 
last_conv_layer = model.get_layer('block5_conv3') 
'''last_conv_layer : <keras.layers.convolutional.Conv2D object at 0x000001F0B37F05F8>、
   最后一个卷积层:输出形状(None, 14, 14, 512)
'''
 
grads = K.gradients(african_elephant_output, last_conv_layer.output)[0]  
'''grad: 由于没有输入,所以第一维值为?(?, 14, 14, 512)'''
 
pooled_grads = K.mean(grads, axis=(0, 1, 2))
'''grad一共有四维,k.mean求的是除了0,1,2这三维,沿着第四维的平均值
pooled_grads形状(512,)
'''

############此处位置都没有输入图像,所以grads,pooled_grads第一维都是? 
iterate = K.function([model.input], [pooled_grads, last_conv_layer.output[0]]) 
'''定义一个function类
   输入:[model.input] 大小(?,224,224,3)
   输出:[pooled_grads, last_conv_layer.output[0]]列表数组元素
   pooled_grads : <tf.Tensor 'Mean_9:0' shape=(512,) dtype=float32>
   last_conv_layer.output[0] :
       <tf.Tensor 'strided_slice_32:0' shape=(14, 14, 512) dtype=float32>
'''
 
pooled_grads_value, conv_layer_output_value = iterate([x]) 
'''实例化类,输入[x]之前预处理好的图像tensor,输出21.png的
pooled_grads_value(输出关于特征图每个像素值偏导数的平均和,也就是Grad-CAM算法中要求的权重)
conv_layer_output_value(对应于权重的特征图,方便之后求热图)
'''
 
for i in range(512):
    conv_layer_output_value[:, :, i] *= pooled_grads_value[i] 
'''将对应权重与特征图相乘相加,见Grad-CAM算法(14,14,512)'''
 
heatmap = np.mean(conv_layer_output_value, axis=-1)
'''沿着最后一个维度求平均值(14,14)''' 
 
heatmap = np.maximum(heatmap,0)
''' heatmap与0比较,取其大者'''
 
heatmap /= np.max(heatmap)
'''将heatmap中的像素值归一化'''
 
img = cv2.imread(img_path) 
 
heatmap = cv2.resize(heatmap, (img.shape[1], img.shape[0]))  
'''resize到与原始图像一样大'''
 
heatmap = np.uint8(255 * heatmap)  
 
heatmap = cv2.applyColorMap(heatmap, cv2.COLORMAP_JET)
'''将数组转化为图片的形式'''
  
cv2.imwrite('22.jpg', heatmap)  
 
superimposed_img = heatmap * 0.4 + img    
 
cv2.imwrite('23.jpg', superimposed_img) 

原始图像如下原图
热图
热图与原始图叠加的效果

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值