3232
3333import funscript_editor .algorithms .signalprocessing as sp
3434import numpy as np
35+ import multiprocessing as mp
3536
3637@dataclass
3738class FunscriptGeneratorParameter :
@@ -75,6 +76,32 @@ class FunscriptGeneratorParameter:
7576 max_threshold : float = float (HYPERPARAMETER ['max_threshold' ])
7677
7778
79+ def merge_score (item : list , number_of_trackers : int ) -> list :
80+ """ Merge score for given number of trackers
81+
82+ Note:
83+ Python multiprocessing methods use a mp.SimpleQueue to pass tasks to the worker processes.
84+ Everything that goes through the mp.SimpleQueue must be pickable.
85+ In python functions are only picklable if they are defined at the top-level of a module.
86+
87+ Args:
88+ item (list): score for each tracker
89+ number_of_trackers (int): number of used tracker (pairs)
90+
91+ Returns:
92+ list: merged score
93+ """
94+ if number_of_trackers == 1 :
95+ return item [0 ] if len (item ) > 0 else []
96+ else :
97+ max_frame_number = max ([len (item [i ]) for i in range (number_of_trackers )])
98+ arr = np .ma .empty ((max_frame_number ,number_of_trackers ))
99+ arr .mask = True
100+ for tracker_number in range (number_of_trackers ):
101+ arr [:item [tracker_number ].shape [0 ],tracker_number ] = item [tracker_number ]
102+ return list (filter (None .__ne__ , arr .mean (axis = 1 ).tolist ()))
103+
104+
78105class FunscriptGeneratorThread (QtCore .QThread ):
79106 """ Funscript Generator Thread
80107
@@ -301,6 +328,7 @@ def min_max_selector(self,
301328 self .clear_keypress_queue ()
302329 trackbarValueMin = lower_limit
303330 trackbarValueMax = upper_limit
331+ self .logger .info ("Waiting for user input for max and min action position" )
304332 while True :
305333 try :
306334 preview = image .copy ()
@@ -314,6 +342,7 @@ def min_max_selector(self,
314342 trackbarValueMax = cv2 .getTrackbarPos ("Max" , self .window_name )
315343 except : pass
316344
345+ self .logger .info ("Receive values for max and min action position" )
317346 self .__show_loading_screen (preview .shape )
318347 return (trackbarValueMin , trackbarValueMax ) if trackbarValueMin < trackbarValueMax else (trackbarValueMax , trackbarValueMin )
319348
@@ -348,6 +377,7 @@ def calculate_score(self, bboxes) -> None:
348377 'distance' : [np .array ([]) for _ in range (self .params .number_of_trackers )],
349378 'roll' : [np .array ([]) for _ in range (self .params .number_of_trackers )]
350379 }
380+ self .logger .info ("Calculate score for %d Tracker(s)" , self .params .number_of_trackers )
351381 for tracker_number in range (self .params .number_of_trackers ):
352382 woman_center = [self .get_center (item ) for item in bboxes ['Woman' ][tracker_number ]]
353383
@@ -383,21 +413,19 @@ def calculate_score(self, bboxes) -> None:
383413 score ['x' ][tracker_number ] = np .array ([w [0 ] - min ([x [0 ] for x in bboxes ['Woman' ][tracker_number ]]) for w in bboxes ['Woman' ][tracker_number ]])
384414 score ['y' ][tracker_number ] = np .array ([max ([x [1 ] for x in bboxes ['Woman' ][tracker_number ]]) - w [1 ] for w in bboxes ['Woman' ][tracker_number ]])
385415
386- def get_mean (item , number_of_trackers ) -> list :
387- if number_of_trackers == 1 :
388- return item [0 ] if len (item ) > 0 else []
389- else :
390- max_frame_number = max ([len (item [i ]) for i in range (number_of_trackers )])
391- arr = np .ma .empty ((max_frame_number ,number_of_trackers ))
392- arr .mask = True
393- for tracker_number in range (number_of_trackers ):
394- arr [:item [tracker_number ].shape [0 ],tracker_number ] = item [tracker_number ]
395- return list (filter (None .__ne__ , arr .mean (axis = 1 ).tolist ()))
416+ self .logger .info ("Merge Scores" )
417+ pool , handle = {}, {}
418+ for metric in score .keys ():
419+ pool [metric ] = mp .Pool (1 )
420+ handle [metric ] = pool [metric ].starmap_async (merge_score , [(score [metric ], self .params .number_of_trackers )])
421+
422+ for metric in score .keys ():
423+ score [metric ] = handle [metric ].get ()[0 ]
424+ pool [metric ].close ()
396425
397- self .score ['x' ] = sp .scale_signal (get_mean (score ['x' ], self .params .number_of_trackers ), 0 , 100 )
398- self .score ['y' ] = sp .scale_signal (get_mean (score ['y' ], self .params .number_of_trackers ), 0 , 100 )
399- self .score ['distance' ] = sp .scale_signal (get_mean (score ['distance' ], self .params .number_of_trackers ), 0 , 100 )
400- self .score ['roll' ] = sp .scale_signal (get_mean (score ['roll' ], self .params .number_of_trackers ), 0 , 100 )
426+ self .logger .info ("Scale Score to 0 - 100" )
427+ for metric in score .keys ():
428+ self .score [metric ] = sp .scale_signal (score [metric ], 0 , 100 )
401429
402430
403431 def scale_score (self , status : str , metric : str = 'y' ) -> None :
@@ -456,6 +484,7 @@ def scale_score(self, status: str, metric : str = 'y') -> None:
456484 desired_min = 0
457485 desired_max = 99
458486
487+ self .logger .info ("Scale score %s to user input" , metric )
459488 self .score [metric ] = sp .scale_signal (self .score [metric ], desired_min , desired_max )
460489
461490
@@ -959,12 +988,11 @@ def tracking(self) -> str:
959988
960989 self .__show_loading_screen (first_frame .shape )
961990 self .logger .info ("Raw tracking data: %d Tracking points for %d seconds of the video" , len (bboxes ["Woman" ]), int (len (bboxes ["Woman" ])* (self .params .skip_frames + 1 )/ self .video_info .fps ))
962- bboxes = self .correct_bboxes (bboxes , delete_last_predictions )
963991 video .stop ()
992+ bboxes = self .correct_bboxes (bboxes , delete_last_predictions )
964993 self .logger .info (status )
965994 self .logger .info ('Interpolate tracking boxes' )
966995 interpolated_bboxes = self .interpolate_bboxes (bboxes )
967- self .logger .info ('Calculate score' )
968996 self .calculate_score (interpolated_bboxes )
969997 return status
970998
@@ -1161,7 +1189,6 @@ def run(self) -> None:
11611189 json .dump (self .score , f )
11621190
11631191 if len (self .score [self .params .metric ]) >= HYPERPARAMETER ['min_frames' ]:
1164- self .logger .info ("Scale score" )
11651192 self .scale_score (status , metric = self .params .metric )
11661193
11671194 if len (self .score [self .params .metric ]) < HYPERPARAMETER ['min_frames' ]:
0 commit comments