Mercurial > hg > nsaunier > traffic-intelligence
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() |
