在OpenCV中可视化图像上的热图矩阵

时间:2019-05-23 12:43:22

标签: python opencv keras heatmap cv2

我的Python程序中有一个(float32)热图矩阵,如下所示:

[[0.99782705 0.99782705 0.99782705 0.99782705 0.99782705 0.99782705
  0.99782705 0.99782705 0.99782705]
 [0.99782705 0.99782705 0.99782705 0.99782705 0.99782705 0.99782705
  0.99782705 0.99782705 0.99782705]
 [0.99782705 0.99782705 0.99782705 0.99782705 0.99782705 0.99782705
  0.99782705 0.99782705 0.99782705]
 [0.99782705 0.99782705 0.99782705 0.99782705 0.99782705 0.99782705
  0.99782705 0.99782705 0.99782705]
 [0.99782705 0.99782705 0.99782705 0.99782705 0.99782705 0.99782705
  0.99919313 0.99782705 0.99782705]
 [0.99782705 0.99782705 0.99782705 0.99782705 0.99782705 0.99782705
  1.         0.99782705 0.99782705]
 [0.99782705 0.99782705 0.99782705 0.99782705 0.99782705 0.99782705
  0.99782705 0.99782705 0.99782705]
 [0.99782705 0.99782705 0.99782705 0.99782705 0.99782705 0.99782705
  0.99782705 0.99782705 0.99782705]
 [0.99782705 0.99782705 0.99782705 0.99782705 0.99782705 0.99782705
  0.99782705 0.99782705 0.99782705]]

以下是通过matplotlib.pyplot.matshow()打印时的热图外观:

Heatmap matrix in its original size

现在,我想将该矩阵的大小调整为图像的大小,并将其作为热图覆盖在该图像上。因此,首先我加载另一张图片,然后将热图调整为图片大小:

img = cv2.imread(image_path)
heatmap = cv2.resize(heatmap, (img.shape[1], img.shape[0]))

调整热图矩阵的大小后,将变为:

Heatmap matrix resized

好,到目前为止,一切看起来都不错。现在,根据我在网上找到的各种资源,我想将该热图转换为uint8 RGB格式,应用cv2.COLORMAP_JET色彩图,并将其覆盖到原始图像上:

heatmap = cv2.applyColorMap(np.uint8(255 * heatmap), cv2.COLORMAP_JET)
superimposed = heatmap * 0.4 + img

但这似乎不起作用。当我现在通过cv2.imshow('Heatmap', heatmap)渲染热图时,它变成了普通的(红色)图像,它失去了原始热图的所有“功能”。因此,我要放置热图的图像也保持与以前相同(即渲染superimposed的外观与img完全一样)。

有什么主意我可能会在这里错过吗?

对于其他记录,我想实现以下类似功能:
Grad-CAM implementation for Keras models

PS:Full working example here

1 个答案:

答案 0 :(得分:2)

如果用于可视化,则需要在数字之间进行更大的分隔。您基本上有3个数字,并且在缩放它们(乘以255)时,它们基本上变成了2个数字(254和255)。当应用颜色时,两个数字几乎相同,而且真的很难知道哪个是哪个...

解决方案:

使用当前数字创建新的比例。您可以使用cv2.normalize

轻松做到这一点
import matplotlib.pyplot as plt
import numpy as np
import cv2

heatmap = np.array([
    [0.99782705,0.99782705,0.99782705,0.99782705,0.99782705,0.99782705,0.99782705,0.99782705,0.99782705],
    [0.99782705,0.99782705,0.99782705,0.99782705,0.99782705,0.99782705,0.99782705,0.99782705,0.99782705],
    [0.99782705,0.99782705,0.99782705,0.99782705,0.99782705,0.99782705,0.99782705,0.99782705,0.99782705],
    [0.99782705,0.99782705,0.99782705,0.99782705,0.99782705,0.99782705,0.99782705,0.99782705,0.99782705],
    [0.99782705,0.99782705,0.99782705,0.99782705,0.99782705,0.99782705,0.99919313,0.99782705,0.99782705],
    [0.99782705,0.99782705,0.99782705,0.99782705,0.99782705,0.99782705,1.00000000,0.99782705,0.99782705],
    [0.99782705,0.99782705,0.99782705,0.99782705,0.99782705,0.99782705,0.99782705,0.99782705,0.99782705],
    [0.99782705,0.99782705,0.99782705,0.99782705,0.99782705,0.99782705,0.99782705,0.99782705,0.99782705],
    [0.99782705,0.99782705,0.99782705,0.99782705,0.99782705,0.99782705,0.99782705,0.99782705,0.99782705]
])

heatmap = cv2.resize(heatmap, (400,300))
plt.matshow(heatmap)
plt.show()
heatmapshow = None
heatmapshow = cv2.normalize(heatmap, heatmapshow, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)
heatmapshow = cv2.applyColorMap(heatmapshow, cv2.COLORMAP_JET)
cv2.imshow("Heatmap", heatmapshow)
cv2.waitKey(0)

您会得到:

enter image description here

注意:由于我没有示例图片,因此我只是将数字放入调整大小中。

但是,这里有一件事情要考虑。使用此解决方案,无论数量有多小,最大的数字都会是红色。如果您需要一个新的固定缩放比例(例如1.红色,而0是最小数字),则需要手动执行以下操作:

newvalue= (maxNew-minNew)/(max-min)*(value-max)+maxNew

其中maxNew= 255minNew=0以及max和min将由您任意决定(例如0.9978和1.0)