refactor article figures
This commit is contained in:
parent
10874caea0
commit
bbe040d4a2
@ -1,5 +1,4 @@
|
|||||||
|
|
||||||
# pylint: skip-file
|
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
@ -96,8 +95,6 @@ def cli():
|
|||||||
|
|
||||||
def main():
|
def main():
|
||||||
args = cli()
|
args = cli()
|
||||||
from .visuals.paper import paper
|
|
||||||
paper()
|
|
||||||
if args.command == 'predict':
|
if args.command == 'predict':
|
||||||
if args.webcam:
|
if args.webcam:
|
||||||
from .visuals.webcam import webcam
|
from .visuals.webcam import webcam
|
||||||
@ -156,8 +153,8 @@ def main():
|
|||||||
training = Trainer(joints=args.joints)
|
training = Trainer(joints=args.joints)
|
||||||
_ = training.evaluate(load=True, model=args.model, debug=False)
|
_ = training.evaluate(load=True, model=args.model, debug=False)
|
||||||
|
|
||||||
# else:
|
else:
|
||||||
# raise ValueError("Main subparser not recognized or not provided")
|
raise ValueError("Main subparser not recognized or not provided")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
271
monoloco/visuals/figures.py
Normal file
271
monoloco/visuals/figures.py
Normal file
@ -0,0 +1,271 @@
|
|||||||
|
|
||||||
|
# pylint: disable=R0915
|
||||||
|
|
||||||
|
import math
|
||||||
|
import itertools
|
||||||
|
import os
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
from matplotlib.patches import Ellipse
|
||||||
|
|
||||||
|
from ..utils import get_task_error
|
||||||
|
|
||||||
|
|
||||||
|
def show_results(dic_stats, show=False):
|
||||||
|
|
||||||
|
"""
|
||||||
|
Visualize error as function of the distance and compare it with target errors based on human height analyses
|
||||||
|
"""
|
||||||
|
|
||||||
|
dir_out = 'docs'
|
||||||
|
phase = 'test'
|
||||||
|
x_min = 0
|
||||||
|
x_max = 38
|
||||||
|
xx = np.linspace(0, 60, 100)
|
||||||
|
excl_clusters = ['all', '50', '>50', 'easy', 'moderate', 'hard']
|
||||||
|
clusters = tuple([clst for clst in dic_stats[phase]['our'] if clst not in excl_clusters])
|
||||||
|
|
||||||
|
yy_gender = get_task_error(xx)
|
||||||
|
yy_gps = np.linspace(5., 5., xx.shape[0])
|
||||||
|
|
||||||
|
plt.figure(0)
|
||||||
|
plt.grid(linewidth=0.2)
|
||||||
|
plt.xlabel("Distance [meters]")
|
||||||
|
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']
|
||||||
|
|
||||||
|
plt.plot(xx, yy_gps, '-', label="GPS Error", color='y')
|
||||||
|
for idx, method in enumerate(['m3d_merged', 'geom_merged', 'md_merged', 'our_merged', '3dop_merged']):
|
||||||
|
errs = [dic_stats[phase][method][clst]['mean'] for clst in clusters]
|
||||||
|
xxs = get_distances(clusters)
|
||||||
|
|
||||||
|
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 show:
|
||||||
|
plt.show()
|
||||||
|
else:
|
||||||
|
plt.savefig(os.path.join(dir_out, 'results.png'))
|
||||||
|
plt.close()
|
||||||
|
|
||||||
|
|
||||||
|
def show_spread(dic_stats, show=False):
|
||||||
|
"""Predicted confidence intervals and task error as a function of ground-truth distance"""
|
||||||
|
|
||||||
|
phase = 'test'
|
||||||
|
dir_out = 'docs'
|
||||||
|
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)
|
||||||
|
fig, ax = plt.subplots(2, sharex=True)
|
||||||
|
plt.xlabel("Distance [m]")
|
||||||
|
plt.ylabel("Aleatoric uncertainty [m]")
|
||||||
|
ar = 0.5 # Change aspect ratio of ellipses
|
||||||
|
scale = 1.5 # Factor to scale ellipses
|
||||||
|
rec_c = 0 # Center of the rectangle
|
||||||
|
plots_line = True
|
||||||
|
|
||||||
|
bbs = np.array([dic_stats[phase]['our'][key]['std_ale'] for key in clusters])
|
||||||
|
xxs = get_distances(clusters)
|
||||||
|
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]
|
||||||
|
|
||||||
|
if plots_line:
|
||||||
|
ax[0].plot(xxs, yys_up, '--', color='lightgreen', markersize=5, linewidth=1.4)
|
||||||
|
ax[0].plot(xxs, yys_down, '--', color='lightgreen', markersize=5, linewidth=1.4)
|
||||||
|
ax[0].plot(xxs, bbs_up, marker='s', color='b', markersize=5, linewidth=0.7)
|
||||||
|
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,
|
||||||
|
fill=False)
|
||||||
|
|
||||||
|
ax[0].add_patch(te)
|
||||||
|
ax[0].add_patch(bi)
|
||||||
|
|
||||||
|
fig.subplots_adjust(hspace=0.1)
|
||||||
|
plt.setp([aa.get_yticklabels() for aa in fig.axes[:-1]], visible=False)
|
||||||
|
plt.legend()
|
||||||
|
if show:
|
||||||
|
plt.show()
|
||||||
|
else:
|
||||||
|
plt.savefig(os.path.join(dir_out, 'spread_bi.png'))
|
||||||
|
plt.close()
|
||||||
|
|
||||||
|
|
||||||
|
def show_method():
|
||||||
|
""" method figure"""
|
||||||
|
std_1 = 0.75
|
||||||
|
fig = plt.figure(1)
|
||||||
|
ax = fig.add_subplot(1, 1, 1)
|
||||||
|
|
||||||
|
ell_3 = Ellipse((0, 2), width=std_1 * 2, height=0.3, angle=-90, color='b', fill=False, linewidth=2.5)
|
||||||
|
ell_4 = Ellipse((0, 2), width=std_1 * 3, height=0.3, angle=-90, color='r', fill=False,
|
||||||
|
linestyle='dashed', linewidth=2.5)
|
||||||
|
ax.add_patch(ell_4)
|
||||||
|
ax.add_patch(ell_3)
|
||||||
|
plt.plot(0, 2, marker='o', color='skyblue', markersize=9)
|
||||||
|
plt.plot([0, 3], [0, 4], 'k--')
|
||||||
|
plt.plot([0, -3], [0, 4], 'k--')
|
||||||
|
plt.xlim(-3, 3)
|
||||||
|
plt.ylim(0, 3.5)
|
||||||
|
plt.xticks([])
|
||||||
|
plt.yticks([])
|
||||||
|
plt.xlabel('X [m]')
|
||||||
|
plt.ylabel('Z [m]')
|
||||||
|
plt.savefig(os.path.join('docs', 'output_method.png'))
|
||||||
|
|
||||||
|
|
||||||
|
def show_task_error():
|
||||||
|
"""Task error figure"""
|
||||||
|
plt.figure(2)
|
||||||
|
xx = np.linspace(0, 40, 100)
|
||||||
|
mu_men = 178
|
||||||
|
mu_women = 165
|
||||||
|
mu_child_m = 164
|
||||||
|
mu_child_w = 156
|
||||||
|
mm_gmm, mm_male, mm_female = calculate_gmm()
|
||||||
|
mm_young_male = mm_male + (mu_men - mu_child_m) / mu_men
|
||||||
|
mm_young_female = mm_female + (mu_women - mu_child_w) / mu_women
|
||||||
|
yy_male = target_error(xx, mm_male)
|
||||||
|
yy_female = target_error(xx, mm_female)
|
||||||
|
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_gps = np.linspace(5., 5., xx.shape[0])
|
||||||
|
plt.grid(linewidth=0.3)
|
||||||
|
plt.plot(xx, yy_gps, color='y', label='GPS')
|
||||||
|
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.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]")
|
||||||
|
plt.legend(loc=(0.01, 0.55)) # Location from 0 to 1 from lower left
|
||||||
|
plt.savefig(os.path.join('docs', 'task_error.png'))
|
||||||
|
|
||||||
|
|
||||||
|
def target_error(xx, mm):
|
||||||
|
return mm * xx
|
||||||
|
|
||||||
|
|
||||||
|
def calculate_gmm():
|
||||||
|
dist_gmm, dist_male, dist_female = height_distributions()
|
||||||
|
# get_percentile(dist_gmm)
|
||||||
|
mu_gmm = np.mean(dist_gmm)
|
||||||
|
mm_gmm = np.mean(np.abs(1 - mu_gmm / dist_gmm))
|
||||||
|
mm_male = np.mean(np.abs(1 - np.mean(dist_male) / dist_male))
|
||||||
|
mm_female = np.mean(np.abs(1 - np.mean(dist_female) / dist_female))
|
||||||
|
|
||||||
|
print("Mean of GMM distribution: {:.4f}".format(mu_gmm))
|
||||||
|
print("coefficient for gmm: {:.4f}".format(mm_gmm))
|
||||||
|
print("coefficient for men: {:.4f}".format(mm_male))
|
||||||
|
print("coefficient for women: {:.4f}".format(mm_female))
|
||||||
|
return mm_gmm, mm_male, mm_female
|
||||||
|
|
||||||
|
|
||||||
|
def get_confidence(xx, zz, std):
|
||||||
|
|
||||||
|
theta = math.atan2(zz, xx)
|
||||||
|
|
||||||
|
delta_x = std * math.cos(theta)
|
||||||
|
delta_z = std * math.sin(theta)
|
||||||
|
return (xx - delta_x, xx + delta_x), (zz - delta_z, zz + delta_z)
|
||||||
|
|
||||||
|
|
||||||
|
def get_distances(clusters):
|
||||||
|
"""Extract distances as intermediate values between 2 clusters"""
|
||||||
|
|
||||||
|
clusters_ext = list(clusters)
|
||||||
|
clusters_ext.insert(0, str(0))
|
||||||
|
distances = []
|
||||||
|
for idx, _ in enumerate(clusters_ext[:-1]):
|
||||||
|
clst_0 = float(clusters_ext[idx])
|
||||||
|
clst_1 = float(clusters_ext[idx + 1])
|
||||||
|
distances.append((clst_1 - clst_0) / 2 + clst_0)
|
||||||
|
return tuple(distances)
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
||||||
|
distance_points.append(dd)
|
||||||
|
distance_points.append(dd)
|
||||||
|
|
||||||
|
return distance_points, confidence_points
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def height_distributions():
|
||||||
|
|
||||||
|
mu_men = 178
|
||||||
|
std_men = 7
|
||||||
|
mu_women = 165
|
||||||
|
std_women = 7
|
||||||
|
dist_men = np.random.normal(mu_men, std_men, int(1e7))
|
||||||
|
dist_women = np.random.normal(mu_women, std_women, int(1e7))
|
||||||
|
|
||||||
|
dist_gmm = np.concatenate((dist_men, dist_women))
|
||||||
|
return dist_gmm, dist_men, dist_women
|
||||||
|
|
||||||
|
|
||||||
|
def expandgrid(*itrs):
|
||||||
|
mm = 0
|
||||||
|
combinations = list(itertools.product(*itrs))
|
||||||
|
|
||||||
|
for h_i, h_gt in combinations:
|
||||||
|
mm += abs(float(1 - h_i / h_gt))
|
||||||
|
|
||||||
|
mm /= len(combinations)
|
||||||
|
|
||||||
|
return combinations
|
||||||
|
|
||||||
|
|
||||||
|
def plot_dist(dist_gmm, dist_men, dist_women):
|
||||||
|
try:
|
||||||
|
import seaborn as sns
|
||||||
|
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")
|
||||||
|
plt.xlabel("X [cm]")
|
||||||
|
plt.ylabel("Height distributions of men and women")
|
||||||
|
plt.legend()
|
||||||
|
plt.show()
|
||||||
|
plt.close()
|
||||||
|
except ImportError:
|
||||||
|
print("Import Seaborn first")
|
||||||
|
|
||||||
|
|
||||||
|
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_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))
|
||||||
@ -1,148 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
import math
|
|
||||||
import os
|
|
||||||
import itertools
|
|
||||||
|
|
||||||
import numpy as np
|
|
||||||
import matplotlib.pyplot as plt
|
|
||||||
from matplotlib.patches import Ellipse
|
|
||||||
|
|
||||||
|
|
||||||
def paper():
|
|
||||||
"""Print paper figures"""
|
|
||||||
|
|
||||||
method = False
|
|
||||||
task_error = True
|
|
||||||
|
|
||||||
# Pull figure
|
|
||||||
if method:
|
|
||||||
std_1 = 0.75
|
|
||||||
fig = plt.figure(1)
|
|
||||||
ax = fig.add_subplot(1, 1, 1)
|
|
||||||
|
|
||||||
ell_3 = Ellipse((0, 2), width=std_1 * 2, height=0.3, angle=-90, color='b', fill=False, linewidth=2.5)
|
|
||||||
ell_4 = Ellipse((0, 2), width=std_1 * 3, height=0.3, angle=-90, color='r', fill=False,
|
|
||||||
linestyle='dashed', linewidth=2.5)
|
|
||||||
ax.add_patch(ell_4)
|
|
||||||
ax.add_patch(ell_3)
|
|
||||||
plt.plot(0, 2, marker='o', color='skyblue', markersize=9)
|
|
||||||
plt.plot([0, 3], [0, 4], 'k--')
|
|
||||||
plt.plot([0, -3], [0, 4], 'k--')
|
|
||||||
plt.xlim(-3, 3)
|
|
||||||
plt.ylim(0, 3.5)
|
|
||||||
plt.xticks([])
|
|
||||||
plt.yticks([])
|
|
||||||
plt.xlabel('X [m]')
|
|
||||||
plt.ylabel('Z [m]')
|
|
||||||
plt.savefig(os.path.join('docs', 'output_method.png'))
|
|
||||||
|
|
||||||
# Task error figure
|
|
||||||
if task_error:
|
|
||||||
plt.figure(2)
|
|
||||||
xx = np.linspace(0, 40, 100)
|
|
||||||
mu_men = 178
|
|
||||||
mu_women = 165
|
|
||||||
mu_child_m = 164
|
|
||||||
mu_child_w = 156
|
|
||||||
mm_gmm, mm_male, mm_female = gmm()
|
|
||||||
mm_young_male = mm_male + (mu_men - mu_child_m) / mu_men
|
|
||||||
mm_young_female = mm_female + (mu_women - mu_child_w) / mu_women
|
|
||||||
yy_male = target_error(xx, mm_male)
|
|
||||||
yy_female = target_error(xx, mm_female)
|
|
||||||
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_gps = np.linspace(5., 5., xx.shape[0])
|
|
||||||
plt.grid(linewidth=0.3)
|
|
||||||
plt.plot(xx, yy_gps, color='y', label='GPS')
|
|
||||||
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.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]")
|
|
||||||
plt.legend(loc=(0.01, 0.55)) # Location from 0 to 1 from lower left
|
|
||||||
plt.savefig(os.path.join('docs', 'task_error.png'))
|
|
||||||
|
|
||||||
|
|
||||||
def target_error(xx, mm):
|
|
||||||
return mm * xx
|
|
||||||
|
|
||||||
|
|
||||||
def gmm():
|
|
||||||
dist_gmm, dist_male, dist_female = height_distributions()
|
|
||||||
# get_percentile(dist_gmm)
|
|
||||||
mu_gmm = np.mean(dist_gmm)
|
|
||||||
mm_gmm = np.mean(np.abs(1 - mu_gmm / dist_gmm))
|
|
||||||
mm_male = np.mean(np.abs(1 - np.mean(dist_male) / dist_male))
|
|
||||||
mm_female = np.mean(np.abs(1 - np.mean(dist_female) / dist_female))
|
|
||||||
|
|
||||||
print("Mean of GMM distribution: {:.4f}".format(mu_gmm))
|
|
||||||
print("coefficient for gmm: {:.4f}".format(mm_gmm))
|
|
||||||
print("coefficient for men: {:.4f}".format(mm_male))
|
|
||||||
print("coefficient for women: {:.4f}".format(mm_female))
|
|
||||||
return mm_gmm, mm_male, mm_female
|
|
||||||
|
|
||||||
|
|
||||||
def get_confidence(xx, zz, std):
|
|
||||||
|
|
||||||
theta = math.atan2(zz, xx)
|
|
||||||
|
|
||||||
delta_x = std * math.cos(theta)
|
|
||||||
delta_z = std * math.sin(theta)
|
|
||||||
return (xx - delta_x, xx + delta_x), (zz - delta_z, zz + delta_z)
|
|
||||||
|
|
||||||
|
|
||||||
def height_distributions():
|
|
||||||
|
|
||||||
mu_men = 178
|
|
||||||
std_men = 7
|
|
||||||
mu_women = 165
|
|
||||||
std_women = 7
|
|
||||||
dist_men = np.random.normal(mu_men, std_men, int(1e7))
|
|
||||||
dist_women = np.random.normal(mu_women, std_women, int(1e7))
|
|
||||||
|
|
||||||
dist_gmm = np.concatenate((dist_men, dist_women))
|
|
||||||
return dist_gmm, dist_men, dist_women
|
|
||||||
|
|
||||||
|
|
||||||
def expandgrid(*itrs):
|
|
||||||
mm = 0
|
|
||||||
combinations = list(itertools.product(*itrs))
|
|
||||||
|
|
||||||
for h_i, h_gt in combinations:
|
|
||||||
mm += abs(float(1 - h_i / h_gt))
|
|
||||||
|
|
||||||
mm /= len(combinations)
|
|
||||||
|
|
||||||
return combinations
|
|
||||||
|
|
||||||
|
|
||||||
def plot_dist(dist_gmm, dist_men, dist_women):
|
|
||||||
try:
|
|
||||||
import seaborn as sns
|
|
||||||
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")
|
|
||||||
plt.xlabel("X [cm]")
|
|
||||||
plt.ylabel("Height distributions of men and women")
|
|
||||||
plt.legend()
|
|
||||||
plt.show()
|
|
||||||
plt.close()
|
|
||||||
except ImportError:
|
|
||||||
print("Import Seaborn first")
|
|
||||||
|
|
||||||
|
|
||||||
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_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))
|
|
||||||
@ -1,128 +0,0 @@
|
|||||||
# pylint: disable=R0915
|
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
import numpy as np
|
|
||||||
import matplotlib.pyplot as plt
|
|
||||||
from matplotlib.patches import Ellipse
|
|
||||||
|
|
||||||
from ..utils import get_task_error
|
|
||||||
|
|
||||||
|
|
||||||
def print_results(dic_stats, show=False):
|
|
||||||
|
|
||||||
"""
|
|
||||||
Visualize error as function of the distance on the test set and compare it with target errors based on human
|
|
||||||
height analyses. We consider:
|
|
||||||
Position error in meters due to a height variation of 7 cm (Standard deviation already knowing the sex)
|
|
||||||
Position error not knowing the gender (13cm as average difference --> 7.5cm of error to add)
|
|
||||||
"""
|
|
||||||
|
|
||||||
# ALE figure
|
|
||||||
dir_out = 'docs'
|
|
||||||
phase = 'test'
|
|
||||||
x_min = 0
|
|
||||||
x_max = 38
|
|
||||||
xx = np.linspace(0, 60, 100)
|
|
||||||
excl_clusters = ['all', '50', '>50', 'easy', 'moderate', 'hard']
|
|
||||||
clusters = tuple([clst for clst in dic_stats[phase]['our'] if clst not in excl_clusters])
|
|
||||||
yy_gender = get_task_error(xx)
|
|
||||||
yy_gps = np.linspace(5., 5., xx.shape[0])
|
|
||||||
|
|
||||||
plt.figure(0)
|
|
||||||
plt.grid(linewidth=0.2)
|
|
||||||
plt.xlabel("Distance [meters]")
|
|
||||||
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']
|
|
||||||
|
|
||||||
plt.plot(xx, yy_gps, '-', label="GPS Error", color='y')
|
|
||||||
for idx, method in enumerate(['m3d_merged', 'geom_merged', 'md_merged', 'our_merged', '3dop_merged']):
|
|
||||||
errs = [dic_stats[phase][method][clst]['mean'] for clst in clusters]
|
|
||||||
xxs = get_distances(clusters)
|
|
||||||
|
|
||||||
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 show:
|
|
||||||
plt.show()
|
|
||||||
else:
|
|
||||||
plt.savefig(os.path.join(dir_out, 'results.png'))
|
|
||||||
plt.close()
|
|
||||||
|
|
||||||
# SPREAD b Figure
|
|
||||||
plt.figure(1)
|
|
||||||
fig, ax = plt.subplots(2, sharex=True)
|
|
||||||
plt.xlabel("Distance [m]")
|
|
||||||
plt.ylabel("Aleatoric uncertainty [m]")
|
|
||||||
ar = 0.5 # Change aspect ratio of ellipses
|
|
||||||
scale = 1.5 # Factor to scale ellipses
|
|
||||||
rec_c = 0 # Center of the rectangle
|
|
||||||
plots_line = True
|
|
||||||
|
|
||||||
bbs = np.array([dic_stats[phase]['our'][key]['std_ale'] for key in clusters])
|
|
||||||
xxs = get_distances(clusters)
|
|
||||||
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]
|
|
||||||
|
|
||||||
if plots_line:
|
|
||||||
ax[0].plot(xxs, yys_up, '--', color='lightgreen', markersize=5, linewidth=1.4)
|
|
||||||
ax[0].plot(xxs, yys_down, '--', color='lightgreen', markersize=5, linewidth=1.4)
|
|
||||||
ax[0].plot(xxs, bbs_up, marker='s', color='b', markersize=5, linewidth=0.7)
|
|
||||||
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,
|
|
||||||
fill=False)
|
|
||||||
|
|
||||||
ax[0].add_patch(te)
|
|
||||||
ax[0].add_patch(bi)
|
|
||||||
|
|
||||||
fig.subplots_adjust(hspace=0.1)
|
|
||||||
plt.setp([aa.get_yticklabels() for aa in fig.axes[:-1]], visible=False)
|
|
||||||
plt.legend()
|
|
||||||
if show:
|
|
||||||
plt.show()
|
|
||||||
else:
|
|
||||||
plt.savefig(os.path.join(dir_out, 'spread_bi.png'))
|
|
||||||
plt.close()
|
|
||||||
|
|
||||||
|
|
||||||
def get_distances(clusters):
|
|
||||||
"""Extract distances as intermediate values between 2 clusters"""
|
|
||||||
|
|
||||||
clusters_ext = list(clusters)
|
|
||||||
clusters_ext.insert(0, str(0))
|
|
||||||
distances = []
|
|
||||||
for idx, _ in enumerate(clusters_ext[:-1]):
|
|
||||||
clst_0 = float(clusters_ext[idx])
|
|
||||||
clst_1 = float(clusters_ext[idx + 1])
|
|
||||||
distances.append((clst_1 - clst_0) / 2 + clst_0)
|
|
||||||
return tuple(distances)
|
|
||||||
|
|
||||||
|
|
||||||
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)
|
|
||||||
distance_points.append(dd)
|
|
||||||
distance_points.append(dd)
|
|
||||||
|
|
||||||
return distance_points, confidence_points
|
|
||||||
Loading…
Reference in New Issue
Block a user