Render directly to video
This commit is contained in:
		
							parent
							
								
									821d06c9cf
								
							
						
					
					
						commit
						ec31810d80
					
				
					 4 changed files with 43 additions and 4 deletions
				
			
		| 
						 | 
					@ -37,6 +37,7 @@ class FrameEmitter:
 | 
				
			||||||
        video = cv2.VideoCapture(str(self.config.video_src))
 | 
					        video = cv2.VideoCapture(str(self.config.video_src))
 | 
				
			||||||
        fps = video.get(cv2.CAP_PROP_FPS)
 | 
					        fps = video.get(cv2.CAP_PROP_FPS)
 | 
				
			||||||
        frame_duration = 1./fps
 | 
					        frame_duration = 1./fps
 | 
				
			||||||
 | 
					        logger.info(f"Emit frames at {fps} fps")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        prev_time = time.time()
 | 
					        prev_time = time.time()
 | 
				
			||||||
        while self.is_running.is_set():
 | 
					        while self.is_running.is_set():
 | 
				
			||||||
| 
						 | 
					@ -66,3 +67,4 @@ class FrameEmitter:
 | 
				
			||||||
def run_frame_emitter(config: Namespace, is_running: Event):
 | 
					def run_frame_emitter(config: Namespace, is_running: Event):
 | 
				
			||||||
    router = FrameEmitter(config, is_running)
 | 
					    router = FrameEmitter(config, is_running)
 | 
				
			||||||
    router.emit_video()
 | 
					    router.emit_video()
 | 
				
			||||||
 | 
					    is_running.clear()
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,11 @@
 | 
				
			||||||
 | 
					import atexit
 | 
				
			||||||
import logging
 | 
					import logging
 | 
				
			||||||
from logging.handlers import SocketHandler
 | 
					from logging.handlers import SocketHandler
 | 
				
			||||||
from multiprocessing import Event, Process, Queue
 | 
					from multiprocessing import Event, Process, Queue
 | 
				
			||||||
 | 
					import multiprocessing
 | 
				
			||||||
 | 
					import signal
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
 | 
					import time
 | 
				
			||||||
from trap.config import parser
 | 
					from trap.config import parser
 | 
				
			||||||
from trap.frame_emitter import run_frame_emitter
 | 
					from trap.frame_emitter import run_frame_emitter
 | 
				
			||||||
from trap.prediction_server import run_prediction_server
 | 
					from trap.prediction_server import run_prediction_server
 | 
				
			||||||
| 
						 | 
					@ -12,17 +16,28 @@ from trap.tracker import run_tracker
 | 
				
			||||||
 | 
					
 | 
				
			||||||
logger = logging.getLogger("trap.plumbing")
 | 
					logger = logging.getLogger("trap.plumbing")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ExceptionHandlingProcess(Process):
 | 
					class ExceptionHandlingProcess(Process):
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
    def run(self):
 | 
					    def run(self):
 | 
				
			||||||
        assert 'is_running' in self._kwargs
 | 
					        assert 'is_running' in self._kwargs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # exit handler to make sure that on many kinds of crashes and kills the
 | 
				
			||||||
 | 
					        # suprocess warns parent/siblings
 | 
				
			||||||
 | 
					        # TODO: Does not work with OOM kill. Would need a watchdog process for that
 | 
				
			||||||
 | 
					        def exit_handler(*args):
 | 
				
			||||||
 | 
					            self._kwargs['is_running'].clear()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        atexit.register(exit_handler)
 | 
				
			||||||
 | 
					        signal.signal(signal.SIGTERM, exit_handler)
 | 
				
			||||||
 | 
					        signal.signal(signal.SIGINT, exit_handler)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            super(Process, self).run()
 | 
					            super(Process, self).run()
 | 
				
			||||||
        except Exception as e:
 | 
					        except Exception as e:
 | 
				
			||||||
            logger.exception(e)
 | 
					            logger.exception(e)
 | 
				
			||||||
            self._kwargs['is_running'].clear()
 | 
					            self._kwargs['is_running'].clear()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
def start():
 | 
					def start():
 | 
				
			||||||
    args = parser.parse_args()
 | 
					    args = parser.parse_args()
 | 
				
			||||||
    loglevel = logging.NOTSET if args.verbose > 1 else logging.DEBUG if args.verbose > 0  else logging.INFO
 | 
					    loglevel = logging.NOTSET if args.verbose > 1 else logging.DEBUG if args.verbose > 0  else logging.INFO
 | 
				
			||||||
