Spaces:
Running on Zero
Running on Zero
Commit ·
0b5792e
1
Parent(s): 8ea1ec9
disappeared object appears in fresh trai
Browse files
app.py
CHANGED
|
@@ -131,10 +131,12 @@ def format_points_list(points, is_video=False):
|
|
| 131 |
return "[" + ", ".join(rows) + "]"
|
| 132 |
|
| 133 |
|
| 134 |
-
def _interpolate_keyframes(keyframes, total_frames):
|
| 135 |
"""Linearly interpolate positions between keyframes.
|
| 136 |
|
| 137 |
keyframes: sorted list of (frame_idx, x, y)
|
|
|
|
|
|
|
| 138 |
Returns dict {frame_idx: (x, y)} for every frame from first to last keyframe.
|
| 139 |
"""
|
| 140 |
if not keyframes:
|
|
@@ -146,7 +148,7 @@ def _interpolate_keyframes(keyframes, total_frames):
|
|
| 146 |
if i + 1 < len(keyframes):
|
| 147 |
nf, nx, ny = keyframes[i + 1]
|
| 148 |
span = nf - f_idx
|
| 149 |
-
if span > 1:
|
| 150 |
for t in range(1, span):
|
| 151 |
alpha = t / span
|
| 152 |
positions[f_idx + t] = (x + alpha * (nx - x), y + alpha * (ny - y))
|
|
@@ -178,9 +180,10 @@ def create_annotated_video(video_path, points, metadata, tracking):
|
|
| 178 |
total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
|
| 179 |
obj_positions = {}
|
| 180 |
obj_keyframe_set = {}
|
|
|
|
| 181 |
for obj_id, kfs in obj_keyframes.items():
|
| 182 |
kfs.sort(key=lambda k: k[0])
|
| 183 |
-
obj_positions[obj_id] = _interpolate_keyframes(kfs, total_frames)
|
| 184 |
raw_kf = set(f_idx for f_idx, _, _ in kfs)
|
| 185 |
obj_keyframe_set[obj_id] = set(
|
| 186 |
f for kf in raw_kf for f in range(kf - KEYFRAME_HOLD_FRAMES, kf + KEYFRAME_HOLD_FRAMES + 1)
|
|
@@ -203,6 +206,9 @@ def create_annotated_video(video_path, points, metadata, tracking):
|
|
| 203 |
for obj_id, positions in obj_positions.items():
|
| 204 |
if current_frame in positions:
|
| 205 |
px, py = positions[current_frame]
|
|
|
|
|
|
|
|
|
|
| 206 |
obj_history[obj_id].append((px, py))
|
| 207 |
if len(obj_history[obj_id]) > trail_length:
|
| 208 |
obj_history[obj_id] = obj_history[obj_id][-trail_length:]
|
|
|
|
| 131 |
return "[" + ", ".join(rows) + "]"
|
| 132 |
|
| 133 |
|
| 134 |
+
def _interpolate_keyframes(keyframes, total_frames, max_gap=None):
|
| 135 |
"""Linearly interpolate positions between keyframes.
|
| 136 |
|
| 137 |
keyframes: sorted list of (frame_idx, x, y)
|
| 138 |
+
max_gap: if set, skip interpolation (leave gap invisible) when two keyframes
|
| 139 |
+
are more than this many frames apart.
|
| 140 |
Returns dict {frame_idx: (x, y)} for every frame from first to last keyframe.
|
| 141 |
"""
|
| 142 |
if not keyframes:
|
|
|
|
| 148 |
if i + 1 < len(keyframes):
|
| 149 |
nf, nx, ny = keyframes[i + 1]
|
| 150 |
span = nf - f_idx
|
| 151 |
+
if span > 1 and (max_gap is None or span <= max_gap):
|
| 152 |
for t in range(1, span):
|
| 153 |
alpha = t / span
|
| 154 |
positions[f_idx + t] = (x + alpha * (nx - x), y + alpha * (ny - y))
|
|
|
|
| 180 |
total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
|
| 181 |
obj_positions = {}
|
| 182 |
obj_keyframe_set = {}
|
| 183 |
+
max_gap_frames = int(fps) # gaps > 1 second: no interpolation, object disappears
|
| 184 |
for obj_id, kfs in obj_keyframes.items():
|
| 185 |
kfs.sort(key=lambda k: k[0])
|
| 186 |
+
obj_positions[obj_id] = _interpolate_keyframes(kfs, total_frames, max_gap=max_gap_frames)
|
| 187 |
raw_kf = set(f_idx for f_idx, _, _ in kfs)
|
| 188 |
obj_keyframe_set[obj_id] = set(
|
| 189 |
f for kf in raw_kf for f in range(kf - KEYFRAME_HOLD_FRAMES, kf + KEYFRAME_HOLD_FRAMES + 1)
|
|
|
|
| 206 |
for obj_id, positions in obj_positions.items():
|
| 207 |
if current_frame in positions:
|
| 208 |
px, py = positions[current_frame]
|
| 209 |
+
# Clear trail if the object was absent in the previous frame (gap reappearance)
|
| 210 |
+
if current_frame > 0 and (current_frame - 1) not in positions:
|
| 211 |
+
obj_history[obj_id] = []
|
| 212 |
obj_history[obj_id].append((px, py))
|
| 213 |
if len(obj_history[obj_id]) > trail_length:
|
| 214 |
obj_history[obj_id] = obj_history[obj_id][-trail_length:]
|