为了关注得到的feature map中是否在ROI有比较大的值,常需要将attention map可视化,将其与输入图片叠加,可以非常直观的看到空间中的权重分布。为达到题图效果,可以使用opencv实现。
代码如下
import matplotlib as mpl
# we cannot use remote server's GUI, so set this
mpl.use('Agg')
import matplotlib.pyplot as plt
from matplotlib import cm as CM
from PIL import Image
import h5py
import numpy as np
import cv2img_path = "/home/datamining/Datasets/CrowdCounting/shanghai/part_A_final/test_data/images/IMG_54.jpg"
img = cv2.imread(img_path)
# adaptive gaussian filter
adaptive = h5py.File(img_path.replace('.jpg','.h5').replace('images','ground_truth'),'r')
adaptive = np.asarray(adaptive['density'])
heatmap = adaptive/np.max(adaptive)
# must convert to type unit8
heatmap = np.uint8(255 * heatmap)
heatmap = cv2.applyColorMap(heatmap, cv2.COLORMAP_JET)
superimposed_img1 = heatmap*0.9+img
# fixed gaussian filter
fixed = h5py.File(img_path.replace('shanghai','shanghaitech_fixed').replace('.jpg','.h5').replace('images','ground_truth'),'r')
fixed = np.asarray(fixed['density'])
heatmap = fixed/np.max(fixed)
heatmap = np.uint8(255 * heatmap)
heatmap = cv2.applyColorMap(heatmap, cv2.COLORMAP_JET)
superimposed_img2 = heatmap*0.9+img
imgs = np.hstack([img, superimposed_img1,superimposed_img2])cv2.imwrite('figs/superimposed_img.jpg', imgs)
使用opencv得到图片img,从h5文件中得到对该图中人头的标注热力图,此处可将其视为attention map,距离人头中心越近,值越大。
使用np.asarray将其转换为ndarray,除以最大值将其归一化,归一化不可缺少,否则可能图片中像素值过小,几乎全是蓝色的区域。再将归一化之后取值为[0,1]的ndarray乘255转化为np.unit8格式,因为下一步的输入必须是这个格式。
最重要的是cv2.applyColorMap(heatmap, cv2.COLORMAP_JET),将np.unit8格式的矩阵转化为colormap,第二个参数有很多种配色方案,上面这个是最常用的蓝红配色,值越小越接近蓝色,越大越接近红色。
此处也可以直接将读取的图片转为colormap,例如
img = cv2.imread(img_path)
heatmap = cv2.applyColorMap(img, cv2.COLORMAP_JET)
cv2.imwrite('figs/heatmap.jpg', heatmap)
将img和heatmap加权,权重取0.9感觉比较合适(如果取1会变成奇怪的黄色)。
将原图和叠加了attention map的图像使用np.hstack()并列显示,此处由于我有两个不同的attention map所以共有3张图片。吐槽一下cv2同时显示多张图片不如plt方便。
最后得到的并列图像如下图
如果只显示最右侧的那一张就是题图: