In [1]:
# extract data from heatmaps
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
In [2]:
img = cv.imread("images/heatmap.png")
In [3]:
img.shape
Out[3]:
In [4]:
# approximate bounding box around the legend
legend_box = [335, 351, 32, 254] # [xmin, xmax, ymin, ymax]
# calibrate legend with data
legend_data = [5, 20] # [val1, val2]
legend_data_px = [(344,216), (344,80)] # [(x,y), (x,y)]
legend_data_px = [(legend_data_px[0][0] - legend_box[0], legend_data_px[0][1] - legend_box[2]),
(legend_data_px[1][0] - legend_box[0], legend_data_px[1][1] - legend_box[2])]
# crop
legend_img = img[legend_box[2]:legend_box[3], legend_box[0]:legend_box[1]]
plt.imshow(cv.cvtColor(legend_img, cv.COLOR_BGR2RGB))
Out[4]:
Assume:
1. approx_val = f(R,G,B)
At calibration points:
2. val1 = f(R1,G1,B1) at (x1,y1)
3. val2 = f(R2,G2,B2) at (x2,y2)
At any (x_l,y_l) on the legend:
4. val_l = f(R,G,B) at (x_l,y_l)
If we assume (x_l,y_l) lies on the line joining (x1,y1) and (x2,y2), then val can be calculated at any (x_l,y_l) assuming linear spacing.
In [5]:
# Plot intensity along the legend "line":
ylist = [v for v in range(0,legend_img.shape[0])]
intensity = np.sqrt([legend_img[y,12,0]**2 + legend_img[y,12,1]**2 + legend_img[y,12,2]**2 for y in ylist])
plt.plot(ylist, intensity)
Out[5]:
In [6]:
# find edges
intensity_jumps = [intensity[i]-intensity[i-1] > 10 for i in range(1,len(intensity))]
intensity_jumps = np.array([j for j in range(0,len(intensity_jumps)) if intensity_jumps[j] == True])
intensity_jumps
Out[6]:
In [7]:
# for smooth legend, it's easy to pick the pick min, max:
# |----|---------x----------|----|----
# i_min mid-pt i_max
i_max = np.min(intensity_jumps[intensity_jumps - len(intensity)/2 > 0]) - 1
i_min = np.max(intensity_jumps[intensity_jumps - len(intensity)/2 < 0]) + 1
print(i_min, i_max)
In [10]:
# build a list of (r,g,b)->val
rgb_list = [(legend_img[y,12,0], legend_img[y,12,1], legend_img[y,12,2]) for y in range(i_min,i_max)]
val_list = [(legend_data[1] - legend_data[0])*(y - legend_data_px[0][1])/(legend_data_px[1][1] - legend_data_px[0][1]) + legend_data[0] for y in range(i_min,i_max)]
val_list
Out[10]:
In [17]:
# do extraction by finding nearest value and calculate error
def valForRGB(r,g,b):
return val_list[np.argmin(np.array([(c[0]-r)**2 + (c[1]-g)**2 + (c[2]-b)**2 for c in rgb_list]))]
results = []
for xi in range(125,300,43):
for yi in range(56,232,43):
(r,g,b) = (img[yi,xi,0], img[yi,xi,1], img[yi,xi,2])
results.append((xi,yi,valForRGB(r,g,b)))
In [18]:
results
Out[18]:
In [ ]: