【问题标题】:Visualizing a heatmap matrix on to an image in OpenCV在 OpenCV 中将热图矩阵可视化到图像上
【发布时间】:2019-10-10 01:05:34
【问题描述】:

我的 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() 打印时热图的样子:

现在我想将该矩阵调整为图像的大小,并将其作为热图覆盖到该图像上。所以首先我加载另一个图像并将热图调整为图像大小:

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

调整热图矩阵大小后变成这样:

好的,到目前为止一切看起来都很好。现在,根据我在网上找到的各种资源,我想将该热图转换为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

【问题讨论】:

  • 请发布一个工作示例,包括“导入”行的完整代码,这样我们就可以重现错误,而不必猜测您的代码是做什么的。
  • 所以基本上用你的数字你会得到 3 个值 -> 254.4458 、 254.7942 和 255 然后 uint8 会将它们转换为 254 和 255,颜色映射更像是一个查找表,并且会给你几乎相同的颜色给它。现在,您可以尝试使用 cv2.normalize,这会将第一个数字设为 0,最后一个数字设为 255,中间的数字介于两者之间,如果您愿意,我可以举个例子
  • @L.C.完成,你可以在这里找到它:pastebin.com/YUmPCy1Y

标签: python opencv keras heatmap cv2


【解决方案1】:

如果是为了可视化,您需要在数字之间进行更大的分隔。你基本上有 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)

你会得到:

注意:我只是在调整大小中输入了数字,因为我没有示例图像。

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

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

maxNew= 255minNew=0 以及 max 和 min 将是您任意决定的值(例如 0.9978 和 1.0)

【讨论】:

  • 谢谢,帮了大忙。还有两个问题:1)当我将热图应用于原始图像时,从蓝色到红色的“渐变”(如上面的屏幕截图所示)会反转,即现在它是从红色到蓝色 - 但为什么呢? 2)有没有一种简单的方法可以摆脱热图所在区域的“硬”(水平和垂直)边界?这是我使用您的更改创建的图像示例:imgur.com/a/dFx1dKb
  • @Matthias 2) 因为它来自一个小图像,所以它的边缘会有点方形......但是在混合之前可以模糊(例如高斯)图像。 1)如果你在你的帖子中使用superimposed = heatmap * 0.4 + img,那么它是uint8的溢出......试试superimposed = heatmap * 0.4 + img * 0.6这将确保它保持在界限内
  • 仅作记录:我剩下的两个问题都已通过将heatmap = cv2.applyColorMap(np.uint8(255 * heatmap), cv2.COLORMAP_JET) 替换为heatmap = cv2.applyColorMap(np.uint8(255 * (255 - heatmap)), cv2.COLORMAP_JET) 来解决。
猜你喜欢
  • 2012-01-19
  • 2020-06-08
  • 1970-01-01
  • 1970-01-01
  • 2014-06-16
  • 1970-01-01
  • 2020-03-26
  • 2021-08-27
相关资源
最近更新 更多