Skip to content

Commit 47d854e

Browse files
author
arch
committed
interpolate after tracking is completed
1 parent e9bb5d2 commit 47d854e

File tree

4 files changed

+32
-57
lines changed

4 files changed

+32
-57
lines changed

funscript_editor/algorithms/funscriptgenerator.py

Lines changed: 25 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -216,57 +216,24 @@ def get_average_tracking_fps(self) -> float:
216216
return sum(self.tracking_fps) / float(len(self.tracking_fps))
217217

218218

219-
def append_interpolated_bbox(self, bbox :tuple, target: str) -> None:
219+
def interpolate_bboxes(self, bboxes :dict) -> None:
220220
""" Interpolate tracking boxes for skiped frames
221221
222222
Args:
223-
bbox (tuple): the new tracking box (x,y,w,h)
224-
target (str): the target where to save the interpolated tracking boxes
223+
bboxes (dict): the new tracking box (x,y,w,h) in dict {Men: {frame_num: box, ...}, Woman: {frame_num: box, ...}}
225224
"""
226-
# TODO: interpolate after tracking when all data points are know
227-
if self.params.skip_frames > 0 and len(self.bboxes[target]) > 0:
228-
back_in_time = 2
229-
if len(self.bboxes[target]) < (self.params.skip_frames+1)*back_in_time:
230-
for i in range(1, self.params.skip_frames+1):
231-
# use linear interpolation for the first steps
232-
x0 = np.interp(i, [0, self.params.skip_frames+1], [self.bboxes[target][-1][0], bbox[0]])
233-
y0 = np.interp(i, [0, self.params.skip_frames+1], [self.bboxes[target][-1][1], bbox[1]])
234-
w = np.interp(i, [0, self.params.skip_frames+1], [self.bboxes[target][-1][2], bbox[2]])
235-
h = np.interp(i, [0, self.params.skip_frames+1], [self.bboxes[target][-1][3], bbox[3]])
236-
self.bboxes[target].append((x0, y0, w, h))
237-
else:
238-
# switch to quadratic interpolation as soon as there is enough data for interpolation
239-
x = [-1*(self.params.skip_frames+1)*back_in_time + x + 1 for x in range((self.params.skip_frames+1)*back_in_time)] \
240-
+ [self.params.skip_frames+1]
241-
242-
fx0 = interp1d(
243-
x,
244-
[item[0] for item in self.bboxes[target][-1*(self.params.skip_frames+1)*back_in_time:]] + [bbox[0]],
245-
kind = 'quadratic'
246-
)
247-
248-
fy0 = interp1d(
249-
x,
250-
[item[1] for item in self.bboxes[target][-1*(self.params.skip_frames+1)*back_in_time:]] + [bbox[1]],
251-
kind = 'quadratic'
252-
)
253-
254-
fw = interp1d(
255-
x,
256-
[item[2] for item in self.bboxes[target][-1*(self.params.skip_frames+1)*back_in_time:]] + [bbox[2]],
257-
kind = 'quadratic'
258-
)
259-
260-
fh = interp1d(
261-
x,
262-
[item[3] for item in self.bboxes[target][-1*(self.params.skip_frames+1)*back_in_time:]] + [bbox[3]],
263-
kind = 'quadratic'
264-
)
225+
for key in bboxes:
226+
x = [k for k in bboxes[key].keys()]
227+
boxes = [v for v in bboxes[key].values()]
228+
if len(boxes) == 0: continue
265229

266-
for i in range(1, self.params.skip_frames+1):
267-
self.bboxes[target].append((float(fx0(i)), float(fy0(i)), float(fw(i)), float(fh(i))))
230+
fx0 = interp1d(x, [item[0] for item in boxes], kind = 'cubic')
231+
fy0 = interp1d(x, [item[1] for item in boxes], kind = 'cubic')
232+
fw = interp1d(x, [item[2] for item in boxes], kind = 'quadratic')
233+
fh = interp1d(x, [item[3] for item in boxes], kind = 'quadratic')
268234

269-
self.bboxes[target].append(bbox)
235+
for i in range(min(x), max(x)+1):
236+
self.bboxes[key].append((float(fx0(i)), float(fy0(i)), float(fw(i)), float(fh(i))))
270237

271238

272239
def min_max_selector(self,
@@ -661,15 +628,20 @@ def tracking(self) -> str:
661628
start_frame = self.params.start_frame
662629
)
663630

631+
bboxes = {
632+
'Men': {},
633+
'Woman': {}
634+
}
635+
664636
first_frame = video.read()
665637
bboxWoman = self.get_bbox(first_frame, "Select Woman Feature")
666638
trackerWoman = StaticVideoTracker(first_frame, bboxWoman)
667-
self.bboxes['Woman'].append(bboxWoman)
639+
bboxes['Woman'][1] = bboxWoman
668640

