Skip to content

Commit 6c66616

Browse files
committed
adding final tests
1 parent db78966 commit 6c66616

File tree

8 files changed

+222
-288
lines changed

8 files changed

+222
-288
lines changed

dynosam/src/frontend/vision/FeatureTrackerBase.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ cv::Mat FeatureTrackerBase::computeImageTracks(const Frame& previous_frame, cons
147147

148148
objects_to_print.push_back(object_id);
149149
const cv::Scalar colour = Color::uniqueId(object_id).bgra();
150+
150151
const std::string label = "object " + std::to_string(object_id);
151152
utils::drawLabeledBoundingBox(img_rgb, label, colour, bb);
152153

dynosam_utils/src/evaluation/core/plotting.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ def plot(self,
127127
subplot_arg: int = 111,
128128
plot_start_end_markers: bool = False,
129129
length_unit: evo_plot.Unit = evo_plot.Unit.meters,
130-
**kwargs):
130+
**kwargs) -> Axes:
131131

132132
if obj_trajectories_ref is not None and len(obj_trajectories) != len(obj_trajectories_ref):
133133
raise evo_plot.PlotException(f"Expected trajectories and ref trajectories to have the same length {len(obj_trajectories)} != {len(obj_trajectories_ref)}")

dynosam_utils/src/evaluation/formatting_utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,13 @@ def prop_cycle() -> List[str]:
4242
def startup_plotting(font_size=14, line_width=1.5, output_dpi=600, tex_backend=True):
4343
"""Edited from https://github.com/nackjaylor/formatting_tips-tricks/
4444
"""
45-
4645
if tex_backend:
4746
try:
4847
plt.rcParams.update({
4948
"text.usetex": True,
5049
"font.family": "serif",
5150
"font.serif": ["Computer Modern Roman"],
51+
"text.latex.unicode": True
5252
})
5353
except:
5454
print("WARNING: LaTeX backend not configured properly. Not using.")

dynosam_utils/src/evaluation/tools.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -250,18 +250,18 @@ def calc_min_max(traj: evo_trajectory.PosePath3D):
250250
for t in trajectories:
251251
calc_min_max(t)
252252

253-
def set_ax_limits(self, ax: plt.Axes, plot_mode: evo_plot.PlotMode = evo_plot.PlotMode.xyz):
253+
def set_ax_limits(self, ax: plt.Axes, plot_mode: evo_plot.PlotMode = evo_plot.PlotMode.xyz, buffer = 0):
254254
from mpl_toolkits.mplot3d import Axes3D
255255

256256
if plot_mode == evo_plot.PlotMode.xyz and isinstance(ax, Axes3D):
257-
ax.set_xlim3d([self.min_x, self.max_x])
258-
ax.set_ylim3d([self.min_y, self.max_y])
259-
ax.set_zlim3d([self.min_z, self.max_z])
257+
ax.set_xlim3d([self.min_x - buffer, self.max_x + buffer])
258+
ax.set_ylim3d([self.min_y - buffer, self.max_y + buffer])
259+
ax.set_zlim3d([self.min_z - buffer, self.max_z + buffer])
260260
set_axes_equal(ax)
261261

262262
elif plot_mode == evo_plot.PlotMode.xy:
263-
ax.set_xlim([self.min_x, self.max_x])
264-
ax.set_ylim([self.min_y, self.max_y])
263+
ax.set_xlim([self.min_x - buffer , self.max_x + buffer])
264+
ax.set_ylim([self.min_y - buffer , self.max_y + buffer])
265265

266266

267267
class ObjectMotionTrajectory(object):
@@ -559,7 +559,7 @@ def plot_object_trajectories(
559559
subplot_arg: int = 111,
560560
plot_start_end_markers: bool = False,
561561
length_unit: evo_plot.Unit = evo_plot.Unit.meters,
562-
**kwargs) -> None:
562+
**kwargs) -> Axes:
563563

564564
from .core.plotting import ObjectTrajectoryPlotter
565565

dynosam_utils/src/make_stats_over_all_runs.py

Lines changed: 56 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424

2525
import matplotlib.pyplot as plt
2626

27+
from typing import Optional
28+
2729
# https://cduvallet.github.io/posts/2018/03/boxplots-in-python
2830
plt.rcdefaults()
2931

@@ -54,7 +56,7 @@ def get_stats(results_path, stats_keys):
5456
stats_dict = {stats_key : {"mean": [], "stddev": []} for stats_key in stats_keys.keys()}
5557

5658
keys = list(stats_keys.keys())
57-
print(f"Statis dict {stats_dict}")
59+
# print(f"Statis dict {stats_dict}")
5860

5961
for folder in sub_folders:
6062
if eval_files.check_if_results_folder(folder):
@@ -69,34 +71,50 @@ def get_stats(results_path, stats_keys):
6971

7072
return stats_dict
7173

