Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
|
@@ -27,10 +27,6 @@ MIN_REP_SECONDS = 0.33
|
|
| 27 |
# Prevents very long false reps when tracking fails.
|
| 28 |
MAX_REP_SECONDS = 8.0
|
| 29 |
|
| 30 |
-
# Downscale only (no crop) for YOLO inference
|
| 31 |
-
# 640 is a safe default across varying camera angles.
|
| 32 |
-
MAX_INFER_SIDE = 640
|
| 33 |
-
|
| 34 |
|
| 35 |
# ----------------------------
|
| 36 |
# Load YOLO pose model (lazy)
|
|
@@ -106,17 +102,6 @@ def likelihood_to_score(p):
|
|
| 106 |
return int(round(s_lo + t * (s_hi - s_lo)))
|
| 107 |
return 0
|
| 108 |
|
| 109 |
-
def resize_for_inference(frame, max_side=640):
|
| 110 |
-
"""Downscale only (no crop) to speed YOLO. Keeps aspect ratio."""
|
| 111 |
-
h, w = frame.shape[:2]
|
| 112 |
-
m = max(h, w)
|
| 113 |
-
if m <= max_side:
|
| 114 |
-
return frame
|
| 115 |
-
scale = max_side / float(m)
|
| 116 |
-
new_w = int(round(w * scale))
|
| 117 |
-
new_h = int(round(h * scale))
|
| 118 |
-
return cv2.resize(frame, (new_w, new_h), interpolation=cv2.INTER_AREA)
|
| 119 |
-
|
| 120 |
|
| 121 |
# ----------------------------
|
| 122 |
# Core pipeline
|
|
@@ -146,8 +131,7 @@ def analyze_pushup_video_yolo(video_path: str, out_dir: str):
|
|
| 146 |
print(
|
| 147 |
f"[speed] video_fps={fps:.2f} target_fps={TARGET_FPS:.2f} "
|
| 148 |
f"stride={frame_stride} effective_fps={effective_fps:.2f} "
|
| 149 |
-
f"min_rep_frames={min_rep_frames} max_rep_frames={max_rep_frames}
|
| 150 |
-
f"infer_max_side={MAX_INFER_SIDE}"
|
| 151 |
)
|
| 152 |
|
| 153 |
# 1) First pass: compute angles + confs per sampled frame
|
|
@@ -163,9 +147,7 @@ def analyze_pushup_video_yolo(video_path: str, out_dir: str):
|
|
| 163 |
frame_i += 1
|
| 164 |
continue
|
| 165 |
|
| 166 |
-
|
| 167 |
-
|
| 168 |
-
res = model(infer_frame, verbose=False)[0]
|
| 169 |
if res.keypoints is None or len(res.keypoints.xy) == 0:
|
| 170 |
angles.append(np.nan)
|
| 171 |
confs.append(0.0)
|
|
@@ -211,7 +193,7 @@ def analyze_pushup_video_yolo(video_path: str, out_dir: str):
|
|
| 211 |
elif not np.any(mask):
|
| 212 |
raise RuntimeError("No valid pose angles detected.")
|
| 213 |
|
| 214 |
-
# Smooth (
|
| 215 |
win = int(round(effective_fps * 1.0))
|
| 216 |
win = max(5, win)
|
| 217 |
if win % 2 == 0:
|
|
@@ -219,7 +201,7 @@ def analyze_pushup_video_yolo(video_path: str, out_dir: str):
|
|
| 219 |
win = min(win, (len(angles) // 2) * 2 + 1)
|
| 220 |
angles_smooth = savgol_filter(angles, win, 2)
|
| 221 |
|
| 222 |
-
# 2) Rep detection on smoothed angles (
|
| 223 |
reps = []
|
| 224 |
state = "WAIT_DOWN"
|
| 225 |
rep_min = rep_max = rep_conf_sum = rep_len = rep_start = None
|
|
@@ -320,7 +302,6 @@ def analyze_pushup_video_yolo(video_path: str, out_dir: str):
|
|
| 320 |
"frame_stride": int(frame_stride),
|
| 321 |
"effective_fps": float(effective_fps),
|
| 322 |
"min_rep_frames": int(min_rep_frames),
|
| 323 |
-
"max_infer_side": int(MAX_INFER_SIDE),
|
| 324 |
}
|
| 325 |
}
|
| 326 |
|
|
@@ -384,4 +365,4 @@ with gr.Blocks(title="Pushup API (YOLO)") as demo:
|
|
| 384 |
)
|
| 385 |
|
| 386 |
if __name__ == "__main__":
|
| 387 |
-
demo.launch()
|
|
|
|
| 27 |
# Prevents very long false reps when tracking fails.
|
| 28 |
MAX_REP_SECONDS = 8.0
|
| 29 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
|
| 31 |
# ----------------------------
|
| 32 |
# Load YOLO pose model (lazy)
|
|
|
|
| 102 |
return int(round(s_lo + t * (s_hi - s_lo)))
|
| 103 |
return 0
|
| 104 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 105 |
|
| 106 |
# ----------------------------
|
| 107 |
# Core pipeline
|
|
|
|
| 131 |
print(
|
| 132 |
f"[speed] video_fps={fps:.2f} target_fps={TARGET_FPS:.2f} "
|
| 133 |
f"stride={frame_stride} effective_fps={effective_fps:.2f} "
|
| 134 |
+
f"min_rep_frames={min_rep_frames} max_rep_frames={max_rep_frames}"
|
|
|
|
| 135 |
)
|
| 136 |
|
| 137 |
# 1) First pass: compute angles + confs per sampled frame
|
|
|
|
| 147 |
frame_i += 1
|
| 148 |
continue
|
| 149 |
|
| 150 |
+
res = model(frame, verbose=False)[0]
|
|
|
|
|
|
|
| 151 |
if res.keypoints is None or len(res.keypoints.xy) == 0:
|
| 152 |
angles.append(np.nan)
|
| 153 |
confs.append(0.0)
|
|
|
|
| 193 |
elif not np.any(mask):
|
| 194 |
raise RuntimeError("No valid pose angles detected.")
|
| 195 |
|
| 196 |
+
# Smooth (match our efficient logic: ~1 second window scaled by effective_fps)
|
| 197 |
win = int(round(effective_fps * 1.0))
|
| 198 |
win = max(5, win)
|
| 199 |
if win % 2 == 0:
|
|
|
|
| 201 |
win = min(win, (len(angles) // 2) * 2 + 1)
|
| 202 |
angles_smooth = savgol_filter(angles, win, 2)
|
| 203 |
|
| 204 |
+
# 2) Rep detection on smoothed angles (match our efficient logic)
|
| 205 |
reps = []
|
| 206 |
state = "WAIT_DOWN"
|
| 207 |
rep_min = rep_max = rep_conf_sum = rep_len = rep_start = None
|
|
|
|
| 302 |
"frame_stride": int(frame_stride),
|
| 303 |
"effective_fps": float(effective_fps),
|
| 304 |
"min_rep_frames": int(min_rep_frames),
|
|
|
|
| 305 |
}
|
| 306 |
}
|
| 307 |
|
|
|
|
| 365 |
)
|
| 366 |
|
| 367 |
if __name__ == "__main__":
|
| 368 |
+
demo.launch()
|