Mercurial Hosting > traffic-intelligence
changeset 619:dc2d0a0d7fe1
merged code from Mohamed Gomaa Mohamed for the use of points of interests in mation pattern learning and motion prediction (TRB 2015)
author | Nicolas Saunier <nicolas.saunier@polymtl.ca> |
---|---|
date | Wed, 10 Dec 2014 15:27:08 -0500 |
parents | 04a8304e13f0 (diff) 1a92d28e2d05 (current diff) |
children | 582508610572 |
files | python/events.py python/moving.py python/objectsmoothing.py python/poly-utils.py python/prediction.py python/storage.py |
diffstat | 11 files changed, 567 insertions(+), 380 deletions(-) [+] |
line wrap: on
line diff
diff -r 1a92d28e2d05 -r dc2d0a0d7fe1 python/events.py --- a/python/events.py Wed Dec 10 14:35:30 2014 -0500 +++ b/python/events.py Wed Dec 10 15:27:08 2014 -0500 @@ -12,27 +12,27 @@ __metaclass__ = type def findRoute(prototypes,objects,i,j,noiseEntryNums,noiseExitNums,minSimilarity= 0.3, spatialThreshold=1.0, delta=180): - if i[0] not in noiseEntryNums: - prototypesRoutes= [ x for x in sorted(prototypes.keys()) if i[0]==x[0]] - elif i[1] not in noiseExitNums: - prototypesRoutes=[ x for x in sorted(prototypes.keys()) if i[1]==x[1]] - else: - prototypesRoutes=[x for x in sorted(prototypes.keys())] - routeSim={} - lcss = utils.LCSS(similarityFunc=lambda x,y: (distanceForLCSS(x,y) <= spatialThreshold),delta=delta) - for y in prototypesRoutes: - if y in prototypes.keys(): - prototypesIDs=prototypes[y] - similarity=[] - for x in prototypesIDs: - s=lcss.computeNormalized(objects[j].positions, objects[x].positions) - similarity.append(s) - routeSim[y]=max(similarity) - route=max(routeSim, key=routeSim.get) - if routeSim[route]>=minSimilarity: - return route - else: - return i + if i[0] not in noiseEntryNums: + prototypesRoutes= [ x for x in sorted(prototypes.keys()) if i[0]==x[0]] + elif i[1] not in noiseExitNums: + prototypesRoutes=[ x for x in sorted(prototypes.keys()) if i[1]==x[1]] + else: + prototypesRoutes=[x for x in sorted(prototypes.keys())] + routeSim={} + lcss = utils.LCSS(similarityFunc=lambda x,y: (distanceForLCSS(x,y) <= spatialThreshold),delta=delta) + for y in prototypesRoutes: + if y in prototypes.keys(): + prototypesIDs=prototypes[y] + similarity=[] + for x in prototypesIDs: + s=lcss.computeNormalized(objects[j].positions, objects[x].positions) + similarity.append(s) + routeSim[y]=max(similarity) + route=max(routeSim, key=routeSim.get) + if routeSim[route]>=minSimilarity: + return route + else: + return i def getRoute(obj,prototypes,objects,noiseEntryNums,noiseExitNums,useDestination=True): route=(obj.startRouteID,obj.endRouteID) @@ -177,9 +177,9 @@ for i, cz in self.crossingZones.iteritems(): pPETs[i] = prediction.SafetyPoint.computeExpectedIndicator(cz) self.addIndicator(indicators.SeverityIndicator(Interaction.indicatorNames[9], pPETs)) - + def addVideoFilename(self,videoFilename): - self.videoFilename= videoFilename + self.videoFilename= videoFilename def addInteractionType(self,interactionType): ''' interaction types: conflict or collision if they are known'''
diff -r 1a92d28e2d05 -r dc2d0a0d7fe1 python/moving.py --- a/python/moving.py Wed Dec 10 14:35:30 2014 -0500 +++ b/python/moving.py Wed Dec 10 15:27:08 2014 -0500 @@ -726,6 +726,11 @@ return Trajectory([[a-b for a,b in zip(self.getXCoordinates(),traj2.getXCoordinates())], [a-b for a,b in zip(self.getYCoordinates(),traj2.getYCoordinates())]]) + def multiply(self, alpha): + '''Returns a new trajectory of the same length''' + return Trajectory([[alpha*x for x in self.getXCoordinates()], + [alpha*y for y in self.getYCoordinates()]]) + def differentiate(self, doubleLastPosition = False): diff = Trajectory() for i in xrange(1, self.length()): @@ -1063,7 +1068,7 @@ else: print('Load features to compute a maximum size') return None - + def setRoutes(self, startRouteID, endRouteID): self.startRouteID = startRouteID self.endRouteID = endRouteID @@ -1286,17 +1291,127 @@ ################## class BBAnnotation(MovingObject): - '''Class for : a series of ground truth annotations using bounding boxes + '''Class for a series of ground truth annotations using bounding boxes Its center is the center of the containing shape + + By default in image space ''' - def __init__(self, num = None, timeInterval = None, topPositions = None, bottomPositions = None, userType = userType2Num['unknown']): - super(BBAnnotation, self).__init__(num, timeInterval, Trajectory(), userType = userType) - self.topPositions = topPositions.getPositions() - self.bottomPositions = bottomPositions.getPositions() - for i in xrange(int(topPositions.length())): - self.positions.addPosition((topPositions.getPositionAt(i) + bottomPositions.getPositionAt(i)).multiply(0.5)) + def __init__(self, num = None, timeInterval = None, topLeftPositions = None, bottomRightPositions = None, userType = userType2Num['unknown']): + super(BBAnnotation, self).__init__(num, timeInterval, userType = userType) + self.topLeftPositions = topLeftPositions.getPositions() + self.bottomRightPositions = bottomRightPositions.getPositions() + + def computeCentroidTrajectory(self, homography = None): + self.positions = self.topLeftPositions.add(self.bottomRightPositions).multiply(0.5) + if homography != None: + self.positions = self.positions.project(homography) + + def matches(self, obj, instant, matchingDistance): + '''Indicates if the annotation matches obj (MovingObject) + with threshold matchingDistance + Returns distance if below matchingDistance, matchingDistance+1 otherwise + (returns an actual value, otherwise munkres does not terminate)''' + d = Point.distanceNorm2(self.getPositionAtInstant(instant), obj.getPositionAtInstant(instant)) + if d < matchingDistance: + return d + else: + return matchingDistance + 1 + +def computeClearMOT(annotations, objects, matchingDistance, firstInstant, lastInstant, debug = False): + '''Computes the CLEAR MOT metrics + + Reference: + Keni, Bernardin, and Stiefelhagen Rainer. "Evaluating multiple object tracking performance: the CLEAR MOT metrics." EURASIP Journal on Image and Video Processing 2008 (2008) + + objects and annotations are supposed to in the same space + current implementation is BBAnnotations (bounding boxes) + mathingDistance is threshold on matching between annotation and object + + TO: tracker output (objects) + GT: ground truth (annotations) + + Should we use the distance as weights or just 1/0 if distance below matchingDistance? + (add argument useDistanceForWeights = False)''' + from munkres import Munkres + + munk = Munkres() + dist = 0. # total distance between GT and TO + ct = 0 # number of associations between GT and tracker output in each frame + gt = 0 # number of GT.frames + mt = 0 # number of missed GT.frames (sum of the number of GT not detected in each frame) + fpt = 0 # number of false alarm.frames (tracker objects without match in each frame) + mme = 0 # number of mismatches + matches = {} # match[i] is the tracker track associated with GT i (using object references) + for t in xrange(firstInstant, lastInstant+1): + previousMatches = matches.copy() + # go through currently matched GT-TO and check if they are still matched withing matchingDistance + toDelete = [] + for a in matches: + if a.existsAtInstant(t) and matches[a].existsAtInstant(t): + d = a.matches(matches[a], t, matchingDistance) + if d < matchingDistance: + dist += d + else: + toDelete.append(a) + else: + toDelete.append(a) + for a in toDelete: + del matches[a] + + # match all unmatched GT-TO + matchedGTs = matches.keys() + matchedTOs = matches.values() + costs = [] + unmatchedGTs = [a for a in annotations if a.existsAtInstant(t) and a not in matchedGTs] + unmatchedTOs = [o for o in objects if o.existsAtInstant(t) and o not in matchedTOs] + nGTs = len(matchedGTs)+len(unmatchedGTs) + nTOs = len(matchedTOs)+len(unmatchedTOs) + if len(unmatchedTOs) > 0: + for a in unmatchedGTs: + costs.append([a.matches(o, t, matchingDistance) for o in unmatchedTOs]) + if len(costs) > 0: + newMatches = munk.compute(costs) + for k,v in newMatches: + if costs[k][v] < matchingDistance: + matches[unmatchedGTs[k]]=unmatchedTOs[v] + dist += costs[k][v] + if debug: + print('{} '.format(t)+', '.join(['{} {}'.format(k.getNum(), v.getNum()) for k,v in matches.iteritems()])) + # compute metrics elements + ct += len(matches) + mt += nGTs-len(matches) + fpt += nTOs-len(matches) + gt += nGTs + # compute mismatches + # for gt that do not appear in both frames, check if the corresponding to was matched to another gt in previous/next frame + mismatches = [] + for a in matches: + if a in previousMatches: + if matches[a] != previousMatches[a]: + mismatches.append(a) + elif matches[a] in previousMatches.values(): + mismatches.append(matches[a]) + for a in previousMatches: + if a not in matches and previousMatches[a] in matches.values(): + mismatches.append(previousMatches[a]) + if debug: + for mm in set(mismatches): + print type(mm), mm.getNum() + # some object mismatches may appear twice + mme += len(set(mismatches)) + + if ct > 0: + motp = dist/ct + else: + motp = None + if gt > 0: + mota = 1.-float(mt+fpt+mme)/gt + else: + mota = None + return motp, mota, mt, mme, fpt, gt + def plotRoadUsers(objects, colors): '''Colors is a PlottingPropertyValues instance'''
diff -r 1a92d28e2d05 -r dc2d0a0d7fe1 python/objectsmoothing.py --- a/python/objectsmoothing.py Wed Dec 10 14:35:30 2014 -0500 +++ b/python/objectsmoothing.py Wed Dec 10 15:27:08 2014 -0500 @@ -1,234 +1,234 @@ -import storage, moving, utils -from math import * #atan2,asin,degrees,sin,cos,pi -import numpy as np - -import matplotlib.pyplot as plt - -def findNearest(feat, featureSet,t,reverse=True): - dist={} - for f in featureSet: - if reverse: - dist[f]= moving.Point.distanceNorm2(feat.getPositionAtInstant(t+1),f.getPositionAtInstant(t)) - else: - dist[f]= moving.Point.distanceNorm2(feat.getPositionAtInstant(t-1),f.getPositionAtInstant(t)) - return min(dist, key=dist.get) # = utils.argmaxDict(dist) - -def getFeatures(obj,features,featureID): - #longestFeature = utils.argmaxDict({f:f.length() for i,f in enumerate(obj.features)}) - t1,t3 = features[featureID].getFirstInstant(), features[featureID].getLastInstant() - listFeatures=[[features[featureID],t1,t3,moving.Point(0,0)]] - # find the features to fill in the beginning of the object existence - currentFeature = features[featureID] - while t1!=obj.getFirstInstant(): - delta=listFeatures[-1][3] - featureSet = [f for f in obj.features if f.existsAtInstant(t1-1)] - feat = findNearest(currentFeature,featureSet,t1-1,reverse=True) - if feat.existsAtInstant(t1): - listFeatures.append([feat,feat.getFirstInstant(),t1-1,(currentFeature.getPositionAtInstant(t1)-feat.getPositionAtInstant(t1))+delta]) - else: - listFeatures.append([feat,feat.getFirstInstant(),t1-1,(currentFeature.getPositionAtInstant(t1)-feat.getPositionAtInstant(t1-1))+delta]) - currentFeature = feat - t1= feat.getFirstInstant() - # find the features to fill in the end of the object existence - delta=moving.Point(0,0) - currentFeature = features[featureID] - while t3!= obj.getLastInstant(): - featureSet = [f for f in obj.features if f.existsAtInstant(t3+1)] - feat = findNearest(currentFeature,featureSet,t3+1,reverse=False) - if feat.existsAtInstant(t3): - listFeatures.append([feat,t3+1,feat.getLastInstant(),(currentFeature.getPositionAtInstant(t3)-feat.getPositionAtInstant(t3))+delta]) - else: - listFeatures.append([feat,t3+1,feat.getLastInstant(),(currentFeature.getPositionAtInstant(t3)-feat.getPositionAtInstant(t3+1))+delta]) - currentFeature = feat - t3= feat.getLastInstant() - delta=listFeatures[-1][3] - return listFeatures - -def buildFeature(obj,features,featureID,num=1): - listFeatures= getFeatures(obj,features,featureID) - tmp={} - delta={} - for i in listFeatures: - for t in xrange(i[1],i[2]+1): - tmp[t]=[i[0],i[3]] - newTraj = moving.Trajectory() - - for instant in obj.getTimeInterval(): - newTraj.addPosition(tmp[instant][0].getPositionAtInstant(instant)+tmp[instant][1]) - newFeature= moving.MovingObject(num,timeInterval=obj.getTimeInterval(),positions=newTraj) - return newFeature - -def getBearing(p1,p2,p3): - angle = degrees(atan2(p3.y -p1.y, p3.x -p1.x)) - bearing1 = (90 - angle) % 360 - angle2 = degrees(atan2(p2.y -p1.y, p2.x -p1.x)) - bearing2 = (90 - angle2) % 360 - dist= moving.Point.distanceNorm2(p1, p2) - return [dist,bearing1,bearing2,bearing2-bearing1] - -#Quantitative analysis "CSJ" functions -def computeVelocities (object,smoothing=True,halfWidth=3): #compute velocities from positions - velocities={} - for i in list(object.timeInterval)[:-1]: - p1= object.getPositionAtInstant(i) - p2= object.getPositionAtInstant(i+1) - velocities[i]=p2-p1 - velocities[object.getLastInstant()]= velocities[object.getLastInstant()-1] # duplicate last point - if smoothing: - velX= [velocities[y].aslist()[0] for y in sorted(velocities.keys())] - velY= [velocities[y].aslist()[1] for y in sorted(velocities.keys())] - v1= list(utils.filterMovingWindow(velX, halfWidth)) - v2= list(utils.filterMovingWindow(velY, halfWidth)) - smoothedVelocity={} - for t,i in enumerate(sorted(velocities.keys())): - smoothedVelocity[i]=moving.Point(v1[t], v2[t]) - velocities=smoothedVelocity - return velocities - -def computeAcceleration (object,fromPosition=True): - acceleration={} - if fromPosition: - velocities=computeVelocities(object,False,1) - for i in sorted (velocities.keys()): - if i != sorted (velocities.keys())[-1]: - acceleration[i]= velocities[i+1]-velocities[i] - else: - for i in list(object.timeInterval)[:-1]: - v1= object.getVelocityAtInstant(i) - v2= object.getVelocityAtInstant(i+1) - acceleration[i]= v2-v1 - return acceleration - -def computeJerk (object,fromPosition=True): - jerk={} - acceleration=computeAcceleration (object,fromPosition=fromPosition) - for i in sorted (acceleration.keys()): - if i != sorted (acceleration.keys())[-1]: - jerk[i]= (acceleration[i+1]-acceleration[i]).norm2() - return jerk - -def sumSquaredJerk (object,fromPosition=True): - jerk= computeJerk (object,fromPosition=fromPosition) - t=0 - for i in sorted(jerk.keys()): - t+= jerk[i]* jerk[i] - return t - -def smoothObjectTrajectory(obj,features,featureID,newNum,smoothing=False,halfWidth=3,create=False): - results=[] - bearing={} - if create: - feature= buildFeature(obj,features,featureID,num=1) - else: - feature=features[featureID] - for t in feature.getTimeInterval(): - p1= feature.getPositionAtInstant(t) - p2= obj.getPositionAtInstant(t) - if t!=feature.getLastInstant(): - p3= feature.getPositionAtInstant(t+1) - else: - p1= feature.getPositionAtInstant(t-1) - p3= feature.getPositionAtInstant(t) - bearing[t]= getBearing(p1,p2,p3)[1] - results.append(getBearing(p1,p2,p3)) - - - medianResults=np.median(results,0) - dist= medianResults[0] - angle= medianResults[3] - - for i in sorted(bearing.keys()): - bearing[i]= bearing[i]+angle - - if smoothing: - bearingInput=[] - for i in sorted(bearing.keys()): - bearingInput.append(bearing[i]) - import utils - bearingOut=utils.filterMovingWindow(bearingInput, halfWidth) - for t,i in enumerate(sorted(bearing.keys())): - bearing[i]=bearingOut[t] - - #solve a smoothing problem in case of big drop in computing bearing (0,360) - for t,i in enumerate(sorted(bearing.keys())): - if i!= max(bearing.keys()) and abs(bearingInput[t] - bearingInput[t+1])>=340: - for x in xrange(max(i-halfWidth,min(bearing.keys())),min(i+halfWidth,max(bearing.keys()))+1): - bearing[x]=bearingInput[t-i+x] - - translated = moving.Trajectory() - for t in feature.getTimeInterval(): - p1= feature.getPositionAtInstant(t) - p1.x = p1.x + dist*sin(bearing[t]*pi/180) - p1.y = p1.y + dist*cos(bearing[t]*pi/180) - translated.addPosition(p1) - - #modify first and last un-smoothed positions (half width) - if smoothing: - d1= translated[halfWidth]- feature.positions[halfWidth] - d2= translated[-halfWidth-1]- feature.positions[-halfWidth-1] - for i in xrange(halfWidth): - p1= feature.getPositionAt(i)+d1 - p2= feature.getPositionAt(-i-1)+d2 - translated.setPosition(i,p1) - translated.setPosition(-i-1,p2) - - newObj= moving.MovingObject(newNum,timeInterval=feature.getTimeInterval(),positions=translated) - return newObj - -def smoothObjectTrajectory(obj,features,newNum,minLengthParam=0.7,smoothing=False,plotResults=True,halfWidth=3,computeVelocities=True,optimize=True,create=False): - featureList=[i.num for i in obj.features if i.length() >= minLengthParam*obj.length()] - if featureList==[]: - featureList.append(longestFeature(obj)) - create=True - objs=[] - for featureID in featureList: - objTMP=smoothObjectTrajectory(obj,features,featureID,newNum,smoothing=smoothing,halfWidth=halfWidth,create=create) - objs.append(objTMP) - newTranslated = moving.Trajectory() - newInterval=[] - for t in obj.timeInterval: - xCoord=[] - yCoord=[] - for i in objs: - if i.existsAtInstant(t): - p1= i.getPositionAtInstant(t) - xCoord.append(p1.x) - yCoord.append(p1.y) - if xCoord!=[]: - tmp= moving.Point(np.median(xCoord),np.median(yCoord)) - newInterval.append(t) - newTranslated.addPosition(tmp) - - newObj= moving.MovingObject(newNum,timeInterval=moving.TimeInterval(min(newInterval),max(newInterval)),positions=newTranslated) - - if computeVelocities: - tmpTraj = moving.Trajectory() - velocities= computeVelocities(newObj,True,5) - for i in sorted(velocities.keys()): - tmpTraj.addPosition(velocities[i]) - newObj.velocities=tmpTraj - else: - newObj.velocities=obj.velocities - - if optimize: - csj1= sumSquaredJerk (obj,fromPosition=True) - csj2= sumSquaredJerk (newObj,fromPosition=True) - if csj1<csj2: - newObj=obj - newObj.velocities=obj.velocities - if computeVelocities and csj1>=csj2: - csj3= sumSquaredJerk (obj,fromPosition=False) - csj4= sumSquaredJerk (newObj,fromPosition=False) - if csj4<=csj3: - newObj.velocities= obj.velocities - newObj.featureNumbers=obj.featureNumbers - newObj.features=obj.features - newObj.userType=obj.userType - if plotResults: - plt.figure() - plt.title('objects_id = {}'.format(obj.num)) - for i in featureList: - features[i].plot('cx-') - obj.plot('rx-') - newObj.plot('gx-') - return newObj \ No newline at end of file +import storage, moving, utils +from math import * #atan2,asin,degrees,sin,cos,pi +import numpy as np + +import matplotlib.pyplot as plt + +def findNearest(feat, featureSet,t,reverse=True): + dist={} + for f in featureSet: + if reverse: + dist[f]= moving.Point.distanceNorm2(feat.getPositionAtInstant(t+1),f.getPositionAtInstant(t)) + else: + dist[f]= moving.Point.distanceNorm2(feat.getPositionAtInstant(t-1),f.getPositionAtInstant(t)) + return min(dist, key=dist.get) # = utils.argmaxDict(dist) + +def getFeatures(obj,features,featureID): + #longestFeature = utils.argmaxDict({f:f.length() for i,f in enumerate(obj.features)}) + t1,t3 = features[featureID].getFirstInstant(), features[featureID].getLastInstant() + listFeatures=[[features[featureID],t1,t3,moving.Point(0,0)]] + # find the features to fill in the beginning of the object existence + currentFeature = features[featureID] + while t1!=obj.getFirstInstant(): + delta=listFeatures[-1][3] + featureSet = [f for f in obj.features if f.existsAtInstant(t1-1)] + feat = findNearest(currentFeature,featureSet,t1-1,reverse=True) + if feat.existsAtInstant(t1): + listFeatures.append([feat,feat.getFirstInstant(),t1-1,(currentFeature.getPositionAtInstant(t1)-feat.getPositionAtInstant(t1))+delta]) + else: + listFeatures.append([feat,feat.getFirstInstant(),t1-1,(currentFeature.getPositionAtInstant(t1)-feat.getPositionAtInstant(t1-1))+delta]) + currentFeature = feat + t1= feat.getFirstInstant() + # find the features to fill in the end of the object existence + delta=moving.Point(0,0) + currentFeature = features[featureID] + while t3!= obj.getLastInstant(): + featureSet = [f for f in obj.features if f.existsAtInstant(t3+1)] + feat = findNearest(currentFeature,featureSet,t3+1,reverse=False) + if feat.existsAtInstant(t3): + listFeatures.append([feat,t3+1,feat.getLastInstant(),(currentFeature.getPositionAtInstant(t3)-feat.getPositionAtInstant(t3))+delta]) + else: + listFeatures.append([feat,t3+1,feat.getLastInstant(),(currentFeature.getPositionAtInstant(t3)-feat.getPositionAtInstant(t3+1))+delta]) + currentFeature = feat + t3= feat.getLastInstant() + delta=listFeatures[-1][3] + return listFeatures + +def buildFeature(obj,features,featureID,num=1): + listFeatures= getFeatures(obj,features,featureID) + tmp={} + delta={} + for i in listFeatures: + for t in xrange(i[1],i[2]+1): + tmp[t]=[i[0],i[3]] + newTraj = moving.Trajectory() + + for instant in obj.getTimeInterval(): + newTraj.addPosition(tmp[instant][0].getPositionAtInstant(instant)+tmp[instant][1]) + newFeature= moving.MovingObject(num,timeInterval=obj.getTimeInterval(),positions=newTraj) + return newFeature + +def getBearing(p1,p2,p3): + angle = degrees(atan2(p3.y -p1.y, p3.x -p1.x)) + bearing1 = (90 - angle) % 360 + angle2 = degrees(atan2(p2.y -p1.y, p2.x -p1.x)) + bearing2 = (90 - angle2) % 360 + dist= moving.Point.distanceNorm2(p1, p2) + return [dist,bearing1,bearing2,bearing2-bearing1] + +#Quantitative analysis "CSJ" functions +def computeVelocities (object,smoothing=True,halfWidth=3): #compute velocities from positions + velocities={} + for i in list(object.timeInterval)[:-1]: + p1= object.getPositionAtInstant(i) + p2= object.getPositionAtInstant(i+1) + velocities[i]=p2-p1 + velocities[object.getLastInstant()]= velocities[object.getLastInstant()-1] # duplicate last point + if smoothing: + velX= [velocities[y].aslist()[0] for y in sorted(velocities.keys())] + velY= [velocities[y].aslist()[1] for y in sorted(velocities.keys())] + v1= list(utils.filterMovingWindow(velX, halfWidth)) + v2= list(utils.filterMovingWindow(velY, halfWidth)) + smoothedVelocity={} + for t,i in enumerate(sorted(velocities.keys())): + smoothedVelocity[i]=moving.Point(v1[t], v2[t]) + velocities=smoothedVelocity + return velocities + +def computeAcceleration (object,fromPosition=True): + acceleration={} + if fromPosition: + velocities=computeVelocities(object,False,1) + for i in sorted (velocities.keys()): + if i != sorted (velocities.keys())[-1]: + acceleration[i]= velocities[i+1]-velocities[i] + else: + for i in list(object.timeInterval)[:-1]: + v1= object.getVelocityAtInstant(i) + v2= object.getVelocityAtInstant(i+1) + acceleration[i]= v2-v1 + return acceleration + +def computeJerk (object,fromPosition=True): + jerk={} + acceleration=computeAcceleration (object,fromPosition=fromPosition) + for i in sorted (acceleration.keys()): + if i != sorted (acceleration.keys())[-1]: + jerk[i]= (acceleration[i+1]-acceleration[i]).norm2() + return jerk + +def sumSquaredJerk (object,fromPosition=True): + jerk= computeJerk (object,fromPosition=fromPosition) + t=0 + for i in sorted(jerk.keys()): + t+= jerk[i]* jerk[i] + return t + +def smoothObjectTrajectory(obj,features,featureID,newNum,smoothing=False,halfWidth=3,create=False): + results=[] + bearing={} + if create: + feature= buildFeature(obj,features,featureID,num=1) + else: + feature=features[featureID] + for t in feature.getTimeInterval(): + p1= feature.getPositionAtInstant(t) + p2= obj.getPositionAtInstant(t) + if t!=feature.getLastInstant(): + p3= feature.getPositionAtInstant(t+1) + else: + p1= feature.getPositionAtInstant(t-1) + p3= feature.getPositionAtInstant(t) + bearing[t]= getBearing(p1,p2,p3)[1] + results.append(getBearing(p1,p2,p3)) + + + medianResults=np.median(results,0) + dist= medianResults[0] + angle= medianResults[3] + + for i in sorted(bearing.keys()): + bearing[i]= bearing[i]+angle + + if smoothing: + bearingInput=[] + for i in sorted(bearing.keys()): + bearingInput.append(bearing[i]) + import utils + bearingOut=utils.filterMovingWindow(bearingInput, halfWidth) + for t,i in enumerate(sorted(bearing.keys())): + bearing[i]=bearingOut[t] + + #solve a smoothing problem in case of big drop in computing bearing (0,360) + for t,i in enumerate(sorted(bearing.keys())): + if i!= max(bearing.keys()) and abs(bearingInput[t] - bearingInput[t+1])>=340: + for x in xrange(max(i-halfWidth,min(bearing.keys())),min(i+halfWidth,max(bearing.keys()))+1): + bearing[x]=bearingInput[t-i+x] + + translated = moving.Trajectory() + for t in feature.getTimeInterval(): + p1= feature.getPositionAtInstant(t) + p1.x = p1.x + dist*sin(bearing[t]*pi/180) + p1.y = p1.y + dist*cos(bearing[t]*pi/180) + translated.addPosition(p1) + + #modify first and last un-smoothed positions (half width) + if smoothing: + d1= translated[halfWidth]- feature.positions[halfWidth] + d2= translated[-halfWidth-1]- feature.positions[-halfWidth-1] + for i in xrange(halfWidth): + p1= feature.getPositionAt(i)+d1 + p2= feature.getPositionAt(-i-1)+d2 + translated.setPosition(i,p1) + translated.setPosition(-i-1,p2) + + newObj= moving.MovingObject(newNum,timeInterval=feature.getTimeInterval(),positions=translated) + return newObj + +def smoothObjectTrajectory(obj,features,newNum,minLengthParam=0.7,smoothing=False,plotResults=True,halfWidth=3,computeVelocities=True,optimize=True,create=False): + featureList=[i.num for i in obj.features if i.length() >= minLengthParam*obj.length()] + if featureList==[]: + featureList.append(longestFeature(obj)) + create=True + objs=[] + for featureID in featureList: + objTMP=smoothObjectTrajectory(obj,features,featureID,newNum,smoothing=smoothing,halfWidth=halfWidth,create=create) + objs.append(objTMP) + newTranslated = moving.Trajectory() + newInterval=[] + for t in obj.timeInterval: + xCoord=[] + yCoord=[] + for i in objs: + if i.existsAtInstant(t): + p1= i.getPositionAtInstant(t) + xCoord.append(p1.x) + yCoord.append(p1.y) + if xCoord!=[]: + tmp= moving.Point(np.median(xCoord),np.median(yCoord)) + newInterval.append(t) + newTranslated.addPosition(tmp) + + newObj= moving.MovingObject(newNum,timeInterval=moving.TimeInterval(min(newInterval),max(newInterval)),positions=newTranslated) + + if computeVelocities: + tmpTraj = moving.Trajectory() + velocities= computeVelocities(newObj,True,5) + for i in sorted(velocities.keys()): + tmpTraj.addPosition(velocities[i]) + newObj.velocities=tmpTraj + else: + newObj.velocities=obj.velocities + + if optimize: + csj1= sumSquaredJerk (obj,fromPosition=True) + csj2= sumSquaredJerk (newObj,fromPosition=True) + if csj1<csj2: + newObj=obj + newObj.velocities=obj.velocities + if computeVelocities and csj1>=csj2: + csj3= sumSquaredJerk (obj,fromPosition=False) + csj4= sumSquaredJerk (newObj,fromPosition=False) + if csj4<=csj3: + newObj.velocities= obj.velocities + newObj.featureNumbers=obj.featureNumbers + newObj.features=obj.features + newObj.userType=obj.userType + if plotResults: + plt.figure() + plt.title('objects_id = {}'.format(obj.num)) + for i in featureList: + features[i].plot('cx-') + obj.plot('rx-') + newObj.plot('gx-') + return newObj
diff -r 1a92d28e2d05 -r dc2d0a0d7fe1 python/poly-utils.py --- a/python/poly-utils.py Wed Dec 10 14:35:30 2014 -0500 +++ b/python/poly-utils.py Wed Dec 10 15:27:08 2014 -0500 @@ -33,8 +33,8 @@ values= {} for i,t in enumerate(indicatorFrameNums): values[t] = [data[i,index] for index in selectedIndicators] - inter.addIndicator(SeverityIndicator('selectedIndicators', values)) - + inter.addIndicator(SeverityIndicator('selectedIndicators', values)) + #interactions.append(inter) file.close() #return interactions @@ -118,9 +118,9 @@ else: for i in xrange(time[0],time[-1]+1): try: - tmp = getDataAtInstant(roadUserData, i) - values[i] = np.sum(tmp[:,5]*tmp[:,6])/np.sum(tmp[:,5])/frameRate + tmp = getDataAtInstant(roadUserData, i) + values[i] = np.sum(tmp[:,5]*tmp[:,6])/np.sum(tmp[:,5])/frameRate except IOError: - values[i] = np.inf + values[i] = np.inf return SeverityIndicator(indicatorName, values, mostSevereIsMax = False), roadUserData - return None, None \ No newline at end of file + return None, None
diff -r 1a92d28e2d05 -r dc2d0a0d7fe1 python/prediction.py --- a/python/prediction.py Wed Dec 10 14:35:30 2014 -0500 +++ b/python/prediction.py Wed Dec 10 15:27:08 2014 -0500 @@ -48,14 +48,14 @@ def getControl(self): return self.control - + def findNearestParams(initialPosition,prototypeTrajectory): - ''' nearest parameters are the index of minDistance and the orientation ''' - distances=[] - for position in prototypeTrajectory.positions: - distances.append(moving.Point.distanceNorm2(initialPosition, position)) - minDistanceIndex= np.argmin(distances) - return minDistanceIndex, moving.NormAngle.fromPoint(prototypeTrajectory.velocities[minDistanceIndex]).angle + ''' nearest parameters are the index of minDistance and the orientation ''' + distances=[] + for position in prototypeTrajectory.positions: + distances.append(moving.Point.distanceNorm2(initialPosition, position)) + minDistanceIndex= np.argmin(distances) + return minDistanceIndex, moving.NormAngle.fromPoint(prototypeTrajectory.velocities[minDistanceIndex]).angle class PredictedTrajectoryPrototype(PredictedTrajectory): '''Predicted trajectory that follows a prototype trajectory @@ -84,7 +84,7 @@ anglePrototype = findNearestParams(self.predictedPositions[nTimeSteps-1],self.prototypeTrajectory)[1] self.predictedSpeedOrientations[nTimeSteps]= moving.NormAngle(speedNorm, anglePrototype) self.predictedPositions[nTimeSteps],tmp= moving.predictPosition(self.predictedPositions[nTimeSteps-1], self.predictedSpeedOrientations[nTimeSteps-1], moving.NormAngle(0,0), None) - + else: # see c++ code, calculate ratio speedNorm= self.predictedSpeedOrientations[0].norm instant=findNearestParams(self.predictedPositions[0],self.prototypeTrajectory)[0] @@ -94,7 +94,7 @@ anglePrototype = findNearestParams(self.predictedPositions[nTimeSteps-1],self.prototypeTrajectory)[1] if nTimeSteps<len(resampledSpeeds): self.predictedSpeedOrientations[nTimeSteps]= moving.NormAngle(resampledSpeeds[nTimeSteps], anglePrototype) - self.predictedPositions[nTimeSteps],tmp= moving.predictPosition(self.predictedPositions[nTimeSteps-1], self.predictedSpeedOrientations[nTimeSteps-1], moving.NormAngle(0,0), None) + self.predictedPositions[nTimeSteps],tmp= moving.predictPosition(self.predictedPositions[nTimeSteps-1], self.predictedSpeedOrientations[nTimeSteps-1], moving.NormAngle(0,0), None) else: self.predictedSpeedOrientations[nTimeSteps]= moving.NormAngle(resampledSpeeds[-1], anglePrototype) self.predictedPositions[nTimeSteps],tmp= moving.predictPosition(self.predictedPositions[nTimeSteps-1], self.predictedSpeedOrientations[nTimeSteps-1], moving.NormAngle(0,0), None) @@ -168,93 +168,93 @@ close() def calculateProbability(nMatching,similarity,objects): - sumFrequencies=sum([nMatching[p] for p in similarity.keys()]) - prototypeProbability={} - for i in similarity.keys(): - prototypeProbability[i]= similarity[i] * float(nMatching[i])/sumFrequencies - sumProbabilities= sum([prototypeProbability[p] for p in prototypeProbability.keys()]) - probabilities={} - for i in prototypeProbability.keys(): - probabilities[objects[i]]= float(prototypeProbability[i])/sumProbabilities - return probabilities + sumFrequencies=sum([nMatching[p] for p in similarity.keys()]) + prototypeProbability={} + for i in similarity.keys(): + prototypeProbability[i]= similarity[i] * float(nMatching[i])/sumFrequencies + sumProbabilities= sum([prototypeProbability[p] for p in prototypeProbability.keys()]) + probabilities={} + for i in prototypeProbability.keys(): + probabilities[objects[i]]= float(prototypeProbability[i])/sumProbabilities + return probabilities def findPrototypes(prototypes,nMatching,objects,route,partialObjPositions,noiseEntryNums,noiseExitNums,minSimilarity=0.1,mostMatched=None,spatialThreshold=1.0, delta=180): - ''' behaviour prediction first step''' - if route[0] not in noiseEntryNums: - prototypesRoutes= [ x for x in sorted(prototypes.keys()) if route[0]==x[0]] - elif route[1] not in noiseExitNums: - prototypesRoutes=[ x for x in sorted(prototypes.keys()) if route[1]==x[1]] - else: - prototypesRoutes=[x for x in sorted(prototypes.keys())] - lcss = LCSS(similarityFunc=lambda x,y: (distanceForLCSS(x,y) <= spatialThreshold),delta=delta) - similarity={} - for y in prototypesRoutes: - if y in prototypes.keys(): - prototypesIDs=prototypes[y] - for x in prototypesIDs: - s=lcss.computeNormalized(partialObjPositions, objects[x].positions) - if s >= minSimilarity: - similarity[x]=s - - if mostMatched==None: - probabilities= calculateProbability(nMatching,similarity,objects) - return probabilities - else: - mostMatchedValues=sorted(similarity.values(),reverse=True)[:mostMatched] - keys=[k for k in similarity.keys() if similarity[k] in mostMatchedValues] - newSimilarity={} - for i in keys: - newSimilarity[i]=similarity[i] - probabilities= calculateProbability(nMatching,newSimilarity,objects) - return probabilities - + ''' behaviour prediction first step''' + if route[0] not in noiseEntryNums: + prototypesRoutes= [ x for x in sorted(prototypes.keys()) if route[0]==x[0]] + elif route[1] not in noiseExitNums: + prototypesRoutes=[ x for x in sorted(prototypes.keys()) if route[1]==x[1]] + else: + prototypesRoutes=[x for x in sorted(prototypes.keys())] + lcss = LCSS(similarityFunc=lambda x,y: (distanceForLCSS(x,y) <= spatialThreshold),delta=delta) + similarity={} + for y in prototypesRoutes: + if y in prototypes.keys(): + prototypesIDs=prototypes[y] + for x in prototypesIDs: + s=lcss.computeNormalized(partialObjPositions, objects[x].positions) + if s >= minSimilarity: + similarity[x]=s + + if mostMatched==None: + probabilities= calculateProbability(nMatching,similarity,objects) + return probabilities + else: + mostMatchedValues=sorted(similarity.values(),reverse=True)[:mostMatched] + keys=[k for k in similarity.keys() if similarity[k] in mostMatchedValues] + newSimilarity={} + for i in keys: + newSimilarity[i]=similarity[i] + probabilities= calculateProbability(nMatching,newSimilarity,objects) + return probabilities + def findPrototypesSpeed(prototypes,secondStepPrototypes,nMatching,objects,route,partialObjPositions,noiseEntryNums,noiseExitNums,minSimilarity=0.1,mostMatched=None,useDestination=True,spatialThreshold=1.0, delta=180): - if useDestination: - prototypesRoutes=[route] - else: - if route[0] not in noiseEntryNums: - prototypesRoutes= [ x for x in sorted(prototypes.keys()) if route[0]==x[0]] - elif route[1] not in noiseExitNums: - prototypesRoutes=[ x for x in sorted(prototypes.keys()) if route[1]==x[1]] - else: - prototypesRoutes=[x for x in sorted(prototypes.keys())] - lcss = LCSS(similarityFunc=lambda x,y: (distanceForLCSS(x,y) <= spatialThreshold),delta=delta) - similarity={} - for y in prototypesRoutes: - if y in prototypes.keys(): - prototypesIDs=prototypes[y] - for x in prototypesIDs: - s=lcss.computeNormalized(partialObjPositions, objects[x].positions) - if s >= minSimilarity: - similarity[x]=s - - newSimilarity={} - for i in similarity.keys(): - if i in secondStepPrototypes.keys(): - for j in secondStepPrototypes[i]: - newSimilarity[j]=similarity[i] - probabilities= calculateProbability(nMatching,newSimilarity,objects) - return probabilities - + if useDestination: + prototypesRoutes=[route] + else: + if route[0] not in noiseEntryNums: + prototypesRoutes= [ x for x in sorted(prototypes.keys()) if route[0]==x[0]] + elif route[1] not in noiseExitNums: + prototypesRoutes=[ x for x in sorted(prototypes.keys()) if route[1]==x[1]] + else: + prototypesRoutes=[x for x in sorted(prototypes.keys())] + lcss = LCSS(similarityFunc=lambda x,y: (distanceForLCSS(x,y) <= spatialThreshold),delta=delta) + similarity={} + for y in prototypesRoutes: + if y in prototypes.keys(): + prototypesIDs=prototypes[y] + for x in prototypesIDs: + s=lcss.computeNormalized(partialObjPositions, objects[x].positions) + if s >= minSimilarity: + similarity[x]=s + + newSimilarity={} + for i in similarity.keys(): + if i in secondStepPrototypes.keys(): + for j in secondStepPrototypes[i]: + newSimilarity[j]=similarity[i] + probabilities= calculateProbability(nMatching,newSimilarity,objects) + return probabilities + def getPrototypeTrajectory(obj,route,currentInstant,prototypes,secondStepPrototypes,nMatching,objects,noiseEntryNums,noiseExitNums,minSimilarity=0.1,mostMatched=None,useDestination=True,useSpeedPrototype=True): partialInterval=moving.Interval(obj.getFirstInstant(),currentInstant) - partialObjPositions= obj.getObjectInTimeInterval(partialInterval).positions + partialObjPositions= obj.getObjectInTimeInterval(partialInterval).positions if useSpeedPrototype: prototypeTrajectories=findPrototypesSpeed(prototypes,secondStepPrototypes,nMatching,objects,route,partialObjPositions,noiseEntryNums,noiseExitNums,minSimilarity,mostMatched,useDestination) else: prototypeTrajectories=findPrototypes(prototypes,nMatching,objects,route,partialObjPositions,noiseEntryNums,noiseExitNums,minSimilarity,mostMatched) - return prototypeTrajectories + return prototypeTrajectories def computeCrossingsCollisionsAtInstant(predictionParams,currentInstant, obj1, obj2, collisionDistanceThreshold, timeHorizon, computeCZ = False, debug = False,usePrototypes=True,route1= (-1,-1),route2=(-1,-1),prototypes={},secondStepPrototypes={},nMatching={},objects=[],noiseEntryNums=[],noiseExitNums=[],minSimilarity=0.1,mostMatched=None,useDestination=True,useSpeedPrototype=True): '''returns the lists of collision points and crossing zones''' if usePrototypes: - prototypeTrajectories1=getPrototypeTrajectory(obj1,route1,currentInstant,prototypes,secondStepPrototypes,nMatching,objects,noiseEntryNums,noiseExitNums,minSimilarity,mostMatched,useDestination,useSpeedPrototype) - prototypeTrajectories2= getPrototypeTrajectory(obj2,route2,currentInstant,prototypes,secondStepPrototypes,nMatching,objects,noiseEntryNums,noiseExitNums,minSimilarity,mostMatched,useDestination,useSpeedPrototype) - predictedTrajectories1 = predictionParams.generatePredictedTrajectories(obj1, currentInstant,prototypeTrajectories1) - predictedTrajectories2 = predictionParams.generatePredictedTrajectories(obj2, currentInstant,prototypeTrajectories2) + prototypeTrajectories1=getPrototypeTrajectory(obj1,route1,currentInstant,prototypes,secondStepPrototypes,nMatching,objects,noiseEntryNums,noiseExitNums,minSimilarity,mostMatched,useDestination,useSpeedPrototype) + prototypeTrajectories2= getPrototypeTrajectory(obj2,route2,currentInstant,prototypes,secondStepPrototypes,nMatching,objects,noiseEntryNums,noiseExitNums,minSimilarity,mostMatched,useDestination,useSpeedPrototype) + predictedTrajectories1 = predictionParams.generatePredictedTrajectories(obj1, currentInstant,prototypeTrajectories1) + predictedTrajectories2 = predictionParams.generatePredictedTrajectories(obj2, currentInstant,prototypeTrajectories2) else: predictedTrajectories1 = predictionParams.generatePredictedTrajectories(obj1, currentInstant) - predictedTrajectories2 = predictionParams.generatePredictedTrajectories(obj2, currentInstant) + predictedTrajectories2 = predictionParams.generatePredictedTrajectories(obj2, currentInstant) collisionPoints = [] crossingZones = [] @@ -276,7 +276,7 @@ #if (et1.predictPosition(t1)-et2.predictPosition(t2)).norm2() < collisionDistanceThreshold: # cz = (et1.predictPosition(t1)+et2.predictPosition(t2)).multiply(0.5) cz = moving.segmentIntersection(et1.predictPosition(t1), et1.predictPosition(t1+1), et2.predictPosition(t2), et2.predictPosition(t2+1)) - if cz: + if cz != None: deltaV= (et1.predictPosition(t1)- et1.predictPosition(t1+1) - et2.predictPosition(t2)+ et2.predictPosition(t2+1)).norm2() crossingZones.append(SafetyPoint(cz, et1.probability*et2.probability, abs(t1-t2)-(float(collisionDistanceThreshold)/deltaV))) t2 += 1 @@ -284,7 +284,8 @@ if debug: savePredictedTrajectoriesFigure(currentInstant, obj1, obj2, predictedTrajectories1, predictedTrajectories2, timeHorizon) - return currentInstant,collisionPoints, crossingZones + + return currentInstant, collisionPoints, crossingZones def computeCrossingsCollisions(predictionParams, obj1, obj2, collisionDistanceThreshold, timeHorizon, computeCZ = False, debug = False, timeInterval = None,nProcesses = 1,usePrototypes=True,route1= (-1,-1),route2=(-1,-1),prototypes={},secondStepPrototypes={},nMatching={},objects=[],noiseEntryNums=[],noiseExitNums=[],minSimilarity=0.1,mostMatched=None,useDestination=True,useSpeedPrototype=True,acceptPartialLength=30, step=1): '''Computes all crossing and collision points at each common instant for two road users. ''' @@ -312,7 +313,7 @@ if len(cp) != 0: collisionPoints[i] = cp if len(cz) != 0: - crossingZones[i] = cz + crossingZones[i] = cz else: for i in list(commonTimeInterval)[:-1]: # do not look at the 1 last position/velocities, often with errors i, cp, cz = computeCrossingsCollisionsAtInstant(predictionParams, i, obj1, obj2, collisionDistanceThreshold, timeHorizon, computeCZ, debug,usePrototypes,route1,route2,prototypes,secondStepPrototypes,nMatching,objects,noiseEntryNums,noiseExitNums,minSimilarity,mostMatched,useDestination,useSpeedPrototype) @@ -334,7 +335,7 @@ if len(cz) != 0: crossingZones[i] = cz pool.close() - return collisionPoints, crossingZones + return collisionPoints, crossingZones class PredictionParameters: def __init__(self, name, maxSpeed): @@ -557,19 +558,19 @@ #### # Other Methods #### -class prototypePredictionParameters(PredictionParameters): - def __init__(self, maxSpeed, nPredictedTrajectories,constantSpeed = True): +class PrototypePredictionParameters(PredictionParameters): + def __init__(self, maxSpeed, nPredictedTrajectories, constantSpeed = True): name = 'prototype' PredictionParameters.__init__(self, name, maxSpeed) self.nPredictedTrajectories = nPredictedTrajectories - self.constantSpeed = constantSpeed + self.constantSpeed = constantSpeed def generatePredictedTrajectories(self, obj, instant,prototypeTrajectories): predictedTrajectories = [] initialPosition = obj.getPositionAtInstant(instant) initialVelocity = obj.getVelocityAtInstant(instant) for prototypeTraj in prototypeTrajectories.keys(): - predictedTrajectories.append(PredictedTrajectoryPrototype(initialPosition, initialVelocity, prototypeTraj, constantSpeed = self.constantSpeed, probability = prototypeTrajectories[prototypeTraj])) + predictedTrajectories.append(PredictedTrajectoryPrototype(initialPosition, initialVelocity, prototypeTraj, constantSpeed = self.constantSpeed, probability = prototypeTrajectories[prototypeTraj])) return predictedTrajectories if __name__ == "__main__":
diff -r 1a92d28e2d05 -r dc2d0a0d7fe1 python/run-tests.sh --- a/python/run-tests.sh Wed Dec 10 14:35:30 2014 -0500 +++ b/python/run-tests.sh Wed Dec 10 15:27:08 2014 -0500 @@ -4,4 +4,3 @@ do python $f done -rm nonexistent
diff -r 1a92d28e2d05 -r dc2d0a0d7fe1 python/storage.py --- a/python/storage.py Wed Dec 10 14:35:30 2014 -0500 +++ b/python/storage.py Wed Dec 10 15:27:08 2014 -0500 @@ -64,7 +64,7 @@ connection.commit() connection.close() - + def writeFeaturesToSqlite(objects, outputFilename, trajectoryType, objectNumbers = -1): '''write features trajectories maintain trajectory ID,velocities dataset ''' connection = sqlite3.connect(outputFilename) @@ -72,7 +72,7 @@ cursor.execute("CREATE TABLE IF NOT EXISTS \"positions\"(trajectory_id INTEGER,frame_number INTEGER, x_coordinate REAL, y_coordinate REAL, PRIMARY KEY(trajectory_id, frame_number))") cursor.execute("CREATE TABLE IF NOT EXISTS \"velocities\"(trajectory_id INTEGER,frame_number INTEGER, x_coordinate REAL, y_coordinate REAL, PRIMARY KEY(trajectory_id, frame_number))") - + if trajectoryType == 'feature': if type(objectNumbers) == int and objectNumbers == -1: for trajectory in objects: @@ -85,14 +85,14 @@ connection.commit() connection.close() - + def writePrototypesToSqlite(prototypes,nMatching, outputFilename): """ prototype dataset is a dictionary with keys== routes, values== prototypes Ids """ connection = sqlite3.connect(outputFilename) cursor = connection.cursor() cursor.execute("CREATE TABLE IF NOT EXISTS \"prototypes\"(prototype_id INTEGER,routeIDstart INTEGER,routeIDend INTEGER, nMatching INTEGER, PRIMARY KEY(prototype_id))") - + for route in prototypes.keys(): if prototypes[route]!=[]: for i in prototypes[route]: @@ -100,7 +100,7 @@ connection.commit() connection.close() - + def loadPrototypesFromSqlite(filename): """ This function loads the prototype file in the database @@ -127,7 +127,7 @@ connection.close() return prototypes,nMatching - + def writeLabelsToSqlite(labels, outputFilename): """ labels is a dictionary with keys: routes, values: prototypes Ids """ @@ -135,7 +135,7 @@ cursor = connection.cursor() cursor.execute("CREATE TABLE IF NOT EXISTS \"labels\"(object_id INTEGER,routeIDstart INTEGER,routeIDend INTEGER, prototype_id INTEGER, PRIMARY KEY(object_id))") - + for route in labels.keys(): if labels[route]!=[]: for i in labels[route]: @@ -144,7 +144,7 @@ connection.commit() connection.close() - + def loadLabelsFromSqlite(filename): labels = {} @@ -174,7 +174,7 @@ cursor = connection.cursor() cursor.execute("CREATE TABLE IF NOT EXISTS \"speedprototypes\"(spdprototype_id INTEGER,prototype_id INTEGER,routeID_start INTEGER, routeID_end INTEGER, nMatching INTEGER, PRIMARY KEY(spdprototype_id))") - + for route in prototypes.keys(): if prototypes[route]!={}: for i in prototypes[route]: @@ -184,7 +184,7 @@ connection.commit() connection.close() - + def loadSpeedPrototypeFromSqlite(filename): """ This function loads the prototypes table in the database of name <filename>. @@ -219,7 +219,7 @@ cursor = connection.cursor() cursor.execute("CREATE TABLE IF NOT EXISTS \"routes\"(object_id INTEGER,routeIDstart INTEGER,routeIDend INTEGER, PRIMARY KEY(object_id))") - + for route in Routes.keys(): if Routes[route]!=[]: for i in Routes[route]: @@ -227,7 +227,7 @@ connection.commit() connection.close() - + def loadRoutesFromSqlite(filename): Routes = {} @@ -247,14 +247,14 @@ Routes[route].append(row[0]) connection.close() - return Routes + return Routes def setRoutes(filename, objects): connection = sqlite3.connect(filename) cursor = connection.cursor() for obj in objects: cursor.execute('update objects set startRouteID = {} where object_id = {}'.format(obj.startRouteID, obj.getNum())) - cursor.execute('update objects set endRouteID = {} where object_id = {}'.format(obj.endRouteID, obj.getNum())) + cursor.execute('update objects set endRouteID = {} where object_id = {}'.format(obj.endRouteID, obj.getNum())) connection.commit() connection.close() @@ -330,7 +330,7 @@ corner = 'top_left' elif trajectoryType == 'bbbottom': corner = 'bottom_right' - queryStatement = 'SELECT object_id, frame_number, x_'+corner+', y_'+corner+' FROM '+tableName+' '+trajectoryIdQuery+'ORDER BY object_id, frame_number' + queryStatement = 'SELECT object_id, frame_number, x_'+corner+', y_'+corner+' FROM '+tableName+' '+idQuery+'ORDER BY object_id, frame_number' cursor.execute(queryStatement) logging.debug(queryStatement) else: @@ -419,7 +419,7 @@ connection.close() return objects -def loadGroundTruthFromSqlite(filename, gtType, gtNumbers = None): +def loadGroundTruthFromSqlite(filename, gtType = 'bb', gtNumbers = None): 'Loads bounding box annotations (ground truth) from an SQLite ' connection = sqlite3.connect(filename) gt = []
diff -r 1a92d28e2d05 -r dc2d0a0d7fe1 python/tests/moving.txt --- a/python/tests/moving.txt Wed Dec 10 14:35:30 2014 -0500 +++ b/python/tests/moving.txt Wed Dec 10 15:27:08 2014 -0500 @@ -160,3 +160,36 @@ >>> o1.classifyUserTypeSpeedMotorized(1.5, np.median) >>> userTypeNames[o1.getUserType()] 'pedestrian' + +>>> o1 = MovingObject.generate(Point(0.,0.), Point(1.,0.), TimeInterval(0,10)) +>>> gt1 = BBAnnotation(1, TimeInterval(0,10), MovingObject.generate(Point(0.2,0.6), Point(1.,0.), TimeInterval(0,10)), MovingObject.generate(Point(-0.2,-0.4), Point(1.,0.), TimeInterval(0,10))) +>>> gt1.computeCentroidTrajectory() +>>> computeClearMOT([gt1], [], 0.2, 0, 10) +(None, 0.0, 11, 0, 0, 11) +>>> computeClearMOT([], [o1], 0.2, 0, 10) +(None, None, 0, 0, 11, 0) +>>> computeClearMOT([gt1], [o1], 0.2, 0, 10) # doctest:+ELLIPSIS +(0.0999..., 1.0, 0, 0, 0, 11) +>>> computeClearMOT([gt1], [o1], 0.05, 0, 10) +(None, -1.0, 11, 0, 11, 11) + +>>> o1 = MovingObject(1, TimeInterval(0,3), positions = Trajectory([range(4), [0.1, 0.1, 1.1, 1.1]])) +>>> o2 = MovingObject(2, TimeInterval(0,3), positions = Trajectory([range(4), [0.9, 0.9, -0.1, -0.1]])) +>>> gt1 = BBAnnotation(1, TimeInterval(0,3), MovingObject(positions = Trajectory([range(4), [0.]*4])), MovingObject(positions = Trajectory([range(4), [0.]*4]))) +>>> gt1.computeCentroidTrajectory() +>>> gt2 = BBAnnotation(2, TimeInterval(0,3), MovingObject(positions = Trajectory([range(4), [1.]*4])), MovingObject(positions = Trajectory([range(4), [1.]*4]))) +>>> gt2.computeCentroidTrajectory() +>>> computeClearMOT([gt1, gt2], [o1, o2], 0.2, 0, 3) # doctest:+ELLIPSIS +(0.1..., 0.75, 0, 2, 0, 8) +>>> computeClearMOT([gt2, gt1], [o2, o1], 0.2, 0, 3) # doctest:+ELLIPSIS +(0.1..., 0.75, 0, 2, 0, 8) +>>> computeClearMOT([gt1], [o1, o2], 0.2, 0, 3) +(0.1, -0.25, 0, 1, 4, 4) +>>> computeClearMOT([gt1], [o2, o1], 0.2, 0, 3) # symmetry +(0.1, -0.25, 0, 1, 4, 4) +>>> computeClearMOT([gt1, gt2], [o1], 0.2, 0, 3) # doctest:+ELLIPSIS +(0.100..., 0.375, 4, 1, 0, 8) +>>> computeClearMOT([gt2, gt1], [o1], 0.2, 0, 3) # doctest:+ELLIPSIS +(0.100..., 0.375, 4, 1, 0, 8) +>>> computeClearMOT([gt1, gt2], [o1, o2], 0.08, 0, 3) +(None, -1.0, 8, 0, 8, 8)
diff -r 1a92d28e2d05 -r dc2d0a0d7fe1 scripts/compute-clearmot.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/compute-clearmot.py Wed Dec 10 15:27:08 2014 -0500 @@ -0,0 +1,39 @@ +#! /usr/bin/env python + +import sys, argparse +from numpy import loadtxt +import moving, storage + +# TODO: need to trim objects to same mask ? + +parser = argparse.ArgumentParser(description='The program computes the CLEAR MOT metrics between ground truth and tracker output (in Polytrack format)', epilog='''CLEAR MOT metrics information: +Keni, Bernardin, and Stiefelhagen Rainer. "Evaluating multiple object tracking performance: the CLEAR MOT metrics." EURASIP Journal on Image and Video Processing 2008 (2008) + +Polytrack format: +JP. Jodoin\'s MSc thesis (in french) +see examples on http://www.jpjodoin.com/urbantracker/dataset.html''', formatter_class=argparse.RawDescriptionHelpFormatter) +parser.add_argument('-d', dest = 'trackerDatabaseFilename', help = 'name of the Sqlite database containing the tracker output', required = True) +parser.add_argument('-g', dest = 'groundTruthDatabaseFilename', help = 'name of the Sqlite database containing the ground truth', required = True) +parser.add_argument('-o', dest = 'homographyFilename', help = 'name of the filename for the homography (if tracking was done using the homography)') +parser.add_argument('-m', dest = 'matchingDistance', help = 'matching distance between tracker and ground truth trajectories', required = True, type = float) +parser.add_argument('-f', dest = 'firstInstant', help = 'first instant for measurement', required = True, type = int) +parser.add_argument('-l', dest = 'lastInstant', help = 'last instant for measurement', required = True, type = int) +args = parser.parse_args() + +if args.homographyFilename != None: + homography = loadtxt(args.homographyFilename) +else: + homography = None + +objects = storage.loadTrajectoriesFromSqlite(args.trackerDatabaseFilename, 'object') +annotations = storage.loadGroundTruthFromSqlite(args.groundTruthDatabaseFilename) +for a in annotations: + a.computeCentroidTrajectory(homography) + +motp, mota, mt, mme, fpt, gt = moving.computeClearMOT(annotations, objects, args.matchingDistance, args.firstInstant, args.lastInstant) + +print 'MOTP: {}'.format(motp) +print 'MOTA: {}'.format(mota) +print 'Number of missed objects.frames: {}'.format(mt) +print 'Number of mismatches: {}'.format(mme) +print 'Number of false alarms.frames: {}'.format(fpt)
diff -r 1a92d28e2d05 -r dc2d0a0d7fe1 scripts/compute-homography.py --- a/scripts/compute-homography.py Wed Dec 10 14:35:30 2014 -0500 +++ b/scripts/compute-homography.py Wed Dec 10 15:27:08 2014 -0500 @@ -17,7 +17,7 @@ If providing video and world images, with a number of points to input and a ration to convert pixels to world distance unit (eg meters per pixel), the images will be shown in turn and the user should click -in the same order the corresponding points in world and image spaces.''', formatter_class=argparse.RawDescriptionHelpFormatter,) +in the same order the corresponding points in world and image spaces.''', formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument('-p', dest = 'pointCorrespondencesFilename', help = 'name of the text file containing the point correspondences') parser.add_argument('-i', dest = 'videoFrameFilename', help = 'filename of the video frame')
diff -r 1a92d28e2d05 -r dc2d0a0d7fe1 tracking.cfg --- a/tracking.cfg Wed Dec 10 14:35:30 2014 -0500 +++ b/tracking.cfg Wed Dec 10 15:27:08 2014 -0500 @@ -62,9 +62,9 @@ # number of frames to compute velocities #nframes-velocity = 5 # maximum number of iterations to stop feature tracking -max-number-iterations = 30 +max-number-iterations = 20 # minimum error to reach to stop feature tracking -min-tracking-error = 0.01 +min-tracking-error = 0.3 # minimum eigen value of a 2x2 normal matrix of optical flow equations min-feature-eig-threshold = 1e-4 # minimum length of a feature (number of frames) to consider a feature for grouping