diff --git a/tsmark/__init__.py b/tsmark/__init__.py index 9565bb3..b157a89 100644 --- a/tsmark/__init__.py +++ b/tsmark/__init__.py @@ -2,7 +2,7 @@ import argparse from tsmark.video_annotator import Marker -VERSION = "0.7.14" +VERSION = "0.7.15" class SmartFormatter(argparse.HelpFormatter): diff --git a/tsmark/video_annotator.py b/tsmark/video_annotator.py index 3c618bc..baa9589 100755 --- a/tsmark/video_annotator.py +++ b/tsmark/video_annotator.py @@ -849,7 +849,25 @@ class World: return {"x0": x0, "y0": y0, "x1": x1, "y1": y1, "type": t, "visible": visible, "age": age} 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 array2point(a, visibility): + w2 = max(1, a[3] / 2) + h2 = max(1, a[4] / 2) + return { + "x0": int(a[1] - w2), + "y0": int(a[2] - h2), + "x1": int(a[1] + w2), + "y1": int(a[2] + h2), + "type": "interp", + "visible": visible, + } if point_index in self.points_interpolation_required: seed_keys = ( @@ -904,8 +922,8 @@ class World: else: point_keys = global_point_keys - xyxy = np.array([point2array(self.points[point_index][k]) for k in point_keys]).T - spline = PchipInterpolator(point_keys, xyxy, axis=1) + xywh = np.array([point2array(self.points[point_index][k]) for k in point_keys]).T + spline = PchipInterpolator(point_keys, xywh, axis=1) start_key = min(global_point_keys) end_key = max(global_point_keys) + 1 @@ -919,14 +937,7 @@ class World: for row in np.vstack((t2, spline(t2))).T: if row[0] in point_keys: visible = self.points[point_index][row[0]]["visible"] - new_points[row[0]] = { - "type": "interp", - "x0": int(row[1]), - "y0": int(row[2]), - "x1": int(row[3]), - "y1": int(row[4]), - "visible": visible, - } + new_points[row[0]] = array2point(row, visible) # post points global_last = self.points[point_index][max(global_point_keys)] @@ -1296,7 +1307,10 @@ class World: ffmpeg_args_print.append( arg.format( input=shlex.quote(src_name_print), - output=shlex.quote(f"{tgt_name_print}.trim.{from_str}-{to_str}"), + output=shlex.quote( + f"{tgt_name_print}.trim.{ + from_str}-{to_str}" + ), start_time=from_ft, end_time=to_ft, ) @@ -1304,7 +1318,8 @@ class World: ffmpeg_args.append( arg.format( input=self.opts.video, - output=f"{os.path.splitext(self.opts.video)[0]}.trim.{from_str}-{to_str}", + output=f"{os.path.splitext(self.opts.video)[0]}.trim.{ + from_str}-{to_str}", start_time=from_ft, end_time=to_ft, ) @@ -1517,14 +1532,18 @@ class World: elif k & 0xFF == ord("f"): # modify FPS 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 self.crop_click = 0 if self.crop_click == 1 else 1 self.crop[2] = True elif k & 0xFF == ord("s"): # toggle crop size self.crop_click = 0 if self.crop_click == 2 else 2 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: self.toggle_point_visibility() elif k & 0xFF == ord("p"): # toggle points @@ -1737,7 +1756,8 @@ class TrackerGUI: show_message = f"Tracking... ({i+1}/{max_frames})" else: # Tracking failure - show_message = f"Tracking failure detected ({i+1}/{max_frames})" + show_message = f"Tracking failure detected ({ + i+1}/{max_frames})" bbox = None if time.time() > show_time + visu_interval: