Визуализация матрицы тепловых карт на изображение в OpenCV - PullRequest
2 голосов
/ 23 мая 2019

У меня есть (float32) матрица тепловой карты в моей программе на Python, например:

[[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 для моделей Keras

PS: Полный рабочий пример здесь

1 Ответ

2 голосов
/ 23 мая 2019

Если это для визуализации, вам нужно будет сделать большее разделение между числами. У вас есть в основном 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= 255 и minNew=0, а также max и min - это то, что вы произвольно решите (например, 0.9978 и 1.0)

...