comparison python/moving.py @ 729:dad99b86a104 dev

merge with default
author Nicolas Saunier <nicolas.saunier@polymtl.ca>
date Mon, 10 Aug 2015 17:52:19 -0400
parents c6d4ea05a2d0
children 15ddc8715236
comparison
equal deleted inserted replaced
728:4e89341edd29 729:dad99b86a104
76 elif self.last < interval2.first: 76 elif self.last < interval2.first:
77 return interval2.first - self.last 77 return interval2.first - self.last
78 else: 78 else:
79 return None 79 return None
80 80
81 def unionIntervals(intervals): 81 @classmethod
82 'returns the smallest interval containing all intervals' 82 def unionIntervals(cls, intervals):
83 inter = intervals[0] 83 'returns the smallest interval containing all intervals'
84 for i in intervals[1:]: 84 inter = cls(intervals[0].first, intervals[0].last)
85 inter = Interval.union(inter, i) 85 for i in intervals[1:]:
86 return inter 86 inter = cls.union(inter, i)
87 return inter
87 88
88 89
89 class TimeInterval(Interval): 90 class TimeInterval(Interval):
90 '''Temporal interval: set of instants at fixed time step, between first and last, included 91 '''Temporal interval: set of instants at fixed time step, between first and last, included
91 92
1065 return obj 1066 return obj
1066 else: 1067 else:
1067 print 'The object does not exist at '+str(inter) 1068 print 'The object does not exist at '+str(inter)
1068 return None 1069 return None
1069 1070
1071 def getObjectsInMask(self, mask, homography = None, minLength = 1):
1072 '''Returns new objects made of the positions in the mask
1073 mask is in the destination of the homography space'''
1074 if homography is not None:
1075 self.projectedPositions = self.positions.project(homography)
1076 else:
1077 self.projectedPositions = self.positions
1078 def inMask(positions, i, mask):
1079 p = positions[i]
1080 return mask[p.y, p.x] != 0.
1081
1082 #subTimeIntervals self.getFirstInstant()+i
1083 filteredIndices = [inMask(self.projectedPositions, i, mask) for i in range(int(self.length()))]
1084 # 'connected components' in subTimeIntervals
1085 l = 0
1086 intervalLabels = []
1087 prev = True
1088 for i in filteredIndices:
1089 if i:
1090 if not prev: # new interval
1091 l += 1
1092 intervalLabels.append(l)
1093 else:
1094 intervalLabels.append(-1)
1095 prev = i
1096 intervalLabels = array(intervalLabels)
1097 subObjects = []
1098 for l in set(intervalLabels):
1099 if l >= 0:
1100 if sum(intervalLabels == l) >= minLength:
1101 times = [self.getFirstInstant()+i for i in range(len(intervalLabels)) if intervalLabels[i] == l]
1102 subTimeInterval = TimeInterval(min(times), max(times))
1103 subObjects.append(self.getObjectInTimeInterval(subTimeInterval))
1104
1105 return subObjects
1106
1070 def getPositions(self): 1107 def getPositions(self):
1071 return self.positions 1108 return self.positions
1072 1109
1073 def getVelocities(self): 1110 def getVelocities(self):
1074 return self.velocities 1111 return self.velocities
1515 if d < matchingDistance: 1552 if d < matchingDistance:
1516 return d 1553 return d
1517 else: 1554 else:
1518 return matchingDistance + 1 1555 return matchingDistance + 1
1519 1556
1520 def computeClearMOT(annotations, objects, matchingDistance, firstInstant, lastInstant, debug = False): 1557 def computeClearMOT(annotations, objects, matchingDistance, firstInstant, lastInstant, returnMatches = False, debug = False):
1521 '''Computes the CLEAR MOT metrics 1558 '''Computes the CLEAR MOT metrics
1522 1559
1523 Reference: 1560 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) 1561 Keni, Bernardin, and Stiefelhagen Rainer. "Evaluating multiple object tracking performance: the CLEAR MOT metrics." EURASIP Journal on Image and Video Processing 2008 (2008)
1525 1562
1533 Output: returns motp, mota, mt, mme, fpt, gt 1570 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) 1571 mt number of missed GT.frames (sum of the number of GT not detected in each frame)
1535 mme number of mismatches 1572 mme number of mismatches
1536 fpt number of false alarm.frames (tracker objects without match in each frame) 1573 fpt number of false alarm.frames (tracker objects without match in each frame)
1537 gt number of GT.frames 1574 gt number of GT.frames
1575
1576 if returnMatches is True, return as 2 new arguments the GT and TO matches
1577 matches is a dict
1578 matches[i] is the list of matches for GT/TO i
1579 the list of matches is a dict, indexed by time, for the TO/GT id matched at time t
1580 (an instant t not present in matches[i] at which GT/TO exists means a missed detection or false alarm)
1538 1581
1539 TODO: Should we use the distance as weights or just 1/0 if distance below matchingDistance? 1582 TODO: Should we use the distance as weights or just 1/0 if distance below matchingDistance?
1540 (add argument useDistanceForWeights = False)''' 1583 (add argument useDistanceForWeights = False)'''
1541 from munkres import Munkres 1584 from munkres import Munkres
1542 1585
1546 gt = 0 # number of GT.frames 1589 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) 1590 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) 1591 fpt = 0 # number of false alarm.frames (tracker objects without match in each frame)
1549 mme = 0 # number of mismatches 1592 mme = 0 # number of mismatches
1550 matches = {} # match[i] is the tracker track associated with GT i (using object references) 1593 matches = {} # match[i] is the tracker track associated with GT i (using object references)
1594 if returnMatches:
1595 gtMatches = {a.getNum():{} for a in annotations}
1596 toMatches = {o.getNum():{} for o in objects}
1551 for t in xrange(firstInstant, lastInstant+1): 1597 for t in xrange(firstInstant, lastInstant+1):
1552 previousMatches = matches.copy() 1598 previousMatches = matches.copy()
1553 # go through currently matched GT-TO and check if they are still matched withing matchingDistance 1599 # go through currently matched GT-TO and check if they are still matched withing matchingDistance
1554 toDelete = [] 1600 toDelete = []
1555 for a in matches: 1601 for a in matches:
1581 if costs[k][v] < matchingDistance: 1627 if costs[k][v] < matchingDistance:
1582 matches[unmatchedGTs[k]]=unmatchedTOs[v] 1628 matches[unmatchedGTs[k]]=unmatchedTOs[v]
1583 dist += costs[k][v] 1629 dist += costs[k][v]
1584 if debug: 1630 if debug:
1585 print('{} '.format(t)+', '.join(['{} {}'.format(k.getNum(), v.getNum()) for k,v in matches.iteritems()])) 1631 print('{} '.format(t)+', '.join(['{} {}'.format(k.getNum(), v.getNum()) for k,v in matches.iteritems()]))
1632 if returnMatches:
1633 for a,o in matches.iteritems():
1634 gtMatches[a.getNum()][t] = o.getNum()
1635 toMatches[o.getNum()][t] = a.getNum()
1586 1636
1587 # compute metrics elements 1637 # compute metrics elements
1588 ct += len(matches) 1638 ct += len(matches)
1589 mt += nGTs-len(matches) 1639 mt += nGTs-len(matches)
1590 fpt += nTOs-len(matches) 1640 fpt += nTOs-len(matches)
1613 motp = None 1663 motp = None
1614 if gt > 0: 1664 if gt > 0:
1615 mota = 1.-float(mt+fpt+mme)/gt 1665 mota = 1.-float(mt+fpt+mme)/gt
1616 else: 1666 else:
1617 mota = None 1667 mota = None
1618 return motp, mota, mt, mme, fpt, gt 1668 if returnMatches:
1619 1669 return motp, mota, mt, mme, fpt, gt, gtMatches, toMatches
1670 else:
1671 return motp, mota, mt, mme, fpt, gt
1620 1672
1621 def plotRoadUsers(objects, colors): 1673 def plotRoadUsers(objects, colors):
1622 '''Colors is a PlottingPropertyValues instance''' 1674 '''Colors is a PlottingPropertyValues instance'''
1623 from matplotlib.pyplot import figure, axis 1675 from matplotlib.pyplot import figure, axis
1624 figure() 1676 figure()