Data and viz options
This commit is contained in:
parent
627b320ec7
commit
cc952424e0
7 changed files with 103 additions and 44 deletions
File diff suppressed because one or more lines are too long
|
@ -95,7 +95,7 @@ class AnimationRenderer:
|
||||||
corners=[[471, 304], [1797, 376], [467, 387], [1792, 484]])
|
corners=[[471, 304], [1797, 376], [467, 387], [1792, 484]])
|
||||||
self.window.push_handlers(self.pins)
|
self.window.push_handlers(self.pins)
|
||||||
|
|
||||||
pyglet.gl.glClearColor(0,0,0, 0)
|
pyglet.gl.glClearColor(255,255,255,255)
|
||||||
self.fps_display = pyglet.window.FPSDisplay(window=self.window, color=(255,255,255,255))
|
self.fps_display = pyglet.window.FPSDisplay(window=self.window, color=(255,255,255,255))
|
||||||
self.fps_display.label.x = self.window.width - 50
|
self.fps_display.label.x = self.window.width - 50
|
||||||
self.fps_display.label.y = self.window.height - 17
|
self.fps_display.label.y = self.window.height - 17
|
||||||
|
@ -115,14 +115,15 @@ class AnimationRenderer:
|
||||||
self.batch_overlay = pyglet.graphics.Batch()
|
self.batch_overlay = pyglet.graphics.Batch()
|
||||||
self.batch_anim = pyglet.graphics.Batch()
|
self.batch_anim = pyglet.graphics.Batch()
|
||||||
|
|
||||||
self.debug_lines = [
|
if self.config.render_debug_shapes:
|
||||||
pyglet.shapes.Line(1370, self.config.camera.h-360, 1380, 670-360, 2, (255,255,255,255), batch=self.batch_overlay),#v
|
self.debug_lines = [
|
||||||
pyglet.shapes.Line(0, 660-360, 1380, 670-360, 2, (255,255,255,255), batch=self.batch_overlay), #h
|
pyglet.shapes.Line(1370, self.config.camera.h-360, 1380, 670-360, 2, (255,255,255,255), batch=self.batch_overlay),#v
|
||||||
pyglet.shapes.Line(1140, 760-360, 1140, 675-360, 2, (255,255,255,255), batch=self.batch_overlay), #h
|
pyglet.shapes.Line(0, 660-360, 1380, 670-360, 2, (255,255,255,255), batch=self.batch_overlay), #h
|
||||||
pyglet.shapes.Line(540, 760-360,540, 675-360, 2, (255,255,255,255), batch=self.batch_overlay), #v
|
pyglet.shapes.Line(1140, 760-360, 1140, 675-360, 2, (255,255,255,255), batch=self.batch_overlay), #h
|
||||||
pyglet.shapes.Line(0, 770-360, 1380, 770-360, 2, (255,255,255,255), batch=self.batch_overlay), #h
|
pyglet.shapes.Line(540, 760-360,540, 675-360, 2, (255,255,255,255), batch=self.batch_overlay), #v
|
||||||
|
pyglet.shapes.Line(0, 770-360, 1380, 770-360, 2, (255,255,255,255), batch=self.batch_overlay), #h
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
self.debug_points = []
|
self.debug_points = []
|
||||||
# print(self.config.debug_points_file)
|
# print(self.config.debug_points_file)
|
||||||
|
@ -277,7 +278,7 @@ class AnimationRenderer:
|
||||||
self.video_sprite = pyglet.sprite.Sprite(img=img, batch=self.batch_bg)
|
self.video_sprite = pyglet.sprite.Sprite(img=img, batch=self.batch_bg)
|
||||||
# transform to flipped coordinate system for pyglet
|
# transform to flipped coordinate system for pyglet
|
||||||
self.video_sprite.y = self.window.height - self.video_sprite.height
|
self.video_sprite.y = self.window.height - self.video_sprite.height
|
||||||
self.video_sprite.opacity = 90
|
self.video_sprite.opacity = 10
|
||||||
except zmq.ZMQError as e:
|
except zmq.ZMQError as e:
|
||||||
# idx = frame.index if frame else "NONE"
|
# idx = frame.index if frame else "NONE"
|
||||||
# logger.debug(f"reuse video frame {idx}")
|
# logger.debug(f"reuse video frame {idx}")
|
||||||
|
@ -306,12 +307,19 @@ class AnimationRenderer:
|
||||||
# # TODO fade out
|
# # TODO fade out
|
||||||
# del self.drawn_tracks[track_id]
|
# del self.drawn_tracks[track_id]
|
||||||
|
|
||||||
|
if self.tracker_frame:
|
||||||
|
for track_id, track in self.tracker_frame.tracks.items():
|
||||||
|
if track_id not in self.drawn_tracks:
|
||||||
|
self.drawn_tracks[track_id] = DrawnTrack(track_id, track, self, self.tracker_frame.H, PROJECTION_MAP, self.config.camera)
|
||||||
|
else:
|
||||||
|
self.drawn_tracks[track_id].set_track(track)
|
||||||
|
|
||||||
if self.prediction_frame:
|
if self.prediction_frame:
|
||||||
for track_id, track in self.prediction_frame.tracks.items():
|
for track_id, track in self.prediction_frame.tracks.items():
|
||||||
if track_id not in self.drawn_tracks:
|
if track_id not in self.drawn_tracks:
|
||||||
self.drawn_tracks[track_id] = DrawnTrack(track_id, track, self, self.prediction_frame.H, PROJECTION_MAP, self.config.camera)
|
self.drawn_tracks[track_id] = DrawnTrack(track_id, track, self, self.prediction_frame.H, PROJECTION_MAP, self.config.camera)
|
||||||
else:
|
else:
|
||||||
self.drawn_tracks[track_id].set_track(track)
|
self.drawn_tracks[track_id].set_predictions(track)
|
||||||
|
|
||||||
# clean up
|
# clean up
|
||||||
for track_id in list(self.drawn_tracks.keys()):
|
for track_id in list(self.drawn_tracks.keys()):
|
||||||
|
@ -364,7 +372,9 @@ class AnimationRenderer:
|
||||||
shape.draw()
|
shape.draw()
|
||||||
# self.batch_anim.draw()
|
# self.batch_anim.draw()
|
||||||
self.batch_overlay.draw()
|
self.batch_overlay.draw()
|
||||||
self.pins.draw()
|
|
||||||
|
if self.config.render_debug_shapes:
|
||||||
|
self.pins.draw()
|
||||||
|
|
||||||
# pyglet.graphics.draw(3, pyglet.gl.GL_LINE, ("v2i", (100,200, 600,800)), ('c3B', (255,255,255, 255,255,255)))
|
# pyglet.graphics.draw(3, pyglet.gl.GL_LINE, ("v2i", (100,200, 600,800)), ('c3B', (255,255,255, 255,255,255)))
|
||||||
|
|
||||||
|
|
|
@ -319,6 +319,9 @@ render_parser.add_argument("--render-window",
|
||||||
render_parser.add_argument("--render-no-preview",
|
render_parser.add_argument("--render-no-preview",
|
||||||
help="No preview, but only animation",
|
help="No preview, but only animation",
|
||||||
action='store_true')
|
action='store_true')
|
||||||
|
render_parser.add_argument("--render-debug-shapes",
|
||||||
|
help="Lines and points for debugging/mapping",
|
||||||
|
action='store_true')
|
||||||
render_parser.add_argument("--full-screen",
|
render_parser.add_argument("--full-screen",
|
||||||
help="Set Window full screen",
|
help="Set Window full screen",
|
||||||
action='store_true')
|
action='store_true')
|
||||||
|
|
|
@ -303,16 +303,16 @@ class PredictionServer:
|
||||||
history = history_cm_to_m(history)
|
history = history_cm_to_m(history)
|
||||||
|
|
||||||
history = np.array(history)
|
history = np.array(history)
|
||||||
x = history[:, 0] #- cx
|
x = history[:, 0] #- cx # we can create bigger steps by doing history[::5,0]
|
||||||
y = history[:, 1] #- cy
|
y = history[:, 1] #- cy # history[::5,1]
|
||||||
if self.config.center_data:
|
if self.config.center_data:
|
||||||
x -= cx
|
x -= cx
|
||||||
y -= cy
|
y -= cy
|
||||||
# TODO: calculate dt based on input
|
# TODO: calculate dt based on input
|
||||||
vx = derivative_of(x, 0.1) #eval_scene.dt
|
vx = derivative_of(x, .1) #eval_scene.dt
|
||||||
vy = derivative_of(y, 0.1)
|
vy = derivative_of(y, .1)
|
||||||
ax = derivative_of(vx, 0.1)
|
ax = derivative_of(vx, .1)
|
||||||
ay = derivative_of(vy, 0.1)
|
ay = derivative_of(vy, .1)
|
||||||
|
|
||||||
data_dict = {('position', 'x'): x[:], # [-10:-1]
|
data_dict = {('position', 'x'): x[:], # [-10:-1]
|
||||||
('position', 'y'): y[:], # [-10:-1]
|
('position', 'y'): y[:], # [-10:-1]
|
||||||
|
@ -445,6 +445,7 @@ class PredictionServer:
|
||||||
frame = self.smoother.smooth_frame_predictions(frame)
|
frame = self.smoother.smooth_frame_predictions(frame)
|
||||||
|
|
||||||
self.prediction_socket.send_pyobj(frame)
|
self.prediction_socket.send_pyobj(frame)
|
||||||
|
time.sleep(.5)
|
||||||
logger.info('Stopping')
|
logger.info('Stopping')
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,7 @@ class DrawnTrack:
|
||||||
self.camera = camera
|
self.camera = camera
|
||||||
self.H = H # TODO)) Move H to Camera object
|
self.H = H # TODO)) Move H to Camera object
|
||||||
self.set_track(track, H)
|
self.set_track(track, H)
|
||||||
|
self.set_predictions(track, H)
|
||||||
self.drawn_positions = []
|
self.drawn_positions = []
|
||||||
self.drawn_predictions = []
|
self.drawn_predictions = []
|
||||||
self.shapes: list[pyglet.shapes.Line] = []
|
self.shapes: list[pyglet.shapes.Line] = []
|
||||||
|
@ -87,6 +88,8 @@ class DrawnTrack:
|
||||||
# perhaps only do in constructor:
|
# perhaps only do in constructor:
|
||||||
self.inv_H = np.linalg.pinv(self.H)
|
self.inv_H = np.linalg.pinv(self.H)
|
||||||
|
|
||||||
|
def set_predictions(self, track: Track, H = None):
|
||||||
|
|
||||||
pred_coords = []
|
pred_coords = []
|
||||||
if track.predictions:
|
if track.predictions:
|
||||||
if self.draw_projection == PROJECTION_IMG:
|
if self.draw_projection == PROJECTION_IMG:
|
||||||
|
@ -116,7 +119,7 @@ class DrawnTrack:
|
||||||
for i, pos in enumerate(drawn_prediction):
|
for i, pos in enumerate(drawn_prediction):
|
||||||
# TODO: this should be done in polar space starting from origin (i.e. self.drawn_posision[-1])
|
# TODO: this should be done in polar space starting from origin (i.e. self.drawn_posision[-1])
|
||||||
decay = max(3, (18/i) if i else 10) # points further away move with more delay
|
decay = max(3, (18/i) if i else 10) # points further away move with more delay
|
||||||
decay = 6
|
decay = 16
|
||||||
origin = self.drawn_positions[-1]
|
origin = self.drawn_positions[-1]
|
||||||
drawn_r, drawn_angle = relativePointToPolar( origin, drawn_prediction[i])
|
drawn_r, drawn_angle = relativePointToPolar( origin, drawn_prediction[i])
|
||||||
pred_r, pred_angle = relativePointToPolar(origin, self.pred_coords[a][i])
|
pred_r, pred_angle = relativePointToPolar(origin, self.pred_coords[a][i])
|
||||||
|
@ -179,7 +182,8 @@ class DrawnTrack:
|
||||||
# for i, pos in drawn_predictions.enumerate():
|
# for i, pos in drawn_predictions.enumerate():
|
||||||
for ci in range(0, len(drawn_predictions)):
|
for ci in range(0, len(drawn_predictions)):
|
||||||
if ci == 0:
|
if ci == 0:
|
||||||
x, y = [int(p) for p in self.drawn_positions[-1]]
|
continue
|
||||||
|
# x, y = [int(p) for p in self.drawn_positions[-1]]
|
||||||
else:
|
else:
|
||||||
x, y = [int(p) for p in drawn_predictions[ci-1]]
|
x, y = [int(p) for p in drawn_predictions[ci-1]]
|
||||||
|
|
||||||
|
@ -191,7 +195,9 @@ class DrawnTrack:
|
||||||
|
|
||||||
if ci >= len(self.pred_shapes[a]):
|
if ci >= len(self.pred_shapes[a]):
|
||||||
# TODO: add color2
|
# TODO: add color2
|
||||||
line = self.renderer.gradientLine(x, y, x2, y2, 3, color, color, batch=self.renderer.batch_anim)
|
# line = self.renderer.gradientLine(x, y, x2, y2, 3, color, color, batch=self.renderer.batch_anim)
|
||||||
|
line = pyglet.shapes.Line(x,y ,x2, y2, 1.5, color, batch=self.renderer.batch_anim)
|
||||||
|
# line = pyglet.shapes.Arc(x,y ,1.5, thickness=1.5, color=color, batch=self.renderer.batch_anim)
|
||||||
line.opacity = 5
|
line.opacity = 5
|
||||||
self.pred_shapes[a].append(line)
|
self.pred_shapes[a].append(line)
|
||||||
|
|
||||||
|
@ -203,9 +209,9 @@ class DrawnTrack:
|
||||||
decay = (16/ci) if ci else 16
|
decay = (16/ci) if ci else 16
|
||||||
half = len(drawn_predictions) / 2
|
half = len(drawn_predictions) / 2
|
||||||
if ci < half:
|
if ci < half:
|
||||||
target_opacity = 180
|
target_opacity = 60
|
||||||
else:
|
else:
|
||||||
target_opacity = (1 - ((ci - half) / half)) * 180
|
target_opacity = (1 - ((ci - half) / half)) * 60
|
||||||
line.opacity = int(exponentialDecay(line.opacity, target_opacity, decay, dt))
|
line.opacity = int(exponentialDecay(line.opacity, target_opacity, decay, dt))
|
||||||
|
|
||||||
|
|
||||||
|
@ -688,10 +694,13 @@ class PreviewRenderer:
|
||||||
# (255, 0, 255),
|
# (255, 0, 255),
|
||||||
# (255, 255, 0)
|
# (255, 255, 0)
|
||||||
# ]
|
# ]
|
||||||
|
# colorset = [
|
||||||
|
# (255,255,100),
|
||||||
|
# (255,100,255),
|
||||||
|
# (100,255,255),
|
||||||
|
# ]
|
||||||
colorset = [
|
colorset = [
|
||||||
(255,255,100),
|
(0,0,0),
|
||||||
(255,100,255),
|
|
||||||
(100,255,255),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
# Deprecated
|
# Deprecated
|
||||||
|
|
|
@ -90,7 +90,7 @@ def augment(scene):
|
||||||
# maybe_makedirs('trajectron-data')
|
# maybe_makedirs('trajectron-data')
|
||||||
# for desired_source in [ 'hof2', ]:# ,'hof-maskrcnn', 'hof-yolov8', 'VIRAT-0102-parsed', 'virat-resnet-keypoints-full']:
|
# for desired_source in [ 'hof2', ]:# ,'hof-maskrcnn', 'hof-yolov8', 'VIRAT-0102-parsed', 'virat-resnet-keypoints-full']:
|
||||||
|
|
||||||
def process_data(src_dir: Path, dst_dir: Path, name: str, smooth_tracks: bool, cm_to_m: bool, center_data: bool):
|
def process_data(src_dir: Path, dst_dir: Path, name: str, smooth_tracks: bool, cm_to_m: bool, center_data: bool, bin_positions: bool):
|
||||||
print(f"Process data in {src_dir}, to {dst_dir}, identified by {name}")
|
print(f"Process data in {src_dir}, to {dst_dir}, identified by {name}")
|
||||||
|
|
||||||
nl = 0
|
nl = 0
|
||||||
|
@ -117,12 +117,18 @@ def process_data(src_dir: Path, dst_dir: Path, name: str, smooth_tracks: bool, c
|
||||||
all_data['pos_x'] /= 100
|
all_data['pos_x'] /= 100
|
||||||
all_data['pos_y'] /= 100
|
all_data['pos_y'] /= 100
|
||||||
|
|
||||||
|
|
||||||
mean_x, mean_y = all_data['pos_x'].mean(), all_data['pos_y'].mean()
|
mean_x, mean_y = all_data['pos_x'].mean(), all_data['pos_y'].mean()
|
||||||
cx = .5 * all_data['pos_x'].min() + .5 * all_data['pos_x'].max()
|
cx = .5 * all_data['pos_x'].min() + .5 * all_data['pos_x'].max()
|
||||||
cy = .5 * all_data['pos_y'].min() + .5 * all_data['pos_y'].max()
|
cy = .5 * all_data['pos_y'].min() + .5 * all_data['pos_y'].max()
|
||||||
print(f"Dataset means: {mean_x=} {mean_y=}")
|
# bins of .5 meter
|
||||||
print(f"Dataset centers: {cx=} {cy=}")
|
# print(np.ceil(all_data['pos_x'].max())*2))
|
||||||
|
if bin_positions:
|
||||||
|
space_x = np.linspace(0, np.ceil(all_data['pos_x'].max()), int(np.ceil(all_data['pos_x'].max())*2)+1)
|
||||||
|
space_y = np.linspace(0, np.ceil(all_data['pos_y'].max()), int(np.ceil(all_data['pos_y'].max())*2)+1)
|
||||||
|
|
||||||
|
print(f"Dataset means: {mean_x=} {mean_y=}, (min: ({all_data['pos_x'].min()}, {all_data['pos_y'].min()}), max: ({all_data['pos_x'].max()}, {all_data['pos_y'].max()}))")
|
||||||
|
print(f"Dataset centers: {cx=} {cy=}")
|
||||||
|
|
||||||
for data_class in ['train', 'val', 'test']:
|
for data_class in ['train', 'val', 'test']:
|
||||||
env = Environment(node_type_list=['PEDESTRIAN'], standardization=standardization)
|
env = Environment(node_type_list=['PEDESTRIAN'], standardization=standardization)
|
||||||
|
@ -174,6 +180,12 @@ def process_data(src_dir: Path, dst_dir: Path, name: str, smooth_tracks: bool, c
|
||||||
data['pos_x'] -= cx
|
data['pos_x'] -= cx
|
||||||
data['pos_y'] -= cy
|
data['pos_y'] -= cy
|
||||||
|
|
||||||
|
|
||||||
|
if bin_positions:
|
||||||
|
data['pos_x'] =np.digitize(data['pos_x'], bins=space_x)
|
||||||
|
data['pos_y'] =np.digitize(data['pos_y'], bins=space_y)
|
||||||
|
print(data['pos_x'])
|
||||||
|
|
||||||
# Mean Position
|
# Mean Position
|
||||||
|
|
||||||
print("Means: x:", data['pos_x'].mean(), "y:", data['pos_y'].mean())
|
print("Means: x:", data['pos_x'].mean(), "y:", data['pos_y'].mean())
|
||||||
|
@ -199,9 +211,22 @@ def process_data(src_dir: Path, dst_dir: Path, name: str, smooth_tracks: bool, c
|
||||||
skipped_for_error += 1
|
skipped_for_error += 1
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# without repeats, there will mostli likely only be straight movements
|
||||||
|
# better to filter by time
|
||||||
|
# only_diff = node_df[['pos_x', 'pos_y']].diff().fillna(1).any(axis=1)
|
||||||
|
# # print(node_df[['pos_x', 'pos_y']], )
|
||||||
|
# # exit()
|
||||||
|
|
||||||
node_values = node_df[['pos_x', 'pos_y']].values
|
|
||||||
|
|
||||||
|
# # mask positions
|
||||||
|
# node_values = node_df[only_diff][['pos_x', 'pos_y']].values
|
||||||
|
# print(node_values)
|
||||||
|
|
||||||
|
if bin_positions:
|
||||||
|
node_values = node_df.iloc[::5, :][['pos_x', 'pos_y']].values
|
||||||
|
else:
|
||||||
|
node_values = node_df[['pos_x', 'pos_y']].values
|
||||||
|
# print(node_values)
|
||||||
|
|
||||||
if node_values.shape[0] < min_track_length:
|
if node_values.shape[0] < min_track_length:
|
||||||
continue
|
continue
|
||||||
|
@ -262,6 +287,7 @@ def main():
|
||||||
parser.add_argument("--smooth-tracks", action='store_true', help=f"Enable smoother. Set to {smooth_window} frames")
|
parser.add_argument("--smooth-tracks", action='store_true', help=f"Enable smoother. Set to {smooth_window} frames")
|
||||||
parser.add_argument("--cm-to-m", action='store_true', help=f"If homography is in cm, convert tracked points to meter for beter results")
|
parser.add_argument("--cm-to-m", action='store_true', help=f"If homography is in cm, convert tracked points to meter for beter results")
|
||||||
parser.add_argument("--center-data", action='store_true', help=f"Normalise around center")
|
parser.add_argument("--center-data", action='store_true', help=f"Normalise around center")
|
||||||
|
parser.add_argument("--bin-positions", action='store_true', help=f"Experiment to put round positions to a grid")
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
process_data(**args.__dict__)
|
process_data(**args.__dict__)
|
||||||
|
|
|
@ -443,7 +443,8 @@ class Smoother:
|
||||||
else:
|
else:
|
||||||
# "Unlike Kalman filtering, which focuses on predicting and updating the current state using historical measurements, Kalman smoothing enhances the accuracy of past state values"
|
# "Unlike Kalman filtering, which focuses on predicting and updating the current state using historical measurements, Kalman smoothing enhances the accuracy of past state values"
|
||||||
# see https://medium.com/@shahalkp1/kalman-smoothing-using-tsmoothie-0175260464e5
|
# see https://medium.com/@shahalkp1/kalman-smoothing-using-tsmoothie-0175260464e5
|
||||||
self.smoother = KalmanSmoother(component='level_trend_season', component_noise={'level':0.03, 'season': .02, 'trend':0.04},n_seasons = 2, copy=None)
|
self.smoother = KalmanSmoother(component='level_trend', component_noise={'level':0.03, 'season': .02, 'trend':0.04},n_seasons = 2, copy=None)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def smooth(self, points: List[float]):
|
def smooth(self, points: List[float]):
|
||||||
|
|
Loading…
Reference in a new issue