Video recorder in frame emitter (for gige video)

This commit is contained in:
Ruben van de Ven 2025-05-27 17:37:51 +02:00
parent 8b9723bdf4
commit f427b6bb3b
4 changed files with 31 additions and 21 deletions

View file

@ -371,9 +371,9 @@ def decorate_frame(frame: Frame, tracker_frame: Frame, prediction_frame: Frame,
for option, value in prediction_frame.log['predictor'].items(): for option, value in prediction_frame.log['predictor'].items():
options.append(f"{option}: {value}") options.append(f"{option}: {value}")
if len(options):
cv2.putText(img, options.pop(-1), (20,img.shape[0]-30), cv2.FONT_HERSHEY_PLAIN, 1, base_color, 1) cv2.putText(img, options.pop(-1), (20,img.shape[0]-30), cv2.FONT_HERSHEY_PLAIN, 1, base_color, 1)
cv2.putText(img, " | ".join(options), (20,img.shape[0]-10), cv2.FONT_HERSHEY_PLAIN, 1, base_color, 1) cv2.putText(img, " | ".join(options), (20,img.shape[0]-10), cv2.FONT_HERSHEY_PLAIN, 1, base_color, 1)
return img return img

View file

@ -1,18 +1,15 @@
from __future__ import annotations from __future__ import annotations
import logging import logging
import multiprocessing
import pickle import pickle
from argparse import ArgumentParser, Namespace from argparse import ArgumentParser, Namespace
from multiprocessing import Event from multiprocessing import Event
from pathlib import Path from pathlib import Path
import zmq
from trap import node from trap import node
from trap.base import * from trap.base import *
from trap.base import LambdaParser from trap.base import LambdaParser
from trap.timer import Timer from trap.preview_renderer import FrameWriter
from trap.video_sources import get_video_source from trap.video_sources import get_video_source
logger = logging.getLogger('trap.frame_emitter') logger = logging.getLogger('trap.frame_emitter')
@ -39,20 +36,31 @@ class FrameEmitter(node.Node):
offset = int(self.config.video_offset or 0) offset = int(self.config.video_offset or 0)
source = get_video_source(self.video_srcs, self.config.camera, offset, self.config.video_end, self.config.video_loop) source = get_video_source(self.video_srcs, self.config.camera, offset, self.config.video_end, self.config.video_loop)
video_gen = enumerate(source, start = offset) video_gen = enumerate(source, start = offset)
while self.run_loop():
try: # writer = FrameWriter(self.config.record, None, None) if self.config.record else nullcontext
i, img = next(video_gen) print(self.config.record)
except StopIteration as e: writer = FrameWriter(str(self.config.record), None, None) if self.config.record else None
logger.info("Video source ended") try:
break while self.run_loop():
frame = Frame(i, img=img, H=self.config.camera.H, camera=self.config.camera) try:
i, img = next(video_gen)
except StopIteration as e:
logger.info("Video source ended")
break
# TODO: this is very dirty, need to find another way. frame = Frame(i, img=img, H=self.config.camera.H, camera=self.config.camera)
# perhaps multiprocessing Array?
self.frame_noimg_sock.send(pickle.dumps(frame.without_img())) # TODO: this is very dirty, need to find another way.
self.frame_sock.send(pickle.dumps(frame)) # perhaps multiprocessing Array?
self.frame_noimg_sock.send(pickle.dumps(frame.without_img()))
self.frame_sock.send(pickle.dumps(frame))
if writer:
writer.write(frame.img)
finally:
if writer:
writer.release()
logger.info("Stopping") logger.info("Stopping")
@ -84,6 +92,10 @@ class FrameEmitter(node.Node):
help="End (or loop) playback at given frame.", help="End (or loop) playback at given frame.",
default=None, default=None,
type=int) type=int)
argparser.add_argument("--record",
help="Record source video to given filename",
default=None,
type=Path)
argparser.add_argument("--video-loop", argparser.add_argument("--video-loop",
help="By default it emitter will run only once. This allows it to loop the video file to keep testing.", help="By default it emitter will run only once. This allows it to loop the video file to keep testing.",

View file

@ -300,7 +300,7 @@ class FrameWriter:
""" """
def __init__(self, filename: str, fps: float, frame_size: Optional[tuple] = None) -> None: def __init__(self, filename: str, fps: float, frame_size: Optional[tuple] = None) -> None:
self.filename = filename self.filename = filename
self.fps = fps self._fps = fps
self.frame_size = frame_size self.frame_size = frame_size
self.tmp_dir = tempfile.TemporaryDirectory(prefix="trap-output-") self.tmp_dir = tempfile.TemporaryDirectory(prefix="trap-output-")

View file

@ -107,8 +107,6 @@ class GigE(VideoSource):
br = self.config.post_crop_br or (img.shape[1], img.shape[0]) br = self.config.post_crop_br or (img.shape[1], img.shape[0])
return img[tl[1]:br[1],tl[0]:br[0],:] return img[tl[1]:br[1],tl[0]:br[0],:]
class SingleCvVideoSource(VideoSource): class SingleCvVideoSource(VideoSource):
def recv(self): def recv(self):