Mercurial > hg > nsaunier > traffic-intelligence
comparison python/moving.py @ 672:5473b7460375
moved and rationalized imports in modules
| author | Nicolas Saunier <nicolas.saunier@polymtl.ca> |
|---|---|
| date | Tue, 26 May 2015 13:53:40 +0200 |
| parents | 93633ce122c3 |
| children | 01b89182891a |
comparison
equal
deleted
inserted
replaced
| 671:849f5f8bf4b9 | 672:5473b7460375 |
|---|---|
| 2 '''Libraries for moving objects, trajectories...''' | 2 '''Libraries for moving objects, trajectories...''' |
| 3 | 3 |
| 4 import utils, cvutils | 4 import utils, cvutils |
| 5 from base import VideoFilenameAddable | 5 from base import VideoFilenameAddable |
| 6 | 6 |
| 7 from math import sqrt | 7 from math import sqrt, atan2, cos, sin |
| 8 from numpy import median | 8 from numpy import median, array, zeros, hypot, NaN, std |
| 9 from matplotlib.pyplot import plot | |
| 10 from scipy.stats import scoreatpercentile | |
| 11 from scipy.spatial.distance import cdist | |
| 9 | 12 |
| 10 try: | 13 try: |
| 11 from shapely.geometry import Polygon, Point as shapelyPoint | 14 from shapely.geometry import Polygon, Point as shapelyPoint |
| 12 from shapely.prepared import prep | 15 from shapely.prepared import prep |
| 13 shapelyAvailable = True | 16 shapelyAvailable = True |
| 197 def divide(self, alpha): | 200 def divide(self, alpha): |
| 198 'Warning, returns a new Point' | 201 'Warning, returns a new Point' |
| 199 return Point(self.x/alpha, self.y/alpha) | 202 return Point(self.x/alpha, self.y/alpha) |
| 200 | 203 |
| 201 def plot(self, options = 'o', **kwargs): | 204 def plot(self, options = 'o', **kwargs): |
| 202 from matplotlib.pylab import plot | |
| 203 plot([self.x], [self.y], options, **kwargs) | 205 plot([self.x], [self.y], options, **kwargs) |
| 204 | 206 |
| 205 def norm2Squared(self): | 207 def norm2Squared(self): |
| 206 '''2-norm distance (Euclidean distance)''' | 208 '''2-norm distance (Euclidean distance)''' |
| 207 return self.x**2+self.y**2 | 209 return self.x**2+self.y**2 |
| 228 if shapelyAvailable: | 230 if shapelyAvailable: |
| 229 def asShapely(self): | 231 def asShapely(self): |
| 230 return shapelyPoint(self.x, self.y) | 232 return shapelyPoint(self.x, self.y) |
| 231 | 233 |
| 232 def project(self, homography): | 234 def project(self, homography): |
| 233 from numpy.core.multiarray import array | |
| 234 projected = cvutils.projectArray(homography, array([[self.x], [self.y]])) | 235 projected = cvutils.projectArray(homography, array([[self.x], [self.y]])) |
| 235 return Point(projected[0], projected[1]) | 236 return Point(projected[0], projected[1]) |
| 236 | 237 |
| 237 def inPolygon(self, polygon): | 238 def inPolygon(self, polygon): |
| 238 '''Indicates if the point x, y is inside the polygon | 239 '''Indicates if the point x, y is inside the polygon |
| 293 def timeToCollision(p1, p2, v1, v2, collisionThreshold): | 294 def timeToCollision(p1, p2, v1, v2, collisionThreshold): |
| 294 '''Computes exact time to collision with a distance threshold | 295 '''Computes exact time to collision with a distance threshold |
| 295 The unknown of the equation is the time to reach the intersection | 296 The unknown of the equation is the time to reach the intersection |
| 296 between the relative trajectory of one road user | 297 between the relative trajectory of one road user |
| 297 and the circle of radius collisionThreshold around the other road user''' | 298 and the circle of radius collisionThreshold around the other road user''' |
| 298 from math import sqrt | |
| 299 dv = v1-v2 | 299 dv = v1-v2 |
| 300 dp = p1-p2 | 300 dp = p1-p2 |
| 301 a = dv.norm2Squared()#(v1.x-v2.x)**2 + (v1.y-v2.y)**2 | 301 a = dv.norm2Squared()#(v1.x-v2.x)**2 + (v1.y-v2.y)**2 |
| 302 b = 2*Point.dot(dv, dp)#2 * ((p1.x-p2.x) * (v1.x-v2.x) + (p1.y-p2.y) * (v1.y-v2.y)) | 302 b = 2*Point.dot(dv, dp)#2 * ((p1.x-p2.x) * (v1.x-v2.x) + (p1.y-p2.y) * (v1.y-v2.y)) |
| 303 c = dp.norm2Squared() - collisionThreshold**2#(p1.x-p2.x)**2 + (p1.y-p2.y)**2 - collisionThreshold**2 | 303 c = dp.norm2Squared() - collisionThreshold**2#(p1.x-p2.x)**2 + (p1.y-p2.y)**2 - collisionThreshold**2 |
| 342 where: | 342 where: |
| 343 mode=0: incremental distance | 343 mode=0: incremental distance |
| 344 mode=1: cumulative distance | 344 mode=1: cumulative distance |
| 345 mode=2: cumulative distance with trailing distance | 345 mode=2: cumulative distance with trailing distance |
| 346 ''' | 346 ''' |
| 347 | |
| 348 from numpy import zeros | |
| 349 ss_spline_d = [] | 347 ss_spline_d = [] |
| 350 #Prepare subsegment distances | 348 #Prepare subsegment distances |
| 351 for spline in range(len(splines)): | 349 for spline in range(len(splines)): |
| 352 ss_spline_d.append([[],[],[]]) | 350 ss_spline_d.append([[],[],[]]) |
| 353 ss_spline_d[spline][0] = zeros(len(splines[spline])-1) #Incremental distance | 351 ss_spline_d[spline][0] = zeros(len(splines[spline])-1) #Incremental distance |
| 478 self.norm = norm | 476 self.norm = norm |
| 479 self.angle = angle | 477 self.angle = angle |
| 480 | 478 |
| 481 @staticmethod | 479 @staticmethod |
| 482 def fromPoint(p): | 480 def fromPoint(p): |
| 483 from math import atan2 | |
| 484 norm = p.norm2() | 481 norm = p.norm2() |
| 485 if norm > 0: | 482 if norm > 0: |
| 486 angle = atan2(p.y, p.x) | 483 angle = atan2(p.y, p.x) |
| 487 else: | 484 else: |
| 488 angle = 0. | 485 angle = 0. |
| 491 def __add__(self, other): | 488 def __add__(self, other): |
| 492 'a norm cannot become negative' | 489 'a norm cannot become negative' |
| 493 return NormAngle(max(self.norm+other.norm, 0), self.angle+other.angle) | 490 return NormAngle(max(self.norm+other.norm, 0), self.angle+other.angle) |
| 494 | 491 |
| 495 def getPoint(self): | 492 def getPoint(self): |
| 496 from math import cos, sin | |
| 497 return Point(self.norm*cos(self.angle), self.norm*sin(self.angle)) | 493 return Point(self.norm*cos(self.angle), self.norm*sin(self.angle)) |
| 498 | 494 |
| 499 | 495 |
| 500 def predictPositionNoLimit(nTimeSteps, initialPosition, initialVelocity, initialAcceleration = Point(0,0)): | 496 def predictPositionNoLimit(nTimeSteps, initialPosition, initialVelocity, initialAcceleration = Point(0,0)): |
| 501 '''Predicts the position in nTimeSteps at constant speed/acceleration''' | 497 '''Predicts the position in nTimeSteps at constant speed/acceleration''' |
| 525 | 521 |
| 526 def multiply(self, alpha): | 522 def multiply(self, alpha): |
| 527 return FlowVector(self.position.multiply(alpha), self.velocity.multiply(alpha)) | 523 return FlowVector(self.position.multiply(alpha), self.velocity.multiply(alpha)) |
| 528 | 524 |
| 529 def plot(self, options = '', **kwargs): | 525 def plot(self, options = '', **kwargs): |
| 530 from matplotlib.pylab import plot | |
| 531 plot([self.position.x, self.position.x+self.velocity.x], [self.position.y, self.position.y+self.velocity.y], options, **kwargs) | 526 plot([self.position.x, self.position.x+self.velocity.x], [self.position.y, self.position.y+self.velocity.y], options, **kwargs) |
| 532 self.position.plot(options+'x', **kwargs) | 527 self.position.plot(options+'x', **kwargs) |
| 533 | 528 |
| 534 @staticmethod | 529 @staticmethod |
| 535 def similar(f1, f2, maxDistance2, maxDeltavelocity2): | 530 def similar(f1, f2, maxDistance2, maxDeltavelocity2): |
| 679 self.positions[0].append(self.positions[0][-1]) | 674 self.positions[0].append(self.positions[0][-1]) |
| 680 self.positions[1].append(self.positions[1][-1]) | 675 self.positions[1].append(self.positions[1][-1]) |
| 681 | 676 |
| 682 @staticmethod | 677 @staticmethod |
| 683 def _plot(positions, options = '', withOrigin = False, lastCoordinate = None, timeStep = 1, **kwargs): | 678 def _plot(positions, options = '', withOrigin = False, lastCoordinate = None, timeStep = 1, **kwargs): |
| 684 from matplotlib.pylab import plot | |
| 685 if lastCoordinate is None: | 679 if lastCoordinate is None: |
| 686 plot(positions[0][::timeStep], positions[1][::timeStep], options, **kwargs) | 680 plot(positions[0][::timeStep], positions[1][::timeStep], options, **kwargs) |
| 687 elif 0 <= lastCoordinate <= len(positions[0]): | 681 elif 0 <= lastCoordinate <= len(positions[0]): |
| 688 plot(positions[0][:lastCoordinate:timeStep], positions[1][:lastCoordinate:timeStep], options, **kwargs) | 682 plot(positions[0][:lastCoordinate:timeStep], positions[1][:lastCoordinate:timeStep], options, **kwargs) |
| 689 if withOrigin: | 683 if withOrigin: |
| 708 | 702 |
| 709 def getYCoordinates(self): | 703 def getYCoordinates(self): |
| 710 return self.positions[1] | 704 return self.positions[1] |
| 711 | 705 |
| 712 def asArray(self): | 706 def asArray(self): |
| 713 from numpy.core.multiarray import array | |
| 714 return array(self.positions) | 707 return array(self.positions) |
| 715 | 708 |
| 716 def xBounds(self): | 709 def xBounds(self): |
| 717 # look for function that does min and max in one pass | 710 # look for function that does min and max in one pass |
| 718 return Interval(min(self.getXCoordinates()), max(self.getXCoordinates())) | 711 return Interval(min(self.getXCoordinates()), max(self.getXCoordinates())) |
| 755 def norm(self): | 748 def norm(self): |
| 756 '''Returns the list of the norms at each instant''' | 749 '''Returns the list of the norms at each instant''' |
| 757 # def add(x, y): return x+y | 750 # def add(x, y): return x+y |
| 758 # sq = map(add, [x*x for x in self.positions[0]], [y*y for y in self.positions[1]]) | 751 # sq = map(add, [x*x for x in self.positions[0]], [y*y for y in self.positions[1]]) |
| 759 # return sqrt(sq) | 752 # return sqrt(sq) |
| 760 from numpy import hypot | |
| 761 return hypot(self.positions[0], self.positions[1]) | 753 return hypot(self.positions[0], self.positions[1]) |
| 762 | 754 |
| 763 # def cumulatedDisplacement(self): | 755 # def cumulatedDisplacement(self): |
| 764 # 'Returns the sum of the distances between each successive point' | 756 # 'Returns the sum of the distances between each successive point' |
| 765 # displacement = 0 | 757 # displacement = 0 |
| 1081 else: | 1073 else: |
| 1082 return None | 1074 return None |
| 1083 | 1075 |
| 1084 def plotCurvilinearPositions(self, lane = None, options = '', withOrigin = False, **kwargs): | 1076 def plotCurvilinearPositions(self, lane = None, options = '', withOrigin = False, **kwargs): |
| 1085 if hasattr(self, 'curvilinearPositions'): | 1077 if hasattr(self, 'curvilinearPositions'): |
| 1086 from matplotlib.pylab import plot | |
| 1087 from numpy import NaN | |
| 1088 if lane is None: | 1078 if lane is None: |
| 1089 plot(list(self.getTimeInterval()), self.curvilinearPositions.positions[0], options, **kwargs) | 1079 plot(list(self.getTimeInterval()), self.curvilinearPositions.positions[0], options, **kwargs) |
| 1090 if withOrigin: | 1080 if withOrigin: |
| 1091 plot([self.getFirstInstant()], [self.curvilinearPositions.positions[0][0]], 'ro', **kwargs) | 1081 plot([self.getFirstInstant()], [self.curvilinearPositions.positions[0][0]], 'ro', **kwargs) |
| 1092 else: | 1082 else: |
| 1177 | 1167 |
| 1178 def play(self, videoFilename, homography = None, undistort = False, intrinsicCameraMatrix = None, distortionCoefficients = None, undistortedImageMultiplication = 1.): | 1168 def play(self, videoFilename, homography = None, undistort = False, intrinsicCameraMatrix = None, distortionCoefficients = None, undistortedImageMultiplication = 1.): |
| 1179 cvutils.displayTrajectories(videoFilename, [self], homography = homography, firstFrameNum = self.getFirstInstant(), lastFrameNumArg = self.getLastInstant(), undistort = undistort, intrinsicCameraMatrix = intrinsicCameraMatrix, distortionCoefficients = distortionCoefficients, undistortedImageMultiplication = undistortedImageMultiplication) | 1169 cvutils.displayTrajectories(videoFilename, [self], homography = homography, firstFrameNum = self.getFirstInstant(), lastFrameNumArg = self.getLastInstant(), undistort = undistort, intrinsicCameraMatrix = intrinsicCameraMatrix, distortionCoefficients = distortionCoefficients, undistortedImageMultiplication = undistortedImageMultiplication) |
| 1180 | 1170 |
| 1181 def speedDiagnostics(self, framerate = 1., display = False): | 1171 def speedDiagnostics(self, framerate = 1., display = False): |
| 1182 from numpy import std | |
| 1183 from scipy.stats import scoreatpercentile | |
| 1184 speeds = framerate*self.getSpeeds() | 1172 speeds = framerate*self.getSpeeds() |
| 1185 coef = utils.linearRegression(range(len(speeds)), speeds) | 1173 coef = utils.linearRegression(range(len(speeds)), speeds) |
| 1186 print('min/5th perc speed: {} / {}\nspeed diff: {}\nspeed stdev: {}\nregression: {}'.format(min(speeds), scoreatpercentile(speeds, 5), speeds[-2]-speeds[1], std(speeds), coef[0])) | 1174 print('min/5th perc speed: {} / {}\nspeed diff: {}\nspeed stdev: {}\nregression: {}'.format(min(speeds), scoreatpercentile(speeds, 5), speeds[-2]-speeds[1], std(speeds), coef[0])) |
| 1187 if display: | 1175 if display: |
| 1188 from matplotlib.pyplot import figure, plot, axis | 1176 from matplotlib.pyplot import figure, axis |
| 1189 figure(1) | 1177 figure(1) |
| 1190 self.plot() | 1178 self.plot() |
| 1191 axis('equal') | 1179 axis('equal') |
| 1192 figure(2) | 1180 figure(2) |
| 1193 plot(list(self.getTimeInterval()), speeds) | 1181 plot(list(self.getTimeInterval()), speeds) |
| 1212 @staticmethod | 1200 @staticmethod |
| 1213 def distances(obj1, obj2, instant1, _instant2 = None): | 1201 def distances(obj1, obj2, instant1, _instant2 = None): |
| 1214 '''Returns the distances between all features of the 2 objects | 1202 '''Returns the distances between all features of the 2 objects |
| 1215 at the same instant instant1 | 1203 at the same instant instant1 |
| 1216 or at instant1 and instant2''' | 1204 or at instant1 and instant2''' |
| 1217 from scipy.spatial.distance import cdist | |
| 1218 if _instant2 is None: | 1205 if _instant2 is None: |
| 1219 instant2 = instant1 | 1206 instant2 = instant1 |
| 1220 else: | 1207 else: |
| 1221 instant2 = _instant2 | 1208 instant2 = _instant2 |
| 1222 positions1 = [f.getPositionAtInstant(instant1).astuple() for f in obj1.features if f.existsAtInstant(instant1)] | 1209 positions1 = [f.getPositionAtInstant(instant1).astuple() for f in obj1.features if f.existsAtInstant(instant1)] |
| 1264 | 1251 |
| 1265 Returns the smallest time difference when the object positions are within collisionDistanceThreshold''' | 1252 Returns the smallest time difference when the object positions are within collisionDistanceThreshold''' |
| 1266 #for i in xrange(int(obj1.length())-1): | 1253 #for i in xrange(int(obj1.length())-1): |
| 1267 # for j in xrange(int(obj2.length())-1): | 1254 # for j in xrange(int(obj2.length())-1): |
| 1268 # inter = segmentIntersection(obj1.getPositionAt(i), obj1.getPositionAt(i+1), obj2.getPositionAt(i), obj2.getPositionAt(i+1)) | 1255 # inter = segmentIntersection(obj1.getPositionAt(i), obj1.getPositionAt(i+1), obj2.getPositionAt(i), obj2.getPositionAt(i+1)) |
| 1269 from scipy.spatial.distance import cdist | |
| 1270 from numpy import zeros | |
| 1271 positions1 = [p.astuple() for p in obj1.getPositions()] | 1256 positions1 = [p.astuple() for p in obj1.getPositions()] |
| 1272 positions2 = [p.astuple() for p in obj2.getPositions()] | 1257 positions2 = [p.astuple() for p in obj2.getPositions()] |
| 1273 pets = zeros((int(obj1.length()), int(obj2.length()))) | 1258 pets = zeros((int(obj1.length()), int(obj2.length()))) |
| 1274 for i,t1 in enumerate(obj1.getTimeInterval()): | 1259 for i,t1 in enumerate(obj1.getTimeInterval()): |
| 1275 for j,t2 in enumerate(obj2.getTimeInterval()): | 1260 for j,t2 in enumerate(obj2.getTimeInterval()): |
| 1337 '''Computes the trajectory as the mean of all features | 1322 '''Computes the trajectory as the mean of all features |
| 1338 if a feature exists, its position is | 1323 if a feature exists, its position is |
| 1339 | 1324 |
| 1340 Warning work in progress | 1325 Warning work in progress |
| 1341 TODO? not use the first/last 1-.. positions''' | 1326 TODO? not use the first/last 1-.. positions''' |
| 1342 from numpy import array, median | |
| 1343 nFeatures = len(self.features) | 1327 nFeatures = len(self.features) |
| 1344 if nFeatures == 0: | 1328 if nFeatures == 0: |
| 1345 print('Empty object features\nCannot compute smooth trajectory') | 1329 print('Empty object features\nCannot compute smooth trajectory') |
| 1346 else: | 1330 else: |
| 1347 # compute the relative position vectors | 1331 # compute the relative position vectors |
| 1407 self.userTypes = {} | 1391 self.userTypes = {} |
| 1408 | 1392 |
| 1409 def classifyUserTypeHoGSVMAtInstant(self, img, pedBikeCarSVM, instant, homography, width, height, bikeCarSVM = None, pedBikeSpeedTreshold = float('Inf'), bikeCarSpeedThreshold = float('Inf'), px = 0.2, py = 0.2, pixelThreshold = 800): | 1393 def classifyUserTypeHoGSVMAtInstant(self, img, pedBikeCarSVM, instant, homography, width, height, bikeCarSVM = None, pedBikeSpeedTreshold = float('Inf'), bikeCarSpeedThreshold = float('Inf'), px = 0.2, py = 0.2, pixelThreshold = 800): |
| 1410 '''Extract the image box around the object and | 1394 '''Extract the image box around the object and |
| 1411 applies the SVM model on it''' | 1395 applies the SVM model on it''' |
| 1412 from numpy import array | |
| 1413 croppedImg, yCropMin, yCropMax, xCropMin, xCropMax = imageBox(img, self, instant, homography, width, height, px, py, pixelThreshold) | 1396 croppedImg, yCropMin, yCropMax, xCropMin, xCropMax = imageBox(img, self, instant, homography, width, height, px, py, pixelThreshold) |
| 1414 if len(croppedImg) > 0: # != [] | 1397 if len(croppedImg) > 0: # != [] |
| 1415 hog = array([cvutils.HOG(croppedImg)], dtype = np.float32) | 1398 hog = array([cvutils.HOG(croppedImg)], dtype = np.float32) |
| 1416 if self.aggregatedSpeed < pedBikeSpeedTreshold or bikeCarSVM is None: | 1399 if self.aggregatedSpeed < pedBikeSpeedTreshold or bikeCarSVM is None: |
| 1417 self.userTypes[instant] = int(pedBikeCarSVM.predict(hog)) | 1400 self.userTypes[instant] = int(pedBikeCarSVM.predict(hog)) |
