diff --git a/trap/frame_emitter.py b/trap/frame_emitter.py index f07a147..2be264e 100644 --- a/trap/frame_emitter.py +++ b/trap/frame_emitter.py @@ -95,9 +95,7 @@ class Track: coords = self.get_projected_history(H) return [{"x":c[0], "y":c[1]} for c in coords] - - @dataclass class Frame: diff --git a/trap/renderer.py b/trap/renderer.py index 67304c9..d48d693 100644 --- a/trap/renderer.py +++ b/trap/renderer.py @@ -24,11 +24,25 @@ from pyglet import shapes from PIL import Image from trap.frame_emitter import DetectionState, Frame, Track - +from dataclasses import dataclass logger = logging.getLogger("trap.renderer") +@dataclass +class LineAnimConfig: + start_opacity: float + target_opacity: float + decay: float + +@dataclass +class AnimConfig: + clear_color = (0,0,0,0) + video_opacity = 100 # on 255 scale + tracks: LineAnimConfig = LineAnimConfig(80, 180, 60) + predictions: LineAnimConfig = LineAnimConfig(20, 50, 10) + + class FrameAnimation: def __init__(self, frame: Frame): self.start_time = time.time() @@ -101,8 +115,8 @@ class DrawnTrack: ''' # TODO: make lerp, currently quick way to get results for i, pos in enumerate(self.drawn_positions): - self.drawn_positions[i][0] = int(exponentialDecay(self.drawn_positions[i][0], self.coords[i][0], 16, dt)) - self.drawn_positions[i][1] = int(exponentialDecay(self.drawn_positions[i][1], self.coords[i][1], 16, dt)) + self.drawn_positions[i][0] = int(exponentialDecay(self.drawn_positions[i][0], self.coords[i][0], AnimConfig.tracks.decay, dt)) + self.drawn_positions[i][1] = int(exponentialDecay(self.drawn_positions[i][1], self.coords[i][1], AnimConfig.tracks.decay, dt)) if len(self.coords) > len(self.drawn_positions): self.drawn_positions.extend(self.coords[len(self.drawn_positions):]) @@ -151,7 +165,7 @@ class DrawnTrack: if ci >= len(self.shapes): # TODO: add color2 line = self.renderer.gradientLine(x, y, x2, y2, 3, color, color, batch=self.renderer.batch_anim) - line.opacity = 5 + line.opacity = AnimConfig.tracks.start_opacity self.shapes.append(line) else: @@ -159,50 +173,53 @@ class DrawnTrack: line.x, line.y = x, y line.x2, line.y2 = x2, y2 line.color = color - line.opacity = int(exponentialDecay(line.opacity, 180, 3, dt)) + line.opacity = int(exponentialDecay(line.opacity, AnimConfig.tracks.target_opacity, AnimConfig.tracks.start_opacity, dt)) # TODO: basically a duplication of the above, do this smarter? # TODO: add intermediate segment - color = colorset[self.track_id % len(colorset)] + #color = colorset[self.track_id % len(colorset)] - for a, drawn_predictions in enumerate(self.drawn_predictions): - if len(self.pred_shapes) <= a: - self.pred_shapes.append([]) + for drawn_prediction in self.predictions: + drawn_prediction.update_opacities(dt) + + # for a, drawn_predictions in enumerate(self.drawn_predictions): + # if len(self.pred_shapes) <= a: + # self.pred_shapes.append([]) - if len(self.pred_shapes[a]) > (len(drawn_predictions) +1): - self.pred_shapes[a] = self.pred_shapes[a][:len(drawn_predictions)] + # if len(self.pred_shapes[a]) > (len(drawn_predictions) +1): + # self.pred_shapes[a] = self.pred_shapes[a][:len(drawn_predictions)] - # for i, pos in drawn_predictions.enumerate(): - for ci in range(0, len(drawn_predictions)): - if ci == 0: - x, y = [int(p) for p in self.drawn_positions[-1]] - else: - x, y = [int(p) for p in drawn_predictions[ci-1]] + # # for i, pos in drawn_predictions.enumerate(): + # for ci in range(0, len(drawn_predictions)): + # if ci == 0: + # x, y = [int(p) for p in self.drawn_positions[-1]] + # else: + # x, y = [int(p) for p in drawn_predictions[ci-1]] - x2, y2 = [int(p) for p in drawn_predictions[ci]] + # x2, y2 = [int(p) for p in drawn_predictions[ci]] - y, y2 = self.renderer.window.height - y, self.renderer.window.height - y2 - # color = [255,0,0] - # print(x,y,x2,y2,color) + # y, y2 = self.renderer.window.height - y, self.renderer.window.height - y2 + # # color = [255,0,0] + # # print(x,y,x2,y2,color) - if ci >= len(self.pred_shapes[a]): - # TODO: add color2 - line = self.renderer.gradientLine(x, y, x2, y2, 3, color, color, batch=self.renderer.batch_anim) - line.opacity = 5 - self.pred_shapes[a].append(line) + # if ci >= len(self.pred_shapes[a]): + # # TODO: add color2 + # line = self.renderer.gradientLine(x, y, x2, y2, 3, color, color, batch=self.renderer.batch_anim) + # line.opacity = 5 + # self.pred_shapes[a].append(line) - else: - line = self.pred_shapes[a][ci-1] - line.x, line.y = x, y - line.x2, line.y2 = x2, y2 - line.color = color - decay = (16/ci) if ci else 16 - half = len(drawn_predictions) / 2 - if ci < half: - target_opacity = 180 - else: - target_opacity = (1 - ((ci - half) / half)) * 180 - line.opacity = int(exponentialDecay(line.opacity, target_opacity, decay, dt)) + # else: + # line = self.pred_shapes[a][ci-1] + # line.x, line.y = x, y + # line.x2, line.y2 = x2, y2 + # line.color = color + # decay = (16/ci) if ci else 16 + # half = len(drawn_predictions) / 2 + # if ci < half: + # target_opacity = 180 + # else: + # target_opacity = (1 - ((ci - half) / half)) * 180 + # line.opacity = int(exponentialDecay(line.opacity, target_opacity, decay, dt)) class DrawnPrediction: def __init__(self, drawn_track: DrawnTrack, coords: list[list] = []): @@ -245,13 +262,17 @@ class DrawnPrediction: # line.x, line.y = x, y # line.x2, line.y2 = x2, y2 # line.color = color - decay = (16/ci) if ci else 16 + + # lower decay for further points slows down fade in + decay = (AnimConfig.predictions.decay/(3*ci)) if ci else AnimConfig.predictions.decay half = len(coords) / 2 + if ci < half: - target_opacity = 180 + target_opacity = AnimConfig.predictions.target_opacity else: - target_opacity = (1 - ((ci - half) / half)) * 180 + target_opacity = (1 - ((ci - half) / half)) * AnimConfig.predictions.target_opacity line.opacity = int(exponentialDecay(line.opacity, target_opacity, decay, dt)) + # logger.info(f"{target_opacity=}, {line.opacity=}") class FrameWriter: @@ -340,7 +361,8 @@ class Renderer: self.window.set_handler('on_refresh', self.on_refresh) self.window.set_handler('on_close', self.on_close) - pyglet.gl.glClearColor(81./255, 20/255, 46./255, 0) + # Purple background color: + pyglet.gl.glClearColor(*AnimConfig.clear_color) 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.y = self.window.height - 17 @@ -486,7 +508,7 @@ class Renderer: img = pyglet.image.ImageData(self.frame_size[0], self.frame_size[1], 'RGB', img.tobytes(), pitch=self.frame_size[0] * -1 * channels) # don't draw in batch, so that it is the background self.video_sprite = pyglet.sprite.Sprite(img=img, batch=self.batch_bg) - self.video_sprite.opacity = 100 + self.video_sprite.opacity = AnimConfig.video_opacity except zmq.ZMQError as e: # idx = frame.index if frame else "NONE" # logger.debug(f"reuse video frame {idx}")