Compare commits
No commits in common. "dc7d95bbcee1afbe7f70f28827bd16769de30c22" and "7710794bad26066688facccae64104b93794433e" have entirely different histories.
dc7d95bbce
...
7710794bad
1 changed files with 4 additions and 46 deletions
|
@ -4,58 +4,18 @@ from argparse import Namespace
|
||||||
import datetime
|
import datetime
|
||||||
import logging
|
import logging
|
||||||
from multiprocessing import Event
|
from multiprocessing import Event
|
||||||
from multiprocessing.synchronize import Event as BaseEvent
|
|
||||||
import cv2
|
import cv2
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
import zmq
|
import zmq
|
||||||
import tempfile
|
|
||||||
from pathlib import Path
|
|
||||||
import shutil
|
|
||||||
|
|
||||||
from trap.frame_emitter import DetectionState, Frame
|
from trap.frame_emitter import DetectionState, Frame
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger("trap.renderer")
|
logger = logging.getLogger("trap.renderer")
|
||||||
|
|
||||||
class FrameWriter:
|
|
||||||
"""
|
|
||||||
Drop-in compatible interface with cv2.VideoWriter, but support variable
|
|
||||||
framerate.
|
|
||||||
See https://video.stackexchange.com/questions/25811/ffmpeg-make-video-with-non-constant-framerate-from-image-filenames
|
|
||||||
"""
|
|
||||||
def __init__(self, filename: str, fps: float, frame_size: tuple) -> None:
|
|
||||||
self.filename = filename
|
|
||||||
self.fps = fps
|
|
||||||
self.frame_size = frame_size
|
|
||||||
|
|
||||||
self.tmp_dir = tempfile.TemporaryDirectory(prefix="trap-output-")
|
|
||||||
|
|
||||||
self.i = 0
|
|
||||||
|
|
||||||
def write(self, img: cv2.typing.MatLike):
|
|
||||||
self.i += 1
|
|
||||||
cv2.imwrite(self.tmp_dir.name + f"/{self.i:07d}.png", img)
|
|
||||||
|
|
||||||
def release(self):
|
|
||||||
"""Actually write the video"""
|
|
||||||
# ffmpeg -f image2 -ts_from_file 2 -i %d.png out.mp4
|
|
||||||
logger.info(f"Write frames from {self.tmp_dir.name} to {self.filename}")
|
|
||||||
(
|
|
||||||
ffmpeg
|
|
||||||
# the magic here is in --ts_from_file which uses the mtime of the file for the interval
|
|
||||||
# this makes it possible to have non-constant intervals between frames, which is usefull
|
|
||||||
# since we render frames when we get them
|
|
||||||
.input(self.tmp_dir.name + "/%07d.png", format="image2", ts_from_file=2)
|
|
||||||
.output(self.filename, framerate=self.fps)
|
|
||||||
.run()
|
|
||||||
)
|
|
||||||
logger.info(f"Rm frame directory: {self.tmp_dir.name}")
|
|
||||||
self.tmp_dir.cleanup()
|
|
||||||
|
|
||||||
|
|
||||||
class Renderer:
|
class Renderer:
|
||||||
def __init__(self, config: Namespace, is_running: BaseEvent):
|
def __init__(self, config: Namespace, is_running: Event):
|
||||||
self.config = config
|
self.config = config
|
||||||
self.is_running = is_running
|
self.is_running = is_running
|
||||||
|
|
||||||
|
@ -89,8 +49,6 @@ class Renderer:
|
||||||
filename = self.config.output_dir / f"render_predictions-{date_str}-{self.config.detector}.mp4"
|
filename = self.config.output_dir / f"render_predictions-{date_str}-{self.config.detector}.mp4"
|
||||||
logger.info(f"Write to {filename}")
|
logger.info(f"Write to {filename}")
|
||||||
|
|
||||||
return FrameWriter(str(filename), self.fps, self.frame_size)
|
|
||||||
|
|
||||||
fourcc = cv2.VideoWriter_fourcc(*'vp09')
|
fourcc = cv2.VideoWriter_fourcc(*'vp09')
|
||||||
|
|
||||||
return cv2.VideoWriter(str(filename), fourcc, self.fps, self.frame_size)
|
return cv2.VideoWriter(str(filename), fourcc, self.fps, self.frame_size)
|
||||||
|
@ -179,9 +137,9 @@ def decorate_frame(frame: Frame, prediction_frame: Frame, first_time: float, con
|
||||||
|
|
||||||
overlay = np.zeros(frame.img.shape, np.uint8)
|
overlay = np.zeros(frame.img.shape, np.uint8)
|
||||||
# Fill image with red color(set each pixel to red)
|
# Fill image with red color(set each pixel to red)
|
||||||
overlay[:] = (130, 0, 75)
|
overlay[:] = (128, 0, 128)
|
||||||
|
|
||||||
frame.img = cv2.addWeighted(frame.img, .4, overlay, .6, 0)
|
frame.img = cv2.addWeighted(frame.img, .5, overlay, .5, 0)
|
||||||
img = frame.img
|
img = frame.img
|
||||||
|
|
||||||
# all not working:
|
# all not working:
|
||||||
|
@ -279,6 +237,6 @@ def decorate_frame(frame: Frame, prediction_frame: Frame, first_time: float, con
|
||||||
return img
|
return img
|
||||||
|
|
||||||
|
|
||||||
def run_renderer(config: Namespace, is_running: BaseEvent):
|
def run_renderer(config: Namespace, is_running: Event):
|
||||||
renderer = Renderer(config, is_running)
|
renderer = Renderer(config, is_running)
|
||||||
renderer.run()
|
renderer.run()
|
Loading…
Reference in a new issue