changeset 723:e14e2101a5a9

returns detailed matching information for clear mot
author Nicolas Saunier <nicolas.saunier@polymtl.ca>
date Thu, 06 Aug 2015 17:47:04 -0400
parents 49e99ca34a7d
children b75d0c258ca9
files python/moving.py scripts/compute-clearmot.py
diffstat 2 files changed, 29 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/python/moving.py	Wed Aug 05 00:12:52 2015 -0400
+++ b/python/moving.py	Thu Aug 06 17:47:04 2015 -0400
@@ -1517,7 +1517,7 @@
         else:
             return matchingDistance + 1
 
-def computeClearMOT(annotations, objects, matchingDistance, firstInstant, lastInstant, debug = False):
+def computeClearMOT(annotations, objects, matchingDistance, firstInstant, lastInstant, returnMatches = False, debug = False):
     '''Computes the CLEAR MOT metrics 
 
     Reference:
@@ -1536,6 +1536,12 @@
     fpt number of false alarm.frames (tracker objects without match in each frame)
     gt number of GT.frames
 
+    if returnMatches is True, return as 2 new arguments the GT and TO matches
+    matches is a dict
+    matches[i] is the list of matches for GT/TO i
+    the list of matches is a dict, indexed by time, for the TO/GT id matched at time t 
+    (an instant t not present in matches[i] at which GT/TO exists means a missed detection or false alarm)
+
     TODO: Should we use the distance as weights or just 1/0 if distance below matchingDistance?
     (add argument useDistanceForWeights = False)'''
     from munkres import Munkres
@@ -1548,6 +1554,9 @@
     fpt = 0 # number of false alarm.frames (tracker objects without match in each frame)
     mme = 0 # number of mismatches
     matches = {} # match[i] is the tracker track associated with GT i (using object references)
+    if returnMatches:
+        gtMatches = {a.getNum():{} for a in annotations}
+        toMatches = {o.getNum():{} for o in objects}
     for t in xrange(firstInstant, lastInstant+1):
         previousMatches = matches.copy()
         # go through currently matched GT-TO and check if they are still matched withing matchingDistance
@@ -1583,6 +1592,10 @@
                     dist += costs[k][v]
         if debug:
             print('{} '.format(t)+', '.join(['{} {}'.format(k.getNum(), v.getNum()) for k,v in matches.iteritems()]))
+        if returnMatches:
+            for a,o in matches.iteritems():
+                gtMatches[a.getNum()][t] = o.getNum()
+                toMatches[o.getNum()][t] = a.getNum()
         
         # compute metrics elements
         ct += len(matches)
@@ -1615,8 +1628,10 @@
         mota = 1.-float(mt+fpt+mme)/gt
     else:
         mota = None
-    return motp, mota, mt, mme, fpt, gt
-
+    if returnMatches:
+        return motp, mota, mt, mme, fpt, gt, gtMatches, toMatches
+    else:
+        return motp, mota, mt, mme, fpt, gt
 
 def plotRoadUsers(objects, colors):
     '''Colors is a PlottingPropertyValues instance'''
--- a/scripts/compute-clearmot.py	Wed Aug 05 00:12:52 2015 -0400
+++ b/scripts/compute-clearmot.py	Thu Aug 06 17:47:04 2015 -0400
@@ -18,6 +18,7 @@
 parser.add_argument('-m', dest = 'matchingDistance', help = 'matching distance between tracker and ground truth trajectories', required = True, type = float)
 parser.add_argument('-f', dest = 'firstInstant', help = 'first instant for measurement', required = True, type = int)
 parser.add_argument('-l', dest = 'lastInstant', help = 'last instant for measurement', required = True, type = int)
+parser.add_argument('--display', dest = 'display', help = 'display the ground truth to object matches (graphically)', action = 'store_true')
 args = parser.parse_args()
 
 if args.homographyFilename is not None:
@@ -30,10 +31,19 @@
 for a in annotations:
     a.computeCentroidTrajectory(homography)
 
-motp, mota, mt, mme, fpt, gt = moving.computeClearMOT(annotations, objects, args.matchingDistance, args.firstInstant, args.lastInstant)
+if args.display:
+    motp, mota, mt, mme, fpt, gt, gtMatches, toMatches = moving.computeClearMOT(annotations, objects, args.matchingDistance, args.firstInstant, args.lastInstant, True)
+else:
+    motp, mota, mt, mme, fpt, gt = moving.computeClearMOT(annotations, objects, args.matchingDistance, args.firstInstant, args.lastInstant)
+
 
 print 'MOTP: {}'.format(motp)
 print 'MOTA: {}'.format(mota)
 print 'Number of missed objects.frames: {}'.format(mt)
 print 'Number of mismatches: {}'.format(mme)
 print 'Number of false alarms.frames: {}'.format(fpt)
+if args.display:
+    print('Ground truth matches')
+    print(gtMatches)
+    print('Object matches')
+    print toMatches