Mercurial Hosting > traffic-intelligence
comparison python/moving.py @ 680:da1352b89d02 dev
classification is working
author | Nicolas Saunier <nicolas.saunier@polymtl.ca> |
---|---|
date | Fri, 05 Jun 2015 02:25:30 +0200 |
parents | ab3fdff42624 |
children | fbe29be25501 |
comparison
equal
deleted
inserted
replaced
678:97c305108460 | 680:da1352b89d02 |
---|---|
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, atan2, cos, sin | 7 from math import sqrt, atan2, cos, sin |
8 from numpy import median, array, zeros, hypot, NaN, std | 8 from numpy import median, array, zeros, hypot, NaN, std, floor, float32 |
9 from matplotlib.pyplot import plot | 9 from matplotlib.pyplot import plot |
10 from scipy.stats import scoreatpercentile | 10 from scipy.stats import scoreatpercentile |
11 from scipy.spatial.distance import cdist | 11 from scipy.spatial.distance import cdist |
12 | 12 |
13 try: | 13 try: |
75 return self.first - interval2.last | 75 return self.first - interval2.last |
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 | |
81 | 80 |
82 def unionIntervals(intervals): | 81 def unionIntervals(intervals): |
83 'returns the smallest interval containing all intervals' | 82 'returns the smallest interval containing all intervals' |
84 inter = intervals[0] | 83 inter = intervals[0] |
85 for i in intervals[1:]: | 84 for i in intervals[1:]: |
1127 return featureNumbers | 1126 return featureNumbers |
1128 else: | 1127 else: |
1129 print('Object {} has no features loaded.'.format(self.getNum())) | 1128 print('Object {} has no features loaded.'.format(self.getNum())) |
1130 return None | 1129 return None |
1131 | 1130 |
1132 def getSpeeds(self): | 1131 def getSpeeds(self, nInstantsIgnoredAtEnds = 0): |
1133 return self.getVelocities().norm() | 1132 n = min(nInstantsIgnoredAtEnds, int(floor(self.length()/2.))) |
1133 return self.getVelocities().norm()[n:-n] | |
1134 | 1134 |
1135 def getSpeedIndicator(self): | 1135 def getSpeedIndicator(self): |
1136 from indicators import SeverityIndicator | 1136 from indicators import SeverityIndicator |
1137 return SeverityIndicator('Speed', {t:self.getVelocityAtInstant(t).norm2() for t in self.getTimeInterval()}) | 1137 return SeverityIndicator('Speed', {t:self.getVelocityAtInstant(t).norm2() for t in self.getTimeInterval()}) |
1138 | 1138 |
1344 relativePositions[(j,i)] = -relativePositions[(i,j)] | 1344 relativePositions[(j,i)] = -relativePositions[(i,j)] |
1345 | 1345 |
1346 ### | 1346 ### |
1347 # User Type Classification | 1347 # User Type Classification |
1348 ### | 1348 ### |
1349 def classifyUserTypeSpeedMotorized(self, threshold, aggregationFunc = median, ignoreNInstantsAtEnds = 0): | 1349 def classifyUserTypeSpeedMotorized(self, threshold, aggregationFunc = median, nInstantsIgnoredAtEnds = 0): |
1350 '''Classifies slow and fast road users | 1350 '''Classifies slow and fast road users |
1351 slow: non-motorized -> pedestrians | 1351 slow: non-motorized -> pedestrians |
1352 fast: motorized -> cars | 1352 fast: motorized -> cars |
1353 | 1353 |
1354 aggregationFunc can be any function that can be applied to a vector of speeds, including percentile: | 1354 aggregationFunc can be any function that can be applied to a vector of speeds, including percentile: |
1355 aggregationFunc = lambda x: percentile(x, percentileFactor) # where percentileFactor is 85 for 85th percentile''' | 1355 aggregationFunc = lambda x: percentile(x, percentileFactor) # where percentileFactor is 85 for 85th percentile''' |
1356 if ignoreNInstantsAtEnds > 0: | 1356 speeds = self.getSpeeds(nInstantsIgnoredAtEnds) |
1357 speeds = self.getSpeeds()[ignoreNInstantsAtEnds:-ignoreNInstantsAtEnds] | |
1358 else: | |
1359 speeds = self.getSpeeds() | |
1360 if aggregationFunc(speeds) >= threshold: | 1357 if aggregationFunc(speeds) >= threshold: |
1361 self.setUserType(userType2Num['car']) | 1358 self.setUserType(userType2Num['car']) |
1362 else: | 1359 else: |
1363 self.setUserType(userType2Num['pedestrian']) | 1360 self.setUserType(userType2Num['pedestrian']) |
1364 | 1361 |
1365 def classifyUserTypeSpeed(self, speedProbabilities, aggregationFunc = median): | 1362 def classifyUserTypeSpeed(self, speedProbabilities, aggregationFunc = median, nInstantsIgnoredAtEnds = 0): |
1366 '''Classifies road user per road user type | 1363 '''Classifies road user per road user type |
1367 speedProbabilities are functions return P(speed|class) | 1364 speedProbabilities are functions return P(speed|class) |
1368 in a dictionary indexed by user type names | 1365 in a dictionary indexed by user type names |
1369 Returns probabilities for each class | 1366 Returns probabilities for each class |
1370 | 1367 |
1373 if abs(x-mu) < sigma: | 1370 if abs(x-mu) < sigma: |
1374 return 1 | 1371 return 1 |
1375 else: | 1372 else: |
1376 return x''' | 1373 return x''' |
1377 if not hasattr(self, 'aggregatedSpeed'): | 1374 if not hasattr(self, 'aggregatedSpeed'): |
1378 self.aggregatedSpeed = aggregationFunc(self.getSpeeds()) | 1375 self.aggregatedSpeed = aggregationFunc(self.getSpeeds(nInstantsIgnoredAtEnds)) |
1379 userTypeProbabilities = {} | 1376 userTypeProbabilities = {} |
1380 for userTypename in speedProbabilities: | 1377 for userTypename in speedProbabilities: |
1381 userTypeProbabilities[userType2Num[userTypename]] = speedProbabilities[userTypename](self.aggregatedSpeed) | 1378 userTypeProbabilities[userType2Num[userTypename]] = speedProbabilities[userTypename](self.aggregatedSpeed) |
1382 self.setUserType(utils.argmaxDict(userTypeProbabilities)) | 1379 self.setUserType(utils.argmaxDict(userTypeProbabilities)) |
1383 return userTypeProbabilities | 1380 return userTypeProbabilities |
1384 | 1381 |
1385 def initClassifyUserTypeHoGSVM(self, aggregationFunc = median): | 1382 def initClassifyUserTypeHoGSVM(self, aggregationFunc, pedBikeCarSVM, bikeCarSVM = None, pedBikeSpeedTreshold = float('Inf'), bikeCarSpeedThreshold = float('Inf'), nInstantsIgnoredAtEnds = 0): |
1386 '''Initializes the data structures for classification | 1383 '''Initializes the data structures for classification |
1387 | 1384 |
1388 TODO? compute speed for longest feature? | 1385 TODO? compute speed for longest feature?''' |
1389 Skip beginning and end of feature for speed? Offer options instead of median''' | 1386 self.aggregatedSpeed = aggregationFunc(self.getSpeeds(nInstantsIgnoredAtEnds)) |
1390 self.aggregatedSpeed = aggregationFunc(self.getSpeeds()) | 1387 if self.aggregatedSpeed < pedBikeSpeedTreshold or bikeCarSVM is None: |
1388 self.appearanceClassifier = pedBikeCarSVM | |
1389 elif self.aggregatedSpeed < bikeCarSpeedThreshold: | |
1390 self.appearanceClassifier = bikeCarSVM | |
1391 else: | |
1392 class CarClassifier: | |
1393 def predict(self, hog): | |
1394 return userType2Num['car'] | |
1395 self.appearanceClassifier = CarClassifier() | |
1396 | |
1391 self.userTypes = {} | 1397 self.userTypes = {} |
1392 | 1398 |
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): | 1399 def classifyUserTypeHoGSVMAtInstant(self, img, instant, homography, width, height, px = 0.2, py = 0.2, minNPixels = 800): |
1394 '''Extract the image box around the object and | 1400 '''Extract the image box around the object and |
1395 applies the SVM model on it''' | 1401 applies the SVM model on it''' |
1396 croppedImg, yCropMin, yCropMax, xCropMin, xCropMax = imageBox(img, self, instant, homography, width, height, px, py, pixelThreshold) | 1402 croppedImg, yCropMin, yCropMax, xCropMin, xCropMax = cvutils.imageBox(img, self, instant, homography, width, height, px, py, minNPixels) |
1397 if len(croppedImg) > 0: # != [] | 1403 if len(croppedImg) > 0: |
1398 hog = array([cvutils.HOG(croppedImg)], dtype = np.float32) | 1404 hog = cvutils.HOG(croppedImg)#HOG(image, rescaleSize = (64, 64), orientations=9, pixelsPerCell=(8, 8), cellsPerBlock=(2, 2), visualize=False, normalize=False) |
1399 if self.aggregatedSpeed < pedBikeSpeedTreshold or bikeCarSVM is None: | 1405 self.userTypes[instant] = int(self.appearanceClassifier.predict(hog)) |
1400 self.userTypes[instant] = int(pedBikeCarSVM.predict(hog)) | |
1401 elif self.aggregatedSpeed < bikeCarSpeedTreshold: | |
1402 self.userTypes[instant] = int(bikeCarSVM.predict(hog)) | |
1403 else: | |
1404 self.userTypes[instant] = userType2Num['car'] | |
1405 else: | 1406 else: |
1406 self.userTypes[instant] = userType2Num['unknown'] | 1407 self.userTypes[instant] = userType2Num['unknown'] |
1407 | 1408 |
1408 def classifyUserTypeHoGSVM(self, images, pedBikeCarSVM, homography, width, height, bikeCarSVM = None, pedBikeSpeedTreshold = float('Inf'), bikeCarSpeedThreshold = float('Inf'), speedProbabilities = None, aggregationFunc = median, px = 0.2, py = 0.2, pixelThreshold = 800): | 1409 def classifyUserTypeHoGSVM(self, pedBikeCarSVM = None, width = 0, height = 0, homography = None, images = None, bikeCarSVM = None, pedBikeSpeedTreshold = float('Inf'), bikeCarSpeedThreshold = float('Inf'), minSpeedEquiprobable = -1, speedProbabilities = None, aggregationFunc = median, nInstantsIgnoredAtEnds = 0, px = 0.2, py = 0.2, minNPixels = 800): |
1409 '''Agregates SVM detections in each image and returns probability | 1410 '''Agregates SVM detections in each image and returns probability |
1410 (proportion of instants with classification in each category) | 1411 (proportion of instants with classification in each category) |
1411 | 1412 |
1412 iamges is a dictionary of images indexed by instant | 1413 images is a dictionary of images indexed by instant |
1413 With default parameters, the general (ped-bike-car) classifier will be used | 1414 With default parameters, the general (ped-bike-car) classifier will be used |
1414 TODO? consider all categories?''' | 1415 |
1415 if not hasattr(self, aggregatedSpeed) or not hasattr(self, userTypes): | 1416 Considered categories are the keys of speedProbabilities''' |
1417 if not hasattr(self, 'aggregatedSpeed') or not hasattr(self, 'userTypes'): | |
1416 print('Initilize the data structures for classification by HoG-SVM') | 1418 print('Initilize the data structures for classification by HoG-SVM') |
1417 self.initClassifyUserTypeHoGSVM(aggregationFunc) | 1419 self.initClassifyUserTypeHoGSVM(aggregationFunc, pedBikeCarSVM, bikeCarSVM, pedBikeSpeedTreshold, bikeCarSpeedThreshold, nInstantsIgnoredAtEnds) |
1418 | 1420 |
1419 if len(self.userTypes) != self.length(): # if classification has not been done previously | 1421 if len(self.userTypes) != self.length() and images is not None: # if classification has not been done previously |
1420 for t in self.getTimeInterval(): | 1422 for t in self.getTimeInterval(): |
1421 if t not in self.userTypes: | 1423 if t not in self.userTypes: |
1422 self.classifyUserTypeHoGSVMAtInstant(images[t], pedBikeCarSVM, t, homography, width, height, bikeCarSVM, pedBikeSpeedTreshold, bikeCarSpeedThreshold, px, py, pixelThreshold) | 1424 self.classifyUserTypeHoGSVMAtInstant(images[t], t, homography, width, height, px, py, minNPixels) |
1423 # compute P(Speed|Class) | 1425 # compute P(Speed|Class) |
1424 if speedProbabilities is None: # equiprobable information from speed | 1426 if speedProbabilities is None or self.aggregatedSpeed < minSpeedEquiprobable: # equiprobable information from speed |
1425 userTypeProbabilities = {userType2Num['car']: 1., userType2Num['pedestrian']: 1., userType2Num['bicycle']: 1.} | 1427 userTypeProbabilities = {userType2Num['car']: 1., userType2Num['pedestrian']: 1., userType2Num['bicycle']: 1.} |
1426 else: | 1428 else: |
1427 userTypeProbabilities = {userType2Num[userTypename]: speedProbabilities[userTypename](self.aggregatedSpeed) for userTypename in speedProbabilities} | 1429 userTypeProbabilities = {userType2Num[userTypename]: speedProbabilities[userTypename](self.aggregatedSpeed) for userTypename in speedProbabilities} |
1428 # result is P(Class|Appearance) x P(Speed|Class) | 1430 # result is P(Class|Appearance) x P(Speed|Class) |
1429 nInstantsUserType = {userType2Num[userTypename]: 0 for userTypename in userTypeProbabilities}# number of instants the object is classified as userTypename | 1431 nInstantsUserType = {userTypeNum: 0 for userTypeNum in userTypeProbabilities}# number of instants the object is classified as userTypename |
1430 for t in self.userTypes: | 1432 for t in self.userTypes: |
1431 nInstantsUserType[self.userTypes[t]] += 1 | 1433 nInstantsUserType[self.userTypes[t]] = nInstantsUserType.get(self.userTypes[t], 0) + 1 |
1432 for userTypename in userTypeProbabilities: | 1434 for userTypeNum in userTypeProbabilities: |
1433 userTypeProbabilities[userTypename] *= nInstantsUserType[userTypename] | 1435 userTypeProbabilities[userTypeNum] *= nInstantsUserType[userTypeNum] |
1434 # class is the user type that maximizes usertype probabilities | 1436 # class is the user type that maximizes usertype probabilities |
1435 self.setUserType(utils.argmaxDict(userTypeProbabilities)) | 1437 self.setUserType(utils.argmaxDict(userTypeProbabilities)) |
1436 | 1438 |
1437 def classifyUserTypeArea(self, areas, homography): | 1439 def classifyUserTypeArea(self, areas, homography): |
1438 '''Classifies the object based on its location (projected to image space) | 1440 '''Classifies the object based on its location (projected to image space) |