comparison python/objectsmoothing.py @ 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 6ee8765bb8db
children 9fe254f11743
comparison
equal deleted inserted replaced
596:04a8304e13f0 619:dc2d0a0d7fe1
3 import numpy as np 3 import numpy as np
4 4
5 import matplotlib.pyplot as plt 5 import matplotlib.pyplot as plt
6 6
7 def findNearest(feat, featureSet,t,reverse=True): 7 def findNearest(feat, featureSet,t,reverse=True):
8 dist={} 8 dist={}
9 for f in featureSet: 9 for f in featureSet:
10 if reverse: 10 if reverse:
11 dist[f]= moving.Point.distanceNorm2(feat.getPositionAtInstant(t+1),f.getPositionAtInstant(t)) 11 dist[f]= moving.Point.distanceNorm2(feat.getPositionAtInstant(t+1),f.getPositionAtInstant(t))
12 else: 12 else:
13 dist[f]= moving.Point.distanceNorm2(feat.getPositionAtInstant(t-1),f.getPositionAtInstant(t)) 13 dist[f]= moving.Point.distanceNorm2(feat.getPositionAtInstant(t-1),f.getPositionAtInstant(t))
14 return min(dist, key=dist.get) # = utils.argmaxDict(dist) 14 return min(dist, key=dist.get) # = utils.argmaxDict(dist)
15 15
16 def getFeatures(obj): 16 def getFeatures(obj,features,featureID):
17 longestFeature = utils.argmaxDict({f:f.length() for i,f in enumerate(obj.features)}) 17 #longestFeature = utils.argmaxDict({f:f.length() for i,f in enumerate(obj.features)})
18 t1,t3 = longestFeature.getFirstInstant(), longestFeature.getLastInstant() 18 t1,t3 = features[featureID].getFirstInstant(), features[featureID].getLastInstant()
19 listFeatures=[[longestFeature,t1,t3,moving.Point(0,0)]] 19 listFeatures=[[features[featureID],t1,t3,moving.Point(0,0)]]
20 # find the features to fill in the beginning of the object existence 20 # find the features to fill in the beginning of the object existence
21 currentFeature = longestFeature 21 currentFeature = features[featureID]
22 while t1!=obj.getFirstInstant(): 22 while t1!=obj.getFirstInstant():
23 delta=listFeatures[-1][3] 23 delta=listFeatures[-1][3]
24 featureSet = [f for f in obj.features if f.existsAtInstant(t1-1)] 24 featureSet = [f for f in obj.features if f.existsAtInstant(t1-1)]
25 feat = findNearest(currentFeature,featureSet,t1-1,reverse=True) 25 feat = findNearest(currentFeature,featureSet,t1-1,reverse=True)
26 if feat.existsAtInstant(t1): 26 if feat.existsAtInstant(t1):
27 listFeatures.append([feat,feat.getFirstInstant(),t1-1,(currentFeature.getPositionAtInstant(t1)-feat.getPositionAtInstant(t1))+delta]) 27 listFeatures.append([feat,feat.getFirstInstant(),t1-1,(currentFeature.getPositionAtInstant(t1)-feat.getPositionAtInstant(t1))+delta])
28 else: 28 else:
29 listFeatures.append([feat,feat.getFirstInstant(),t1-1,(currentFeature.getPositionAtInstant(t1)-feat.getPositionAtInstant(t1-1))+delta]) 29 listFeatures.append([feat,feat.getFirstInstant(),t1-1,(currentFeature.getPositionAtInstant(t1)-feat.getPositionAtInstant(t1-1))+delta])
30 currentFeature = feat 30 currentFeature = feat
31 t1= feat.getFirstInstant() 31 t1= feat.getFirstInstant()
32 # find the features to fill in the end of the object existence 32 # find the features to fill in the end of the object existence
33 delta=moving.Point(0,0) 33 delta=moving.Point(0,0)
34 currentFeature = longestFeature 34 currentFeature = features[featureID]
35 while t3!= obj.getLastInstant(): 35 while t3!= obj.getLastInstant():
36 featureSet = [f for f in obj.features if f.existsAtInstant(t3+1)] 36 featureSet = [f for f in obj.features if f.existsAtInstant(t3+1)]
37 feat = findNearest(currentFeature,featureSet,t3+1,reverse=False) 37 feat = findNearest(currentFeature,featureSet,t3+1,reverse=False)
38 if feat.existsAtInstant(t3): 38 if feat.existsAtInstant(t3):
39 listFeatures.append([feat,t3+1,feat.getLastInstant(),(currentFeature.getPositionAtInstant(t3)-feat.getPositionAtInstant(t3))+delta]) 39 listFeatures.append([feat,t3+1,feat.getLastInstant(),(currentFeature.getPositionAtInstant(t3)-feat.getPositionAtInstant(t3))+delta])
40 else: 40 else:
41 listFeatures.append([feat,t3+1,feat.getLastInstant(),(currentFeature.getPositionAtInstant(t3)-feat.getPositionAtInstant(t3+1))+delta]) 41 listFeatures.append([feat,t3+1,feat.getLastInstant(),(currentFeature.getPositionAtInstant(t3)-feat.getPositionAtInstant(t3+1))+delta])
42 currentFeature = feat 42 currentFeature = feat
43 t3= feat.getLastInstant() 43 t3= feat.getLastInstant()
44 delta=listFeatures[-1][3] 44 delta=listFeatures[-1][3]
45 return listFeatures 45 return listFeatures
46 46
47 def buildFeature(obj,num=1): 47 def buildFeature(obj,features,featureID,num=1):
48 listFeatures= getFeatures(obj) 48 listFeatures= getFeatures(obj,features,featureID)
49 tmp={} 49 tmp={}
50 delta={} 50 delta={}
51 for i in listFeatures: 51 for i in listFeatures:
52 for t in xrange(i[1],i[2]+1): 52 for t in xrange(i[1],i[2]+1):
53 tmp[t]=[i[0],i[3]] 53 tmp[t]=[i[0],i[3]]
54 newTraj = moving.Trajectory() 54 newTraj = moving.Trajectory()
55 55
56 for instant in obj.getTimeInterval(): 56 for instant in obj.getTimeInterval():
57 newTraj.addPosition(tmp[instant][0].getPositionAtInstant(instant)+tmp[instant][1]) 57 newTraj.addPosition(tmp[instant][0].getPositionAtInstant(instant)+tmp[instant][1])
58 newFeature= moving.MovingObject(num,timeInterval=obj.getTimeInterval(),positions=newTraj) 58 newFeature= moving.MovingObject(num,timeInterval=obj.getTimeInterval(),positions=newTraj)
59 return newFeature 59 return newFeature
60 60
61 def getBearing(p1,p2,p3): 61 def getBearing(p1,p2,p3):
62 angle = degrees(atan2(p3.y -p1.y, p3.x -p1.x)) 62 angle = degrees(atan2(p3.y -p1.y, p3.x -p1.x))
63 bearing1 = (90 - angle) % 360 63 bearing1 = (90 - angle) % 360
64 angle2 = degrees(atan2(p2.y -p1.y, p2.x -p1.x)) 64 angle2 = degrees(atan2(p2.y -p1.y, p2.x -p1.x))
65 bearing2 = (90 - angle2) % 360 65 bearing2 = (90 - angle2) % 360
66 dist= moving.Point.distanceNorm2(p1, p2) 66 dist= moving.Point.distanceNorm2(p1, p2)
67 return [dist,bearing1,bearing2,bearing2-bearing1] 67 return [dist,bearing1,bearing2,bearing2-bearing1]
68 68
69 def smoothObjectTrajectory(obj,newNum,smoothing=False,plotResults=True,halfWidth=3): 69 #Quantitative analysis "CSJ" functions
70 results=[] 70 def computeVelocities (object,smoothing=True,halfWidth=3): #compute velocities from positions
71 bearing={} 71 velocities={}
72 feature= buildFeature(obj,1) 72 for i in list(object.timeInterval)[:-1]:
73 for t in feature.getTimeInterval(): 73 p1= object.getPositionAtInstant(i)
74 p1= feature.getPositionAtInstant(t) 74 p2= object.getPositionAtInstant(i+1)
75 p2= obj.getPositionAtInstant(t) 75 velocities[i]=p2-p1
76 if t!=feature.getLastInstant(): 76 velocities[object.getLastInstant()]= velocities[object.getLastInstant()-1] # duplicate last point
77 p3= feature.getPositionAtInstant(t+1) 77 if smoothing:
78 else: 78 velX= [velocities[y].aslist()[0] for y in sorted(velocities.keys())]
79 p1= feature.getPositionAtInstant(t-1) 79 velY= [velocities[y].aslist()[1] for y in sorted(velocities.keys())]
80 p3= feature.getPositionAtInstant(t) 80 v1= list(utils.filterMovingWindow(velX, halfWidth))
81 bearing[t]= getBearing(p1,p2,p3)[1] 81 v2= list(utils.filterMovingWindow(velY, halfWidth))
82 results.append(getBearing(p1,p2,p3)) 82 smoothedVelocity={}
83 83 for t,i in enumerate(sorted(velocities.keys())):
84 medianResults=np.median(results,0) 84 smoothedVelocity[i]=moving.Point(v1[t], v2[t])
85 dist= medianResults[0] 85 velocities=smoothedVelocity
86 angle= medianResults[3] 86 return velocities
87 87
88 for i in sorted(bearing.keys()): 88 def computeAcceleration (object,fromPosition=True):
89 bearing[i]= bearing[i]+angle 89 acceleration={}
90 90 if fromPosition:
91 if smoothing: 91 velocities=computeVelocities(object,False,1)
92 bearingInput=[] 92 for i in sorted (velocities.keys()):
93 for i in sorted(bearing.keys()): 93 if i != sorted (velocities.keys())[-1]:
94 bearingInput.append(bearing[i]) 94 acceleration[i]= velocities[i+1]-velocities[i]
95 bearingOut=utils.filterMovingWindow(bearingInput, halfWidth) 95 else:
96 for t,i in enumerate(sorted(bearing.keys())): 96 for i in list(object.timeInterval)[:-1]:
97 bearing[i]=bearingOut[t] 97 v1= object.getVelocityAtInstant(i)
98 98 v2= object.getVelocityAtInstant(i+1)
99 #solve a smoothing problem in case of big drop in computing bearing (0,360) 99 acceleration[i]= v2-v1
100 for t,i in enumerate(sorted(bearing.keys())): 100 return acceleration
101 if i!= max(bearing.keys()) and abs(bearingInput[t] - bearingInput[t+1])>=340: 101
102 for x in xrange(max(i-halfWidth,min(bearing.keys())),min(i+halfWidth,max(bearing.keys()))+1): 102 def computeJerk (object,fromPosition=True):
103 bearing[x]=bearingInput[t-i+x] 103 jerk={}
104 104 acceleration=computeAcceleration (object,fromPosition=fromPosition)
105 translated = moving.Trajectory() 105 for i in sorted (acceleration.keys()):
106 for t in feature.getTimeInterval(): 106 if i != sorted (acceleration.keys())[-1]:
107 p1= feature.getPositionAtInstant(t) 107 jerk[i]= (acceleration[i+1]-acceleration[i]).norm2()
108 p1.x = p1.x + dist*sin(bearing[t]*pi/180) 108 return jerk
109 p1.y = p1.y + dist*cos(bearing[t]*pi/180) 109
110 translated.addPosition(p1) 110 def sumSquaredJerk (object,fromPosition=True):
111 111 jerk= computeJerk (object,fromPosition=fromPosition)
112 #modify first and last un-smoothed positions (half width) 112 t=0
113 if smoothing: 113 for i in sorted(jerk.keys()):
114 d1= translated[halfWidth]- feature.positions[halfWidth] 114 t+= jerk[i]* jerk[i]
115 d2= translated[-halfWidth-1]- feature.positions[-halfWidth-1] 115 return t
116 for i in xrange(halfWidth): 116
117 p1 = feature.getPositionAt(i)+d1 117 def smoothObjectTrajectory(obj,features,featureID,newNum,smoothing=False,halfWidth=3,create=False):
118 p2 = feature.getPositionAt(-i-1)+d2 118 results=[]
119 translated.setPosition(i,p1) 119 bearing={}
120 translated.setPosition(-i-1,p2) 120 if create:
121 121 feature= buildFeature(obj,features,featureID,num=1)
122 newObj= moving.MovingObject(newNum,timeInterval=feature.getTimeInterval(),positions=translated,velocities=obj.getVelocities()) 122 else:
123 newObj.features=obj.features 123 feature=features[featureID]
124 newObj.userType=obj.userType 124 for t in feature.getTimeInterval():
125 if plotResults: 125 p1= feature.getPositionAtInstant(t)
126 plt.figure() 126 p2= obj.getPositionAtInstant(t)
127 plt.title('objects_id = {}'.format(obj.num)) 127 if t!=feature.getLastInstant():
128 newObj.plot('gx-') 128 p3= feature.getPositionAtInstant(t+1)
129 feature.plot('cx-') 129 else:
130 obj.plot('rx-') 130 p1= feature.getPositionAtInstant(t-1)
131 return newObj 131 p3= feature.getPositionAtInstant(t)
132 bearing[t]= getBearing(p1,p2,p3)[1]
133 results.append(getBearing(p1,p2,p3))
134
135
136 medianResults=np.median(results,0)
137 dist= medianResults[0]
138 angle= medianResults[3]
139
140 for i in sorted(bearing.keys()):
141 bearing[i]= bearing[i]+angle
142
143 if smoothing:
144 bearingInput=[]
145 for i in sorted(bearing.keys()):
146 bearingInput.append(bearing[i])
147 import utils
148 bearingOut=utils.filterMovingWindow(bearingInput, halfWidth)
149 for t,i in enumerate(sorted(bearing.keys())):
150 bearing[i]=bearingOut[t]
151
152 #solve a smoothing problem in case of big drop in computing bearing (0,360)
153 for t,i in enumerate(sorted(bearing.keys())):
154 if i!= max(bearing.keys()) and abs(bearingInput[t] - bearingInput[t+1])>=340:
155 for x in xrange(max(i-halfWidth,min(bearing.keys())),min(i+halfWidth,max(bearing.keys()))+1):
156 bearing[x]=bearingInput[t-i+x]
157
158 translated = moving.Trajectory()
159 for t in feature.getTimeInterval():
160 p1= feature.getPositionAtInstant(t)
161 p1.x = p1.x + dist*sin(bearing[t]*pi/180)
162 p1.y = p1.y + dist*cos(bearing[t]*pi/180)
163 translated.addPosition(p1)
164
165 #modify first and last un-smoothed positions (half width)
166 if smoothing:
167 d1= translated[halfWidth]- feature.positions[halfWidth]
168 d2= translated[-halfWidth-1]- feature.positions[-halfWidth-1]
169 for i in xrange(halfWidth):
170 p1= feature.getPositionAt(i)+d1
171 p2= feature.getPositionAt(-i-1)+d2
172 translated.setPosition(i,p1)
173 translated.setPosition(-i-1,p2)
174
175 newObj= moving.MovingObject(newNum,timeInterval=feature.getTimeInterval(),positions=translated)
176 return newObj
177
178 def smoothObjectTrajectory(obj,features,newNum,minLengthParam=0.7,smoothing=False,plotResults=True,halfWidth=3,computeVelocities=True,optimize=True,create=False):
179 featureList=[i.num for i in obj.features if i.length() >= minLengthParam*obj.length()]
180 if featureList==[]:
181 featureList.append(longestFeature(obj))
182 create=True
183 objs=[]
184 for featureID in featureList:
185 objTMP=smoothObjectTrajectory(obj,features,featureID,newNum,smoothing=smoothing,halfWidth=halfWidth,create=create)
186 objs.append(objTMP)
187 newTranslated = moving.Trajectory()
188 newInterval=[]
189 for t in obj.timeInterval:
190 xCoord=[]
191 yCoord=[]
192 for i in objs:
193 if i.existsAtInstant(t):
194 p1= i.getPositionAtInstant(t)
195 xCoord.append(p1.x)
196 yCoord.append(p1.y)
197 if xCoord!=[]:
198 tmp= moving.Point(np.median(xCoord),np.median(yCoord))
199 newInterval.append(t)
200 newTranslated.addPosition(tmp)
201
202 newObj= moving.MovingObject(newNum,timeInterval=moving.TimeInterval(min(newInterval),max(newInterval)),positions=newTranslated)
203
204 if computeVelocities:
205 tmpTraj = moving.Trajectory()
206 velocities= computeVelocities(newObj,True,5)
207 for i in sorted(velocities.keys()):
208 tmpTraj.addPosition(velocities[i])
209 newObj.velocities=tmpTraj
210 else:
211 newObj.velocities=obj.velocities
212
213 if optimize:
214 csj1= sumSquaredJerk (obj,fromPosition=True)
215 csj2= sumSquaredJerk (newObj,fromPosition=True)
216 if csj1<csj2:
217 newObj=obj
218 newObj.velocities=obj.velocities
219 if computeVelocities and csj1>=csj2:
220 csj3= sumSquaredJerk (obj,fromPosition=False)
221 csj4= sumSquaredJerk (newObj,fromPosition=False)
222 if csj4<=csj3:
223 newObj.velocities= obj.velocities
224 newObj.featureNumbers=obj.featureNumbers
225 newObj.features=obj.features
226 newObj.userType=obj.userType
227 if plotResults:
228 plt.figure()
229 plt.title('objects_id = {}'.format(obj.num))
230 for i in featureList:
231 features[i].plot('cx-')
232 obj.plot('rx-')
233 newObj.plot('gx-')
234 return newObj