1515from PyQt5 import QtGui , QtCore , QtWidgets
1616from matplotlib .figure import Figure
1717from funscript_editor .definitions import VIDEO_SCALING_CONFIG_FILE
18- from funscript_editor .utils .config import HYPERPARAMETER
18+ from funscript_editor .utils .config import HYPERPARAMETER , SETTINGS
1919from datetime import datetime
2020
2121import funscript_editor .algorithms .signalprocessing as sp
@@ -29,9 +29,11 @@ class FunscriptGeneratorParameter:
2929 video_path : str # no default value
3030 start_frame : int = 0 # default is video start
3131 skip_frames : int = HYPERPARAMETER ['skip_frames' ]
32- max_playback_fps : int = HYPERPARAMETER ['max_playback_fps' ]
33- direction : str = HYPERPARAMETER ['tracking_direction' ]
34- use_zoom : bool = HYPERPARAMETER ['use_zoom' ]
32+ max_playback_fps : int = SETTINGS ['max_playback_fps' ]
33+ direction : str = SETTINGS ['tracking_direction' ]
34+ use_zoom : bool = SETTINGS ['use_zoom' ]
35+ shift_bottom_points :int = HYPERPARAMETER ['shift_bottom_points' ]
36+ shift_top_points :int = HYPERPARAMETER ['shift_top_points' ]
3537 track_men : bool = True
3638
3739
@@ -324,7 +326,7 @@ def plot_y_score(self, name: str, idx_list: list, dpi : int = 300) -> None:
324326
325327 Args:
326328 name (str): file name for the figure
327- idx_list (list): list with funscript action points
329+ idx_list (list): list with all frame numbers with funscript action points
328330 dpi (int): picture output dpi
329331 """
330332 if len (self .score_y ) < 2 : return
@@ -432,6 +434,9 @@ def tracking(self) -> str:
432434 if first_frame is None :
433435 return
434436
437+ if self .params .skip_frames < 0 :
438+ self .params .skip_frames = 0
439+
435440 bboxWoman = self .get_bbox (first_frame , "Select Woman Feature" )
436441 trackerWoman = StaticVideoTracker (first_frame , bboxWoman )
437442 self .bboxes ['Woman' ].append (bboxWoman )
@@ -441,7 +446,7 @@ def tracking(self) -> str:
441446 trackerMen = StaticVideoTracker (first_frame , bboxMen )
442447 self .bboxes ['Men' ].append (bboxMen )
443448
444- if self .params .max_playback_fps > 2 :
449+ if self .params .max_playback_fps > ( self . params . skip_frames + 1 ) :
445450 cycle_time_in_ms = (float (1000 ) / float (self .params .max_playback_fps )) * (self .params .skip_frames + 1 )
446451 else :
447452 cycle_time_in_ms = 0
@@ -562,6 +567,23 @@ def finished(self, status: str, success :bool) -> None:
562567 self .stopped = True
563568
564569
570+ def apply_shift (self , frame_number , position : str ) -> int :
571+ """ Apply shift to predicted frame positions
572+
573+ Args:
574+ position (str): is max or min
575+ """
576+ if position in ['max' , 'top' ] and self .params .direction != 'x' :
577+ if frame_number >= - 1 * self .params .shift_top_points and frame_number + self .params .shift_top_points < len (self .score_y ):
578+ return self .params .start_frame + frame_number + self .params .shift_top_points
579+
580+ if position in ['min' , 'bottom' ] and self .params .direction != 'x' :
581+ if frame_number >= - 1 * self .params .shift_bottom_points and frame_number + self .params .shift_bottom_points < len (self .score_y ):
582+ return self .params .start_frame + frame_number + self .params .shift_bottom_points
583+
584+ return self .params .start_frame + frame_number
585+
586+
565587 def run (self ) -> None :
566588 """ The Funscript Generator Thread Function """
567589 # NOTE: score_y and score_x should have the same number of elements so it should be enouth to check one score length
@@ -578,18 +600,28 @@ def run(self) -> None:
578600 return
579601
580602 if self .params .direction != 'x' :
581- idx_list = sp .get_local_max_and_min_idx (self .score_y , self .fps )
603+ idx_dict = sp .get_local_max_and_min_idx (self .score_y , self .fps )
582604 else :
583- idx_list = sp .get_local_max_and_min_idx (self .score_x , self .fps )
605+ idx_dict = sp .get_local_max_and_min_idx (self .score_x , self .fps )
606+
607+ idx_list = [x for k in ['min' , 'max' ] for x in idx_dict [k ]]
608+ idx_list .sort ()
584609
585610 if False :
586- if self .params .direction != 'x' : self .plot_y_score ('debug_001.png' , idx_list )
587- self .plot_scores ('debug_002.png' )
611+ self .plot_scores ('debug_001.png' )
612+ if self .params .direction != 'x' :
613+ self .plot_y_score ('debug_002.png' , idx_list )
614+
615+ for idx in idx_dict ['min' ]:
616+ self .funscript .add_action (
617+ self .score_y [idx ],
618+ self .frame_to_millisec (self .apply_shift (idx , 'min' ), self .fps )
619+ )
588620
589- for idx in idx_list :
621+ for idx in idx_dict [ 'max' ] :
590622 self .funscript .add_action (
591623 self .score_y [idx ],
592- self .frame_to_millisec (idx + self .params . start_frame , self .fps )
624+ self .frame_to_millisec (self .apply_shift ( idx , 'max' ) , self .fps )
593625 )
594626
595627 self .finished (status , True )
0 commit comments