11""" Top level process to generate the funscript actions by tracking selected features in the video """
22
33import cv2
4- import json
54import copy
65import time
6+ import math
77import logging
88
99from screeninfo import get_monitors
10- from threading import Thread
1110from queue import Queue
1211from pynput .keyboard import Key , Listener
1312from dataclasses import dataclass
1817
1918from funscript_editor .algorithms .kalmanfilter import KalmanFilter2D
2019from funscript_editor .algorithms .videotracker import StaticVideoTracker
21- from funscript_editor .data .ffmpegstream import FFmpegStream , VideoInfo
20+ from funscript_editor .data .ffmpegstream import FFmpegStream
2221from funscript_editor .data .funscript import Funscript
2322from funscript_editor .utils .config import HYPERPARAMETER , SETTINGS , PROJECTION
2423from funscript_editor .utils .logging import get_logfiles_paths
@@ -95,7 +94,8 @@ def __init__(self,
9594 self .score = {
9695 'x' : [],
9796 'y' : [],
98- 'euclideanDistance' : []
97+ 'euclideanDistance' : [],
98+ 'pitch' : []
9999 }
100100 self .bboxes = {
101101 'Men' : [],
@@ -263,8 +263,8 @@ def min_max_selector(self,
263263 Returns:
264264 tuple: with selected (min: flaot, max float)
265265 """
266- cv2 .createTrackbar ("Min" , self .window_name , lower_limit , upper_limit , lambda x : None )
267- cv2 .createTrackbar ("Max" , self .window_name , upper_limit , upper_limit , lambda x : None )
266+ cv2 .createTrackbar ("Min" , self .window_name , lower_limit , upper_limit , lambda _ : None )
267+ cv2 .createTrackbar ("Max" , self .window_name , upper_limit , upper_limit , lambda _ : None )
268268 image = np .concatenate ((image_min , image_max ), axis = 1 )
269269
270270 if info != "" :
@@ -317,13 +317,33 @@ def calculate_score(self) -> None:
317317 self .score ['euclideanDistance' ] = [np .sqrt (np .sum ((np .array (m ) - np .array (w )) ** 2 , axis = 0 )) \
318318 for w , m in zip (woman_center , men_center )]
319319
320+ for i in range ( min (( len (men_center ), len (woman_center ) )) ):
321+ x = self .bboxes ['Woman' ][i ][0 ] - self .bboxes ['Men' ][i ][0 ]
322+ y = self .bboxes ['Men' ][i ][1 ] - self .bboxes ['Woman' ][i ][1 ]
323+ if x >= 0 and y >= 0 :
324+ self .score ['pitch' ].append (np .arctan (np .array (y / max ((10e-3 , x )))))
325+ elif x >= 0 and y < 0 :
326+ self .score ['pitch' ].append (- 1.0 * np .arctan (np .array (y / max ((10e-3 , x )))))
327+ elif x < 0 and y < 0 :
328+ self .score ['pitch' ].append (math .pi + - 1.0 * np .arctan (np .array (y / x )))
329+ elif x < 0 and y >= 0 :
330+ self .score ['pitch' ].append (math .pi + np .arctan (np .array (y / x )))
331+ else :
332+ # this should never happen
333+ self .logger .error ('Calculate score not implement for x=%d, y=%d' , x , y )
334+
335+ # invert
336+ self .score ['pitch' ] = [- 1.0 * item for item in self .score ['pitch' ]]
337+
338+
320339 else :
321340 self .score ['x' ] = [w [0 ] - min ([x [0 ] for x in self .bboxes ['Woman' ]]) for w in self .bboxes ['Woman' ]]
322341 self .score ['y' ] = [max ([x [1 ] for x in self .bboxes ['Woman' ]]) - w [1 ] for w in self .bboxes ['Woman' ]]
323342
324343 self .score ['x' ] = sp .scale_signal (self .score ['x' ], 0 , 100 )
325344 self .score ['y' ] = sp .scale_signal (self .score ['y' ], 0 , 100 )
326345 self .score ['euclideanDistance' ] = sp .scale_signal (self .score ['euclideanDistance' ], 0 , 100 )
346+ self .score ['pitch' ] = sp .scale_signal (self .score ['pitch' ], 0 , 100 )
327347
328348
329349 def scale_score (self , status : str , metric : str = 'y' ) -> None :
@@ -339,8 +359,6 @@ def scale_score(self, status: str, metric : str = 'y') -> None:
339359 if len (self .score ['y' ]) < 2 : return
340360
341361 cap = cv2 .VideoCapture (self .params .video_path )
342- width = int (cap .get (cv2 .CAP_PROP_FRAME_WIDTH ))
343- height = int (cap .get (cv2 .CAP_PROP_FRAME_HEIGHT ))
344362
345363 if metric == 'euclideanDistance' :
346364 min_frame = np .argmin (np .array (self .score ['euclideanDistance' ])) + self .params .start_frame
@@ -898,11 +916,11 @@ def determin_change_points(self) -> dict:
898916 """
899917 self .logger .info ("Determine change points" )
900918 if self .params .metric == 'euclideanDistance' :
901- idx_dict = sp .get_local_max_and_min_idx (self .score ['euclideanDistance' ], self .video_info .fps )
919+ idx_dict = sp .get_local_max_and_min_idx (self .score ['euclideanDistance' ], round ( self .video_info .fps ) )
902920 elif self .params .metric == 'x' :
903- idx_dict = sp .get_local_max_and_min_idx (self .score ['x' ], self .video_info .fps )
921+ idx_dict = sp .get_local_max_and_min_idx (self .score ['x' ], round ( self .video_info .fps ) )
904922 else :
905- idx_dict = sp .get_local_max_and_min_idx (self .score ['y' ], self .video_info .fps )
923+ idx_dict = sp .get_local_max_and_min_idx (self .score ['y' ], round ( self .video_info .fps ) )
906924 return idx_dict
907925
908926
@@ -976,7 +994,7 @@ def run(self) -> None:
976994 self .logger .warning ("Raw output is enabled!" )
977995
978996 # NOTE: score['y'] and score['x'] should have the same number size so it should be enouth to check one score length
979- with Listener (on_press = self .on_key_press ) as listener :
997+ with Listener (on_press = self .on_key_press ) as _ :
980998 status = self .tracking ()
981999
9821000 if self .params .use_kalman_filter :
0 commit comments