0

I want to use GradCAM activation to infer the obeject location on the image, it is not really a problem if there is only one contour heatmap since I can simply use argmax to get that. But I want to be able to grab more than one heatmap hoping that with more than one heatmap we can point the location more accurately.
Here is the example

import matplotlib.pyplot as plt
activation_map = [[0.0724, 0.0615, 0.0607, 0.0710, 0.0000, 0.0000, 0.0154],
        [0.1111, 0.0835, 0.0923, 0.0409, 0.0000, 0.0000, 0.0000],
        [0.0986, 0.0860, 0.1138, 0.0706, 0.0144, 0.0000, 0.0000],
        [0.1134, 0.1109, 0.2244, 0.3414, 0.2652, 0.2708, 0.1664],
        [0.1165, 0.1620, 0.5605, 0.7064, 0.4593, 0.6628, 0.6103],
        [0.0852, 0.2324, 1.0000, 0.8605, 0.5095, 0.8457, 0.8332],
        [0.0349, 0.2422, 0.9287, 0.5717, 0.2054, 0.4749, 0.6983]]
plt.imshow(activation_map)

enter image description here

After I rescale this activation map to proper scaling it looks something like this

import cv2
activation_map_resized = cv2.resize(np.array(activation_map), (64, 64))
plt.imshow(activation_map_resized)

enter image description here

I want to be able to get the point around (22, 50) and (55, 50).

Any method I can use to find the center of that two contour heatmap efficiently? I can imagine using gradient or some clustering, but I'm not sure if it is the most effiient method to use.

desertnaut
  • 57,590
  • 26
  • 140
  • 166
wanburana
  • 157
  • 1
  • 9

1 Answers1

1

What you are looking for is called peak detection, in your case you'll have to threshold the data first as the gradient has some "low" peaks in it that you would like to ignore

import numpy as np
from scipy.ndimage.filters import maximum_filter
from scipy.ndimage.morphology import generate_binary_structure, binary_erosion
import matplotlib.pyplot as pp

def detect_peaks(image):
    neighborhood = generate_binary_structure(2,2)
    local_max = maximum_filter(image, footprint=neighborhood)==image
    background = (image==0)
    eroded_background = binary_erosion(background, structure=neighborhood, border_value=1)
    detected_peaks = local_max ^ eroded_background
    return detected_peaks


activation_map = np.array([[0.0724, 0.0615, 0.0607, 0.0710, 0.0000, 0.0000, 0.0154],
                           [0.1111, 0.0835, 0.0923, 0.0409, 0.0000, 0.0000, 0.0000],
                           [0.0986, 0.0860, 0.1138, 0.0706, 0.0144, 0.0000, 0.0000],
                           [0.1134, 0.1109, 0.2244, 0.3414, 0.2652, 0.2708, 0.1664],
                           [0.1165, 0.1620, 0.5605, 0.7064, 0.4593, 0.6628, 0.6103],
                           [0.0852, 0.2324, 1.0000, 0.8605, 0.5095, 0.8457, 0.8332],
                           [0.0349, 0.2422, 0.9287, 0.5717, 0.2054, 0.4749, 0.6983]])

#Thresholding - remove this line to expose "low" peaks
activation_map[activation_map<0.3] = 0
detected_peaks = detect_peaks(activation_map)
pp.subplot(4,2,1)
pp.imshow(activation_map)
pp.subplot(4,2,2)
pp.imshow(detected_peaks)
pp.show()

Reference/more detailed info about peak detection: Peak detection in a 2D array

Black0ut
  • 1,642
  • 14
  • 28
  • thank you, I have tried it and it worked, will look into it further. also thank for the additional resources! – wanburana Oct 14 '21 at 10:12