Disparity calculation (#12)
* add filter for z < 40 * change figure name * stereo results in figure * stereo figure * pylint * pylint(2) * pylint updated
This commit is contained in:
parent
4071971e48
commit
39eef3195b
@ -113,7 +113,7 @@ class EvalKitti:
|
||||
|
||||
def printer(self, show, save):
|
||||
if save or show:
|
||||
show_results(self.dic_stats, show, save)
|
||||
show_results(self.dic_stats, show, save, stereo=self.stereo)
|
||||
show_spread(self.dic_stats, show, save)
|
||||
show_task_error(show, save)
|
||||
|
||||
@ -178,7 +178,7 @@ class EvalKitti:
|
||||
self.update_uncertainty(stds_ale[idx], stds_epi[idx], dds[idx], dds_gt[idx_gt], cat)
|
||||
dd_task_error = dds_gt[idx_gt] + (get_task_error(dds_gt[idx_gt]))**2
|
||||
self.update_errors(dd_task_error, dds_gt[idx_gt], cat, self.errors['task_error'])
|
||||
dd_pixel_error = get_pixel_error(dds_gt[idx_gt], zzs_gt[idx_gt])
|
||||
dd_pixel_error = dds_gt[idx_gt] + get_pixel_error(zzs_gt[idx_gt])
|
||||
self.update_errors(dd_pixel_error, dds_gt[idx_gt], cat, self.errors['pixel_error'])
|
||||
|
||||
def _compare_error(self, out_gt, methods_out):
|
||||
@ -211,7 +211,7 @@ class EvalKitti:
|
||||
self.update_errors(dd_monoloco, dd_gt, cat, self.errors['monoloco_merged'])
|
||||
self.update_errors(dd_geometric, dd_gt, cat, self.errors['geometric_merged'])
|
||||
self.update_errors(dd_gt + get_task_error(dd_gt), dd_gt, cat, self.errors['task_error_merged'])
|
||||
dd_pixel = get_pixel_error(dd_gt, zzs_gt[idx_gt])
|
||||
dd_pixel = dd_gt + get_pixel_error(zzs_gt[idx_gt])
|
||||
self.update_errors(dd_pixel, dd_gt, cat, self.errors['pixel_error_merged'])
|
||||
|
||||
for key in self.methods:
|
||||
|
||||
@ -20,7 +20,7 @@ def baselines_association(baselines, zzs, keypoints, keypoints_right, reid_featu
|
||||
keypoints, keypoints_right, baselines, reid_features)
|
||||
|
||||
# count maximum possible associations
|
||||
cnt_stereo['max'] = min(keypoints.shape[0], keypoints_r.shape[0])
|
||||
cnt_stereo['max'] = min(keypoints.shape[0], keypoints_r.shape[0]) # pylint: disable=E1136
|
||||
|
||||
# Filter joints disparity and calculate avg disparity
|
||||
avg_disparities, disparities_x, disparities_y = mask_joint_disparity(keypoints, keypoints_r)
|
||||
@ -161,7 +161,8 @@ def verify_stereo(zz_stereo, zz_mono, disparity_x, disparity_y):
|
||||
|
||||
if abs(zz_stereo - zz_mono) < z_max_difference and \
|
||||
avg_disparity_y < y_max_difference and \
|
||||
cov < COV_MIN:
|
||||
cov < COV_MIN\
|
||||
and 4 < zz_stereo < 40:
|
||||
return True
|
||||
# if not np.isnan(zz_stereo):
|
||||
# return True
|
||||
|
||||
@ -128,7 +128,7 @@ def main():
|
||||
|
||||
elif args.command == 'eval':
|
||||
if args.geometric:
|
||||
assert args.joints, "joints argument not provided"
|
||||
assert args.joints, "joints argument not provided"
|
||||
from .eval import geometric_baseline
|
||||
geometric_baseline(args.joints)
|
||||
|
||||
|
||||
@ -231,7 +231,7 @@ class Trainer:
|
||||
# Debug plot for input-output distributions
|
||||
if debug:
|
||||
debug_plots(inputs, labels)
|
||||
exit()
|
||||
sys.exit()
|
||||
|
||||
# Forward pass
|
||||
outputs = self.model(inputs)
|
||||
|
||||
@ -93,8 +93,9 @@ def check_conditions(line, category, method, thresh=0.3):
|
||||
check = True
|
||||
|
||||
else:
|
||||
zz = float(line[13])
|
||||
conf = float(line[15])
|
||||
if conf >= thresh:
|
||||
if conf >= thresh and 0.5 < zz < 70:
|
||||
check = True
|
||||
|
||||
return check
|
||||
|
||||
@ -30,12 +30,12 @@ def get_task_error(dd):
|
||||
return dd * mm
|
||||
|
||||
|
||||
def get_pixel_error(dd_gt, zz_gt):
|
||||
def get_pixel_error(zz_gt):
|
||||
"""calculate error in stereo distance due to 1 pixel mismatch (function of depth)"""
|
||||
|
||||
disp = 0.54 * 721 / zz_gt
|
||||
delta_z = zz_gt - 0.54 * 721 / (disp - 1)
|
||||
return dd_gt + delta_z
|
||||
error = abs(zz_gt - 0.54 * 721 / (disp - 1))
|
||||
return error
|
||||
|
||||
|
||||
def open_annotations(path_ann):
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
|
||||
# pylint: disable=R0915
|
||||
|
||||
import math
|
||||
@ -9,11 +8,10 @@ import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
from matplotlib.patches import Ellipse
|
||||
|
||||
from ..utils import get_task_error
|
||||
from ..utils import get_task_error, get_pixel_error
|
||||
|
||||
|
||||
def show_results(dic_stats, show=False, save=False):
|
||||
|
||||
def show_results(dic_stats, show=False, save=False, stereo=False):
|
||||
"""
|
||||
Visualize error as function of the distance and compare it with target errors based on human height analyses
|
||||
"""
|
||||
@ -22,40 +20,41 @@ def show_results(dic_stats, show=False, save=False):
|
||||
phase = 'test'
|
||||
x_min = 0
|
||||
x_max = 38
|
||||
y_min = 0
|
||||
y_max = 4.7
|
||||
xx = np.linspace(0, 60, 100)
|
||||
excl_clusters = ['all', '50', '>50', 'easy', 'moderate', 'hard']
|
||||
clusters = tuple([clst for clst in dic_stats[phase]['monoloco'] if clst not in excl_clusters])
|
||||
yy_gender = get_task_error(xx)
|
||||
|
||||
plt.figure(0)
|
||||
plt.grid(linewidth=0.2)
|
||||
plt.xlabel("Ground-truth distance [m]")
|
||||
plt.ylabel("Average localization error [m]")
|
||||
plt.xlim(x_min, x_max)
|
||||
labels = ['Mono3D', 'Geometric Baseline', 'MonoDepth', 'Our MonoLoco', '3DOP (stereo)']
|
||||
mks = ['*', '^', 'p', 's', 'o']
|
||||
mksizes = [6, 6, 6, 6, 6]
|
||||
lws = [1.5, 1.5, 1.5, 2.2, 1.6]
|
||||
colors = ['r', 'deepskyblue', 'grey', 'b', 'darkorange']
|
||||
lstyles = ['solid', 'solid', 'solid', 'solid', 'dashdot']
|
||||
styles = printing_styles(stereo)
|
||||
for idx_style, (key, style) in enumerate(styles.items()):
|
||||
plt.figure(idx_style)
|
||||
plt.grid(linewidth=0.2)
|
||||
plt.xlim(x_min, x_max)
|
||||
plt.ylim(y_min, y_max)
|
||||
plt.xlabel("Ground-truth distance [m]")
|
||||
plt.ylabel("Average localization error [m]")
|
||||
for idx, method in enumerate(style['methods']):
|
||||
errs = [dic_stats[phase][method][clst]['mean'] for clst in clusters]
|
||||
assert errs, "method %s empty" % method
|
||||
xxs = get_distances(clusters)
|
||||
|
||||
for idx, method in enumerate(['m3d_merged', 'geometric_merged', 'monodepth_merged', 'monoloco_merged',
|
||||
'3dop_merged']):
|
||||
errs = [dic_stats[phase][method][clst]['mean'] for clst in clusters]
|
||||
assert errs, "method %s empty" % method
|
||||
xxs = get_distances(clusters)
|
||||
plt.plot(xxs, errs, marker=style['mks'][idx], markersize=style['mksizes'][idx], linewidth=style['lws'][idx],
|
||||
label=style['labels'][idx], linestyle=style['lstyles'][idx], color=style['colors'][idx])
|
||||
plt.plot(xx, yy_gender, '--', label="Task error", color='lightgreen', linewidth=2.5)
|
||||
if key == 'stereo':
|
||||
yy_stereo = get_pixel_error(xx)
|
||||
plt.plot(xx, yy_stereo, linewidth=1.7, color='k', label='Pixel error')
|
||||
|
||||
plt.plot(xxs, errs, marker=mks[idx], markersize=mksizes[idx], linewidth=lws[idx], label=labels[idx],
|
||||
linestyle=lstyles[idx], color=colors[idx])
|
||||
plt.plot(xx, yy_gender, '--', label="Task error", color='lightgreen', linewidth=2.5)
|
||||
plt.legend(loc='upper left')
|
||||
if save:
|
||||
path_fig = os.path.join(dir_out, 'results.png')
|
||||
plt.savefig(path_fig)
|
||||
print("Figure of results saved in {}".format(path_fig))
|
||||
if show:
|
||||
plt.show()
|
||||
plt.close()
|
||||
plt.legend(loc='upper left')
|
||||
if save:
|
||||
path_fig = os.path.join(dir_out, 'results_' + key + '.png')
|
||||
plt.savefig(path_fig)
|
||||
print("Figure of results " + key + " saved in {}".format(path_fig))
|
||||
if show:
|
||||
plt.show()
|
||||
plt.close()
|
||||
|
||||
|
||||
def show_spread(dic_stats, show=False, save=False):
|
||||
@ -66,7 +65,7 @@ def show_spread(dic_stats, show=False, save=False):
|
||||
excl_clusters = ['all', '50', '>50', 'easy', 'moderate', 'hard']
|
||||
clusters = tuple([clst for clst in dic_stats[phase]['our'] if clst not in excl_clusters])
|
||||
|
||||
plt.figure(1)
|
||||
plt.figure(2)
|
||||
fig, ax = plt.subplots(2, sharex=True)
|
||||
plt.xlabel("Distance [m]")
|
||||
plt.ylabel("Aleatoric uncertainty [m]")
|
||||
@ -80,10 +79,10 @@ def show_spread(dic_stats, show=False, save=False):
|
||||
yys = get_task_error(np.array(xxs))
|
||||
ax[1].plot(xxs, bbs, marker='s', color='b', label="Spread b")
|
||||
ax[1].plot(xxs, yys, '--', color='lightgreen', label="Task error", linewidth=2.5)
|
||||
yys_up = [rec_c + ar/2 * scale * yy for yy in yys]
|
||||
bbs_up = [rec_c + ar/2 * scale * bb for bb in bbs]
|
||||
yys_down = [rec_c - ar/2 * scale * yy for yy in yys]
|
||||
bbs_down = [rec_c - ar/2 * scale * bb for bb in bbs]
|
||||
yys_up = [rec_c + ar / 2 * scale * yy for yy in yys]
|
||||
bbs_up = [rec_c + ar / 2 * scale * bb for bb in bbs]
|
||||
yys_down = [rec_c - ar / 2 * scale * yy for yy in yys]
|
||||
bbs_down = [rec_c - ar / 2 * scale * bb for bb in bbs]
|
||||
|
||||
if plots_line:
|
||||
ax[0].plot(xxs, yys_up, '--', color='lightgreen', markersize=5, linewidth=1.4)
|
||||
@ -92,8 +91,8 @@ def show_spread(dic_stats, show=False, save=False):
|
||||
ax[0].plot(xxs, bbs_down, marker='s', color='b', markersize=5, linewidth=0.7)
|
||||
|
||||
for idx, xx in enumerate(xxs):
|
||||
te = Ellipse((xx, rec_c), width=yys[idx]*ar*scale, height=scale, angle=90, color='lightgreen', fill=True)
|
||||
bi = Ellipse((xx, rec_c), width=bbs[idx]*ar*scale, height=scale, angle=90, color='b', linewidth=1.8,
|
||||
te = Ellipse((xx, rec_c), width=yys[idx] * ar * scale, height=scale, angle=90, color='lightgreen', fill=True)
|
||||
bi = Ellipse((xx, rec_c), width=bbs[idx] * ar * scale, height=scale, angle=90, color='b', linewidth=1.8,
|
||||
fill=False)
|
||||
|
||||
ax[0].add_patch(te)
|
||||
@ -113,9 +112,9 @@ def show_spread(dic_stats, show=False, save=False):
|
||||
|
||||
def show_task_error(show, save):
|
||||
"""Task error figure"""
|
||||
plt.figure(2)
|
||||
plt.figure(3)
|
||||
dir_out = 'docs'
|
||||
xx = np.linspace(0, 40, 100)
|
||||
xx = np.linspace(0.1, 50, 100)
|
||||
mu_men = 178
|
||||
mu_women = 165
|
||||
mu_child_m = 164
|
||||
@ -128,12 +127,14 @@ def show_task_error(show, save):
|
||||
yy_young_male = target_error(xx, mm_young_male)
|
||||
yy_young_female = target_error(xx, mm_young_female)
|
||||
yy_gender = target_error(xx, mm_gmm)
|
||||
yy_stereo = get_pixel_error(xx)
|
||||
plt.grid(linewidth=0.3)
|
||||
plt.plot(xx, yy_young_male, linestyle='dotted', linewidth=2.1, color='b', label='Adult/young male')
|
||||
plt.plot(xx, yy_young_female, linestyle='dotted', linewidth=2.1, color='darkorange', label='Adult/young female')
|
||||
plt.plot(xx, yy_gender, '--', color='lightgreen', linewidth=2.8, label='Generic adult (task error)')
|
||||
plt.plot(xx, yy_female, '-.', linewidth=1.7, color='darkorange', label='Adult female')
|
||||
plt.plot(xx, yy_male, '-.', linewidth=1.7, color='b', label='Adult male')
|
||||
plt.plot(xx, yy_stereo, linewidth=1.7, color='k', label='Pixel error')
|
||||
plt.xlim(np.min(xx), np.max(xx))
|
||||
plt.xlabel("Ground-truth distance from the camera $d_{gt}$ [m]")
|
||||
plt.ylabel("Localization error $\hat{e}$ due to human height variation [m]") # pylint: disable=W1401
|
||||
@ -193,7 +194,6 @@ def calculate_gmm():
|
||||
|
||||
|
||||
def get_confidence(xx, zz, std):
|
||||
|
||||
theta = math.atan2(zz, xx)
|
||||
|
||||
delta_x = std * math.cos(theta)
|
||||
@ -215,11 +215,9 @@ def get_distances(clusters):
|
||||
|
||||
|
||||
def get_confidence_points(confidences, distances, errors):
|
||||
|
||||
confidence_points = []
|
||||
distance_points = []
|
||||
for idx, dd in enumerate(distances):
|
||||
|
||||
conf_perc = confidences[idx]
|
||||
confidence_points.append(errors[idx] + conf_perc)
|
||||
confidence_points.append(errors[idx] - conf_perc)
|
||||
@ -230,7 +228,6 @@ def get_confidence_points(confidences, distances, errors):
|
||||
|
||||
|
||||
def height_distributions():
|
||||
|
||||
mu_men = 178
|
||||
std_men = 7
|
||||
mu_women = 165
|
||||
@ -256,7 +253,7 @@ def expandgrid(*itrs):
|
||||
|
||||
def plot_dist(dist_gmm, dist_men, dist_women):
|
||||
try:
|
||||
import seaborn as sns
|
||||
import seaborn as sns # pylint: disable=C0415
|
||||
sns.distplot(dist_men, hist=False, rug=False, label="Men")
|
||||
sns.distplot(dist_women, hist=False, rug=False, label="Women")
|
||||
sns.distplot(dist_gmm, hist=False, rug=False, label="GMM")
|
||||
@ -273,9 +270,30 @@ def get_percentile(dist_gmm):
|
||||
dd_gt = 1000
|
||||
mu_gmm = np.mean(dist_gmm)
|
||||
dist_d = dd_gt * mu_gmm / dist_gmm
|
||||
perc_d, _ = np.nanpercentile(dist_d, [18.5, 81.5]) # Laplace bi => 63%
|
||||
perc_d, _ = np.nanpercentile(dist_d, [18.5, 81.5]) # Laplace bi => 63%
|
||||
perc_d2, _ = np.nanpercentile(dist_d, [23, 77])
|
||||
mu_d = np.mean(dist_d)
|
||||
# mm_bi = (mu_d - perc_d) / mu_d
|
||||
# mm_test = (mu_d - perc_d2) / mu_d
|
||||
# mad_d = np.mean(np.abs(dist_d - mu_d))
|
||||
|
||||
|
||||
def printing_styles(stereo):
|
||||
style = {'mono': {"labels": ['Mono3D', 'Geometric Baseline', 'MonoDepth', 'Our MonoLoco', '3DOP (stereo)'],
|
||||
"methods": ['m3d_merged', 'geometric_merged', 'monodepth_merged', 'monoloco_merged',
|
||||
'3dop_merged'],
|
||||
"mks": ['*', '^', 'p', 's', 'o'],
|
||||
"mksizes": [6, 6, 6, 6, 6], "lws": [1.5, 1.5, 1.5, 2.2, 1.6],
|
||||
"colors": ['r', 'deepskyblue', 'grey', 'b', 'darkorange'],
|
||||
"lstyles": ['solid', 'solid', 'solid', 'solid', 'dashdot']}}
|
||||
if stereo:
|
||||
style['stereo'] = {"labels": ['3DOP', 'Pose Baseline', 'ReiD Baseline', 'Our MonoLoco (monocular)',
|
||||
'Our Stereo Baseline'],
|
||||
"methods": ['3dop_merged', 'pose_merged', 'reid_merged', 'monoloco_merged',
|
||||
'ml_stereo_merged'],
|
||||
"mks": ['o', '^', 'p', 's', 's'],
|
||||
"mksizes": [6, 6, 6, 4, 6], "lws": [1.5, 1.5, 1.5, 1.2, 1.5],
|
||||
"colors": ['darkorange', 'lightblue', 'red', 'b', 'b'],
|
||||
"lstyles": ['solid', 'solid', 'solid', 'dashed', 'solid']}
|
||||
|
||||
return style
|
||||
|
||||
Loading…
Reference in New Issue
Block a user