72-
def main(results_path, details):
74+
75+
def plot(results_path, details_list):
76+
77+
num_details = len(details_list)
78+
fig, axes = plt.subplots(nrows=num_details, ncols=1, constrained_layout=True)
79+
80+
from string import ascii_lowercase
81+
82+
alphabet = iter(ascii_lowercase)
83+
84+
for ax, details in zip(axes, details_list):
85+
letter = next(alphabet)
86+
title = f"({letter})"
87+
88+
detail_name = details.get("name", None)
89+
if detail_name is not None:
90+
title += f" {detail_name}"
91+
92+
main(results_path, ax, details, title=title)
93+
94+
fig.tight_layout()
95+
plt.show()
96+
97+
def main(results_path:str, ax: plt.Axes, details: dict, title: Optional[str] = None):
7398
stats_keys = details["keys"]
7499
log_scale= details.get("log_scale", False)
75100
stats_dict = get_stats(results_path, stats_keys)
76101
means = {}
77-
stddev = {}
78-
print(log_scale)
79102
for key, stats in stats_dict.items():
80103

81104
label = stats_keys[key]["label"]
82-
83105
data = stats["mean"]
84106

85107
# label could be in twice if we want to map a stats key to the same label
86108
if label in means:
87-
means[label].extends(data)
109+
means[label].extend(data)
88110
else:
89111
means[label] = data
90-
# stddev[label] = stats["stddev"]
91112

92-
# df = pd.DataFrame({k: pd.Series(v) for k, v in means.items()})
93113
# Convert the dictionary into a DataFrame with varying lengths (introducing NaNs)
94114
df = pd.DataFrame(dict([(k, pd.Series(v)) for k, v in means.items()]))
115+
for series_name, series in df.items():
116+
print(f"{series_name}: max {series.mean()} min {series.min()} max {series.max()}")
95117

96-
# Prepare the data as a list of arrays (each array can have different length)
97-
data_for_boxplot = [df[col].dropna().values for col in df.columns]
98-
fig = plt.figure(figsize=(13,5))
99-
ax = fig.gca()
100118

101119

102120
boxprops = { 'linewidth': 2, 'facecolor': 'w'}
@@ -111,7 +129,14 @@ def main(results_path, details):
111129

112130
# boxplot = ax.boxplot(data_for_boxplot, labels=df.columns,patch_artist=True)
113131
# ax.set_yscale("log")
114-
sns.boxplot(data=df,ax=ax,fliersize=0, saturation=0.6,log_scale=log_scale,patch_artist=True)
132+
sns.boxplot(
133+
data=df,
134+
ax=ax,
135+
fliersize=0,
136+
saturation=0.6,
137+
log_scale=log_scale,
138+
patch_artist=True,
139+
width=0.8)
115140

