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)