PanMatch-demo / utils /visualization.py
yumeng313's picture
Upload folder using huggingface_hub
c6147a7 verified
Raw
History Blame Contribute Delete
7.38 kB
import numpy as np
import torch
def disp_color_func(disp):
"""
Based on color histogram, convert the gray disp into color disp map.
The histogram consists of 7 bins, value of each is e.g. [114.0, 185.0, 114.0, 174.0, 114.0, 185.0, 114.0]
Accumulate each bin, named cbins, and scale it to [0,1], e.g. [0.114, 0.299, 0.413, 0.587, 0.701, 0.886, 1.0]
For each value in disp, we have to find which bin it belongs to
Therefore, we have to compare it with every value in cbins
Finally, we have to get the ratio of it accounts for the bin, and then we can interpolate it with the histogram map
For example, 0.780 belongs to the 5th bin, the ratio is (0.780-0.701)/0.114,
then we can interpolate it into 3 channel with the 5th [0, 1, 0] and 6th [0, 1, 1] channel-map
Inputs:
disp: numpy array, disparity gray map in (Height * Width, 1) layout, value range [0,1]
Outputs:
disp: numpy array, disparity color map in (Height * Width, 3) layout, value range [0,1]
"""
map = np.array([
[0, 0, 0, 114],
[0, 0, 1, 185],
[1, 0, 0, 114],
[1, 0, 1, 174],
[0, 1, 0, 114],
[0, 1, 1, 185],
[1, 1, 0, 114],
[1, 1, 1, 0]
])
# grab the last element of each column and convert into float type, e.g. 114 -> 114.0
# the final result: [114.0, 185.0, 114.0, 174.0, 114.0, 185.0, 114.0]
bins = map[0:map.shape[0] - 1, map.shape[1] - 1].astype(float)
# reshape the bins from [7] into [7,1]
bins = bins.reshape((bins.shape[0], 1))
# accumulate element in bins, and get [114.0, 299.0, 413.0, 587.0, 701.0, 886.0, 1000.0]
cbins = np.cumsum(bins)
# divide the last element in cbins, e.g. 1000.0
bins = bins / cbins[cbins.shape[0] - 1]
# divide the last element of cbins, e.g. 1000.0, and reshape it, final shape [6,1]
cbins = cbins[0:cbins.shape[0] - 1] / cbins[cbins.shape[0] - 1]
cbins = cbins.reshape((cbins.shape[0], 1))
# transpose disp array, and repeat disp 6 times in axis-0, 1 times in axis-1, final shape=[6, Height*Width]
ind = np.tile(disp.T, (6, 1))
tmp = np.tile(cbins, (1, disp.size))
# get the number of disp's elements bigger than each value in cbins, and sum up the 6 numbers
b = (ind > tmp).astype(int)
s = np.sum(b, axis=0)
bins = 1 / bins
# add an element 0 ahead of cbins, [0, cbins]
t = cbins
cbins = np.zeros((cbins.size + 1, 1))
cbins[1:] = t
# get the ratio and interpolate it
disp = (disp - cbins[s]) * bins[s]
disp = map[s, 0:3] * np.tile(1 - disp, (1, 3)) + map[s + 1, 0:3] * np.tile(disp, (1, 3))
return disp
def gen_disp_error_colormap():
"""
format:[[min_error<= this_error<=max_error, RGB],
[min_error<= this_error<=max_error, RGB],
...
[min_error<= this_error<=max_error, RGB],]
unit: pixel
"""
cols = np.array(
[[0 / 3.0, 0.1875 / 3.0, 49, 54, 149],
[0.1875 / 3.0, 0.375 / 3.0, 69, 117, 180],
[0.375 / 3.0, 0.75 / 3.0, 116, 173, 209],
[0.75 / 3.0, 1.5 / 3.0, 171, 217, 233],
[1.5 / 3.0, 3 / 3.0, 224, 243, 248],
[3 / 3.0, 6 / 3.0, 254, 224, 144],
[6 / 3.0, 12 / 3.0, 253, 174, 97],
[12 / 3.0, 24 / 3.0, 244, 109, 67],
[24 / 3.0, 48 / 3.0, 215, 48, 39],
[48 / 3.0, np.inf, 165, 0, 38]], dtype=np.float32)
cols[:, 2: 5] /= 255.
return cols
error_colormap = gen_disp_error_colormap()
def disp_error_image_func(D_est_tensor, D_gt_tensor, abs_thres=3., rel_thres=0.05, dilate_radius=1):
"""
D_est_tensor: estimated disparity, BHW
D_gt_tensor: ground-truth disparity, BHW
abs_thres: abs(D_est - D_gt) > abs_thres? outliers : zeros
"""
D_gt_np = D_gt_tensor.detach().cpu().numpy()
D_est_np = D_est_tensor.detach().cpu().numpy()
B, H, W = D_gt_np.shape
# valid mask
mask = D_gt_np > 1e-3
# error in percentage. When error <= 1, the pixel is valid since <= 3px & 5%
error = np.abs(D_gt_np - D_est_np)
error[np.logical_not(mask)] = 0 # remove the invalid pixels
error[mask] = np.minimum(error[mask] / abs_thres, (error[mask] / D_gt_np[mask]) / rel_thres)
# get colormap
cols = error_colormap
# create error image
error_image = np.zeros([B, H, W, 3], dtype=np.float32)
for i in range(cols.shape[0]):
error_image[np.logical_and(error >= cols[i][0], error < cols[i][1])] = cols[i, 2:] # find out the correspondant range, give RGB values
# TODO: imdilate
# error_image = cv2.imdilate(D_err, strel('disk', dilate_radius));
# remove the color in invalid pixels
error_image[np.logical_not(mask)] = 0.
# show color tag in the top-left cornor of the image
for i in range(cols.shape[0]):
distance = 20
error_image[:, :10, i * distance:(i + 1) * distance, :] = cols[i, 2:]
return torch.from_numpy(np.ascontiguousarray(error_image.transpose([0, 3, 1, 2])))
def gen_dep_error_colormap(max_range=2):
"""
format:[[min_error<= this_error<=max_error, RGB],
[min_error<= this_error<=max_error, RGB],
...
[min_error<= this_error<=max_error, RGB],]
unit: meter
range: (0, max_range) meters
"""
max_range = max_range / 0.9
cols = np.array(
[[0.0 * max_range, 0.1 * max_range, 49, 54, 149],
[0.1 * max_range, 0.2 * max_range, 69, 117, 180],
[0.2 * max_range, 0.3 * max_range, 116, 173, 209],
[0.3 * max_range, 0.4 * max_range, 171, 217, 233],
[0.4 * max_range, 0.5 * max_range, 224, 243, 248],
[0.5 * max_range, 0.6 * max_range, 254, 224, 144],
[0.6 * max_range, 0.7 * max_range, 253, 174, 97],
[0.7 * max_range, 0.8 * max_range, 244, 109, 67],
[0.8 * max_range, 0.9 * max_range, 215, 48, 39],
[0.9 * max_range, np.inf, 165, 0, 38]], dtype=np.float32)
cols[:, 2: 5] /= 255.
return cols
dep_error_colormap = gen_dep_error_colormap(max_range=2.)
def dep_error_image_func(D_est_tensor, D_gt_tensor):
"""
D_est_tensor: estimated depth, BHW
D_gt_tensor: ground-truth depth, BHW
abs_thres: abs(D_est - D_gt) > abs_thres? outliers : zeros
"""
D_gt_np = D_gt_tensor.detach().cpu().numpy()
D_est_np = D_est_tensor.detach().cpu().numpy()
B, H, W = D_gt_np.shape
# valid mask
mask = D_gt_np > 1e-3
# error in percentage. When error <= 1, the pixel is valid since <= 3px & 5%
error = np.abs(D_gt_np - D_est_np)
error[np.logical_not(mask)] = 0 # remove the invalid pixels
# get colormap
cols = error_colormap
# create error image
error_image = np.zeros([B, H, W, 3], dtype=np.float32)
for i in range(cols.shape[0]):
error_image[np.logical_and(error >= cols[i][0], error < cols[i][1])] = cols[i, 2:] # find out the correspondant range, give RGB values
# TODO: imdilate
# error_image = cv2.imdilate(D_err, strel('disk', dilate_radius));
# remove the color in invalid pixels
error_image[np.logical_not(mask)] = 0.
# show color tag in the top-left cornor of the image
for i in range(cols.shape[0]):
distance = 20
error_image[:, :10, i * distance:(i + 1) * distance, :] = cols[i, 2:]
return torch.from_numpy(np.ascontiguousarray(error_image.transpose([0, 3, 1, 2])))