669641
if self.params.track_men:
670642
bboxMen = self.get_bbox(self.drawBox(first_frame, bboxWoman), "Select Men Feature")
671643
trackerMen = StaticVideoTracker(first_frame, bboxMen)
672-
self.bboxes['Men'].append(bboxMen)
644+
bboxes['Men'][1] = bboxMen
673645

674646
if self.params.max_playback_fps > (self.params.skip_frames+1):
675647
cycle_time_in_ms = (float(1000) / float(self.params.max_playback_fps)) * (self.params.skip_frames+1)
@@ -703,12 +675,12 @@ def tracking(self) -> str:
703675
if last_frame is not None:
704676
# Process data from last step while the next tracking points get predicted.
705677
# This should improve the whole processing speed, because the tracker run in a seperate thread
706-
self.append_interpolated_bbox(bboxWoman, 'Woman')
707-
last_frame = self.drawBox(last_frame, self.bboxes['Woman'][-1])
678+
bboxes['Woman'][frame_num-1] = bboxWoman
679+
last_frame = self.drawBox(last_frame, bboxes['Woman'][frame_num-1])
708680

709681
if self.params.track_men:
710-
self.append_interpolated_bbox(bboxMen, 'Men')
711-
last_frame = self.drawBox(last_frame, self.bboxes['Men'][-1])
682+
bboxes['Men'][frame_num-1] = bboxMen
683+
last_frame = self.drawBox(last_frame, bboxes['Men'][frame_num-1])
712684

713685
last_frame = self.drawFPS(last_frame)
714686
cv2.putText(last_frame, "Press 'q' if the tracking point shifts or a video cut occured",
@@ -742,6 +714,8 @@ def tracking(self) -> str:
742714

743715
video.stop()
744716
self.logger.info(status)
717+
self.logger.info('Interpolate tracking boxes')
718+
self.interpolate_bboxes(bboxes)
745719
self.logger.info('Calculate score')
746720
self.calculate_score()
747721
return status

funscript_editor/algorithms/signalprocessing.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ def scale_signal_with_anomalies(
3636
Returns:
3737
list: list with scaled signal
3838
"""
39+
if len(signal) == 0: return signal
3940
a1 = np.quantile(signal, lower_quantile)
4041
a2 = np.quantile(signal, upper_quantile)
4142
anomaly_free = np.array([x for x in signal if a1 < x < a2])
@@ -93,8 +94,8 @@ def get_local_max_and_min_idx(score :list, fps: int, shift_min :int = 0, shift_m
9394
changepoints['max'].append(tmp_max_idx)
9495
tmp_max_idx = -1
9596

96-
delta_max = (max(score) - min(score)) * 0.01 * min((10.0, float(HYPERPARAMETER['local_max_delta_in_percent']) ))
97-
delta_min = (max(score) - min(score)) * 0.01 * min((10.0, float(HYPERPARAMETER['local_min_delta_in_percent']) ))
97+
delta_max = (max(score) - min(score)) * 0.01 * min((10.0, float(HYPERPARAMETER['local_max_delta_in_percent'])))
98+
delta_min = (max(score) - min(score)) * 0.01 * min((10.0, float(HYPERPARAMETER['local_min_delta_in_percent'])))
9899

99100
# shift points to the real change points
100101
for k, idx in enumerate(changepoints['min']):
@@ -109,7 +110,7 @@ def get_local_max_and_min_idx(score :list, fps: int, shift_min :int = 0, shift_m
109110
new_pos += 1
110111
changepoints['max'][k] = new_pos
111112

112-
# apply shift
113+
# apply manual shift
113114
if shift_min != 0:
114115
for k, idx in enumerate(changepoints['min']):
115116
changepoints['min'][k] = max((0, min((len(score)-1, idx+shift_min)) ))

funscript_editor/algorithms/videotracker.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
class StaticVideoTracker:
1313
"""
1414
Video tracker for static feature tracking. We assume that the tracked feature is always in
15-
the neighborhood fo the first tracking box. This allows an accelerated prediction.
15+
the neighborhood to the first tracking box. This allows an accelerated prediction.
1616
1717
1818
Args:

funscript_editor/config/hyperparameter.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ skip_frames: 1
1414
avg_sec_for_local_min_max_extraction: 2.0
1515

1616
# Specify the maximum deviation for a max point in percent
17-
local_max_delta_in_percent: 1.25
17+
local_max_delta_in_percent: 0.5
1818

1919
# Specify the maximum deviation for a min point in percent
20-
local_min_delta_in_percent: 1.25
20+
local_min_delta_in_percent: 0.5
2121

2222
# Specify the minimum required frames for the tracking. Wee need this parameter to
2323
# ensure there is at leas two strokes in the tracking result.

0 commit comments

Comments
 (0)