Skip to content

Commit 60b5416

Browse files
author
arch
committed
implement missing part for supervised ignore tracking
1 parent 24eb43b commit 60b5416

File tree

1 file changed

+135
-5
lines changed

1 file changed

+135
-5
lines changed

funscript_editor/algorithms/videotracker.py

Lines changed: 135 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ def __init__(self,
5050
self.logger = logging.getLogger(__name__)
5151
self.params = StaticVideoTrackerParameter()
5252
self.first_frame = first_frame
53+
self.frame_heigt, self.frame_width = first_frame.shape[:2]
5354
self.limit_searchspace = limit_searchspace
5455
self.first_tracking_bbox = tracking_bbox
5556
self.supervised_tracking_area = supervised_tracking_area
@@ -69,6 +70,7 @@ def __init__(self,
6970
self.lats_detected_tracking_box = tracking_bbox
7071
self.last_valid_tracking_box = tracking_bbox
7172
self.supervised_tracking_is_exit_condition = supervised_tracking_is_exit_condition
73+
self.last_box_was_in_tracking_area = True
7274

7375

7476
@dataclass
@@ -227,6 +229,129 @@ def create_tracking_box(box: tuple):
227229
return (box[0], box[1], box[2], box[3], center[0], center[1])
228230

229231

232+
def move_box_by(self, box: tuple, x0: int, y0: int) -> tuple:
233+
""" Move box by given (x, y)
234+
235+
Args:
236+
box: the tracking box
237+
x0: shift value in x direction
238+
y0: shift value in y direction
239+
"""
240+
return (
241+
min(( self.frame_width, max((0, box[0] + x0)) )),
242+
min(( self.frame_heigt, max((0, box[1] + y0)) )),
243+
box[2],
244+
box[3],
245+
min(( self.frame_width, max((0, box[4] + x0)) )),
246+
min(( self.frame_heigt, max((0, box[5] + y0)) ))
247+
)
248+
249+
250+
def move_box_to(self, box: tuple, cx: int, cy: int) -> tuple:
251+
""" Move box to given (x, y) center coordinates
252+
253+
Args:
254+
box: the tracking box
255+
x0: shift value in x direction
256+
y0: shift value in y direction
257+
"""
258+
return self.move_box_by(box, cx - box[4], cy - box[5])
259+
260+
261+
@staticmethod
262+
def get_line_intersection(line1, line2):
263+
""" Compute the intersection point of two lines
264+
265+
Args:
266+
line1 (list): [[x1,y1], [x2,y2]]
267+
line2 (list): [[x1,y1], [x2,y2]]
268+
269+
Returns:
270+
tuple: (x, y)
271+
"""
272+
xdiff = (line1[0][0] - line1[1][0], line2[0][0] - line2[1][0])
273+
ydiff = (line1[0][1] - line1[1][1], line2[0][1] - line2[1][1])
274+
275+
def det(a, b):
276+
return a[0] * b[1] - a[1] * b[0]
277+
278+
div = det(xdiff, ydiff)
279+
if div == 0:
280+
return None
281+
282+
d = (det(*line1), det(*line2))
283+
x = det(d, xdiff) / div
284+
y = det(d, ydiff) / div
285+
return (round(x), round(y))
286+
287+
288+
def get_border_box(self, last_valid_box, invalid_box) -> tuple:
289+
""" Calculate the intersection with the tracking area to predict a box exacly
290+
at the border of the tracking area.
291+
292+
Args:
293+
last_valid_box (tuple): last valid tracking box
294+
invert_box (tuple): box that is outside the tracking area
295+
296+
Returns:
297+
tuple: border box
298+
"""
299+
if invalid_box is None:
300+
return last_valid_box
301+
302+
if self.supervised_tracking_area is None:
303+
return last_valid_box
304+
305+
x0 = self.supervised_tracking_area[0]
306+
y0 = self.supervised_tracking_area[1]
307+
x1 = self.supervised_tracking_area[0] + self.supervised_tracking_area[2]
308+
y1 = self.supervised_tracking_area[1] + self.supervised_tracking_area[3]
309+
310+
# left top point
311+
if invalid_box[4] < x0 and invalid_box[5] < y0:
312+
return self.move_box_to(invalid_box, x0, y0)
313+
314+
# left bottom point
315+
if invalid_box[4] < x0 and invalid_box[5] > y1:
316+
return self.move_box_to(invalid_box, x0, y1)
317+
318+
# left bottom point
319+
if invalid_box[4] > x1 and invalid_box[5] > y1:
320+
return self.move_box_to(invalid_box, x1, y1)
321+
322+
# right top point
323+
if invalid_box[4] > x1 and invalid_box[5] < y0:
324+
return self.move_box_to(invalid_box, x1, y0)
325+
326+
line1 = [ [invalid_box[4], invalid_box[5]], [last_valid_box[4], last_valid_box[5]] ]
327+
328+
# left
329+
if invalid_box[4] <= x0:
330+
intersection = self.get_line_intersection(line1, [ [x0, y0], [x0, y1] ])
331+
if intersection:
332+
return self.move_box_to(invalid_box, intersection[0], intersection[1])
333+
334+
# bottom
335+
if invalid_box[5] >= y1:
336+
intersection = self.get_line_intersection(line1, [ [x0, y1], [x1, y1] ])
337+
if intersection:
338+
return self.move_box_to(invalid_box, intersection[0], intersection[1])
339+
340+
# right
341+
if invalid_box[4] >= x1:
342+
intersection = self.get_line_intersection(line1, [ [x1, y1], [x1, y0] ])
343+
if intersection:
344+
return self.move_box_to(invalid_box, intersection[0], intersection[1])
345+
346+
# top
347+
if invalid_box[5] <= y0:
348+
intersection = self.get_line_intersection(line1, [ [x1, y0], [x0, y0] ])
349+
if intersection:
350+
return self.move_box_to(invalid_box, intersection[0], intersection[1])
351+
352+
return last_valid_box
353+
354+
230355
def run(self) -> None:
231356
""" The Video Tracker Thread Function """
232357
self.__setup_tracker()
@@ -276,14 +401,19 @@ def run(self) -> None:
276401
if self.params.tracking_plausibility_check:
277402
if not self.__is_plausible(bbox):
278403
status = StaticVideoTracker.Status.IMPLAUSIBLE
279-
elif not StaticVideoTracker.is_bbox_in_tracking_area(bbox, self.supervised_tracking_area):
404+
elif StaticVideoTracker.is_bbox_in_tracking_area(bbox, self.supervised_tracking_area):
405+
self.last_box_was_in_tracking_area = True
406+
else:
280407
if self.supervised_tracking_is_exit_condition:
281408
status = StaticVideoTracker.Status.FEATURE_OUTSIDE
282409
else:
283-
bbox = self.last_valid_tracking_box
284-
elif self.supervised_tracking_area is not None and not self.supervised_tracking_is_exit_condition:
285-
# TODO: When we insert the tracking area again make sure the point is below/above the last valid box
286-
pass
410+
if self.last_box_was_in_tracking_area:
411+
self.last_box_was_in_tracking_area = False
412+
self.last_valid_tracking_box = self.get_border_box(self.last_valid_tracking_box, bbox)
413+
self.logger.info("Determine Border Intersection with box: %s", str(self.last_valid_tracking_box))
414+
bbox = self.last_valid_tracking_box
415+
else:
416+
bbox = self.last_valid_tracking_box
287417

288418

289419
self.queue_out.put((status, bbox))

0 commit comments

Comments
 (0)