Skip to content

Instantly share code, notes, and snippets.

@smidm
Created October 15, 2018 12:59
Show Gist options
  • Save smidm/fc02907a42f87c28c3b985bbb8c676d3 to your computer and use it in GitHub Desktop.
Save smidm/fc02907a42f87c28c3b985bbb8c676d3 to your computer and use it in GitHub Desktop.
multiple object tracking challenge data file and evaluation
import pandas as pd
import errno
import numpy as np
import sys
import warnings
def save_mot(filename, df):
df.to_csv(filename, header=False, index=False)
def load_mot(filename):
"""
Load Multiple Object Tacking Challenge trajectories file.
:param filename: mot filename
:return: DataFrame, columns frame and id start with 1 (MATLAB indexing)
"""
return pd.read_csv(filename, names=[u'frame', u'id', u'x', u'y', u'width', u'height', u'confidence'])
def eval_mot(df_gt, df_results, sqdistth=10000):
"""
Evaluate trajectories by comparing them to a ground truth.
:param df_gt: ground truth DataFrame, columns <frame>, <id>, <x>, <y>; <frame> and <id> are 1-based; see load_mot
:param df_results: result trajectories DataFrame, format same as df_gt
:param sqdistth: square of the distance threshold, only detections and ground truth objects closer than
the threshold can be matched
:return: (summary DataFrame, MOTAccumulator)
"""
nan_mask = (df_results.x == -1) | (df_results.x == -1) | df_results.x.isna() | df_results.y.isna()
if len(df_results[nan_mask]) > 0:
warnings.warn('stripping nans from the evaluated trajectories')
df_results = df_results[~nan_mask]
from motmetrics.utils import compare_to_groundtruth
import motmetrics as mm
columns_mapper = {'frame': 'FrameId', 'id': 'Id'}
acc = compare_to_groundtruth(df_gt.set_index(['frame', 'id']).rename(columns=columns_mapper),
df_results.set_index(['frame', 'id']).rename(columns=columns_mapper),
dist='euc', distfields=['x', 'y'], distth=sqdistth)
mh = mm.metrics.create()
return mh.compute(acc), acc
def eval_and_save(gt_file, mot_results_file, out_csv=None):
"""
Evaluate results and save metrics.
:param gt_file: ground truth filename (MOT format)
:param mot_results_file: results filename (MOT format)
:param out_csv: output file with a summary
"""
df_gt = load_mot(gt_file)
df_results = load_mot(mot_results_file)
print('Evaluating...')
assert sys.version_info >= (3, 5), 'motmetrics requires Python 3.5'
summary, acc = eval_mot(df_gt, df_results)
summary['motp_px'] = np.sqrt(summary['motp']) # convert from square pixels to pixels
import motmetrics as mm
print(mm.io.render_summary(summary))
if out_csv is not None:
summary.to_csv(out_csv, index=False)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment