Reem commited on
Commit
5f8bdff
Β·
1 Parent(s): 263a2a5

pipeline-integration

Browse files
A12/service/__init__.py CHANGED
@@ -1,4 +1,3 @@
1
- from .pipeline import run_video_pipeline, validate_video
2
- from .ui import run_a12_video_tab
3
 
4
- __all__ = ["run_video_pipeline", "validate_video", "run_a12_video_tab"]
 
1
+ from .pipeline import run_full_pipeline
 
2
 
3
+ __all__ = ["run_full_pipeline"]
A12/service/pipeline.py CHANGED
@@ -1,285 +1,107 @@
1
  from __future__ import annotations
2
 
3
- import csv
4
  import json
5
- import math
6
- import os
7
  import time
8
- from datetime import datetime
9
  from pathlib import Path
10
- from typing import Any, Dict, List, Tuple
11
 
12
- import cv2
13
- import numpy as np
14
 
15
- from .schemas import ClassificationResult, PipelineMetadata, PipelineOutput
16
-
17
- try:
18
- from A8.pose_estimator import MoveNetPoseEstimator
19
- except Exception: # pragma: no cover - used only if A8 is unavailable during isolated tests
20
- MoveNetPoseEstimator = None
21
-
22
- try:
23
- from A12.pose_interpolator import smooth_pose_sequence
24
- except Exception: # pragma: no cover
25
- smooth_pose_sequence = None
26
-
27
- KEYPOINT_NAMES = [
28
- "nose", "left_eye", "right_eye", "left_ear", "right_ear",
29
- "left_shoulder", "right_shoulder", "left_elbow", "right_elbow",
30
- "left_wrist", "right_wrist", "left_hip", "right_hip",
31
- "left_knee", "right_knee", "left_ankle", "right_ankle",
32
- ]
33
-
34
- # 13-joint subset used by the classification data in A13.
35
- CLASSIFIER_JOINTS = [
36
- "left_shoulder", "right_shoulder", "left_elbow", "right_elbow", "left_wrist", "right_wrist",
37
- "left_hip", "right_hip", "left_knee", "right_knee", "left_ankle", "right_ankle", "nose",
38
- ]
39
-
40
- SKELETON_EDGES = [
41
- ("left_shoulder", "right_shoulder"), ("left_shoulder", "left_elbow"), ("left_elbow", "left_wrist"),
42
- ("right_shoulder", "right_elbow"), ("right_elbow", "right_wrist"), ("left_shoulder", "left_hip"),
43
- ("right_shoulder", "right_hip"), ("left_hip", "right_hip"), ("left_hip", "left_knee"),
44
- ("left_knee", "left_ankle"), ("right_hip", "right_knee"), ("right_knee", "right_ankle"),
45
- ]
46
-
47
-
48
- def validate_video(video_path: str | None) -> Path:
49
- if not video_path:
50
- raise ValueError("A video file is required.")
51
- path = Path(video_path)
52
- if not path.exists():
53
- raise ValueError(f"Video file does not exist: {video_path}")
54
- if path.suffix.lower() not in {".mp4", ".mov", ".avi", ".mkv", ".webm", ".m4v"}:
55
- raise ValueError("Unsupported video type. Use mp4, mov, avi, mkv, webm, or m4v.")
56
- cap = cv2.VideoCapture(str(path))
57
- ok = cap.isOpened()
58
- cap.release()
59
- if not ok:
60
- raise ValueError("OpenCV could not open this video. Try re-encoding it as mp4.")
61
- return path
62
 
 
 
 
 
 
63
 
64
- def _pose_result_to_frame_dict(pose_result: Dict[str, Any], frame_id: int, timestamp_s: float) -> Dict[str, Any]:
65
- keypoints = pose_result.get("keypoints", {}) or {}
66
- out = []
67
- for name in KEYPOINT_NAMES:
68
- kp = keypoints.get(name, {}) or {}
69
- out.append({
70
- "name": name,
71
- "x": kp.get("x"),
72
- "y": kp.get("y"),
73
- "z": 0.0,
74
- "score": kp.get("confidence", kp.get("score", 0.0)),
75
- })
76
- return {
77
- "frame_id": frame_id,
78
- "timestamp": timestamp_s,
79
- "poses": [{"pose_id": 0, "keypoints": out}],
80
- "inference_time_ms": pose_result.get("inference_time_ms", 0.0),
81
- }
82
 
 
83
 
84
- def _get_pose_estimator():
85
- if MoveNetPoseEstimator is None:
86
- raise RuntimeError("A8.pose_estimator.MoveNetPoseEstimator could not be imported.")
87
- return MoveNetPoseEstimator(model_name="lightning")
88
 
 
 
89
 
90
- def _detect_motion_window(frames: List[Dict[str, Any]], min_window: int = 10) -> Tuple[int, int]:
91
- """Cut leading/trailing frames by motion energy of 13 classifier joints."""
92
- if len(frames) <= min_window:
93
- return 0, max(0, len(frames) - 1)
94
 
95
- coords = []
96
- for f in frames:
97
- kp_by_name = {kp["name"]: kp for kp in f["poses"][0]["keypoints"]}
98
- row = []
99
- for name in CLASSIFIER_JOINTS:
100
- kp = kp_by_name.get(name, {})
101
- x = kp.get("x")
102
- y = kp.get("y")
103
- row.append([np.nan if x is None else float(x), np.nan if y is None else float(y)])
104
- coords.append(row)
105
- arr = np.asarray(coords, dtype="float32")
106
- arr = np.nan_to_num(arr, nan=np.nanmean(arr) if not np.isnan(arr).all() else 0.0)
107
- velocity = np.linalg.norm(np.diff(arr, axis=0), axis=-1).mean(axis=1)
108
- if len(velocity) == 0 or float(np.max(velocity)) == 0.0:
109
- return 0, len(frames) - 1
110
 
111
- threshold = max(float(np.percentile(velocity, 35)), float(np.max(velocity)) * 0.08)
112
- active = np.where(velocity >= threshold)[0]
113
- if active.size == 0:
114
- return 0, len(frames) - 1
115
 
116
- start = max(0, int(active[0]) - 2)
117
- end = min(len(frames) - 1, int(active[-1]) + 3)
118
- if end - start + 1 < min_window:
119
- mid = (start + end) // 2
120
- start = max(0, mid - min_window // 2)
121
- end = min(len(frames) - 1, start + min_window - 1)
122
- return start, end
123
 
 
 
124
 
125
- def _frames_to_classifier_sequence(frames: List[Dict[str, Any]], sequence_len: int = 10) -> np.ndarray:
126
- """Return B-problem PoseNet-like data: shape (10, 13, 2)."""
127
- if not frames:
128
- raise ValueError("No pose frames were produced from the video.")
129
- indices = np.linspace(0, len(frames) - 1, sequence_len, dtype=int)
130
- sequence = np.zeros((sequence_len, len(CLASSIFIER_JOINTS), 2), dtype="float32")
131
- for out_i, frame_i in enumerate(indices):
132
- kp_by_name = {kp["name"]: kp for kp in frames[frame_i]["poses"][0]["keypoints"]}
133
- for joint_i, name in enumerate(CLASSIFIER_JOINTS):
134
- kp = kp_by_name.get(name, {})
135
- sequence[out_i, joint_i, 0] = 0.0 if kp.get("x") is None else float(kp.get("x"))
136
- sequence[out_i, joint_i, 1] = 0.0 if kp.get("y") is None else float(kp.get("y"))
137
- # normalize per clip to make dimensions roughly model-friendly
138
- max_abs = float(np.max(np.abs(sequence)))
139
- if max_abs > 1.5:
140
- sequence[:, :, 0] /= max_abs
141
- sequence[:, :, 1] /= max_abs
142
- return sequence
143
 
 
 
 
 
 
 
 
144
 
145
- def _classify(sequence: np.ndarray) -> ClassificationResult:
146
- """Use a real persisted model if present; otherwise deterministic dummy classifier.
147
 
148
- Replace this function with the Issue #10 champion wrapper when it is merged.
149
- Expected future wrapper: A13.models.champion.predict_proba(sequence[None, ...]).
150
- """
151
- try:
152
- from A13.models.champion import predict_good_probability # type: ignore
153
- good_prob = float(predict_good_probability(sequence))
154
- mode = "champion_model"
155
- except Exception:
156
- # Deterministic fallback so app integration can be finished before #10/#11 is merged.
157
- # Higher motion smoothness is treated as slightly better. This is not a scientific classifier.
158
- velocity = np.linalg.norm(np.diff(sequence, axis=0), axis=-1).mean()
159
- good_prob = float(np.clip(0.55 + (0.08 - velocity) * 0.8, 0.05, 0.95))
160
- mode = "deterministic_dummy_until_issue_10_model_is_available"
161
- label = "good" if good_prob >= 0.5 else "bad"
162
- return ClassificationResult(
163
- label=label,
164
- is_good=label == "good",
165
- confidence=max(good_prob, 1.0 - good_prob),
166
- probabilities={"bad": 1.0 - good_prob, "good": good_prob, "mode": mode},
167
  )
168
 
 
169
 
170
- def _write_keypoints_csv(frames: List[Dict[str, Any]], path: Path) -> None:
171
- with path.open("w", newline="") as f:
172
- writer = csv.writer(f)
173
- writer.writerow(["frame_id", "timestamp", "joint", "x", "y", "z", "confidence"])
174
- for frame in frames:
175
- for kp in frame["poses"][0]["keypoints"]:
176
- writer.writerow([
177
- frame["frame_id"], frame["timestamp"], kp["name"], kp.get("x"), kp.get("y"), kp.get("z", 0.0), kp.get("score", 0.0)
178
- ])
179
-
180
-
181
- def _write_animation_json(frames: List[Dict[str, Any]], path: Path) -> None:
182
- skeleton_frames = []
183
- for frame in frames:
184
- joints = {kp["name"]: {"x": kp.get("x"), "y": kp.get("y"), "z": kp.get("z", 0.0), "confidence": kp.get("score", 0.0)}
185
- for kp in frame["poses"][0]["keypoints"]}
186
- skeleton_frames.append({"frame_id": frame["frame_id"], "timestamp": frame["timestamp"], "joints": joints})
187
- path.write_text(json.dumps({"joint_names": KEYPOINT_NAMES, "edges": SKELETON_EDGES, "frames": skeleton_frames}, indent=2))
188
-
189
-
190
- def run_video_pipeline(
191
- video_path: str | None,
192
- confidence_threshold: float = 0.3,
193
- smoothing_strategy: str = "exponential",
194
- smoothing_method: str = "zscore",
195
- output_dir: str | os.PathLike[str] = "pose_outputs",
196
- ) -> PipelineOutput:
197
- start_time = time.perf_counter()
198
- warnings: List[str] = []
199
- video = validate_video(video_path)
200
- out_dir = Path(output_dir)
201
- out_dir.mkdir(parents=True, exist_ok=True)
202
-
203
- cap = cv2.VideoCapture(str(video))
204
- fps = float(cap.get(cv2.CAP_PROP_FPS) or 30.0)
205
- if fps <= 0 or fps > 240:
206
- warnings.append(f"Invalid FPS reported by OpenCV ({fps}); using 30 FPS.")
207
- fps = 30.0
208
- width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
209
- height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
210
-
211
- pose_estimator = _get_pose_estimator()
212
- original_frames: List[np.ndarray] = []
213
- pose_frames: List[Dict[str, Any]] = []
214
- frame_id = 0
215
- while True:
216
- ok, frame = cap.read()
217
- if not ok:
218
- break
219
- original_frames.append(frame)
220
- pose_result = pose_estimator.detect_pose(frame)
221
- pose_frames.append(_pose_result_to_frame_dict(pose_result, frame_id, frame_id / fps))
222
- frame_id += 1
223
- cap.release()
224
-
225
- if not pose_frames:
226
- raise ValueError("The video contained no readable frames.")
227
-
228
- if smooth_pose_sequence is not None:
229
- try:
230
- pose_frames = smooth_pose_sequence(
231
- pose_frames,
232
- strategy=smoothing_strategy,
233
- outlier_method=smoothing_method,
234
- outlier_threshold=3.0,
235
- window_size=7,
236
- min_confidence=0.2,
237
- )
238
- except Exception as exc:
239
- warnings.append(f"Smoothing failed; using unsmoothed poses. Error: {exc}")
240
- else:
241
- warnings.append("A12.pose_interpolator could not be imported; using unsmoothed poses.")
242
-
243
- cut_start, cut_end = _detect_motion_window(pose_frames)
244
- cut_pose_frames = pose_frames[cut_start:cut_end + 1]
245
- cut_video_frames = original_frames[cut_start:cut_end + 1]
246
-
247
- timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
248
- annotated_video = out_dir / f"a12_annotated_cut_{timestamp}.mp4"
249
- keypoints_csv = out_dir / f"a12_keypoints_cut_{timestamp}.csv"
250
- animation_json = out_dir / f"a12_animation_data_{timestamp}.json"
251
 
252
- writer = cv2.VideoWriter(str(annotated_video), cv2.VideoWriter_fourcc(*"mp4v"), fps, (width, height))
253
- for frame, pose_frame in zip(cut_video_frames, cut_pose_frames):
254
- # Redraw via estimator on frame. If a future A11 pipeline returns annotated frames, replace this block.
255
- pose_result = pose_estimator.detect_pose(frame)
256
- annotated = pose_estimator.draw_keypoints(frame, pose_result, confidence_threshold=confidence_threshold)
257
- writer.write(annotated)
258
- writer.release()
259
 
260
- _write_keypoints_csv(cut_pose_frames, keypoints_csv)
261
- _write_animation_json(cut_pose_frames, animation_json)
 
262
 
263
- sequence = _frames_to_classifier_sequence(cut_pose_frames)
264
- classification = _classify(sequence)
265
- classifier_mode = str(classification.probabilities.pop("mode", "unknown"))
 
 
 
 
 
 
266
 
267
- elapsed_ms = (time.perf_counter() - start_time) * 1000.0
268
- return PipelineOutput(
269
- annotated_video_path=str(annotated_video),
270
- animation_data_path=str(animation_json),
271
- keypoints_csv_path=str(keypoints_csv),
272
- classification=classification,
273
- metadata=PipelineMetadata(
274
- model_version="A12-pipeline-integration-v1",
275
- inference_time_ms=elapsed_ms,
276
- frame_count_original=len(pose_frames),
277
- frame_count_cut=len(cut_pose_frames),
278
- fps=fps,
279
- cut_start_frame=cut_start,
280
- cut_end_frame=cut_end,
281
- smoothing_strategy=f"{smoothing_strategy}/{smoothing_method}",
282
- classifier_mode=classifier_mode,
283
- ),
284
- warnings=warnings,
285
- )
 
1
  from __future__ import annotations
2
 
 
3
  import json
 
 
4
  import time
 
5
  from pathlib import Path
 
6
 
7
+ from exercise_pipeline import ExercisePipeline
 
8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
 
10
+ def run_full_pipeline(video_path: str):
11
+ """
12
+ Runs the existing exercise pipeline and adapts its saved output files
13
+ to the Gradio UI.
14
+ """
15
 
16
+ start_time = time.time()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
 
18
+ pipeline = ExercisePipeline()
19
 
20
+ print("\n[DEBUG] Running full pipeline...")
21
+ result = pipeline.process_video(video_path)
 
 
22
 
23
+ if result is None:
24
+ raise ValueError("Pipeline failed to process video.")
25
 
26
+ print("\n[DEBUG] Pipeline result:")
27
+ print(result)
 
 
28
 
29
+ video_path = Path(video_path)
30
+ stem = video_path.stem
 
 
 
 
 
 
 
 
 
 
 
 
 
31
 
32
+ output_dir = Path("outputs")
 
 
 
33
 
34
+ cut_csv_path = output_dir / f"{stem}_cut_3d_points.csv"
35
+ full_csv_path = output_dir / f"{stem}_3d_points.csv"
36
+ animation_video_path = output_dir / f"{stem}_skeleton.mp4"
37
+ results_json_path = output_dir / f"{stem}_results.json"
 
 
 
38
 
39
+ if not cut_csv_path.exists():
40
+ raise FileNotFoundError(f"Expected cut CSV was not found: {cut_csv_path}")
41
 
42
+ if not animation_video_path.exists():
43
+ raise FileNotFoundError(f"Expected skeleton animation video was not found: {animation_video_path}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
 
45
+ if results_json_path.exists():
46
+ try:
47
+ results_json = json.loads(results_json_path.read_text())
48
+ except Exception:
49
+ results_json = {}
50
+ else:
51
+ results_json = {}
52
 
53
+ quality_label = result.get("quality_label", results_json.get("quality_label", "UNKNOWN"))
 
54
 
55
+ confidence = (
56
+ result.get("quality_confidence")
57
+ or results_json.get("quality_confidence")
58
+ or results_json.get("confidence")
59
+ or 0.0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  )
61
 
62
+ elapsed = (time.time() - start_time) * 1000
63
 
64
+ return {
65
+ "annotated_video": None,
66
+ "animation_video": make_browser_playable(animation_video_path),
67
+ "csv_path": str(cut_csv_path),
68
+ "full_csv_path": str(full_csv_path) if full_csv_path.exists() else None,
69
+ "results_json_path": str(results_json_path) if results_json_path.exists() else None,
70
+ "classification": {
71
+ "label": quality_label,
72
+ "confidence": confidence,
73
+ },
74
+ "metadata": {
75
+ "inference_time_ms": elapsed,
76
+ "total_frames": result.get("total_frames"),
77
+ "start_frame": result.get("start_frame"),
78
+ "stop_frame": result.get("stop_frame"),
79
+ "exercise_frames": result.get("exercise_frames"),
80
+ "exercise_duration_sec": result.get("exercise_duration_sec"),
81
+ "pipeline_version": result.get("pipeline_version"),
82
+ },
83
+ "raw_pipeline_result": result,
84
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
 
86
+ import subprocess
 
 
 
 
 
 
87
 
88
+ def make_browser_playable(video_path):
89
+ video_path = Path(video_path)
90
+ fixed_path = video_path.with_name(video_path.stem + "_browser.mp4")
91
 
92
+ cmd = [
93
+ "ffmpeg",
94
+ "-y",
95
+ "-i", str(video_path),
96
+ "-vcodec", "libx264",
97
+ "-pix_fmt", "yuv420p",
98
+ "-movflags", "+faststart",
99
+ str(fixed_path),
100
+ ]
101
 
102
+ try:
103
+ subprocess.run(cmd, check=True)
104
+ return str(fixed_path)
105
+ except Exception as e:
106
+ print(f"[WARNING] Could not convert video for browser playback: {e}")
107
+ return str(video_path)
 
 
 
 
 
 
 
 
 
 
 
 
 
A12/service/ui.py CHANGED
@@ -1,44 +1,41 @@
1
- from __future__ import annotations
2
 
3
- import json
4
- from typing import Any, Dict, Tuple
5
 
6
- from .pipeline import run_video_pipeline, validate_video
 
 
 
7
 
 
 
8
 
 
 
 
 
 
 
 
9
 
10
- def run_a12_video_tab(video_path: str, confidence_threshold: float, smoothing_strategy: str, smoothing_method: str):
11
- """Gradio callback: video -> annotated video, animation json, keypoints csv, JSON, Markdown."""
12
- try:
13
- result = run_video_pipeline(
14
- video_path=video_path,
15
- confidence_threshold=confidence_threshold,
16
- smoothing_strategy=smoothing_strategy,
17
- smoothing_method=smoothing_method,
18
- )
19
- payload = result.to_json()
20
  summary = f"""
21
- ### A12 pipeline completed
22
 
23
- - **Classification:** `{payload['classification']['label']}`
24
- - **Confidence:** `{payload['classification']['confidence']:.3f}`
25
- - **Frames:** `{payload['metadata']['frame_count_cut']}` cut from `{payload['metadata']['frame_count_original']}` original frames
26
- - **Cut window:** frames `{payload['metadata']['cut_start_frame']}` to `{payload['metadata']['cut_end_frame']}`
27
- - **Classifier mode:** `{payload['metadata']['classifier_mode']}`
 
 
28
  """
29
- if payload["warnings"]:
30
- summary += "\n### Warnings\n" + "\n".join(f"- {w}" for w in payload["warnings"])
31
- return result.annotated_video_path, result.animation_data_path, result.keypoints_csv_path, payload, summary
32
- except Exception as exc:
33
- return None, None, None, {"error": str(exc)}, f"### Error\n{exc}"
34
-
35
-
36
- # Backward-compatible function name used by the uploaded app.py A12 CSV prototype.
37
- def run_a12_tab(csv_path: str, problem: str = "B"):
38
- if not csv_path:
39
- return {"error": "Upload a CSV file first."}, "### Error\nUpload a CSV file first."
40
- return {
41
- "message": "This CSV endpoint was superseded by the Issue #12 video pipeline tab.",
42
- "csv_path": csv_path,
43
- "problem": problem,
44
- }, "### CSV received\nThe Issue #12 implementation uses the video pipeline endpoint."
 
1
+ from A12.service.pipeline import run_full_pipeline
2
 
 
 
3
 
4
+ def run_a12_video_tab(video_path, confidence, smoothing_strategy, smoothing_method):
5
+ """
6
+ Gradio UI callback
7
+ """
8
 
9
+ try:
10
+ result = run_full_pipeline(video_path)
11
 
12
+ annotated_video = result["annotated_video"]
13
+ animation_video = result["animation_video"]
14
+ csv_path = result["csv_path"]
15
+
16
+ classification = result.get("classification", {})
17
+ label = classification.get("label", "unknown")
18
+ conf = classification.get("confidence", 0.0)
19
 
 
 
 
 
 
 
 
 
 
 
20
  summary = f"""
21
+ ### A12 Pipeline Results
22
 
23
+ - Classification: **{label}**
24
+ - Confidence: **{conf:.2f}**
25
+
26
+ Outputs:
27
+ - Annotated 2D video
28
+ - 3D skeleton animation video
29
+ - CSV joint data
30
  """
31
+
32
+ return (
33
+ annotated_video,
34
+ animation_video,
35
+ csv_path,
36
+ result,
37
+ summary
38
+ )
39
+
40
+ except Exception as e:
41
+ return None, None, None, {"error": str(e)}, f"### Error\n{e}"
 
 
 
 
 
app.py CHANGED
@@ -2,7 +2,7 @@ from PIL import Image
2
  import gradio as gr
3
  from A8.pose_estimator import MoveNetPoseEstimator
4
  from A12.pose_interpolator import smooth_pose_sequence
5
- from A12.service.ui import run_a12_tab
6
  from A12.service.ui import run_a12_video_tab
7
  import json
8
  import csv
@@ -426,7 +426,7 @@ with gr.Blocks(title="MoveNet Pose Estimation") as demo:
426
  Endpoint alternative chosen: **Gradio tab inside the existing app.py**.
427
 
428
  **Input:** one video file.
429
- **Output:** annotated cut 2D video, 3D-animation data JSON, keypoints CSV,
430
  and good/bad classification JSON.
431
  """
432
  )
@@ -464,8 +464,8 @@ with gr.Blocks(title="MoveNet Pose Estimation") as demo:
464
 
465
  with gr.Column():
466
  a12_video_output = gr.Video(label="Annotated cut 2D video")
467
- a12_animation_file = gr.File(label="3D animation data JSON")
468
- a12_keypoints_file = gr.File(label="Cut keypoints CSV")
469
  a12_json_output = gr.JSON(label="Structured output")
470
  a12_summary = gr.Markdown()
471
 
@@ -479,7 +479,7 @@ with gr.Blocks(title="MoveNet Pose Estimation") as demo:
479
  ],
480
  outputs=[
481
  a12_video_output,
482
- a12_animation_file,
483
  a12_keypoints_file,
484
  a12_json_output,
485
  a12_summary
 
2
  import gradio as gr
3
  from A8.pose_estimator import MoveNetPoseEstimator
4
  from A12.pose_interpolator import smooth_pose_sequence
5
+ #from A12.service.ui import run_a12_tab
6
  from A12.service.ui import run_a12_video_tab
7
  import json
8
  import csv
 
426
  Endpoint alternative chosen: **Gradio tab inside the existing app.py**.
427
 
428
  **Input:** one video file.
429
+ **Output:** annotated cut 2D video, 3D skeleton animation video, keypoints CSV,
430
  and good/bad classification JSON.
431
  """
432
  )
 
464
 
465
  with gr.Column():
466
  a12_video_output = gr.Video(label="Annotated cut 2D video")
467
+ a12_animation_output = gr.Video(label="3D Skeleton Animation")
468
+ a12_keypoints_file = gr.File(label="3D joint CSV")
469
  a12_json_output = gr.JSON(label="Structured output")
470
  a12_summary = gr.Markdown()
471
 
 
479
  ],
480
  outputs=[
481
  a12_video_output,
482
+ a12_animation_output,
483
  a12_keypoints_file,
484
  a12_json_output,
485
  a12_summary
pipeline/exercise_pipeline.py β†’ exercise_pipeline.py RENAMED
File without changes
pipeline/generate_skeleton_animation.py β†’ generate_skeleton_animation.py RENAMED
File without changes
{pipeline/models β†’ models}/A_CNN.keras RENAMED
File without changes
{pipeline/models β†’ models}/week15_2d_to_3d.h5 RENAMED
File without changes
{pipeline/models β†’ models}/week16_result.h5 RENAMED
File without changes
{pipeline/models β†’ models}/week16_scaler_X.pkl RENAMED
File without changes
{pipeline/models β†’ models}/week16_scaler_y.pkl RENAMED
File without changes
{pipeline/models β†’ models}/week17_start_and_stop.h5 RENAMED
File without changes
{pipeline/models β†’ models}/week17_start_and_stop.pkl RENAMED
File without changes
outputs/sample_3d_points.csv ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FrameNo,head_x,head_y,head_z,left_shoulder_x,left_shoulder_y,left_shoulder_z,left_elbow_x,left_elbow_y,left_elbow_z,right_shoulder_x,right_shoulder_y,right_shoulder_z,right_elbow_x,right_elbow_y,right_elbow_z,left_hand_x,left_hand_y,left_hand_z,right_hand_x,right_hand_y,right_hand_z,left_hip_x,left_hip_y,left_hip_z,right_hip_x,right_hip_y,right_hip_z,left_knee_x,left_knee_y,left_knee_z,right_knee_x,right_knee_y,right_knee_z,left_foot_x,left_foot_y,left_foot_z,right_foot_x,right_foot_y,right_foot_z
2
+ 0,-0.02469086,-0.30549058,-0.018785262,-0.12703425,-0.426884,-0.011260768,-0.29270473,-0.41702956,0.1328801,0.07084155,-0.38588476,0.013126321,0.23063543,-0.36249387,0.15875928,-0.36443374,-0.35633016,0.17076011,0.35865226,-0.24766573,0.23165596,-0.057423618,-0.6028143,0.1600125,0.002160171,-0.59173155,0.18322186,-0.112163454,-0.26498652,-0.38839594,0.16870892,-0.23564726,-0.31331667,-0.15622751,-0.53223246,-0.16083004,0.17306173,-0.51093787,-0.046685148
3
+ 1,-0.024967998,-0.43002096,-0.11993482,-0.16634907,-0.6029453,-0.08897782,-0.4108195,-0.60338145,-0.005416114,0.10584397,-0.5481941,-0.07426232,0.32827705,-0.5247129,0.022675084,-0.52109426,-0.53243273,0.017140254,0.5016788,-0.3797387,0.07519173,-0.076798156,-0.84479314,0.23260473,0.011549044,-0.8324699,0.25527912,-0.13188972,-0.38021573,-0.34699273,0.21129197,-0.3468837,-0.24424936,-0.18481304,-0.7210791,-0.18890223,0.20832768,-0.69434476,-0.010231925
4
+ 2,-0.02414888,-0.61061734,-0.09319575,-0.21161069,-0.84490645,-0.06928711,-0.5708368,-0.8908951,0.059444766,0.14638667,-0.77097154,-0.04901571,0.4590649,-0.7769989,0.091104925,-0.75290143,-0.83687013,0.09707974,0.7131239,-0.62381417,0.15956458,-0.100947306,-1.1470639,0.18025766,0.019786028,-1.1333593,0.20328687,-0.14754353,-0.502594,-0.36217874,0.2578762,-0.46165797,-0.27717394,-0.2108277,-0.9108006,-0.1536338,0.24051256,-0.8751469,-0.020496482
5
+ 3,-0.013226548,-0.68977755,0.0025674808,-0.21472667,-0.93940926,0.009742875,-0.63140476,-1.0369221,0.19737546,0.16485368,-0.86013496,0.05515663,0.51786846,-0.9074119,0.24655451,-0.8660449,-1.0319337,0.23498516,0.8194193,-0.7970122,0.32669598,-0.10658018,-1.2373304,0.15459265,0.026427073,-1.2260693,0.18387927,-0.13153192,-0.52633345,-0.47800654,0.2555401,-0.4869593,-0.41701788,-0.18542565,-0.92079663,-0.1525866,0.21814753,-0.8816034,-0.0926064
6
+ 4,0.009047891,-0.7392828,0.034269605,-0.21348421,-1.0154557,0.048781406,-0.7082192,-1.1924334,0.40399614,0.19673905,-0.9361615,0.114488415,0.6077443,-1.0504693,0.47008902,-1.0265698,-1.2705503,0.50487024,0.98468524,-1.0187703,0.6277303,-0.1211725,-1.3116975,0.18193126,0.036616314,-1.3068303,0.22110492,-0.095800996,-0.5379187,-0.6342735,0.24401952,-0.49753776,-0.5616469,-0.14026351,-0.8981151,-0.18917379,0.17222938,-0.85470587,-0.12589683
7
+ 5,0.022042712,-0.7635862,-0.000114143375,-0.21294382,-1.0556674,0.008392397,-0.74880743,-1.265961,0.3608372,0.21619855,-0.97694767,0.07932784,0.65240276,-1.1172265,0.43553036,-1.1018922,-1.3828393,0.4717759,1.055883,-1.1195118,0.5943852,-0.12859234,-1.3574991,0.16084704,0.04362619,-1.3567797,0.20154983,-0.07456537,-0.5522193,-0.644905,0.2309073,-0.51710236,-0.56981236,-0.11017247,-0.8899279,-0.16436917,0.14285906,-0.8433899,-0.09889043
8
+ 6,0.024529304,-0.75996757,-0.0056383465,-0.21581618,-1.061273,-0.008470051,-0.7695494,-1.2810006,0.37713203,0.22194579,-0.98078483,0.09286531,0.66735184,-1.1242925,0.48672962,-1.1351275,-1.4085078,0.5028141,1.0829362,-1.1319119,0.6343571,-0.1297238,-1.3674327,0.22603694,0.04468104,-1.367493,0.27839312,-0.06783855,-0.54800254,-0.6643527,0.22942469,-0.5135493,-0.55100036,-0.107502185,-0.8810016,-0.18776204,0.14075574,-0.832743,-0.09382089
9
+ 7,0.023272803,-0.66779035,-0.0030694534,-0.21766637,-0.9724214,-0.01990227,-0.7603292,-1.1703928,0.2916156,0.22164972,-0.894805,0.049701806,0.6502828,-1.0134927,0.36073697,-1.0994763,-1.2866545,0.40388083,1.0350951,-1.0038729,0.5083502,-0.12637372,-1.2900611,0.07972265,0.045099538,-1.2910244,0.117074266,-0.065368,-0.5273993,-0.5876736,0.21636654,-0.50157505,-0.5127229,-0.10639665,-0.86776555,-0.14148124,0.13927191,-0.8214608,-0.10719744
10
+ 8,0.024705535,-0.58386123,0.066184714,-0.2154029,-0.8957351,0.05501746,-0.7441619,-1.0620182,0.38405702,0.22137682,-0.81881773,0.116502695,0.6260127,-0.9007416,0.43088531,-1.0575076,-1.154499,0.49057716,0.9799235,-0.8617208,0.5862814,-0.117789656,-1.2306415,0.08113742,0.048661944,-1.2322085,0.115060344,-0.05579769,-0.5073569,-0.57003796,0.20506641,-0.4879735,-0.50459844,-0.10860262,-0.8566477,-0.1357212,0.14244123,-0.8165791,-0.102750875
11
+ 9,0.017574131,-0.4862826,0.07338355,-0.21633428,-0.8063493,0.052881967,-0.7213944,-0.9145907,0.42840508,0.21355283,-0.7268078,0.108747296,0.578042,-0.7435104,0.45885223,-0.9810788,-0.94568473,0.5535445,0.8708266,-0.6341384,0.6507237,-0.100756675,-1.1731671,0.03146303,0.053432982,-1.1728935,0.062376928,-0.053147294,-0.5059184,-0.5694852,0.19084024,-0.49864644,-0.5256524,-0.12172098,-0.86682004,-0.1146292,0.15813166,-0.83696455,-0.13403897
12
+ 10,0.020190854,-0.41577786,0.12860602,-0.21093641,-0.7443312,0.10429788,-0.7071521,-0.82721794,0.47614226,0.21497853,-0.66419536,0.17117976,0.56014085,-0.65089965,0.53289694,-0.94455075,-0.82837987,0.5848937,0.8239665,-0.5062333,0.7031617,-0.08906301,-1.1311117,0.03648026,0.060196083,-1.1307741,0.07144055,-0.047073282,-0.5004439,-0.552691,0.1867086,-0.49835464,-0.50169647,-0.12932019,-0.8585285,-0.08873396,0.16726677,-0.8361604,-0.08473495
13
+ 11,0.02781475,-0.31052482,0.16056702,-0.20111583,-0.64346623,0.13345166,-0.67857987,-0.69987077,0.5337809,0.21901684,-0.5667577,0.20293851,0.5436546,-0.52811015,0.5958343,-0.89461833,-0.68247557,0.65845007,0.7852174,-0.36315736,0.77966887,-0.08074329,-1.0496901,0.020843035,0.0649163,-1.05041,0.05524949,-0.042777497,-0.47735226,-0.5539148,0.18597901,-0.47773105,-0.5015852,-0.13148953,-0.82632196,-0.09383124,0.17361589,-0.8074571,-0.10430949
14
+ 12,0.03499816,-0.29470032,0.10651444,-0.19561177,-0.6352916,0.07668292,-0.6789569,-0.69094855,0.40371385,0.22329937,-0.5617383,0.13981663,0.55088407,-0.518373,0.4641862,-0.911031,-0.6797424,0.5041157,0.80665886,-0.3588746,0.60854846,-0.082945846,-1.0455476,-0.057555754,0.06586339,-1.048193,-0.028248725,-0.036412034,-0.4701197,-0.5196088,0.18348567,-0.47469482,-0.4757585,-0.12709771,-0.80234224,-0.08741084,0.16847353,-0.7814256,-0.10876298
15
+ 13,0.037818126,-0.25092977,0.073557675,-0.19253306,-0.596006,0.03880195,-0.675931,-0.6506023,0.32225707,0.2240776,-0.52803093,0.0987095,0.55121386,-0.48300922,0.38608462,-0.9083958,-0.6431865,0.41184688,0.80378884,-0.32687035,0.51049966,-0.08691648,-1.005896,-0.13236938,0.063660055,-1.0102956,-0.10515933,-0.0350925,-0.4613651,-0.52169293,0.17463525,-0.47445127,-0.4849976,-0.12315126,-0.778575,-0.095966354,0.16116282,-0.75511146,-0.12360523
16
+ 14,0.052978832,-0.16701533,0.19423673,-0.1688662,-0.5124306,0.17419684,-0.6254804,-0.5407258,0.6804645,0.23472814,-0.45056424,0.22832853,0.53865457,-0.39336902,0.69231105,-0.8216678,-0.51441634,0.87169135,0.75083494,-0.22003047,0.9471732,-0.075556934,-0.9305056,-0.020171937,0.07222251,-0.93654644,0.008004425,-0.03099946,-0.45198303,-0.5782114,0.18433292,-0.46745718,-0.51964563,-0.12751013,-0.7272324,-0.116691776,0.17193404,-0.7083499,-0.14867833
17
+ 15,0.007154687,-0.04653315,0.2044721,-0.22356796,-0.41391316,0.17375821,-0.7048898,-0.47962978,0.6450333,0.19241618,-0.33398438,0.2308414,0.50680596,-0.3152617,0.67156047,-0.87542003,-0.49308464,0.8246429,0.6989828,-0.17722756,0.90898675,-0.09571954,-0.82781863,-0.057988536,0.03684979,-0.82793427,-0.03299932,-0.03786193,-0.39966807,-0.518352,0.15391846,-0.3795176,-0.46638972,-0.122510225,-0.72770303,-0.1114996,0.15286076,-0.68134403,-0.16496184
18
+ 16,-0.030549519,0.026343836,0.082283676,-0.27262565,-0.35879228,0.022534918,-0.7886123,-0.4679009,0.35129222,0.15988685,-0.26162165,0.13095927,0.49447125,-0.28259027,0.52818817,-0.95666873,-0.5246529,0.53289497,0.6873422,-0.18569648,0.6827554,-0.11426451,-0.76392305,-0.32541722,0.008480151,-0.7593226,-0.2952911,-0.04023534,-0.3581588,-0.53012073,0.12616858,-0.31059688,-0.5373486,-0.11554043,-0.7388911,-0.09479359,0.13152616,-0.67350435,-0.27719963
19
+ 17,-0.017396213,0.22256497,-0.037545063,-0.23314069,-0.13409738,-0.087940976,-0.69369805,-0.2351123,0.29224744,0.16808541,-0.018479852,-0.06705817,0.46268135,-0.11452953,0.30796984,-0.7288793,-0.28886288,0.380314,0.5658634,-0.019348912,0.5018317,-0.072220385,-0.4884954,-0.1657466,-0.0026780316,-0.47820404,-0.13140927,-0.060764905,-0.22931616,-0.26292428,0.19590475,-0.15439714,-0.62978554,-0.20807345,-0.58697164,0.19955347,0.23814176,-0.537924,-0.21788627
20
+ 18,-0.04098874,0.28373918,0.015594545,-0.26292372,-0.078799605,-0.031958744,-0.7356199,-0.19730926,0.34115997,0.1468724,0.050529156,0.008519974,0.45004827,-0.06127154,0.390431,-0.7730339,-0.27023926,0.44570178,0.5607917,0.0106240725,0.5945268,-0.07854575,-0.4346433,-0.1107735,-0.018237554,-0.41990554,-0.07451986,-0.06297732,-0.19384296,-0.27253804,0.18943614,-0.09115834,-0.55203974,-0.20324814,-0.5922176,0.17151111,0.23071682,-0.533481,-0.15357815
21
+ 19,-0.043162398,0.3864855,-0.25371343,-0.25213242,0.043076288,-0.3164339,-0.7004571,-0.08095757,-0.12652276,0.14128825,0.1796152,-0.007924065,0.4338347,0.024758397,0.6316918,-0.6882822,-0.16299605,0.44481707,0.5236024,0.08547923,0.7834527,-0.06646228,-0.2749815,-0.3544545,-0.035133053,-0.2565814,-0.3190019,-0.07612187,-0.096065745,0.1790697,0.21596159,0.023301492,-0.2644672,-0.2539412,-0.49832407,0.4471255,0.2822029,-0.44072542,-0.63122314
22
+ 20,0.012587316,0.43754143,0.055150483,-0.17047799,0.13121313,0.031084474,-0.5629589,0.049790066,0.4319456,0.18831153,0.25349373,0.067976125,0.44879797,0.09479564,0.46217877,-0.5033636,0.006436485,0.5483463,0.5111903,0.1896561,0.673778,-0.025714535,-0.15835302,-0.015877694,-0.01094421,-0.14374593,0.017455729,-0.076313026,-0.037340824,-0.37139443,0.2790233,0.06154625,-0.50823146,-0.313239,-0.3580276,0.076294236,0.3598086,-0.33197254,-0.076949954
23
+ 21,0.057457976,0.5215612,0.008790615,-0.09625772,0.25307402,-0.055573914,-0.42499578,0.20996904,0.22541209,0.22356088,0.36494875,0.14645198,0.44736782,0.18881953,0.6916029,-0.29525286,0.19703001,0.6543524,0.46652243,0.3118246,0.8746148,0.013606155,0.0021561757,-0.30168,0.0024682037,0.015206924,-0.2737049,-0.0853603,0.040528364,-0.02998759,0.34487534,0.12735905,-0.2476353,-0.38467884,-0.20833233,0.18392104,0.44885412,-0.2070623,-0.43012595
24
+ 22,0.052833375,0.5201032,0.013005215,-0.104124606,0.2501646,-0.041123416,-0.4257887,0.2304849,0.25110134,0.21570313,0.3449106,0.1607988,0.43727365,0.22590245,0.71962255,-0.33683908,0.23850743,0.6845193,0.48146528,0.3687996,0.90729433,-0.0016149875,-0.025322689,-0.285101,0.0061833593,-0.014521397,-0.25985363,-0.0776624,0.025289994,0.025305672,0.31407675,0.103184804,-0.21334043,-0.35393432,-0.2317183,0.23211084,0.41210696,-0.2231072,-0.4127522
25
+ 23,0.081244685,0.6535795,-0.028697666,-0.045099627,0.4228617,-0.07924897,-0.2971248,0.43790504,0.19633518,0.23537232,0.51381063,0.13297658,0.4137002,0.36446056,0.7057569,-0.10787404,0.47456518,0.6783065,0.39242417,0.5351378,0.9028283,0.03430652,0.19291702,-0.28066742,0.0058976803,0.2047429,-0.25643876,-0.09717406,0.12213553,0.104816794,0.37661177,0.19908547,-0.15258974,-0.44211748,-0.08444937,0.25307,0.5122515,-0.09268303,-0.4341644
26
+ 24,0.07335723,0.7014076,0.030060131,-0.047837466,0.4857009,-0.010854894,-0.28781793,0.49869964,0.26666105,0.22722428,0.5812788,0.15496309,0.40140757,0.41382957,0.6591808,-0.07850506,0.53205395,0.67609185,0.3742166,0.5796362,0.85145336,0.03813192,0.2749377,-0.23203191,-0.005520275,0.28933087,-0.21209028,-0.113845535,0.1553861,0.026525063,0.39192867,0.2393343,-0.15453354,-0.47179133,-0.06873234,0.16127054,0.54124016,-0.07526341,-0.3546225
27
+ 25,0.06814824,0.71703726,-0.07693544,-0.046309967,0.51717025,-0.11905854,-0.26763597,0.5325772,0.13743146,0.21947436,0.61688024,0.09807851,0.38755864,0.43638307,0.6729511,-0.039820097,0.56336665,0.65506923,0.3558808,0.5976023,0.8820849,0.041529186,0.33024812,-0.24008393,-0.015931686,0.34714416,-0.21708867,-0.13027024,0.18418148,0.2048834,0.40969798,0.2734485,-0.09072301,-0.5012408,-0.053700242,0.32038826,0.5718045,-0.059774447,-0.4283529
28
+ 26,0.066361904,0.7300952,-0.118019216,-0.046485677,0.5332344,-0.15796795,-0.26361412,0.5489896,0.07103729,0.21833867,0.6357992,0.06318332,0.38387173,0.4491255,0.62610924,-0.026184306,0.57956195,0.59784365,0.34566766,0.6091911,0.82703084,0.04369943,0.35052353,-0.24669352,-0.017974982,0.3680935,-0.22475246,-0.13423328,0.18685015,0.23658177,0.41394094,0.2771948,-0.07126081,-0.509324,-0.05521239,0.3340324,0.580071,-0.06361486,-0.4328624
29
+ 27,0.06360658,0.7668551,-0.09329257,-0.045802087,0.5771864,-0.1354443,-0.25386733,0.59278184,0.101657584,0.21511292,0.68354017,0.080496676,0.37727425,0.48516256,0.6424117,-0.0023396355,0.6201277,0.62531316,0.33393848,0.6408795,0.84900945,0.047165513,0.4075718,-0.23559794,-0.024663053,0.42650807,-0.21363828,-0.14121324,0.20905633,0.22381285,0.4238731,0.30287403,-0.063659444,-0.52808166,-0.04171351,0.30341667,0.5991162,-0.051625885,-0.43240446
30
+ 28,0.065535836,0.7421878,-0.070998274,-0.04533498,0.54725766,-0.12915745,-0.25304073,0.56763023,0.10595347,0.21622518,0.6502264,0.100352325,0.3772321,0.4649783,0.66840005,-0.011381428,0.5994352,0.6120852,0.33622715,0.6235447,0.85955983,0.044342425,0.36729985,-0.279044,-0.019547392,0.38513896,-0.25368837,-0.13523518,0.18971802,0.18516529,0.41528797,0.28022003,-0.11855517,-0.5122194,-0.055381738,0.31802815,0.58361775,-0.06518331,-0.45898423
31
+ 29,0.06894657,0.7080616,-0.024275785,-0.045256577,0.50274897,-0.06866373,-0.2566514,0.52902013,0.18610142,0.21893732,0.6008613,0.12547335,0.38027352,0.43652043,0.6677839,-0.032491356,0.567396,0.6782442,0.34522852,0.6003291,0.8795088,0.039695796,0.30566153,-0.23226899,-0.01138334,0.32169828,-0.21258846,-0.123397194,0.16198921,0.20169237,0.40058964,0.24695894,-0.03711687,-0.48702475,-0.07487579,0.2514776,0.55862606,-0.08496612,-0.38822493
32
+ 30,0.07131534,0.68522894,-0.035644926,-0.049536064,0.46434096,-0.080997474,-0.2723258,0.49782002,0.16610236,0.22229713,0.5548915,0.10932804,0.38639987,0.42188397,0.6227061,-0.079544775,0.54436857,0.6025198,0.36521906,0.5933434,0.80000144,0.032383688,0.23686719,-0.24764335,-0.00038999147,0.25030035,-0.22497925,-0.105261125,0.1245204,0.07220529,0.37601712,0.20299082,-0.16038077,-0.4484833,-0.10309605,0.22329207,0.51971,-0.11178865,-0.3993556
33
+ 31,0.07267108,0.64013773,-0.023243826,-0.056171037,0.40247497,-0.073404305,-0.29228523,0.4429945,0.17088152,0.22520426,0.48627374,0.11223952,0.3932173,0.38672748,0.6110275,-0.13761263,0.4967748,0.5849863,0.39036956,0.5639689,0.7789126,0.023855386,0.14097963,-0.2594543,0.011881955,0.15174899,-0.23598784,-0.08747738,0.07364186,0.028246565,0.3499229,0.14514323,-0.18704231,-0.40522966,-0.14520226,0.19491369,0.47630218,-0.15292677,-0.3973155
34
+ 32,0.04744854,0.53161496,0.04441225,-0.10888696,0.2610721,-0.0007314082,-0.40325737,0.27477273,0.29276,0.20835543,0.34954333,0.15423264,0.4072571,0.28238207,0.6472705,-0.32645497,0.30980408,0.66985077,0.45081115,0.44128078,0.83247596,-0.0033979372,-0.046972614,-0.26495853,0.01616153,-0.037153453,-0.24400625,-0.07185076,-0.01455532,-0.050620873,0.29279056,0.055422995,-0.21259613,-0.32708782,-0.2896302,0.13744968,0.38589832,-0.28676873,-0.3397671
35
+ 33,-0.0048352405,0.49311218,0.03862613,-0.18773037,0.18163985,-0.021670064,-0.5409614,0.1558977,0.2500906,0.16569617,0.28228897,0.13775659,0.39228806,0.22504115,0.5999424,-0.5055533,0.1605796,0.5718455,0.4522495,0.35930207,0.7505857,-0.04074443,-0.16524498,-0.3137786,-0.0021163793,-0.15278439,-0.2891364,-0.06784279,-0.08556174,-0.1553202,0.22313786,0.00045711844,-0.32087347,-0.2631417,-0.43815497,0.12707976,0.3023237,-0.4078196,-0.3578511
36
+ 34,-0.060146887,0.47034582,0.009051221,-0.26976264,0.11856279,-0.008589447,-0.68317777,0.050394475,0.27229816,0.12027015,0.23297356,0.0387916,0.3750957,0.18051977,0.33516556,-0.6842449,0.021443788,0.33282572,0.44895822,0.28785926,0.48901862,-0.0788544,-0.2628517,-0.023839194,-0.024343956,-0.24731131,0.0065647196,-0.06672142,-0.14617996,-0.31393138,0.15254238,-0.04328699,-0.4026435,-0.2039698,-0.5816791,0.080756076,0.22163889,-0.52222264,-0.0005605244
37
+ 35,-0.0695247,0.2963787,-0.06714642,-0.298763,-0.07107652,-0.112595156,-0.75714207,-0.16068976,0.20434915,0.11685931,0.043539856,-0.101768516,0.40362772,0.012030657,0.20926441,-0.83714503,-0.20649055,0.2588036,0.5363284,0.102895945,0.36723512,-0.09990322,-0.47740605,-0.17303236,-0.01692996,-0.46382394,-0.14322671,-0.06149266,-0.24536607,-0.232485,0.123406075,-0.15636835,-0.6037265,-0.15404364,-0.71064675,0.19416262,0.16494465,-0.64645594,-0.22303624
38
+ 36,-0.0794205,0.12395796,-0.07303181,-0.32583916,-0.25359792,-0.12455183,-0.8305728,-0.37010232,0.19680856,0.112323485,-0.13954115,-0.112774745,0.43632314,-0.15814805,0.20527269,-0.9876604,-0.4367054,0.2506146,0.63204515,-0.083222136,0.36775744,-0.12134151,-0.6688927,-0.20164356,-0.014900536,-0.65669626,-0.17138283,-0.062395245,-0.32492673,-0.22727713,0.102440335,-0.24791783,-0.62020415,-0.118459605,-0.8224018,0.19997607,0.122652195,-0.7491057,-0.25502822
39
+ 37,-0.06005143,0.0352049,0.13248606,-0.30377,-0.33852765,0.12091838,-0.8071644,-0.44570714,0.5018129,0.13135129,-0.23353572,0.16734454,0.4593936,-0.24272567,0.52766585,-0.98473096,-0.50364023,0.62665313,0.6739943,-0.15651849,0.7124744,-0.118355,-0.75659525,0.0021275538,-0.0015399546,-0.74743414,0.029427523,-0.059231438,-0.3701834,-0.50164354,0.11520378,-0.30940554,-0.44731057,-0.11885921,-0.8309194,-0.053768713,0.13082705,-0.76218826,-0.044708718
40
+ 38,-0.015634187,-0.09442303,0.14246754,-0.25418475,-0.44918096,0.13733998,-0.7454039,-0.5302048,0.56891716,0.17354535,-0.36044574,0.18550691,0.5028225,-0.33986953,0.5867544,-0.9631595,-0.5628434,0.71781737,0.7533641,-0.23057339,0.79119474,-0.102146275,-0.8693373,0.015444489,0.031179367,-0.8659165,0.043872662,-0.050019898,-0.41655585,-0.5410843,0.14500882,-0.388982,-0.4822972,-0.118696995,-0.8281381,-0.08073149,0.14445372,-0.7841055,-0.07525381
41
+ 39,0.02983219,-0.27769747,0.11246711,-0.20525846,-0.6142157,0.100273326,-0.697147,-0.67981136,0.4784014,0.2181813,-0.54061246,0.14875236,0.55983204,-0.49847567,0.5078597,-0.9729084,-0.6950254,0.6017671,0.863553,-0.37270322,0.68155843,-0.08848679,-1.0301002,-0.036404368,0.06396461,-1.0325254,-0.008970277,-0.039066337,-0.4713133,-0.51518846,0.17857443,-0.4753464,-0.4632356,-0.11761328,-0.82922477,-0.073566675,0.15714084,-0.8077329,-0.073376544
42
+ 40,0.030059813,-0.34321827,0.097525984,-0.2060767,-0.6829585,0.0784561,-0.71529114,-0.7645289,0.4069073,0.22139087,-0.6071268,0.12995547,0.57384443,-0.5800509,0.44640082,-0.9921827,-0.78395814,0.50323987,0.8772989,-0.45088375,0.5927576,-0.08993733,-1.0868587,-0.020415608,0.06292554,-1.0894337,0.007609332,-0.038025443,-0.4831975,-0.50270903,0.1815902,-0.48637384,-0.45890912,-0.122634694,-0.8363079,-0.06801194,0.16087233,-0.8131407,-0.0750723
43
+ 41,0.03195446,-0.42882866,0.14583847,-0.20688184,-0.7683925,0.13212827,-0.7301786,-0.87196916,0.5396811,0.22435111,-0.6916035,0.18993089,0.59039867,-0.6889693,0.57277906,-1.0171556,-0.9080522,0.6657609,0.9068001,-0.5751068,0.7600776,-0.09716977,-1.1542708,0.051134977,0.05919559,-1.1574967,0.08382375,-0.03720799,-0.48852116,-0.5549105,0.18601947,-0.48833665,-0.5002594,-0.12235691,-0.83334094,-0.088992774,0.157495,-0.8056331,-0.08195632
44
+ 42,0.033320114,-0.5754316,0.17172968,-0.21139044,-0.91698426,0.15556721,-0.76927626,-1.0641346,0.6176048,0.23003294,-0.8348044,0.22200626,0.62718487,-0.87482524,0.6520606,-1.0874143,-1.1349602,0.77348316,0.97790426,-0.7924919,0.8707079,-0.10684803,-1.2752603,0.059875518,0.05557548,-1.2786304,0.09450272,-0.034777436,-0.5043957,-0.6007901,0.19521707,-0.49766806,-0.5370576,-0.11894582,-0.8415272,-0.11958732,0.15219763,-0.807679,-0.11469011
45
+ 43,0.029600954,-0.6634475,0.15630412,-0.21635638,-1.0006791,0.13631403,-0.7877781,-1.1722142,0.6253385,0.22888352,-0.9173746,0.21673757,0.64397097,-0.98501945,0.67592484,-1.1185095,-1.2629759,0.8047919,1.0088989,-0.92411405,0.908187,-0.11629235,-1.3374423,0.09125228,0.049924094,-1.340474,0.13234939,-0.039107792,-0.5174464,-0.6623873,0.1977912,-0.5079838,-0.5772163,-0.11446328,-0.84967935,-0.15762171,0.14593227,-0.808882,-0.13609351
46
+ 44,0.031246021,-0.7456626,0.107513204,-0.21826005,-1.0795842,0.095280156,-0.8089694,-1.2876856,0.59942436,0.2329833,-0.99411976,0.1839411,0.67384094,-1.1021429,0.66156447,-1.1694511,-1.411436,0.78121054,1.073952,-1.0777793,0.89531094,-0.124766216,-1.3969917,0.12800357,0.047023553,-1.4000306,0.17523238,-0.04103094,-0.52878034,-0.7347359,0.20810165,-0.51148206,-0.64259565,-0.10904517,-0.85623264,-0.16437396,0.14087516,-0.81025934,-0.11817902
47
+ 45,0.030035976,-0.84585667,0.040436264,-0.2204664,-1.1723188,0.023950074,-0.82349014,-1.4126109,0.38200507,0.2333045,-1.0840421,0.0885813,0.6965323,-1.2312021,0.42940915,-1.2054198,-1.5586874,0.50751877,1.123604,-1.2353098,0.60529554,-0.13206369,-1.4722458,0.08887128,0.04416928,-1.4741646,0.1246635,-0.04721503,-0.5498324,-0.61323065,0.22053297,-0.52239394,-0.5501608,-0.106527455,-0.87312347,-0.14884588,0.13846982,-0.82243574,-0.13895318
48
+ 46,0.022933088,-0.9247158,0.03556187,-0.22558503,-1.2442796,0.03403582,-0.8370996,-1.50359,0.44721785,0.22877641,-1.1498007,0.11591417,0.70536697,-1.319879,0.52307,-1.2258257,-1.6511116,0.585184,1.1426209,-1.328174,0.7032502,-0.1313143,-1.5365305,0.15497585,0.043219246,-1.535426,0.20010866,-0.057043303,-0.5789138,-0.67909175,0.23184606,-0.54367316,-0.5898861,-0.111570455,-0.9080902,-0.16700068,0.1460037,-0.8571436,-0.10017924
49
+ 47,0.010790251,-0.84531343,0.03545061,-0.22158709,-1.1380284,0.041519407,-0.76031405,-1.3407024,0.42913243,0.20892377,-1.0535942,0.120587446,0.64003086,-1.1875377,0.50277656,-1.0794197,-1.4341366,0.54273695,1.0072117,-1.1565472,0.66954005,-0.12348783,-1.4453121,0.21671855,0.04097887,-1.4419003,0.2628229,-0.08096054,-0.5925072,-0.7020398,0.22652759,-0.56490964,-0.61788285,-0.1223385,-0.93139946,-0.19732541,0.15625729,-0.88841015,-0.12462552
50
+ 48,0.0036226215,-0.78691053,0.008665851,-0.21581858,-1.0596783,0.025326494,-0.6968408,-1.2166605,0.41699675,0.19407699,-0.9816566,0.098062806,0.58868873,-1.0844705,0.48732352,-0.96952564,-1.2681135,0.53246456,0.91160536,-1.0216049,0.6627365,-0.11553718,-1.3774989,0.2114047,0.039597075,-1.3722273,0.25618625,-0.09948036,-0.5982906,-0.7197473,0.23054104,-0.57156914,-0.64181316,-0.13808611,-0.94753474,-0.20045204,0.1721196,-0.9114915,-0.12786175
51
+ 49,-0.008115099,-0.73289156,-0.14425541,-0.21192874,-0.9800142,-0.12965763,-0.6242146,-1.0754312,-0.08043971,0.17362869,-0.9072904,-0.12580138,0.5220053,-0.9631782,-0.07453658,-0.83205366,-1.0670006,-0.10844222,0.7857832,-0.8524035,-0.063993044,-0.10596263,-1.3080554,0.049540337,0.037480403,-1.2994324,0.060351912,-0.12591347,-0.5999667,-0.48802397,0.23590331,-0.5739321,-0.37617636,-0.15735452,-0.9651723,-0.22107367,0.19198947,-0.9326573,-0.073545255
52
+ 50,-0.019777363,-0.71168065,-0.13240965,-0.21384683,-0.9433229,-0.12444708,-0.5901511,-1.0079603,-0.10792533,0.15754469,-0.87091297,-0.116469614,0.48518628,-0.90344465,-0.08757432,-0.7642039,-0.9668787,-0.13821852,0.72341746,-0.76257956,-0.08704329,-0.10189326,-1.2665734,0.05021001,0.030404523,-1.2544879,0.06409191,-0.14815012,-0.583812,-0.3906068,0.24675901,-0.55449456,-0.31200084,-0.18311228,-0.96294147,-0.17100972,0.21517292,-0.93025535,-0.056549612
53
+ 51,-0.029609213,-0.6111115,-0.15480736,-0.21536456,-0.8312672,-0.13658892,-0.550558,-0.8584026,-0.110540085,0.14332369,-0.7620933,-0.11336934,0.44392803,-0.7626019,-0.059852123,-0.6911185,-0.78509325,-0.1455294,0.65878624,-0.59491014,-0.0598404,-0.09743078,-1.1637237,0.15434363,0.024606327,-1.1492499,0.17949641,-0.16277906,-0.55103076,-0.41789523,0.2501383,-0.51775044,-0.36535063,-0.20297277,-0.9458148,-0.13326868,0.23377302,-0.9140967,-0.038446397
54
+ 52,-0.034604784,-0.6367072,-0.044328958,-0.2243854,-0.8651859,-0.023074968,-0.5909432,-0.92176557,0.22749726,0.14245561,-0.78645617,0.018413667,0.46823403,-0.807683,0.2730782,-0.7635301,-0.86116076,0.3070609,0.7290457,-0.6458291,0.39902115,-0.1007771,-1.1881236,0.24581212,0.018121017,-1.170995,0.28129733,-0.165472,-0.5277078,-0.53714454,0.26665375,-0.47730637,-0.4523361,-0.2211554,-0.928618,-0.19579762,0.25071502,-0.8886933,-0.06412574
55
+ 53,-0.04193799,-0.66294456,-0.058457445,-0.2368667,-0.89673674,-0.03657858,-0.6347506,-0.98385006,0.2109613,0.14010149,-0.8101263,-0.0066729374,0.49322104,-0.8559203,0.2358649,-0.831904,-0.9344117,0.28437728,0.7946123,-0.69909555,0.35244834,-0.10680722,-1.210937,0.16566065,0.009056156,-1.1910857,0.194968,-0.17077632,-0.50354946,-0.5209059,0.27934638,-0.43709987,-0.4495787,-0.24003208,-0.90659755,-0.1555896,0.26591736,-0.8563742,-0.05085176
56
+ 54,-0.047971185,-0.626659,-0.041103423,-0.24305668,-0.86307055,-0.021941662,-0.646035,-0.9590687,0.24239035,0.13579589,-0.7750252,0.007945154,0.4953666,-0.8293575,0.26522756,-0.8442446,-0.9070664,0.32759643,0.80728495,-0.66490793,0.39242566,-0.10953838,-1.1744919,0.16926251,0.00032625798,-1.1531658,0.19893186,-0.17358038,-0.47494265,-0.5204724,0.2832004,-0.40080714,-0.44590315,-0.25883308,-0.87991786,-0.16177207,0.28082156,-0.8245937,-0.047528177
57
+ 55,-0.06596061,-0.4196215,-0.047312506,-0.25220752,-0.6405507,-0.03437469,-0.6019773,-0.69498473,0.19244365,0.11231881,-0.5624591,-0.0136328805,0.4451997,-0.58382255,0.20949651,-0.7620113,-0.6092367,0.27926594,0.7371782,-0.3947922,0.3305024,-0.11350987,-0.96868545,0.1474194,-0.015733713,-0.94515,0.1724582,-0.19328605,-0.4322505,-0.43176603,0.28222698,-0.35398582,-0.3884386,-0.28759256,-0.8527587,-0.12879765,0.30817676,-0.7962622,-0.044709917
58
+ 56,-0.098083116,-0.124883115,-0.054785818,-0.27594066,-0.32324332,-0.042036936,-0.57057273,-0.34654745,0.10856278,0.07336958,-0.26217616,-0.026328804,0.38701695,-0.26372498,0.12543263,-0.69330317,-0.23103285,0.16053183,0.6642477,-0.057149757,0.20353284,-0.12742862,-0.6784661,0.14652167,-0.052997787,-0.6531698,0.16735163,-0.25961655,-0.3973437,-0.3636153,0.31229582,-0.31950122,-0.2954799,-0.36466137,-0.8454295,-0.13622205,0.37646055,-0.7959223,-0.012431735
59
+ 57,-0.117018975,0.25144464,-0.11807093,-0.2908982,0.06691498,-0.08412305,-0.53542686,0.07503261,0.056231048,0.049069073,0.114369676,-0.12828834,0.33636183,0.11444169,-0.006662933,-0.59604144,0.21165694,0.15750585,0.5703068,0.32401842,0.07897305,-0.13596354,-0.31949532,0.11687501,-0.08877346,-0.2960728,0.1132994,-0.3499292,-0.35080028,-0.09832272,0.37950823,-0.27438948,-0.057775237,-0.47999558,-0.8347976,-0.11542002,0.47638673,-0.8015664,-0.036116052
60
+ 58,-0.14211887,0.53075945,-0.2463722,-0.30963382,0.3562199,-0.13939299,-0.5067433,0.37733915,0.088536724,0.015703693,0.39523366,-0.30419546,0.28277466,0.37516713,-0.14066319,-0.50972444,0.5128726,0.24055211,0.48302534,0.57140267,-0.055588264,-0.15208896,-0.04460803,-0.084918834,-0.12979573,-0.021264095,-0.13518137,-0.43408126,-0.33683777,0.1534571,0.44218814,-0.25871664,0.08393689,-0.58612204,-0.8516703,-0.052590378,0.5726651,-0.8312559,-0.22246063
61
+ 59,-0.14468373,0.58150554,-0.2539165,-0.30479503,0.42175373,-0.17222705,-0.46815562,0.47487208,-0.021824557,0.0083506415,0.45167747,-0.2234433,0.24759208,0.45827708,-0.008173404,-0.44204974,0.6323354,0.14590882,0.40544868,0.667878,-0.006215114,-0.14877565,0.005621305,-0.17315821,-0.12761484,0.027414853,-0.20477292,-0.4633923,-0.36458924,0.37780914,0.4429642,-0.2978475,0.15939903,-0.59061456,-0.87995505,0.2530141,0.5747904,-0.8670689,-0.2737254
62
+ 60,-0.1479219,0.6764391,-0.3141335,-0.31129456,0.518174,-0.21181631,-0.46867135,0.56401014,-0.0770106,0.0041421345,0.5446301,-0.30564997,0.22927694,0.5288666,-0.12237814,-0.4217166,0.7073542,0.090525016,0.36186802,0.71530646,-0.13282451,-0.15598136,0.080740765,-0.119778566,-0.13931012,0.09866087,-0.1583537,-0.53576714,-0.39049554,0.3813593,0.5039164,-0.33103514,0.1139737,-0.65525347,-0.9242032,0.22688277,0.6335826,-0.9260258,-0.36330643
63
+ 61,-0.112428494,0.6516762,-0.28164583,-0.27228823,0.48476937,-0.21808204,-0.41435945,0.5721357,-0.338148,0.037153058,0.51116943,-0.27431726,0.22025594,0.5418745,-0.40830353,-0.35830677,0.7346207,-0.45378634,0.3109234,0.74812835,-0.4987687,-0.12974112,0.037116982,0.054869857,-0.097141206,0.050591093,0.047649644,-0.47279274,-0.39420414,-0.21247844,0.45173174,-0.34420973,-0.24851237,-0.57550097,-0.9103184,-0.061501224,0.56391966,-0.91013205,-0.06422504
64
+ 62,-0.09103554,0.5547939,-0.33249456,-0.24270572,0.38905492,-0.20309092,-0.3632189,0.5197957,-0.19746445,0.05510991,0.41152126,-0.3039917,0.2048554,0.5094369,-0.30647743,-0.32080173,0.7102199,-0.21825275,0.2806625,0.7493054,-0.41792518,-0.10913862,-0.062063176,-0.058699314,-0.055535793,-0.049201995,-0.09165037,-0.38424742,-0.40785474,0.17509207,0.36072242,-0.3676058,0.0013949955,-0.4564941,-0.8993815,0.21680887,0.46103308,-0.8881922,-0.16287842
65
+ 63,-0.05450813,0.51899403,-0.13416813,-0.20222828,0.34960678,-0.11314775,-0.30940634,0.53419816,-0.16079761,0.0909899,0.36306226,-0.1398728,0.20537688,0.5436428,-0.19091126,-0.29342833,0.7632361,-0.19823475,0.26289412,0.81832844,-0.21972354,-0.081040986,-0.12460665,-0.1608541,-0.0010121474,-0.11632469,-0.16703326,-0.28938067,-0.40498132,-0.14201446,0.26948807,-0.38302714,-0.14130121,-0.3259743,-0.8667137,-0.048198007,0.3433392,-0.8521733,-0.026648559
66
+ 64,-0.042475343,0.68199605,-0.12477704,-0.19070338,0.49985614,-0.10424075,-0.28930712,0.7044905,-0.13756119,0.10223628,0.5080706,-0.12688246,0.20154704,0.7129844,-0.16148733,-0.28028125,0.93971777,-0.15515603,0.25866067,0.98965454,-0.17811911,-0.074580766,0.0043733316,-0.1290907,0.00983741,0.009931089,-0.13458927,-0.24925196,-0.36964312,-0.100701116,0.24004623,-0.35108078,-0.09211344,-0.29674906,-0.83008087,-0.04426422,0.3178232,-0.81786835,-0.015314525
67
+ 65,-0.015421361,0.70412195,-0.05613072,-0.1580778,0.51341116,-0.05630099,-0.24399723,0.7617416,-0.10672235,0.12749,0.5160716,-0.062375423,0.20367083,0.782771,-0.10825008,-0.24982002,1.0275607,-0.14774327,0.24880569,1.0912722,-0.14606719,-0.050537985,0.004624112,-0.13816565,0.04755968,0.0082393605,-0.1403145,-0.15033801,-0.3539091,-0.12458016,0.14806692,-0.34366027,-0.11993563,-0.18704289,-0.7849262,-0.054021556,0.21779928,-0.76643765,-0.054414142
68
+ 66,-0.020704431,0.7520492,-0.06792267,-0.16945045,0.5677246,-0.06512402,-0.2608206,0.7972916,-0.13405524,0.12612762,0.56928235,-0.07403793,0.21310808,0.80878955,-0.13801304,-0.27025154,1.049148,-0.19156432,0.27208728,1.0949885,-0.18866193,-0.060757264,0.05601455,-0.107895695,0.03444517,0.05866107,-0.10995118,-0.2166279,-0.33557197,-0.12861313,0.22244187,-0.32584035,-0.12734224,-0.25846136,-0.7844915,-0.048477218,0.2840549,-0.7725242,-0.050498277
69
+ 67,-0.01610525,0.7042563,-0.08332976,-0.16527677,0.51752514,-0.076051556,-0.2592773,0.7456311,-0.13631332,0.13039204,0.5196528,-0.08621372,0.2154866,0.7549845,-0.14288984,-0.26969185,0.99476856,-0.18406567,0.26734722,1.0367528,-0.1867298,-0.060580086,0.0016844496,-0.12794746,0.039319918,0.0031913407,-0.12989342,-0.21478525,-0.35613227,-0.14799643,0.22044815,-0.34970567,-0.14740452,-0.24793471,-0.7975488,-0.05712388,0.2736901,-0.7896914,-0.05379279
70
+ 68,-0.020051334,0.54722637,-0.22476086,-0.16854317,0.3726211,-0.12172642,-0.26833263,0.58511347,-0.12726885,0.12784185,0.37945467,-0.17425506,0.2179707,0.5958597,-0.20001361,-0.27415797,0.826602,-0.16845037,0.26536033,0.87294936,-0.29767343,-0.061312173,-0.12899256,-0.17603597,0.03729878,-0.12612677,-0.19676138,-0.24677104,-0.38876584,0.065785706,0.24592133,-0.38252655,0.054732867,-0.2648463,-0.82745504,0.17284514,0.2881745,-0.8196524,0.08292069
71
+ 69,-0.029047199,0.426036,-0.11189928,-0.17737702,0.26567683,-0.104333445,-0.28056654,0.4612519,-0.19981429,0.11890579,0.27520204,-0.11958446,0.21817496,0.47107446,-0.2113361,-0.28597945,0.6941025,-0.2795303,0.27133664,0.740662,-0.27814773,-0.06775988,-0.21922764,-0.10852539,0.02591972,-0.21492952,-0.11018944,-0.29572663,-0.4068969,-0.18177928,0.2889417,-0.39897847,-0.18958907,-0.3038112,-0.8512732,-0.051461063,0.3234812,-0.8422887,-0.05552731
72
+ 70,-0.044211455,0.34814957,-0.23955487,-0.19622727,0.20061325,-0.18574463,-0.30584556,0.36622646,-0.32669437,0.103588775,0.21357523,-0.21965525,0.21968538,0.3683676,-0.37055677,-0.30529606,0.579779,-0.4640936,0.28272378,0.6185332,-0.486178,-0.08254976,-0.26677716,-0.014552604,0.002023819,-0.26107234,-0.017615398,-0.3705754,-0.42134023,-0.28734952,0.35899335,-0.41043139,-0.31054232,-0.3787896,-0.8909702,-0.04187236,0.39062983,-0.88582945,-0.03013003
73
+ 71,-0.054515168,0.22345658,-0.25591394,-0.20364353,0.07904651,-0.17467827,-0.31664672,0.23130666,-0.26627818,0.090320885,0.09389014,-0.23806506,0.21829425,0.23350133,-0.35763338,-0.31193498,0.43869197,-0.37451798,0.27963918,0.4825184,-0.4547262,-0.08996652,-0.37142664,0.0023411545,-0.005255211,-0.36333323,-0.010231981,-0.3682732,-0.46564794,-0.1843815,0.34598854,-0.4521384,-0.2000036,-0.36807638,-0.93070555,-0.03059377,0.37870327,-0.9223107,-0.02514531
74
+ 72,-0.074645646,0.17614843,-0.27417913,-0.22423929,0.036672167,-0.1684494,-0.34052473,0.1655117,-0.22883452,0.07015312,0.055352412,-0.26022327,0.21828291,0.16478251,-0.34150884,-0.32782853,0.36056203,-0.30572405,0.2909718,0.40634415,-0.44755322,-0.10593573,-0.39255774,0.0017391775,-0.02747626,-0.3807955,-0.021306394,-0.39986485,-0.47690594,0.011270491,0.37196612,-0.4558714,-0.05461207,-0.4056507,-0.9510805,0.074670844,0.41075805,-0.93872726,-0.058212474
75
+ 73,-0.089715496,0.21751933,-0.25930685,-0.23869611,0.07247445,-0.14813611,-0.35342768,0.1964561,-0.16135572,0.054050047,0.095770694,-0.25766414,0.21672511,0.19513975,-0.30990952,-0.33520553,0.38757032,-0.21324186,0.30353838,0.43499157,-0.38681307,-0.116924465,-0.34202087,-0.0019859453,-0.043689735,-0.32671574,-0.029633326,-0.3939939,-0.4590169,0.033669602,0.36941037,-0.42889753,-0.018484406,-0.4212787,-0.94470686,0.05141461,0.4247266,-0.92853636,-0.05226376
76
+ 74,-0.0895743,0.1330666,-0.20560062,-0.24029225,-0.023600882,-0.15573555,-0.37293565,0.08518717,-0.17681211,0.056836978,0.0067836666,-0.23755877,0.23787811,0.09032208,-0.2714478,-0.3619537,0.2708309,-0.18286023,0.33620167,0.32963967,-0.29687554,-0.11965431,-0.42413795,0.012904797,-0.040726144,-0.40710264,-0.0048003215,-0.35824645,-0.4719636,-0.016399423,0.3476784,-0.4363635,-0.06685807,-0.39904436,-0.9461182,-0.020008326,0.40321735,-0.9261634,-0.08727823
77
+ 75,-0.084184,-0.023487544,-0.20018584,-0.2345534,-0.19143102,-0.17742671,-0.3918294,-0.095428355,-0.21128878,0.06649509,-0.15281364,-0.20721518,0.26678097,-0.075426295,-0.22180542,-0.3973261,0.08999575,-0.20655192,0.3768667,0.17090245,-0.23336428,-0.11597562,-0.5740547,0.046192937,-0.02662026,-0.55490667,0.045761634,-0.2982967,-0.49068734,-0.08864828,0.3024684,-0.44976714,-0.101225644,-0.3439881,-0.93502766,-0.07078881,0.35161135,-0.90647066,-0.073393986
78
+ 76,-0.07651439,-0.20115028,-0.07794628,-0.22723113,-0.3777301,-0.07579477,-0.41023207,-0.29769242,-0.07147227,0.077610195,-0.32821548,-0.06469338,0.29648995,-0.262941,-0.04173874,-0.43139634,-0.11777773,-0.09749046,0.41704518,-0.014336273,-0.045553673,-0.11132231,-0.7340499,0.12823711,-0.013937253,-0.71313035,0.14688489,-0.24608326,-0.5018751,-0.28383365,0.26469985,-0.4551464,-0.22937265,-0.29618874,-0.9225702,-0.14745605,0.30512226,-0.88600427,-0.036422968
79
+ 77,-0.06430555,-0.37580332,-0.072699964,-0.21832031,-0.5564383,-0.06761635,-0.4332566,-0.5009173,-0.027625661,0.09457724,-0.49987546,-0.0544319,0.33347023,-0.45457116,0.00096531375,-0.48120645,-0.3336833,-0.03824243,0.47194022,-0.21728225,0.018753853,-0.106307,-0.89490366,0.17358674,-0.00032264553,-0.8743419,0.19479491,-0.22419865,-0.5165938,-0.32365856,0.2626155,-0.46829414,-0.26556122,-0.27529857,-0.9213661,-0.1707353,0.28617164,-0.8826568,-0.048607003
80
+ 78,-0.053629868,-0.52061003,-0.103407554,-0.21151382,-0.7028449,-0.08763795,-0.45159507,-0.6703644,-0.042322855,0.108624406,-0.6433743,-0.080952115,0.36229834,-0.61692655,-0.022160804,-0.52062625,-0.51474553,-0.04535891,0.51255405,-0.3887998,0.0022838674,-0.10360808,-1.0307896,0.19393596,0.009999821,-1.0113328,0.2134599,-0.21421053,-0.54025674,-0.3196997,0.26757854,-0.49311003,-0.26444703,-0.26233545,-0.93247914,-0.17244491,0.27513492,-0.893589,-0.045867324
81
+ 79,-0.04969892,-0.51666033,-0.07731839,-0.207567,-0.6984336,-0.0667275,-0.44595847,-0.66292644,-0.008151848,0.11239668,-0.6403414,-0.049071204,0.36293662,-0.61041343,0.026483076,-0.5161198,-0.5086765,-0.010444195,0.5098557,-0.3862198,0.054540213,-0.10170866,-1.0289695,0.18989933,0.014064074,-1.0102178,0.21303499,-0.21067336,-0.54380924,-0.35868877,0.26640418,-0.4988089,-0.2982473,-0.25623688,-0.933917,-0.18040101,0.27082074,-0.897155,-0.0564549
82
+ 80,-0.05001559,-0.49516463,-0.097707115,-0.20855804,-0.6770158,-0.08733784,-0.44897056,-0.6443721,-0.061452214,0.11283077,-0.6196798,-0.07135005,0.3647051,-0.58952713,-0.024029223,-0.52525055,-0.4983426,-0.077761516,0.5144634,-0.37587893,-0.011606757,-0.10120284,-1.0085385,0.17792708,0.016933512,-0.9900505,0.20005834,-0.20790918,-0.54604363,-0.34013975,0.26241168,-0.50465626,-0.27411357,-0.24737523,-0.93793434,-0.18098801,0.26432097,-0.9041923,-0.049776897
83
+ 81,-0.062462993,-0.39673606,-0.08356008,-0.21975942,-0.58237237,-0.08453045,-0.4454682,-0.54193544,-0.10372501,0.10028906,-0.5292051,-0.06766208,0.3451967,-0.4904999,-0.06012272,-0.51670223,-0.4013494,-0.14360914,0.49406347,-0.28675765,-0.07606954,-0.1086439,-0.932029,0.11050848,0.012219623,-0.91288775,0.1299182,-0.20843305,-0.55609155,-0.30196586,0.25281918,-0.5169086,-0.2523538,-0.24029903,-0.9493027,-0.15670933,0.2606104,-0.92044973,-0.0643491
84
+ 82,-0.068108074,-0.24423528,-0.13772781,-0.22135092,-0.42943615,-0.1078018,-0.41722792,-0.36076844,-0.08176224,0.091365464,-0.3829806,-0.10641917,0.31275153,-0.31506225,-0.06191285,-0.47106785,-0.21121153,-0.10301165,0.44447348,-0.10947635,-0.059600715,-0.10658012,-0.80004513,0.16865917,0.0132380435,-0.7811362,0.18406257,-0.20763786,-0.5445931,-0.30686978,0.24044503,-0.5119293,-0.26450345,-0.23375295,-0.9504685,-0.15493788,0.2563023,-0.9302958,-0.061562892
85
+ 83,-0.07172711,-0.15542014,-0.176602,-0.22545199,-0.34274372,-0.13618004,-0.41672927,-0.27015886,-0.095641196,0.08777492,-0.2986045,-0.205724,0.30474344,-0.22243369,-0.19177115,-0.47275445,-0.12785023,-0.09908773,0.43930665,-0.028064596,-0.20138769,-0.10580992,-0.72319233,0.07867124,0.014530829,-0.7044354,0.07254535,-0.20283276,-0.5365045,-0.1954621,0.23039861,-0.50733733,-0.2116429,-0.22391726,-0.95357656,-0.10440006,0.24887846,-0.93906534,-0.115906015
86
+ 84,-0.06733154,-0.32911536,-0.18515158,-0.22779118,-0.5213714,-0.14764206,-0.47528848,-0.51566684,-0.19806524,0.09670181,-0.4716651,-0.1881991,0.35908297,-0.4551834,-0.23438789,-0.56610423,-0.40547115,-0.24321961,0.52311426,-0.2795702,-0.2757266,-0.110750325,-0.8741813,0.052880052,0.014758387,-0.8554441,0.050989363,-0.2026094,-0.56464803,-0.17220746,0.23890455,-0.5306217,-0.15780953,-0.22630395,-0.9601637,-0.08905518,0.24437553,-0.9391737,-0.047012255
87
+ 85,-0.062590115,-0.36013454,-0.18772909,-0.22090214,-0.54779136,-0.1440745,-0.46664476,-0.54589534,-0.12943049,0.10051195,-0.49862728,-0.16416432,0.36453775,-0.48984107,-0.13850138,-0.5540429,-0.43333402,-0.1437503,0.5230648,-0.31181332,-0.14055596,-0.110823445,-0.8912455,0.11722179,0.013827435,-0.8729459,0.124875054,-0.20879379,-0.5654688,-0.25460002,0.24889682,-0.53115994,-0.22929999,-0.23703843,-0.95250165,-0.11061984,0.2539044,-0.9308824,-0.045148402
88
+ 86,-0.048566516,-0.4963293,-0.043334305,-0.21185684,-0.6872338,-0.017407777,-0.49693456,-0.71765083,0.1360596,0.11900921,-0.6320712,0.039202165,0.40848944,-0.65343213,0.20881929,-0.6058562,-0.61127377,0.11788373,0.57911664,-0.47446948,0.25904328,-0.1065935,-1.0134103,0.31102905,0.0212116,-0.9963483,0.34970635,-0.20509323,-0.5792983,-0.5247377,0.25695282,-0.5444435,-0.4698791,-0.23660456,-0.949169,-0.26389834,0.24849625,-0.9222418,-0.17071815
89
+ 87,-0.04408339,-0.66380817,-0.057513528,-0.21184348,-0.8553576,-0.0589436,-0.53153896,-0.92083687,-0.025659118,0.12724218,-0.7924717,-0.029330585,0.4453829,-0.8499874,0.039812967,-0.66261923,-0.82726437,-0.014230595,0.6389535,-0.6759979,0.08300289,-0.11073462,-1.1561571,0.19894785,0.018011611,-1.1385548,0.22524816,-0.20823632,-0.59045446,-0.29229313,0.27256998,-0.5481837,-0.21604721,-0.24615586,-0.9455214,-0.22668205,0.25535133,-0.9086132,-0.08954857
90
+ 88,-0.03959072,-0.7422143,-0.06816849,-0.20590915,-0.9291209,-0.05235537,-0.52448905,-0.99354696,0.05678485,0.13048007,-0.8646985,-0.034213908,0.4487342,-0.9261915,0.08670996,-0.64983135,-0.89200747,0.0570613,0.63616705,-0.7416251,0.12831396,-0.11002425,-1.2182822,0.21002926,0.01693509,-1.2005458,0.23384863,-0.21482413,-0.59180874,-0.4138695,0.28493586,-0.5473187,-0.36761746,-0.25814566,-0.93940294,-0.20053986,0.26562706,-0.8984798,-0.10441358
91
+ 89,-0.04441382,-0.5876535,-0.06804422,-0.20751561,-0.7745869,-0.051815696,-0.4870633,-0.7864849,0.03501561,0.12331097,-0.7125928,-0.036933385,0.40585527,-0.72358763,0.062018156,-0.5884077,-0.6628477,0.049923643,0.5776028,-0.52599484,0.1073411,-0.10448168,-1.0912478,0.21219957,0.017027622,-1.0731121,0.23468368,-0.21071887,-0.56504387,-0.36921918,0.276158,-0.52435046,-0.29957435,-0.2539352,-0.9383652,-0.19825114,0.26962125,-0.90488017,-0.062055234
92
+ 90,-0.044019874,-0.5594833,-0.12537739,-0.208911,-0.7516517,-0.107237466,-0.48778287,-0.75310355,-0.103084,0.12333795,-0.6895816,-0.094248995,0.39771712,-0.6848784,-0.06418177,-0.5906493,-0.62852037,-0.12017627,0.57250404,-0.48611972,-0.0566662,-0.10040943,-1.0789036,0.17682715,0.020869639,-1.0610085,0.19645393,-0.19850698,-0.5591068,-0.31943783,0.26532516,-0.5191693,-0.25087547,-0.24122517,-0.94323677,-0.18135893,0.2598244,-0.91200495,-0.051724106
93
+ 91,-0.036601983,-0.504811,-0.09935363,-0.19994265,-0.69604725,-0.08088996,-0.4610373,-0.6713505,-0.023383964,0.12690432,-0.6377028,-0.06507906,0.3794414,-0.60343975,0.00794168,-0.5559061,-0.53954345,-0.042627513,0.5433979,-0.40176526,0.026581224,-0.092524245,-1.0315856,0.12966187,0.028005367,-1.0152757,0.15047255,-0.18483694,-0.5438624,-0.39429858,0.25550526,-0.5087666,-0.3451454,-0.22749442,-0.9396092,-0.1457466,0.25183195,-0.9134006,-0.05971948
94
+ 92,-0.027403677,-0.4594469,-0.10596084,-0.19197427,-0.65685016,-0.08718218,-0.45147508,-0.6205442,-0.047544945,0.13446228,-0.602284,-0.070322745,0.3771579,-0.5503838,-0.01161023,-0.54935837,-0.48980135,-0.06039396,0.53567654,-0.3515139,0.0045737587,-0.08752841,-1.0017097,0.14819384,0.036690842,-0.9879737,0.16839604,-0.16645253,-0.5424993,-0.3562558,0.24163416,-0.5135646,-0.30007094,-0.20580612,-0.93611777,-0.16267079,0.23356327,-0.9140815,-0.063748896
95
+ 93,-0.020903708,-0.4788327,-0.088820465,-0.19228585,-0.6924434,-0.068670474,-0.48433378,-0.6762967,-0.006616745,0.14487253,-0.63579303,-0.045959525,0.40330002,-0.5939301,0.03185478,-0.60833687,-0.56281763,-0.022931784,0.5811267,-0.40692773,0.049915876,-0.089226946,-1.0420523,0.14156125,0.04148402,-1.0304197,0.16295652,-0.14598623,-0.55642545,-0.397515,0.22899652,-0.52937084,-0.34984738,-0.18418904,-0.93821865,-0.15422828,0.21346977,-0.9151464,-0.0809829
96
+ 94,-0.017250055,-0.51665413,-0.06484027,-0.19193359,-0.7365643,-0.046557028,-0.5030982,-0.7356614,0.037271556,0.15022787,-0.6779865,-0.017080156,0.4201897,-0.646891,0.08261657,-0.6429061,-0.6360506,0.03803499,0.6103663,-0.4701995,0.11054584,-0.091454744,-1.0790557,0.13654263,0.04218438,-1.0684053,0.15889652,-0.1385162,-0.56199914,-0.39785674,0.22725055,-0.5359485,-0.34855857,-0.17674206,-0.9379405,-0.15593429,0.20661893,-0.91342753,-0.094583556
97
+ 95,-0.014063195,-0.5554924,-0.034025047,-0.19443116,-0.78680295,-0.019539861,-0.53318757,-0.80638665,0.13871689,0.15698452,-0.7249383,0.018626027,0.4428952,-0.7085265,0.18457703,-0.6903773,-0.7203745,0.16513543,0.64831203,-0.5384354,0.24962205,-0.093965836,-1.1301277,0.15176216,0.043078497,-1.1203094,0.17871168,-0.12964702,-0.574367,-0.480571,0.22495273,-0.5481038,-0.4259721,-0.16995715,-0.94263965,-0.16000319,0.19975887,-0.9165519,-0.097124845
98
+ 96,-0.013022283,-0.595134,-0.053480804,-0.19916572,-0.83740777,-0.03398297,-0.56705934,-0.880536,0.121852145,0.16221121,-0.7712011,-0.0007876455,0.46643764,-0.77250737,0.16113614,-0.74185663,-0.80975884,0.14584945,0.6896976,-0.6098094,0.22688913,-0.09674494,-1.1807041,0.15815642,0.042462632,-1.1710142,0.18436015,-0.12439869,-0.5832349,-0.48094162,0.22628056,-0.5555404,-0.42643937,-0.16968948,-0.9476728,-0.15586509,0.19837005,-0.9210198,-0.08611833
99
+ 97,-0.015117516,-0.6322607,-0.03867337,-0.20503467,-0.87981915,-0.024547655,-0.59173745,-0.9389011,0.13952832,0.16371766,-0.8091012,0.010107558,0.481092,-0.82311815,0.17802797,-0.7763694,-0.8772352,0.16472916,0.71801364,-0.6642335,0.24784127,-0.09867723,-1.2228996,0.14537683,0.04053959,-1.2124202,0.17253314,-0.12505473,-0.5895048,-0.49387187,0.23042908,-0.559434,-0.43782857,-0.17406754,-0.95625037,-0.15790299,0.20296675,-0.92891544,-0.08781682
100
+ 98,-0.01618085,-0.6537265,-0.024549596,-0.20819992,-0.9051685,-0.008742362,-0.60580945,-0.97292453,0.19316567,0.16468829,-0.8319925,0.028350491,0.48924583,-0.85283077,0.22907169,-0.794652,-0.9140139,0.22590317,0.73228866,-0.69265944,0.314407,-0.09949856,-1.248998,0.1497232,0.039572243,-1.2379808,0.178466,-0.1252431,-0.59340316,-0.5370802,0.23374486,-0.56133956,-0.48193333,-0.17868814,-0.95899194,-0.15772748,0.20698278,-0.93120265,-0.09403172
101
+ 99,-0.015579455,-0.6055335,-0.03981399,-0.20232946,-0.850869,-0.025574997,-0.5721794,-0.8919387,0.14948834,0.16176301,-0.78217965,0.009047963,0.4669167,-0.7829638,0.1883386,-0.7401021,-0.81342655,0.18363686,0.6866358,-0.60742337,0.26581886,-0.09661516,-1.1986899,0.15262002,0.04009023,-1.1879135,0.18056029,-0.12916169,-0.58596903,-0.49479824,0.234135,-0.5540843,-0.43495005,-0.18300806,-0.94756263,-0.15990855,0.2109477,-0.9201802,-0.08278805
102
+ 100,-0.014648253,-0.5478827,-0.009746757,-0.19527973,-0.7860111,0.00019899051,-0.5343113,-0.7981471,0.21879773,0.15835267,-0.7225243,0.04214007,0.44192517,-0.70136374,0.25947177,-0.6802622,-0.69965005,0.2668351,0.6361189,-0.5111561,0.35653067,-0.093340784,-1.1366034,0.14317708,0.04076569,-1.1262769,0.17392732,-0.13324879,-0.5768993,-0.54699075,0.23313498,-0.54611874,-0.48521736,-0.185932,-0.9353642,-0.17168263,0.21349318,-0.9087695,-0.10220436
103
+ 101,-0.01440207,-0.5512203,-0.069317415,-0.19263515,-0.7882797,-0.06779521,-0.5246434,-0.7947056,-0.028510947,0.15705341,-0.7260872,-0.039956123,0.4367486,-0.7014727,0.015435385,-0.6675049,-0.6918164,-0.037766993,0.62570506,-0.5079209,0.02762061,-0.09427799,-1.1330724,0.08524441,0.03939949,-1.1230247,0.10627792,-0.13338104,-0.5732562,-0.37455198,0.23322791,-0.5420925,-0.3300648,-0.18700029,-0.9259156,-0.15349482,0.21350458,-0.89771175,-0.092523284
104
+ 102,-0.012967175,-0.55613583,-0.06421246,-0.19075905,-0.79508835,-0.064822406,-0.52383506,-0.8017488,-0.03571381,0.15808077,-0.73335564,-0.037101705,0.43773654,-0.7093791,0.008816408,-0.66774344,-0.6981096,-0.04839842,0.62478614,-0.51464075,0.017063286,-0.09493901,-1.1373513,0.075537235,0.03927371,-1.1278255,0.095979095,-0.13136625,-0.5740143,-0.35863307,0.2319058,-0.5430405,-0.31725973,-0.18543132,-0.9210688,-0.15018836,0.21114208,-0.8917728,-0.09373416
105
+ 103,-0.012576786,-0.4983898,0.01116459,-0.18443212,-0.7283302,0.01974475,-0.48491642,-0.7061479,0.21702917,0.15400048,-0.6720471,0.062018503,0.41169083,-0.6261644,0.25913972,-0.6071693,-0.5849208,0.25932056,0.5751823,-0.42034608,0.34510648,-0.091878,-1.0731955,0.16448452,0.03987525,-1.064145,0.19335972,-0.13566115,-0.5644918,-0.5034561,0.22985071,-0.5354078,-0.44218165,-0.1860761,-0.91275537,-0.17808789,0.21240197,-0.8848653,-0.107176706
106
+ 104,-0.015219904,-0.57057595,-0.003212661,-0.19302464,-0.80901176,0.006169927,-0.5287683,-0.8220172,0.1925074,0.15580688,-0.7460963,0.047089096,0.44095442,-0.7294351,0.23519568,-0.6768803,-0.7218042,0.23101036,0.63493353,-0.53785145,0.3159063,-0.097059585,-1.1464193,0.15949246,0.036283366,-1.1363761,0.18790704,-0.13472179,-0.5714684,-0.4965475,0.23391661,-0.53829646,-0.43652943,-0.18793498,-0.91962415,-0.17172259,0.21230483,-0.8881866,-0.1013167
107
+ 105,-0.02026193,-0.5550826,-0.05635968,-0.19418153,-0.7833674,-0.054698367,-0.50727355,-0.78349507,0.014778357,0.14655071,-0.7211225,-0.02393518,0.42133635,-0.6966683,0.05871655,-0.6416047,-0.6768909,0.018848255,0.60959464,-0.5010642,0.08600774,-0.0958663,-1.1150056,0.09689772,0.030128058,-1.1032631,0.11967213,-0.15034172,-0.5532754,-0.39613086,0.2456385,-0.51818913,-0.34716615,-0.20408109,-0.91877455,-0.14798208,0.23001087,-0.8871033,-0.08466994
108
+ 106,-0.020176578,-0.5192762,-0.013831752,-0.18902485,-0.7376723,-9.563152e-05,-0.4720097,-0.71204567,0.20069776,0.14209306,-0.6791448,0.03746299,0.39769018,-0.6359663,0.24280538,-0.58695567,-0.5900048,0.24095984,0.56743735,-0.43092307,0.3307504,-0.09274899,-1.0717691,0.18454427,0.030399255,-1.0599556,0.21447597,-0.1560115,-0.5504005,-0.5063163,0.2463427,-0.5159708,-0.44300234,-0.20581675,-0.9191559,-0.17953928,0.23370744,-0.88824636,-0.09047407
109
+ 107,-0.01761519,-0.5040449,-0.16682982,-0.18495603,-0.71851057,-0.14730544,-0.45549414,-0.6810148,-0.21936728,0.14233638,-0.6622064,-0.14760381,0.38906962,-0.60969114,-0.19551563,-0.56301856,-0.55344296,-0.26864854,0.550077,-0.4030945,-0.22754683,-0.09080364,-1.0549948,0.10691094,0.03280185,-1.0437421,0.119140275,-0.1559245,-0.5529118,-0.25237522,0.24486095,-0.52024055,-0.18240453,-0.20025451,-0.92050606,-0.1640654,0.23034552,-0.8897417,-0.030328007
110
+ 108,-0.015073013,-0.41833434,-0.06120167,-0.14905955,-0.58893734,-0.061750762,-0.36738488,-0.5632284,-0.012087543,0.11245206,-0.54275566,-0.029748721,0.31282037,-0.50529844,0.039262727,-0.45564774,-0.46344173,-0.014598594,0.4458926,-0.34218535,0.05820429,-0.07320443,-0.854942,0.099363714,0.024685245,-0.8454318,0.12403383,-0.12772256,-0.44185567,-0.39065662,0.19894382,-0.41458637,-0.33806056,-0.16299394,-0.73848176,-0.169457,0.18711492,-0.7128157,-0.09275875
111
+ 109,-0.009910918,-0.2716814,-0.054792043,-0.10580795,-0.3919747,-0.04462167,-0.24183895,-0.34743276,0.057149198,0.081365764,-0.36167035,-0.0063384846,0.21163532,-0.31339392,0.10822314,-0.28898305,-0.2587549,0.058432862,0.2908574,-0.18216579,0.14206696,-0.051481575,-0.5936258,0.12917596,0.019487761,-0.58695656,0.15523133,-0.09916766,-0.32557714,-0.4616093,0.14880773,-0.30779508,-0.4128279,-0.122748785,-0.55158186,-0.15676272,0.14304225,-0.5342679,-0.10087231
outputs/sample_cut_3d_points.csv ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FrameNo,head_x,head_y,head_z,left_shoulder_x,left_shoulder_y,left_shoulder_z,left_elbow_x,left_elbow_y,left_elbow_z,right_shoulder_x,right_shoulder_y,right_shoulder_z,right_elbow_x,right_elbow_y,right_elbow_z,left_hand_x,left_hand_y,left_hand_z,right_hand_x,right_hand_y,right_hand_z,left_hip_x,left_hip_y,left_hip_z,right_hip_x,right_hip_y,right_hip_z,left_knee_x,left_knee_y,left_knee_z,right_knee_x,right_knee_y,right_knee_z,left_foot_x,left_foot_y,left_foot_z,right_foot_x,right_foot_y,right_foot_z
2
+ 1,-0.024967998,-0.43002096,-0.11993482,-0.16634907,-0.6029453,-0.08897782,-0.4108195,-0.60338145,-0.005416114,0.10584397,-0.5481941,-0.07426232,0.32827705,-0.5247129,0.022675084,-0.52109426,-0.53243273,0.017140254,0.5016788,-0.3797387,0.07519173,-0.076798156,-0.84479314,0.23260473,0.011549044,-0.8324699,0.25527912,-0.13188972,-0.38021573,-0.34699273,0.21129197,-0.3468837,-0.24424936,-0.18481304,-0.7210791,-0.18890223,0.20832768,-0.69434476,-0.010231925
3
+ 2,-0.02414888,-0.61061734,-0.09319575,-0.21161069,-0.84490645,-0.06928711,-0.5708368,-0.8908951,0.059444766,0.14638667,-0.77097154,-0.04901571,0.4590649,-0.7769989,0.091104925,-0.75290143,-0.83687013,0.09707974,0.7131239,-0.62381417,0.15956458,-0.100947306,-1.1470639,0.18025766,0.019786028,-1.1333593,0.20328687,-0.14754353,-0.502594,-0.36217874,0.2578762,-0.46165797,-0.27717394,-0.2108277,-0.9108006,-0.1536338,0.24051256,-0.8751469,-0.020496482
4
+ 3,-0.013226548,-0.68977755,0.0025674808,-0.21472667,-0.93940926,0.009742875,-0.63140476,-1.0369221,0.19737546,0.16485368,-0.86013496,0.05515663,0.51786846,-0.9074119,0.24655451,-0.8660449,-1.0319337,0.23498516,0.8194193,-0.7970122,0.32669598,-0.10658018,-1.2373304,0.15459265,0.026427073,-1.2260693,0.18387927,-0.13153192,-0.52633345,-0.47800654,0.2555401,-0.4869593,-0.41701788,-0.18542565,-0.92079663,-0.1525866,0.21814753,-0.8816034,-0.0926064
5
+ 4,0.009047891,-0.7392828,0.034269605,-0.21348421,-1.0154557,0.048781406,-0.7082192,-1.1924334,0.40399614,0.19673905,-0.9361615,0.114488415,0.6077443,-1.0504693,0.47008902,-1.0265698,-1.2705503,0.50487024,0.98468524,-1.0187703,0.6277303,-0.1211725,-1.3116975,0.18193126,0.036616314,-1.3068303,0.22110492,-0.095800996,-0.5379187,-0.6342735,0.24401952,-0.49753776,-0.5616469,-0.14026351,-0.8981151,-0.18917379,0.17222938,-0.85470587,-0.12589683
6
+ 5,0.022042712,-0.7635862,-0.000114143375,-0.21294382,-1.0556674,0.008392397,-0.74880743,-1.265961,0.3608372,0.21619855,-0.97694767,0.07932784,0.65240276,-1.1172265,0.43553036,-1.1018922,-1.3828393,0.4717759,1.055883,-1.1195118,0.5943852,-0.12859234,-1.3574991,0.16084704,0.04362619,-1.3567797,0.20154983,-0.07456537,-0.5522193,-0.644905,0.2309073,-0.51710236,-0.56981236,-0.11017247,-0.8899279,-0.16436917,0.14285906,-0.8433899,-0.09889043
7
+ 6,0.024529304,-0.75996757,-0.0056383465,-0.21581618,-1.061273,-0.008470051,-0.7695494,-1.2810006,0.37713203,0.22194579,-0.98078483,0.09286531,0.66735184,-1.1242925,0.48672962,-1.1351275,-1.4085078,0.5028141,1.0829362,-1.1319119,0.6343571,-0.1297238,-1.3674327,0.22603694,0.04468104,-1.367493,0.27839312,-0.06783855,-0.54800254,-0.6643527,0.22942469,-0.5135493,-0.55100036,-0.107502185,-0.8810016,-0.18776204,0.14075574,-0.832743,-0.09382089
8
+ 7,0.023272803,-0.66779035,-0.0030694534,-0.21766637,-0.9724214,-0.01990227,-0.7603292,-1.1703928,0.2916156,0.22164972,-0.894805,0.049701806,0.6502828,-1.0134927,0.36073697,-1.0994763,-1.2866545,0.40388083,1.0350951,-1.0038729,0.5083502,-0.12637372,-1.2900611,0.07972265,0.045099538,-1.2910244,0.117074266,-0.065368,-0.5273993,-0.5876736,0.21636654,-0.50157505,-0.5127229,-0.10639665,-0.86776555,-0.14148124,0.13927191,-0.8214608,-0.10719744
9
+ 8,0.024705535,-0.58386123,0.066184714,-0.2154029,-0.8957351,0.05501746,-0.7441619,-1.0620182,0.38405702,0.22137682,-0.81881773,0.116502695,0.6260127,-0.9007416,0.43088531,-1.0575076,-1.154499,0.49057716,0.9799235,-0.8617208,0.5862814,-0.117789656,-1.2306415,0.08113742,0.048661944,-1.2322085,0.115060344,-0.05579769,-0.5073569,-0.57003796,0.20506641,-0.4879735,-0.50459844,-0.10860262,-0.8566477,-0.1357212,0.14244123,-0.8165791,-0.102750875
10
+ 9,0.017574131,-0.4862826,0.07338355,-0.21633428,-0.8063493,0.052881967,-0.7213944,-0.9145907,0.42840508,0.21355283,-0.7268078,0.108747296,0.578042,-0.7435104,0.45885223,-0.9810788,-0.94568473,0.5535445,0.8708266,-0.6341384,0.6507237,-0.100756675,-1.1731671,0.03146303,0.053432982,-1.1728935,0.062376928,-0.053147294,-0.5059184,-0.5694852,0.19084024,-0.49864644,-0.5256524,-0.12172098,-0.86682004,-0.1146292,0.15813166,-0.83696455,-0.13403897
11
+ 10,0.020190854,-0.41577786,0.12860602,-0.21093641,-0.7443312,0.10429788,-0.7071521,-0.82721794,0.47614226,0.21497853,-0.66419536,0.17117976,0.56014085,-0.65089965,0.53289694,-0.94455075,-0.82837987,0.5848937,0.8239665,-0.5062333,0.7031617,-0.08906301,-1.1311117,0.03648026,0.060196083,-1.1307741,0.07144055,-0.047073282,-0.5004439,-0.552691,0.1867086,-0.49835464,-0.50169647,-0.12932019,-0.8585285,-0.08873396,0.16726677,-0.8361604,-0.08473495
12
+ 11,0.02781475,-0.31052482,0.16056702,-0.20111583,-0.64346623,0.13345166,-0.67857987,-0.69987077,0.5337809,0.21901684,-0.5667577,0.20293851,0.5436546,-0.52811015,0.5958343,-0.89461833,-0.68247557,0.65845007,0.7852174,-0.36315736,0.77966887,-0.08074329,-1.0496901,0.020843035,0.0649163,-1.05041,0.05524949,-0.042777497,-0.47735226,-0.5539148,0.18597901,-0.47773105,-0.5015852,-0.13148953,-0.82632196,-0.09383124,0.17361589,-0.8074571,-0.10430949
13
+ 12,0.03499816,-0.29470032,0.10651444,-0.19561177,-0.6352916,0.07668292,-0.6789569,-0.69094855,0.40371385,0.22329937,-0.5617383,0.13981663,0.55088407,-0.518373,0.4641862,-0.911031,-0.6797424,0.5041157,0.80665886,-0.3588746,0.60854846,-0.082945846,-1.0455476,-0.057555754,0.06586339,-1.048193,-0.028248725,-0.036412034,-0.4701197,-0.5196088,0.18348567,-0.47469482,-0.4757585,-0.12709771,-0.80234224,-0.08741084,0.16847353,-0.7814256,-0.10876298
14
+ 13,0.037818126,-0.25092977,0.073557675,-0.19253306,-0.596006,0.03880195,-0.675931,-0.6506023,0.32225707,0.2240776,-0.52803093,0.0987095,0.55121386,-0.48300922,0.38608462,-0.9083958,-0.6431865,0.41184688,0.80378884,-0.32687035,0.51049966,-0.08691648,-1.005896,-0.13236938,0.063660055,-1.0102956,-0.10515933,-0.0350925,-0.4613651,-0.52169293,0.17463525,-0.47445127,-0.4849976,-0.12315126,-0.778575,-0.095966354,0.16116282,-0.75511146,-0.12360523
15
+ 14,0.052978832,-0.16701533,0.19423673,-0.1688662,-0.5124306,0.17419684,-0.6254804,-0.5407258,0.6804645,0.23472814,-0.45056424,0.22832853,0.53865457,-0.39336902,0.69231105,-0.8216678,-0.51441634,0.87169135,0.75083494,-0.22003047,0.9471732,-0.075556934,-0.9305056,-0.020171937,0.07222251,-0.93654644,0.008004425,-0.03099946,-0.45198303,-0.5782114,0.18433292,-0.46745718,-0.51964563,-0.12751013,-0.7272324,-0.116691776,0.17193404,-0.7083499,-0.14867833
16
+ 15,0.007154687,-0.04653315,0.2044721,-0.22356796,-0.41391316,0.17375821,-0.7048898,-0.47962978,0.6450333,0.19241618,-0.33398438,0.2308414,0.50680596,-0.3152617,0.67156047,-0.87542003,-0.49308464,0.8246429,0.6989828,-0.17722756,0.90898675,-0.09571954,-0.82781863,-0.057988536,0.03684979,-0.82793427,-0.03299932,-0.03786193,-0.39966807,-0.518352,0.15391846,-0.3795176,-0.46638972,-0.122510225,-0.72770303,-0.1114996,0.15286076,-0.68134403,-0.16496184
17
+ 16,-0.030549519,0.026343836,0.082283676,-0.27262565,-0.35879228,0.022534918,-0.7886123,-0.4679009,0.35129222,0.15988685,-0.26162165,0.13095927,0.49447125,-0.28259027,0.52818817,-0.95666873,-0.5246529,0.53289497,0.6873422,-0.18569648,0.6827554,-0.11426451,-0.76392305,-0.32541722,0.008480151,-0.7593226,-0.2952911,-0.04023534,-0.3581588,-0.53012073,0.12616858,-0.31059688,-0.5373486,-0.11554043,-0.7388911,-0.09479359,0.13152616,-0.67350435,-0.27719963
18
+ 17,-0.017396213,0.22256497,-0.037545063,-0.23314069,-0.13409738,-0.087940976,-0.69369805,-0.2351123,0.29224744,0.16808541,-0.018479852,-0.06705817,0.46268135,-0.11452953,0.30796984,-0.7288793,-0.28886288,0.380314,0.5658634,-0.019348912,0.5018317,-0.072220385,-0.4884954,-0.1657466,-0.0026780316,-0.47820404,-0.13140927,-0.060764905,-0.22931616,-0.26292428,0.19590475,-0.15439714,-0.62978554,-0.20807345,-0.58697164,0.19955347,0.23814176,-0.537924,-0.21788627
19
+ 18,-0.04098874,0.28373918,0.015594545,-0.26292372,-0.078799605,-0.031958744,-0.7356199,-0.19730926,0.34115997,0.1468724,0.050529156,0.008519974,0.45004827,-0.06127154,0.390431,-0.7730339,-0.27023926,0.44570178,0.5607917,0.0106240725,0.5945268,-0.07854575,-0.4346433,-0.1107735,-0.018237554,-0.41990554,-0.07451986,-0.06297732,-0.19384296,-0.27253804,0.18943614,-0.09115834,-0.55203974,-0.20324814,-0.5922176,0.17151111,0.23071682,-0.533481,-0.15357815
20
+ 19,-0.043162398,0.3864855,-0.25371343,-0.25213242,0.043076288,-0.3164339,-0.7004571,-0.08095757,-0.12652276,0.14128825,0.1796152,-0.007924065,0.4338347,0.024758397,0.6316918,-0.6882822,-0.16299605,0.44481707,0.5236024,0.08547923,0.7834527,-0.06646228,-0.2749815,-0.3544545,-0.035133053,-0.2565814,-0.3190019,-0.07612187,-0.096065745,0.1790697,0.21596159,0.023301492,-0.2644672,-0.2539412,-0.49832407,0.4471255,0.2822029,-0.44072542,-0.63122314
21
+ 20,0.012587316,0.43754143,0.055150483,-0.17047799,0.13121313,0.031084474,-0.5629589,0.049790066,0.4319456,0.18831153,0.25349373,0.067976125,0.44879797,0.09479564,0.46217877,-0.5033636,0.006436485,0.5483463,0.5111903,0.1896561,0.673778,-0.025714535,-0.15835302,-0.015877694,-0.01094421,-0.14374593,0.017455729,-0.076313026,-0.037340824,-0.37139443,0.2790233,0.06154625,-0.50823146,-0.313239,-0.3580276,0.076294236,0.3598086,-0.33197254,-0.076949954
22
+ 21,0.057457976,0.5215612,0.008790615,-0.09625772,0.25307402,-0.055573914,-0.42499578,0.20996904,0.22541209,0.22356088,0.36494875,0.14645198,0.44736782,0.18881953,0.6916029,-0.29525286,0.19703001,0.6543524,0.46652243,0.3118246,0.8746148,0.013606155,0.0021561757,-0.30168,0.0024682037,0.015206924,-0.2737049,-0.0853603,0.040528364,-0.02998759,0.34487534,0.12735905,-0.2476353,-0.38467884,-0.20833233,0.18392104,0.44885412,-0.2070623,-0.43012595
23
+ 22,0.052833375,0.5201032,0.013005215,-0.104124606,0.2501646,-0.041123416,-0.4257887,0.2304849,0.25110134,0.21570313,0.3449106,0.1607988,0.43727365,0.22590245,0.71962255,-0.33683908,0.23850743,0.6845193,0.48146528,0.3687996,0.90729433,-0.0016149875,-0.025322689,-0.285101,0.0061833593,-0.014521397,-0.25985363,-0.0776624,0.025289994,0.025305672,0.31407675,0.103184804,-0.21334043,-0.35393432,-0.2317183,0.23211084,0.41210696,-0.2231072,-0.4127522
24
+ 23,0.081244685,0.6535795,-0.028697666,-0.045099627,0.4228617,-0.07924897,-0.2971248,0.43790504,0.19633518,0.23537232,0.51381063,0.13297658,0.4137002,0.36446056,0.7057569,-0.10787404,0.47456518,0.6783065,0.39242417,0.5351378,0.9028283,0.03430652,0.19291702,-0.28066742,0.0058976803,0.2047429,-0.25643876,-0.09717406,0.12213553,0.104816794,0.37661177,0.19908547,-0.15258974,-0.44211748,-0.08444937,0.25307,0.5122515,-0.09268303,-0.4341644
25
+ 24,0.07335723,0.7014076,0.030060131,-0.047837466,0.4857009,-0.010854894,-0.28781793,0.49869964,0.26666105,0.22722428,0.5812788,0.15496309,0.40140757,0.41382957,0.6591808,-0.07850506,0.53205395,0.67609185,0.3742166,0.5796362,0.85145336,0.03813192,0.2749377,-0.23203191,-0.005520275,0.28933087,-0.21209028,-0.113845535,0.1553861,0.026525063,0.39192867,0.2393343,-0.15453354,-0.47179133,-0.06873234,0.16127054,0.54124016,-0.07526341,-0.3546225
26
+ 25,0.06814824,0.71703726,-0.07693544,-0.046309967,0.51717025,-0.11905854,-0.26763597,0.5325772,0.13743146,0.21947436,0.61688024,0.09807851,0.38755864,0.43638307,0.6729511,-0.039820097,0.56336665,0.65506923,0.3558808,0.5976023,0.8820849,0.041529186,0.33024812,-0.24008393,-0.015931686,0.34714416,-0.21708867,-0.13027024,0.18418148,0.2048834,0.40969798,0.2734485,-0.09072301,-0.5012408,-0.053700242,0.32038826,0.5718045,-0.059774447,-0.4283529
27
+ 26,0.066361904,0.7300952,-0.118019216,-0.046485677,0.5332344,-0.15796795,-0.26361412,0.5489896,0.07103729,0.21833867,0.6357992,0.06318332,0.38387173,0.4491255,0.62610924,-0.026184306,0.57956195,0.59784365,0.34566766,0.6091911,0.82703084,0.04369943,0.35052353,-0.24669352,-0.017974982,0.3680935,-0.22475246,-0.13423328,0.18685015,0.23658177,0.41394094,0.2771948,-0.07126081,-0.509324,-0.05521239,0.3340324,0.580071,-0.06361486,-0.4328624
28
+ 27,0.06360658,0.7668551,-0.09329257,-0.045802087,0.5771864,-0.1354443,-0.25386733,0.59278184,0.101657584,0.21511292,0.68354017,0.080496676,0.37727425,0.48516256,0.6424117,-0.0023396355,0.6201277,0.62531316,0.33393848,0.6408795,0.84900945,0.047165513,0.4075718,-0.23559794,-0.024663053,0.42650807,-0.21363828,-0.14121324,0.20905633,0.22381285,0.4238731,0.30287403,-0.063659444,-0.52808166,-0.04171351,0.30341667,0.5991162,-0.051625885,-0.43240446
29
+ 28,0.065535836,0.7421878,-0.070998274,-0.04533498,0.54725766,-0.12915745,-0.25304073,0.56763023,0.10595347,0.21622518,0.6502264,0.100352325,0.3772321,0.4649783,0.66840005,-0.011381428,0.5994352,0.6120852,0.33622715,0.6235447,0.85955983,0.044342425,0.36729985,-0.279044,-0.019547392,0.38513896,-0.25368837,-0.13523518,0.18971802,0.18516529,0.41528797,0.28022003,-0.11855517,-0.5122194,-0.055381738,0.31802815,0.58361775,-0.06518331,-0.45898423
30
+ 29,0.06894657,0.7080616,-0.024275785,-0.045256577,0.50274897,-0.06866373,-0.2566514,0.52902013,0.18610142,0.21893732,0.6008613,0.12547335,0.38027352,0.43652043,0.6677839,-0.032491356,0.567396,0.6782442,0.34522852,0.6003291,0.8795088,0.039695796,0.30566153,-0.23226899,-0.01138334,0.32169828,-0.21258846,-0.123397194,0.16198921,0.20169237,0.40058964,0.24695894,-0.03711687,-0.48702475,-0.07487579,0.2514776,0.55862606,-0.08496612,-0.38822493
31
+ 30,0.07131534,0.68522894,-0.035644926,-0.049536064,0.46434096,-0.080997474,-0.2723258,0.49782002,0.16610236,0.22229713,0.5548915,0.10932804,0.38639987,0.42188397,0.6227061,-0.079544775,0.54436857,0.6025198,0.36521906,0.5933434,0.80000144,0.032383688,0.23686719,-0.24764335,-0.00038999147,0.25030035,-0.22497925,-0.105261125,0.1245204,0.07220529,0.37601712,0.20299082,-0.16038077,-0.4484833,-0.10309605,0.22329207,0.51971,-0.11178865,-0.3993556
32
+ 31,0.07267108,0.64013773,-0.023243826,-0.056171037,0.40247497,-0.073404305,-0.29228523,0.4429945,0.17088152,0.22520426,0.48627374,0.11223952,0.3932173,0.38672748,0.6110275,-0.13761263,0.4967748,0.5849863,0.39036956,0.5639689,0.7789126,0.023855386,0.14097963,-0.2594543,0.011881955,0.15174899,-0.23598784,-0.08747738,0.07364186,0.028246565,0.3499229,0.14514323,-0.18704231,-0.40522966,-0.14520226,0.19491369,0.47630218,-0.15292677,-0.3973155
33
+ 32,0.04744854,0.53161496,0.04441225,-0.10888696,0.2610721,-0.0007314082,-0.40325737,0.27477273,0.29276,0.20835543,0.34954333,0.15423264,0.4072571,0.28238207,0.6472705,-0.32645497,0.30980408,0.66985077,0.45081115,0.44128078,0.83247596,-0.0033979372,-0.046972614,-0.26495853,0.01616153,-0.037153453,-0.24400625,-0.07185076,-0.01455532,-0.050620873,0.29279056,0.055422995,-0.21259613,-0.32708782,-0.2896302,0.13744968,0.38589832,-0.28676873,-0.3397671
34
+ 33,-0.0048352405,0.49311218,0.03862613,-0.18773037,0.18163985,-0.021670064,-0.5409614,0.1558977,0.2500906,0.16569617,0.28228897,0.13775659,0.39228806,0.22504115,0.5999424,-0.5055533,0.1605796,0.5718455,0.4522495,0.35930207,0.7505857,-0.04074443,-0.16524498,-0.3137786,-0.0021163793,-0.15278439,-0.2891364,-0.06784279,-0.08556174,-0.1553202,0.22313786,0.00045711844,-0.32087347,-0.2631417,-0.43815497,0.12707976,0.3023237,-0.4078196,-0.3578511
35
+ 34,-0.060146887,0.47034582,0.009051221,-0.26976264,0.11856279,-0.008589447,-0.68317777,0.050394475,0.27229816,0.12027015,0.23297356,0.0387916,0.3750957,0.18051977,0.33516556,-0.6842449,0.021443788,0.33282572,0.44895822,0.28785926,0.48901862,-0.0788544,-0.2628517,-0.023839194,-0.024343956,-0.24731131,0.0065647196,-0.06672142,-0.14617996,-0.31393138,0.15254238,-0.04328699,-0.4026435,-0.2039698,-0.5816791,0.080756076,0.22163889,-0.52222264,-0.0005605244
36
+ 35,-0.0695247,0.2963787,-0.06714642,-0.298763,-0.07107652,-0.112595156,-0.75714207,-0.16068976,0.20434915,0.11685931,0.043539856,-0.101768516,0.40362772,0.012030657,0.20926441,-0.83714503,-0.20649055,0.2588036,0.5363284,0.102895945,0.36723512,-0.09990322,-0.47740605,-0.17303236,-0.01692996,-0.46382394,-0.14322671,-0.06149266,-0.24536607,-0.232485,0.123406075,-0.15636835,-0.6037265,-0.15404364,-0.71064675,0.19416262,0.16494465,-0.64645594,-0.22303624
37
+ 36,-0.0794205,0.12395796,-0.07303181,-0.32583916,-0.25359792,-0.12455183,-0.8305728,-0.37010232,0.19680856,0.112323485,-0.13954115,-0.112774745,0.43632314,-0.15814805,0.20527269,-0.9876604,-0.4367054,0.2506146,0.63204515,-0.083222136,0.36775744,-0.12134151,-0.6688927,-0.20164356,-0.014900536,-0.65669626,-0.17138283,-0.062395245,-0.32492673,-0.22727713,0.102440335,-0.24791783,-0.62020415,-0.118459605,-0.8224018,0.19997607,0.122652195,-0.7491057,-0.25502822
38
+ 37,-0.06005143,0.0352049,0.13248606,-0.30377,-0.33852765,0.12091838,-0.8071644,-0.44570714,0.5018129,0.13135129,-0.23353572,0.16734454,0.4593936,-0.24272567,0.52766585,-0.98473096,-0.50364023,0.62665313,0.6739943,-0.15651849,0.7124744,-0.118355,-0.75659525,0.0021275538,-0.0015399546,-0.74743414,0.029427523,-0.059231438,-0.3701834,-0.50164354,0.11520378,-0.30940554,-0.44731057,-0.11885921,-0.8309194,-0.053768713,0.13082705,-0.76218826,-0.044708718
39
+ 38,-0.015634187,-0.09442303,0.14246754,-0.25418475,-0.44918096,0.13733998,-0.7454039,-0.5302048,0.56891716,0.17354535,-0.36044574,0.18550691,0.5028225,-0.33986953,0.5867544,-0.9631595,-0.5628434,0.71781737,0.7533641,-0.23057339,0.79119474,-0.102146275,-0.8693373,0.015444489,0.031179367,-0.8659165,0.043872662,-0.050019898,-0.41655585,-0.5410843,0.14500882,-0.388982,-0.4822972,-0.118696995,-0.8281381,-0.08073149,0.14445372,-0.7841055,-0.07525381
40
+ 39,0.02983219,-0.27769747,0.11246711,-0.20525846,-0.6142157,0.100273326,-0.697147,-0.67981136,0.4784014,0.2181813,-0.54061246,0.14875236,0.55983204,-0.49847567,0.5078597,-0.9729084,-0.6950254,0.6017671,0.863553,-0.37270322,0.68155843,-0.08848679,-1.0301002,-0.036404368,0.06396461,-1.0325254,-0.008970277,-0.039066337,-0.4713133,-0.51518846,0.17857443,-0.4753464,-0.4632356,-0.11761328,-0.82922477,-0.073566675,0.15714084,-0.8077329,-0.073376544
41
+ 40,0.030059813,-0.34321827,0.097525984,-0.2060767,-0.6829585,0.0784561,-0.71529114,-0.7645289,0.4069073,0.22139087,-0.6071268,0.12995547,0.57384443,-0.5800509,0.44640082,-0.9921827,-0.78395814,0.50323987,0.8772989,-0.45088375,0.5927576,-0.08993733,-1.0868587,-0.020415608,0.06292554,-1.0894337,0.007609332,-0.038025443,-0.4831975,-0.50270903,0.1815902,-0.48637384,-0.45890912,-0.122634694,-0.8363079,-0.06801194,0.16087233,-0.8131407,-0.0750723
42
+ 41,0.03195446,-0.42882866,0.14583847,-0.20688184,-0.7683925,0.13212827,-0.7301786,-0.87196916,0.5396811,0.22435111,-0.6916035,0.18993089,0.59039867,-0.6889693,0.57277906,-1.0171556,-0.9080522,0.6657609,0.9068001,-0.5751068,0.7600776,-0.09716977,-1.1542708,0.051134977,0.05919559,-1.1574967,0.08382375,-0.03720799,-0.48852116,-0.5549105,0.18601947,-0.48833665,-0.5002594,-0.12235691,-0.83334094,-0.088992774,0.157495,-0.8056331,-0.08195632
43
+ 42,0.033320114,-0.5754316,0.17172968,-0.21139044,-0.91698426,0.15556721,-0.76927626,-1.0641346,0.6176048,0.23003294,-0.8348044,0.22200626,0.62718487,-0.87482524,0.6520606,-1.0874143,-1.1349602,0.77348316,0.97790426,-0.7924919,0.8707079,-0.10684803,-1.2752603,0.059875518,0.05557548,-1.2786304,0.09450272,-0.034777436,-0.5043957,-0.6007901,0.19521707,-0.49766806,-0.5370576,-0.11894582,-0.8415272,-0.11958732,0.15219763,-0.807679,-0.11469011
44
+ 43,0.029600954,-0.6634475,0.15630412,-0.21635638,-1.0006791,0.13631403,-0.7877781,-1.1722142,0.6253385,0.22888352,-0.9173746,0.21673757,0.64397097,-0.98501945,0.67592484,-1.1185095,-1.2629759,0.8047919,1.0088989,-0.92411405,0.908187,-0.11629235,-1.3374423,0.09125228,0.049924094,-1.340474,0.13234939,-0.039107792,-0.5174464,-0.6623873,0.1977912,-0.5079838,-0.5772163,-0.11446328,-0.84967935,-0.15762171,0.14593227,-0.808882,-0.13609351
45
+ 44,0.031246021,-0.7456626,0.107513204,-0.21826005,-1.0795842,0.095280156,-0.8089694,-1.2876856,0.59942436,0.2329833,-0.99411976,0.1839411,0.67384094,-1.1021429,0.66156447,-1.1694511,-1.411436,0.78121054,1.073952,-1.0777793,0.89531094,-0.124766216,-1.3969917,0.12800357,0.047023553,-1.4000306,0.17523238,-0.04103094,-0.52878034,-0.7347359,0.20810165,-0.51148206,-0.64259565,-0.10904517,-0.85623264,-0.16437396,0.14087516,-0.81025934,-0.11817902
46
+ 45,0.030035976,-0.84585667,0.040436264,-0.2204664,-1.1723188,0.023950074,-0.82349014,-1.4126109,0.38200507,0.2333045,-1.0840421,0.0885813,0.6965323,-1.2312021,0.42940915,-1.2054198,-1.5586874,0.50751877,1.123604,-1.2353098,0.60529554,-0.13206369,-1.4722458,0.08887128,0.04416928,-1.4741646,0.1246635,-0.04721503,-0.5498324,-0.61323065,0.22053297,-0.52239394,-0.5501608,-0.106527455,-0.87312347,-0.14884588,0.13846982,-0.82243574,-0.13895318
47
+ 46,0.022933088,-0.9247158,0.03556187,-0.22558503,-1.2442796,0.03403582,-0.8370996,-1.50359,0.44721785,0.22877641,-1.1498007,0.11591417,0.70536697,-1.319879,0.52307,-1.2258257,-1.6511116,0.585184,1.1426209,-1.328174,0.7032502,-0.1313143,-1.5365305,0.15497585,0.043219246,-1.535426,0.20010866,-0.057043303,-0.5789138,-0.67909175,0.23184606,-0.54367316,-0.5898861,-0.111570455,-0.9080902,-0.16700068,0.1460037,-0.8571436,-0.10017924
48
+ 47,0.010790251,-0.84531343,0.03545061,-0.22158709,-1.1380284,0.041519407,-0.76031405,-1.3407024,0.42913243,0.20892377,-1.0535942,0.120587446,0.64003086,-1.1875377,0.50277656,-1.0794197,-1.4341366,0.54273695,1.0072117,-1.1565472,0.66954005,-0.12348783,-1.4453121,0.21671855,0.04097887,-1.4419003,0.2628229,-0.08096054,-0.5925072,-0.7020398,0.22652759,-0.56490964,-0.61788285,-0.1223385,-0.93139946,-0.19732541,0.15625729,-0.88841015,-0.12462552
49
+ 48,0.0036226215,-0.78691053,0.008665851,-0.21581858,-1.0596783,0.025326494,-0.6968408,-1.2166605,0.41699675,0.19407699,-0.9816566,0.098062806,0.58868873,-1.0844705,0.48732352,-0.96952564,-1.2681135,0.53246456,0.91160536,-1.0216049,0.6627365,-0.11553718,-1.3774989,0.2114047,0.039597075,-1.3722273,0.25618625,-0.09948036,-0.5982906,-0.7197473,0.23054104,-0.57156914,-0.64181316,-0.13808611,-0.94753474,-0.20045204,0.1721196,-0.9114915,-0.12786175
50
+ 49,-0.008115099,-0.73289156,-0.14425541,-0.21192874,-0.9800142,-0.12965763,-0.6242146,-1.0754312,-0.08043971,0.17362869,-0.9072904,-0.12580138,0.5220053,-0.9631782,-0.07453658,-0.83205366,-1.0670006,-0.10844222,0.7857832,-0.8524035,-0.063993044,-0.10596263,-1.3080554,0.049540337,0.037480403,-1.2994324,0.060351912,-0.12591347,-0.5999667,-0.48802397,0.23590331,-0.5739321,-0.37617636,-0.15735452,-0.9651723,-0.22107367,0.19198947,-0.9326573,-0.073545255
51
+ 50,-0.019777363,-0.71168065,-0.13240965,-0.21384683,-0.9433229,-0.12444708,-0.5901511,-1.0079603,-0.10792533,0.15754469,-0.87091297,-0.116469614,0.48518628,-0.90344465,-0.08757432,-0.7642039,-0.9668787,-0.13821852,0.72341746,-0.76257956,-0.08704329,-0.10189326,-1.2665734,0.05021001,0.030404523,-1.2544879,0.06409191,-0.14815012,-0.583812,-0.3906068,0.24675901,-0.55449456,-0.31200084,-0.18311228,-0.96294147,-0.17100972,0.21517292,-0.93025535,-0.056549612
52
+ 51,-0.029609213,-0.6111115,-0.15480736,-0.21536456,-0.8312672,-0.13658892,-0.550558,-0.8584026,-0.110540085,0.14332369,-0.7620933,-0.11336934,0.44392803,-0.7626019,-0.059852123,-0.6911185,-0.78509325,-0.1455294,0.65878624,-0.59491014,-0.0598404,-0.09743078,-1.1637237,0.15434363,0.024606327,-1.1492499,0.17949641,-0.16277906,-0.55103076,-0.41789523,0.2501383,-0.51775044,-0.36535063,-0.20297277,-0.9458148,-0.13326868,0.23377302,-0.9140967,-0.038446397
53
+ 52,-0.034604784,-0.6367072,-0.044328958,-0.2243854,-0.8651859,-0.023074968,-0.5909432,-0.92176557,0.22749726,0.14245561,-0.78645617,0.018413667,0.46823403,-0.807683,0.2730782,-0.7635301,-0.86116076,0.3070609,0.7290457,-0.6458291,0.39902115,-0.1007771,-1.1881236,0.24581212,0.018121017,-1.170995,0.28129733,-0.165472,-0.5277078,-0.53714454,0.26665375,-0.47730637,-0.4523361,-0.2211554,-0.928618,-0.19579762,0.25071502,-0.8886933,-0.06412574
54
+ 53,-0.04193799,-0.66294456,-0.058457445,-0.2368667,-0.89673674,-0.03657858,-0.6347506,-0.98385006,0.2109613,0.14010149,-0.8101263,-0.0066729374,0.49322104,-0.8559203,0.2358649,-0.831904,-0.9344117,0.28437728,0.7946123,-0.69909555,0.35244834,-0.10680722,-1.210937,0.16566065,0.009056156,-1.1910857,0.194968,-0.17077632,-0.50354946,-0.5209059,0.27934638,-0.43709987,-0.4495787,-0.24003208,-0.90659755,-0.1555896,0.26591736,-0.8563742,-0.05085176
55
+ 54,-0.047971185,-0.626659,-0.041103423,-0.24305668,-0.86307055,-0.021941662,-0.646035,-0.9590687,0.24239035,0.13579589,-0.7750252,0.007945154,0.4953666,-0.8293575,0.26522756,-0.8442446,-0.9070664,0.32759643,0.80728495,-0.66490793,0.39242566,-0.10953838,-1.1744919,0.16926251,0.00032625798,-1.1531658,0.19893186,-0.17358038,-0.47494265,-0.5204724,0.2832004,-0.40080714,-0.44590315,-0.25883308,-0.87991786,-0.16177207,0.28082156,-0.8245937,-0.047528177
56
+ 55,-0.06596061,-0.4196215,-0.047312506,-0.25220752,-0.6405507,-0.03437469,-0.6019773,-0.69498473,0.19244365,0.11231881,-0.5624591,-0.0136328805,0.4451997,-0.58382255,0.20949651,-0.7620113,-0.6092367,0.27926594,0.7371782,-0.3947922,0.3305024,-0.11350987,-0.96868545,0.1474194,-0.015733713,-0.94515,0.1724582,-0.19328605,-0.4322505,-0.43176603,0.28222698,-0.35398582,-0.3884386,-0.28759256,-0.8527587,-0.12879765,0.30817676,-0.7962622,-0.044709917
57
+ 56,-0.098083116,-0.124883115,-0.054785818,-0.27594066,-0.32324332,-0.042036936,-0.57057273,-0.34654745,0.10856278,0.07336958,-0.26217616,-0.026328804,0.38701695,-0.26372498,0.12543263,-0.69330317,-0.23103285,0.16053183,0.6642477,-0.057149757,0.20353284,-0.12742862,-0.6784661,0.14652167,-0.052997787,-0.6531698,0.16735163,-0.25961655,-0.3973437,-0.3636153,0.31229582,-0.31950122,-0.2954799,-0.36466137,-0.8454295,-0.13622205,0.37646055,-0.7959223,-0.012431735
58
+ 57,-0.117018975,0.25144464,-0.11807093,-0.2908982,0.06691498,-0.08412305,-0.53542686,0.07503261,0.056231048,0.049069073,0.114369676,-0.12828834,0.33636183,0.11444169,-0.006662933,-0.59604144,0.21165694,0.15750585,0.5703068,0.32401842,0.07897305,-0.13596354,-0.31949532,0.11687501,-0.08877346,-0.2960728,0.1132994,-0.3499292,-0.35080028,-0.09832272,0.37950823,-0.27438948,-0.057775237,-0.47999558,-0.8347976,-0.11542002,0.47638673,-0.8015664,-0.036116052
59
+ 58,-0.14211887,0.53075945,-0.2463722,-0.30963382,0.3562199,-0.13939299,-0.5067433,0.37733915,0.088536724,0.015703693,0.39523366,-0.30419546,0.28277466,0.37516713,-0.14066319,-0.50972444,0.5128726,0.24055211,0.48302534,0.57140267,-0.055588264,-0.15208896,-0.04460803,-0.084918834,-0.12979573,-0.021264095,-0.13518137,-0.43408126,-0.33683777,0.1534571,0.44218814,-0.25871664,0.08393689,-0.58612204,-0.8516703,-0.052590378,0.5726651,-0.8312559,-0.22246063
60
+ 59,-0.14468373,0.58150554,-0.2539165,-0.30479503,0.42175373,-0.17222705,-0.46815562,0.47487208,-0.021824557,0.0083506415,0.45167747,-0.2234433,0.24759208,0.45827708,-0.008173404,-0.44204974,0.6323354,0.14590882,0.40544868,0.667878,-0.006215114,-0.14877565,0.005621305,-0.17315821,-0.12761484,0.027414853,-0.20477292,-0.4633923,-0.36458924,0.37780914,0.4429642,-0.2978475,0.15939903,-0.59061456,-0.87995505,0.2530141,0.5747904,-0.8670689,-0.2737254
61
+ 60,-0.1479219,0.6764391,-0.3141335,-0.31129456,0.518174,-0.21181631,-0.46867135,0.56401014,-0.0770106,0.0041421345,0.5446301,-0.30564997,0.22927694,0.5288666,-0.12237814,-0.4217166,0.7073542,0.090525016,0.36186802,0.71530646,-0.13282451,-0.15598136,0.080740765,-0.119778566,-0.13931012,0.09866087,-0.1583537,-0.53576714,-0.39049554,0.3813593,0.5039164,-0.33103514,0.1139737,-0.65525347,-0.9242032,0.22688277,0.6335826,-0.9260258,-0.36330643
62
+ 61,-0.112428494,0.6516762,-0.28164583,-0.27228823,0.48476937,-0.21808204,-0.41435945,0.5721357,-0.338148,0.037153058,0.51116943,-0.27431726,0.22025594,0.5418745,-0.40830353,-0.35830677,0.7346207,-0.45378634,0.3109234,0.74812835,-0.4987687,-0.12974112,0.037116982,0.054869857,-0.097141206,0.050591093,0.047649644,-0.47279274,-0.39420414,-0.21247844,0.45173174,-0.34420973,-0.24851237,-0.57550097,-0.9103184,-0.061501224,0.56391966,-0.91013205,-0.06422504
63
+ 62,-0.09103554,0.5547939,-0.33249456,-0.24270572,0.38905492,-0.20309092,-0.3632189,0.5197957,-0.19746445,0.05510991,0.41152126,-0.3039917,0.2048554,0.5094369,-0.30647743,-0.32080173,0.7102199,-0.21825275,0.2806625,0.7493054,-0.41792518,-0.10913862,-0.062063176,-0.058699314,-0.055535793,-0.049201995,-0.09165037,-0.38424742,-0.40785474,0.17509207,0.36072242,-0.3676058,0.0013949955,-0.4564941,-0.8993815,0.21680887,0.46103308,-0.8881922,-0.16287842
64
+ 63,-0.05450813,0.51899403,-0.13416813,-0.20222828,0.34960678,-0.11314775,-0.30940634,0.53419816,-0.16079761,0.0909899,0.36306226,-0.1398728,0.20537688,0.5436428,-0.19091126,-0.29342833,0.7632361,-0.19823475,0.26289412,0.81832844,-0.21972354,-0.081040986,-0.12460665,-0.1608541,-0.0010121474,-0.11632469,-0.16703326,-0.28938067,-0.40498132,-0.14201446,0.26948807,-0.38302714,-0.14130121,-0.3259743,-0.8667137,-0.048198007,0.3433392,-0.8521733,-0.026648559
65
+ 64,-0.042475343,0.68199605,-0.12477704,-0.19070338,0.49985614,-0.10424075,-0.28930712,0.7044905,-0.13756119,0.10223628,0.5080706,-0.12688246,0.20154704,0.7129844,-0.16148733,-0.28028125,0.93971777,-0.15515603,0.25866067,0.98965454,-0.17811911,-0.074580766,0.0043733316,-0.1290907,0.00983741,0.009931089,-0.13458927,-0.24925196,-0.36964312,-0.100701116,0.24004623,-0.35108078,-0.09211344,-0.29674906,-0.83008087,-0.04426422,0.3178232,-0.81786835,-0.015314525
66
+ 65,-0.015421361,0.70412195,-0.05613072,-0.1580778,0.51341116,-0.05630099,-0.24399723,0.7617416,-0.10672235,0.12749,0.5160716,-0.062375423,0.20367083,0.782771,-0.10825008,-0.24982002,1.0275607,-0.14774327,0.24880569,1.0912722,-0.14606719,-0.050537985,0.004624112,-0.13816565,0.04755968,0.0082393605,-0.1403145,-0.15033801,-0.3539091,-0.12458016,0.14806692,-0.34366027,-0.11993563,-0.18704289,-0.7849262,-0.054021556,0.21779928,-0.76643765,-0.054414142
67
+ 66,-0.020704431,0.7520492,-0.06792267,-0.16945045,0.5677246,-0.06512402,-0.2608206,0.7972916,-0.13405524,0.12612762,0.56928235,-0.07403793,0.21310808,0.80878955,-0.13801304,-0.27025154,1.049148,-0.19156432,0.27208728,1.0949885,-0.18866193,-0.060757264,0.05601455,-0.107895695,0.03444517,0.05866107,-0.10995118,-0.2166279,-0.33557197,-0.12861313,0.22244187,-0.32584035,-0.12734224,-0.25846136,-0.7844915,-0.048477218,0.2840549,-0.7725242,-0.050498277
68
+ 67,-0.01610525,0.7042563,-0.08332976,-0.16527677,0.51752514,-0.076051556,-0.2592773,0.7456311,-0.13631332,0.13039204,0.5196528,-0.08621372,0.2154866,0.7549845,-0.14288984,-0.26969185,0.99476856,-0.18406567,0.26734722,1.0367528,-0.1867298,-0.060580086,0.0016844496,-0.12794746,0.039319918,0.0031913407,-0.12989342,-0.21478525,-0.35613227,-0.14799643,0.22044815,-0.34970567,-0.14740452,-0.24793471,-0.7975488,-0.05712388,0.2736901,-0.7896914,-0.05379279
69
+ 68,-0.020051334,0.54722637,-0.22476086,-0.16854317,0.3726211,-0.12172642,-0.26833263,0.58511347,-0.12726885,0.12784185,0.37945467,-0.17425506,0.2179707,0.5958597,-0.20001361,-0.27415797,0.826602,-0.16845037,0.26536033,0.87294936,-0.29767343,-0.061312173,-0.12899256,-0.17603597,0.03729878,-0.12612677,-0.19676138,-0.24677104,-0.38876584,0.065785706,0.24592133,-0.38252655,0.054732867,-0.2648463,-0.82745504,0.17284514,0.2881745,-0.8196524,0.08292069
70
+ 69,-0.029047199,0.426036,-0.11189928,-0.17737702,0.26567683,-0.104333445,-0.28056654,0.4612519,-0.19981429,0.11890579,0.27520204,-0.11958446,0.21817496,0.47107446,-0.2113361,-0.28597945,0.6941025,-0.2795303,0.27133664,0.740662,-0.27814773,-0.06775988,-0.21922764,-0.10852539,0.02591972,-0.21492952,-0.11018944,-0.29572663,-0.4068969,-0.18177928,0.2889417,-0.39897847,-0.18958907,-0.3038112,-0.8512732,-0.051461063,0.3234812,-0.8422887,-0.05552731
71
+ 70,-0.044211455,0.34814957,-0.23955487,-0.19622727,0.20061325,-0.18574463,-0.30584556,0.36622646,-0.32669437,0.103588775,0.21357523,-0.21965525,0.21968538,0.3683676,-0.37055677,-0.30529606,0.579779,-0.4640936,0.28272378,0.6185332,-0.486178,-0.08254976,-0.26677716,-0.014552604,0.002023819,-0.26107234,-0.017615398,-0.3705754,-0.42134023,-0.28734952,0.35899335,-0.41043139,-0.31054232,-0.3787896,-0.8909702,-0.04187236,0.39062983,-0.88582945,-0.03013003
72
+ 71,-0.054515168,0.22345658,-0.25591394,-0.20364353,0.07904651,-0.17467827,-0.31664672,0.23130666,-0.26627818,0.090320885,0.09389014,-0.23806506,0.21829425,0.23350133,-0.35763338,-0.31193498,0.43869197,-0.37451798,0.27963918,0.4825184,-0.4547262,-0.08996652,-0.37142664,0.0023411545,-0.005255211,-0.36333323,-0.010231981,-0.3682732,-0.46564794,-0.1843815,0.34598854,-0.4521384,-0.2000036,-0.36807638,-0.93070555,-0.03059377,0.37870327,-0.9223107,-0.02514531
73
+ 72,-0.074645646,0.17614843,-0.27417913,-0.22423929,0.036672167,-0.1684494,-0.34052473,0.1655117,-0.22883452,0.07015312,0.055352412,-0.26022327,0.21828291,0.16478251,-0.34150884,-0.32782853,0.36056203,-0.30572405,0.2909718,0.40634415,-0.44755322,-0.10593573,-0.39255774,0.0017391775,-0.02747626,-0.3807955,-0.021306394,-0.39986485,-0.47690594,0.011270491,0.37196612,-0.4558714,-0.05461207,-0.4056507,-0.9510805,0.074670844,0.41075805,-0.93872726,-0.058212474
outputs/sample_results.json ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "video": "sample.webm",
3
+ "total_frames": 110,
4
+ "start_frame": 1,
5
+ "stop_frame": 72,
6
+ "exercise_frames": 72,
7
+ "exercise_duration_sec": 2.4,
8
+ "quality_label": "GOOD",
9
+ "pipeline_version": "A8-A13 finsihed"
10
+ }
pose_estimator.py ADDED
@@ -0,0 +1,439 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ MoveNet Pose Estimator Module
3
+ =============================
4
+ A Python module for human pose estimation using TensorFlow's MoveNet model.
5
+
6
+ This module provides functionality to:
7
+ - Load and run MoveNet pose estimation model
8
+ - Process images and videos
9
+ - Extract 17 COCO keypoints
10
+ - Visualize pose detection results
11
+
12
+ Issue #33 - A8: PoseNet/MoveNet Python Environment Setup
13
+ """
14
+
15
+ import os
16
+ import time
17
+ from typing import Dict, List, Optional, Tuple, Union
18
+
19
+ import cv2
20
+ import numpy as np
21
+ import tensorflow as tf
22
+ import tensorflow_hub as hub
23
+
24
+
25
+ # COCO Keypoint definitions (17 keypoints)
26
+ KEYPOINT_NAMES = [
27
+ 'nose',
28
+ 'left_eye',
29
+ 'right_eye',
30
+ 'left_ear',
31
+ 'right_ear',
32
+ 'left_shoulder',
33
+ 'right_shoulder',
34
+ 'left_elbow',
35
+ 'right_elbow',
36
+ 'left_wrist',
37
+ 'right_wrist',
38
+ 'left_hip',
39
+ 'right_hip',
40
+ 'left_knee',
41
+ 'right_knee',
42
+ 'left_ankle',
43
+ 'right_ankle'
44
+ ]
45
+
46
+ # Skeleton connections for visualization
47
+ KEYPOINT_EDGES = {
48
+ (0, 1): 'face',
49
+ (0, 2): 'face',
50
+ (1, 3): 'face',
51
+ (2, 4): 'face',
52
+ (0, 5): 'torso',
53
+ (0, 6): 'torso',
54
+ (5, 7): 'left_arm',
55
+ (7, 9): 'left_arm',
56
+ (6, 8): 'right_arm',
57
+ (8, 10): 'right_arm',
58
+ (5, 6): 'torso',
59
+ (5, 11): 'torso',
60
+ (6, 12): 'torso',
61
+ (11, 12): 'torso',
62
+ (11, 13): 'left_leg',
63
+ (13, 15): 'left_leg',
64
+ (12, 14): 'right_leg',
65
+ (14, 16): 'right_leg',
66
+ }
67
+
68
+ # Colors for different body parts (BGR format for OpenCV)
69
+ EDGE_COLORS = {
70
+ 'face': (255, 255, 0), # Cyan
71
+ 'torso': (0, 255, 0), # Green
72
+ 'left_arm': (255, 0, 0), # Blue
73
+ 'right_arm': (0, 0, 255), # Red
74
+ 'left_leg': (255, 165, 0), # Orange
75
+ 'right_leg': (128, 0, 128), # Purple
76
+ }
77
+
78
+
79
+ class MoveNetPoseEstimator:
80
+ """
81
+ MoveNet-based human pose estimator.
82
+
83
+ Supports two model variants:
84
+ - 'lightning': Faster, lower accuracy (default)
85
+ - 'thunder': Slower, higher accuracy
86
+
87
+ Example usage:
88
+ estimator = MoveNetPoseEstimator(model_name='lightning')
89
+ keypoints = estimator.detect_pose(image)
90
+ visualized = estimator.draw_keypoints(image, keypoints)
91
+ """
92
+
93
+ # TensorFlow Hub model URLs
94
+ MODEL_URLS = {
95
+ 'lightning': 'https://tfhub.dev/google/movenet/singlepose/lightning/4',
96
+ 'thunder': 'https://tfhub.dev/google/movenet/singlepose/thunder/4',
97
+ }
98
+
99
+ # Input sizes for each model
100
+ INPUT_SIZES = {
101
+ 'lightning': 192,
102
+ 'thunder': 256,
103
+ }
104
+
105
+ def __init__(self, model_name: str = 'lightning'):
106
+ """
107
+ Initialize the MoveNet pose estimator.
108
+
109
+ Args:
110
+ model_name: Model variant ('lightning' or 'thunder')
111
+ """
112
+ if model_name not in self.MODEL_URLS:
113
+ raise ValueError(f"Model must be one of: {list(self.MODEL_URLS.keys())}")
114
+
115
+ self.model_name = model_name
116
+ self.input_size = self.INPUT_SIZES[model_name]
117
+
118
+ print(f"Loading MoveNet {model_name} model...")
119
+ self.model = hub.load(self.MODEL_URLS[model_name])
120
+ self.movenet = self.model.signatures['serving_default']
121
+ print(f"Model loaded successfully. Input size: {self.input_size}x{self.input_size}")
122
+
123
+ def preprocess_image(self, image: np.ndarray) -> tf.Tensor:
124
+ """
125
+ Preprocess image for MoveNet inference.
126
+
127
+ Args:
128
+ image: Input image (BGR or RGB format, any size)
129
+
130
+ Returns:
131
+ Preprocessed tensor ready for inference
132
+ """
133
+ # Convert BGR to RGB if needed (OpenCV loads as BGR)
134
+ if len(image.shape) == 3 and image.shape[2] == 3:
135
+ image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
136
+ else:
137
+ image_rgb = image
138
+
139
+ # Resize to model input size
140
+ input_image = tf.image.resize_with_pad(
141
+ tf.expand_dims(image_rgb, axis=0),
142
+ self.input_size,
143
+ self.input_size
144
+ )
145
+
146
+ # Convert to int32 as required by MoveNet
147
+ input_image = tf.cast(input_image, dtype=tf.int32)
148
+
149
+ return input_image
150
+
151
+ def detect_pose(self, image: np.ndarray) -> Dict:
152
+ """
153
+ Detect pose keypoints in an image.
154
+
155
+ Args:
156
+ image: Input image (BGR format from OpenCV)
157
+
158
+ Returns:
159
+ Dictionary with keypoint data:
160
+ {
161
+ 'keypoints': {
162
+ 'nose': {'x': float, 'y': float, 'confidence': float},
163
+ ...
164
+ },
165
+ 'inference_time_ms': float
166
+ }
167
+ """
168
+ start_time = time.time()
169
+
170
+ # Preprocess
171
+ input_tensor = self.preprocess_image(image)
172
+
173
+ # Run inference
174
+ outputs = self.movenet(input_tensor)
175
+ keypoints_with_scores = outputs['output_0'].numpy()[0, 0, :, :]
176
+
177
+ inference_time = (time.time() - start_time) * 1000
178
+
179
+ # Parse keypoints
180
+ keypoints_dict = {}
181
+ for i, name in enumerate(KEYPOINT_NAMES):
182
+ y, x, confidence = keypoints_with_scores[i]
183
+ keypoints_dict[name] = {
184
+ 'x': float(x),
185
+ 'y': float(y),
186
+ 'confidence': float(confidence)
187
+ }
188
+
189
+ return {
190
+ 'keypoints': keypoints_dict,
191
+ 'inference_time_ms': inference_time
192
+ }
193
+
194
+ def detect_pose_raw(self, image: np.ndarray) -> np.ndarray:
195
+ """
196
+ Detect pose and return raw keypoints array.
197
+
198
+ Args:
199
+ image: Input image (BGR format)
200
+
201
+ Returns:
202
+ Array of shape (17, 3) with [y, x, confidence] for each keypoint
203
+ """
204
+ input_tensor = self.preprocess_image(image)
205
+ outputs = self.movenet(input_tensor)
206
+ return outputs['output_0'].numpy()[0, 0, :, :]
207
+
208
+ def draw_keypoints(
209
+ self,
210
+ image: np.ndarray,
211
+ keypoints: Dict,
212
+ confidence_threshold: float = 0.3,
213
+ circle_radius: int = 5,
214
+ line_thickness: int = 2
215
+ ) -> np.ndarray:
216
+ """
217
+ Draw detected keypoints and skeleton on image.
218
+
219
+ Args:
220
+ image: Input image (will be copied, not modified)
221
+ keypoints: Keypoint dictionary from detect_pose()
222
+ confidence_threshold: Minimum confidence to draw keypoint
223
+ circle_radius: Radius of keypoint circles
224
+ line_thickness: Thickness of skeleton lines
225
+
226
+ Returns:
227
+ Image with keypoints and skeleton drawn
228
+ """
229
+ output_image = image.copy()
230
+ height, width = image.shape[:2]
231
+
232
+ kps = keypoints['keypoints']
233
+
234
+ # Draw skeleton edges first (so keypoints appear on top)
235
+ for (start_idx, end_idx), body_part in KEYPOINT_EDGES.items():
236
+ start_name = KEYPOINT_NAMES[start_idx]
237
+ end_name = KEYPOINT_NAMES[end_idx]
238
+
239
+ start_kp = kps[start_name]
240
+ end_kp = kps[end_name]
241
+
242
+ if start_kp['confidence'] > confidence_threshold and end_kp['confidence'] > confidence_threshold:
243
+ start_point = (int(start_kp['x'] * width), int(start_kp['y'] * height))
244
+ end_point = (int(end_kp['x'] * width), int(end_kp['y'] * height))
245
+ color = EDGE_COLORS[body_part]
246
+ cv2.line(output_image, start_point, end_point, color, line_thickness)
247
+
248
+ # Draw keypoints
249
+ for name, kp in kps.items():
250
+ if kp['confidence'] > confidence_threshold:
251
+ x = int(kp['x'] * width)
252
+ y = int(kp['y'] * height)
253
+ cv2.circle(output_image, (x, y), circle_radius, (0, 255, 255), -1)
254
+ cv2.circle(output_image, (x, y), circle_radius, (0, 0, 0), 1)
255
+
256
+ return output_image
257
+
258
+ def process_video(
259
+ self,
260
+ video_path: str,
261
+ output_path: Optional[str] = None,
262
+ show_preview: bool = False,
263
+ confidence_threshold: float = 0.3
264
+ ) -> List[Dict]:
265
+ """
266
+ Process a video file and extract keypoints from each frame.
267
+
268
+ Args:
269
+ video_path: Path to input video file
270
+ output_path: Optional path to save annotated video
271
+ show_preview: Whether to show live preview (press 'q' to quit)
272
+ confidence_threshold: Minimum confidence for visualization
273
+
274
+ Returns:
275
+ List of keypoint dictionaries, one per frame
276
+ """
277
+ cap = cv2.VideoCapture(video_path)
278
+
279
+ if not cap.isOpened():
280
+ raise ValueError(f"Could not open video: {video_path}")
281
+
282
+ # Get video properties
283
+ fps = cap.get(cv2.CAP_PROP_FPS)
284
+ width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
285
+ height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
286
+ total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
287
+
288
+ print(f"Video: {video_path}")
289
+ print(f"Resolution: {width}x{height}, FPS: {fps:.2f}, Frames: {total_frames}")
290
+
291
+ # Setup video writer if output path specified
292
+ writer = None
293
+ if output_path:
294
+ fourcc = cv2.VideoWriter_fourcc(*'mp4v')
295
+ writer = cv2.VideoWriter(output_path, fourcc, fps, (width, height))
296
+
297
+ all_keypoints = []
298
+ frame_idx = 0
299
+
300
+ while True:
301
+ ret, frame = cap.read()
302
+ if not ret:
303
+ break
304
+
305
+ # Detect pose
306
+ result = self.detect_pose(frame)
307
+ result['frame_id'] = frame_idx
308
+ result['timestamp'] = frame_idx / fps if fps > 0 else 0
309
+ all_keypoints.append(result)
310
+
311
+ # Draw and optionally show/save
312
+ annotated_frame = self.draw_keypoints(frame, result, confidence_threshold)
313
+
314
+ if writer:
315
+ writer.write(annotated_frame)
316
+
317
+ if show_preview:
318
+ cv2.imshow('Pose Estimation', annotated_frame)
319
+ if cv2.waitKey(1) & 0xFF == ord('q'):
320
+ break
321
+
322
+ frame_idx += 1
323
+ if frame_idx % 30 == 0:
324
+ print(f"Processed {frame_idx}/{total_frames} frames...")
325
+
326
+ cap.release()
327
+ if writer:
328
+ writer.release()
329
+ if show_preview:
330
+ cv2.destroyAllWindows()
331
+
332
+ print(f"Completed! Processed {frame_idx} frames.")
333
+ avg_inference = np.mean([r['inference_time_ms'] for r in all_keypoints])
334
+ print(f"Average inference time: {avg_inference:.2f} ms/frame")
335
+
336
+ return all_keypoints
337
+
338
+ def process_image_file(
339
+ self,
340
+ image_path: str,
341
+ output_path: Optional[str] = None,
342
+ confidence_threshold: float = 0.3
343
+ ) -> Dict:
344
+ """
345
+ Process a single image file.
346
+
347
+ Args:
348
+ image_path: Path to input image
349
+ output_path: Optional path to save annotated image
350
+ confidence_threshold: Minimum confidence for visualization
351
+
352
+ Returns:
353
+ Keypoint dictionary for the image
354
+ """
355
+ image = cv2.imread(image_path)
356
+ if image is None:
357
+ raise ValueError(f"Could not read image: {image_path}")
358
+
359
+ result = self.detect_pose(image)
360
+
361
+ if output_path:
362
+ annotated = self.draw_keypoints(image, result, confidence_threshold)
363
+ cv2.imwrite(output_path, annotated)
364
+ print(f"Saved annotated image to: {output_path}")
365
+
366
+ return result
367
+
368
+
369
+ def main():
370
+ """Demo: Test the pose estimator on a sample image or webcam."""
371
+ import argparse
372
+
373
+ parser = argparse.ArgumentParser(description='MoveNet Pose Estimation Demo')
374
+ parser.add_argument('--model', choices=['lightning', 'thunder'], default='lightning',
375
+ help='Model variant (default: lightning)')
376
+ parser.add_argument('--image', type=str, help='Path to input image')
377
+ parser.add_argument('--video', type=str, help='Path to input video')
378
+ parser.add_argument('--webcam', action='store_true', help='Use webcam')
379
+ parser.add_argument('--output', type=str, help='Output path for annotated image/video')
380
+ args = parser.parse_args()
381
+
382
+ # Initialize estimator
383
+ estimator = MoveNetPoseEstimator(model_name=args.model)
384
+
385
+ if args.image:
386
+ # Process image
387
+ print(f"\nProcessing image: {args.image}")
388
+ result = estimator.process_image_file(
389
+ args.image,
390
+ output_path=args.output
391
+ )
392
+ print(f"Inference time: {result['inference_time_ms']:.2f} ms")
393
+ print("\nDetected keypoints:")
394
+ for name, kp in result['keypoints'].items():
395
+ if kp['confidence'] > 0.3:
396
+ print(f" {name}: ({kp['x']:.3f}, {kp['y']:.3f}) conf={kp['confidence']:.3f}")
397
+
398
+ elif args.video:
399
+ # Process video
400
+ print(f"\nProcessing video: {args.video}")
401
+ keypoints = estimator.process_video(
402
+ args.video,
403
+ output_path=args.output,
404
+ show_preview=True
405
+ )
406
+ print(f"\nExtracted keypoints from {len(keypoints)} frames")
407
+
408
+ elif args.webcam:
409
+ # Webcam demo
410
+ print("\nStarting webcam demo (press 'q' to quit)...")
411
+ cap = cv2.VideoCapture(0)
412
+
413
+ while True:
414
+ ret, frame = cap.read()
415
+ if not ret:
416
+ break
417
+
418
+ result = estimator.detect_pose(frame)
419
+ annotated = estimator.draw_keypoints(frame, result)
420
+
421
+ # Add FPS display
422
+ fps_text = f"Inference: {result['inference_time_ms']:.1f} ms"
423
+ cv2.putText(annotated, fps_text, (10, 30),
424
+ cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
425
+
426
+ cv2.imshow('MoveNet Pose Estimation', annotated)
427
+ if cv2.waitKey(1) & 0xFF == ord('q'):
428
+ break
429
+
430
+ cap.release()
431
+ cv2.destroyAllWindows()
432
+
433
+ else:
434
+ print("Please specify --image, --video, or --webcam")
435
+ print("Example: python pose_estimator.py --image test.jpg --output result.jpg")
436
+
437
+
438
+ if __name__ == '__main__':
439
+ main()
pose_interpolator.py ADDED
@@ -0,0 +1,1010 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Pose Interpolation & Smoothing Module (A12)
4
+ ============================================
5
+ Provides robust smoothing strategies for pose-estimation keypoint sequences,
6
+ eliminating jitter, filling detection gaps, and removing outlier spikes
7
+ to produce clean animations.
8
+
9
+ Supported strategies
10
+ --------------------
11
+ - ``moving_average`` Box-car (sliding window) average
12
+ - ``gaussian`` Gaussian-weighted convolution
13
+ - ``exponential`` Exponential moving average (EMA) – usable online
14
+ - ``median`` Median filter – excellent against isolated spikes
15
+ - ``savitzky_golay`` Savitzky-Golay filter – preserves signal shape
16
+ - ``kalman`` 1-D constant-velocity Kalman filter (online)
17
+ - ``spline`` Cubic-spline interpolation through high-confidence
18
+ points, discarding outliers
19
+ - ``hybrid`` (Default) Outlier detection β†’ interpolation β†’
20
+ Savitzky-Golay smoothing
21
+
22
+ Data formats
23
+ ------------
24
+ The module accepts two common representations:
25
+
26
+ 1. **App‑style list of dicts** (from ``app.py`` ``all_keypoints``):
27
+
28
+ .. code:: python
29
+
30
+ [
31
+ {
32
+ "poses": [{
33
+ "keypoints": [
34
+ {"x": 0.5, "y": 0.3, "score": 0.92, "name": "nose"},
35
+ ...
36
+ ]
37
+ }],
38
+ "frame_id": 0, ...
39
+ },
40
+ ...
41
+ ]
42
+
43
+ 2. **NumPy array** with shape ``(frames, joints, 3)`` where the last axis
44
+ holds ``[x, y, confidence]``.
45
+
46
+ Basic usage
47
+ -----------
48
+ .. code:: python
49
+
50
+ from A12.pose_interpolator import PoseInterpolator, smooth_pose_sequence
51
+
52
+ # High-level convenience (recommended)
53
+ smoothed = smooth_pose_sequence(all_keypoints, strategy="hybrid")
54
+
55
+ # Low-level API
56
+ interp = PoseInterpolator(strategy="kalman", process_noise=0.001,
57
+ measurement_noise=0.05)
58
+ arr = interp.keypoints_to_array(all_keypoints)
59
+ smoothed_arr = interp.fit_transform(arr)
60
+ """
61
+
62
+ from __future__ import annotations
63
+
64
+ import warnings
65
+ from collections import defaultdict
66
+ from copy import deepcopy
67
+ from enum import Enum
68
+ from typing import Any, Dict, List, Optional, Sequence, Tuple, Union
69
+
70
+ import numpy as np
71
+
72
+ import pandas as pd
73
+
74
+ # ---------------------------------------------------------------------------
75
+ # Try importing scipy – it is a transitive dependency of statsmodels /
76
+ # scikit-learn (both in requirements.txt), but we guard in case it is
77
+ # not available for some strategies.
78
+ # ---------------------------------------------------------------------------
79
+ try:
80
+ from scipy import interpolate as _scipy_interpolate, ndimage, signal as _scipy_signal
81
+
82
+ _HAS_SCIPY = True
83
+ except ImportError: # pragma: no cover
84
+ _HAS_SCIPY = False
85
+
86
+
87
+ # ---------------------------------------------------------------------------
88
+ # Standard joint-name lists (for reference / validation)
89
+ # ---------------------------------------------------------------------------
90
+
91
+ COCO_KEYPOINTS: List[str] = [
92
+ "nose",
93
+ "left_eye",
94
+ "right_eye",
95
+ "left_ear",
96
+ "right_ear",
97
+ "left_shoulder",
98
+ "right_shoulder",
99
+ "left_elbow",
100
+ "right_elbow",
101
+ "left_wrist",
102
+ "right_wrist",
103
+ "left_hip",
104
+ "right_hip",
105
+ "left_knee",
106
+ "right_knee",
107
+ "left_ankle",
108
+ "right_ankle",
109
+ ]
110
+
111
+ A11_JOINTS: List[str] = [
112
+ "head",
113
+ "left_shoulder",
114
+ "left_elbow",
115
+ "right_shoulder",
116
+ "right_elbow",
117
+ "left_hand",
118
+ "right_hand",
119
+ "left_hip",
120
+ "right_hip",
121
+ "left_knee",
122
+ "right_knee",
123
+ "left_foot",
124
+ "right_foot",
125
+ ]
126
+
127
+
128
+ class SmoothingStrategy(Enum):
129
+ """Available smoothing strategies."""
130
+
131
+ MOVING_AVERAGE = "moving_average"
132
+ GAUSSIAN = "gaussian"
133
+ EXPONENTIAL = "exponential"
134
+ MEDIAN = "median"
135
+ SAVITZKY_GOLAY = "savitzky_golay"
136
+ KALMAN = "kalman"
137
+ SPLINE = "spline"
138
+ HYBRID = "hybrid"
139
+
140
+
141
+ # ===================================================================
142
+ # Small helpers
143
+ # ===================================================================
144
+
145
+
146
+ def _validate_array(arr: np.ndarray) -> np.ndarray:
147
+ """Ensure *arr* is a contiguous float64 array of shape (F, J, 3)."""
148
+ arr = np.asarray(arr, dtype=np.float64)
149
+ if arr.ndim != 3 or arr.shape[2] != 3:
150
+ raise ValueError(
151
+ f"Expected array of shape (frames, joints, 3), got {arr.shape}"
152
+ )
153
+ return arr
154
+
155
+
156
+ def _ensure_scipy(strategy_name: str) -> None:
157
+ if not _HAS_SCIPY:
158
+ raise ImportError(
159
+ f"Strategy '{strategy_name}' requires scipy, which is not installed."
160
+ )
161
+
162
+
163
+ # ===================================================================
164
+ # 1-D Kalman filter (constant velocity) – no external dependencies
165
+ # ===================================================================
166
+
167
+
168
+ class KalmanFilter1D:
169
+ """
170
+ Simple 1-D constant-velocity Kalman filter.
171
+
172
+ State: [position, velocity]α΅€
173
+ Measurement: position
174
+
175
+ Parameters
176
+ ----------
177
+ process_noise : float
178
+ Process noise (Q) – higher values trust the model less.
179
+ measurement_noise : float
180
+ Measurement noise (R) – higher values trust measurements less.
181
+
182
+ Notes
183
+ -----
184
+ When ``update(None)`` is called the filter performs a pure prediction
185
+ step, allowing it to bridge gaps in the detection sequence.
186
+ """
187
+
188
+ def __init__(
189
+ self, process_noise: float = 0.001, measurement_noise: float = 0.1
190
+ ) -> None:
191
+ # State transition (constant velocity, dt = 1)
192
+ self._A = np.array([[1, 1], [0, 1]], dtype=np.float64)
193
+ self._H = np.array([[1, 0]], dtype=np.float64) # observe position only
194
+ self._Q = np.eye(2, dtype=np.float64) * process_noise
195
+ self._R = np.array([[measurement_noise]], dtype=np.float64)
196
+ self._P = np.eye(2, dtype=np.float64) * 1.0
197
+ self._x = np.zeros(2, dtype=np.float64)
198
+
199
+ @property
200
+ def position(self) -> float:
201
+ """Current position estimate."""
202
+ return float(self._x[0])
203
+
204
+ def reset(self, position: float = 0.0) -> None:
205
+ """Re-initialise filter with a new position and zero velocity."""
206
+ self._x = np.array([position, 0.0], dtype=np.float64)
207
+ self._P = np.eye(2, dtype=np.float64) * 1.0
208
+
209
+ def update(self, measurement: Optional[float]) -> float:
210
+ """
211
+ Predict + (optionally) update step.
212
+
213
+ Parameters
214
+ ----------
215
+ measurement : float or None
216
+ Observed position. If ``None``, only the prediction step runs.
217
+
218
+ Returns
219
+ -------
220
+ float
221
+ Filtered position estimate.
222
+ """
223
+ # -- predict --
224
+ self._x = self._A @ self._x
225
+ self._P = self._A @ self._P @ self._A.T + self._Q
226
+
227
+ if measurement is not None:
228
+ # -- update --
229
+ y = measurement - (self._H @ self._x) # innovation
230
+ S = self._H @ self._P @ self._H.T + self._R
231
+ K = self._P @ self._H.T @ np.linalg.inv(S) # Kalman gain
232
+ self._x = self._x + (K @ y).ravel()
233
+ self._P = (np.eye(2) - K @ self._H) @ self._P
234
+
235
+ return self.position
236
+
237
+
238
+ # ===================================================================
239
+ # Outlier detection utilities
240
+ # ===================================================================
241
+
242
+
243
+ def detect_outliers_velocity(
244
+ positions: np.ndarray,
245
+ threshold: float = 3.0,
246
+ min_confidence: float = 0.2,
247
+ confidences: Optional[np.ndarray] = None,
248
+ ) -> np.ndarray:
249
+ """
250
+ Flag outliers based on inter-frame velocity.
251
+
252
+ A point is considered an outlier if its frame-to-frame displacement
253
+ exceeds *threshold* times the median absolute deviation of all
254
+ non-zero displacements across the sequence.
255
+
256
+ Parameters
257
+ ----------
258
+ positions : (F,) ndarray
259
+ 1-D coordinate signal (may contain NaN).
260
+ threshold : float
261
+ MAD multiplier.
262
+ min_confidence : float
263
+ Points with confidence below this are already treated as
264
+ missing – they are **not** flagged here (they will be
265
+ interpolated later).
266
+ confidences : (F,) ndarray or None
267
+ Confidence values (same length as *positions*).
268
+
269
+ Returns
270
+ -------
271
+ (F,) bool ndarray
272
+ ``True`` where the point is an outlier.
273
+ """
274
+ positions = np.asarray(positions, dtype=np.float64)
275
+ n = len(positions)
276
+
277
+ outlier_mask = np.zeros(n, dtype=bool)
278
+
279
+ # Low-confidence points are handled by the interpolation stage.
280
+ if confidences is not None:
281
+ confidences = np.asarray(confidences, dtype=np.float64)
282
+ low_conf = confidences < min_confidence
283
+ else:
284
+ low_conf = np.isnan(positions)
285
+
286
+ # Compute finite differences
287
+ diffs = np.abs(np.diff(positions))
288
+ valid_diffs = diffs[np.isfinite(diffs)]
289
+ if len(valid_diffs) == 0:
290
+ return outlier_mask
291
+
292
+ mad = np.median(np.abs(valid_diffs - np.median(valid_diffs)))
293
+ if mad == 0:
294
+ mad = np.mean(valid_diffs) + 1e-9 # fallback
295
+
296
+ limit = threshold * mad * 1.4826 # 1.4826 converts MAD β†’ std for normal
297
+
298
+ for i in range(1, n):
299
+ if low_conf[i]:
300
+ continue
301
+ d = abs(positions[i] - positions[i - 1])
302
+ if np.isfinite(d) and d > limit:
303
+ outlier_mask[i] = True
304
+
305
+ return outlier_mask
306
+
307
+
308
+ def detect_outliers_zscore(
309
+ positions: np.ndarray,
310
+ threshold: float = 3.0,
311
+ min_confidence: float = 0.2,
312
+ confidences: Optional[np.ndarray] = None,
313
+ ) -> np.ndarray:
314
+ """
315
+ Flag outliers whose absolute z-score exceeds *threshold*.
316
+
317
+ Computed against the sequence mean / std (ignoring NaN).
318
+ """
319
+ positions = np.asarray(positions, dtype=np.float64)
320
+ n = len(positions)
321
+
322
+ outlier_mask = np.zeros(n, dtype=bool)
323
+
324
+ if confidences is not None:
325
+ confidences = np.asarray(confidences, dtype=np.float64)
326
+ low_conf = confidences < min_confidence
327
+ else:
328
+ low_conf = np.isnan(positions)
329
+
330
+ finite = np.isfinite(positions) & ~low_conf
331
+ if not finite.any():
332
+ return outlier_mask
333
+
334
+ mu = np.mean(positions[finite])
335
+ sigma = np.std(positions[finite])
336
+ if sigma == 0:
337
+ return outlier_mask
338
+
339
+ z = np.abs(positions - mu) / sigma
340
+ outlier_mask = (z > threshold) & ~low_conf & np.isfinite(positions)
341
+ return outlier_mask
342
+
343
+
344
+ # ===================================================================
345
+ # Core interpolator class
346
+ # ===================================================================
347
+
348
+
349
+ class PoseInterpolator:
350
+ """
351
+ Smooth a multi-joint pose trajectory using a configurable strategy.
352
+
353
+ Parameters
354
+ ----------
355
+ strategy : str or SmoothingStrategy
356
+ One of the strategies listed in :class:`SmoothingStrategy`.
357
+ window_size : int
358
+ Window length (frames) for moving‑average, gaussian, median,
359
+ savitzky_golay. Must be odd for savitzky_golay and median.
360
+ poly_order : int
361
+ Polynomial order for Savitzky‑Golay (must be < window_size).
362
+ sigma : float
363
+ Standard deviation of the Gaussian kernel.
364
+ alpha : float
365
+ Smoothing factor for exponential moving average (0 < Ξ± ≀ 1).
366
+ Larger Ξ± gives more weight to recent observations.
367
+ process_noise : float
368
+ Kalman-filter process noise.
369
+ measurement_noise : float
370
+ Kalman-filter measurement noise.
371
+ outlier_method : str
372
+ ``"velocity"`` or ``"zscore"`` – used by the hybrid strategy.
373
+ outlier_threshold : float
374
+ MAD / z-score multiplier for outlier flagging.
375
+ min_confidence : float
376
+ Keypoints with confidence below this are treated as missing and
377
+ interpolated regardless of strategy.
378
+ fill_method : str
379
+ How to fill missing / masked positions before smoothing:
380
+ ``"linear"``, ``"spline"``, or ``"forward"`` (last valid
381
+ carried forward).
382
+ """
383
+
384
+ def __init__(
385
+ self,
386
+ strategy: Union[str, SmoothingStrategy] = SmoothingStrategy.HYBRID,
387
+ window_size: int = 5,
388
+ poly_order: int = 2,
389
+ sigma: float = 1.0,
390
+ alpha: float = 0.3,
391
+ process_noise: float = 0.001,
392
+ measurement_noise: float = 0.05,
393
+ outlier_method: str = "velocity",
394
+ outlier_threshold: float = 3.0,
395
+ min_confidence: float = 0.2,
396
+ fill_method: str = "linear",
397
+ ) -> None:
398
+ if isinstance(strategy, str):
399
+ strategy = SmoothingStrategy(strategy)
400
+ self.strategy = strategy
401
+ self.window_size = window_size
402
+ self.poly_order = poly_order
403
+ self.sigma = sigma
404
+ self.alpha = float(np.clip(alpha, 0.0, 1.0))
405
+ self.process_noise = process_noise
406
+ self.measurement_noise = measurement_noise
407
+ self.outlier_method = outlier_method
408
+ self.outlier_threshold = outlier_threshold
409
+ self.min_confidence = min_confidence
410
+ self.fill_method = fill_method
411
+
412
+ # Internal state (set during fit / transform)
413
+ self._joint_names: List[str] = []
414
+ self._n_frames: int = 0
415
+ self._n_joints: int = 0
416
+
417
+ # --- public API ---------------------------------------------------
418
+
419
+ @staticmethod
420
+ def keypoints_to_array(
421
+ frames_data: List[Dict[str, Any]],
422
+ joint_names: Optional[List[str]] = None,
423
+ ) -> np.ndarray:
424
+ """
425
+ Convert *app.py* style frame dicts into a ``(F, J, 3)`` array.
426
+
427
+ Parameters
428
+ ----------
429
+ frames_data : list of dict
430
+ Each dict must have the structure produced by
431
+ ``extract_joint_positions_from_movenet()`` (see module
432
+ docstring).
433
+ joint_names : list of str, optional
434
+ Names of joints in the desired order. When ``None``,
435
+ ``COCO_KEYPOINTS`` is used.
436
+
437
+ Returns
438
+ -------
439
+ ndarray of shape ``(len(frames_data), len(joint_names), 3)``
440
+ The last axis holds ``[x, y, confidence]``. Missing values
441
+ are represented as ``NaN``.
442
+ """
443
+ if joint_names is None:
444
+ joint_names = COCO_KEYPOINTS
445
+
446
+ n_frames = len(frames_data)
447
+ n_joints = len(joint_names)
448
+ arr = np.full((n_frames, n_joints, 3), np.nan, dtype=np.float64)
449
+
450
+ for f_idx, frame in enumerate(frames_data):
451
+ poses = frame.get("poses", [])
452
+ if not poses:
453
+ continue
454
+ kps = poses[0].get("keypoints", [])
455
+ kp_map = {kp.get("name"): kp for kp in kps}
456
+ for j_idx, name in enumerate(joint_names):
457
+ kp = kp_map.get(name)
458
+ if kp is None:
459
+ continue
460
+ x, y, c = kp.get("x"), kp.get("y"), kp.get("score")
461
+ arr[f_idx, j_idx, 0] = x if x is not None else np.nan
462
+ arr[f_idx, j_idx, 1] = y if y is not None else np.nan
463
+ arr[f_idx, j_idx, 2] = (
464
+ c if c is not None else np.nan
465
+ )
466
+
467
+ return arr
468
+
469
+ @staticmethod
470
+ def array_to_keypoints(
471
+ arr: np.ndarray,
472
+ frames_data: List[Dict[str, Any]],
473
+ joint_names: Optional[List[str]] = None,
474
+ ) -> List[Dict[str, Any]]:
475
+ """
476
+ Write a smoothed ``(F, J, 3)`` array back into the original
477
+ app‑style frame dicts (returns a **deep copy** of
478
+ *frames_data* with modified keypoint coordinates).
479
+
480
+ Confidence values are preserved from the original data;
481
+ coordinates are overwritten with the smoothed values.
482
+ """
483
+ if joint_names is None:
484
+ joint_names = COCO_KEYPOINTS
485
+
486
+ arr = _validate_array(arr)
487
+ n_frames, n_joints, _ = arr.shape
488
+
489
+ out: List[Dict[str, Any]] = deepcopy(frames_data)
490
+
491
+ for f_idx in range(min(n_frames, len(out))):
492
+ poses = out[f_idx].get("poses", [])
493
+ if not poses:
494
+ continue
495
+ kps = poses[0].get("keypoints", [])
496
+ kp_map = {kp.get("name"): kp for kp in kps}
497
+ for j_idx, name in enumerate(joint_names):
498
+ kp = kp_map.get(name)
499
+ if kp is None:
500
+ continue
501
+ if not np.isnan(arr[f_idx, j_idx, 0]):
502
+ kp["x"] = float(arr[f_idx, j_idx, 0])
503
+ if not np.isnan(arr[f_idx, j_idx, 1]):
504
+ kp["y"] = float(arr[f_idx, j_idx, 1])
505
+ # confidence deliberately kept from original
506
+
507
+ return out
508
+
509
+ @staticmethod
510
+ def array_to_dataframe(
511
+ arr: np.ndarray,
512
+ joint_names: Optional[List[str]] = None,
513
+ frame_numbers: Optional[Sequence[int]] = None,
514
+ ) -> "pd.DataFrame":
515
+ """
516
+ Convert ``(F, J, 3)`` array to a DataFrame compatible with
517
+ A11 visualisation tools (columns ``<joint>_x``, ``<joint>_y``,
518
+ optionally ``<joint>_z`` and a ``FrameNo`` column).
519
+ """
520
+
521
+ if joint_names is None:
522
+ joint_names = COCO_KEYPOINTS
523
+
524
+ arr = _validate_array(arr)
525
+ n_frames, n_joints, _ = arr.shape
526
+
527
+ data: Dict[str, List[float]] = {}
528
+ for j_idx, name in enumerate(joint_names):
529
+ data[f"{name}_x"] = arr[:, j_idx, 0].tolist()
530
+ data[f"{name}_y"] = arr[:, j_idx, 1].tolist()
531
+
532
+ if frame_numbers is None:
533
+ data["FrameNo"] = list(range(n_frames))
534
+ else:
535
+ data["FrameNo"] = list(frame_numbers)
536
+
537
+ return pd.DataFrame(data)
538
+
539
+ def fit_transform(self, arr: np.ndarray) -> np.ndarray:
540
+ """
541
+ Run the full smoothing pipeline on one array.
542
+
543
+ Parameters
544
+ ----------
545
+ arr : (F, J, 3) ndarray
546
+ Raw coordinates + confidence.
547
+
548
+ Returns
549
+ -------
550
+ (F, J, 3) ndarray
551
+ Smoothed coordinates. The confidence channel is passed
552
+ through unchanged (it is used internally for filtering).
553
+ """
554
+ arr = _validate_array(arr)
555
+ self._n_frames, self._n_joints, _ = arr.shape
556
+
557
+ # Always mask low-confidence points before any processing
558
+ arr = self._mask_low_confidence(arr)
559
+
560
+ if self.strategy == SmoothingStrategy.KALMAN:
561
+ smoothed = self._apply_kalman(arr)
562
+ elif self.strategy == SmoothingStrategy.EXPONENTIAL:
563
+ smoothed = self._apply_ema(arr)
564
+ elif self.strategy == SmoothingStrategy.SPLINE:
565
+ smoothed = self._apply_spline(arr)
566
+ elif self.strategy == SmoothingStrategy.HYBRID:
567
+ smoothed = self._apply_hybrid(arr)
568
+ else:
569
+ # scipy-based windowed filters
570
+ smoothed = self._apply_windowed(arr)
571
+
572
+ return smoothed
573
+
574
+ def fit_transform_frames(
575
+ self,
576
+ frames_data: List[Dict[str, Any]],
577
+ joint_names: Optional[List[str]] = None,
578
+ ) -> List[Dict[str, Any]]:
579
+ """
580
+ High-level convenience: accept app‑style frame dicts, return
581
+ smoothed frame dicts.
582
+
583
+ Parameters
584
+ ----------
585
+ frames_data : list of dict
586
+ Raw per-frame keypoint dicts.
587
+ joint_names : list of str, optional
588
+ Ordered joint names.
589
+
590
+ Returns
591
+ -------
592
+ list of dict
593
+ Deep-copied frame dicts with smoothed coordinates.
594
+ """
595
+ if joint_names is None:
596
+ joint_names = COCO_KEYPOINTS
597
+ self._joint_names = list(joint_names)
598
+
599
+ arr = self.keypoints_to_array(frames_data, joint_names)
600
+ smoothed = self.fit_transform(arr)
601
+ return self.array_to_keypoints(smoothed, frames_data, joint_names)
602
+
603
+ # --- internal steps ------------------------------------------------
604
+
605
+ def _mask_low_confidence(self, arr: np.ndarray) -> np.ndarray:
606
+ """Set coordinates to NaN where confidence < *min_confidence*."""
607
+ arr = arr.copy()
608
+ conf = arr[:, :, 2]
609
+ low = conf < self.min_confidence
610
+ arr[low, 0] = np.nan
611
+ arr[low, 1] = np.nan
612
+ return arr
613
+
614
+ def _fill_missing(self, signal_1d: np.ndarray) -> np.ndarray:
615
+ """
616
+ Fill NaN values in a 1-D signal.
617
+
618
+ Returns a copy with NaNs replaced according to *fill_method*.
619
+ """
620
+ s = np.asarray(signal_1d, dtype=np.float64).copy()
621
+ n = len(s)
622
+ valid = np.isfinite(s)
623
+
624
+ if valid.all():
625
+ return s
626
+
627
+ if self.fill_method == "forward":
628
+ # Forward fill
629
+ last = np.nan
630
+ for i in range(n):
631
+ if np.isfinite(s[i]):
632
+ last = s[i]
633
+ elif not np.isnan(last):
634
+ s[i] = last
635
+ # Backward fill for leading NaN
636
+ first = np.nan
637
+ for i in range(n - 1, -1, -1):
638
+ if np.isfinite(s[i]):
639
+ first = s[i]
640
+ elif not np.isnan(first):
641
+ s[i] = first
642
+ return s
643
+
644
+ if self.fill_method == "spline":
645
+ _ensure_scipy("spline fill")
646
+ idx = np.arange(n)
647
+ if valid.sum() < 3:
648
+ # Not enough points for cubic spline β†’ fall back to linear
649
+ return self._fill_linear(s, idx, valid)
650
+ try:
651
+ spl = _scipy_interpolate.UnivariateSpline(
652
+ idx[valid], s[valid], s=0, ext="const"
653
+ )
654
+ s[~valid] = spl(idx[~valid])
655
+ except Exception:
656
+ s = self._fill_linear(s, idx, valid)
657
+ return s
658
+
659
+ # Default: linear
660
+ idx = np.arange(n)
661
+ return self._fill_linear(s, idx, valid)
662
+
663
+ @staticmethod
664
+ def _fill_linear(s: np.ndarray, idx: np.ndarray, valid: np.ndarray) -> np.ndarray:
665
+ """Linear interpolation (also handles edge extrapolation)."""
666
+ n = len(s)
667
+ s_filled = s.copy()
668
+ if valid.sum() >= 2:
669
+ s_filled[~valid] = np.interp(idx[~valid], idx[valid], s[valid])
670
+ elif valid.sum() == 1:
671
+ s_filled[~valid] = s[valid][0]
672
+ else:
673
+ s_filled[:] = 0.0
674
+ return s_filled
675
+
676
+ # --- strategy implementations --------------------------------------
677
+
678
+ def _apply_windowed(self, arr: np.ndarray) -> np.ndarray:
679
+ """scipy-based sliding-window filters."""
680
+ _ensure_scipy(self.strategy.value)
681
+ result = arr.copy()
682
+ ws = self._effective_window()
683
+
684
+ for j in range(self._n_joints):
685
+ for c in [0, 1]: # x, y
686
+ sig = result[:, j, c]
687
+ valid = np.isfinite(sig)
688
+ if not valid.any():
689
+ continue
690
+
691
+ # Fill gaps first
692
+ sig_filled = self._fill_missing(sig)
693
+
694
+ if self.strategy == SmoothingStrategy.MOVING_AVERAGE:
695
+ kernel = np.ones(ws) / ws
696
+ smoothed = np.convolve(sig_filled, kernel, mode="same")
697
+ elif self.strategy == SmoothingStrategy.GAUSSIAN:
698
+ # Create Gaussian kernel
699
+ ax = np.arange(-(ws // 2), ws // 2 + 1)
700
+ kernel = np.exp(-0.5 * (ax / self.sigma) ** 2)
701
+ kernel /= kernel.sum()
702
+ smoothed = np.convolve(sig_filled, kernel, mode="same")
703
+ elif self.strategy == SmoothingStrategy.MEDIAN:
704
+ smoothed = ndimage.median_filter(sig_filled, size=ws)
705
+ elif self.strategy == SmoothingStrategy.SAVITZKY_GOLAY:
706
+ if ws >= len(sig_filled):
707
+ ws = len(sig_filled) if len(sig_filled) % 2 == 1 else len(sig_filled) - 1
708
+ if ws <= self.poly_order:
709
+ ws = self.poly_order + 2
710
+ if ws % 2 == 0:
711
+ ws += 1
712
+ try:
713
+ smoothed = _scipy_signal.savgol_filter(
714
+ sig_filled, ws, self.poly_order, mode="nearest"
715
+ )
716
+ except Exception:
717
+ smoothed = sig_filled
718
+ else:
719
+ smoothed = sig_filled
720
+
721
+ # Restore original NaN positions so downstream code
722
+ # knows which points were originally missing.
723
+ smoothed[~valid] = np.nan
724
+ result[:, j, c] = smoothed
725
+
726
+ return result
727
+
728
+ def _apply_ema(self, arr: np.ndarray) -> np.ndarray:
729
+ """Exponential moving average (online-capable)."""
730
+ result = arr.copy()
731
+ alpha = self.alpha
732
+ for j in range(self._n_joints):
733
+ for c in [0, 1]:
734
+ sig = arr[:, j, c]
735
+ out = np.empty_like(sig)
736
+ ema = np.nan
737
+ for i in range(len(sig)):
738
+ if np.isfinite(sig[i]):
739
+ if np.isnan(ema):
740
+ ema = sig[i]
741
+ else:
742
+ ema = alpha * sig[i] + (1 - alpha) * ema
743
+ out[i] = ema
744
+ result[:, j, c] = out
745
+ return result
746
+
747
+ def _apply_kalman(self, arr: np.ndarray) -> np.ndarray:
748
+ """Per-joint, per-coordinate Kalman filter (forward pass)."""
749
+ result = arr.copy()
750
+ kf = KalmanFilter1D(self.process_noise, self.measurement_noise)
751
+ for j in range(self._n_joints):
752
+ for c in [0, 1]:
753
+ kf.reset()
754
+ # Initialise with first valid point (if any)
755
+ initialized = False
756
+ for i in range(self._n_frames):
757
+ val = arr[i, j, c]
758
+ if np.isfinite(val):
759
+ kf.reset(float(val))
760
+ initialized = True
761
+ break
762
+ if not initialized:
763
+ result[:, j, c] = np.nan
764
+ continue
765
+ result[0, j, c] = kf.position
766
+ for i in range(1, self._n_frames):
767
+ meas = arr[i, j, c]
768
+ pos = kf.update(
769
+ float(meas) if np.isfinite(meas) else None
770
+ )
771
+ result[i, j, c] = pos
772
+ return result
773
+
774
+ def _apply_spline(self, arr: np.ndarray) -> np.ndarray:
775
+ """
776
+ Fit a cubic smoothing spline through high-confidence points.
777
+
778
+ Low-confidence points are excluded from the fit and replaced
779
+ by the spline evaluation.
780
+ """
781
+ _ensure_scipy("spline")
782
+ result = arr.copy()
783
+ n = self._n_frames
784
+ idx = np.arange(n, dtype=np.float64)
785
+
786
+ for j in range(self._n_joints):
787
+ for c in [0, 1]:
788
+ sig = arr[:, j, c]
789
+ valid = np.isfinite(sig)
790
+ if valid.sum() < 3:
791
+ result[:, j, c] = self._fill_missing(sig)
792
+ continue
793
+
794
+ try:
795
+ spl = _scipy_interpolate.UnivariateSpline(
796
+ idx[valid], sig[valid], s=len(valid) * 0.5
797
+ )
798
+ result[:, j, c] = spl(idx)
799
+ except Exception:
800
+ result[:, j, c] = self._fill_missing(sig)
801
+
802
+ return result
803
+
804
+ def _apply_hybrid(self, arr: np.ndarray) -> np.ndarray:
805
+ """
806
+ Hybrid pipeline:
807
+
808
+ 1. Detect positional outliers (velocity or z-score).
809
+ 2. Mask outliers + low-confidence points β†’ NaN.
810
+ 3. Interpolate NaN gaps.
811
+ 4. Apply Savitzky-Golay smoothing.
812
+ """
813
+ result = arr.copy()
814
+
815
+ for j in range(self._n_joints):
816
+ for c in [0, 1]:
817
+ sig = arr[:, j, c]
818
+ conf = arr[:, j, 2]
819
+
820
+ # Step 1 – outlier detection
821
+ if self.outlier_method == "zscore":
822
+ outlier = detect_outliers_zscore(
823
+ sig, self.outlier_threshold, self.min_confidence, conf
824
+ )
825
+ else:
826
+ outlier = detect_outliers_velocity(
827
+ sig, self.outlier_threshold, self.min_confidence, conf
828
+ )
829
+
830
+ # Step 2 – mask
831
+ sig_clean = sig.copy()
832
+ sig_clean[outlier] = np.nan
833
+ # low-confidence already masked by _mask_low_confidence
834
+
835
+ # Step 3 – interpolate
836
+ sig_filled = self._fill_missing(sig_clean)
837
+
838
+ # Step 4 – Savitzky-Golay
839
+ _ensure_scipy("savitzky_golay")
840
+ ws = self._effective_window()
841
+ if ws >= len(sig_filled):
842
+ ws = len(sig_filled) if len(sig_filled) % 2 == 1 else len(sig_filled) - 1
843
+ if ws <= self.poly_order:
844
+ ws = self.poly_order + 2
845
+ if ws % 2 == 0:
846
+ ws += 1
847
+ try:
848
+ smoothed = _scipy_signal.savgol_filter(
849
+ sig_filled, ws, self.poly_order, mode="nearest"
850
+ )
851
+ except Exception:
852
+ smoothed = sig_filled
853
+
854
+ # Restore NaN for originally completely missing frames
855
+ orig_missing = ~np.isfinite(sig) & ~outlier
856
+ smoothed[orig_missing] = np.nan
857
+ result[:, j, c] = smoothed
858
+
859
+ return result
860
+
861
+ def _effective_window(self) -> int:
862
+ """Clamp window size to available frames and ensure odd."""
863
+ ws = min(self.window_size, self._n_frames)
864
+ if ws % 2 == 0:
865
+ ws -= 1
866
+ return max(ws, 3)
867
+
868
+
869
+ # ===================================================================
870
+ # High-level convenience function
871
+ # ===================================================================
872
+
873
+
874
+ def smooth_pose_sequence(
875
+ frames_data: List[Dict[str, Any]],
876
+ strategy: Union[str, SmoothingStrategy] = SmoothingStrategy.HYBRID,
877
+ joint_names: Optional[List[str]] = None,
878
+ **kwargs: Any,
879
+ ) -> List[Dict[str, Any]]:
880
+ """
881
+ Smooth an entire pose sequence with a single call.
882
+
883
+ Parameters
884
+ ----------
885
+ frames_data : list of dict
886
+ Per-frame keypoint dicts in the format produced by
887
+ ``extract_joint_positions_from_movenet()`` in ``app.py``.
888
+ strategy : str or SmoothingStrategy
889
+ Smoothing strategy to use (default: ``"hybrid"``).
890
+ joint_names : list of str, optional
891
+ Ordered joint names (defaults to COCO 17).
892
+ **kwargs
893
+ Passed through to :class:`PoseInterpolator` (window_size,
894
+ alpha, outlier_threshold, …).
895
+
896
+ Returns
897
+ -------
898
+ list of dict
899
+ Deep copy of *frames_data* with smoothed (x, y) coordinates.
900
+
901
+ Examples
902
+ --------
903
+ >>> # Quick hybrid smoothing (recommended for animations)
904
+ >>> smoothed = smooth_pose_sequence(all_keypoints, strategy="hybrid")
905
+
906
+ >>> # Light EMA for near-real-time use
907
+ >>> smoothed = smooth_pose_sequence(all_keypoints, strategy="exponential",
908
+ ... alpha=0.15)
909
+
910
+ >>> # Strong outlier removal for noisy recordings
911
+ >>> smoothed = smooth_pose_sequence(all_keypoints, strategy="hybrid",
912
+ ... outlier_method="zscore",
913
+ ... outlier_threshold=2.5,
914
+ ... window_size=7)
915
+ """
916
+ interpolator = PoseInterpolator(strategy=strategy, **kwargs)
917
+ return interpolator.fit_transform_frames(frames_data, joint_names=joint_names)
918
+
919
+
920
+ # ===================================================================
921
+ # Smoke test (runs when module is executed directly)
922
+ # ===================================================================
923
+
924
+ if __name__ == "__main__":
925
+ # Generate a synthetic trajectory with gaps and spikes
926
+ np.random.seed(42)
927
+ n_frames = 100
928
+ n_joints = 3 # nose, left_shoulder, right_shoulder
929
+ t = np.linspace(0, 4 * np.pi, n_frames)
930
+
931
+ # Ground truth – smooth sinusoid
932
+ true_x = np.sin(t) * 0.3 + 0.5
933
+ true_y = np.cos(t) * 0.2 + 0.5
934
+
935
+ # Build array: (F, J, 3)
936
+ raw = np.zeros((n_frames, n_joints, 3), dtype=np.float64)
937
+ for j in range(n_joints):
938
+ raw[:, j, 0] = true_x + np.random.randn(n_frames) * 0.02
939
+ raw[:, j, 1] = true_y + np.random.randn(n_frames) * 0.02
940
+ raw[:, j, 2] = 0.9 # high confidence
941
+
942
+ # Inject outliers
943
+ raw[20, 0, 0] += 0.4 # spike
944
+ raw[50, 0, 1] -= 0.3
945
+ raw[75, 0, 0] += 0.5
946
+
947
+ # Inject gaps
948
+ raw[40:45, 1, :] = np.nan
949
+ raw[60:65, 1, :] = np.nan
950
+ raw[80, 1, :] = np.nan
951
+
952
+ # --- Test each strategy -------------------------------------------
953
+ strategies = [
954
+ SmoothingStrategy.HYBRID,
955
+ SmoothingStrategy.MOVING_AVERAGE,
956
+ SmoothingStrategy.GAUSSIAN,
957
+ SmoothingStrategy.EXPONENTIAL,
958
+ SmoothingStrategy.MEDIAN,
959
+ SmoothingStrategy.SAVITZKY_GOLAY,
960
+ SmoothingStrategy.KALMAN,
961
+ SmoothingStrategy.SPLINE,
962
+ ]
963
+
964
+ print(f"{'Strategy':<22s} {'MAE (x)':>10s} {'MAE (y)':>10s}")
965
+ print("-" * 44)
966
+
967
+ for strat in strategies:
968
+ interp = PoseInterpolator(strategy=strat)
969
+ smoothed = interp.fit_transform(raw.copy())
970
+
971
+ # Mean absolute error against ground truth (only first joint)
972
+ mae_x = np.nanmean(np.abs(smoothed[:, 0, 0] - true_x))
973
+ mae_y = np.nanmean(np.abs(smoothed[:, 0, 1] - true_y))
974
+ print(f"{strat.value:<22s} {mae_x:10.6f} {mae_y:10.6f}")
975
+
976
+ # --- Test high-level convenience ----------------------------------
977
+ frames_data = PoseInterpolator.array_to_keypoints(
978
+ raw,
979
+ [
980
+ {
981
+ "poses": [
982
+ {
983
+ "pose_id": 0,
984
+ "keypoints": [
985
+ {
986
+ "x": raw[i, j, 0],
987
+ "y": raw[i, j, 1],
988
+ "score": raw[i, j, 2],
989
+ "name": COCO_KEYPOINTS[j],
990
+ }
991
+ for j in range(n_joints)
992
+ ],
993
+ }
994
+ ],
995
+ "frame_id": i,
996
+ }
997
+ for i in range(n_frames)
998
+ ],
999
+ joint_names=COCO_KEYPOINTS[:n_joints],
1000
+ )
1001
+
1002
+ smoothed_frames = smooth_pose_sequence(frames_data, strategy="hybrid")
1003
+ print(f"\nHigh-level convenience: processed {len(smoothed_frames)} frames βœ“")
1004
+
1005
+ # Convert to DataFrame for A11 compatibility
1006
+ df = PoseInterpolator.array_to_dataframe(
1007
+ raw, joint_names=COCO_KEYPOINTS[:n_joints]
1008
+ )
1009
+ print(f"DataFrame conversion: {df.shape} βœ“")
1010
+ print("\nAll tests passed.")