10 Commits

2 changed files with 60 additions and 53 deletions

View File

@@ -2,7 +2,7 @@ import argparse
from tsmark.video_annotator import Marker from tsmark.video_annotator import Marker
VERSION = "0.7.13" VERSION = "0.7.15"
class SmartFormatter(argparse.HelpFormatter): class SmartFormatter(argparse.HelpFormatter):

View File

@@ -710,7 +710,6 @@ class Marker:
self.points[self.point_index][self.nr]["y0"] = int(curr_point["cy"] - new_hh) self.points[self.point_index][self.nr]["y0"] = int(curr_point["cy"] - new_hh)
self.points[self.point_index][self.nr]["x1"] = int(curr_point["cx"] + new_wh) self.points[self.point_index][self.nr]["x1"] = int(curr_point["cx"] + new_wh)
self.points[self.point_index][self.nr]["y1"] = int(curr_point["cy"] + new_hh) self.points[self.point_index][self.nr]["y1"] = int(curr_point["cy"] + new_hh)
self.points[self.point_index][self.nr]["visible"] = POINT_VISIBILITY[0]
self.interpolate_set(self.point_index, self.nr) self.interpolate_set(self.point_index, self.nr)
def toggle_point_visibility(self): def toggle_point_visibility(self):
@@ -814,7 +813,7 @@ class World:
return True return True
return False return False
def interpolate_set(self, point_index=None, nr=None): def interpolate_set(self, point_index=None, nr=None, refresh=False):
if point_index is None: if point_index is None:
point_index = self.point_index point_index = self.point_index
@@ -823,6 +822,11 @@ class World:
if not point_index in self.points_interpolation_required: if not point_index in self.points_interpolation_required:
self.points_interpolation_required[point_index] = [] self.points_interpolation_required[point_index] = []
self.points_interpolation_required[point_index].append(nr) self.points_interpolation_required[point_index].append(nr)
if refresh:
# refresh all points
if point_index in self.points:
self.points_interpolation_required[point_index].extend(list(self.points[point_index].keys()))
if not self.interpolate_thread_alive(): if not self.interpolate_thread_alive():
print("ERROR: Interpolator thread is not running!") print("ERROR: Interpolator thread is not running!")
self.interpolate_thread_start() self.interpolate_thread_start()
@@ -837,6 +841,7 @@ class World:
if point_index is None: if point_index is None:
point_index = self.point_index point_index = self.point_index
if not point_index in self.points: if not point_index in self.points:
self.points_interpolation_required[point_index] = []
return return
try: try:
@@ -844,13 +849,25 @@ class World:
return {"x0": x0, "y0": y0, "x1": x1, "y1": y1, "type": t, "visible": visible, "age": age} return {"x0": x0, "y0": y0, "x1": x1, "y1": y1, "type": t, "visible": visible, "age": age}
def point2array(p): def point2array(p):
return [p["x0"], p["y0"], p["x1"], p["y1"]] """cx, cy, w, h"""
return [
(p["x0"] + p["x1"]) / 2,
(p["y0"] + p["y1"]) / 2,
abs(p["x0"] - p["x1"]),
abs(p["y0"] - p["y1"]),
]
def tryadd(s, key, l): def array2point(a, visibility):
try: w2 = max(1, a[3] / 2)
s.add(l[key]) h2 = max(1, a[4] / 2)
except IndexError: return {
pass "x0": max(0, int(a[1] - w2)),
"y0": max(0, int(a[2] - h2)),
"x1": min(self.video_res[0] - 1, int(a[1] + w2)),
"y1": min(self.video_res[1] - 1, int(a[2] + h2)),
"type": "interp",
"visible": visible,
}
if point_index in self.points_interpolation_required: if point_index in self.points_interpolation_required:
seed_keys = ( seed_keys = (
@@ -866,6 +883,10 @@ class World:
new_points = {k: v for k, v in self.points_interpolated[point_index].items()} new_points = {k: v for k, v in self.points_interpolated[point_index].items()}
if len(self.points[point_index]) == 0: # no points yet
self.points_interpolation_required[point_index] = []
return
if len(self.points[point_index]) == 1: # only one point added if len(self.points[point_index]) == 1: # only one point added
key = list(self.points[point_index].keys())[0] key = list(self.points[point_index].keys())[0]
vals = self.points[point_index][key] vals = self.points[point_index][key]
@@ -881,40 +902,28 @@ class World:
global_point_keys = list(sorted(list(self.points[point_index].keys()))) global_point_keys = list(sorted(list(self.points[point_index].keys())))
if len(seed_keys) > 0: if len(seed_keys) > 0:
point_keys = set() point_indexes = []
min_seed = min(seed_keys) min_seed = min(seed_keys)
max_seed = max(seed_keys) max_seed = max(seed_keys)
min_found = False first_seed = None
max_found = False
for pi, nr in enumerate(global_point_keys): for pi, nr in enumerate(global_point_keys):
if not min_found: if nr >= min_seed and nr <= max_seed:
min_index = pi point_indexes.append(pi)
if not max_found: if nr > min_seed and first_seed is None:
max_index = pi first_seed = pi
if nr >= min_seed: point_indexes.append(pi)
min_found = True
if nr <= max_seed:
tryadd(point_keys, pi, global_point_keys)
if nr > max_seed: if nr > max_seed:
max_found = True
break break
if min_found: if len(point_indexes) == 0:
for shift in range(-3, 0): point_indexes.append(pi)
tryadd(point_keys, min_index + shift, global_point_keys) min_index = max(0, min(point_indexes) - 3)
if max_found: max_index = min(len(global_point_keys) - 1, max(point_indexes) + 3)
for shift in range(2): point_keys = [global_point_keys[pi] for pi in range(min_index, max_index + 1)]
tryadd(point_keys, max_index + shift, global_point_keys)
else:
for shift in range(-3, -1):
tryadd(point_keys, len(global_point_keys) + shift, global_point_keys)
point_keys = list(sorted(list(point_keys)))
else: else:
point_keys = global_point_keys point_keys = global_point_keys
xyxy = np.array([point2array(self.points[point_index][k]) for k in point_keys]).T xywh = np.array([point2array(self.points[point_index][k]) for k in point_keys]).T
spline = PchipInterpolator(point_keys, xyxy, axis=1) spline = PchipInterpolator(point_keys, xywh, axis=1)
start_key = min(global_point_keys) start_key = min(global_point_keys)
end_key = max(global_point_keys) + 1 end_key = max(global_point_keys) + 1
@@ -928,14 +937,7 @@ class World:
for row in np.vstack((t2, spline(t2))).T: for row in np.vstack((t2, spline(t2))).T:
if row[0] in point_keys: if row[0] in point_keys:
visible = self.points[point_index][row[0]]["visible"] visible = self.points[point_index][row[0]]["visible"]
new_points[row[0]] = { new_points[row[0]] = array2point(row, visible)
"type": "interp",
"x0": int(row[1]),
"y0": int(row[2]),
"x1": int(row[3]),
"y1": int(row[4]),
"visible": visible,
}
# post points # post points
global_last = self.points[point_index][max(global_point_keys)] global_last = self.points[point_index][max(global_point_keys)]
@@ -988,7 +990,7 @@ class World:
def interpolate_points_in_thread(self): def interpolate_points_in_thread(self):
self.points_interpolation_frequency = 1 self.points_interpolation_frequency = 0.5
while True: while True:
if self.points_interpolation_thread_exit: if self.points_interpolation_thread_exit:
@@ -998,6 +1000,8 @@ class World:
continue continue
for point_index in self.points_interpolation_required: for point_index in self.points_interpolation_required:
if self.points_interpolation_thread_exit:
return
if self.get_interpolation_required(point_index): if self.get_interpolation_required(point_index):
self.interpolate_points(point_index) self.interpolate_points(point_index)
@@ -1009,6 +1013,7 @@ class World:
self.points_interpolation_enabled = not self.points_interpolation_enabled self.points_interpolation_enabled = not self.points_interpolation_enabled
if self.points_interpolation_enabled: if self.points_interpolation_enabled:
self.interpolate_thread_start() self.interpolate_thread_start()
self.interpolate_set(refresh=True)
def draw_help(self, frame): def draw_help(self, frame):
@@ -1249,7 +1254,7 @@ class World:
) )
if not self.points[index][key].get("visible", "NA") in POINT_VISIBILITY: if not self.points[index][key].get("visible", "NA") in POINT_VISIBILITY:
self.points[index][key]["visible"] = POINT_VISIBILITY[0] self.points[index][key]["visible"] = POINT_VISIBILITY[0]
self.interpolate_set(index, key) self.interpolate_set(index, refresh=True)
print(f"Loaded points with index: {index}") print(f"Loaded points with index: {index}")
self.point_index = None self.point_index = None
@@ -1414,7 +1419,7 @@ class World:
self.frame_raw = frame self.frame_raw = frame
if ret == True: if ret == True:
read_fails = 0 read_fails = 0
draw_wait = 200 if self.paused or (self.paused and self.point_click == 0) else 1 draw_wait = 50 if self.paused or (self.paused and self.point_click == 0) else 1
if (not self.paused) or self.read_next: if (not self.paused) or self.read_next:
self.read_next = False self.read_next = False
@@ -1523,14 +1528,15 @@ class World:
elif k & 0xFF == ord("f"): # modify FPS elif k & 0xFF == ord("f"): # modify FPS
FPS_modifier = (FPS_modifier + 1) % len(FPS_modifiers) FPS_modifier = (FPS_modifier + 1) % len(FPS_modifiers)
self.add_message(f"Player speed {round(1/FPS_modifiers[FPS_modifier],2)}") self.add_message(f"Player speed {round(1/FPS_modifiers[FPS_modifier], 2)}")
elif k & 0xFF == ord("a"): # toggle crop offset elif k & 0xFF == ord("a"): # toggle crop offset
self.crop_click = 0 if self.crop_click == 1 else 1 self.crop_click = 0 if self.crop_click == 1 else 1
self.crop[2] = True self.crop[2] = True
elif k & 0xFF == ord("s"): # toggle crop size elif k & 0xFF == ord("s"): # toggle crop size
self.crop_click = 0 if self.crop_click == 2 else 2 self.crop_click = 0 if self.crop_click == 2 else 2
self.crop[2] = True self.crop[2] = True
elif k & 0xFF == ord("o"): # toggle point visibility (yes/occlusion/hidden) # toggle point visibility (yes/occlusion/hidden)
elif k & 0xFF == ord("o"):
if self.opts.output_points is not None: if self.opts.output_points is not None:
self.toggle_point_visibility() self.toggle_point_visibility()
elif k & 0xFF == ord("p"): # toggle points elif k & 0xFF == ord("p"): # toggle points
@@ -1561,6 +1567,7 @@ class World:
self.point_click = 0 self.point_click = 0
else: else:
self.point_index = chr(k2) self.point_index = chr(k2)
self.interpolate_set(point_index=self.point_index, refresh=True)
elif k & 0xFF == ord("g"): # Go to elif k & 0xFF == ord("g"): # Go to
self.shadow_text( self.shadow_text(
frame_visu, frame_visu,
@@ -1786,7 +1793,7 @@ class TrackerGUI:
cv2.rectangle(frame, p1, p2, color, thicc, 1) cv2.rectangle(frame, p1, p2, color, thicc, 1)
cv2.imshow("tsmark - tracker", frame) cv2.imshow("tsmark - tracker", frame)
# speed up fps by 2 # speed up fps by 2
time_to_wait = 0.2 if paused else (self.marker.viewer_spf / 2 - time.time() + show_time) time_to_wait = 0.05 if paused else (self.marker.viewer_spf / 2 - time.time() + show_time)
k = cv2.waitKey(max(1, int(time_to_wait * 1000))) k = cv2.waitKey(max(1, int(time_to_wait * 1000)))
if k & 0xFF == ord("q") or k & 0xFF == 13: # accept with q or enter if k & 0xFF == ord("q") or k & 0xFF == 13: # accept with q or enter
done = True done = True