1515from funscript_editor .algorithms .videotracker import StaticVideoTracker
1616from PyQt5 import QtGui , QtCore , QtWidgets
1717from matplotlib .figure import Figure
18- from funscript_editor .utils .config import HYPERPARAMETER , SETTINGS
18+ from funscript_editor .utils .config import HYPERPARAMETER , SETTINGS , PROJECTION
1919from datetime import datetime
20- from funscript_editor .data .ffmpegstream import FFmpegStream , FFmpegStreamParameter , VideoInfo
20+ from funscript_editor .data .ffmpegstream import FFmpegStream , VideoInfo
2121
2222import funscript_editor .algorithms .signalprocessing as sp
2323import numpy as np
@@ -42,7 +42,8 @@ class FunscriptGeneratorParameter:
4242 zoom_factor :float = max ((1.0 , float (SETTINGS ['zoom_factor' ])))
4343 top_threshold :float = float (HYPERPARAMETER ['top_threshold' ])
4444 bottom_threshold :float = float (HYPERPARAMETER ['bottom_threshold' ])
45- preview_scaling :float = 1.0
45+ preview_scaling :float = float (SETTINGS ['preview_scaling' ])
46+ projection :str = str (SETTINGS ['projection' ]).lower ()
4647
4748
4849class FunscriptGenerator (QtCore .QThread ):
@@ -89,6 +90,24 @@ def __init__(self,
8990 logger = logging .getLogger (__name__ )
9091
9192
93+ def determine_monitor_scaling (self ):
94+ frame_width = PROJECTION [self .params .projection ]['parameter' ]['width' ]
95+ frame_height = PROJECTION [self .params .projection ]['parameter' ]['height' ]
96+
97+ scale = []
98+ try :
99+ for monitor in get_monitors ():
100+ scale .append ( min ((monitor .width / float (frame_width ), monitor .height / float (frame_height ) )) )
101+ except : pass
102+
103+ if len (scale ) == 0 :
104+ self .logger .error ("Monitor resolution info not found" )
105+ self .monitor_scale = 1.0
106+ else :
107+ # asume we use the largest monitor for scipting
108+ self .mointor_scale = max (scale )
109+
110+
92111 def drawBox (self , img : np .ndarray , bbox : tuple ) -> np .ndarray :
93112 """ Draw an tracking box on the image/frame
94113
@@ -291,9 +310,20 @@ def scale_score(self, status: str, direction : str = 'y') -> None:
291310 cap .release ()
292311
293312 if successMin and successMax :
294- # TODO: Assume we have VR 3D Side by Side
295- imgMin = imgMin [:, :int (imgMin .shape [1 ]/ 2 )]
296- imgMax = imgMax [:, :int (imgMax .shape [1 ]/ 2 )]
313+ if 'vr' in self .params .projection .split ('_' ):
314+ if 'sbs' in self .params .projection .split ('_' ):
315+ imgMin = imgMin [:, :int (imgMin .shape [1 ]/ 2 )]
316+ imgMax = imgMax [:, :int (imgMax .shape [1 ]/ 2 )]
317+ elif 'ou' in self .params .projection .split ('_' ):
318+ imgMin = imgMin [:int (imgMin .shape [0 ]/ 2 ), :]
319+ imgMax = imgMax [:int (imgMax .shape [0 ]/ 2 ), :]
320+
321+ if PROJECTION [self .params .projection ]['parameter' ]['width' ] > 0 :
322+ scale = PROJECTION [self .params .projection ]['parameter' ]['width' ] / float (2 * imgMax .shape [1 ])
323+ else :
324+ scale = PROJECTION [self .params .projection ]['parameter' ]['height' ] / float (2 * imgMax .shape [1 ])
325+ imgMin = cv2 .resize (imgMin , None , fx = scale , fy = scale )
326+ imgMax = cv2 .resize (imgMax , None , fx = scale , fy = scale )
297327
298328 (desired_min , desired_max ) = self .min_max_selector (
299329 image_min = imgMin ,
@@ -381,31 +411,16 @@ def preview_scaling(self, preview_image :np.ndarray) -> np.ndarray:
381411 Returns:
382412 np.ndarray: scaled opencv image
383413 """
384- """
385- frame_height, frame_width = preview_image.shape[:2]
386- scale = []
387- try:
388- for monitor in get_monitors():
389- scale.append( min((monitor.width / (frame_width*1.1), monitor.height / (frame_height*1.1) )) )
390- except: pass
391-
392- if len(scale) == 0:
393- self.logger.error("Monitor resolution info not found")
394- scale = 1.0
395- else:
396- # asume we use the largest monitor for scipting
397- scale = max(scale)
398- """
399414 return cv2 .resize (preview_image , None , fx = self .params .preview_scaling , fy = self .params .preview_scaling )
400415
401416
402- def get_projection_parameter (self , image :np .ndarray ) -> None :
403- """ Get the projection ROI parameters form user input
417+ def get_vr_projection_config (self , image :np .ndarray ) -> None :
418+ """ Get the projection ROI config form user input
404419
405420 Args:
406421 image (np.ndarray): opencv vr 180 or 360 image
407422 """
408- parameter = FFmpegStreamParameter ()
423+ config = PROJECTION [ self . params . projection ]
409424
410425 # NOTE: improve processing speed to make this menu more responsive
411426 if image .shape [0 ] > 6000 or image .shape [1 ] > 6000 :
@@ -418,7 +433,7 @@ def get_projection_parameter(self, image :np.ndarray) -> None:
418433 while not selected :
419434 if parameter_changed :
420435 parameter_changed = False
421- preview = FFmpegStream .get_projection (image , parameter )
436+ preview = FFmpegStream .get_projection (image , config )
422437
423438 preview = self .drawText (preview , "Press 'q' to use current selected region of interest)" ,
424439 y = 50 , color = (255 , 0 , 0 ))
@@ -433,10 +448,10 @@ def get_projection_parameter(self, image :np.ndarray) -> None:
433448 selected = True
434449 break
435450 elif pressed_key == "'w'" :
436- parameter . phi = min ((80 , parameter . phi + 5 ))
451+ config [ ' parameter' ][ ' phi' ] = min ((80 , config [ ' parameter' ][ ' phi' ] + 5 ))
437452 parameter_changed = True
438453 elif pressed_key == "'s'" :
439- parameter . phi = max ((- 80 , parameter . phi - 5 ))
454+ config [ ' parameter' ][ ' phi' ] = max ((- 80 , config [ ' parameter' ][ ' phi' ] - 5 ))
440455 parameter_changed = True
441456
442457 if cv2 .waitKey (1 ) in [ord ('q' )]: break
@@ -448,7 +463,7 @@ def get_projection_parameter(self, image :np.ndarray) -> None:
448463 cv2 .waitKey (1 )
449464 except : pass
450465
451- return parameter
466+ return config
452467
453468
454469 def get_bbox (self , image : np .ndarray , txt : str ) -> tuple :
@@ -514,18 +529,45 @@ def get_first_frame(self) -> np.ndarray:
514529 return first_frame
515530
516531
532+ def get_flat_projection_config (self ,
533+ first_frame :np .ndarray ) -> dict :
534+ """ Get the flat config parameter
535+
536+ Args:
537+ first_frame (np.ndarray): opencv image
538+
539+ Returns:
540+ dict: config
541+ """
542+ h , w = first_frame .shape [:2 ]
543+ config = PROJECTION [self .params .projection ]
544+
545+ if config ['parameter' ]['height' ] == - 1 :
546+ scaling = config ['parameter' ]['width' ] / float (w )
547+ config ['parameter' ]['height' ] = round (h * scaling )
548+ elif config ['parameter' ]['width' ] == - 1 :
549+ scaling = config ['parameter' ]['height' ] / float (h )
550+ config ['parameter' ]['width' ] = round (w * scaling )
551+
552+ return config
553+
554+
517555 def tracking (self ) -> str :
518556 """ Tracking function to track the features in the video
519557
520558 Returns:
521559 str: a process status message e.g. 'end of video reached'
522560 """
523561 first_frame = FFmpegStream .get_frame (self .params .video_path , self .params .start_frame )
524- projection_parameter = self .get_projection_parameter (first_frame )
562+
563+ if 'vr' in self .params .projection .split ('_' ):
564+ projection_config = self .get_vr_projection_config (first_frame )
565+ else :
566+ projection_config = self .get_flat_projection_config (first_frame )
525567
526568 video = FFmpegStream (
527569 video_path = self .params .video_path ,
528- parameter = projection_parameter ,
570+ config = projection_config ,
529571 start_frame = self .params .start_frame
530572 )
531573
@@ -553,7 +595,7 @@ def tracking(self) -> str:
553595 frame_num += 1
554596
555597 if frame is None :
556- status = 'Reach a corrupt video frame'
598+ status = 'Reach a corrupt video frame' if video . isOpen () else 'End of video reached'
557599 break
558600
559601 # NOTE: Use != 1 to ensure that the first difference is equal to the folowing (reqired for the interpolation)
@@ -607,7 +649,6 @@ def tracking(self) -> str:
607649 wait = cycle_time_in_ms - (time .time () - cycle_start )* float (1000 )
608650 if wait > 0 : time .sleep (wait / float (1000 ))
609651
610-
611652 video .stop ()
612653 self .logger .info (status )
613654 self .calculate_score ()
0 commit comments