116141
colour_iter = itertools.cycle(formatting.prop_cycle())
117142
sns.stripplot(data=df,
@@ -141,24 +166,21 @@ def main(results_path, details):
141166
ax.grid(True, alpha=0.5)
142167
ax.yaxis.grid(True)
143168
ax.xaxis.grid(False) # Show the vertical gridlines
144-
# ax.grid(True)
145-
# # ax.set_yscale("log")
146-
fig.tight_layout()
147169

170+
if title is not None:
171+
ax.set_title(title, loc="left", pad=10)
148172

149173

150-
plt.show()
151174

152175
def get_all_stats(results_folder, stats_dict, stats_key):
153176

154-
print(f"Starting results folder {results_folder}")
155-
print(f"Stats keys {stats_key}")
177+
# print(f"Starting results folder {results_folder}")
178+
# print(f"Stats keys {stats_key}")
156179

157180
sub_files = [os.path.join(results_folder, name) for name in os.listdir(results_folder)]
158181
# from all the logging files in the results folder, get those prefixed by stats
159182
stats_files = list(filter(lambda file: Path(file).name.startswith("stats_") and Path(file).name.endswith("csv"), sub_files))
160183

161-
print(stats_key)
162184
for stats_file in stats_files:
163185

164186

@@ -171,98 +193,28 @@ def get_all_stats(results_folder, stats_dict, stats_key):
171193
stats_dict["stddev"].append(float(row["stddev"]))
172194

173195

174-
# def make_batch_plots()
175-
176-
177-
# def make_POM_plots(results_path):
178-
# print(f"Iterating over parent results path {results_path}")
179-
# sub_folders = [os.path.join(results_path, name) for name in os.listdir(results_path) if os.path.isdir(os.path.join(results_path, name))]
180-
181-
# timing_results = {}
182-
183-
# for folder in sub_folders:
184-
# if not eval_files.check_if_results_folder(folder):
185-
# continue
186-
187-
# # ignore the frontend-testing ones
188-
# if not "_POM" in Path(folder).name:
189-
# continue
190-
191-
# print(f"Processing POM for {folder}")
192-
193-
# folder = Path(folder)
194-
# stats_file = folder / "statistics_samples.csv"
195-
# if not os.path.exists(stats_file):
196-
# continue
197196

198-
# reader = eval_files.read_csv(stats_file, ["label", "samples"])
199197

200-
# for row in reader:
201-
# label = row["label"]
202-
# samples = list(row["samples"])
203-
# samples = [float(i) for i in samples if i !=' ']
204-
205-
206-
207-
# if "joint_of_pose" in label:
208-
# if "joint_of_pose" not in timing_results:
209-
# timing_results["joint_of_pose"] = {"ms": [], "all": [], "inliers":[]}
210-
211-
# elif "object_nlo_refinement" in label:
212-
# if "object_nlo_refinement" not in timing_results:
213-
# timing_results["object_nlo_refinement"] = {"ms": [], "all": [], "inliers":[]}
214-
# else:
215-
# continue
216-
217-
# print(label)
218-
# print(len(samples))
219-
220-
# if label.endswith("joint_of_pose [ms]"):
221-
# timing_results["joint_of_pose"]["ms"].extend(samples)
222-
# elif label.endswith("joint_of_pose_num_vars_all"):
223-
# timing_results["joint_of_pose"]["all"].extend(samples)
224-
# elif label.endswith("joint_of_pose_num_vars_inliers"):
225-
# timing_results["joint_of_pose"]["inliers"].extend(samples)
226-
# # elif label.endswith("object_nlo_refinement [ms]"):
227-
# # timing_results["object_nlo_refinement"]["ms"].extend(samples)
228-
# # elif label.endswith("object_nlo_refinement_num_vars_all"):
229-
# # timing_results["object_nlo_refinement"]["all"].extend(samples)
230-
# # elif label.endswith("object_nlo_refinement_num_vars_inliers"):
231-
# # timing_results["object_nlo_refinement"]["inliers"].extend(samples)
232-
# # else:
233-
# # continue
234-
235-
# fig = plt.figure(figsize=(8,8))
236-
# joint_of_ax = fig.add_subplot(211)
237-
238-
# def plot_result(ax, result, label):
239-
# timing = result["ms"]
240-
# all = result["all"]
241-
242-
# ax.plot(timing, all, label=label)
243-
# ax.set_ylabel(r"Num Vars")
244-
# ax.set_xlabel(r"[ms]")
245-
246-
# plot_result(joint_of_ax, timing_results["joint_of_pose"], "joint_of_pose")
247-
248-
# plt.show()
249-
250-
251-
# KEYS = [{"frontend.feature_tracker"}]
252-
253-
254-
TRACKING_STATS_KEYS = {"name": "Tracking",
198+
TRACKING_STATS_KEYS = {"name": "Feature Tracking",
255199
"log_scale":False,
256200
"keys":{"frontend.feature_tracker": {"label":"Feature Tracker"},
201+
"tracking_timer": {"label":"Feature Tracker"},
257202
"static_feature": {"label": "Static Features"},
258203
"dynamic_feature": {"label": "Dynamic Features"}}
259204
}
260205

261-
REFINEMENT_STATS_KEYS = {"name": "Refinement",
206+
207+
BACKEND_STATS_KEYS = {"name": "Back-end",
208+
"log_scale":False,
209+
"keys":{
210+
"full_batch_opt": {"label":"Feature Tracker"}}
211+
}
212+
213+
REFINEMENT_STATS_KEYS = {"name": "Motion Estimation",
262214
"log_scale":True,
263215
"keys":{"motion_solver.solve_3d2d": {"label":"PnP Solve"},
264-
"joint_of_pose [ms]": {"label": "Joint Optical Flow"},
265-
"object_nlo_refinement [ms]": {"label": "3D Motion Refinement"}}
216+
"joint_of_pose [ms]": {"label": "Optical Flow Refinement"},
217+
"object_nlo_refinement [ms]": {"label": "Motion Refinement"}}
266218
}
267219

268220
# hardcoded key to search for
@@ -271,20 +223,14 @@ def get_all_stats(results_folder, stats_dict, stats_key):
271223
# OPT_STATS_KEYS=["batch_opt [ms]", "sliding_window_optimise [ms]"]
272224
# OPT_STATS_KEYS=["batch_opt_num_vars", "sliding_window_optimise_num_vars"]
273225

274-
STATS_KEYS = TRACKING_STATS_KEYS
226+
STATS_KEYS = REFINEMENT_STATS_KEYS
275227

276228

277229
if __name__ == "__main__":
278230
parser = parser()
279231
argcomplete.autocomplete(parser)
280232
args = parser.parse_args()
281-
if main(args.dynosam_results_path, STATS_KEYS):
233+
if plot(args.dynosam_results_path, [TRACKING_STATS_KEYS,REFINEMENT_STATS_KEYS,BACKEND_STATS_KEYS]):
282234
sys.exit(os.EX_OK)
283235
else:
284236
sys.exit(os.EX_IOERR)
285-
286-
287-
# if make_POM_plots(args.dynosam_results_path):
288-
# sys.exit(os.EX_OK)
289-
# else:
290-
# sys.exit(os.EX_IOERR)

0 commit comments

Comments
 (0)