|
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 |
|
|
|
""" |
|
|
|
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 |
|
|