Skip to content

Commit 9135ce6

Browse files
author
arch
committed
add plausibility check for trackers
1 parent d3f4944 commit 9135ce6

File tree

4 files changed

+80
-10
lines changed

4 files changed

+80
-10
lines changed

funscript_editor/algorithms/funscriptgenerator.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -736,9 +736,9 @@ def init_trackers(self, ffmpeg_stream: FFmpegStream) -> tuple:
736736
if StaticVideoTracker.is_bbox_in_tracking_area(bbox_woman, tracking_areas_woman[tracker_number]): break
737737
self.logger.error("Invalid supervised tracking area selected")
738738
preview_frame = self.draw_box(preview_frame, tracking_areas_woman[tracker_number], color=(0,255,0))
739-
trackers_woman[tracker_number] = StaticVideoTracker(first_frame, bbox_woman, supervised_tracking_area = tracking_areas_woman[tracker_number])
739+
trackers_woman[tracker_number] = StaticVideoTracker(first_frame, bbox_woman, self.video_info.fps, supervised_tracking_area = tracking_areas_woman[tracker_number])
740740
else:
741-
trackers_woman[tracker_number] = StaticVideoTracker(first_frame, bbox_woman)
741+
trackers_woman[tracker_number] = StaticVideoTracker(first_frame, bbox_woman, self.video_info.fps)
742742

743743
if tracker_number == 0:
744744
bboxes['Woman'][1] = { tracker_number: bbox_woman }
@@ -754,9 +754,9 @@ def init_trackers(self, ffmpeg_stream: FFmpegStream) -> tuple:
754754
if StaticVideoTracker.is_bbox_in_tracking_area(bbox_men, tracking_areas_men[tracker_number]): break
755755
self.logger.error("Invalid supervised tracking area selected")
756756
preview_frame = self.draw_box(preview_frame, tracking_areas_men[tracker_number], color=(255,0,255))
757-
trackers_men[tracker_number] = StaticVideoTracker(first_frame, bbox_men, supervised_tracking_area = tracking_areas_men[tracker_number])
757+
trackers_men[tracker_number] = StaticVideoTracker(first_frame, bbox_men, self.video_info.fps, supervised_tracking_area = tracking_areas_men[tracker_number])
758758
else:
759-
trackers_men[tracker_number] = StaticVideoTracker(first_frame, bbox_men)
759+
trackers_men[tracker_number] = StaticVideoTracker(first_frame, bbox_men, self.video_info.fps)
760760

761761
if tracker_number == 0:
762762
bboxes['Men'][1] = { tracker_number: bbox_men }

funscript_editor/algorithms/videotracker.py

Lines changed: 58 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from dataclasses import dataclass
99
from threading import Thread
1010
from queue import Queue
11-
from funscript_editor.utils.config import SETTINGS
11+
from funscript_editor.utils.config import SETTINGS, HYPERPARAMETER
1212

1313
import numpy as np
1414

@@ -21,6 +21,7 @@ class StaticVideoTracker:
2121
Args:
2222
first_frame (np.ndarray): open cv image representing the start frame
2323
tracking_bbox (tuple): tuple with (x,y,w,h) of the init tracking box
24+
fps (float): video fps
2425
limit_searchspace (dict) : only insert the specified region around the init box
2526
supervised_tracking_area (tuple, optional): tuple with (x,y,w,h) of the supervised tracking area
2627
queue_size (int): in (work) and out (result) queue size
@@ -29,20 +30,27 @@ class StaticVideoTracker:
2930
def __init__(self,
3031
first_frame: np.ndarray,
3132
tracking_bbox: tuple,
33+
fps: float,
3234
limit_searchspace : dict = {'h': 0.45, 'w':0.4},
3335
supervised_tracking_area: tuple = None,
3436
queue_size : int = 2):
3537
self.first_frame = first_frame
3638
self.limit_searchspace = limit_searchspace
3739
self.first_tracking_bbox = tracking_bbox
3840
self.supervised_tracking_area = supervised_tracking_area
41+
self.fps = max((1,fps))
3942
self.stopped = False
4043
self.sleep_time = 0.001
4144
self.queue_in = Queue(maxsize=queue_size)
4245
self.queue_out = Queue(maxsize=queue_size)
4346
self.thread = Thread(target=self.run, args=())
4447
self.thread.daemon = True
4548
self.thread.start()
49+
self.tracking_points = []
50+
self.tracking_counter = 0
51+
self.cluster_center = [0, 0]
52+
self.plausibility_thresholds = [0, 0]
53+
4654

4755

4856
__logger = logging.getLogger(__name__)
@@ -53,6 +61,7 @@ class Status:
5361
OK :str = "OK"
5462
TRACKING_LOST :str = "Tracking Lost"
5563
FEATURE_OUTSIDE :str = "Feature outside the specified area"
64+
IMPLAUSIBLE :str = "Tracking point is not plausible"
5665

5766

