@@ -160,6 +160,48 @@ def interpolate_bboxes(self, bboxes :dict) -> dict:
160160 return interpolated_bboxes
161161
162162
163+ @staticmethod
164+ def clamp (val : float , min_value : float , max_value : float ) -> float :
165+ """ limit a value in a given range
166+
167+ Args:
168+ val (float): input value
169+ min_value (float): min allowed value
170+ max_value (float): max allowed value
171+
172+ Returns:
173+ float: clamp value
174+ """
175+ return max (min (val , max_value ), min_value )
176+
177+
178+ def get_dick_pos (self , max_distance_frame_num : int ) -> dict :
179+ """ Get Start and End points of the dick
180+
181+ Args:
182+ max_distance_frame_num (int): absolute frame number with max tracker distance
183+
184+ Returns:
185+ dict: dick points
186+ """
187+ max_distance_frame = FFmpegStream .get_frame (self .params .video_path , max_distance_frame_num )
188+ max_distance_frame = FFmpegStream .get_projection (max_distance_frame , self .projection_config )
189+ frame_h , frame_w = max_distance_frame .shape [:2 ]
190+ center_line = self .ui .line_selector (max_distance_frame , "draw line on center of dick" )
191+
192+ # last idx: 0 = x, 1 = y
193+ dick_pos = { 'w' : center_line [1 ], 'm' : center_line [0 ] } \
194+ if center_line [0 ][0 ] > center_line [1 ][0 ] \
195+ else { 'w' : center_line [0 ], 'm' : center_line [1 ] }
196+
197+ # TODO: dividor is an hyperparameter
198+ dx = (dick_pos ['m' ][0 ] - dick_pos ['w' ][0 ]) / 8
199+ dy = (dick_pos ['m' ][1 ] - dick_pos ['w' ][1 ]) / 8
200+ return {
201+ 'w' : (self .clamp (dick_pos ['w' ][0 ] - dx , 0 , frame_w - 1 ), self .clamp (dick_pos ['w' ][1 ] - dy , 0 , frame_h - 1 )),
202+ 'm' : (self .clamp (dick_pos ['m' ][0 ] + dx , 0 , frame_w - 1 ), self .clamp (dick_pos ['m' ][1 ] + dy , 0 , frame_h - 1 ))
203+ }
204+
163205
164206 def calculate_score (self , bboxes ) -> None :
165207 """ Calculate the score for the predicted tracking boxes
@@ -176,6 +218,9 @@ def calculate_score(self, bboxes) -> None:
176218 'distance' : [np .array ([]) for _ in range (self .params .number_of_trackers )],
177219 'roll' : [[] for _ in range (self .params .number_of_trackers )]
178220 }
221+
222+ dick_pos = None
223+
179224 self .logger .info ("Calculate score for %d Tracker(s)" , self .params .number_of_trackers )
180225 for tracker_number in range (self .params .number_of_trackers ):
181226 woman_center = [self .get_center (item ) for item in bboxes ['Woman' ][tracker_number ]]
@@ -189,9 +234,18 @@ def calculate_score(self, bboxes) -> None:
189234 score ['distance' ][tracker_number ] = np .array ([np .sqrt (np .sum ((np .array (m ) - np .array (w )) ** 2 , axis = 0 )) \
190235 for w , m in zip (woman_center , men_center )])
191236
237+ if dick_pos is None :
238+ max_distance_frame_num = np .argmax (np .array ([abs (x ) for x in score ['distance' ][tracker_number ]])) + self .params .start_frame
239+ dick_pos = self .get_dick_pos (max_distance_frame_num )
240+ dick_pos ['idx' ] = max_distance_frame_num - self .params .start_frame
241+
242+ roll_woman_offset = (dick_pos ['w' ][0 ] - woman_center [dick_pos ['idx' ]][0 ], dick_pos ['w' ][1 ] - woman_center [dick_pos ['idx' ]][1 ])
243+ roll_men_offset = (dick_pos ['m' ][0 ] - woman_center [dick_pos ['idx' ]][0 ], dick_pos ['m' ][1 ] - woman_center [dick_pos ['idx' ]][1 ])
244+ self .logger .info ('use roll offset w = %s, m = %s' , str (roll_woman_offset ), str (roll_men_offset ))
245+
192246 for i in range ( min (( len (men_center ), len (woman_center ) )) ):
193- x = woman_center [i ][0 ] - men_center [i ][0 ]
194- y = men_center [i ][1 ] - woman_center [i ][1 ]
247+ x = woman_center [i ][0 ] + roll_woman_offset [ 0 ] - ( men_center [i ][0 ] + roll_men_offset [ 0 ])
248+ y = men_center [i ][1 ] + roll_men_offset [ 1 ] - ( woman_center [i ][1 ] + roll_woman_offset [ 1 ])
195249 if x >= 0 and y >= 0 :
196250 score ['roll' ][tracker_number ].append (np .arctan (np .array (y / max ((10e-3 , x )))))
197251 elif x >= 0 and y < 0 :
@@ -270,15 +324,6 @@ def scale_score(self, status: str, metric : str = 'y') -> None:
270324 imgMin = FFmpegStream .get_projection (imgMin , self .projection_config )
271325 imgMax = FFmpegStream .get_projection (imgMax , self .projection_config )
272326
273- if metric == 'roll' :
274- max_distance_frame_num = np .argmax (np .array ([abs (x ) for x in self .score ['distance' ]])) + self .params .start_frame
275- max_distance_frame = FFmpegStream .get_frame (self .params .video_path , max_distance_frame_num )
276- max_distance_frame = FFmpegStream .get_projection (max_distance_frame , self .projection_config )
277- center_line = self .ui .line_selector (max_distance_frame , "draw line on center of dick" )
278- max_distance_roll_score = self .score ['roll' ][max_distance_frame_num - self .params .start_frame ]
279- print ('center line' , center_line )
280- # TODO calc angel of line and apply max_distance_roll_score to get real center offset and appl offset to all items in roll score
281-
282327 min_tracking_points = self .get_tracking_points_by_frame_number (min_frame - self .params .start_frame )
283328 max_tracking_points = self .get_tracking_points_by_frame_number (max_frame - self .params .start_frame )
284329
@@ -290,7 +335,6 @@ def scale_score(self, status: str, metric : str = 'y') -> None:
290335
291336 # print('min_tracking_points', min_tracking_points, 'max_tracking_points', max_tracking_points)
292337
293-
294338 (desired_min , desired_max ) = self .ui .min_max_selector (
295339 image_min = imgMin ,
296340 image_max = imgMax ,
@@ -307,7 +351,7 @@ def scale_score(self, status: str, metric : str = 'y') -> None:
307351
308352 self .logger .info ("Scale score %s to user input" , metric )
309353
310- if False and metric == 'roll' :
354+ if metric == 'roll' :
311355 self .score [metric ] = Signal .scale_with_center (self .score [metric ], desired_min , desired_max , 50 )
312356 else :
313357 self .score [metric ] = Signal .scale (self .score [metric ], desired_min , desired_max )
0 commit comments