From cdca120582ce0d06c2e8bae8cd05c847bd925a3e Mon Sep 17 00:00:00 2001 From: Ramana Subramanyam Date: Tue, 28 Jul 2020 11:38:13 +0200 Subject: [PATCH 1/4] Added MODP metric --- motmetrics/metrics.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/motmetrics/metrics.py b/motmetrics/metrics.py index 49a789a2..92c0fed9 100644 --- a/motmetrics/metrics.py +++ b/motmetrics/metrics.py @@ -500,6 +500,24 @@ def num_fragmentations(df, obj_frequencies): simple_add_func.append(num_fragmentations) +def average_overlap(df): + matches = df.noraw.Type.isin(['MATCH']) + oid_ious = df.noraw.set_index('OId')['D'].fillna(0).groupby('OId').apply(list).to_dict().items() + return oid_ious + +simple_add_func.append(average_overlap) + + +def modp(df, average_overlap): + del df # unused + return np.mean([np.mean(d) for _, d in average_overlap]) + + +def modp_m(df, average_overlap): + del df # unused + return 1. - np.mean([np.mean(d) for _, d in average_overlap]) + + def motp(df, num_detections): """Multiple object tracker precision.""" return math_util.quiet_divide(df.noraw['D'].sum(), num_detections) @@ -742,6 +760,8 @@ def create(): m.register(partially_tracked, formatter='{:d}'.format) m.register(mostly_lost, formatter='{:d}'.format) m.register(num_fragmentations) + m.register(average_overlap) + m.register(modp, formatter='{:.3f}'.format) m.register(motp, formatter='{:.3f}'.format) m.register(mota, formatter='{:.1%}'.format) m.register(precision, formatter='{:.1%}'.format) @@ -772,6 +792,7 @@ def create(): 'num_misses', 'num_switches', 'num_fragmentations', + 'modp', 'mota', 'motp', 'num_transfer', From e1d72e644261599cc477b117c97eb4ed8ca721f5 Mon Sep 17 00:00:00 2001 From: Ramana Subramanyam Date: Tue, 28 Jul 2020 12:01:23 +0200 Subject: [PATCH 2/4] Added MODA --- motmetrics/metrics.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/motmetrics/metrics.py b/motmetrics/metrics.py index 92c0fed9..6c02d23c 100644 --- a/motmetrics/metrics.py +++ b/motmetrics/metrics.py @@ -518,6 +518,18 @@ def modp_m(df, average_overlap): return 1. - np.mean([np.mean(d) for _, d in average_overlap]) +def moda(df, average_overlap, num_misses, num_false_positives): + del df + num_oids = sum([len(d) for _, d in average_overlap]) + return math_util.quiet_divide(num_misses+num_false_positives, num_oids) + + +def moda_m(df, average_overlap, num_misses, num_false_positives): + del df + num_oids = sum([len(d) for _, d in average_overlap]) + return 1. - math_util.quiet_divide(num_misses+num_false_positives, num_oids) + + def motp(df, num_detections): """Multiple object tracker precision.""" return math_util.quiet_divide(df.noraw['D'].sum(), num_detections) @@ -762,6 +774,7 @@ def create(): m.register(num_fragmentations) m.register(average_overlap) m.register(modp, formatter='{:.3f}'.format) + m.register(moda, formatter='{:.3f}'.format) m.register(motp, formatter='{:.3f}'.format) m.register(mota, formatter='{:.1%}'.format) m.register(precision, formatter='{:.1%}'.format) @@ -793,6 +806,7 @@ def create(): 'num_switches', 'num_fragmentations', 'modp', + 'moda', 'mota', 'motp', 'num_transfer', From cf978ccb6b966531b5e17d555b586670508387b8 Mon Sep 17 00:00:00 2001 From: Ramana Subramanyam Date: Tue, 28 Jul 2020 12:49:43 +0200 Subject: [PATCH 3/4] Rectified mistake in averaging --- motmetrics/metrics.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/motmetrics/metrics.py b/motmetrics/metrics.py index 6c02d23c..405fd4ff 100644 --- a/motmetrics/metrics.py +++ b/motmetrics/metrics.py @@ -501,9 +501,9 @@ def num_fragmentations(df, obj_frequencies): def average_overlap(df): - matches = df.noraw.Type.isin(['MATCH']) - oid_ious = df.noraw.set_index('OId')['D'].fillna(0).groupby('OId').apply(list).to_dict().items() - return oid_ious + mdf = df.full[(df.full.Type == 'MATCH') | (df.full.Type == 'MISS')] + frame_dist = mdf.reset_index().set_index('FrameId')['D'].fillna(0).groupby('FrameId') + return frame_dist.apply(list).to_dict().items() simple_add_func.append(average_overlap) From 9bf8f128385a48dbb67dd99dd8e6521ddbd3ecdf Mon Sep 17 00:00:00 2001 From: Ramana Subramanyam Date: Sun, 2 Aug 2020 12:54:23 +0200 Subject: [PATCH 4/4] Fixed testing errors --- motmetrics/metrics.py | 39 ++++++++++++++++++++------------ motmetrics/tests/test_metrics.py | 8 +++---- 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/motmetrics/metrics.py b/motmetrics/metrics.py index 405fd4ff..822b27da 100644 --- a/motmetrics/metrics.py +++ b/motmetrics/metrics.py @@ -502,32 +502,40 @@ def num_fragmentations(df, obj_frequencies): def average_overlap(df): mdf = df.full[(df.full.Type == 'MATCH') | (df.full.Type == 'MISS')] - frame_dist = mdf.reset_index().set_index('FrameId')['D'].fillna(0).groupby('FrameId') - return frame_dist.apply(list).to_dict().items() + overlaps = mdf.reset_index().set_index('FrameId')['D'].fillna(0).groupby('FrameId') + return overlaps.agg(np.mean) + simple_add_func.append(average_overlap) -def modp(df, average_overlap): - del df # unused - return np.mean([np.mean(d) for _, d in average_overlap]) +def num_overlaps(df): + mdf = df.full[(df.full.Type == 'MATCH') | (df.full.Type == 'MISS')] + overlaps = mdf.reset_index().set_index('FrameId')['D'].fillna(0).groupby('FrameId') + return overlaps.count().sum() -def modp_m(df, average_overlap): - del df # unused - return 1. - np.mean([np.mean(d) for _, d in average_overlap]) +simple_add_func.append(num_overlaps) -def moda(df, average_overlap, num_misses, num_false_positives): +def modp(df, average_overlap): del df - num_oids = sum([len(d) for _, d in average_overlap]) - return math_util.quiet_divide(num_misses+num_false_positives, num_oids) + return average_overlap.mean() -def moda_m(df, average_overlap, num_misses, num_false_positives): +def modp_m(partials, average_overlap): + del partials + return average_overlap.mean() + + +def moda(df, num_overlaps, num_misses, num_false_positives): del df - num_oids = sum([len(d) for _, d in average_overlap]) - return 1. - math_util.quiet_divide(num_misses+num_false_positives, num_oids) + return math_util.quiet_divide(num_misses+num_false_positives, num_overlaps) + + +def moda_m(partials, num_overlaps, num_misses, num_false_positives): + del partials + return math_util.quiet_divide(num_misses+num_false_positives, num_overlaps) def motp(df, num_detections): @@ -772,7 +780,8 @@ def create(): m.register(partially_tracked, formatter='{:d}'.format) m.register(mostly_lost, formatter='{:d}'.format) m.register(num_fragmentations) - m.register(average_overlap) + m.register(average_overlap, formatter='{:d}'.format) + m.register(num_overlaps, formatter='{:d}'.format) m.register(modp, formatter='{:.3f}'.format) m.register(moda, formatter='{:.3f}'.format) m.register(motp, formatter='{:.3f}'.format) diff --git a/motmetrics/tests/test_metrics.py b/motmetrics/tests/test_metrics.py index ec1d0257..59f607f5 100644 --- a/motmetrics/tests/test_metrics.py +++ b/motmetrics/tests/test_metrics.py @@ -369,10 +369,10 @@ def compute_motchallenge(dname): print() print(mm.io.render_summary(summary, namemap=mm.io.motchallenge_metric_names, formatters=mh.formatters)) # assert ((summary['num_transfer'] - summary['num_migrate']) == (summary['num_switches'] - summary['num_ascend'])).all() # False assertion - summary = summary[mm.metrics.motchallenge_metrics[:15]] + summary = summary[mm.metrics.motchallenge_metrics[:17]] expected = pd.DataFrame([ - [0.557659, 0.729730, 0.451253, 0.582173, 0.941441, 8.0, 1, 6, 1, 13, 150, 7, 7, 0.526462, 0.277201], - [0.644619, 0.819760, 0.531142, 0.608997, 0.939920, 10.0, 5, 4, 1, 45, 452, 7, 6, 0.564014, 0.345904], - [0.624296, 0.799176, 0.512211, 0.602640, 0.940268, 18.0, 6, 10, 2, 58, 602, 14, 13, 0.555116, 0.330177], + [0.557659, 0.729730, 0.451253, 0.582173, 0.941441, 8.0, 1, 6, 1, 13, 150, 7, 7, 0.160351, 0.463068, 0.526462, 0.277201], + [0.644619, 0.819760, 0.531142, 0.608997, 0.939920, 10.0, 5, 4, 1, 45, 452, 7, 6, 0.210594, 0.432550, 0.564014, 0.345904], + [0.624296, 0.799176, 0.512211, 0.602640, 0.940268, 18.0, 6, 10, 2, 58, 602, 14, 13, 0.351243, 0.439707, 0.555116, 0.330177], ]) np.testing.assert_allclose(summary, expected, atol=1e-3)