| 
						 | 
					@ -40,6 +55,8 @@ def start():
 | 
				
			||||||
    isRunning.set()
 | 
					    isRunning.set()
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if args.remote_log_addr:
 | 
					    if args.remote_log_addr:
 | 
				
			||||||
        logging.captureWarnings(True)
 | 
					        logging.captureWarnings(True)
 | 
				
			||||||
        root_logger.setLevel(logging.NOTSET)  # to send all records to cutelog
 | 
					        root_logger.setLevel(logging.NOTSET)  # to send all records to cutelog
 | 
				
			||||||
| 
						 | 
					@ -64,6 +81,9 @@ def start():
 | 
				
			||||||
    for proc in procs:
 | 
					    for proc in procs:
 | 
				
			||||||
        proc.start()
 | 
					        proc.start()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # wait for processes to clean up
 | 
				
			||||||
    for proc in procs:
 | 
					    for proc in procs:
 | 
				
			||||||
        proc.join()
 | 
					        proc.join()
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    logger.info('Stop')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -207,8 +207,13 @@ class PredictionServer:
 | 
				
			||||||
        trajectron.set_environment(online_env, init_timestep)
 | 
					        trajectron.set_environment(online_env, init_timestep)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        timestep = init_timestep + 1
 | 
					        timestep = init_timestep + 1
 | 
				
			||||||
 | 
					        prev_run_time = 0
 | 
				
			||||||
        while self.is_running.is_set():
 | 
					        while self.is_running.is_set():
 | 
				
			||||||
            timestep += 1
 | 
					            timestep += 1
 | 
				
			||||||
 | 
					            this_run_time = time.time()
 | 
				
			||||||
 | 
					            logger.debug('test')
 | 
				
			||||||
 | 
					            time.sleep(max(0, prev_run_time - this_run_time + .5))
 | 
				
			||||||
 | 
					            prev_run_time = this_run_time
 | 
				
			||||||
            # for timestep in range(init_timestep + 1, eval_scene.timesteps):
 | 
					            # for timestep in range(init_timestep + 1, eval_scene.timesteps):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # input_dict = eval_scene.get_clipped_input_dict(timestep, hyperparams['state'])
 | 
					            # input_dict = eval_scene.get_clipped_input_dict(timestep, hyperparams['state'])
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,6 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from argparse import Namespace
 | 
					from argparse import Namespace
 | 
				
			||||||
 | 
					import datetime
 | 
				
			||||||
import logging
 | 
					import logging
 | 
				
			||||||
from multiprocessing import Event
 | 
					from multiprocessing import Event
 | 
				
			||||||
import cv2
 | 
					import cv2
 | 
				
			||||||
| 
						 | 
					@ -36,6 +37,15 @@ class Renderer:
 | 
				
			||||||
        if not self.config.output_dir.exists():
 | 
					        if not self.config.output_dir.exists():
 | 
				
			||||||
            raise FileNotFoundError("Path does not exist")
 | 
					            raise FileNotFoundError("Path does not exist")
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					        date_str = datetime.datetime.now().isoformat(timespec="minutes")
 | 
				
			||||||
 | 
					        filename = self.config.output_dir / f"render_predictions-{date_str}.mp4"
 | 
				
			||||||
 | 
					        logger.info(f"Write to {filename}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        fourcc = cv2.VideoWriter_fourcc(*'vp09')
 | 
				
			||||||
 | 
					        # TODO: get FPS from frame_emitter
 | 
				
			||||||
 | 
					        self.out = cv2.VideoWriter(str(filename), fourcc, 23.97, (1280,720))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    def run(self):
 | 
					    def run(self):
 | 
				
			||||||
        predictions = {}
 | 
					        predictions = {}
 | 
				
			||||||
        i=0
 | 
					        i=0
 | 
				
			||||||
| 
						 | 
					@ -81,8 +91,10 @@ class Renderer:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            img_path = (self.config.output_dir / f"{i:05d}.png").resolve()
 | 
					            img_path = (self.config.output_dir / f"{i:05d}.png").resolve()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            cv2.imwrite(str(img_path), img)
 | 
					            # cv2.imwrite(str(img_path), img)
 | 
				
			||||||
 | 
					            self.out.write(img)
 | 
				
			||||||
        logger.info('Stopping')
 | 
					        logger.info('Stopping')
 | 
				
			||||||
 | 
					        self.out.release() 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue