comparison python/moving.py @ 1012:01db14e947e4

resolved
author Wendlasida
date Fri, 01 Jun 2018 10:47:49 -0400
parents 4f0312bee393 cc7c6b821ae6
children d6f121ded971
comparison
equal deleted inserted replaced
1011:4f0312bee393 1012:01db14e947e4
120 120
121 def __iter__(self): 121 def __iter__(self):
122 self.iterInstantNum = -1 122 self.iterInstantNum = -1
123 return self 123 return self
124 124
125 def next(self): 125 def __next__(self):
126 if self.iterInstantNum >= self.length()-1: 126 if self.iterInstantNum >= self.length()-1:
127 raise StopIteration 127 raise StopIteration
128 else: 128 else:
129 self.iterInstantNum += 1 129 self.iterInstantNum += 1
130 return self[self.iterInstantNum] 130 return self[self.iterInstantNum]
169 def getFirstInstant(self): 169 def getFirstInstant(self):
170 return self.timeInterval.first 170 return self.timeInterval.first
171 171
172 def getLastInstant(self): 172 def getLastInstant(self):
173 return self.timeInterval.last 173 return self.timeInterval.last
174
175 def setFirstInstant(self, t):
176 if t <= self.timeInterval.last:
177 self.timeInterval.first = t
178 else:
179 print('new first instant is after last, not changing')
180
181 def setLastInstant(self, t):
182 if t >= self.timeInterval.first:
183 self.timeInterval.last = t
184 else:
185 print('new last instant is before first, not changing')
174 186
175 def getTimeInterval(self): 187 def getTimeInterval(self):
176 return self.timeInterval 188 return self.timeInterval
177 189
178 def existsAtInstant(self, t): 190 def existsAtInstant(self, t):
377 '''Optimized tests of a series of points within (Shapely) polygon (not prepared)''' 389 '''Optimized tests of a series of points within (Shapely) polygon (not prepared)'''
378 if type(polygon) == PreparedGeometry: 390 if type(polygon) == PreparedGeometry:
379 prepared_polygon = polygon 391 prepared_polygon = polygon
380 else: 392 else:
381 prepared_polygon = prep(polygon) 393 prepared_polygon = prep(polygon)
382 return filter(prepared_polygon.contains, points) 394 return list(filter(prepared_polygon.contains, points))
383 395
384 # Functions for coordinate transformation 396 # Functions for coordinate transformation
385 # From Paul St-Aubin's PVA tools 397 # From Paul St-Aubin's PVA tools
386 def subsec_spline_dist(splines): 398 def subsec_spline_dist(splines):
387 ''' Prepare list of spline subsegments from a spline list. 399 ''' Prepare list of spline subsegments from a spline list.
415 427
416 def prepareSplines(splines): 428 def prepareSplines(splines):
417 'Approximates slope singularity by giving some slope roundoff; account for roundoff error' 429 'Approximates slope singularity by giving some slope roundoff; account for roundoff error'
418 for spline in splines: 430 for spline in splines:
419 p1 = spline[0] 431 p1 = spline[0]
420 for i in xrange(len(spline)-1): 432 for i in range(len(spline)-1):
421 p2 = spline[i+1] 433 p2 = spline[i+1]
422 if(round(p1.x, 10) == round(p2.x, 10)): 434 if(round(p1.x, 10) == round(p2.x, 10)):
423 p2.x += 0.0000000001 435 p2.x += 0.0000000001
424 if(round(p1.y, 10) == round(p2.y, 10)): 436 if(round(p1.y, 10) == round(p2.y, 10)):
425 p2.y += 0.0000000001 437 p2.y += 0.0000000001
664 @staticmethod 676 @staticmethod
665 def generate(p, v, nPoints): 677 def generate(p, v, nPoints):
666 t = Trajectory() 678 t = Trajectory()
667 p0 = Point(p.x, p.y) 679 p0 = Point(p.x, p.y)
668 t.addPosition(p0) 680 t.addPosition(p0)
669 for i in xrange(nPoints-1): 681 for i in range(nPoints-1):
670 p0 += v 682 p0 += v
671 t.addPosition(p0) 683 t.addPosition(p0)
672 return t, Trajectory([[v.x]*nPoints, [v.y]*nPoints]) 684 return t, Trajectory([[v.x]*nPoints, [v.y]*nPoints])
673 685
674 @staticmethod 686 @staticmethod
703 return Trajectory([self.positions[0][i],self.positions[1][i]]) 715 return Trajectory([self.positions[0][i],self.positions[1][i]])
704 else: 716 else:
705 raise TypeError("Invalid argument type.") 717 raise TypeError("Invalid argument type.")
706 718
707 def __str__(self): 719 def __str__(self):
708 return ' '.join([self.__getitem__(i).__str__() for i in xrange(self.length())]) 720 return ' '.join([self.__getitem__(i).__str__() for i in range(self.length())])
709 721
710 def __repr__(self): 722 def __repr__(self):
711 return self.__str__() 723 return self.__str__()
712 724
713 def __iter__(self): 725 def __iter__(self):
714 self.iterInstantNum = 0 726 self.iterInstantNum = 0
715 return self 727 return self
716 728
717 def next(self): 729 def __next__(self):
718 if self.iterInstantNum >= self.length(): 730 if self.iterInstantNum >= self.length():
719 raise StopIteration 731 raise StopIteration
720 else: 732 else:
721 self.iterInstantNum += 1 733 self.iterInstantNum += 1
722 return self[self.iterInstantNum-1] 734 return self[self.iterInstantNum-1]
817 return Trajectory([[alpha*x for x in self.getXCoordinates()], 829 return Trajectory([[alpha*x for x in self.getXCoordinates()],
818 [alpha*y for y in self.getYCoordinates()]]) 830 [alpha*y for y in self.getYCoordinates()]])
819 831
820 def differentiate(self, doubleLastPosition = False): 832 def differentiate(self, doubleLastPosition = False):
821 diff = Trajectory() 833 diff = Trajectory()
822 for i in xrange(1, self.length()): 834 for i in range(1, self.length()):
823 diff.addPosition(self[i]-self[i-1]) 835 diff.addPosition(self[i]-self[i-1])
824 if doubleLastPosition: 836 if doubleLastPosition:
825 diff.addPosition(diff[-1]) 837 diff.addPosition(diff[-1])
826 return diff 838 return diff
827 839
854 Can be accessed through getDistance(idx) and getCumulativeDistance(idx)''' 866 Can be accessed through getDistance(idx) and getCumulativeDistance(idx)'''
855 self.distances = [] 867 self.distances = []
856 self.cumulativeDistances = [0.] 868 self.cumulativeDistances = [0.]
857 p1 = self[0] 869 p1 = self[0]
858 cumulativeDistance = 0. 870 cumulativeDistance = 0.
859 for i in xrange(self.length()-1): 871 for i in range(self.length()-1):
860 p2 = self[i+1] 872 p2 = self[i+1]
861 self.distances.append(Point.distanceNorm2(p1,p2)) 873 self.distances.append(Point.distanceNorm2(p1,p2))
862 cumulativeDistance += self.distances[-1] 874 cumulativeDistance += self.distances[-1]
863 self.cumulativeDistances.append(cumulativeDistance) 875 self.cumulativeDistances.append(cumulativeDistance)
864 p1 = p2 876 p1 = p2
921 intersects with the segment of extremities p1 and p2 933 intersects with the segment of extremities p1 and p2
922 Returns an empty list if there is no crossing''' 934 Returns an empty list if there is no crossing'''
923 indices = [] 935 indices = []
924 intersections = [] 936 intersections = []
925 937
926 for i in xrange(self.length()-1): 938 for i in range(self.length()-1):
927 q1=self.__getitem__(i) 939 q1=self.__getitem__(i)
928 q2=self.__getitem__(i+1) 940 q2=self.__getitem__(i+1)
929 p = segmentIntersection(q1, q2, p1, p2) 941 p = segmentIntersection(q1, q2, p1, p2)
930 if p is not None: 942 if p is not None:
931 if q1.x != q2.x: 943 if q1.x != q2.x:
943 intersects with the line going through p1 and p2 955 intersects with the line going through p1 and p2
944 Returns an empty list if there is no crossing''' 956 Returns an empty list if there is no crossing'''
945 indices = [] 957 indices = []
946 intersections = [] 958 intersections = []
947 959
948 for i in xrange(self.length()-1): 960 for i in range(self.length()-1):
949 q1=self.__getitem__(i) 961 q1=self.__getitem__(i)
950 q2=self.__getitem__(i+1) 962 q2=self.__getitem__(i+1)
951 p = segmentLineIntersection(p1, p2, q1, q2) 963 p = segmentLineIntersection(p1, p2, q1, q2)
952 if p is not None: 964 if p is not None:
953 if q1.x != q2.x: 965 if q1.x != q2.x:
1076 self.lanes[i] = lane 1088 self.lanes[i] = lane
1077 1089
1078 def differentiate(self, doubleLastPosition = False): 1090 def differentiate(self, doubleLastPosition = False):
1079 diff = CurvilinearTrajectory() 1091 diff = CurvilinearTrajectory()
1080 p1 = self[0] 1092 p1 = self[0]
1081 for i in xrange(1, self.length()): 1093 for i in range(1, self.length()):
1082 p2 = self[i] 1094 p2 = self[i]
1083 diff.addPositionSYL(p2[0]-p1[0], p2[1]-p1[1], p1[2]) 1095 diff.addPositionSYL(p2[0]-p1[0], p2[1]-p1[1], p1[2])
1084 p1=p2 1096 p1=p2
1085 if doubleLastPosition and self.length() > 1: 1097 if doubleLastPosition and self.length() > 1:
1086 diff.addPosition(diff[-1]) 1098 diff.addPosition(diff[-1])
1090 '''Returns a list of the indices at which the trajectory 1102 '''Returns a list of the indices at which the trajectory
1091 goes past the curvilinear coordinate S1 1103 goes past the curvilinear coordinate S1
1092 (in provided lane if lane is not None) 1104 (in provided lane if lane is not None)
1093 Returns an empty list if there is no crossing''' 1105 Returns an empty list if there is no crossing'''
1094 indices = [] 1106 indices = []
1095 for i in xrange(self.length()-1): 1107 for i in range(self.length()-1):
1096 q1=self.__getitem__(i) 1108 q1=self.__getitem__(i)
1097 q2=self.__getitem__(i+1) 1109 q2=self.__getitem__(i+1)
1098 if q1[0] <= S1 < q2[0] and (lane is None or (self.lanes[i] == lane and self.lanes[i+1] == lane)): 1110 if q1[0] <= S1 < q2[0] and (lane is None or (self.lanes[i] == lane and self.lanes[i+1] == lane)):
1099 indices.append(i+(S1-q1[0])/(q2[0]-q1[0])) 1111 indices.append(i+(S1-q1[0])/(q2[0]-q1[0]))
1100 return indices 1112 return indices
1259 self.positions = positions 1271 self.positions = positions
1260 1272
1261 @staticmethod 1273 @staticmethod
1262 def concatenate(obj1, obj2, num = None): 1274 def concatenate(obj1, obj2, num = None):
1263 '''Concatenates two objects supposed to overlap temporally ''' 1275 '''Concatenates two objects supposed to overlap temporally '''
1264 if num is None: 1276 if num is None:
1265 newNum = obj1.getNum() 1277 newNum = obj1.getNum()
1266 else: 1278 else:
1267 newNum = num 1279 newNum = num
1268 commonTimeInterval = obj1.commonTimeInterval(obj2) 1280 commonTimeInterval = obj1.commonTimeInterval(obj2)
1269 if commonTimeInterval.empty(): 1281 if commonTimeInterval.empty():
1270 print('The two objects\' time intervals do not overlap: obj1 {} and obj2 {}'.format(obj1.getTimeInterval(), obj2.getTimeInterval())) 1282 print('The two objects\' time intervals do not overlap: obj1 {} and obj2 {}'.format(obj1.getTimeInterval(), obj2.getTimeInterval()))
1271 emptyInterval = TimeInterval(min(obj1.getLastInstant(),obj2.getLastInstant()) , max(obj1.getFirstInstant(),obj2.getFirstInstant())) 1283 emptyInterval = TimeInterval(min(obj1.getLastInstant(),obj2.getLastInstant()) , max(obj1.getFirstInstant(),obj2.getFirstInstant()))
1272 positions = Trajectory() 1284 positions = Trajectory()
1287 py+=vitessey 1299 py+=vitessey
1288 1300
1289 newObject = MovingObject(newNum, emptyInterval, positions, velocities, userType = obj1.getUserType()) 1301 newObject = MovingObject(newNum, emptyInterval, positions, velocities, userType = obj1.getUserType())
1290 newObject.features = [MovingObject(newNum, emptyInterval, positions, velocities, userType = obj1.getUserType())] #In case there is features to add when we recursively call concatenate 1302 newObject.features = [MovingObject(newNum, emptyInterval, positions, velocities, userType = obj1.getUserType())] #In case there is features to add when we recursively call concatenate
1291 return MovingObject.concatenate(MovingObject.concatenate(obj1, newObject),obj2) 1303 return MovingObject.concatenate(MovingObject.concatenate(obj1, newObject),obj2)
1292 1304
1293
1294 else: 1305 else:
1295 newTimeInterval = TimeInterval.union(obj1.getTimeInterval(), obj2.getTimeInterval()) 1306 newTimeInterval = TimeInterval.union(obj1.getTimeInterval(), obj2.getTimeInterval())
1296 # positions 1307 # positions
1297 positions = Trajectory() 1308 positions = Trajectory()
1298 for t in newTimeInterval: 1309 for t in newTimeInterval:
1422 coords.append(NaN) 1433 coords.append(NaN)
1423 plot(instants, coords, options, **kwargs) 1434 plot(instants, coords, options, **kwargs)
1424 if withOrigin and len(instants)>0: 1435 if withOrigin and len(instants)>0:
1425 plot([instants[0]], [coords[0]], 'ro', **kwargs) 1436 plot([instants[0]], [coords[0]], 'ro', **kwargs)
1426 else: 1437 else:
1427 print('Object {} has no curvilinear positions'.format(self.getNum())) 1438 print('Object {} has no curvilinear positions'.format(self.getNum()))
1428 1439
1429 def setUserType(self, userType): 1440 def setUserType(self, userType):
1430 self.userType = userType 1441 self.userType = userType
1431 1442
1432 def setFeatures(self, features, featuresOrdered = False): 1443 def setFeatures(self, features, featuresOrdered = False):
1531 def play(self, videoFilename, homography = None, undistort = False, intrinsicCameraMatrix = None, distortionCoefficients = None, undistortedImageMultiplication = 1.): 1542 def play(self, videoFilename, homography = None, undistort = False, intrinsicCameraMatrix = None, distortionCoefficients = None, undistortedImageMultiplication = 1.):
1532 cvutils.displayTrajectories(videoFilename, [self], homography = homography, firstFrameNum = self.getFirstInstant(), lastFrameNumArg = self.getLastInstant(), undistort = undistort, intrinsicCameraMatrix = intrinsicCameraMatrix, distortionCoefficients = distortionCoefficients, undistortedImageMultiplication = undistortedImageMultiplication) 1543 cvutils.displayTrajectories(videoFilename, [self], homography = homography, firstFrameNum = self.getFirstInstant(), lastFrameNumArg = self.getLastInstant(), undistort = undistort, intrinsicCameraMatrix = intrinsicCameraMatrix, distortionCoefficients = distortionCoefficients, undistortedImageMultiplication = undistortedImageMultiplication)
1533 1544
1534 def speedDiagnostics(self, framerate = 1., display = False, nInstantsIgnoredAtEnds=0): 1545 def speedDiagnostics(self, framerate = 1., display = False, nInstantsIgnoredAtEnds=0):
1535 speeds = framerate*self.getSpeeds(nInstantsIgnoredAtEnds) 1546 speeds = framerate*self.getSpeeds(nInstantsIgnoredAtEnds)
1536 coef = utils.linearRegression(range(len(speeds)), speeds) 1547 coef = utils.linearRegression(list(range(len(speeds))), speeds)
1537 print('min/5th perc speed: {} / {}\nspeed diff: {}\nspeed stdev: {}\nregression: {}'.format(min(speeds), scoreatpercentile(speeds, 5), speeds[-2]-speeds[1], std(speeds), coef[0])) 1548 print('min/5th perc speed: {} / {}\nspeed diff: {}\nspeed stdev: {}\nregression: {}'.format(min(speeds), scoreatpercentile(speeds, 5), speeds[-2]-speeds[1], std(speeds), coef[0]))
1538 if display: 1549 if display:
1539 from matplotlib.pyplot import figure, axis 1550 from matplotlib.pyplot import figure, axis
1540 figure(1) 1551 figure(1)
1541 self.plot() 1552 self.plot()
1666 ''' 1677 '''
1667 1678
1668 self.curvilinearPositions = CurvilinearTrajectory() 1679 self.curvilinearPositions = CurvilinearTrajectory()
1669 1680
1670 #For each point 1681 #For each point
1671 for i in xrange(int(self.length())): 1682 for i in range(int(self.length())):
1672 result = getSYfromXY(self.getPositionAt(i), alignments) 1683 result = getSYfromXY(self.getPositionAt(i), alignments)
1673 1684
1674 # Error handling 1685 # Error handling
1675 if(result is None): 1686 if(result is None):
1676 print('Warning: trajectory {} at point {} {} has alignment errors (spline snapping)\nCurvilinear trajectory could not be computed'.format(self.getNum(), i, self.getPositionAt(i))) 1687 print('Warning: trajectory {} at point {} {} has alignment errors (spline snapping)\nCurvilinear trajectory could not be computed'.format(self.getNum(), i, self.getPositionAt(i)))
1682 #Run through objects looking for outlier point 1693 #Run through objects looking for outlier point
1683 smoothed_lanes = utils.cat_mvgavg(self.curvilinearPositions.getLanes(),ln_mv_av_win) 1694 smoothed_lanes = utils.cat_mvgavg(self.curvilinearPositions.getLanes(),ln_mv_av_win)
1684 ## Recalculate projected point to new lane 1695 ## Recalculate projected point to new lane
1685 lanes = self.curvilinearPositions.getLanes() 1696 lanes = self.curvilinearPositions.getLanes()
1686 if(lanes != smoothed_lanes): 1697 if(lanes != smoothed_lanes):
1687 for i in xrange(len(lanes)): 1698 for i in range(len(lanes)):
1688 if(lanes[i] != smoothed_lanes[i]): 1699 if(lanes[i] != smoothed_lanes[i]):
1689 result = getSYfromXY(self.getPositionAt(i),[alignments[smoothed_lanes[i]]]) 1700 result = getSYfromXY(self.getPositionAt(i),[alignments[smoothed_lanes[i]]])
1690 1701
1691 # Error handling 1702 # Error handling
1692 if(result is None): 1703 if(result is None):
1706 if nFeatures == 0: 1717 if nFeatures == 0:
1707 print('Empty object features\nCannot compute smooth trajectory') 1718 print('Empty object features\nCannot compute smooth trajectory')
1708 else: 1719 else:
1709 # compute the relative position vectors 1720 # compute the relative position vectors
1710 relativePositions = {} # relativePositions[(i,j)] is the position of j relative to i 1721 relativePositions = {} # relativePositions[(i,j)] is the position of j relative to i
1711 for i in xrange(nFeatures): 1722 for i in range(nFeatures):
1712 for j in xrange(i): 1723 for j in range(i):
1713 fi = self.features[i] 1724 fi = self.features[i]
1714 fj = self.features[j] 1725 fj = self.features[j]
1715 inter = fi.commonTimeInterval(fj) 1726 inter = fi.commonTimeInterval(fj)
1716 if inter.length() >= minCommonIntervalLength: 1727 if inter.length() >= minCommonIntervalLength:
1717 xi = array(fi.getXCoordinates()[inter.first-fi.getFirstInstant():int(fi.length())-(fi.getLastInstant()-inter.last)]) 1728 xi = array(fi.getXCoordinates()[inter.first-fi.getFirstInstant():int(fi.length())-(fi.getLastInstant()-inter.last)])
1960 gtMatches = {a.getNum():{} for a in annotations} 1971 gtMatches = {a.getNum():{} for a in annotations}
1961 toMatches = {o.getNum():{} for o in objects} 1972 toMatches = {o.getNum():{} for o in objects}
1962 else: 1973 else:
1963 gtMatches = None 1974 gtMatches = None
1964 toMatches = None 1975 toMatches = None
1965 for t in xrange(firstInstant, lastInstant+1): 1976 for t in range(firstInstant, lastInstant+1):
1966 previousMatches = matches.copy() 1977 previousMatches = matches.copy()
1967 # go through currently matched GT-TO and check if they are still matched withing matchingDistance 1978 # go through currently matched GT-TO and check if they are still matched withing matchingDistance
1968 toDelete = [] 1979 toDelete = []
1969 for a in matches: 1980 for a in matches:
1970 if a.existsAtInstant(t) and matches[a].existsAtInstant(t): 1981 if a.existsAtInstant(t) and matches[a].existsAtInstant(t):
1977 toDelete.append(a) 1988 toDelete.append(a)
1978 for a in toDelete: 1989 for a in toDelete:
1979 del matches[a] 1990 del matches[a]
1980 1991
1981 # match all unmatched GT-TO 1992 # match all unmatched GT-TO
1982 matchedGTs = matches.keys() 1993 matchedGTs = list(matches.keys())
1983 matchedTOs = matches.values() 1994 matchedTOs = list(matches.values())
1984 costs = [] 1995 costs = []
1985 unmatchedGTs = [a for a in annotations if a.existsAtInstant(t) and a not in matchedGTs] 1996 unmatchedGTs = [a for a in annotations if a.existsAtInstant(t) and a not in matchedGTs]
1986 unmatchedTOs = [o for o in objects if o.existsAtInstant(t) and o not in matchedTOs] 1997 unmatchedTOs = [o for o in objects if o.existsAtInstant(t) and o not in matchedTOs]
1987 nGTs = len(matchedGTs)+len(unmatchedGTs) 1998 nGTs = len(matchedGTs)+len(unmatchedGTs)
1988 nTOs = len(matchedTOs)+len(unmatchedTOs) 1999 nTOs = len(matchedTOs)+len(unmatchedTOs)
1994 for k,v in newMatches: 2005 for k,v in newMatches:
1995 if costs[k][v] < matchingDistance: 2006 if costs[k][v] < matchingDistance:
1996 matches[unmatchedGTs[k]]=unmatchedTOs[v] 2007 matches[unmatchedGTs[k]]=unmatchedTOs[v]
1997 dist += costs[k][v] 2008 dist += costs[k][v]
1998 if debug: 2009 if debug:
1999 print('{} '.format(t)+', '.join(['{} {}'.format(k.getNum(), v.getNum()) for k,v in matches.iteritems()])) 2010 print('{} '.format(t)+', '.join(['{} {}'.format(k.getNum(), v.getNum()) for k,v in matches.items()]))
2000 if returnMatches: 2011 if returnMatches:
2001 for a,o in matches.iteritems(): 2012 for a,o in matches.items():
2002 gtMatches[a.getNum()][t] = o.getNum() 2013 gtMatches[a.getNum()][t] = o.getNum()
2003 toMatches[o.getNum()][t] = a.getNum() 2014 toMatches[o.getNum()][t] = a.getNum()
2004 2015
2005 # compute metrics elements 2016 # compute metrics elements
2006 ct += len(matches) 2017 ct += len(matches)
2012 mismatches = [] 2023 mismatches = []
2013 for a in matches: 2024 for a in matches:
2014 if a in previousMatches: 2025 if a in previousMatches:
2015 if matches[a] != previousMatches[a]: 2026 if matches[a] != previousMatches[a]:
2016 mismatches.append(a) 2027 mismatches.append(a)
2017 elif matches[a] in previousMatches.values(): 2028 elif matches[a] in list(previousMatches.values()):
2018 mismatches.append(matches[a]) 2029 mismatches.append(matches[a])
2019 for a in previousMatches: 2030 for a in previousMatches:
2020 if a not in matches and previousMatches[a] in matches.values(): 2031 if a not in matches and previousMatches[a] in list(matches.values()):
2021 mismatches.append(previousMatches[a]) 2032 mismatches.append(previousMatches[a])
2022 if debug: 2033 if debug:
2023 for mm in set(mismatches): 2034 for mm in set(mismatches):
2024 print('{} {}'.format(type(mm), mm.getNum())) 2035 print('{} {}'.format(type(mm), mm.getNum()))
2025 # some object mismatches may appear twice 2036 # some object mismatches may appear twice