code / SparseNeuS_demo_v1 /loss /depth_metric.py
Chao Xu
sparseneus and elev est
854f0d0
import numpy as np
def l1(depth1, depth2):
"""
Computes the l1 errors between the two depth maps.
Takes preprocessed depths (no nans, infs and non-positive values)
depth1: one depth map
depth2: another depth map
Returns:
L1(log)
"""
assert (np.all(np.isfinite(depth1) & np.isfinite(depth2) & (depth1 >= 0) & (depth2 >= 0)))
diff = depth1 - depth2
num_pixels = float(diff.size)
if num_pixels == 0:
return np.nan
else:
return np.sum(np.absolute(diff)) / num_pixels
def l1_inverse(depth1, depth2):
"""
Computes the l1 errors between inverses of two depth maps.
Takes preprocessed depths (no nans, infs and non-positive values)
depth1: one depth map
depth2: another depth map
Returns:
L1(log)
"""
assert (np.all(np.isfinite(depth1) & np.isfinite(depth2) & (depth1 >= 0) & (depth2 >= 0)))
diff = np.reciprocal(depth1) - np.reciprocal(depth2)
num_pixels = float(diff.size)
if num_pixels == 0:
return np.nan
else:
return np.sum(np.absolute(diff)) / num_pixels
def rmse_log(depth1, depth2):
"""
Computes the root min square errors between the logs of two depth maps.
Takes preprocessed depths (no nans, infs and non-positive values)
depth1: one depth map
depth2: another depth map
Returns:
RMSE(log)
"""
assert (np.all(np.isfinite(depth1) & np.isfinite(depth2) & (depth1 >= 0) & (depth2 >= 0)))
log_diff = np.log(depth1) - np.log(depth2)
num_pixels = float(log_diff.size)
if num_pixels == 0:
return np.nan
else:
return np.sqrt(np.sum(np.square(log_diff)) / num_pixels)
def rmse(depth1, depth2):
"""
Computes the root min square errors between the two depth maps.
Takes preprocessed depths (no nans, infs and non-positive values)
depth1: one depth map
depth2: another depth map
Returns:
RMSE(log)
"""
assert (np.all(np.isfinite(depth1) & np.isfinite(depth2) & (depth1 >= 0) & (depth2 >= 0)))
diff = depth1 - depth2
num_pixels = float(diff.size)
if num_pixels == 0:
return np.nan
else:
return np.sqrt(np.sum(np.square(diff)) / num_pixels)
def scale_invariant(depth1, depth2):
"""
Computes the scale invariant loss based on differences of logs of depth maps.
Takes preprocessed depths (no nans, infs and non-positive values)
depth1: one depth map
depth2: another depth map
Returns:
scale_invariant_distance
"""
# sqrt(Eq. 3)
assert (np.all(np.isfinite(depth1) & np.isfinite(depth2) & (depth1 >= 0) & (depth2 >= 0)))
log_diff = np.log(depth1) - np.log(depth2)
num_pixels = float(log_diff.size)
if num_pixels == 0:
return np.nan
else:
return np.sqrt(np.sum(np.square(log_diff)) / num_pixels - np.square(np.sum(log_diff)) / np.square(num_pixels))
def abs_relative(depth_pred, depth_gt):
"""
Computes relative absolute distance.
Takes preprocessed depths (no nans, infs and non-positive values)
depth_pred: depth map prediction
depth_gt: depth map ground truth
Returns:
abs_relative_distance
"""
assert (np.all(np.isfinite(depth_pred) & np.isfinite(depth_gt) & (depth_pred >= 0) & (depth_gt >= 0)))
diff = depth_pred - depth_gt
num_pixels = float(diff.size)
if num_pixels == 0:
return np.nan
else:
return np.sum(np.absolute(diff) / depth_gt) / num_pixels
def avg_log10(depth1, depth2):
"""
Computes average log_10 error (Liu, Neural Fields, 2015).
Takes preprocessed depths (no nans, infs and non-positive values)
depth1: one depth map
depth2: another depth map
Returns:
abs_relative_distance
"""
assert (np.all(np.isfinite(depth1) & np.isfinite(depth2) & (depth1 >= 0) & (depth2 >= 0)))
log_diff = np.log10(depth1) - np.log10(depth2)
num_pixels = float(log_diff.size)
if num_pixels == 0:
return np.nan
else:
return np.sum(np.absolute(log_diff)) / num_pixels
def sq_relative(depth_pred, depth_gt):
"""
Computes relative squared distance.
Takes preprocessed depths (no nans, infs and non-positive values)
depth_pred: depth map prediction
depth_gt: depth map ground truth
Returns:
squared_relative_distance
"""
assert (np.all(np.isfinite(depth_pred) & np.isfinite(depth_gt) & (depth_pred >= 0) & (depth_gt >= 0)))
diff = depth_pred - depth_gt
num_pixels = float(diff.size)
if num_pixels == 0:
return np.nan
else:
return np.sum(np.square(diff) / depth_gt) / num_pixels
def ratio_threshold(depth1, depth2, threshold):
"""
Computes the percentage of pixels for which the ratio of the two depth maps is less than a given threshold.
Takes preprocessed depths (no nans, infs and non-positive values)
depth1: one depth map
depth2: another depth map
Returns:
percentage of pixels with ratio less than the threshold
"""
assert (threshold > 0.)
assert (np.all(np.isfinite(depth1) & np.isfinite(depth2) & (depth1 >= 0) & (depth2 >= 0)))
log_diff = np.log(depth1) - np.log(depth2)
num_pixels = float(log_diff.size)
if num_pixels == 0:
return np.nan
else:
return float(np.sum(np.absolute(log_diff) < np.log(threshold))) / num_pixels
def compute_depth_errors(depth_pred, depth_gt, valid_mask):
"""
Computes different distance measures between two depth maps.
depth_pred: depth map prediction
depth_gt: depth map ground truth
distances_to_compute: which distances to compute
Returns:
a dictionary with computed distances, and the number of valid pixels
"""
depth_pred = depth_pred[valid_mask]
depth_gt = depth_gt[valid_mask]
num_valid = np.sum(valid_mask)
distances_to_compute = ['l1',
'l1_inverse',
'scale_invariant',
'abs_relative',
'sq_relative',
'avg_log10',
'rmse_log',
'rmse',
'ratio_threshold_1.25',
'ratio_threshold_1.5625',
'ratio_threshold_1.953125']
results = {'num_valid': num_valid}
for dist in distances_to_compute:
if dist.startswith('ratio_threshold'):
threshold = float(dist.split('_')[-1])
results[dist] = ratio_threshold(depth_pred, depth_gt, threshold)
else:
results[dist] = globals()[dist](depth_pred, depth_gt)
return results