5867
@staticmethod
@@ -126,6 +135,47 @@ def __setup_tracker(self) -> None:
126135
self.tracker = cv2.TrackerCSRT_create()
127136

128137

138+
def __is_plausible(self, box) -> bool:
139+
tracking_init_phase_in_sec = HYPERPARAMETER['tracking_init_phase_in_sec']
140+
tracking_plausibility_factor_x = HYPERPARAMETER['tracking_plausibility_factor_x']
141+
tracking_plausibility_factor_y = HYPERPARAMETER['tracking_plausibility_factor_y']
142+
if self.tracking_counter <= round(self.fps * tracking_init_phase_in_sec):
143+
self.tracking_points.append([box[0] + box[2]/2, box[1] + box[3]/2])
144+
if self.tracking_counter == round(self.fps * tracking_init_phase_in_sec):
145+
self.__logger.info("Determine Plausibility Threshold for Tracker")
146+
self.cluster_center = np.mean(np.array(self.tracking_points), axis = 0)
147+
distances_x = [abs(self.cluster_center[0] - point[0]) for point in self.tracking_points]
148+
distances_y = [abs(self.cluster_center[1] - point[1]) for point in self.tracking_points]
149+
self.plausibility_thresholds = [ \
150+
max(distances_x) * tracking_plausibility_factor_x, \
151+
max(distances_y) * tracking_plausibility_factor_y \
152+
]
153+
else:
154+
point = [box[0] + box[2]/2, box[1] + box[3]/2]
155+
if abs(point[0] - self.cluster_center[0]) > self.plausibility_thresholds[0]:
156+
self.__logger.warning(
157+
"Tracking point x is not plausible (%d > %d +- %d)",
158+
round(point[0]),
159+
round(self.cluster_center[0]),
160+
round(self.plausibility_thresholds[0])
161+
)
162+
return False
163+
164+
if abs(point[1] - self.cluster_center[1]) > self.plausibility_thresholds[1]:
165+
self.__logger.warning(
166+
"Tracking point y is not plausible (%d > %d +- %d)",
167+
round(point[1]),
168+
round(self.cluster_center[1]),
169+
round(self.plausibility_thresholds[1])
170+
)
171+
return False
172+
173+
self.cluster_center[0] = (self.cluster_center[0] * self.tracking_counter + point[0]) / (self.tracking_counter + 1)
174+
self.cluster_center[1] = (self.cluster_center[1] * self.tracking_counter + point[1]) / (self.tracking_counter + 1)
175+
176+
return True
177+
178+
129179
def run(self) -> None:
130180
""" The Video Tracker Thread Function """
131181
self.__setup_tracker()
@@ -155,15 +205,18 @@ def run(self) -> None:
155205
frame = self.queue_in.get()
156206
frame_roi = frame[y0:y1, x0:x1]
157207
success, bbox = self.tracker.update(frame_roi)
208+
self.tracking_counter += 1
158209
status = StaticVideoTracker.Status.TRACKING_LOST
159-
if success:
210+
if not success or bbox is None:
211+
bbox = None
212+
else:
160213
status = StaticVideoTracker.Status.OK
161214
bbox = (int(bbox[0] + x0), int(bbox[1] + y0), int(bbox[2]), int(bbox[3]))
162215
if not StaticVideoTracker.is_bbox_in_tracking_area(bbox, self.supervised_tracking_area):
163216
status = StaticVideoTracker.Status.FEATURE_OUTSIDE
164-
bbox = None
165-
else:
166-
bbox = None
217+
elif SETTINGS['tracking_plausibility_check']:
218+
if not self.__is_plausible(bbox):
219+
status = StaticVideoTracker.Status.IMPLAUSIBLE
167220

168221
self.queue_out.put((status, bbox))
169222

funscript_editor/config/hyperparameter.yaml

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ user_reaction_time_in_milliseconds: 1000
3737
# Scene Detector #
3838
##################
3939

40-
# Specify the miniimum scene length in seconds
40+
# Specify the minimum scene length in seconds
4141
min_scene_len: 3
4242

4343
# Threshold value for the content detector to detect an scene change
@@ -47,6 +47,20 @@ scene_content_detector_threshold: 30.0
4747
scene_threshold_detector_threshold: 12
4848

4949

50+
###########
51+
# Tracker #
52+
###########
53+
54+
# Specify the init phase for the tracker (currently only used for the plausible check)
55+
tracking_init_phase_in_sec: 6
56+
57+
# plausiblity factor to veriify a correct tracking position
58+
tracking_plausibility_factor_x: 4.0
59+
60+
# plausiblity factor to veriify a correct tracking position
61+
tracking_plausibility_factor_y: 2.5
62+
63+
5064
##############################
5165
# VR Movement in y Direction #
5266
##############################

funscript_editor/config/settings.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,6 @@ additional_changepoints: True
3838

3939
# Force dark ui theme
4040
dark_theme: False
41+
42+
# enable the tracking plausiblity check
43+
tracking_plausibility_check: True

0 commit comments

Comments
 (0)