comparison python/moving.py @ 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 463150a8e129
children 43ae3a1af290
comparison
equal deleted inserted replaced
722:49e99ca34a7d 723:e14e2101a5a9
1515 if d < matchingDistance: 1515 if d < matchingDistance:
1516 return d 1516 return d
1517 else: 1517 else:
1518 return matchingDistance + 1 1518 return matchingDistance + 1
1519 1519
1520 def computeClearMOT(annotations, objects, matchingDistance, firstInstant, lastInstant, debug = False): 1520 def computeClearMOT(annotations, objects, matchingDistance, firstInstant, lastInstant, returnMatches = False, debug = False):
1521 '''Computes the CLEAR MOT metrics 1521 '''Computes the CLEAR MOT metrics
1522 1522
1523 Reference: 1523 Reference:
1524 Keni, Bernardin, and Stiefelhagen Rainer. "Evaluating multiple object tracking performance: the CLEAR MOT metrics." EURASIP Journal on Image and Video Processing 2008 (2008) 1524 Keni, Bernardin, and Stiefelhagen Rainer. "Evaluating multiple object tracking performance: the CLEAR MOT metrics." EURASIP Journal on Image and Video Processing 2008 (2008)
1525 1525
1533 Output: returns motp, mota, mt, mme, fpt, gt 1533 Output: returns motp, mota, mt, mme, fpt, gt
1534 mt number of missed GT.frames (sum of the number of GT not detected in each frame) 1534 mt number of missed GT.frames (sum of the number of GT not detected in each frame)
1535 mme number of mismatches 1535 mme number of mismatches
1536 fpt number of false alarm.frames (tracker objects without match in each frame) 1536 fpt number of false alarm.frames (tracker objects without match in each frame)
1537 gt number of GT.frames 1537 gt number of GT.frames
1538
1539 if returnMatches is True, return as 2 new arguments the GT and TO matches
1540 matches is a dict
1541 matches[i] is the list of matches for GT/TO i
1542 the list of matches is a dict, indexed by time, for the TO/GT id matched at time t
1543 (an instant t not present in matches[i] at which GT/TO exists means a missed detection or false alarm)
1538 1544
1539 TODO: Should we use the distance as weights or just 1/0 if distance below matchingDistance? 1545 TODO: Should we use the distance as weights or just 1/0 if distance below matchingDistance?
1540 (add argument useDistanceForWeights = False)''' 1546 (add argument useDistanceForWeights = False)'''
1541 from munkres import Munkres 1547 from munkres import Munkres
1542 1548
1546 gt = 0 # number of GT.frames 1552 gt = 0 # number of GT.frames
1547 mt = 0 # number of missed GT.frames (sum of the number of GT not detected in each frame) 1553 mt = 0 # number of missed GT.frames (sum of the number of GT not detected in each frame)
1548 fpt = 0 # number of false alarm.frames (tracker objects without match in each frame) 1554 fpt = 0 # number of false alarm.frames (tracker objects without match in each frame)
1549 mme = 0 # number of mismatches 1555 mme = 0 # number of mismatches
1550 matches = {} # match[i] is the tracker track associated with GT i (using object references) 1556 matches = {} # match[i] is the tracker track associated with GT i (using object references)
1557 if returnMatches:
1558 gtMatches = {a.getNum():{} for a in annotations}
1559 toMatches = {o.getNum():{} for o in objects}
1551 for t in xrange(firstInstant, lastInstant+1): 1560 for t in xrange(firstInstant, lastInstant+1):
1552 previousMatches = matches.copy() 1561 previousMatches = matches.copy()
1553 # go through currently matched GT-TO and check if they are still matched withing matchingDistance 1562 # go through currently matched GT-TO and check if they are still matched withing matchingDistance
1554 toDelete = [] 1563 toDelete = []
1555 for a in matches: 1564 for a in matches:
1581 if costs[k][v] < matchingDistance: 1590 if costs[k][v] < matchingDistance:
1582 matches[unmatchedGTs[k]]=unmatchedTOs[v] 1591 matches[unmatchedGTs[k]]=unmatchedTOs[v]
1583 dist += costs[k][v] 1592 dist += costs[k][v]
1584 if debug: 1593 if debug:
1585 print('{} '.format(t)+', '.join(['{} {}'.format(k.getNum(), v.getNum()) for k,v in matches.iteritems()])) 1594 print('{} '.format(t)+', '.join(['{} {}'.format(k.getNum(), v.getNum()) for k,v in matches.iteritems()]))
1595 if returnMatches:
1596 for a,o in matches.iteritems():
1597 gtMatches[a.getNum()][t] = o.getNum()
1598 toMatches[o.getNum()][t] = a.getNum()
1586 1599
1587 # compute metrics elements 1600 # compute metrics elements
1588 ct += len(matches) 1601 ct += len(matches)
1589 mt += nGTs-len(matches) 1602 mt += nGTs-len(matches)
1590 fpt += nTOs-len(matches) 1603 fpt += nTOs-len(matches)
1613 motp = None 1626 motp = None
1614 if gt > 0: 1627 if gt > 0:
1615 mota = 1.-float(mt+fpt+mme)/gt 1628 mota = 1.-float(mt+fpt+mme)/gt
1616 else: 1629 else:
1617 mota = None 1630 mota = None
1618 return motp, mota, mt, mme, fpt, gt 1631 if returnMatches:
1619 1632 return motp, mota, mt, mme, fpt, gt, gtMatches, toMatches
1633 else:
1634 return motp, mota, mt, mme, fpt, gt
1620 1635
1621 def plotRoadUsers(objects, colors): 1636 def plotRoadUsers(objects, colors):
1622 '''Colors is a PlottingPropertyValues instance''' 1637 '''Colors is a PlottingPropertyValues instance'''
1623 from matplotlib.pyplot import figure, axis 1638 from matplotlib.pyplot import figure, axis
1624 figure() 1639 figure()