Spaces:
Sleeping
Sleeping
htrnguyen commited on
Commit ·
caa082c
1
Parent(s): 5d4c695
Fix vertical video support & improve biomechanics analysis logic
Browse files- .gitattributes +2 -1
- .gitignore +3 -0
- SCORING_METHODOLOGY.md +0 -50
- analyze.py +135 -82
- coach.py +20 -5
- docs/final_golf_swing.py +730 -0
- extract.py +12 -17
- hf_api_result.json → golf_analysis.json +1085 -1087
- models_v1/mobilenet_v2.pth.tar +3 -0
- models_v1/swingnet_1800.pth.tar +3 -0
- src/eval.py +1 -1
- src/model.py +1 -1
.gitattributes
CHANGED
|
@@ -1,2 +1,3 @@
|
|
| 1 |
models/*.pth.tar filter=lfs diff=lfs merge=lfs -text
|
| 2 |
-
*.
|
|
|
|
|
|
| 1 |
models/*.pth.tar filter=lfs diff=lfs merge=lfs -text
|
| 2 |
+
models_v1/*.pth.tar filter=lfs diff=lfs merge=lfs -text
|
| 3 |
+
*.TTF filter=lfs diff=lfs merge=lfs -text
|
.gitignore
CHANGED
|
@@ -71,3 +71,6 @@ ngrok.exe
|
|
| 71 |
!demo/
|
| 72 |
!demo/*.mp4
|
| 73 |
!demo/*.json
|
|
|
|
|
|
|
|
|
|
|
|
| 71 |
!demo/
|
| 72 |
!demo/*.mp4
|
| 73 |
!demo/*.json
|
| 74 |
+
|
| 75 |
+
# documents
|
| 76 |
+
!docs/
|
SCORING_METHODOLOGY.md
DELETED
|
@@ -1,50 +0,0 @@
|
|
| 1 |
-
# Thuyết minh: Phương pháp Đánh giá Golf AI (Thang điểm 10)
|
| 2 |
-
|
| 3 |
-
Hệ thống của chúng tôi đánh giá cú swing dựa trên sự kết hợp giữa **Dữ liệu Hình ảnh (AI)** và **Hình học Tư thế (Pose Geometry)**.
|
| 4 |
-
|
| 5 |
-
## 1. Cơ chế Chấm điểm
|
| 6 |
-
|
| 7 |
-
- **Điểm cơ sở**: Mỗi giai đoạn bắt đầu với **10.0 điểm**.
|
| 8 |
-
- **Điểm trừ (Penalties)**: Tùy theo mức độ nghiêm trọng của lỗi, hệ thống sẽ trừ từ 0.5 đến 2.5 điểm mỗi lỗi.
|
| 9 |
-
- **Trọng số (Weights)**: Điểm tổng kết không phải là trung bình cộng đơn thuần mà được tính theo tầm quan trọng của từng pha.
|
| 10 |
-
|
| 11 |
-
| Giai đoạn | Trọng số | Tầm quan trọng |
|
| 12 |
-
| :----------- | :------- | :--------------------------------------- |
|
| 13 |
-
| Address | 10% | Nền tảng ban đầu |
|
| 14 |
-
| Top | 20% | Đỉnh cao của năng lượng |
|
| 15 |
-
| Impact | 35% | **Quan trọng nhất** (Điểm tiếp xúc bóng) |
|
| 16 |
-
| Finish | 10% | Thể hiện sự thăng bằng |
|
| 17 |
-
| Các pha khác | 25% | Độ mượt mà của quá trình chuyển động |
|
| 18 |
-
|
| 19 |
-
## 2. Tiêu chí Chẩn đoán Chi tiết
|
| 20 |
-
|
| 21 |
-
### Pha Address (Tư thế chuẩn bị)
|
| 22 |
-
|
| 23 |
-
- **Độ rộng chân (Stance Width)**: Được đo so với độ rộng vai.
|
| 24 |
-
- _Chuẩn_: Tỉ lệ từ 0.8 đến 1.4.
|
| 25 |
-
- _Lỗi_: Quá rộng (mất linh hoạt) hoặc quá hẹp (mất thăng bằng).
|
| 26 |
-
|
| 27 |
-
### Pha Top (Đỉnh Backswing)
|
| 28 |
-
|
| 29 |
-
- **Tay dẫn (Lead Arm - Tay trái)**: Phải thẳng để tạo cung swing lớn nhất.
|
| 30 |
-
- _Chuẩn_: Góc tay >= 150 độ.
|
| 31 |
-
- _Lỗi_: "Chicken Wing" (Tay bị gập) làm giảm lực đánh.
|
| 32 |
-
|
| 33 |
-
### Pha Impact (Tiếp bóng)
|
| 34 |
-
|
| 35 |
-
- **Tay dẫn lúc va chạm**: Đây là khoảnh khắc truyền lực.
|
| 36 |
-
- _Chuẩn_: Góc tay >= 160 độ (Gần như thẳng tuyệt đối).
|
| 37 |
-
- _Lỗi_: Tay bị nhấc hoặc gập sớm làm mất lực và dễ đánh trượt.
|
| 38 |
-
|
| 39 |
-
### Pha Finish (Kết thúc)
|
| 40 |
-
|
| 41 |
-
- **Thăng bằng (Balance Control)**: Kiểm tra vị trí hông so với chân trụ.
|
| 42 |
-
- _Chuẩn_: Trọng tâm dồn hoàn toàn về chân trái, kết thúc vững chãi.
|
| 43 |
-
- _Lỗi_: Ngả người ra sau hoặc đổ về phía trước.
|
| 44 |
-
|
| 45 |
-
## 3. Phân loại Trình độ
|
| 46 |
-
|
| 47 |
-
- **9.0 - 10.0**: Pro / Low Handicap (Kỹ thuật tiệm cận chuyên nghiệp).
|
| 48 |
-
- **7.5 - 8.9**: Mid Handicap (Kỹ thuật tốt, cần tinh chỉnh chi tiết).
|
| 49 |
-
- **5.5 - 7.4**: High Handicap (Cần tập trung vào các bài tập cơ bản).
|
| 50 |
-
- **Dưới 5.5**: Beginner (Cần sự hướng dẫn trực tiếp từ huấn luyện viên).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
analyze.py
CHANGED
|
@@ -32,23 +32,19 @@ class GolfDiagnosticEngine:
|
|
| 32 |
r_hip = landmarks[self.mp_pose.PoseLandmark.RIGHT_HIP.value]
|
| 33 |
|
| 34 |
shoulder_width = abs(l_shoulder.x - r_shoulder.x)
|
| 35 |
-
|
| 36 |
-
# Tính chiều cao thân người (Torso Height) để chuẩn hóa
|
| 37 |
mid_shoulder_y = (l_shoulder.y + r_shoulder.y) / 2
|
| 38 |
mid_hip_y = (l_hip.y + r_hip.y) / 2
|
| 39 |
torso_height = abs(mid_shoulder_y - mid_hip_y)
|
| 40 |
|
| 41 |
if torso_height == 0: return "Unknown"
|
| 42 |
|
| 43 |
-
# Tỷ lệ chiều rộng vai / chiều cao thân
|
| 44 |
ratio = shoulder_width / torso_height
|
| 45 |
|
| 46 |
-
#
|
| 47 |
-
if ratio > 0.
|
| 48 |
-
return "Face-on
|
| 49 |
else:
|
| 50 |
-
return "Down-the-Line
|
| 51 |
-
|
| 52 |
|
| 53 |
def calculate_angle(self, a, b, c):
|
| 54 |
"""Tính góc (độ) giữa 3 điểm a, b, c (b là đỉnh)"""
|
|
@@ -74,101 +70,158 @@ class GolfDiagnosticEngine:
|
|
| 74 |
"""Vẽ landmarks tinh tế và chuyên nghiệp hơn"""
|
| 75 |
annotated_image = image.copy()
|
| 76 |
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
connection_style = self.mp_drawing.DrawingSpec(color=(255, 255, 255), thickness=1) # Đường nối trắng mỏng
|
| 80 |
|
| 81 |
-
# Vẽ khung xương
|
| 82 |
self.mp_drawing.draw_landmarks(
|
| 83 |
annotated_image, landmarks_proto, self.mp_pose.POSE_CONNECTIONS,
|
| 84 |
landmark_style,
|
| 85 |
connection_style
|
| 86 |
)
|
| 87 |
-
|
| 88 |
return annotated_image
|
| 89 |
|
| 90 |
-
def analyze_phase(self, phase_name, landmarks):
|
| 91 |
if not landmarks:
|
| 92 |
return {"score": 0, "comments": ["Không tìm thấy tư thế"], "data": {}}
|
| 93 |
|
| 94 |
analysis = {"score": 10.0, "comments": [], "data": {}, "raw_landmarks": []}
|
| 95 |
|
| 96 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 97 |
for i, lm in enumerate(landmarks):
|
| 98 |
analysis["raw_landmarks"].append({
|
| 99 |
-
"id": i,
|
| 100 |
-
"
|
| 101 |
-
"x": round(lm.x, 4),
|
| 102 |
-
"y": round(lm.y, 4),
|
| 103 |
-
"z": round(lm.z, 4),
|
| 104 |
-
"visibility": round(lm.visibility, 4)
|
| 105 |
})
|
| 106 |
|
| 107 |
-
#
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 121 |
if phase_name.endswith('Address'):
|
| 122 |
-
# 1.
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 131 |
analysis["score"] -= 1.0
|
| 132 |
-
analysis["comments"].append("
|
|
|
|
|
|
|
|
|
|
|
|
|
| 133 |
|
| 134 |
elif phase_name.endswith('Top'):
|
| 135 |
-
#
|
| 136 |
lead_arm_angle = self.calculate_angle(l_shoulder, l_elbow, l_wrist)
|
| 137 |
analysis["data"]["lead_arm_angle"] = lead_arm_angle
|
| 138 |
-
if
|
|
|
|
| 139 |
analysis["score"] -= 2.0
|
| 140 |
-
analysis["comments"].append("Tay trái bị
|
| 141 |
-
|
| 142 |
-
#
|
| 143 |
-
|
| 144 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 145 |
|
| 146 |
elif phase_name.endswith('Impact'):
|
| 147 |
-
#
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
analysis["
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
analysis["data"]["hip_openness"] = hip_openness
|
| 156 |
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
|
| 160 |
-
|
| 161 |
-
analysis["
|
| 162 |
-
analysis["comments"].append("Kết thúc thiếu thăng bằng")
|
| 163 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 164 |
if not analysis["comments"]:
|
| 165 |
-
analysis["comments"].append("
|
| 166 |
|
| 167 |
-
analysis["score"] = round(max(0, analysis["score"]), 1)
|
| 168 |
return analysis
|
| 169 |
|
| 170 |
def process_video_results(self, output_dir, return_dict=False):
|
| 171 |
-
# Lấy video_id từ tên thư mục output
|
| 172 |
video_id = os.path.basename(output_dir)
|
| 173 |
extraction_dir = os.path.join(output_dir, 'phases')
|
| 174 |
|
|
@@ -177,8 +230,18 @@ class GolfDiagnosticEngine:
|
|
| 177 |
total_score = 0
|
| 178 |
valid_phases = 0
|
| 179 |
|
| 180 |
-
# Mảng lưu landmarks Address để detect view
|
| 181 |
address_landmarks = None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 182 |
|
| 183 |
for label in self.labels:
|
| 184 |
img_path = os.path.join(extraction_dir, label, f"{video_id}.jpg")
|
|
@@ -188,11 +251,7 @@ class GolfDiagnosticEngine:
|
|
| 188 |
image = cv2.imread(img_path)
|
| 189 |
landmarks_list, _ = self.get_landmarks(image)
|
| 190 |
|
| 191 |
-
|
| 192 |
-
if label == '1_Address' and landmarks_list:
|
| 193 |
-
address_landmarks = landmarks_list
|
| 194 |
-
|
| 195 |
-
phase_analysis = self.analyze_phase(label, landmarks_list)
|
| 196 |
|
| 197 |
report["phases"][label] = phase_analysis
|
| 198 |
total_score += phase_analysis["score"]
|
|
@@ -201,15 +260,9 @@ class GolfDiagnosticEngine:
|
|
| 201 |
if valid_phases > 0:
|
| 202 |
report["overall_score"] = round(total_score / valid_phases, 1)
|
| 203 |
|
| 204 |
-
# Detect View Angle một lần duy nhất
|
| 205 |
-
if address_landmarks:
|
| 206 |
-
report["view_angle"] = self.detect_view_angle(address_landmarks)
|
| 207 |
-
|
| 208 |
-
# Return dict hoặc ghi file (legacy)
|
| 209 |
if return_dict:
|
| 210 |
return report
|
| 211 |
else:
|
| 212 |
-
# Lưu báo cáo vào thư mục output của video
|
| 213 |
report_path = os.path.join(output_dir, 'report.json')
|
| 214 |
with open(report_path, 'w', encoding='utf-8') as f:
|
| 215 |
json.dump(report, f, indent=4, ensure_ascii=False)
|
|
|
|
| 32 |
r_hip = landmarks[self.mp_pose.PoseLandmark.RIGHT_HIP.value]
|
| 33 |
|
| 34 |
shoulder_width = abs(l_shoulder.x - r_shoulder.x)
|
|
|
|
|
|
|
| 35 |
mid_shoulder_y = (l_shoulder.y + r_shoulder.y) / 2
|
| 36 |
mid_hip_y = (l_hip.y + r_hip.y) / 2
|
| 37 |
torso_height = abs(mid_shoulder_y - mid_hip_y)
|
| 38 |
|
| 39 |
if torso_height == 0: return "Unknown"
|
| 40 |
|
|
|
|
| 41 |
ratio = shoulder_width / torso_height
|
| 42 |
|
| 43 |
+
# Nếu tỷ lệ > 0.35 -> Face-on.
|
| 44 |
+
if ratio > 0.35:
|
| 45 |
+
return "Face-on"
|
| 46 |
else:
|
| 47 |
+
return "Down-the-Line"
|
|
|
|
| 48 |
|
| 49 |
def calculate_angle(self, a, b, c):
|
| 50 |
"""Tính góc (độ) giữa 3 điểm a, b, c (b là đỉnh)"""
|
|
|
|
| 70 |
"""Vẽ landmarks tinh tế và chuyên nghiệp hơn"""
|
| 71 |
annotated_image = image.copy()
|
| 72 |
|
| 73 |
+
landmark_style = self.mp_drawing.DrawingSpec(color=(0, 255, 0), thickness=1, circle_radius=1)
|
| 74 |
+
connection_style = self.mp_drawing.DrawingSpec(color=(255, 255, 255), thickness=1)
|
|
|
|
| 75 |
|
|
|
|
| 76 |
self.mp_drawing.draw_landmarks(
|
| 77 |
annotated_image, landmarks_proto, self.mp_pose.POSE_CONNECTIONS,
|
| 78 |
landmark_style,
|
| 79 |
connection_style
|
| 80 |
)
|
|
|
|
| 81 |
return annotated_image
|
| 82 |
|
| 83 |
+
def analyze_phase(self, phase_name, landmarks, address_landmarks=None, view_angle="Unknown"):
|
| 84 |
if not landmarks:
|
| 85 |
return {"score": 0, "comments": ["Không tìm thấy tư thế"], "data": {}}
|
| 86 |
|
| 87 |
analysis = {"score": 10.0, "comments": [], "data": {}, "raw_landmarks": []}
|
| 88 |
|
| 89 |
+
# Helper lấy tọa độ (x, y)
|
| 90 |
+
def get_xy(idx):
|
| 91 |
+
return [landmarks[idx].x, landmarks[idx].y]
|
| 92 |
+
|
| 93 |
+
l_shoulder = get_xy(self.mp_pose.PoseLandmark.LEFT_SHOULDER.value)
|
| 94 |
+
r_shoulder = get_xy(self.mp_pose.PoseLandmark.RIGHT_SHOULDER.value)
|
| 95 |
+
l_elbow = get_xy(self.mp_pose.PoseLandmark.LEFT_ELBOW.value)
|
| 96 |
+
r_elbow = get_xy(self.mp_pose.PoseLandmark.RIGHT_ELBOW.value)
|
| 97 |
+
l_wrist = get_xy(self.mp_pose.PoseLandmark.LEFT_WRIST.value)
|
| 98 |
+
r_wrist = get_xy(self.mp_pose.PoseLandmark.RIGHT_WRIST.value)
|
| 99 |
+
l_hip = get_xy(self.mp_pose.PoseLandmark.LEFT_HIP.value)
|
| 100 |
+
r_hip = get_xy(self.mp_pose.PoseLandmark.RIGHT_HIP.value)
|
| 101 |
+
l_knee = get_xy(self.mp_pose.PoseLandmark.LEFT_KNEE.value)
|
| 102 |
+
r_knee = get_xy(self.mp_pose.PoseLandmark.RIGHT_KNEE.value)
|
| 103 |
+
l_ankle = get_xy(self.mp_pose.PoseLandmark.LEFT_ANKLE.value)
|
| 104 |
+
r_ankle = get_xy(self.mp_pose.PoseLandmark.RIGHT_ANKLE.value)
|
| 105 |
+
nose = get_xy(self.mp_pose.PoseLandmark.NOSE.value)
|
| 106 |
+
|
| 107 |
+
# Trích xuất landmarks thô
|
| 108 |
for i, lm in enumerate(landmarks):
|
| 109 |
analysis["raw_landmarks"].append({
|
| 110 |
+
"id": i, "name": self.mp_pose.PoseLandmark(i).name,
|
| 111 |
+
"x": round(lm.x, 4), "y": round(lm.y, 4), "z": round(lm.z, 4), "visibility": round(lm.visibility, 4)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 112 |
})
|
| 113 |
|
| 114 |
+
# --- CHUẨN HÓA TỌA ĐỘ (Normalization) ---
|
| 115 |
+
current_ankle_center_x = (l_ankle[0] + r_ankle[0]) / 2
|
| 116 |
+
|
| 117 |
+
addr_ankle_center_x = 0
|
| 118 |
+
addr_nose_x_rel = 0
|
| 119 |
+
addr_hip_x_rel = 0
|
| 120 |
+
|
| 121 |
+
if address_landmarks:
|
| 122 |
+
al_ankle_l = address_landmarks[self.mp_pose.PoseLandmark.LEFT_ANKLE.value].x
|
| 123 |
+
al_ankle_r = address_landmarks[self.mp_pose.PoseLandmark.RIGHT_ANKLE.value].x
|
| 124 |
+
addr_ankle_center_x = (al_ankle_l + al_ankle_r) / 2
|
| 125 |
+
|
| 126 |
+
al_nose = address_landmarks[self.mp_pose.PoseLandmark.NOSE.value].x
|
| 127 |
+
al_hip = (address_landmarks[self.mp_pose.PoseLandmark.LEFT_HIP.value].x +
|
| 128 |
+
address_landmarks[self.mp_pose.PoseLandmark.RIGHT_HIP.value].x) / 2
|
| 129 |
+
|
| 130 |
+
addr_nose_x_rel = al_nose - addr_ankle_center_x
|
| 131 |
+
addr_hip_x_rel = al_hip - addr_ankle_center_x
|
| 132 |
+
|
| 133 |
+
curr_nose_x_rel = nose[0] - current_ankle_center_x
|
| 134 |
+
curr_hip_x_rel = ((l_hip[0] + r_hip[0])/2) - current_ankle_center_x
|
| 135 |
+
|
| 136 |
+
# --- LOGIC ---
|
| 137 |
+
|
| 138 |
if phase_name.endswith('Address'):
|
| 139 |
+
# 1. Stance Width (CHỈ CHECK FACE-ON)
|
| 140 |
+
if view_angle == "Face-on":
|
| 141 |
+
shoulder_width = np.abs(l_shoulder[0] - r_shoulder[0])
|
| 142 |
+
stance_width = np.abs(l_ankle[0] - r_ankle[0])
|
| 143 |
+
if shoulder_width > 0:
|
| 144 |
+
ratio = stance_width / shoulder_width
|
| 145 |
+
analysis["data"]["stance_ratio"] = ratio
|
| 146 |
+
if ratio < 0.9:
|
| 147 |
+
analysis["score"] -= 1.0
|
| 148 |
+
analysis["comments"].append("Tư thế đứng quá hẹp (Narrow Stance)")
|
| 149 |
+
elif ratio > 1.5:
|
| 150 |
+
analysis["score"] -= 1.0
|
| 151 |
+
analysis["comments"].append("Tư thế đứng quá rộng (Wide Stance)")
|
| 152 |
+
|
| 153 |
+
# 2. Knee Flex
|
| 154 |
+
avg_knee_angle = (self.calculate_angle(l_hip, l_knee, l_ankle) +
|
| 155 |
+
self.calculate_angle(r_hip, r_knee, r_ankle)) / 2
|
| 156 |
+
analysis["data"]["knee_angle"] = avg_knee_angle
|
| 157 |
+
if avg_knee_angle > 175:
|
| 158 |
+
# DTL thấy rõ hơn, Face-on cũng thấy được
|
| 159 |
analysis["score"] -= 1.0
|
| 160 |
+
analysis["comments"].append("Đầu gối quá thẳng (Locking Knees)")
|
| 161 |
+
elif avg_knee_angle < 135:
|
| 162 |
+
if view_angle == "Face-on":
|
| 163 |
+
analysis["score"] -= 1.0
|
| 164 |
+
analysis["comments"].append("Đầu gối khuỵu quá mức")
|
| 165 |
|
| 166 |
elif phase_name.endswith('Top'):
|
| 167 |
+
# 3. Chicken Wing
|
| 168 |
lead_arm_angle = self.calculate_angle(l_shoulder, l_elbow, l_wrist)
|
| 169 |
analysis["data"]["lead_arm_angle"] = lead_arm_angle
|
| 170 |
+
threshold = 140 if view_angle == "Face-on" else 130
|
| 171 |
+
if lead_arm_angle < threshold:
|
| 172 |
analysis["score"] -= 2.0
|
| 173 |
+
analysis["comments"].append("Tay trái bị gập (Chicken Wing)")
|
| 174 |
+
|
| 175 |
+
# 4. Sway / Slide (CHỈ FACE-ON)
|
| 176 |
+
if address_landmarks and view_angle == "Face-on":
|
| 177 |
+
sway = curr_nose_x_rel - addr_nose_x_rel
|
| 178 |
+
analysis["data"]["head_sway"] = sway
|
| 179 |
+
if abs(sway) > 0.08:
|
| 180 |
+
analysis["score"] -= 1.5
|
| 181 |
+
analysis["comments"].append("Đầu di chuy��n quá nhiều (Sway)")
|
| 182 |
+
|
| 183 |
+
slide = curr_hip_x_rel - addr_hip_x_rel
|
| 184 |
+
if slide > 0.08:
|
| 185 |
+
analysis["score"] -= 1.0
|
| 186 |
+
analysis["comments"].append("Hông trượt sang phải (Hip Slide)")
|
| 187 |
+
|
| 188 |
+
# 5. Reverse Spine Angle (Face-on only)
|
| 189 |
+
if view_angle == "Face-on":
|
| 190 |
+
if curr_nose_x_rel < curr_hip_x_rel - 0.05:
|
| 191 |
+
analysis["score"] -= 2.0
|
| 192 |
+
analysis["comments"].append("Lỗi trục nghiêng ngược (Reverse Spine Angle)")
|
| 193 |
|
| 194 |
elif phase_name.endswith('Impact'):
|
| 195 |
+
# 6. Weight Shift
|
| 196 |
+
if address_landmarks and view_angle == "Face-on":
|
| 197 |
+
shift = curr_hip_x_rel - addr_hip_x_rel
|
| 198 |
+
analysis["data"]["weight_shift"] = shift
|
| 199 |
+
|
| 200 |
+
if shift > -0.01:
|
| 201 |
+
analysis["score"] -= 2.0
|
| 202 |
+
analysis["comments"].append("Thiếu chuyển trọng tâm sang trái")
|
|
|
|
| 203 |
|
| 204 |
+
# 7. Scooping
|
| 205 |
+
impact_angle = self.calculate_angle(l_shoulder, l_elbow, l_wrist)
|
| 206 |
+
if impact_angle < 155:
|
| 207 |
+
analysis["score"] -= 2.0
|
| 208 |
+
analysis["comments"].append("Tay trái gập sớm (Scooping/Chicken Wing)")
|
|
|
|
| 209 |
|
| 210 |
+
elif phase_name.endswith('Finish'):
|
| 211 |
+
# 8. Balance
|
| 212 |
+
if view_angle == "Face-on":
|
| 213 |
+
hip_vs_ankle = l_hip[0] - l_ankle[0]
|
| 214 |
+
if abs(hip_vs_ankle) > 0.15:
|
| 215 |
+
analysis["score"] -= 1.0
|
| 216 |
+
analysis["comments"].append("Kết thúc chưa vững (Off Balance)")
|
| 217 |
+
|
| 218 |
if not analysis["comments"]:
|
| 219 |
+
analysis["comments"].append("Tư thế tốt")
|
| 220 |
|
| 221 |
+
analysis["score"] = round(max(0, min(10, analysis["score"])), 1)
|
| 222 |
return analysis
|
| 223 |
|
| 224 |
def process_video_results(self, output_dir, return_dict=False):
|
|
|
|
| 225 |
video_id = os.path.basename(output_dir)
|
| 226 |
extraction_dir = os.path.join(output_dir, 'phases')
|
| 227 |
|
|
|
|
| 230 |
total_score = 0
|
| 231 |
valid_phases = 0
|
| 232 |
|
|
|
|
| 233 |
address_landmarks = None
|
| 234 |
+
address_path = os.path.join(extraction_dir, '1_Address', f"{video_id}.jpg")
|
| 235 |
+
|
| 236 |
+
view_angle = "Unknown"
|
| 237 |
+
if os.path.exists(address_path):
|
| 238 |
+
img = cv2.imread(address_path)
|
| 239 |
+
lm_list, _ = self.get_landmarks(img)
|
| 240 |
+
if lm_list:
|
| 241 |
+
address_landmarks = lm_list
|
| 242 |
+
view_angle = self.detect_view_angle(address_landmarks)
|
| 243 |
+
|
| 244 |
+
report["view_angle"] = view_angle
|
| 245 |
|
| 246 |
for label in self.labels:
|
| 247 |
img_path = os.path.join(extraction_dir, label, f"{video_id}.jpg")
|
|
|
|
| 251 |
image = cv2.imread(img_path)
|
| 252 |
landmarks_list, _ = self.get_landmarks(image)
|
| 253 |
|
| 254 |
+
phase_analysis = self.analyze_phase(label, landmarks_list, address_landmarks, view_angle)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 255 |
|
| 256 |
report["phases"][label] = phase_analysis
|
| 257 |
total_score += phase_analysis["score"]
|
|
|
|
| 260 |
if valid_phases > 0:
|
| 261 |
report["overall_score"] = round(total_score / valid_phases, 1)
|
| 262 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 263 |
if return_dict:
|
| 264 |
return report
|
| 265 |
else:
|
|
|
|
| 266 |
report_path = os.path.join(output_dir, 'report.json')
|
| 267 |
with open(report_path, 'w', encoding='utf-8') as f:
|
| 268 |
json.dump(report, f, indent=4, ensure_ascii=False)
|
coach.py
CHANGED
|
@@ -24,11 +24,26 @@ class GolfCoachEngine:
|
|
| 24 |
|
| 25 |
# Thư viện bài tập gợi ý
|
| 26 |
self.drill_library = {
|
| 27 |
-
|
| 28 |
-
"Tư thế đứng quá
|
| 29 |
-
"
|
| 30 |
-
"
|
| 31 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 32 |
}
|
| 33 |
|
| 34 |
def generate_report(self, diagnostic_json_path):
|
|
|
|
| 24 |
|
| 25 |
# Thư viện bài tập gợi ý
|
| 26 |
self.drill_library = {
|
| 27 |
+
# Stance & Address
|
| 28 |
+
"Tư thế đứng quá rộng (Wide Stance)": "Thu hẹp khoảng cách chân bằng chiều rộng vai để xoay hông dễ dàng hơn.",
|
| 29 |
+
"Tư thế đứng quá hẹp (Narrow Stance)": "Mở rộng chân thêm chút (bằng vai) để tạo nền tảng vững chắc.",
|
| 30 |
+
"Đầu gối quá thẳng, thiếu sự linh hoạt (Locking Knees)": "Thả lỏng đầu gối, làm động tác như chuẩn bị ngồi xuống ghế cao.",
|
| 31 |
+
"Đầu gối khuỵu quá mức (Sitting too much)": "Đứng cao hơn chút, chỉ khuỵu nhẹ đầu gối để dồn trọng tâm lên ức bàn chân.",
|
| 32 |
+
|
| 33 |
+
# Backswing & Top
|
| 34 |
+
"Tay trái bị gập (Chicken Wing) - Mất bán kính swing": "Tập kẹp khăn dưới nách khi swing để giữ tay sát thân.",
|
| 35 |
+
"Đầu di chuyển quá nhiều (Head Sway) - Gây mất ổn định": "Nhờ bạn giữ đầu hoặc nhìn vào gương, tập xoay vai mà đầu vẫn giữ yên.",
|
| 36 |
+
"Hông trượt sang phải (Hip Slide) thay vì xoay": "Tập bài xoay hông trong xô nước (Barrel Turn) - tưởng tượng đứng trong thùng phuy và chỉ xoay, không trượt.",
|
| 37 |
+
"Lỗi trục nghiêng ngược (Reverse Spine Angle) - Dễ gây đau lưng": "Đảm bảo vai trái hạ thấp hơn vai phải khi lên đỉnh, mắt vẫn nhìn vào phía sau bóng.",
|
| 38 |
+
|
| 39 |
+
# Impact
|
| 40 |
+
"Tay trái gập khi tiếp bóng (Scooping/Chicken Wing)": "Bài tập Impact Bag: Tập đánh vào túi đệm và dừng lại ở Impact để cảm nhận tay thẳng.",
|
| 41 |
+
"Trọng tâm dồn về chân sau (Hanging Back) - Mất lực": "Bài tập bước chân (Step Drill): Bước chân trái lên khi downswing để ép trọng tâm chuyển sang trái.",
|
| 42 |
+
"Thiếu chuyển trọng tâm sang chân trái": "Đặt bóng dưới lòng bàn chân phải, khi swing xuống phải nhấc gót phải lên khỏi bóng.",
|
| 43 |
+
"Đầu lao về trước quá sớm (Lunging)": "Cố gắng cảm giác như 'đánh đầu' về phía sau khi gậy tiếp xúc bóng.",
|
| 44 |
+
|
| 45 |
+
# Finish
|
| 46 |
+
"Kết thúc không dồn hết trọng tâm sang trái": "Tập giữ tư thế kết thúc trong 3 giây, nhấc hoàn toàn chân phải lên chỉ tì bằng mũi giày."
|
| 47 |
}
|
| 48 |
|
| 49 |
def generate_report(self, diagnostic_json_path):
|
docs/final_golf_swing.py
ADDED
|
@@ -0,0 +1,730 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Generated from: final_golf_swing.ipynb
|
| 2 |
+
# Converted at: 2026-01-01T14:06:29.903Z
|
| 3 |
+
# Next step (optional): refactor into modules & generate tests with RunCell
|
| 4 |
+
# Quick start: pip install runcell
|
| 5 |
+
|
| 6 |
+
# ### 📦 Installation Summary
|
| 7 |
+
#
|
| 8 |
+
# This code installs essential Python libraries for video processing, pose detection, progress tracking, and data handling:
|
| 9 |
+
#
|
| 10 |
+
# - `moviepy==1.0.3`: Used for video editing (cutting, merging, adding audio).
|
| 11 |
+
# - `mediapipe==0.10.21`: Provides pose and hand detection (great for analyzing movement like golf swings).
|
| 12 |
+
# - `tqdm==4.67.1`: Adds progress bars to loops and downloads.
|
| 13 |
+
# - `dataclasses-json==0.6.7`: Allows easy serialization/deserialization of Python dataclasses to/from JSON.
|
| 14 |
+
# - `backoff==2.2.1`: Helps with retry logic for functions that might fail (e.g., API calls).
|
| 15 |
+
# - `supervision==0.26.0`: Useful for drawing overlays on video frames (bounding boxes, labels).
|
| 16 |
+
# - `yt-dlp`: Downloads videos from YouTube and other platforms (quietly installed with `-q`).
|
| 17 |
+
#
|
| 18 |
+
# Note: `--no-deps` skips installing dependencies for the first command to avoid version conflicts.
|
| 19 |
+
#
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
!pip install --no-deps moviepy==1.0.3 mediapipe==0.10.21 tqdm==4.67.1
|
| 23 |
+
!pip install dataclasses-json==0.6.7
|
| 24 |
+
!pip install backoff==2.2.1
|
| 25 |
+
!pip install supervision==0.26.0
|
| 26 |
+
!!pip install -q yt-dlp
|
| 27 |
+
|
| 28 |
+
# ### 🎬 YouTube Shorts Downloader (with `yt-dlp`)
|
| 29 |
+
#
|
| 30 |
+
# This code uses `yt-dlp` to download high-quality YouTube Shorts as `.mp4` files:
|
| 31 |
+
#
|
| 32 |
+
# - `-f "bestvideo[ext=mp4]+bestaudio[ext=m4a]/mp4"`: Selects the best available video stream in MP4 format and merges it with the best audio in M4A. Falls back to a single MP4 if needed.
|
| 33 |
+
# - `-o "filename.mp4"`: Specifies the output filename for the downloaded video.
|
| 34 |
+
# - URLs point to YouTube Shorts featuring golfers Ludvig Åberg and Max Homa.
|
| 35 |
+
#
|
| 36 |
+
# 📥 Output files:
|
| 37 |
+
# - `ludvig_aberg_driver.mp4`
|
| 38 |
+
# - `max_homa_iron.mp4`
|
| 39 |
+
#
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
!yt-dlp -f "bestvideo[ext=mp4]+bestaudio[ext=m4a]/mp4" -o "ludvig_aberg_driver.mp4" "https://www.youtube.com/shorts/9nhFobbdJxQ"
|
| 43 |
+
!yt-dlp -f "bestvideo[ext=mp4]+bestaudio[ext=m4a]/mp4" -o "max_homa_iron.mp4" "https://www.youtube.com/shorts/aB__zg42i9g"
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
# ### 🧠 Core Imports Overview
|
| 47 |
+
#
|
| 48 |
+
# This block imports essential libraries for processing, visualization, and media handling:
|
| 49 |
+
#
|
| 50 |
+
# - **System & Utilities**:
|
| 51 |
+
# - `gc`, `time`, `subprocess`: For garbage collection, timing operations, and running shell commands.
|
| 52 |
+
#
|
| 53 |
+
# - **Numerical & Signal Processing**:
|
| 54 |
+
# - `numpy`: Core library for numerical computations.
|
| 55 |
+
# - `uniform_filter1d` (from `scipy.ndimage`): Smooths 1D signals (e.g., joint positions over frames).
|
| 56 |
+
#
|
| 57 |
+
# - **Visualization**:
|
| 58 |
+
# - `matplotlib.pyplot`: For plotting graphs and visuals.
|
| 59 |
+
# - `FigureCanvas`: Renders plots into images.
|
| 60 |
+
# - `mpl_use`: Sets a Colab-safe backend for rendering plots.
|
| 61 |
+
#
|
| 62 |
+
# - **Media Processing**:
|
| 63 |
+
# - `cv2`: OpenCV library for reading, processing, and displaying video frames.
|
| 64 |
+
# - `mediapipe`: Used for pose estimation and landmark detection.
|
| 65 |
+
#
|
| 66 |
+
# - **Colab Display**:
|
| 67 |
+
# - `IPython.display`: For showing videos inline using `Video()` and `display()` functions.
|
| 68 |
+
#
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
# Core
|
| 72 |
+
import gc
|
| 73 |
+
import time
|
| 74 |
+
import subprocess
|
| 75 |
+
|
| 76 |
+
# Numerical and signal processing
|
| 77 |
+
import numpy as np
|
| 78 |
+
from scipy.ndimage import uniform_filter1d
|
| 79 |
+
|
| 80 |
+
# Visualization
|
| 81 |
+
import matplotlib.pyplot as plt
|
| 82 |
+
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
|
| 83 |
+
from matplotlib import use as mpl_use # Needed for Colab-safe rendering
|
| 84 |
+
|
| 85 |
+
# Media processing
|
| 86 |
+
import cv2
|
| 87 |
+
import mediapipe as mp
|
| 88 |
+
|
| 89 |
+
# Colab display tools
|
| 90 |
+
from IPython.display import Video, display
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
# ### 🔇 Add Silent Audio to Videos Using FFmpeg
|
| 94 |
+
#
|
| 95 |
+
# This code prepares four golf swing videos (two input clips and two YouTube references) by adding a silent audio track to each. This ensures compatibility with video players that require an audio stream.
|
| 96 |
+
#
|
| 97 |
+
# - **Input Videos**:
|
| 98 |
+
# - `video_iron`, `video_driver`: Your own recorded swing clips.
|
| 99 |
+
# - `iron_reference`, `driver_reference`: Reference swings from YouTube (e.g., Max Homa, Ludvig Åberg).
|
| 100 |
+
#
|
| 101 |
+
# - **Output Paths**:
|
| 102 |
+
# - For each video, a `_fixed.MP4` version is created with silent audio.
|
| 103 |
+
#
|
| 104 |
+
# - **FFmpeg Command**:
|
| 105 |
+
# - `-i <input>`: Input video file.
|
| 106 |
+
# - `-f lavfi -i anullsrc`: Adds silent stereo audio at 44.1kHz.
|
| 107 |
+
# - `-shortest`: Ends the audio when video ends.
|
| 108 |
+
# - `-c:v libx264`: Encodes video using H.264.
|
| 109 |
+
# - `-c:a aac -b:a 128k`: Encodes audio using AAC at 128 kbps.
|
| 110 |
+
# - `-movflags +faststart`: Optimizes video for fast playback start.
|
| 111 |
+
#
|
| 112 |
+
# 📁 Outputs:
|
| 113 |
+
# - `*_fixed.MP4` files for all input and reference videos with embedded silent audio.
|
| 114 |
+
#
|
| 115 |
+
|
| 116 |
+
|
| 117 |
+
# Input video path and define output path for audio-fixed video
|
| 118 |
+
|
| 119 |
+
iron_reference = "max_homa_iron.mp4"
|
| 120 |
+
driver_reference = "ludvig_aberg_driver"
|
| 121 |
+
|
| 122 |
+
video_iron = "/content/IMG_1022.MP4" # original input video # IRON
|
| 123 |
+
video_iron_fixed = video_iron.rsplit(".", 1)[0] + "_fixed.MP4"
|
| 124 |
+
|
| 125 |
+
video_driver = "/content/IMG_0758.MP4" # alternate input # DRIVER
|
| 126 |
+
video_driver_fixed = video_driver.rsplit(".", 1)[0] + "_fixed.MP4"
|
| 127 |
+
|
| 128 |
+
iron_reference = "/content/max_homa_iron.mp4"
|
| 129 |
+
iron_reference_fixed = iron_reference.rsplit(".", 1)[0] + "_fixed.MP4"
|
| 130 |
+
|
| 131 |
+
driver_reference = "/content/ludvig_aberg_driver.mp4"
|
| 132 |
+
driver_reference_fixed = driver_reference.rsplit(".", 1)[0] + "_fixed.MP4"
|
| 133 |
+
|
| 134 |
+
|
| 135 |
+
# 1. Preserve original video and add silent audio track to a copy
|
| 136 |
+
ffmpeg_cmd = f"""
|
| 137 |
+
ffmpeg -y -i "{video_iron}" -f lavfi -i anullsrc=channel_layout=stereo:sample_rate=44100 \
|
| 138 |
+
-shortest -c:v libx264 -c:a aac -b:a 128k -movflags +faststart "{video_iron_fixed}"
|
| 139 |
+
"""
|
| 140 |
+
subprocess.run(ffmpeg_cmd, shell=True)
|
| 141 |
+
|
| 142 |
+
# 1. Preserve original video and add silent audio track to a copy
|
| 143 |
+
ffmpeg_cmd = f"""
|
| 144 |
+
ffmpeg -y -i "{video_driver}" -f lavfi -i anullsrc=channel_layout=stereo:sample_rate=44100 \
|
| 145 |
+
-shortest -c:v libx264 -c:a aac -b:a 128k -movflags +faststart "{video_driver_fixed}"
|
| 146 |
+
"""
|
| 147 |
+
subprocess.run(ffmpeg_cmd, shell=True)
|
| 148 |
+
|
| 149 |
+
# 1. Preserve original video and add silent audio track to a copy
|
| 150 |
+
ffmpeg_cmd = f"""
|
| 151 |
+
ffmpeg -y -i "{iron_reference}" -f lavfi -i anullsrc=channel_layout=stereo:sample_rate=44100 \
|
| 152 |
+
-shortest -c:v libx264 -c:a aac -b:a 128k -movflags +faststart "{iron_reference_fixed}"
|
| 153 |
+
"""
|
| 154 |
+
subprocess.run(ffmpeg_cmd, shell=True)
|
| 155 |
+
|
| 156 |
+
# 1. Preserve original video and add silent audio track to a copy
|
| 157 |
+
ffmpeg_cmd = f"""
|
| 158 |
+
ffmpeg -y -i "{driver_reference}" -f lavfi -i anullsrc=channel_layout=stereo:sample_rate=44100 \
|
| 159 |
+
-shortest -c:v libx264 -c:a aac -b:a 128k -movflags +faststart "{driver_reference_fixed}"
|
| 160 |
+
"""
|
| 161 |
+
subprocess.run(ffmpeg_cmd, shell=True)
|
| 162 |
+
|
| 163 |
+
# Preview the audio-fixed video (same content as original, with an added audio stream)
|
| 164 |
+
Video(video_iron_fixed, embed=True, width=600, height=800)
|
| 165 |
+
|
| 166 |
+
# Preview the audio-fixed video (same content as original, with an added audio stream)
|
| 167 |
+
Video(video_driver_fixed, embed=True, width=600, height=800)
|
| 168 |
+
|
| 169 |
+
# Preview the audio-fixed video (same content as original, with an added audio stream)
|
| 170 |
+
Video(iron_reference_fixed, embed=True, width=600, height=800)
|
| 171 |
+
|
| 172 |
+
# Preview the audio-fixed video (same content as original, with an added audio stream)
|
| 173 |
+
Video(driver_reference_fixed, embed=True, width=600, height=800)
|
| 174 |
+
|
| 175 |
+
# ### 🏌️♂️ Pose Feature Extraction (Wrist Y-Coordinate)
|
| 176 |
+
#
|
| 177 |
+
# This function `extract_pose_features_debug(video_path)` analyzes a video frame-by-frame to extract the **vertical (Y) position of visible wrists** using MediaPipe Pose:
|
| 178 |
+
#
|
| 179 |
+
# - **Video Setup**:
|
| 180 |
+
# - Loads the video and retrieves its frame count and resolution.
|
| 181 |
+
# - Initializes MediaPipe Pose in video (non-static) mode.
|
| 182 |
+
#
|
| 183 |
+
# - **Frame Loop**:
|
| 184 |
+
# - For each frame:
|
| 185 |
+
# - Converts BGR to RGB for pose processing.
|
| 186 |
+
# - Detects body landmarks using MediaPipe.
|
| 187 |
+
# - If pose is found:
|
| 188 |
+
# - Checks visibility of **left and right wrists**.
|
| 189 |
+
# - Computes average Y-position (vertical) of visible wrists (scaled to video height).
|
| 190 |
+
# - If no pose or wrist visibility is low, logs a warning and sets `wrist_y` as `None`.
|
| 191 |
+
#
|
| 192 |
+
# - **Return**:
|
| 193 |
+
# - Returns a list of dictionaries like `{"frame_idx": 42, "wrist_y": 138.5}` for each frame.
|
| 194 |
+
#
|
| 195 |
+
# 👀 Use this to analyze hand motion over time, useful for swing segmentation or performance analysis.
|
| 196 |
+
#
|
| 197 |
+
|
| 198 |
+
|
| 199 |
+
def extract_pose_features_debug(video_path):
|
| 200 |
+
cap = cv2.VideoCapture(video_path)
|
| 201 |
+
original_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
|
| 202 |
+
original_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
|
| 203 |
+
num_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
|
| 204 |
+
print(f"🎞️ Total frames: {num_frames}, Resolution: {original_width}x{original_height}")
|
| 205 |
+
|
| 206 |
+
used_height = original_height # No rotation, use original height
|
| 207 |
+
|
| 208 |
+
mp_pose = mp.solutions.pose
|
| 209 |
+
pose = mp_pose.Pose(static_image_mode=False)
|
| 210 |
+
frame_data = []
|
| 211 |
+
|
| 212 |
+
for i in range(num_frames):
|
| 213 |
+
ret, frame = cap.read()
|
| 214 |
+
if not ret:
|
| 215 |
+
print(f"❌ Failed to read frame {i}")
|
| 216 |
+
break
|
| 217 |
+
|
| 218 |
+
rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
| 219 |
+
results = pose.process(rgb)
|
| 220 |
+
data = {"frame_idx": i}
|
| 221 |
+
|
| 222 |
+
if results.pose_landmarks:
|
| 223 |
+
# print(f"✅ Pose detected on frame {i}")
|
| 224 |
+
lm = results.pose_landmarks.landmark
|
| 225 |
+
lw = lm[mp_pose.PoseLandmark.LEFT_WRIST]
|
| 226 |
+
rw = lm[mp_pose.PoseLandmark.RIGHT_WRIST]
|
| 227 |
+
visible_wrists = [p for p in (lw, rw) if p.visibility > 0.4]
|
| 228 |
+
if visible_wrists:
|
| 229 |
+
avg_y = np.mean([p.y for p in visible_wrists])
|
| 230 |
+
data["wrist_y"] = avg_y * used_height
|
| 231 |
+
# print(f"👋 Frame {i}: Wrist Y = {data['wrist_y']:.2f}")
|
| 232 |
+
else:
|
| 233 |
+
print(f"⚠️ Frame {i}: Wrists not visible")
|
| 234 |
+
data["wrist_y"] = None
|
| 235 |
+
else:
|
| 236 |
+
print(f"❌ Frame {i}: No pose detected")
|
| 237 |
+
data["wrist_y"] = None
|
| 238 |
+
|
| 239 |
+
frame_data.append(data)
|
| 240 |
+
|
| 241 |
+
cap.release()
|
| 242 |
+
pose.close()
|
| 243 |
+
return frame_data
|
| 244 |
+
|
| 245 |
+
|
| 246 |
+
|
| 247 |
+
|
| 248 |
+
# ### 📈 Run Pose Extraction on All Videos
|
| 249 |
+
#
|
| 250 |
+
# This block runs the `extract_pose_features_debug()` function on all four prepared videos (with silent audio):
|
| 251 |
+
#
|
| 252 |
+
# - `video_iron_fixed`: Your iron swing clip
|
| 253 |
+
# - `video_driver_fixed`: Your driver swing clip
|
| 254 |
+
# - `iron_reference_fixed`: Max Homa’s reference swing
|
| 255 |
+
# - `driver_reference_fixed`: Ludvig Åberg’s reference swing
|
| 256 |
+
#
|
| 257 |
+
# Each call extracts the **Y-coordinate of visible wrists** frame-by-frame and stores the results in:
|
| 258 |
+
#
|
| 259 |
+
# - `frame_data_iron`
|
| 260 |
+
# - `frame_data_driver`
|
| 261 |
+
# - `frame_data_iron_reference`
|
| 262 |
+
# - `frame_data_driver_reference`
|
| 263 |
+
#
|
| 264 |
+
# 📦 These variables now hold pose-based wrist motion data for later analysis or swing comparison.
|
| 265 |
+
#
|
| 266 |
+
|
| 267 |
+
|
| 268 |
+
frame_data_iron = extract_pose_features_debug(video_iron_fixed)
|
| 269 |
+
frame_data_driver = extract_pose_features_debug(video_driver_fixed)
|
| 270 |
+
frame_data_iron_reference = extract_pose_features_debug(iron_reference_fixed)
|
| 271 |
+
frame_data_driver_reference = extract_pose_features_debug(driver_reference_fixed)
|
| 272 |
+
|
| 273 |
+
#
|
| 274 |
+
|
| 275 |
+
|
| 276 |
+
# ### 🏌️♀️ Golf Swing Phase Detection via Wrist Y-Motion
|
| 277 |
+
#
|
| 278 |
+
# This function `detect_swing_phases()` takes wrist Y-coordinate data and dynamically identifies key golf swing phases using smoothed motion patterns and gradient analysis:
|
| 279 |
+
#
|
| 280 |
+
# #### 🔍 Key Steps:
|
| 281 |
+
# - **Smoothing & Velocity**:
|
| 282 |
+
# - Applies a moving average to wrist Y (`smoothing_window`), then calculates velocity and its magnitude.
|
| 283 |
+
#
|
| 284 |
+
# - **Swing Start & End**:
|
| 285 |
+
# - Detects when motion exceeds a dynamic threshold (`threshold_percentile`) to mark swing boundaries.
|
| 286 |
+
#
|
| 287 |
+
# - **Address Detection**:
|
| 288 |
+
# - Scans backwards from swing start to find a stable ("flat") wrist phase, indicating the pre-swing address.
|
| 289 |
+
#
|
| 290 |
+
# - **Top of Backswing**:
|
| 291 |
+
# - Finds the lowest wrist Y point before the swing starts descending (indicating the top of the backswing).
|
| 292 |
+
#
|
| 293 |
+
# - **Impact Detection**:
|
| 294 |
+
# - After the top, identifies a stable high point in wrist Y as impact, using tolerance around local max.
|
| 295 |
+
#
|
| 296 |
+
# - **Phase Segmentation**:
|
| 297 |
+
# - Returns six labeled segments: `"Address"`, `"Backswing"`, `"Top"`, `"Downswing"`, `"Impact"`, `"Follow Through"`.
|
| 298 |
+
#
|
| 299 |
+
# #### 📊 Visualization:
|
| 300 |
+
# - Plots wrist trajectory with Y flipped (so upward motion looks natural).
|
| 301 |
+
# - Highlights each swing phase using colored spans and labels.
|
| 302 |
+
#
|
| 303 |
+
# #### 📤 Returns:
|
| 304 |
+
# - `phase_ranges`: Dictionary of start/end frames for each phase.
|
| 305 |
+
# - `swing_start`, `swing_end`: Frame indices marking full swing.
|
| 306 |
+
# - `wrist_y`, `smoothed`: Raw and smoothed wrist Y arrays for further analysis.
|
| 307 |
+
#
|
| 308 |
+
# ✅ This unified logic handles both pros and amateurs, dynamically adjusting to wrist movement stability and swing patterns.
|
| 309 |
+
#
|
| 310 |
+
|
| 311 |
+
|
| 312 |
+
|
| 313 |
+
|
| 314 |
+
def detect_swing_phases(frame_data, smoothing_window=5, precheck_window=30, threshold_percentile=90):
|
| 315 |
+
"""
|
| 316 |
+
Analyze wrist Y trajectory and determine key golf swing phase ranges.
|
| 317 |
+
Unified logic. Dynamically determines Address using flatness in wrist_y.
|
| 318 |
+
"""
|
| 319 |
+
# Convert to numpy and handle None
|
| 320 |
+
wrist_y = np.array([d["wrist_y"] if d["wrist_y"] is not None else np.nan for d in frame_data], dtype=np.float32)
|
| 321 |
+
smoothed = uniform_filter1d(wrist_y, size=smoothing_window, mode='nearest')
|
| 322 |
+
velocity = np.gradient(smoothed)
|
| 323 |
+
velocity_mag = np.abs(velocity)
|
| 324 |
+
|
| 325 |
+
# Motion threshold and swing start
|
| 326 |
+
early_motion = np.nanmean(velocity_mag[:precheck_window])
|
| 327 |
+
motion_std = np.nanstd(velocity_mag[:precheck_window])
|
| 328 |
+
buffer_start = precheck_window if (early_motion < 0.001 and motion_std < 0.001) else 0
|
| 329 |
+
threshold = np.nanpercentile(velocity_mag[buffer_start:], threshold_percentile)
|
| 330 |
+
motion_indices = np.where(velocity_mag > threshold)[0]
|
| 331 |
+
motion_indices = motion_indices[motion_indices > buffer_start]
|
| 332 |
+
|
| 333 |
+
if len(motion_indices) > 0:
|
| 334 |
+
swing_start = int(motion_indices[0])
|
| 335 |
+
peak_idx = motion_indices[np.argmax(velocity_mag[motion_indices])]
|
| 336 |
+
target_y = smoothed[swing_start]
|
| 337 |
+
post_peak_range = smoothed[peak_idx+1:]
|
| 338 |
+
swing_end = peak_idx + 1 + int(np.nanargmin(np.abs(post_peak_range - target_y))) if len(post_peak_range) > 0 else len(wrist_y) - 1
|
| 339 |
+
else:
|
| 340 |
+
swing_start = 0
|
| 341 |
+
swing_end = len(wrist_y) - 1
|
| 342 |
+
|
| 343 |
+
# === Dynamic Address detection ===
|
| 344 |
+
flat_std_thresh = 1.0
|
| 345 |
+
min_flat_frames = 10
|
| 346 |
+
address_start = 0
|
| 347 |
+
for i in range(swing_start - min_flat_frames, 0, -1):
|
| 348 |
+
window = smoothed[i:swing_start]
|
| 349 |
+
if np.count_nonzero(~np.isnan(window)) < min_flat_frames:
|
| 350 |
+
continue
|
| 351 |
+
if np.nanstd(window) < flat_std_thresh:
|
| 352 |
+
address_start = i
|
| 353 |
+
else:
|
| 354 |
+
break
|
| 355 |
+
address_end = swing_start
|
| 356 |
+
|
| 357 |
+
# === Top of backswing ===
|
| 358 |
+
full_swing_segment = smoothed[swing_start:swing_end]
|
| 359 |
+
diff = np.diff(full_swing_segment)
|
| 360 |
+
rising_indices = np.where(diff > 0)[0]
|
| 361 |
+
top_candidate_max = swing_start + rising_indices[0] if len(rising_indices) > 0 else min(swing_start + 20, len(smoothed) - 1)
|
| 362 |
+
top_search_end = min(top_candidate_max, swing_end)
|
| 363 |
+
top_idx = swing_start + int(np.nanargmin(smoothed[swing_start:top_search_end])) if top_search_end > swing_start else swing_start
|
| 364 |
+
top_range = (max(0, top_idx - 5), min(len(wrist_y) - 1, top_idx + 5))
|
| 365 |
+
|
| 366 |
+
# === Impact ===
|
| 367 |
+
post_top = smoothed[top_range[1]:swing_end]
|
| 368 |
+
if len(post_top) == 0 or np.all(np.isnan(post_top)):
|
| 369 |
+
impact_range = (top_range[1], top_range[1] + 1)
|
| 370 |
+
else:
|
| 371 |
+
local_max_idx = int(np.nanargmax(post_top))
|
| 372 |
+
max_val = post_top[local_max_idx]
|
| 373 |
+
local_min = np.nanmin(post_top)
|
| 374 |
+
local_max = np.nanmax(post_top)
|
| 375 |
+
dynamic_tol = 0.05 * (local_max - local_min)
|
| 376 |
+
left = local_max_idx
|
| 377 |
+
right = local_max_idx
|
| 378 |
+
while left > 0 and abs(post_top[left - 1] - max_val) < dynamic_tol:
|
| 379 |
+
left -= 1
|
| 380 |
+
while right < len(post_top) - 1 and abs(post_top[right + 1] - max_val) < dynamic_tol:
|
| 381 |
+
right += 1
|
| 382 |
+
impact_range = (top_range[1] + left, top_range[1] + right)
|
| 383 |
+
|
| 384 |
+
# === Phase dictionary ===
|
| 385 |
+
phase_ranges = {
|
| 386 |
+
"Address": (address_start, address_end),
|
| 387 |
+
"Backswing": (swing_start, top_range[0]),
|
| 388 |
+
"Top": top_range,
|
| 389 |
+
"Downswing": (top_range[1], impact_range[0]),
|
| 390 |
+
"Impact": impact_range,
|
| 391 |
+
"Follow Through": (impact_range[1], swing_end)
|
| 392 |
+
}
|
| 393 |
+
|
| 394 |
+
# === Plotting with gaps and flipped Y ===
|
| 395 |
+
x = np.array([d['frame_idx'] for d in frame_data])
|
| 396 |
+
y = np.array([d['wrist_y'] if d['wrist_y'] is not None else np.nan for d in frame_data], dtype=np.float32)
|
| 397 |
+
valid_y = y[~np.isnan(y)]
|
| 398 |
+
y_flipped = np.nan if len(valid_y) == 0 else np.max(valid_y) - y + np.min(valid_y)
|
| 399 |
+
|
| 400 |
+
plt.figure(figsize=(12, 6))
|
| 401 |
+
plt.plot(x, y_flipped, label='Wrist Y (flipped)', color='black')
|
| 402 |
+
colors = ['gray', 'blue', 'orange', 'green', 'red', 'purple']
|
| 403 |
+
for i, (phase, (start, end)) in enumerate(phase_ranges.items()):
|
| 404 |
+
plt.axvspan(start, end, alpha=0.3, color=colors[i % len(colors)], label=phase)
|
| 405 |
+
plt.xlabel("Frame Index")
|
| 406 |
+
plt.ylabel("Wrist Y (flipped)")
|
| 407 |
+
plt.title("Wrist Trajectory with Dynamic Phase Detection")
|
| 408 |
+
plt.legend(loc='upper left')
|
| 409 |
+
plt.grid(True)
|
| 410 |
+
plt.tight_layout()
|
| 411 |
+
plt.show()
|
| 412 |
+
|
| 413 |
+
return phase_ranges, swing_start, swing_end, wrist_y, smoothed
|
| 414 |
+
|
| 415 |
+
|
| 416 |
+
phase_ranges_iron, swing_start_iron, swing_end_iron, wrist_y_iron, smoothed_iron = detect_swing_phases(frame_data_iron)
|
| 417 |
+
print("🏌️♂️ Detected Phase Ranges:", phase_ranges_iron)
|
| 418 |
+
|
| 419 |
+
phase_ranges_driver, swing_start_driver, swing_end_driver, wrist_y_driver, smoothed_driver = detect_swing_phases(frame_data_driver)
|
| 420 |
+
print("🏌️♂️ Detected Phase Ranges:", phase_ranges_driver)
|
| 421 |
+
|
| 422 |
+
phase_ranges_iron_reference, swing_start, swing_end, wrist_y, smoothed = detect_swing_phases(frame_data_iron_reference)
|
| 423 |
+
print("🏌️♂️ Detected Phase Ranges:", phase_ranges_iron_reference)
|
| 424 |
+
|
| 425 |
+
phase_ranges_driver_reference, swing_start, swing_end, wrist_y, smoothed = detect_swing_phases(frame_data_driver_reference)
|
| 426 |
+
print("🏌️♂️ Detected Phase Ranges:", phase_ranges_driver_reference)
|
| 427 |
+
|
| 428 |
+
# ### 🧑🎓📹 Pro vs Student Swing Comparison by Phase (with Pose Overlay)
|
| 429 |
+
#
|
| 430 |
+
# The `compare_swing_phases()` function visually compares each swing phase between a **student video** and a **pro reference video**, displaying side-by-side frames (optionally with pose landmarks).
|
| 431 |
+
#
|
| 432 |
+
# #### 📦 Inputs:
|
| 433 |
+
# - `student_video_path`, `pro_video_path`: Paths to fixed videos (with silent audio).
|
| 434 |
+
# - `student_phases`, `pro_phases`: Dicts of frame ranges per phase (from `detect_swing_phases()`).
|
| 435 |
+
# - `show_pose`: If `True`, overlays pose landmarks using MediaPipe.
|
| 436 |
+
#
|
| 437 |
+
# #### 🧠 Core Logic:
|
| 438 |
+
# - For each swing phase (e.g., `"Address"`, `"Impact"`):
|
| 439 |
+
# - Finds the middle frame of that phase for both student and pro.
|
| 440 |
+
# - Extracts and optionally annotates frames using MediaPipe Pose.
|
| 441 |
+
# - Converts BGR → RGB for display compatibility.
|
| 442 |
+
#
|
| 443 |
+
# #### 🎨 Output:
|
| 444 |
+
# - A multi-row Matplotlib figure with:
|
| 445 |
+
# - Left: Student frame for each phase.
|
| 446 |
+
# - Right: Pro frame for the same phase.
|
| 447 |
+
# - Optional pose overlay to help analyze alignment, posture, and joint positioning.
|
| 448 |
+
#
|
| 449 |
+
# #### 🧹 Cleanup:
|
| 450 |
+
# - Releases video capture resources and closes the MediaPipe model.
|
| 451 |
+
#
|
| 452 |
+
# ✅ Use this for **visual feedback and coaching**, making swing differences easy to spot phase-by-phase.
|
| 453 |
+
#
|
| 454 |
+
|
| 455 |
+
|
| 456 |
+
|
| 457 |
+
|
| 458 |
+
def compare_swing_phases(
|
| 459 |
+
student_video_path, student_phases,
|
| 460 |
+
pro_video_path, pro_phases,
|
| 461 |
+
show_pose=True
|
| 462 |
+
):
|
| 463 |
+
mp_pose = mp.solutions.pose
|
| 464 |
+
pose = mp_pose.Pose(static_image_mode=True)
|
| 465 |
+
mp_drawing = mp.solutions.drawing_utils
|
| 466 |
+
mp_style = mp.solutions.drawing_styles
|
| 467 |
+
|
| 468 |
+
def get_frame(cap, frame_idx, apply_pose=False):
|
| 469 |
+
cap.set(cv2.CAP_PROP_POS_FRAMES, frame_idx)
|
| 470 |
+
ret, frame = cap.read()
|
| 471 |
+
if not ret:
|
| 472 |
+
raise ValueError(f"❌ Failed to read frame {frame_idx}")
|
| 473 |
+
if apply_pose:
|
| 474 |
+
rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
| 475 |
+
results = pose.process(rgb)
|
| 476 |
+
if results.pose_landmarks:
|
| 477 |
+
mp_drawing.draw_landmarks(
|
| 478 |
+
frame,
|
| 479 |
+
results.pose_landmarks,
|
| 480 |
+
mp_pose.POSE_CONNECTIONS,
|
| 481 |
+
landmark_drawing_spec=mp_style.get_default_pose_landmarks_style()
|
| 482 |
+
)
|
| 483 |
+
return frame
|
| 484 |
+
|
| 485 |
+
student_cap = cv2.VideoCapture(student_video_path)
|
| 486 |
+
pro_cap = cv2.VideoCapture(pro_video_path)
|
| 487 |
+
|
| 488 |
+
phase_names = list(student_phases.keys())
|
| 489 |
+
num_phases = len(phase_names)
|
| 490 |
+
|
| 491 |
+
plt.figure(figsize=(16, 6 * num_phases))
|
| 492 |
+
|
| 493 |
+
for i, phase in enumerate(phase_names):
|
| 494 |
+
# === Frame indices ===
|
| 495 |
+
s_start, s_end = student_phases[phase]
|
| 496 |
+
p_start, p_end = pro_phases[phase]
|
| 497 |
+
|
| 498 |
+
s_middle = int((s_start + s_end) // 2)
|
| 499 |
+
p_middle = int((p_start + p_end) // 2)
|
| 500 |
+
|
| 501 |
+
# === Load frames ===
|
| 502 |
+
student_frame = get_frame(student_cap, s_middle, apply_pose=show_pose)
|
| 503 |
+
pro_frame = get_frame(pro_cap, p_middle, apply_pose=show_pose)
|
| 504 |
+
|
| 505 |
+
student_rgb = cv2.cvtColor(student_frame, cv2.COLOR_BGR2RGB)
|
| 506 |
+
pro_rgb = cv2.cvtColor(pro_frame, cv2.COLOR_BGR2RGB)
|
| 507 |
+
|
| 508 |
+
# === Plot ===
|
| 509 |
+
plt.subplot(num_phases, 2, 2*i+1)
|
| 510 |
+
plt.imshow(student_rgb)
|
| 511 |
+
plt.title(f"Student - {phase}")
|
| 512 |
+
plt.axis("off")
|
| 513 |
+
|
| 514 |
+
plt.subplot(num_phases, 2, 2*i+2)
|
| 515 |
+
plt.imshow(pro_rgb)
|
| 516 |
+
plt.title(f"Pro - {phase}")
|
| 517 |
+
plt.axis("off")
|
| 518 |
+
|
| 519 |
+
plt.tight_layout()
|
| 520 |
+
plt.show()
|
| 521 |
+
|
| 522 |
+
student_cap.release()
|
| 523 |
+
pro_cap.release()
|
| 524 |
+
pose.close()
|
| 525 |
+
|
| 526 |
+
|
| 527 |
+
compare_swing_phases(
|
| 528 |
+
student_video_path=video_iron_fixed,
|
| 529 |
+
student_phases=phase_ranges_iron,
|
| 530 |
+
pro_video_path=iron_reference_fixed,
|
| 531 |
+
pro_phases=phase_ranges_iron_reference,
|
| 532 |
+
show_pose=True # Set to False to skip pose overlay
|
| 533 |
+
)
|
| 534 |
+
|
| 535 |
+
|
| 536 |
+
compare_swing_phases(
|
| 537 |
+
student_video_path=video_driver_fixed,
|
| 538 |
+
student_phases=phase_ranges_driver,
|
| 539 |
+
pro_video_path=driver_reference_fixed,
|
| 540 |
+
pro_phases=phase_ranges_driver_reference,
|
| 541 |
+
show_pose=True # Set to False to skip pose overlay
|
| 542 |
+
)
|
| 543 |
+
|
| 544 |
+
|
| 545 |
+
# ### 🎥 Generate Annotated Debug Video with Swing Overlay and Slow Motion
|
| 546 |
+
#
|
| 547 |
+
# This function `generate_debug_video_with_overlay()` creates a side-by-side **video+plot debug visualization**, showing real-time wrist motion trajectory alongside the actual video frames.
|
| 548 |
+
#
|
| 549 |
+
# ---
|
| 550 |
+
#
|
| 551 |
+
# #### 🔁 Step-by-Step Workflow:
|
| 552 |
+
#
|
| 553 |
+
# - **Frame-by-Frame Rendering**:
|
| 554 |
+
# - Reads each frame from the input video.
|
| 555 |
+
# - Overlays a Matplotlib plot of smoothed wrist Y-position (`smoothed`), marks current frame, swing start/end, and displays swing phase label (via `get_swing_phase_label()`).
|
| 556 |
+
#
|
| 557 |
+
# - **Combined Output**:
|
| 558 |
+
# - Horizontally stacks video frame + debug plot.
|
| 559 |
+
# - Writes to an MP4 video using OpenCV (`cv2.VideoWriter`).
|
| 560 |
+
#
|
| 561 |
+
# - **Plot Details**:
|
| 562 |
+
# - Flipped Y-axis for intuitive visualization.
|
| 563 |
+
# - Clear phase zones (`Address`, `Backswing`, etc.) shown with labels and color spans.
|
| 564 |
+
#
|
| 565 |
+
# ---
|
| 566 |
+
#
|
| 567 |
+
# #### 🐢 Slow-Mo Re-encoding:
|
| 568 |
+
# - After video is saved, re-encodes it using **FFmpeg** to:
|
| 569 |
+
# - Insert a slow-motion segment during the swing window (`swing_start` → `swing_end`).
|
| 570 |
+
# - Concatenate trimmed clips before, during (slowed), and after the swing.
|
| 571 |
+
# - Save to a more compatible format (`*_playable.mp4`).
|
| 572 |
+
#
|
| 573 |
+
# ---
|
| 574 |
+
#
|
| 575 |
+
# #### 📤 Returns:
|
| 576 |
+
# - A Colab-embedded video (`IPython.display.Video`) showing:
|
| 577 |
+
# - Original clip + live tracking plot.
|
| 578 |
+
# - Frame-wise swing phase.
|
| 579 |
+
# - Smooth debug overlay and swing window.
|
| 580 |
+
#
|
| 581 |
+
# 🎯 Perfect for **visual diagnostics**, **student feedback**, and **explaining biomechanics** with frame-accurate debug context.
|
| 582 |
+
#
|
| 583 |
+
|
| 584 |
+
|
| 585 |
+
|
| 586 |
+
# Get swing phase label for a given frame index
|
| 587 |
+
def get_swing_phase_label(frame_idx, phase_ranges):
|
| 588 |
+
for label, (start, end) in phase_ranges.items():
|
| 589 |
+
if start <= frame_idx <= end:
|
| 590 |
+
return label
|
| 591 |
+
return None
|
| 592 |
+
|
| 593 |
+
def generate_debug_video_with_overlay(
|
| 594 |
+
video_filename: str,
|
| 595 |
+
output_path: str,
|
| 596 |
+
wrist_y: list,
|
| 597 |
+
smoothed: list,
|
| 598 |
+
phase_ranges: dict,
|
| 599 |
+
swing_start: int,
|
| 600 |
+
swing_end: int
|
| 601 |
+
):
|
| 602 |
+
import gc
|
| 603 |
+
import cv2
|
| 604 |
+
import numpy as np
|
| 605 |
+
import matplotlib.pyplot as plt
|
| 606 |
+
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
|
| 607 |
+
from matplotlib import use as mpl_use
|
| 608 |
+
mpl_use("Agg") # ✅ For headless backend in Colab
|
| 609 |
+
|
| 610 |
+
cap = cv2.VideoCapture(video_filename)
|
| 611 |
+
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
|
| 612 |
+
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
|
| 613 |
+
total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
|
| 614 |
+
fps = cap.get(cv2.CAP_PROP_FPS)
|
| 615 |
+
|
| 616 |
+
print(f"📹 Frame resolution: {width}x{height}, FPS: {fps:.2f}, Total frames: {total_frames}")
|
| 617 |
+
|
| 618 |
+
plot_width = int(width * 2.0)
|
| 619 |
+
output_size = (width + plot_width, height)
|
| 620 |
+
|
| 621 |
+
# ✅ Use mp4v codec for writing temporary mp4
|
| 622 |
+
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
|
| 623 |
+
out = cv2.VideoWriter(output_path, fourcc, fps, output_size)
|
| 624 |
+
|
| 625 |
+
fig, ax = plt.subplots(figsize=(plot_width / 100.0, height / 100.0), dpi=100)
|
| 626 |
+
canvas = FigureCanvas(fig)
|
| 627 |
+
|
| 628 |
+
cap.set(cv2.CAP_PROP_POS_FRAMES, 0)
|
| 629 |
+
frame_idx = 0
|
| 630 |
+
print("🔄 Rendering video with overlaid debug plots...")
|
| 631 |
+
|
| 632 |
+
while cap.isOpened():
|
| 633 |
+
ret, frame = cap.read()
|
| 634 |
+
if not ret or frame is None:
|
| 635 |
+
break
|
| 636 |
+
|
| 637 |
+
if frame_idx >= len(wrist_y):
|
| 638 |
+
print(f"📌 Reached end of trajectory data at frame {frame_idx}.")
|
| 639 |
+
break
|
| 640 |
+
|
| 641 |
+
try:
|
| 642 |
+
ax.clear()
|
| 643 |
+
ax.plot(smoothed, label="Smoothed Wrist Y", linestyle='--', color='blue')
|
| 644 |
+
ax.axvline(frame_idx, color='black', linestyle='-', label="Current Frame")
|
| 645 |
+
|
| 646 |
+
# ✅ Phase label helper (you must define or import this)
|
| 647 |
+
phase_label = get_swing_phase_label(frame_idx, phase_ranges)
|
| 648 |
+
if phase_label:
|
| 649 |
+
ax.text(0.02, 0.95, phase_label, transform=ax.transAxes,
|
| 650 |
+
fontsize=18, color='black', fontweight='bold',
|
| 651 |
+
verticalalignment='top', horizontalalignment='left',
|
| 652 |
+
bbox=dict(facecolor='white', alpha=0.7, boxstyle='round'))
|
| 653 |
+
|
| 654 |
+
ax.axvspan(swing_start, swing_end, color='green', alpha=0.2, label="Swing Window")
|
| 655 |
+
|
| 656 |
+
ax.set_title(f"Debug Plot (Frame {frame_idx})", fontsize=20)
|
| 657 |
+
ax.set_xlabel("Frame", fontsize=16)
|
| 658 |
+
ax.set_ylabel("Wrist Y Position", fontsize=16)
|
| 659 |
+
ax.set_xlim(0, len(wrist_y))
|
| 660 |
+
ax.set_ylim(np.nanmax(wrist_y) + 10, np.nanmin(wrist_y) - 10)
|
| 661 |
+
ax.legend(fontsize=14)
|
| 662 |
+
fig.tight_layout()
|
| 663 |
+
canvas.draw()
|
| 664 |
+
|
| 665 |
+
plot_img = np.frombuffer(canvas.buffer_rgba(), dtype=np.uint8).reshape(
|
| 666 |
+
canvas.get_width_height()[1], canvas.get_width_height()[0], 4
|
| 667 |
+
)[..., :3]
|
| 668 |
+
|
| 669 |
+
plot_img = cv2.resize(plot_img, (plot_width, height))
|
| 670 |
+
frame = cv2.resize(frame, (width, height))
|
| 671 |
+
combined_frame = np.hstack((frame, plot_img))
|
| 672 |
+
out.write(combined_frame)
|
| 673 |
+
|
| 674 |
+
if frame_idx % 50 == 0:
|
| 675 |
+
print(f"✅ Processed frame {frame_idx}/{total_frames}")
|
| 676 |
+
|
| 677 |
+
frame_idx += 1
|
| 678 |
+
gc.collect()
|
| 679 |
+
|
| 680 |
+
except Exception as e:
|
| 681 |
+
print(f"❌ Error at frame {frame_idx}: {e}")
|
| 682 |
+
break
|
| 683 |
+
|
| 684 |
+
cap.release()
|
| 685 |
+
out.release()
|
| 686 |
+
print(f"✅ Debug video saved as {output_path}")
|
| 687 |
+
|
| 688 |
+
# === Re-encode with FFmpeg ===
|
| 689 |
+
reencoded_path = output_path.replace(".mp4", "_playable.mp4")
|
| 690 |
+
|
| 691 |
+
# Convert swing frame indices to seconds
|
| 692 |
+
start_time = swing_start / fps
|
| 693 |
+
end_time = swing_end / fps
|
| 694 |
+
slow_factor = 2.0 # Adjust this factor as needed
|
| 695 |
+
|
| 696 |
+
# FFmpeg slow-motion filter logic
|
| 697 |
+
filter_complex = (
|
| 698 |
+
f"[0:v]trim=0:{start_time:.3f},setpts=PTS-STARTPTS[v1];"
|
| 699 |
+
f"[0:v]trim={start_time:.3f}:{end_time:.3f},setpts={slow_factor}*(PTS-STARTPTS)[v2];"
|
| 700 |
+
f"[0:v]trim={end_time:.3f},setpts=PTS-STARTPTS[v3];"
|
| 701 |
+
f"[v1][v2][v3]concat=n=3:v=1:a=0[outv]"
|
| 702 |
+
)
|
| 703 |
+
|
| 704 |
+
cmd = [
|
| 705 |
+
"ffmpeg", "-y", "-i", output_path,
|
| 706 |
+
"-filter_complex", filter_complex,
|
| 707 |
+
"-map", "[outv]",
|
| 708 |
+
"-vcodec", "libx264", "-crf", "23", "-preset", "veryfast",
|
| 709 |
+
"-pix_fmt", "yuv420p",
|
| 710 |
+
reencoded_path
|
| 711 |
+
]
|
| 712 |
+
|
| 713 |
+
print("🎬 Re-encoding with slow-motion for Colab compatibility...")
|
| 714 |
+
subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
| 715 |
+
|
| 716 |
+
|
| 717 |
+
# Optional: give disk a moment to flush
|
| 718 |
+
time.sleep(1)
|
| 719 |
+
|
| 720 |
+
return Video(reencoded_path, embed=True, width=960)
|
| 721 |
+
|
| 722 |
+
|
| 723 |
+
debug_video = generate_debug_video_with_overlay(video_iron_fixed, "iron_debug.mp4", wrist_y_iron, smoothed_iron, phase_ranges_iron, swing_start_iron, swing_end_iron)
|
| 724 |
+
|
| 725 |
+
debug_video
|
| 726 |
+
|
| 727 |
+
|
| 728 |
+
debug_video = generate_debug_video_with_overlay(video_driver_fixed, "iron_debug.mp4", wrist_y_driver, smoothed_driver, phase_ranges_driver, swing_start_driver, swing_end_driver)
|
| 729 |
+
|
| 730 |
+
debug_video
|
extract.py
CHANGED
|
@@ -33,18 +33,15 @@ def run_ai_extraction(video_path, slow_factor=1.0, output_dir=None, skip_slow_vi
|
|
| 33 |
video_name = os.path.basename(video_path)
|
| 34 |
video_prefix = os.path.splitext(video_name)[0]
|
| 35 |
|
| 36 |
-
# Nếu không có output_dir, dùng mặc định
|
| 37 |
if output_dir is None:
|
| 38 |
output_dir = os.path.join('output', video_prefix)
|
| 39 |
|
| 40 |
model_path = 'models/swingnet_1800.pth.tar'
|
| 41 |
phases_dir = os.path.join(output_dir, 'phases')
|
| 42 |
|
| 43 |
-
# Thêm số thứ tự để đảm bảo sắp xếp đúng trong thư mục
|
| 44 |
labels = ['1_Address', '2_Toe-up', '3_Mid-Backswing', '4_Top',
|
| 45 |
'5_Mid-Downswing', '6_Impact', '7_Mid-Follow-Through', '8_Finish']
|
| 46 |
|
| 47 |
-
# Chỉ tạo thư mục phases nếu cần lưu ảnh
|
| 48 |
if not skip_phase_images:
|
| 49 |
for label in labels:
|
| 50 |
os.makedirs(os.path.join(phases_dir, label), exist_ok=True)
|
|
@@ -74,7 +71,7 @@ def run_ai_extraction(video_path, slow_factor=1.0, output_dir=None, skip_slow_vi
|
|
| 74 |
print("Không tìm thấy frame nào.")
|
| 75 |
return
|
| 76 |
|
| 77 |
-
# Frame Interpolation
|
| 78 |
if slow_factor < 1.0:
|
| 79 |
if not production:
|
| 80 |
print(f"Đang nội suy frame (Slow-mo {slow_factor}x)...")
|
|
@@ -115,13 +112,20 @@ def run_ai_extraction(video_path, slow_factor=1.0, output_dir=None, skip_slow_vi
|
|
| 115 |
else:
|
| 116 |
full_res_frames = raw_frames
|
| 117 |
|
| 118 |
-
# Tiền xử lý cho AI
|
| 119 |
if not production:
|
| 120 |
print("Đang tiền xử lý cho AI...")
|
| 121 |
images = []
|
| 122 |
input_size = 160
|
| 123 |
for img in tqdm(full_res_frames, disable=production):
|
| 124 |
h, w = img.shape[:2]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 125 |
ratio = input_size / max(h, w)
|
| 126 |
new_size = (int(w * ratio), int(h * ratio))
|
| 127 |
resized = cv2.resize(img, new_size)
|
|
@@ -145,15 +149,11 @@ def run_ai_extraction(video_path, slow_factor=1.0, output_dir=None, skip_slow_vi
|
|
| 145 |
logits_concat = np.concatenate(all_logits, axis=0)
|
| 146 |
probs = F.softmax(torch.tensor(logits_concat), dim=1).numpy()
|
| 147 |
|
| 148 |
-
# Làm mượt kết quả để giảm nhiễu (đặc biệt cho DTL)
|
| 149 |
probs = smooth_probs(probs, window_size=5)
|
| 150 |
|
| 151 |
-
# Áp dụng thuật toán Anchor-based Bidirectional Search
|
| 152 |
-
# 1. Tìm sự kiện "Neo" (Anchor) đáng tin cậy nhất (thường là Impact hoặc Top)
|
| 153 |
-
# Chỉ xét 8 lớp sự kiện đầu tiên, bỏ qua lớp số 9 (No Event/Background)
|
| 154 |
probs_events = probs[:, :8]
|
| 155 |
-
max_probs = np.max(probs_events, axis=0)
|
| 156 |
-
anchor_class = np.argmax(max_probs)
|
| 157 |
anchor_frame = np.argmax(probs_events[:, anchor_class])
|
| 158 |
|
| 159 |
if not production:
|
|
@@ -162,11 +162,9 @@ def run_ai_extraction(video_path, slow_factor=1.0, output_dir=None, skip_slow_vi
|
|
| 162 |
events = np.zeros(8, dtype=int)
|
| 163 |
events[anchor_class] = anchor_frame
|
| 164 |
|
| 165 |
-
# 2. Đi lùi: Tìm các pha trước Anchor
|
| 166 |
current_limit = anchor_frame
|
| 167 |
for i in range(anchor_class - 1, -1, -1):
|
| 168 |
if current_limit > 0:
|
| 169 |
-
# Tìm max trong vùng cho phép [0, current_limit]
|
| 170 |
segment = probs[0:current_limit, i]
|
| 171 |
if len(segment) > 0:
|
| 172 |
events[i] = np.argmax(segment)
|
|
@@ -176,12 +174,11 @@ def run_ai_extraction(video_path, slow_factor=1.0, output_dir=None, skip_slow_vi
|
|
| 176 |
events[i] = 0
|
| 177 |
current_limit = events[i]
|
| 178 |
|
| 179 |
-
# 3. Đi tiến: Tìm các pha sau Anchor
|
| 180 |
current_limit = anchor_frame
|
| 181 |
total_frames = probs.shape[0]
|
| 182 |
for i in range(anchor_class + 1, 8):
|
| 183 |
if current_limit < total_frames - 1:
|
| 184 |
-
|
| 185 |
# Bắt buộc tiến ít nhất 1 frame
|
| 186 |
segment = probs[current_limit + 1:, i]
|
| 187 |
if len(segment) > 0:
|
|
@@ -195,11 +192,9 @@ def run_ai_extraction(video_path, slow_factor=1.0, output_dir=None, skip_slow_vi
|
|
| 195 |
if not production:
|
| 196 |
print(f"Detected Events (Frames): {events}")
|
| 197 |
|
| 198 |
-
# Lưu thông tin frame index để visual_report sử dụng
|
| 199 |
event_metadata = {}
|
| 200 |
for i, frame_idx in enumerate(events):
|
| 201 |
if frame_idx < len(full_res_frames):
|
| 202 |
-
# Chỉ lưu ảnh nếu không skip
|
| 203 |
if not skip_phase_images:
|
| 204 |
cv2.imwrite(os.path.join(phases_dir, labels[i], f"{video_prefix}.jpg"), full_res_frames[frame_idx])
|
| 205 |
event_metadata[labels[i]] = int(frame_idx)
|
|
|
|
| 33 |
video_name = os.path.basename(video_path)
|
| 34 |
video_prefix = os.path.splitext(video_name)[0]
|
| 35 |
|
|
|
|
| 36 |
if output_dir is None:
|
| 37 |
output_dir = os.path.join('output', video_prefix)
|
| 38 |
|
| 39 |
model_path = 'models/swingnet_1800.pth.tar'
|
| 40 |
phases_dir = os.path.join(output_dir, 'phases')
|
| 41 |
|
|
|
|
| 42 |
labels = ['1_Address', '2_Toe-up', '3_Mid-Backswing', '4_Top',
|
| 43 |
'5_Mid-Downswing', '6_Impact', '7_Mid-Follow-Through', '8_Finish']
|
| 44 |
|
|
|
|
| 45 |
if not skip_phase_images:
|
| 46 |
for label in labels:
|
| 47 |
os.makedirs(os.path.join(phases_dir, label), exist_ok=True)
|
|
|
|
| 71 |
print("Không tìm thấy frame nào.")
|
| 72 |
return
|
| 73 |
|
| 74 |
+
# Frame Interpolation
|
| 75 |
if slow_factor < 1.0:
|
| 76 |
if not production:
|
| 77 |
print(f"Đang nội suy frame (Slow-mo {slow_factor}x)...")
|
|
|
|
| 112 |
else:
|
| 113 |
full_res_frames = raw_frames
|
| 114 |
|
|
|
|
| 115 |
if not production:
|
| 116 |
print("Đang tiền xử lý cho AI...")
|
| 117 |
images = []
|
| 118 |
input_size = 160
|
| 119 |
for img in tqdm(full_res_frames, disable=production):
|
| 120 |
h, w = img.shape[:2]
|
| 121 |
+
if h > w:
|
| 122 |
+
center_y = h // 2
|
| 123 |
+
half_w = w // 2
|
| 124 |
+
start_y = max(0, center_y - half_w)
|
| 125 |
+
end_y = min(h, center_y + half_w)
|
| 126 |
+
img = img[start_y:end_y, :]
|
| 127 |
+
h, w = img.shape[:2]
|
| 128 |
+
|
| 129 |
ratio = input_size / max(h, w)
|
| 130 |
new_size = (int(w * ratio), int(h * ratio))
|
| 131 |
resized = cv2.resize(img, new_size)
|
|
|
|
| 149 |
logits_concat = np.concatenate(all_logits, axis=0)
|
| 150 |
probs = F.softmax(torch.tensor(logits_concat), dim=1).numpy()
|
| 151 |
|
|
|
|
| 152 |
probs = smooth_probs(probs, window_size=5)
|
| 153 |
|
|
|
|
|
|
|
|
|
|
| 154 |
probs_events = probs[:, :8]
|
| 155 |
+
max_probs = np.max(probs_events, axis=0)
|
| 156 |
+
anchor_class = np.argmax(max_probs)
|
| 157 |
anchor_frame = np.argmax(probs_events[:, anchor_class])
|
| 158 |
|
| 159 |
if not production:
|
|
|
|
| 162 |
events = np.zeros(8, dtype=int)
|
| 163 |
events[anchor_class] = anchor_frame
|
| 164 |
|
|
|
|
| 165 |
current_limit = anchor_frame
|
| 166 |
for i in range(anchor_class - 1, -1, -1):
|
| 167 |
if current_limit > 0:
|
|
|
|
| 168 |
segment = probs[0:current_limit, i]
|
| 169 |
if len(segment) > 0:
|
| 170 |
events[i] = np.argmax(segment)
|
|
|
|
| 174 |
events[i] = 0
|
| 175 |
current_limit = events[i]
|
| 176 |
|
|
|
|
| 177 |
current_limit = anchor_frame
|
| 178 |
total_frames = probs.shape[0]
|
| 179 |
for i in range(anchor_class + 1, 8):
|
| 180 |
if current_limit < total_frames - 1:
|
| 181 |
+
segment = probs[current_limit + 1:, i]
|
| 182 |
# Bắt buộc tiến ít nhất 1 frame
|
| 183 |
segment = probs[current_limit + 1:, i]
|
| 184 |
if len(segment) > 0:
|
|
|
|
| 192 |
if not production:
|
| 193 |
print(f"Detected Events (Frames): {events}")
|
| 194 |
|
|
|
|
| 195 |
event_metadata = {}
|
| 196 |
for i, frame_idx in enumerate(events):
|
| 197 |
if frame_idx < len(full_res_frames):
|
|
|
|
| 198 |
if not skip_phase_images:
|
| 199 |
cv2.imwrite(os.path.join(phases_dir, labels[i], f"{video_prefix}.jpg"), full_res_frames[frame_idx])
|
| 200 |
event_metadata[labels[i]] = int(frame_idx)
|
hf_api_result.json → golf_analysis.json
RENAMED
|
@@ -1,300 +1,300 @@
|
|
| 1 |
{
|
| 2 |
"status": "success",
|
| 3 |
-
"job_id": "
|
| 4 |
"metadata": {
|
| 5 |
"event_frames": {
|
| 6 |
-
"1_Address":
|
| 7 |
-
"2_Toe-up":
|
| 8 |
-
"3_Mid-Backswing":
|
| 9 |
-
"4_Top":
|
| 10 |
-
"5_Mid-Downswing":
|
| 11 |
-
"6_Impact":
|
| 12 |
-
"7_Mid-Follow-Through":
|
| 13 |
-
"8_Finish":
|
| 14 |
},
|
| 15 |
-
"slow_factor": 1
|
| 16 |
-
"fps":
|
| 17 |
},
|
| 18 |
"analysis": {
|
| 19 |
-
"video_id": "
|
| 20 |
"phases": {
|
| 21 |
"1_Address": {
|
| 22 |
-
"score":
|
| 23 |
"comments": [
|
| 24 |
-
"
|
| 25 |
],
|
| 26 |
"data": {
|
| 27 |
-
"stance_ratio": 1.
|
| 28 |
},
|
| 29 |
"raw_landmarks": [
|
| 30 |
{
|
| 31 |
"id": 0,
|
| 32 |
"name": "NOSE",
|
| 33 |
-
"x": 0.
|
| 34 |
-
"y": 0.
|
| 35 |
-
"z": -0.
|
| 36 |
-
"visibility":
|
| 37 |
},
|
| 38 |
{
|
| 39 |
"id": 1,
|
| 40 |
"name": "LEFT_EYE_INNER",
|
| 41 |
-
"x": 0.
|
| 42 |
-
"y": 0.
|
| 43 |
-
"z": -0.
|
| 44 |
-
"visibility":
|
| 45 |
},
|
| 46 |
{
|
| 47 |
"id": 2,
|
| 48 |
"name": "LEFT_EYE",
|
| 49 |
-
"x": 0.
|
| 50 |
-
"y": 0.
|
| 51 |
-
"z": -0.
|
| 52 |
-
"visibility": 0.
|
| 53 |
},
|
| 54 |
{
|
| 55 |
"id": 3,
|
| 56 |
"name": "LEFT_EYE_OUTER",
|
| 57 |
-
"x": 0.
|
| 58 |
-
"y": 0.
|
| 59 |
-
"z": -0.
|
| 60 |
-
"visibility": 0.
|
| 61 |
},
|
| 62 |
{
|
| 63 |
"id": 4,
|
| 64 |
"name": "RIGHT_EYE_INNER",
|
| 65 |
-
"x": 0.
|
| 66 |
-
"y": 0.
|
| 67 |
-
"z": -0.
|
| 68 |
-
"visibility":
|
| 69 |
},
|
| 70 |
{
|
| 71 |
"id": 5,
|
| 72 |
"name": "RIGHT_EYE",
|
| 73 |
-
"x": 0.
|
| 74 |
-
"y": 0.
|
| 75 |
-
"z": -0.
|
| 76 |
-
"visibility":
|
| 77 |
},
|
| 78 |
{
|
| 79 |
"id": 6,
|
| 80 |
"name": "RIGHT_EYE_OUTER",
|
| 81 |
-
"x": 0.
|
| 82 |
-
"y": 0.
|
| 83 |
-
"z": -0.
|
| 84 |
-
"visibility":
|
| 85 |
},
|
| 86 |
{
|
| 87 |
"id": 7,
|
| 88 |
"name": "LEFT_EAR",
|
| 89 |
-
"x": 0.
|
| 90 |
-
"y": 0.
|
| 91 |
-
"z": -0.
|
| 92 |
-
"visibility": 0.
|
| 93 |
},
|
| 94 |
{
|
| 95 |
"id": 8,
|
| 96 |
"name": "RIGHT_EAR",
|
| 97 |
-
"x": 0.
|
| 98 |
-
"y": 0.
|
| 99 |
-
"z": -0.
|
| 100 |
-
"visibility":
|
| 101 |
},
|
| 102 |
{
|
| 103 |
"id": 9,
|
| 104 |
"name": "MOUTH_LEFT",
|
| 105 |
-
"x": 0.
|
| 106 |
-
"y": 0.
|
| 107 |
-
"z": -0.
|
| 108 |
-
"visibility":
|
| 109 |
},
|
| 110 |
{
|
| 111 |
"id": 10,
|
| 112 |
"name": "MOUTH_RIGHT",
|
| 113 |
-
"x": 0.
|
| 114 |
-
"y": 0.
|
| 115 |
-
"z": -0.
|
| 116 |
-
"visibility":
|
| 117 |
},
|
| 118 |
{
|
| 119 |
"id": 11,
|
| 120 |
"name": "LEFT_SHOULDER",
|
| 121 |
-
"x": 0.
|
| 122 |
-
"y": 0.
|
| 123 |
-
"z": -0.
|
| 124 |
-
"visibility":
|
| 125 |
},
|
| 126 |
{
|
| 127 |
"id": 12,
|
| 128 |
"name": "RIGHT_SHOULDER",
|
| 129 |
-
"x": 0.
|
| 130 |
-
"y": 0.
|
| 131 |
-
"z": -0.
|
| 132 |
-
"visibility":
|
| 133 |
},
|
| 134 |
{
|
| 135 |
"id": 13,
|
| 136 |
"name": "LEFT_ELBOW",
|
| 137 |
-
"x": 0.
|
| 138 |
-
"y": 0.
|
| 139 |
-
"z": -0.
|
| 140 |
-
"visibility": 0.
|
| 141 |
},
|
| 142 |
{
|
| 143 |
"id": 14,
|
| 144 |
"name": "RIGHT_ELBOW",
|
| 145 |
-
"x": 0.
|
| 146 |
-
"y": 0.
|
| 147 |
-
"z": -0.
|
| 148 |
-
"visibility": 0.
|
| 149 |
},
|
| 150 |
{
|
| 151 |
"id": 15,
|
| 152 |
"name": "LEFT_WRIST",
|
| 153 |
-
"x": 0.
|
| 154 |
-
"y": 0.
|
| 155 |
-
"z": -0.
|
| 156 |
-
"visibility": 0.
|
| 157 |
},
|
| 158 |
{
|
| 159 |
"id": 16,
|
| 160 |
"name": "RIGHT_WRIST",
|
| 161 |
-
"x": 0.
|
| 162 |
-
"y": 0.
|
| 163 |
-
"z": -0.
|
| 164 |
-
"visibility": 0.
|
| 165 |
},
|
| 166 |
{
|
| 167 |
"id": 17,
|
| 168 |
"name": "LEFT_PINKY",
|
| 169 |
-
"x": 0.
|
| 170 |
-
"y": 0.
|
| 171 |
-
"z": -0.
|
| 172 |
-
"visibility": 0.
|
| 173 |
},
|
| 174 |
{
|
| 175 |
"id": 18,
|
| 176 |
"name": "RIGHT_PINKY",
|
| 177 |
-
"x": 0.
|
| 178 |
-
"y": 0.
|
| 179 |
-
"z": -0.
|
| 180 |
-
"visibility": 0.
|
| 181 |
},
|
| 182 |
{
|
| 183 |
"id": 19,
|
| 184 |
"name": "LEFT_INDEX",
|
| 185 |
-
"x": 0.
|
| 186 |
-
"y": 0.
|
| 187 |
-
"z": -0.
|
| 188 |
-
"visibility": 0.
|
| 189 |
},
|
| 190 |
{
|
| 191 |
"id": 20,
|
| 192 |
"name": "RIGHT_INDEX",
|
| 193 |
-
"x": 0.
|
| 194 |
-
"y": 0.
|
| 195 |
-
"z": -0.
|
| 196 |
-
"visibility": 0.
|
| 197 |
},
|
| 198 |
{
|
| 199 |
"id": 21,
|
| 200 |
"name": "LEFT_THUMB",
|
| 201 |
-
"x": 0.
|
| 202 |
-
"y": 0.
|
| 203 |
-
"z": -0.
|
| 204 |
-
"visibility": 0.
|
| 205 |
},
|
| 206 |
{
|
| 207 |
"id": 22,
|
| 208 |
"name": "RIGHT_THUMB",
|
| 209 |
-
"x": 0.
|
| 210 |
-
"y": 0.
|
| 211 |
-
"z": -0.
|
| 212 |
-
"visibility": 0.
|
| 213 |
},
|
| 214 |
{
|
| 215 |
"id": 23,
|
| 216 |
"name": "LEFT_HIP",
|
| 217 |
-
"x": 0.
|
| 218 |
-
"y": 0.
|
| 219 |
-
"z": -0.
|
| 220 |
-
"visibility":
|
| 221 |
},
|
| 222 |
{
|
| 223 |
"id": 24,
|
| 224 |
"name": "RIGHT_HIP",
|
| 225 |
-
"x": 0.
|
| 226 |
-
"y": 0.
|
| 227 |
-
"z": 0.
|
| 228 |
-
"visibility":
|
| 229 |
},
|
| 230 |
{
|
| 231 |
"id": 25,
|
| 232 |
"name": "LEFT_KNEE",
|
| 233 |
-
"x": 0.
|
| 234 |
-
"y": 0.
|
| 235 |
-
"z": -0.
|
| 236 |
-
"visibility": 0.
|
| 237 |
},
|
| 238 |
{
|
| 239 |
"id": 26,
|
| 240 |
"name": "RIGHT_KNEE",
|
| 241 |
-
"x": 0.
|
| 242 |
-
"y": 0.
|
| 243 |
-
"z": -0.
|
| 244 |
-
"visibility": 0.
|
| 245 |
},
|
| 246 |
{
|
| 247 |
"id": 27,
|
| 248 |
"name": "LEFT_ANKLE",
|
| 249 |
-
"x": 0.
|
| 250 |
-
"y": 0.
|
| 251 |
-
"z": 0.
|
| 252 |
-
"visibility": 0.
|
| 253 |
},
|
| 254 |
{
|
| 255 |
"id": 28,
|
| 256 |
"name": "RIGHT_ANKLE",
|
| 257 |
-
"x": 0.
|
| 258 |
-
"y": 0.
|
| 259 |
-
"z": 0.
|
| 260 |
-
"visibility": 0.
|
| 261 |
},
|
| 262 |
{
|
| 263 |
"id": 29,
|
| 264 |
"name": "LEFT_HEEL",
|
| 265 |
-
"x": 0.
|
| 266 |
-
"y": 0.
|
| 267 |
-
"z": 0.
|
| 268 |
-
"visibility": 0.
|
| 269 |
},
|
| 270 |
{
|
| 271 |
"id": 30,
|
| 272 |
"name": "RIGHT_HEEL",
|
| 273 |
-
"x": 0.
|
| 274 |
-
"y": 0.
|
| 275 |
-
"z": 0.
|
| 276 |
-
"visibility": 0.
|
| 277 |
},
|
| 278 |
{
|
| 279 |
"id": 31,
|
| 280 |
"name": "LEFT_FOOT_INDEX",
|
| 281 |
-
"x": 0.
|
| 282 |
-
"y": 0.
|
| 283 |
-
"z": -0.
|
| 284 |
-
"visibility": 0.
|
| 285 |
},
|
| 286 |
{
|
| 287 |
"id": 32,
|
| 288 |
"name": "RIGHT_FOOT_INDEX",
|
| 289 |
-
"x": 0.
|
| 290 |
-
"y": 0.
|
| 291 |
-
"z": -0.
|
| 292 |
-
"visibility": 0.
|
| 293 |
}
|
| 294 |
]
|
| 295 |
},
|
| 296 |
"2_Toe-up": {
|
| 297 |
-
"score": 10
|
| 298 |
"comments": [
|
| 299 |
"Đạt chuẩn"
|
| 300 |
],
|
|
@@ -303,271 +303,271 @@
|
|
| 303 |
{
|
| 304 |
"id": 0,
|
| 305 |
"name": "NOSE",
|
| 306 |
-
"x": 0.
|
| 307 |
-
"y": 0.
|
| 308 |
-
"z": -0.
|
| 309 |
-
"visibility":
|
| 310 |
},
|
| 311 |
{
|
| 312 |
"id": 1,
|
| 313 |
"name": "LEFT_EYE_INNER",
|
| 314 |
-
"x": 0.
|
| 315 |
-
"y": 0.
|
| 316 |
-
"z": -0.
|
| 317 |
-
"visibility":
|
| 318 |
},
|
| 319 |
{
|
| 320 |
"id": 2,
|
| 321 |
"name": "LEFT_EYE",
|
| 322 |
-
"x": 0.
|
| 323 |
-
"y": 0.
|
| 324 |
-
"z": -0.
|
| 325 |
-
"visibility": 0.
|
| 326 |
},
|
| 327 |
{
|
| 328 |
"id": 3,
|
| 329 |
"name": "LEFT_EYE_OUTER",
|
| 330 |
-
"x": 0.
|
| 331 |
-
"y": 0.
|
| 332 |
-
"z": -0.
|
| 333 |
-
"visibility": 0.
|
| 334 |
},
|
| 335 |
{
|
| 336 |
"id": 4,
|
| 337 |
"name": "RIGHT_EYE_INNER",
|
| 338 |
-
"x": 0.
|
| 339 |
-
"y": 0.
|
| 340 |
-
"z": -0.
|
| 341 |
-
"visibility":
|
| 342 |
},
|
| 343 |
{
|
| 344 |
"id": 5,
|
| 345 |
"name": "RIGHT_EYE",
|
| 346 |
-
"x": 0.
|
| 347 |
-
"y": 0.
|
| 348 |
-
"z": -0.
|
| 349 |
-
"visibility":
|
| 350 |
},
|
| 351 |
{
|
| 352 |
"id": 6,
|
| 353 |
"name": "RIGHT_EYE_OUTER",
|
| 354 |
-
"x": 0.
|
| 355 |
-
"y": 0.
|
| 356 |
-
"z": -0.
|
| 357 |
-
"visibility":
|
| 358 |
},
|
| 359 |
{
|
| 360 |
"id": 7,
|
| 361 |
"name": "LEFT_EAR",
|
| 362 |
-
"x": 0.
|
| 363 |
-
"y": 0.
|
| 364 |
-
"z": -0.
|
| 365 |
-
"visibility": 0.
|
| 366 |
},
|
| 367 |
{
|
| 368 |
"id": 8,
|
| 369 |
"name": "RIGHT_EAR",
|
| 370 |
-
"x": 0.
|
| 371 |
-
"y": 0.
|
| 372 |
-
"z": -0.
|
| 373 |
-
"visibility":
|
| 374 |
},
|
| 375 |
{
|
| 376 |
"id": 9,
|
| 377 |
"name": "MOUTH_LEFT",
|
| 378 |
-
"x": 0.
|
| 379 |
-
"y": 0.
|
| 380 |
-
"z": -0.
|
| 381 |
-
"visibility":
|
| 382 |
},
|
| 383 |
{
|
| 384 |
"id": 10,
|
| 385 |
"name": "MOUTH_RIGHT",
|
| 386 |
-
"x": 0.
|
| 387 |
-
"y": 0.
|
| 388 |
-
"z": -0.
|
| 389 |
-
"visibility":
|
| 390 |
},
|
| 391 |
{
|
| 392 |
"id": 11,
|
| 393 |
"name": "LEFT_SHOULDER",
|
| 394 |
-
"x": 0.
|
| 395 |
-
"y": 0.
|
| 396 |
-
"z": -0.
|
| 397 |
-
"visibility":
|
| 398 |
},
|
| 399 |
{
|
| 400 |
"id": 12,
|
| 401 |
"name": "RIGHT_SHOULDER",
|
| 402 |
-
"x": 0.
|
| 403 |
-
"y": 0.
|
| 404 |
-
"z": -0.
|
| 405 |
-
"visibility":
|
| 406 |
},
|
| 407 |
{
|
| 408 |
"id": 13,
|
| 409 |
"name": "LEFT_ELBOW",
|
| 410 |
-
"x": 0.
|
| 411 |
-
"y": 0.
|
| 412 |
-
"z": -0.
|
| 413 |
-
"visibility": 0.
|
| 414 |
},
|
| 415 |
{
|
| 416 |
"id": 14,
|
| 417 |
"name": "RIGHT_ELBOW",
|
| 418 |
-
"x": 0.
|
| 419 |
-
"y": 0.
|
| 420 |
-
"z": 0.
|
| 421 |
-
"visibility": 0.
|
| 422 |
},
|
| 423 |
{
|
| 424 |
"id": 15,
|
| 425 |
"name": "LEFT_WRIST",
|
| 426 |
-
"x": 0.
|
| 427 |
-
"y": 0.
|
| 428 |
-
"z": -0.
|
| 429 |
-
"visibility": 0.
|
| 430 |
},
|
| 431 |
{
|
| 432 |
"id": 16,
|
| 433 |
"name": "RIGHT_WRIST",
|
| 434 |
-
"x": 0.
|
| 435 |
-
"y": 0.
|
| 436 |
-
"z": -0.
|
| 437 |
-
"visibility": 0.
|
| 438 |
},
|
| 439 |
{
|
| 440 |
"id": 17,
|
| 441 |
"name": "LEFT_PINKY",
|
| 442 |
-
"x": 0.
|
| 443 |
-
"y": 0.
|
| 444 |
-
"z": -0.
|
| 445 |
-
"visibility": 0.
|
| 446 |
},
|
| 447 |
{
|
| 448 |
"id": 18,
|
| 449 |
"name": "RIGHT_PINKY",
|
| 450 |
-
"x": 0.
|
| 451 |
-
"y": 0.
|
| 452 |
-
"z": -0.
|
| 453 |
-
"visibility": 0.
|
| 454 |
},
|
| 455 |
{
|
| 456 |
"id": 19,
|
| 457 |
"name": "LEFT_INDEX",
|
| 458 |
-
"x": 0.
|
| 459 |
-
"y": 0.
|
| 460 |
-
"z": -0.
|
| 461 |
-
"visibility": 0.
|
| 462 |
},
|
| 463 |
{
|
| 464 |
"id": 20,
|
| 465 |
"name": "RIGHT_INDEX",
|
| 466 |
-
"x": 0.
|
| 467 |
-
"y": 0.
|
| 468 |
-
"z": -0.
|
| 469 |
-
"visibility": 0.
|
| 470 |
},
|
| 471 |
{
|
| 472 |
"id": 21,
|
| 473 |
"name": "LEFT_THUMB",
|
| 474 |
-
"x": 0.
|
| 475 |
-
"y": 0.
|
| 476 |
-
"z": -0.
|
| 477 |
-
"visibility": 0.
|
| 478 |
},
|
| 479 |
{
|
| 480 |
"id": 22,
|
| 481 |
"name": "RIGHT_THUMB",
|
| 482 |
-
"x": 0.
|
| 483 |
-
"y": 0.
|
| 484 |
-
"z": -0.
|
| 485 |
-
"visibility": 0.
|
| 486 |
},
|
| 487 |
{
|
| 488 |
"id": 23,
|
| 489 |
"name": "LEFT_HIP",
|
| 490 |
-
"x": 0.
|
| 491 |
-
"y": 0.
|
| 492 |
-
"z": -0.
|
| 493 |
-
"visibility":
|
| 494 |
},
|
| 495 |
{
|
| 496 |
"id": 24,
|
| 497 |
"name": "RIGHT_HIP",
|
| 498 |
-
"x": 0.
|
| 499 |
-
"y": 0.
|
| 500 |
-
"z": 0.
|
| 501 |
-
"visibility":
|
| 502 |
},
|
| 503 |
{
|
| 504 |
"id": 25,
|
| 505 |
"name": "LEFT_KNEE",
|
| 506 |
-
"x": 0.
|
| 507 |
-
"y": 0.
|
| 508 |
-
"z": -0.
|
| 509 |
-
"visibility": 0.
|
| 510 |
},
|
| 511 |
{
|
| 512 |
"id": 26,
|
| 513 |
"name": "RIGHT_KNEE",
|
| 514 |
-
"x": 0.
|
| 515 |
-
"y": 0.
|
| 516 |
-
"z": 0.
|
| 517 |
-
"visibility": 0.
|
| 518 |
},
|
| 519 |
{
|
| 520 |
"id": 27,
|
| 521 |
"name": "LEFT_ANKLE",
|
| 522 |
-
"x": 0.
|
| 523 |
-
"y": 0.
|
| 524 |
-
"z": 0.
|
| 525 |
-
"visibility": 0.
|
| 526 |
},
|
| 527 |
{
|
| 528 |
"id": 28,
|
| 529 |
"name": "RIGHT_ANKLE",
|
| 530 |
-
"x": 0.
|
| 531 |
-
"y": 0.
|
| 532 |
-
"z": 0.
|
| 533 |
-
"visibility": 0.
|
| 534 |
},
|
| 535 |
{
|
| 536 |
"id": 29,
|
| 537 |
"name": "LEFT_HEEL",
|
| 538 |
-
"x": 0.
|
| 539 |
-
"y": 0.
|
| 540 |
-
"z": 0.
|
| 541 |
-
"visibility": 0.
|
| 542 |
},
|
| 543 |
{
|
| 544 |
"id": 30,
|
| 545 |
"name": "RIGHT_HEEL",
|
| 546 |
-
"x": 0.
|
| 547 |
-
"y": 0.
|
| 548 |
-
"z": 0.
|
| 549 |
-
"visibility": 0.
|
| 550 |
},
|
| 551 |
{
|
| 552 |
"id": 31,
|
| 553 |
"name": "LEFT_FOOT_INDEX",
|
| 554 |
-
"x": 0.
|
| 555 |
-
"y": 0.
|
| 556 |
-
"z": -0.
|
| 557 |
-
"visibility": 0.
|
| 558 |
},
|
| 559 |
{
|
| 560 |
"id": 32,
|
| 561 |
"name": "RIGHT_FOOT_INDEX",
|
| 562 |
-
"x": 0.
|
| 563 |
-
"y": 0.
|
| 564 |
-
"z": 0.
|
| 565 |
-
"visibility": 0.
|
| 566 |
}
|
| 567 |
]
|
| 568 |
},
|
| 569 |
"3_Mid-Backswing": {
|
| 570 |
-
"score": 10
|
| 571 |
"comments": [
|
| 572 |
"Đạt chuẩn"
|
| 573 |
],
|
|
@@ -576,547 +576,547 @@
|
|
| 576 |
{
|
| 577 |
"id": 0,
|
| 578 |
"name": "NOSE",
|
| 579 |
-
"x": 0.
|
| 580 |
-
"y": 0.
|
| 581 |
-
"z": -0.
|
| 582 |
-
"visibility":
|
| 583 |
},
|
| 584 |
{
|
| 585 |
"id": 1,
|
| 586 |
"name": "LEFT_EYE_INNER",
|
| 587 |
-
"x": 0.
|
| 588 |
-
"y": 0.
|
| 589 |
-
"z": -0.
|
| 590 |
-
"visibility":
|
| 591 |
},
|
| 592 |
{
|
| 593 |
"id": 2,
|
| 594 |
"name": "LEFT_EYE",
|
| 595 |
-
"x": 0.
|
| 596 |
-
"y": 0.
|
| 597 |
-
"z": -0.
|
| 598 |
-
"visibility": 0.
|
| 599 |
},
|
| 600 |
{
|
| 601 |
"id": 3,
|
| 602 |
"name": "LEFT_EYE_OUTER",
|
| 603 |
-
"x": 0.
|
| 604 |
-
"y": 0.
|
| 605 |
-
"z": -0.
|
| 606 |
-
"visibility": 0.
|
| 607 |
},
|
| 608 |
{
|
| 609 |
"id": 4,
|
| 610 |
"name": "RIGHT_EYE_INNER",
|
| 611 |
-
"x": 0.
|
| 612 |
-
"y": 0.
|
| 613 |
-
"z": -0.
|
| 614 |
-
"visibility":
|
| 615 |
},
|
| 616 |
{
|
| 617 |
"id": 5,
|
| 618 |
"name": "RIGHT_EYE",
|
| 619 |
-
"x": 0.
|
| 620 |
-
"y": 0.
|
| 621 |
-
"z": -0.
|
| 622 |
-
"visibility":
|
| 623 |
},
|
| 624 |
{
|
| 625 |
"id": 6,
|
| 626 |
"name": "RIGHT_EYE_OUTER",
|
| 627 |
-
"x": 0.
|
| 628 |
-
"y": 0.
|
| 629 |
-
"z": -0.
|
| 630 |
-
"visibility":
|
| 631 |
},
|
| 632 |
{
|
| 633 |
"id": 7,
|
| 634 |
"name": "LEFT_EAR",
|
| 635 |
-
"x": 0.
|
| 636 |
-
"y": 0.
|
| 637 |
-
"z": -0.
|
| 638 |
-
"visibility": 0.
|
| 639 |
},
|
| 640 |
{
|
| 641 |
"id": 8,
|
| 642 |
"name": "RIGHT_EAR",
|
| 643 |
-
"x": 0.
|
| 644 |
-
"y": 0.
|
| 645 |
-
"z": -0.
|
| 646 |
-
"visibility":
|
| 647 |
},
|
| 648 |
{
|
| 649 |
"id": 9,
|
| 650 |
"name": "MOUTH_LEFT",
|
| 651 |
-
"x": 0.
|
| 652 |
-
"y": 0.
|
| 653 |
-
"z": -0.
|
| 654 |
-
"visibility":
|
| 655 |
},
|
| 656 |
{
|
| 657 |
"id": 10,
|
| 658 |
"name": "MOUTH_RIGHT",
|
| 659 |
-
"x": 0.
|
| 660 |
-
"y": 0.
|
| 661 |
-
"z": -0.
|
| 662 |
-
"visibility":
|
| 663 |
},
|
| 664 |
{
|
| 665 |
"id": 11,
|
| 666 |
"name": "LEFT_SHOULDER",
|
| 667 |
-
"x": 0.
|
| 668 |
-
"y": 0.
|
| 669 |
-
"z": -0.
|
| 670 |
-
"visibility":
|
| 671 |
},
|
| 672 |
{
|
| 673 |
"id": 12,
|
| 674 |
"name": "RIGHT_SHOULDER",
|
| 675 |
-
"x": 0.
|
| 676 |
-
"y": 0.
|
| 677 |
-
"z": 0.
|
| 678 |
-
"visibility":
|
| 679 |
},
|
| 680 |
{
|
| 681 |
"id": 13,
|
| 682 |
"name": "LEFT_ELBOW",
|
| 683 |
-
"x": 0.
|
| 684 |
-
"y": 0.
|
| 685 |
-
"z": -0.
|
| 686 |
-
"visibility": 0.
|
| 687 |
},
|
| 688 |
{
|
| 689 |
"id": 14,
|
| 690 |
"name": "RIGHT_ELBOW",
|
| 691 |
-
"x": 0.
|
| 692 |
-
"y": 0.
|
| 693 |
-
"z": 0.
|
| 694 |
-
"visibility": 0.
|
| 695 |
},
|
| 696 |
{
|
| 697 |
"id": 15,
|
| 698 |
"name": "LEFT_WRIST",
|
| 699 |
-
"x": 0.
|
| 700 |
-
"y": 0.
|
| 701 |
-
"z": 0.
|
| 702 |
-
"visibility": 0.
|
| 703 |
},
|
| 704 |
{
|
| 705 |
"id": 16,
|
| 706 |
"name": "RIGHT_WRIST",
|
| 707 |
-
"x": 0.
|
| 708 |
-
"y": 0.
|
| 709 |
-
"z": 0.
|
| 710 |
-
"visibility": 0.
|
| 711 |
},
|
| 712 |
{
|
| 713 |
"id": 17,
|
| 714 |
"name": "LEFT_PINKY",
|
| 715 |
-
"x": 0.
|
| 716 |
-
"y": 0.
|
| 717 |
-
"z": 0.
|
| 718 |
-
"visibility": 0.
|
| 719 |
},
|
| 720 |
{
|
| 721 |
"id": 18,
|
| 722 |
"name": "RIGHT_PINKY",
|
| 723 |
-
"x": 0.
|
| 724 |
-
"y": 0.
|
| 725 |
-
"z": 0.
|
| 726 |
-
"visibility": 0.
|
| 727 |
},
|
| 728 |
{
|
| 729 |
"id": 19,
|
| 730 |
"name": "LEFT_INDEX",
|
| 731 |
-
"x": 0.
|
| 732 |
-
"y": 0.
|
| 733 |
-
"z": 0.
|
| 734 |
-
"visibility": 0.
|
| 735 |
},
|
| 736 |
{
|
| 737 |
"id": 20,
|
| 738 |
"name": "RIGHT_INDEX",
|
| 739 |
-
"x": 0.
|
| 740 |
-
"y": 0.
|
| 741 |
-
"z": 0.
|
| 742 |
-
"visibility": 0.
|
| 743 |
},
|
| 744 |
{
|
| 745 |
"id": 21,
|
| 746 |
"name": "LEFT_THUMB",
|
| 747 |
-
"x": 0.
|
| 748 |
-
"y": 0.
|
| 749 |
-
"z": 0.
|
| 750 |
-
"visibility": 0.
|
| 751 |
},
|
| 752 |
{
|
| 753 |
"id": 22,
|
| 754 |
"name": "RIGHT_THUMB",
|
| 755 |
-
"x": 0.
|
| 756 |
-
"y": 0.
|
| 757 |
-
"z": 0.
|
| 758 |
-
"visibility": 0.
|
| 759 |
},
|
| 760 |
{
|
| 761 |
"id": 23,
|
| 762 |
"name": "LEFT_HIP",
|
| 763 |
-
"x": 0.
|
| 764 |
-
"y": 0.
|
| 765 |
-
"z": -0.
|
| 766 |
-
"visibility":
|
| 767 |
},
|
| 768 |
{
|
| 769 |
"id": 24,
|
| 770 |
"name": "RIGHT_HIP",
|
| 771 |
-
"x": 0.
|
| 772 |
-
"y": 0.
|
| 773 |
-
"z": 0.
|
| 774 |
-
"visibility":
|
| 775 |
},
|
| 776 |
{
|
| 777 |
"id": 25,
|
| 778 |
"name": "LEFT_KNEE",
|
| 779 |
-
"x": 0.
|
| 780 |
-
"y": 0.
|
| 781 |
-
"z": -0.
|
| 782 |
-
"visibility": 0.
|
| 783 |
},
|
| 784 |
{
|
| 785 |
"id": 26,
|
| 786 |
"name": "RIGHT_KNEE",
|
| 787 |
-
"x": 0.
|
| 788 |
-
"y": 0.
|
| 789 |
-
"z": 0.
|
| 790 |
-
"visibility": 0.
|
| 791 |
},
|
| 792 |
{
|
| 793 |
"id": 27,
|
| 794 |
"name": "LEFT_ANKLE",
|
| 795 |
-
"x": 0.
|
| 796 |
-
"y": 0.
|
| 797 |
-
"z": -0.
|
| 798 |
-
"visibility": 0.
|
| 799 |
},
|
| 800 |
{
|
| 801 |
"id": 28,
|
| 802 |
"name": "RIGHT_ANKLE",
|
| 803 |
-
"x": 0.
|
| 804 |
-
"y": 0.
|
| 805 |
-
"z": 0.
|
| 806 |
-
"visibility": 0.
|
| 807 |
},
|
| 808 |
{
|
| 809 |
"id": 29,
|
| 810 |
"name": "LEFT_HEEL",
|
| 811 |
-
"x": 0.
|
| 812 |
-
"y": 0.
|
| 813 |
-
"z": -0.
|
| 814 |
-
"visibility": 0.
|
| 815 |
},
|
| 816 |
{
|
| 817 |
"id": 30,
|
| 818 |
"name": "RIGHT_HEEL",
|
| 819 |
-
"x": 0.
|
| 820 |
-
"y": 0.
|
| 821 |
-
"z": 0.
|
| 822 |
-
"visibility": 0.
|
| 823 |
},
|
| 824 |
{
|
| 825 |
"id": 31,
|
| 826 |
"name": "LEFT_FOOT_INDEX",
|
| 827 |
-
"x": 0.
|
| 828 |
-
"y": 0.
|
| 829 |
-
"z": -0.
|
| 830 |
-
"visibility": 0.
|
| 831 |
},
|
| 832 |
{
|
| 833 |
"id": 32,
|
| 834 |
"name": "RIGHT_FOOT_INDEX",
|
| 835 |
-
"x": 0.
|
| 836 |
-
"y": 0.
|
| 837 |
-
"z": 0.
|
| 838 |
-
"visibility": 0.
|
| 839 |
}
|
| 840 |
]
|
| 841 |
},
|
| 842 |
"4_Top": {
|
| 843 |
-
"score":
|
| 844 |
"comments": [
|
| 845 |
-
"
|
| 846 |
],
|
| 847 |
"data": {
|
| 848 |
-
"lead_arm_angle":
|
| 849 |
-
"shoulder_tilt": 0.
|
| 850 |
},
|
| 851 |
"raw_landmarks": [
|
| 852 |
{
|
| 853 |
"id": 0,
|
| 854 |
"name": "NOSE",
|
| 855 |
-
"x": 0.
|
| 856 |
-
"y": 0.
|
| 857 |
-
"z": 0.
|
| 858 |
-
"visibility":
|
| 859 |
},
|
| 860 |
{
|
| 861 |
"id": 1,
|
| 862 |
"name": "LEFT_EYE_INNER",
|
| 863 |
-
"x": 0.
|
| 864 |
-
"y": 0.
|
| 865 |
-
"z": 0.
|
| 866 |
-
"visibility":
|
| 867 |
},
|
| 868 |
{
|
| 869 |
"id": 2,
|
| 870 |
"name": "LEFT_EYE",
|
| 871 |
-
"x": 0.
|
| 872 |
-
"y": 0.
|
| 873 |
-
"z": 0.
|
| 874 |
-
"visibility": 0.
|
| 875 |
},
|
| 876 |
{
|
| 877 |
"id": 3,
|
| 878 |
"name": "LEFT_EYE_OUTER",
|
| 879 |
-
"x": 0.
|
| 880 |
-
"y": 0.
|
| 881 |
-
"z": 0.
|
| 882 |
-
"visibility": 0.
|
| 883 |
},
|
| 884 |
{
|
| 885 |
"id": 4,
|
| 886 |
"name": "RIGHT_EYE_INNER",
|
| 887 |
-
"x": 0.
|
| 888 |
-
"y": 0.
|
| 889 |
-
"z": 0.
|
| 890 |
-
"visibility":
|
| 891 |
},
|
| 892 |
{
|
| 893 |
"id": 5,
|
| 894 |
"name": "RIGHT_EYE",
|
| 895 |
-
"x": 0.
|
| 896 |
-
"y": 0.
|
| 897 |
-
"z": 0.
|
| 898 |
-
"visibility":
|
| 899 |
},
|
| 900 |
{
|
| 901 |
"id": 6,
|
| 902 |
"name": "RIGHT_EYE_OUTER",
|
| 903 |
-
"x": 0.
|
| 904 |
-
"y": 0.
|
| 905 |
-
"z": 0.
|
| 906 |
-
"visibility":
|
| 907 |
},
|
| 908 |
{
|
| 909 |
"id": 7,
|
| 910 |
"name": "LEFT_EAR",
|
| 911 |
-
"x": 0.
|
| 912 |
-
"y": 0.
|
| 913 |
-
"z": -0.
|
| 914 |
-
"visibility": 0.
|
| 915 |
},
|
| 916 |
{
|
| 917 |
"id": 8,
|
| 918 |
"name": "RIGHT_EAR",
|
| 919 |
-
"x": 0.
|
| 920 |
-
"y": 0.
|
| 921 |
-
"z": 0.
|
| 922 |
-
"visibility":
|
| 923 |
},
|
| 924 |
{
|
| 925 |
"id": 9,
|
| 926 |
"name": "MOUTH_LEFT",
|
| 927 |
-
"x": 0.
|
| 928 |
-
"y": 0.
|
| 929 |
-
"z": 0.
|
| 930 |
-
"visibility":
|
| 931 |
},
|
| 932 |
{
|
| 933 |
"id": 10,
|
| 934 |
"name": "MOUTH_RIGHT",
|
| 935 |
-
"x": 0.
|
| 936 |
-
"y": 0.
|
| 937 |
-
"z": 0.
|
| 938 |
-
"visibility":
|
| 939 |
},
|
| 940 |
{
|
| 941 |
"id": 11,
|
| 942 |
"name": "LEFT_SHOULDER",
|
| 943 |
-
"x": 0.
|
| 944 |
-
"y": 0.
|
| 945 |
-
"z": -0.
|
| 946 |
-
"visibility":
|
| 947 |
},
|
| 948 |
{
|
| 949 |
"id": 12,
|
| 950 |
"name": "RIGHT_SHOULDER",
|
| 951 |
-
"x": 0.
|
| 952 |
-
"y": 0.
|
| 953 |
-
"z": 0.
|
| 954 |
-
"visibility":
|
| 955 |
},
|
| 956 |
{
|
| 957 |
"id": 13,
|
| 958 |
"name": "LEFT_ELBOW",
|
| 959 |
-
"x": 0.
|
| 960 |
-
"y": 0.
|
| 961 |
-
"z": -0.
|
| 962 |
-
"visibility": 0.
|
| 963 |
},
|
| 964 |
{
|
| 965 |
"id": 14,
|
| 966 |
"name": "RIGHT_ELBOW",
|
| 967 |
-
"x": 0.
|
| 968 |
-
"y": 0.
|
| 969 |
-
"z": 0.
|
| 970 |
-
"visibility": 0.
|
| 971 |
},
|
| 972 |
{
|
| 973 |
"id": 15,
|
| 974 |
"name": "LEFT_WRIST",
|
| 975 |
-
"x": 0.
|
| 976 |
-
"y": 0.
|
| 977 |
-
"z": 0.
|
| 978 |
-
"visibility": 0.
|
| 979 |
},
|
| 980 |
{
|
| 981 |
"id": 16,
|
| 982 |
"name": "RIGHT_WRIST",
|
| 983 |
-
"x": 0.
|
| 984 |
-
"y": 0.
|
| 985 |
-
"z": 0.
|
| 986 |
-
"visibility": 0.
|
| 987 |
},
|
| 988 |
{
|
| 989 |
"id": 17,
|
| 990 |
"name": "LEFT_PINKY",
|
| 991 |
-
"x": 0.
|
| 992 |
-
"y": 0.
|
| 993 |
-
"z": 0.
|
| 994 |
-
"visibility": 0.
|
| 995 |
},
|
| 996 |
{
|
| 997 |
"id": 18,
|
| 998 |
"name": "RIGHT_PINKY",
|
| 999 |
-
"x": 0.
|
| 1000 |
-
"y": 0.
|
| 1001 |
-
"z": 0.
|
| 1002 |
-
"visibility": 0.
|
| 1003 |
},
|
| 1004 |
{
|
| 1005 |
"id": 19,
|
| 1006 |
"name": "LEFT_INDEX",
|
| 1007 |
-
"x": 0.
|
| 1008 |
-
"y": 0.
|
| 1009 |
-
"z": 0.
|
| 1010 |
-
"visibility": 0.
|
| 1011 |
},
|
| 1012 |
{
|
| 1013 |
"id": 20,
|
| 1014 |
"name": "RIGHT_INDEX",
|
| 1015 |
-
"x": 0.
|
| 1016 |
-
"y": 0.
|
| 1017 |
-
"z": 0.
|
| 1018 |
-
"visibility": 0.
|
| 1019 |
},
|
| 1020 |
{
|
| 1021 |
"id": 21,
|
| 1022 |
"name": "LEFT_THUMB",
|
| 1023 |
-
"x": 0.
|
| 1024 |
-
"y": 0.
|
| 1025 |
-
"z": 0.
|
| 1026 |
-
"visibility": 0.
|
| 1027 |
},
|
| 1028 |
{
|
| 1029 |
"id": 22,
|
| 1030 |
"name": "RIGHT_THUMB",
|
| 1031 |
-
"x": 0.
|
| 1032 |
-
"y": 0.
|
| 1033 |
-
"z": 0.
|
| 1034 |
-
"visibility": 0.
|
| 1035 |
},
|
| 1036 |
{
|
| 1037 |
"id": 23,
|
| 1038 |
"name": "LEFT_HIP",
|
| 1039 |
-
"x": 0.
|
| 1040 |
-
"y": 0.
|
| 1041 |
-
"z": -0.
|
| 1042 |
-
"visibility":
|
| 1043 |
},
|
| 1044 |
{
|
| 1045 |
"id": 24,
|
| 1046 |
"name": "RIGHT_HIP",
|
| 1047 |
-
"x": 0.
|
| 1048 |
-
"y": 0.
|
| 1049 |
-
"z": 0.
|
| 1050 |
-
"visibility":
|
| 1051 |
},
|
| 1052 |
{
|
| 1053 |
"id": 25,
|
| 1054 |
"name": "LEFT_KNEE",
|
| 1055 |
-
"x": 0.
|
| 1056 |
-
"y": 0.
|
| 1057 |
-
"z": -0.
|
| 1058 |
-
"visibility": 0.
|
| 1059 |
},
|
| 1060 |
{
|
| 1061 |
"id": 26,
|
| 1062 |
"name": "RIGHT_KNEE",
|
| 1063 |
-
"x": 0.
|
| 1064 |
-
"y": 0.
|
| 1065 |
-
"z": 0.
|
| 1066 |
-
"visibility": 0.
|
| 1067 |
},
|
| 1068 |
{
|
| 1069 |
"id": 27,
|
| 1070 |
"name": "LEFT_ANKLE",
|
| 1071 |
-
"x": 0.
|
| 1072 |
-
"y": 0.
|
| 1073 |
-
"z": -0.
|
| 1074 |
-
"visibility": 0.
|
| 1075 |
},
|
| 1076 |
{
|
| 1077 |
"id": 28,
|
| 1078 |
"name": "RIGHT_ANKLE",
|
| 1079 |
-
"x": 0.
|
| 1080 |
-
"y": 0.
|
| 1081 |
-
"z": 0.
|
| 1082 |
-
"visibility": 0.
|
| 1083 |
},
|
| 1084 |
{
|
| 1085 |
"id": 29,
|
| 1086 |
"name": "LEFT_HEEL",
|
| 1087 |
-
"x": 0.
|
| 1088 |
-
"y": 0.
|
| 1089 |
-
"z": -0.
|
| 1090 |
-
"visibility": 0.
|
| 1091 |
},
|
| 1092 |
{
|
| 1093 |
"id": 30,
|
| 1094 |
"name": "RIGHT_HEEL",
|
| 1095 |
-
"x": 0.
|
| 1096 |
-
"y": 0.
|
| 1097 |
-
"z": 0.
|
| 1098 |
-
"visibility": 0.
|
| 1099 |
},
|
| 1100 |
{
|
| 1101 |
"id": 31,
|
| 1102 |
"name": "LEFT_FOOT_INDEX",
|
| 1103 |
-
"x": 0.
|
| 1104 |
-
"y": 0.
|
| 1105 |
-
"z": -0.
|
| 1106 |
"visibility": 0.9763
|
| 1107 |
},
|
| 1108 |
{
|
| 1109 |
"id": 32,
|
| 1110 |
"name": "RIGHT_FOOT_INDEX",
|
| 1111 |
-
"x": 0.
|
| 1112 |
-
"y": 0.
|
| 1113 |
-
"z": 0.
|
| 1114 |
-
"visibility": 0.
|
| 1115 |
}
|
| 1116 |
]
|
| 1117 |
},
|
| 1118 |
"5_Mid-Downswing": {
|
| 1119 |
-
"score": 10
|
| 1120 |
"comments": [
|
| 1121 |
"Đạt chuẩn"
|
| 1122 |
],
|
|
@@ -1125,546 +1125,546 @@
|
|
| 1125 |
{
|
| 1126 |
"id": 0,
|
| 1127 |
"name": "NOSE",
|
| 1128 |
-
"x": 0.
|
| 1129 |
-
"y": 0.
|
| 1130 |
-
"z": -0.
|
| 1131 |
-
"visibility":
|
| 1132 |
},
|
| 1133 |
{
|
| 1134 |
"id": 1,
|
| 1135 |
"name": "LEFT_EYE_INNER",
|
| 1136 |
-
"x": 0.
|
| 1137 |
-
"y": 0.
|
| 1138 |
-
"z": -0.
|
| 1139 |
-
"visibility":
|
| 1140 |
},
|
| 1141 |
{
|
| 1142 |
"id": 2,
|
| 1143 |
"name": "LEFT_EYE",
|
| 1144 |
-
"x": 0.
|
| 1145 |
-
"y": 0.
|
| 1146 |
-
"z": -0.
|
| 1147 |
-
"visibility": 0.
|
| 1148 |
},
|
| 1149 |
{
|
| 1150 |
"id": 3,
|
| 1151 |
"name": "LEFT_EYE_OUTER",
|
| 1152 |
-
"x": 0.
|
| 1153 |
-
"y": 0.
|
| 1154 |
-
"z": -0.
|
| 1155 |
-
"visibility": 0.
|
| 1156 |
},
|
| 1157 |
{
|
| 1158 |
"id": 4,
|
| 1159 |
"name": "RIGHT_EYE_INNER",
|
| 1160 |
-
"x": 0.
|
| 1161 |
-
"y": 0.
|
| 1162 |
-
"z": -0.
|
| 1163 |
-
"visibility":
|
| 1164 |
},
|
| 1165 |
{
|
| 1166 |
"id": 5,
|
| 1167 |
"name": "RIGHT_EYE",
|
| 1168 |
-
"x": 0.
|
| 1169 |
-
"y": 0.
|
| 1170 |
-
"z": -0.
|
| 1171 |
-
"visibility":
|
| 1172 |
},
|
| 1173 |
{
|
| 1174 |
"id": 6,
|
| 1175 |
"name": "RIGHT_EYE_OUTER",
|
| 1176 |
-
"x": 0.
|
| 1177 |
-
"y": 0.
|
| 1178 |
-
"z": -0.
|
| 1179 |
-
"visibility":
|
| 1180 |
},
|
| 1181 |
{
|
| 1182 |
"id": 7,
|
| 1183 |
"name": "LEFT_EAR",
|
| 1184 |
-
"x": 0.
|
| 1185 |
-
"y": 0.
|
| 1186 |
-
"z": -0.
|
| 1187 |
-
"visibility": 0.
|
| 1188 |
},
|
| 1189 |
{
|
| 1190 |
"id": 8,
|
| 1191 |
"name": "RIGHT_EAR",
|
| 1192 |
-
"x": 0.
|
| 1193 |
-
"y": 0.
|
| 1194 |
-
"z": -0.
|
| 1195 |
-
"visibility":
|
| 1196 |
},
|
| 1197 |
{
|
| 1198 |
"id": 9,
|
| 1199 |
"name": "MOUTH_LEFT",
|
| 1200 |
-
"x": 0.
|
| 1201 |
-
"y": 0.
|
| 1202 |
-
"z": -0.
|
| 1203 |
-
"visibility":
|
| 1204 |
},
|
| 1205 |
{
|
| 1206 |
"id": 10,
|
| 1207 |
"name": "MOUTH_RIGHT",
|
| 1208 |
-
"x": 0.
|
| 1209 |
-
"y": 0.
|
| 1210 |
-
"z": -0.
|
| 1211 |
-
"visibility":
|
| 1212 |
},
|
| 1213 |
{
|
| 1214 |
"id": 11,
|
| 1215 |
"name": "LEFT_SHOULDER",
|
| 1216 |
-
"x": 0.
|
| 1217 |
-
"y": 0.
|
| 1218 |
-
"z": -0.
|
| 1219 |
-
"visibility":
|
| 1220 |
},
|
| 1221 |
{
|
| 1222 |
"id": 12,
|
| 1223 |
"name": "RIGHT_SHOULDER",
|
| 1224 |
-
"x": 0.
|
| 1225 |
-
"y": 0.
|
| 1226 |
-
"z": -0.
|
| 1227 |
-
"visibility":
|
| 1228 |
},
|
| 1229 |
{
|
| 1230 |
"id": 13,
|
| 1231 |
"name": "LEFT_ELBOW",
|
| 1232 |
-
"x": 0.
|
| 1233 |
-
"y": 0.
|
| 1234 |
-
"z": -0.
|
| 1235 |
-
"visibility": 0.
|
| 1236 |
},
|
| 1237 |
{
|
| 1238 |
"id": 14,
|
| 1239 |
"name": "RIGHT_ELBOW",
|
| 1240 |
-
"x": 0.
|
| 1241 |
-
"y": 0.
|
| 1242 |
-
"z": -0.
|
| 1243 |
-
"visibility": 0.
|
| 1244 |
},
|
| 1245 |
{
|
| 1246 |
"id": 15,
|
| 1247 |
"name": "LEFT_WRIST",
|
| 1248 |
-
"x": 0.
|
| 1249 |
-
"y": 0.
|
| 1250 |
-
"z": -0.
|
| 1251 |
-
"visibility": 0.
|
| 1252 |
},
|
| 1253 |
{
|
| 1254 |
"id": 16,
|
| 1255 |
"name": "RIGHT_WRIST",
|
| 1256 |
-
"x": 0.
|
| 1257 |
-
"y": 0.
|
| 1258 |
-
"z": -0.
|
| 1259 |
-
"visibility": 0.
|
| 1260 |
},
|
| 1261 |
{
|
| 1262 |
"id": 17,
|
| 1263 |
"name": "LEFT_PINKY",
|
| 1264 |
-
"x": 0.
|
| 1265 |
-
"y": 0.
|
| 1266 |
-
"z": -0.
|
| 1267 |
-
"visibility": 0.
|
| 1268 |
},
|
| 1269 |
{
|
| 1270 |
"id": 18,
|
| 1271 |
"name": "RIGHT_PINKY",
|
| 1272 |
-
"x": 0.
|
| 1273 |
-
"y": 0.
|
| 1274 |
-
"z": -0.
|
| 1275 |
-
"visibility": 0.
|
| 1276 |
},
|
| 1277 |
{
|
| 1278 |
"id": 19,
|
| 1279 |
"name": "LEFT_INDEX",
|
| 1280 |
-
"x": 0.
|
| 1281 |
-
"y": 0.
|
| 1282 |
-
"z": -0.
|
| 1283 |
-
"visibility": 0.
|
| 1284 |
},
|
| 1285 |
{
|
| 1286 |
"id": 20,
|
| 1287 |
"name": "RIGHT_INDEX",
|
| 1288 |
-
"x": 0.
|
| 1289 |
-
"y": 0.
|
| 1290 |
-
"z": -0.
|
| 1291 |
-
"visibility": 0.
|
| 1292 |
},
|
| 1293 |
{
|
| 1294 |
"id": 21,
|
| 1295 |
"name": "LEFT_THUMB",
|
| 1296 |
-
"x": 0.
|
| 1297 |
-
"y": 0.
|
| 1298 |
-
"z": -0.
|
| 1299 |
-
"visibility": 0.
|
| 1300 |
},
|
| 1301 |
{
|
| 1302 |
"id": 22,
|
| 1303 |
"name": "RIGHT_THUMB",
|
| 1304 |
-
"x": 0.
|
| 1305 |
-
"y": 0.
|
| 1306 |
-
"z": -0.
|
| 1307 |
-
"visibility": 0.
|
| 1308 |
},
|
| 1309 |
{
|
| 1310 |
"id": 23,
|
| 1311 |
"name": "LEFT_HIP",
|
| 1312 |
-
"x": 0.
|
| 1313 |
-
"y": 0.
|
| 1314 |
-
"z": -0.
|
| 1315 |
-
"visibility":
|
| 1316 |
},
|
| 1317 |
{
|
| 1318 |
"id": 24,
|
| 1319 |
"name": "RIGHT_HIP",
|
| 1320 |
-
"x": 0.
|
| 1321 |
-
"y": 0.
|
| 1322 |
-
"z": 0.
|
| 1323 |
-
"visibility":
|
| 1324 |
},
|
| 1325 |
{
|
| 1326 |
"id": 25,
|
| 1327 |
"name": "LEFT_KNEE",
|
| 1328 |
-
"x": 0.
|
| 1329 |
-
"y": 0.
|
| 1330 |
-
"z": -0.
|
| 1331 |
-
"visibility": 0.
|
| 1332 |
},
|
| 1333 |
{
|
| 1334 |
"id": 26,
|
| 1335 |
"name": "RIGHT_KNEE",
|
| 1336 |
-
"x": 0.
|
| 1337 |
-
"y": 0.
|
| 1338 |
-
"z": 0.
|
| 1339 |
-
"visibility": 0.
|
| 1340 |
},
|
| 1341 |
{
|
| 1342 |
"id": 27,
|
| 1343 |
"name": "LEFT_ANKLE",
|
| 1344 |
-
"x": 0.
|
| 1345 |
-
"y": 0.
|
| 1346 |
-
"z": 0.
|
| 1347 |
-
"visibility": 0.
|
| 1348 |
},
|
| 1349 |
{
|
| 1350 |
"id": 28,
|
| 1351 |
"name": "RIGHT_ANKLE",
|
| 1352 |
-
"x": 0.
|
| 1353 |
-
"y": 0.
|
| 1354 |
-
"z": 0.
|
| 1355 |
-
"visibility": 0.
|
| 1356 |
},
|
| 1357 |
{
|
| 1358 |
"id": 29,
|
| 1359 |
"name": "LEFT_HEEL",
|
| 1360 |
-
"x": 0.
|
| 1361 |
-
"y": 0.
|
| 1362 |
-
"z": 0.
|
| 1363 |
-
"visibility": 0.
|
| 1364 |
},
|
| 1365 |
{
|
| 1366 |
"id": 30,
|
| 1367 |
"name": "RIGHT_HEEL",
|
| 1368 |
-
"x": 0.
|
| 1369 |
-
"y": 0.
|
| 1370 |
-
"z": 0.
|
| 1371 |
-
"visibility": 0.
|
| 1372 |
},
|
| 1373 |
{
|
| 1374 |
"id": 31,
|
| 1375 |
"name": "LEFT_FOOT_INDEX",
|
| 1376 |
-
"x": 0.
|
| 1377 |
-
"y": 0.
|
| 1378 |
-
"z": -0.
|
| 1379 |
-
"visibility": 0.
|
| 1380 |
},
|
| 1381 |
{
|
| 1382 |
"id": 32,
|
| 1383 |
"name": "RIGHT_FOOT_INDEX",
|
| 1384 |
-
"x": 0.
|
| 1385 |
-
"y": 0.
|
| 1386 |
-
"z": 0.
|
| 1387 |
-
"visibility": 0.
|
| 1388 |
}
|
| 1389 |
]
|
| 1390 |
},
|
| 1391 |
"6_Impact": {
|
| 1392 |
-
"score": 10
|
| 1393 |
"comments": [
|
| 1394 |
"Đạt chuẩn"
|
| 1395 |
],
|
| 1396 |
"data": {
|
| 1397 |
-
"hip_openness": 0.
|
| 1398 |
},
|
| 1399 |
"raw_landmarks": [
|
| 1400 |
{
|
| 1401 |
"id": 0,
|
| 1402 |
"name": "NOSE",
|
| 1403 |
-
"x": 0.
|
| 1404 |
-
"y": 0.
|
| 1405 |
-
"z": -0.
|
| 1406 |
-
"visibility":
|
| 1407 |
},
|
| 1408 |
{
|
| 1409 |
"id": 1,
|
| 1410 |
"name": "LEFT_EYE_INNER",
|
| 1411 |
-
"x": 0.
|
| 1412 |
-
"y": 0.
|
| 1413 |
-
"z": -0.
|
| 1414 |
-
"visibility":
|
| 1415 |
},
|
| 1416 |
{
|
| 1417 |
"id": 2,
|
| 1418 |
"name": "LEFT_EYE",
|
| 1419 |
-
"x": 0.
|
| 1420 |
-
"y": 0.
|
| 1421 |
-
"z": -0.
|
| 1422 |
-
"visibility": 0.
|
| 1423 |
},
|
| 1424 |
{
|
| 1425 |
"id": 3,
|
| 1426 |
"name": "LEFT_EYE_OUTER",
|
| 1427 |
-
"x": 0.
|
| 1428 |
-
"y": 0.
|
| 1429 |
-
"z": -0.
|
| 1430 |
-
"visibility": 0.
|
| 1431 |
},
|
| 1432 |
{
|
| 1433 |
"id": 4,
|
| 1434 |
"name": "RIGHT_EYE_INNER",
|
| 1435 |
-
"x": 0.
|
| 1436 |
-
"y": 0.
|
| 1437 |
-
"z": -0.
|
| 1438 |
-
"visibility":
|
| 1439 |
},
|
| 1440 |
{
|
| 1441 |
"id": 5,
|
| 1442 |
"name": "RIGHT_EYE",
|
| 1443 |
-
"x": 0.
|
| 1444 |
-
"y": 0.
|
| 1445 |
-
"z": -0.
|
| 1446 |
-
"visibility":
|
| 1447 |
},
|
| 1448 |
{
|
| 1449 |
"id": 6,
|
| 1450 |
"name": "RIGHT_EYE_OUTER",
|
| 1451 |
-
"x": 0.
|
| 1452 |
-
"y": 0.
|
| 1453 |
-
"z": -0.
|
| 1454 |
-
"visibility":
|
| 1455 |
},
|
| 1456 |
{
|
| 1457 |
"id": 7,
|
| 1458 |
"name": "LEFT_EAR",
|
| 1459 |
-
"x": 0.
|
| 1460 |
-
"y": 0.
|
| 1461 |
-
"z": -0.
|
| 1462 |
-
"visibility": 0.
|
| 1463 |
},
|
| 1464 |
{
|
| 1465 |
"id": 8,
|
| 1466 |
"name": "RIGHT_EAR",
|
| 1467 |
-
"x": 0.
|
| 1468 |
-
"y": 0.
|
| 1469 |
-
"z": -0.
|
| 1470 |
-
"visibility":
|
| 1471 |
},
|
| 1472 |
{
|
| 1473 |
"id": 9,
|
| 1474 |
"name": "MOUTH_LEFT",
|
| 1475 |
-
"x": 0.
|
| 1476 |
-
"y": 0.
|
| 1477 |
-
"z": -0.
|
| 1478 |
-
"visibility":
|
| 1479 |
},
|
| 1480 |
{
|
| 1481 |
"id": 10,
|
| 1482 |
"name": "MOUTH_RIGHT",
|
| 1483 |
-
"x": 0.
|
| 1484 |
-
"y": 0.
|
| 1485 |
-
"z": -0.
|
| 1486 |
-
"visibility":
|
| 1487 |
},
|
| 1488 |
{
|
| 1489 |
"id": 11,
|
| 1490 |
"name": "LEFT_SHOULDER",
|
| 1491 |
-
"x": 0.
|
| 1492 |
-
"y": 0.
|
| 1493 |
-
"z": -0.
|
| 1494 |
-
"visibility": 1
|
| 1495 |
},
|
| 1496 |
{
|
| 1497 |
"id": 12,
|
| 1498 |
"name": "RIGHT_SHOULDER",
|
| 1499 |
-
"x": 0.
|
| 1500 |
-
"y": 0.
|
| 1501 |
-
"z": -0.
|
| 1502 |
-
"visibility":
|
| 1503 |
},
|
| 1504 |
{
|
| 1505 |
"id": 13,
|
| 1506 |
"name": "LEFT_ELBOW",
|
| 1507 |
-
"x": 0.
|
| 1508 |
-
"y": 0.
|
| 1509 |
-
"z": -0.
|
| 1510 |
-
"visibility": 0.
|
| 1511 |
},
|
| 1512 |
{
|
| 1513 |
"id": 14,
|
| 1514 |
"name": "RIGHT_ELBOW",
|
| 1515 |
-
"x": 0.
|
| 1516 |
-
"y": 0.
|
| 1517 |
-
"z": -0.
|
| 1518 |
-
"visibility": 0.
|
| 1519 |
},
|
| 1520 |
{
|
| 1521 |
"id": 15,
|
| 1522 |
"name": "LEFT_WRIST",
|
| 1523 |
-
"x": 0.
|
| 1524 |
-
"y": 0.
|
| 1525 |
-
"z": -0.
|
| 1526 |
-
"visibility": 0.
|
| 1527 |
},
|
| 1528 |
{
|
| 1529 |
"id": 16,
|
| 1530 |
"name": "RIGHT_WRIST",
|
| 1531 |
-
"x": 0.
|
| 1532 |
-
"y": 0.
|
| 1533 |
-
"z": -0.
|
| 1534 |
-
"visibility": 0.
|
| 1535 |
},
|
| 1536 |
{
|
| 1537 |
"id": 17,
|
| 1538 |
"name": "LEFT_PINKY",
|
| 1539 |
-
"x": 0.
|
| 1540 |
-
"y": 0.
|
| 1541 |
-
"z": -0.
|
| 1542 |
-
"visibility": 0.
|
| 1543 |
},
|
| 1544 |
{
|
| 1545 |
"id": 18,
|
| 1546 |
"name": "RIGHT_PINKY",
|
| 1547 |
-
"x": 0.
|
| 1548 |
-
"y": 0.
|
| 1549 |
-
"z": -0.
|
| 1550 |
-
"visibility": 0.
|
| 1551 |
},
|
| 1552 |
{
|
| 1553 |
"id": 19,
|
| 1554 |
"name": "LEFT_INDEX",
|
| 1555 |
-
"x": 0.
|
| 1556 |
-
"y": 0.
|
| 1557 |
-
"z": -0.
|
| 1558 |
-
"visibility": 0.
|
| 1559 |
},
|
| 1560 |
{
|
| 1561 |
"id": 20,
|
| 1562 |
"name": "RIGHT_INDEX",
|
| 1563 |
-
"x": 0.
|
| 1564 |
-
"y": 0.
|
| 1565 |
-
"z": -0.
|
| 1566 |
-
"visibility": 0.
|
| 1567 |
},
|
| 1568 |
{
|
| 1569 |
"id": 21,
|
| 1570 |
"name": "LEFT_THUMB",
|
| 1571 |
-
"x": 0.
|
| 1572 |
-
"y": 0.
|
| 1573 |
-
"z": -0.
|
| 1574 |
-
"visibility": 0.
|
| 1575 |
},
|
| 1576 |
{
|
| 1577 |
"id": 22,
|
| 1578 |
"name": "RIGHT_THUMB",
|
| 1579 |
-
"x": 0.
|
| 1580 |
-
"y": 0.
|
| 1581 |
-
"z": -0.
|
| 1582 |
-
"visibility": 0.
|
| 1583 |
},
|
| 1584 |
{
|
| 1585 |
"id": 23,
|
| 1586 |
"name": "LEFT_HIP",
|
| 1587 |
-
"x": 0.
|
| 1588 |
-
"y": 0.
|
| 1589 |
-
"z": -0.
|
| 1590 |
-
"visibility":
|
| 1591 |
},
|
| 1592 |
{
|
| 1593 |
"id": 24,
|
| 1594 |
"name": "RIGHT_HIP",
|
| 1595 |
-
"x": 0.
|
| 1596 |
-
"y": 0.
|
| 1597 |
-
"z": 0.
|
| 1598 |
-
"visibility":
|
| 1599 |
},
|
| 1600 |
{
|
| 1601 |
"id": 25,
|
| 1602 |
"name": "LEFT_KNEE",
|
| 1603 |
-
"x": 0.
|
| 1604 |
-
"y": 0.
|
| 1605 |
-
"z": -0.
|
| 1606 |
-
"visibility": 0.
|
| 1607 |
},
|
| 1608 |
{
|
| 1609 |
"id": 26,
|
| 1610 |
"name": "RIGHT_KNEE",
|
| 1611 |
-
"x": 0.
|
| 1612 |
-
"y": 0.
|
| 1613 |
-
"z": -0.
|
| 1614 |
-
"visibility": 0.
|
| 1615 |
},
|
| 1616 |
{
|
| 1617 |
"id": 27,
|
| 1618 |
"name": "LEFT_ANKLE",
|
| 1619 |
-
"x": 0.
|
| 1620 |
-
"y": 0.
|
| 1621 |
-
"z": 0.
|
| 1622 |
-
"visibility": 0.
|
| 1623 |
},
|
| 1624 |
{
|
| 1625 |
"id": 28,
|
| 1626 |
"name": "RIGHT_ANKLE",
|
| 1627 |
-
"x": 0.
|
| 1628 |
-
"y": 0.
|
| 1629 |
-
"z": 0.
|
| 1630 |
-
"visibility": 0.
|
| 1631 |
},
|
| 1632 |
{
|
| 1633 |
"id": 29,
|
| 1634 |
"name": "LEFT_HEEL",
|
| 1635 |
-
"x": 0.
|
| 1636 |
-
"y": 0.
|
| 1637 |
-
"z": 0.
|
| 1638 |
-
"visibility": 0.
|
| 1639 |
},
|
| 1640 |
{
|
| 1641 |
"id": 30,
|
| 1642 |
"name": "RIGHT_HEEL",
|
| 1643 |
-
"x": 0.
|
| 1644 |
-
"y": 0.
|
| 1645 |
-
"z": 0.
|
| 1646 |
-
"visibility": 0.
|
| 1647 |
},
|
| 1648 |
{
|
| 1649 |
"id": 31,
|
| 1650 |
"name": "LEFT_FOOT_INDEX",
|
| 1651 |
-
"x": 0.
|
| 1652 |
-
"y": 0.
|
| 1653 |
-
"z": -0.
|
| 1654 |
-
"visibility": 0.
|
| 1655 |
},
|
| 1656 |
{
|
| 1657 |
"id": 32,
|
| 1658 |
"name": "RIGHT_FOOT_INDEX",
|
| 1659 |
-
"x": 0.
|
| 1660 |
-
"y": 0.
|
| 1661 |
-
"z": -0.
|
| 1662 |
-
"visibility": 0.
|
| 1663 |
}
|
| 1664 |
]
|
| 1665 |
},
|
| 1666 |
"7_Mid-Follow-Through": {
|
| 1667 |
-
"score": 10
|
| 1668 |
"comments": [
|
| 1669 |
"Đạt chuẩn"
|
| 1670 |
],
|
|
@@ -1673,271 +1673,271 @@
|
|
| 1673 |
{
|
| 1674 |
"id": 0,
|
| 1675 |
"name": "NOSE",
|
| 1676 |
-
"x": 0.
|
| 1677 |
-
"y": 0.
|
| 1678 |
-
"z": -0.
|
| 1679 |
-
"visibility":
|
| 1680 |
},
|
| 1681 |
{
|
| 1682 |
"id": 1,
|
| 1683 |
"name": "LEFT_EYE_INNER",
|
| 1684 |
-
"x": 0.
|
| 1685 |
-
"y": 0.
|
| 1686 |
-
"z": -0.
|
| 1687 |
-
"visibility": 0.
|
| 1688 |
},
|
| 1689 |
{
|
| 1690 |
"id": 2,
|
| 1691 |
"name": "LEFT_EYE",
|
| 1692 |
-
"x": 0.
|
| 1693 |
-
"y": 0.
|
| 1694 |
-
"z": -0.
|
| 1695 |
-
"visibility": 0.
|
| 1696 |
},
|
| 1697 |
{
|
| 1698 |
"id": 3,
|
| 1699 |
"name": "LEFT_EYE_OUTER",
|
| 1700 |
-
"x": 0.
|
| 1701 |
-
"y": 0.
|
| 1702 |
-
"z": -0.
|
| 1703 |
-
"visibility": 0.
|
| 1704 |
},
|
| 1705 |
{
|
| 1706 |
"id": 4,
|
| 1707 |
"name": "RIGHT_EYE_INNER",
|
| 1708 |
-
"x": 0.
|
| 1709 |
-
"y": 0.
|
| 1710 |
-
"z": -0.
|
| 1711 |
-
"visibility": 0.
|
| 1712 |
},
|
| 1713 |
{
|
| 1714 |
"id": 5,
|
| 1715 |
"name": "RIGHT_EYE",
|
| 1716 |
-
"x": 0.
|
| 1717 |
-
"y": 0.
|
| 1718 |
-
"z": -0.
|
| 1719 |
-
"visibility": 0.
|
| 1720 |
},
|
| 1721 |
{
|
| 1722 |
"id": 6,
|
| 1723 |
"name": "RIGHT_EYE_OUTER",
|
| 1724 |
-
"x": 0.
|
| 1725 |
-
"y": 0.
|
| 1726 |
-
"z": -0.
|
| 1727 |
-
"visibility": 0.
|
| 1728 |
},
|
| 1729 |
{
|
| 1730 |
"id": 7,
|
| 1731 |
"name": "LEFT_EAR",
|
| 1732 |
-
"x": 0.
|
| 1733 |
-
"y": 0.
|
| 1734 |
-
"z": -0.
|
| 1735 |
-
"visibility": 0.
|
| 1736 |
},
|
| 1737 |
{
|
| 1738 |
"id": 8,
|
| 1739 |
"name": "RIGHT_EAR",
|
| 1740 |
-
"x": 0.
|
| 1741 |
-
"y": 0.
|
| 1742 |
-
"z": -0.
|
| 1743 |
-
"visibility": 0.
|
| 1744 |
},
|
| 1745 |
{
|
| 1746 |
"id": 9,
|
| 1747 |
"name": "MOUTH_LEFT",
|
| 1748 |
-
"x": 0.
|
| 1749 |
-
"y": 0.
|
| 1750 |
-
"z": -0.
|
| 1751 |
-
"visibility":
|
| 1752 |
},
|
| 1753 |
{
|
| 1754 |
"id": 10,
|
| 1755 |
"name": "MOUTH_RIGHT",
|
| 1756 |
-
"x": 0.
|
| 1757 |
-
"y": 0.
|
| 1758 |
-
"z": -0.
|
| 1759 |
-
"visibility":
|
| 1760 |
},
|
| 1761 |
{
|
| 1762 |
"id": 11,
|
| 1763 |
"name": "LEFT_SHOULDER",
|
| 1764 |
-
"x": 0.
|
| 1765 |
-
"y": 0.
|
| 1766 |
-
"z": -0.
|
| 1767 |
-
"visibility":
|
| 1768 |
},
|
| 1769 |
{
|
| 1770 |
"id": 12,
|
| 1771 |
"name": "RIGHT_SHOULDER",
|
| 1772 |
-
"x": 0.
|
| 1773 |
-
"y": 0.
|
| 1774 |
-
"z": -0.
|
| 1775 |
-
"visibility":
|
| 1776 |
},
|
| 1777 |
{
|
| 1778 |
"id": 13,
|
| 1779 |
"name": "LEFT_ELBOW",
|
| 1780 |
-
"x": 0.
|
| 1781 |
-
"y": 0.
|
| 1782 |
-
"z": -0.
|
| 1783 |
-
"visibility": 0.
|
| 1784 |
},
|
| 1785 |
{
|
| 1786 |
"id": 14,
|
| 1787 |
"name": "RIGHT_ELBOW",
|
| 1788 |
-
"x": 0.
|
| 1789 |
-
"y": 0.
|
| 1790 |
-
"z": -0.
|
| 1791 |
-
"visibility": 0.
|
| 1792 |
},
|
| 1793 |
{
|
| 1794 |
"id": 15,
|
| 1795 |
"name": "LEFT_WRIST",
|
| 1796 |
-
"x": 0.
|
| 1797 |
-
"y": 0.
|
| 1798 |
-
"z": -0.
|
| 1799 |
-
"visibility": 0.
|
| 1800 |
},
|
| 1801 |
{
|
| 1802 |
"id": 16,
|
| 1803 |
"name": "RIGHT_WRIST",
|
| 1804 |
-
"x": 0.
|
| 1805 |
-
"y": 0.
|
| 1806 |
-
"z": -0.
|
| 1807 |
-
"visibility": 0.
|
| 1808 |
},
|
| 1809 |
{
|
| 1810 |
"id": 17,
|
| 1811 |
"name": "LEFT_PINKY",
|
| 1812 |
-
"x": 0.
|
| 1813 |
-
"y": 0.
|
| 1814 |
-
"z": -0.
|
| 1815 |
-
"visibility": 0.
|
| 1816 |
},
|
| 1817 |
{
|
| 1818 |
"id": 18,
|
| 1819 |
"name": "RIGHT_PINKY",
|
| 1820 |
-
"x": 0.
|
| 1821 |
-
"y": 0.
|
| 1822 |
-
"z": -0.
|
| 1823 |
-
"visibility": 0.
|
| 1824 |
},
|
| 1825 |
{
|
| 1826 |
"id": 19,
|
| 1827 |
"name": "LEFT_INDEX",
|
| 1828 |
-
"x": 0.
|
| 1829 |
-
"y": 0.
|
| 1830 |
-
"z": -0.
|
| 1831 |
-
"visibility": 0.
|
| 1832 |
},
|
| 1833 |
{
|
| 1834 |
"id": 20,
|
| 1835 |
"name": "RIGHT_INDEX",
|
| 1836 |
-
"x": 0.
|
| 1837 |
-
"y": 0.
|
| 1838 |
-
"z": -0.
|
| 1839 |
-
"visibility": 0.
|
| 1840 |
},
|
| 1841 |
{
|
| 1842 |
"id": 21,
|
| 1843 |
"name": "LEFT_THUMB",
|
| 1844 |
-
"x": 0.
|
| 1845 |
-
"y": 0.
|
| 1846 |
-
"z": -0.
|
| 1847 |
-
"visibility": 0.
|
| 1848 |
},
|
| 1849 |
{
|
| 1850 |
"id": 22,
|
| 1851 |
"name": "RIGHT_THUMB",
|
| 1852 |
-
"x": 0.
|
| 1853 |
-
"y": 0.
|
| 1854 |
-
"z": -0.
|
| 1855 |
-
"visibility": 0.
|
| 1856 |
},
|
| 1857 |
{
|
| 1858 |
"id": 23,
|
| 1859 |
"name": "LEFT_HIP",
|
| 1860 |
-
"x": 0.
|
| 1861 |
-
"y": 0.
|
| 1862 |
-
"z": 0.
|
| 1863 |
-
"visibility":
|
| 1864 |
},
|
| 1865 |
{
|
| 1866 |
"id": 24,
|
| 1867 |
"name": "RIGHT_HIP",
|
| 1868 |
-
"x": 0.
|
| 1869 |
-
"y": 0.
|
| 1870 |
-
"z":
|
| 1871 |
-
"visibility":
|
| 1872 |
},
|
| 1873 |
{
|
| 1874 |
"id": 25,
|
| 1875 |
"name": "LEFT_KNEE",
|
| 1876 |
-
"x": 0.
|
| 1877 |
-
"y": 0.
|
| 1878 |
-
"z": -0.
|
| 1879 |
-
"visibility": 0.
|
| 1880 |
},
|
| 1881 |
{
|
| 1882 |
"id": 26,
|
| 1883 |
"name": "RIGHT_KNEE",
|
| 1884 |
-
"x": 0.
|
| 1885 |
-
"y": 0.
|
| 1886 |
-
"z": -0.
|
| 1887 |
-
"visibility": 0.
|
| 1888 |
},
|
| 1889 |
{
|
| 1890 |
"id": 27,
|
| 1891 |
"name": "LEFT_ANKLE",
|
| 1892 |
-
"x": 0.
|
| 1893 |
-
"y": 0.
|
| 1894 |
-
"z": 0.
|
| 1895 |
-
"visibility": 0.
|
| 1896 |
},
|
| 1897 |
{
|
| 1898 |
"id": 28,
|
| 1899 |
"name": "RIGHT_ANKLE",
|
| 1900 |
-
"x": 0.
|
| 1901 |
-
"y": 0.
|
| 1902 |
-
"z": 0.
|
| 1903 |
-
"visibility": 0.
|
| 1904 |
},
|
| 1905 |
{
|
| 1906 |
"id": 29,
|
| 1907 |
"name": "LEFT_HEEL",
|
| 1908 |
-
"x": 0.
|
| 1909 |
-
"y": 0.
|
| 1910 |
-
"z": 0.
|
| 1911 |
-
"visibility": 0.
|
| 1912 |
},
|
| 1913 |
{
|
| 1914 |
"id": 30,
|
| 1915 |
"name": "RIGHT_HEEL",
|
| 1916 |
-
"x": 0.
|
| 1917 |
-
"y": 0.
|
| 1918 |
-
"z": 0.
|
| 1919 |
-
"visibility": 0.
|
| 1920 |
},
|
| 1921 |
{
|
| 1922 |
"id": 31,
|
| 1923 |
"name": "LEFT_FOOT_INDEX",
|
| 1924 |
-
"x": 0.
|
| 1925 |
-
"y": 0.
|
| 1926 |
-
"z": -0.
|
| 1927 |
-
"visibility": 0.
|
| 1928 |
},
|
| 1929 |
{
|
| 1930 |
"id": 32,
|
| 1931 |
"name": "RIGHT_FOOT_INDEX",
|
| 1932 |
-
"x": 0.
|
| 1933 |
-
"y": 0.
|
| 1934 |
-
"z": -0.
|
| 1935 |
-
"visibility": 0.
|
| 1936 |
}
|
| 1937 |
]
|
| 1938 |
},
|
| 1939 |
"8_Finish": {
|
| 1940 |
-
"score": 10
|
| 1941 |
"comments": [
|
| 1942 |
"Đạt chuẩn"
|
| 1943 |
],
|
|
@@ -1946,290 +1946,288 @@
|
|
| 1946 |
{
|
| 1947 |
"id": 0,
|
| 1948 |
"name": "NOSE",
|
| 1949 |
-
"x": 0.
|
| 1950 |
-
"y": 0.
|
| 1951 |
-
"z": 0.
|
| 1952 |
"visibility": 0.9998
|
| 1953 |
},
|
| 1954 |
{
|
| 1955 |
"id": 1,
|
| 1956 |
"name": "LEFT_EYE_INNER",
|
| 1957 |
-
"x": 0.
|
| 1958 |
-
"y": 0.
|
| 1959 |
-
"z": 0.
|
| 1960 |
-
"visibility": 0.
|
| 1961 |
},
|
| 1962 |
{
|
| 1963 |
"id": 2,
|
| 1964 |
"name": "LEFT_EYE",
|
| 1965 |
-
"x": 0.
|
| 1966 |
-
"y": 0.
|
| 1967 |
-
"z": 0.
|
| 1968 |
-
"visibility": 0.
|
| 1969 |
},
|
| 1970 |
{
|
| 1971 |
"id": 3,
|
| 1972 |
"name": "LEFT_EYE_OUTER",
|
| 1973 |
-
"x": 0.
|
| 1974 |
-
"y": 0.
|
| 1975 |
-
"z": 0.
|
| 1976 |
-
"visibility": 0.
|
| 1977 |
},
|
| 1978 |
{
|
| 1979 |
"id": 4,
|
| 1980 |
"name": "RIGHT_EYE_INNER",
|
| 1981 |
-
"x": 0.
|
| 1982 |
-
"y": 0.
|
| 1983 |
-
"z": -0.
|
| 1984 |
"visibility": 0.9999
|
| 1985 |
},
|
| 1986 |
{
|
| 1987 |
"id": 5,
|
| 1988 |
"name": "RIGHT_EYE",
|
| 1989 |
-
"x": 0.
|
| 1990 |
-
"y": 0.
|
| 1991 |
-
"z": -0.
|
| 1992 |
"visibility": 0.9999
|
| 1993 |
},
|
| 1994 |
{
|
| 1995 |
"id": 6,
|
| 1996 |
"name": "RIGHT_EYE_OUTER",
|
| 1997 |
-
"x": 0.
|
| 1998 |
-
"y": 0.
|
| 1999 |
-
"z": -0.
|
| 2000 |
"visibility": 0.9999
|
| 2001 |
},
|
| 2002 |
{
|
| 2003 |
"id": 7,
|
| 2004 |
"name": "LEFT_EAR",
|
| 2005 |
-
"x": 0.
|
| 2006 |
-
"y": 0.
|
| 2007 |
-
"z": 0.
|
| 2008 |
-
"visibility": 0.
|
| 2009 |
},
|
| 2010 |
{
|
| 2011 |
"id": 8,
|
| 2012 |
"name": "RIGHT_EAR",
|
| 2013 |
-
"x": 0.
|
| 2014 |
-
"y": 0.
|
| 2015 |
-
"z": -0.
|
| 2016 |
-
"visibility": 0.
|
| 2017 |
},
|
| 2018 |
{
|
| 2019 |
"id": 9,
|
| 2020 |
"name": "MOUTH_LEFT",
|
| 2021 |
-
"x": 0.
|
| 2022 |
-
"y": 0.
|
| 2023 |
-
"z": 0.
|
| 2024 |
-
"visibility": 0.
|
| 2025 |
},
|
| 2026 |
{
|
| 2027 |
"id": 10,
|
| 2028 |
"name": "MOUTH_RIGHT",
|
| 2029 |
-
"x": 0.
|
| 2030 |
-
"y": 0.
|
| 2031 |
-
"z": -0.
|
| 2032 |
-
"visibility": 0.
|
| 2033 |
},
|
| 2034 |
{
|
| 2035 |
"id": 11,
|
| 2036 |
"name": "LEFT_SHOULDER",
|
| 2037 |
-
"x": 0.
|
| 2038 |
-
"y": 0.
|
| 2039 |
-
"z": 0.
|
| 2040 |
-
"visibility": 0.
|
| 2041 |
},
|
| 2042 |
{
|
| 2043 |
"id": 12,
|
| 2044 |
"name": "RIGHT_SHOULDER",
|
| 2045 |
-
"x": 0.
|
| 2046 |
-
"y": 0.
|
| 2047 |
-
"z": -0.
|
| 2048 |
-
"visibility": 0.
|
| 2049 |
},
|
| 2050 |
{
|
| 2051 |
"id": 13,
|
| 2052 |
"name": "LEFT_ELBOW",
|
| 2053 |
-
"x": 0.
|
| 2054 |
-
"y": 0.
|
| 2055 |
-
"z": 0.
|
| 2056 |
-
"visibility": 0.
|
| 2057 |
},
|
| 2058 |
{
|
| 2059 |
"id": 14,
|
| 2060 |
"name": "RIGHT_ELBOW",
|
| 2061 |
-
"x": 0.
|
| 2062 |
-
"y": 0.
|
| 2063 |
-
"z": -0.
|
| 2064 |
-
"visibility": 0.
|
| 2065 |
},
|
| 2066 |
{
|
| 2067 |
"id": 15,
|
| 2068 |
"name": "LEFT_WRIST",
|
| 2069 |
-
"x": 0.
|
| 2070 |
-
"y": 0.
|
| 2071 |
-
"z": 0.
|
| 2072 |
-
"visibility": 0.
|
| 2073 |
},
|
| 2074 |
{
|
| 2075 |
"id": 16,
|
| 2076 |
"name": "RIGHT_WRIST",
|
| 2077 |
-
"x": 0.
|
| 2078 |
-
"y": 0.
|
| 2079 |
-
"z": -0.
|
| 2080 |
-
"visibility": 0.
|
| 2081 |
},
|
| 2082 |
{
|
| 2083 |
"id": 17,
|
| 2084 |
"name": "LEFT_PINKY",
|
| 2085 |
-
"x": 0.
|
| 2086 |
-
"y": 0.
|
| 2087 |
-
"z": 0.
|
| 2088 |
-
"visibility": 0.
|
| 2089 |
},
|
| 2090 |
{
|
| 2091 |
"id": 18,
|
| 2092 |
"name": "RIGHT_PINKY",
|
| 2093 |
-
"x": 0.
|
| 2094 |
-
"y": 0.
|
| 2095 |
-
"z": -0.
|
| 2096 |
-
"visibility": 0.
|
| 2097 |
},
|
| 2098 |
{
|
| 2099 |
"id": 19,
|
| 2100 |
"name": "LEFT_INDEX",
|
| 2101 |
-
"x": 0.
|
| 2102 |
-
"y": 0.
|
| 2103 |
-
"z": 0.
|
| 2104 |
-
"visibility": 0.
|
| 2105 |
},
|
| 2106 |
{
|
| 2107 |
"id": 20,
|
| 2108 |
"name": "RIGHT_INDEX",
|
| 2109 |
-
"x": 0.
|
| 2110 |
-
"y": 0.
|
| 2111 |
-
"z": -0.
|
| 2112 |
-
"visibility": 0.
|
| 2113 |
},
|
| 2114 |
{
|
| 2115 |
"id": 21,
|
| 2116 |
"name": "LEFT_THUMB",
|
| 2117 |
-
"x": 0.
|
| 2118 |
-
"y": 0.
|
| 2119 |
-
"z": 0.
|
| 2120 |
-
"visibility": 0.
|
| 2121 |
},
|
| 2122 |
{
|
| 2123 |
"id": 22,
|
| 2124 |
"name": "RIGHT_THUMB",
|
| 2125 |
-
"x": 0.
|
| 2126 |
-
"y": 0.
|
| 2127 |
-
"z": -0.
|
| 2128 |
-
"visibility": 0.
|
| 2129 |
},
|
| 2130 |
{
|
| 2131 |
"id": 23,
|
| 2132 |
"name": "LEFT_HIP",
|
| 2133 |
-
"x": 0.
|
| 2134 |
-
"y": 0.
|
| 2135 |
-
"z": 0.
|
| 2136 |
-
"visibility": 0.
|
| 2137 |
},
|
| 2138 |
{
|
| 2139 |
"id": 24,
|
| 2140 |
"name": "RIGHT_HIP",
|
| 2141 |
-
"x": 0.
|
| 2142 |
-
"y": 0.
|
| 2143 |
-
"z": -0.
|
| 2144 |
-
"visibility": 0.
|
| 2145 |
},
|
| 2146 |
{
|
| 2147 |
"id": 25,
|
| 2148 |
"name": "LEFT_KNEE",
|
| 2149 |
-
"x": 0.
|
| 2150 |
-
"y": 0.
|
| 2151 |
-
"z": 0.
|
| 2152 |
-
"visibility": 0.
|
| 2153 |
},
|
| 2154 |
{
|
| 2155 |
"id": 26,
|
| 2156 |
"name": "RIGHT_KNEE",
|
| 2157 |
-
"x": 0.
|
| 2158 |
-
"y": 0.
|
| 2159 |
-
"z": -0.
|
| 2160 |
-
"visibility": 0.
|
| 2161 |
},
|
| 2162 |
{
|
| 2163 |
"id": 27,
|
| 2164 |
"name": "LEFT_ANKLE",
|
| 2165 |
-
"x": 0.
|
| 2166 |
-
"y": 0.
|
| 2167 |
-
"z": 0.
|
| 2168 |
-
"visibility": 0.
|
| 2169 |
},
|
| 2170 |
{
|
| 2171 |
"id": 28,
|
| 2172 |
"name": "RIGHT_ANKLE",
|
| 2173 |
-
"x": 0.
|
| 2174 |
-
"y": 0.
|
| 2175 |
-
"z": -0.
|
| 2176 |
-
"visibility": 0.
|
| 2177 |
},
|
| 2178 |
{
|
| 2179 |
"id": 29,
|
| 2180 |
"name": "LEFT_HEEL",
|
| 2181 |
-
"x": 0.
|
| 2182 |
-
"y": 0.
|
| 2183 |
-
"z": 0.
|
| 2184 |
-
"visibility": 0.
|
| 2185 |
},
|
| 2186 |
{
|
| 2187 |
"id": 30,
|
| 2188 |
"name": "RIGHT_HEEL",
|
| 2189 |
-
"x": 0.
|
| 2190 |
-
"y": 0.
|
| 2191 |
-
"z": -0.
|
| 2192 |
-
"visibility": 0.
|
| 2193 |
},
|
| 2194 |
{
|
| 2195 |
"id": 31,
|
| 2196 |
"name": "LEFT_FOOT_INDEX",
|
| 2197 |
-
"x": 0.
|
| 2198 |
-
"y": 0.
|
| 2199 |
-
"z": 0.
|
| 2200 |
-
"visibility": 0.
|
| 2201 |
},
|
| 2202 |
{
|
| 2203 |
"id": 32,
|
| 2204 |
"name": "RIGHT_FOOT_INDEX",
|
| 2205 |
-
"x": 0.
|
| 2206 |
-
"y": 0.
|
| 2207 |
-
"z": -0.
|
| 2208 |
-
"visibility": 0.
|
| 2209 |
}
|
| 2210 |
]
|
| 2211 |
}
|
| 2212 |
},
|
| 2213 |
-
"overall_score":
|
| 2214 |
-
"view_angle": "
|
| 2215 |
},
|
| 2216 |
"coaching": {
|
| 2217 |
-
"video_id": "
|
| 2218 |
-
"final_score":
|
| 2219 |
"skill_level": "Professional / Low Handicap",
|
| 2220 |
"key_faults": [
|
| 2221 |
-
"[1_Address]
|
| 2222 |
"[2_Toe-up] Đạt chuẩn",
|
| 2223 |
"[3_Mid-Backswing] Đạt chuẩn",
|
| 2224 |
-
"[4_Top]
|
| 2225 |
"[5_Mid-Downswing] Đạt chuẩn",
|
| 2226 |
"[6_Impact] Đạt chuẩn",
|
| 2227 |
"[7_Mid-Follow-Through] Đạt chuẩn",
|
| 2228 |
"[8_Finish] Đạt chuẩn"
|
| 2229 |
],
|
| 2230 |
-
"recommended_drills": [
|
| 2231 |
-
|
| 2232 |
-
],
|
| 2233 |
-
"summary": "Điểm kỹ thuật của bạn đạt 9.5/10. Kỹ thuật của bạn khá tốt, chỉ cần tinh chỉnh một vài chi tiết nhỏ. Lỗi ưu tiên cần sửa: Tư thế đứng quá rộng."
|
| 2234 |
}
|
| 2235 |
}
|
|
|
|
| 1 |
{
|
| 2 |
"status": "success",
|
| 3 |
+
"job_id": "d907f221-0b2f-44cd-9af8-cb4921bb13bb",
|
| 4 |
"metadata": {
|
| 5 |
"event_frames": {
|
| 6 |
+
"1_Address": 0,
|
| 7 |
+
"2_Toe-up": 0,
|
| 8 |
+
"3_Mid-Backswing": 0,
|
| 9 |
+
"4_Top": 0,
|
| 10 |
+
"5_Mid-Downswing": 0,
|
| 11 |
+
"6_Impact": 0,
|
| 12 |
+
"7_Mid-Follow-Through": 34,
|
| 13 |
+
"8_Finish": 98
|
| 14 |
},
|
| 15 |
+
"slow_factor": 1,
|
| 16 |
+
"fps": 30
|
| 17 |
},
|
| 18 |
"analysis": {
|
| 19 |
+
"video_id": "d907f221-0b2f-44cd-9af8-cb4921bb13bb",
|
| 20 |
"phases": {
|
| 21 |
"1_Address": {
|
| 22 |
+
"score": 10,
|
| 23 |
"comments": [
|
| 24 |
+
"Đạt chuẩn"
|
| 25 |
],
|
| 26 |
"data": {
|
| 27 |
+
"stance_ratio": 1.3912659454869785
|
| 28 |
},
|
| 29 |
"raw_landmarks": [
|
| 30 |
{
|
| 31 |
"id": 0,
|
| 32 |
"name": "NOSE",
|
| 33 |
+
"x": 0.5452,
|
| 34 |
+
"y": 0.5194,
|
| 35 |
+
"z": -0.5827,
|
| 36 |
+
"visibility": 1
|
| 37 |
},
|
| 38 |
{
|
| 39 |
"id": 1,
|
| 40 |
"name": "LEFT_EYE_INNER",
|
| 41 |
+
"x": 0.5509,
|
| 42 |
+
"y": 0.5123,
|
| 43 |
+
"z": -0.5868,
|
| 44 |
+
"visibility": 1
|
| 45 |
},
|
| 46 |
{
|
| 47 |
"id": 2,
|
| 48 |
"name": "LEFT_EYE",
|
| 49 |
+
"x": 0.5553,
|
| 50 |
+
"y": 0.5111,
|
| 51 |
+
"z": -0.5867,
|
| 52 |
+
"visibility": 0.9999
|
| 53 |
},
|
| 54 |
{
|
| 55 |
"id": 3,
|
| 56 |
"name": "LEFT_EYE_OUTER",
|
| 57 |
+
"x": 0.5596,
|
| 58 |
+
"y": 0.5099,
|
| 59 |
+
"z": -0.5867,
|
| 60 |
+
"visibility": 0.9999
|
| 61 |
},
|
| 62 |
{
|
| 63 |
"id": 4,
|
| 64 |
"name": "RIGHT_EYE_INNER",
|
| 65 |
+
"x": 0.5385,
|
| 66 |
+
"y": 0.5137,
|
| 67 |
+
"z": -0.5845,
|
| 68 |
+
"visibility": 1
|
| 69 |
},
|
| 70 |
{
|
| 71 |
"id": 5,
|
| 72 |
"name": "RIGHT_EYE",
|
| 73 |
+
"x": 0.5341,
|
| 74 |
+
"y": 0.5134,
|
| 75 |
+
"z": -0.5847,
|
| 76 |
+
"visibility": 1
|
| 77 |
},
|
| 78 |
{
|
| 79 |
"id": 6,
|
| 80 |
"name": "RIGHT_EYE_OUTER",
|
| 81 |
+
"x": 0.5296,
|
| 82 |
+
"y": 0.513,
|
| 83 |
+
"z": -0.5849,
|
| 84 |
+
"visibility": 1
|
| 85 |
},
|
| 86 |
{
|
| 87 |
"id": 7,
|
| 88 |
"name": "LEFT_EAR",
|
| 89 |
+
"x": 0.5626,
|
| 90 |
+
"y": 0.5054,
|
| 91 |
+
"z": -0.493,
|
| 92 |
+
"visibility": 0.9999
|
| 93 |
},
|
| 94 |
{
|
| 95 |
"id": 8,
|
| 96 |
"name": "RIGHT_EAR",
|
| 97 |
+
"x": 0.5201,
|
| 98 |
+
"y": 0.508,
|
| 99 |
+
"z": -0.4836,
|
| 100 |
+
"visibility": 1
|
| 101 |
},
|
| 102 |
{
|
| 103 |
"id": 9,
|
| 104 |
"name": "MOUTH_LEFT",
|
| 105 |
+
"x": 0.552,
|
| 106 |
+
"y": 0.521,
|
| 107 |
+
"z": -0.5366,
|
| 108 |
+
"visibility": 1
|
| 109 |
},
|
| 110 |
{
|
| 111 |
"id": 10,
|
| 112 |
"name": "MOUTH_RIGHT",
|
| 113 |
+
"x": 0.5369,
|
| 114 |
+
"y": 0.5218,
|
| 115 |
+
"z": -0.5344,
|
| 116 |
+
"visibility": 1
|
| 117 |
},
|
| 118 |
{
|
| 119 |
"id": 11,
|
| 120 |
"name": "LEFT_SHOULDER",
|
| 121 |
+
"x": 0.602,
|
| 122 |
+
"y": 0.5248,
|
| 123 |
+
"z": -0.3651,
|
| 124 |
+
"visibility": 1
|
| 125 |
},
|
| 126 |
{
|
| 127 |
"id": 12,
|
| 128 |
"name": "RIGHT_SHOULDER",
|
| 129 |
+
"x": 0.4712,
|
| 130 |
+
"y": 0.5315,
|
| 131 |
+
"z": -0.3288,
|
| 132 |
+
"visibility": 1
|
| 133 |
},
|
| 134 |
{
|
| 135 |
"id": 13,
|
| 136 |
"name": "LEFT_ELBOW",
|
| 137 |
+
"x": 0.584,
|
| 138 |
+
"y": 0.5799,
|
| 139 |
+
"z": -0.3018,
|
| 140 |
+
"visibility": 0.9806
|
| 141 |
},
|
| 142 |
{
|
| 143 |
"id": 14,
|
| 144 |
"name": "RIGHT_ELBOW",
|
| 145 |
+
"x": 0.4933,
|
| 146 |
+
"y": 0.5926,
|
| 147 |
+
"z": -0.2602,
|
| 148 |
+
"visibility": 0.9898
|
| 149 |
},
|
| 150 |
{
|
| 151 |
"id": 15,
|
| 152 |
"name": "LEFT_WRIST",
|
| 153 |
+
"x": 0.5475,
|
| 154 |
+
"y": 0.6287,
|
| 155 |
+
"z": -0.3638,
|
| 156 |
+
"visibility": 0.968
|
| 157 |
},
|
| 158 |
{
|
| 159 |
"id": 16,
|
| 160 |
"name": "RIGHT_WRIST",
|
| 161 |
+
"x": 0.5229,
|
| 162 |
+
"y": 0.6379,
|
| 163 |
+
"z": -0.3363,
|
| 164 |
+
"visibility": 0.98
|
| 165 |
},
|
| 166 |
{
|
| 167 |
"id": 17,
|
| 168 |
"name": "LEFT_PINKY",
|
| 169 |
+
"x": 0.5475,
|
| 170 |
+
"y": 0.6448,
|
| 171 |
+
"z": -0.3947,
|
| 172 |
+
"visibility": 0.9426
|
| 173 |
},
|
| 174 |
{
|
| 175 |
"id": 18,
|
| 176 |
"name": "RIGHT_PINKY",
|
| 177 |
+
"x": 0.529,
|
| 178 |
+
"y": 0.6524,
|
| 179 |
+
"z": -0.3639,
|
| 180 |
+
"visibility": 0.9546
|
| 181 |
},
|
| 182 |
{
|
| 183 |
"id": 19,
|
| 184 |
"name": "LEFT_INDEX",
|
| 185 |
+
"x": 0.5399,
|
| 186 |
+
"y": 0.6458,
|
| 187 |
+
"z": -0.4222,
|
| 188 |
+
"visibility": 0.9451
|
| 189 |
},
|
| 190 |
{
|
| 191 |
"id": 20,
|
| 192 |
"name": "RIGHT_INDEX",
|
| 193 |
+
"x": 0.5351,
|
| 194 |
+
"y": 0.6513,
|
| 195 |
+
"z": -0.3988,
|
| 196 |
+
"visibility": 0.958
|
| 197 |
},
|
| 198 |
{
|
| 199 |
"id": 21,
|
| 200 |
"name": "LEFT_THUMB",
|
| 201 |
+
"x": 0.5387,
|
| 202 |
+
"y": 0.6405,
|
| 203 |
+
"z": -0.3737,
|
| 204 |
+
"visibility": 0.9237
|
| 205 |
},
|
| 206 |
{
|
| 207 |
"id": 22,
|
| 208 |
"name": "RIGHT_THUMB",
|
| 209 |
+
"x": 0.5338,
|
| 210 |
+
"y": 0.646,
|
| 211 |
+
"z": -0.3491,
|
| 212 |
+
"visibility": 0.9522
|
| 213 |
},
|
| 214 |
{
|
| 215 |
"id": 23,
|
| 216 |
"name": "LEFT_HIP",
|
| 217 |
+
"x": 0.5697,
|
| 218 |
+
"y": 0.5977,
|
| 219 |
+
"z": -0.0158,
|
| 220 |
+
"visibility": 1
|
| 221 |
},
|
| 222 |
{
|
| 223 |
"id": 24,
|
| 224 |
"name": "RIGHT_HIP",
|
| 225 |
+
"x": 0.5028,
|
| 226 |
+
"y": 0.5995,
|
| 227 |
+
"z": 0.0155,
|
| 228 |
+
"visibility": 1
|
| 229 |
},
|
| 230 |
{
|
| 231 |
"id": 25,
|
| 232 |
"name": "LEFT_KNEE",
|
| 233 |
+
"x": 0.5888,
|
| 234 |
+
"y": 0.6708,
|
| 235 |
+
"z": -0.0782,
|
| 236 |
+
"visibility": 0.9769
|
| 237 |
},
|
| 238 |
{
|
| 239 |
"id": 26,
|
| 240 |
"name": "RIGHT_KNEE",
|
| 241 |
+
"x": 0.4641,
|
| 242 |
+
"y": 0.6745,
|
| 243 |
+
"z": -0.0431,
|
| 244 |
+
"visibility": 0.9759
|
| 245 |
},
|
| 246 |
{
|
| 247 |
"id": 27,
|
| 248 |
"name": "LEFT_ANKLE",
|
| 249 |
+
"x": 0.6158,
|
| 250 |
+
"y": 0.7507,
|
| 251 |
+
"z": -0.0037,
|
| 252 |
+
"visibility": 0.9864
|
| 253 |
},
|
| 254 |
{
|
| 255 |
"id": 28,
|
| 256 |
"name": "RIGHT_ANKLE",
|
| 257 |
+
"x": 0.4338,
|
| 258 |
+
"y": 0.7489,
|
| 259 |
+
"z": 0.0473,
|
| 260 |
+
"visibility": 0.9817
|
| 261 |
},
|
| 262 |
{
|
| 263 |
"id": 29,
|
| 264 |
"name": "LEFT_HEEL",
|
| 265 |
+
"x": 0.6155,
|
| 266 |
+
"y": 0.7593,
|
| 267 |
+
"z": -0.0068,
|
| 268 |
+
"visibility": 0.8259
|
| 269 |
},
|
| 270 |
{
|
| 271 |
"id": 30,
|
| 272 |
"name": "RIGHT_HEEL",
|
| 273 |
+
"x": 0.4388,
|
| 274 |
+
"y": 0.7566,
|
| 275 |
+
"z": 0.0478,
|
| 276 |
+
"visibility": 0.8404
|
| 277 |
},
|
| 278 |
{
|
| 279 |
"id": 31,
|
| 280 |
"name": "LEFT_FOOT_INDEX",
|
| 281 |
+
"x": 0.6305,
|
| 282 |
+
"y": 0.7788,
|
| 283 |
+
"z": -0.1656,
|
| 284 |
+
"visibility": 0.9763
|
| 285 |
},
|
| 286 |
{
|
| 287 |
"id": 32,
|
| 288 |
"name": "RIGHT_FOOT_INDEX",
|
| 289 |
+
"x": 0.4196,
|
| 290 |
+
"y": 0.7767,
|
| 291 |
+
"z": -0.0952,
|
| 292 |
+
"visibility": 0.978
|
| 293 |
}
|
| 294 |
]
|
| 295 |
},
|
| 296 |
"2_Toe-up": {
|
| 297 |
+
"score": 10,
|
| 298 |
"comments": [
|
| 299 |
"Đạt chuẩn"
|
| 300 |
],
|
|
|
|
| 303 |
{
|
| 304 |
"id": 0,
|
| 305 |
"name": "NOSE",
|
| 306 |
+
"x": 0.5452,
|
| 307 |
+
"y": 0.5194,
|
| 308 |
+
"z": -0.5827,
|
| 309 |
+
"visibility": 1
|
| 310 |
},
|
| 311 |
{
|
| 312 |
"id": 1,
|
| 313 |
"name": "LEFT_EYE_INNER",
|
| 314 |
+
"x": 0.5509,
|
| 315 |
+
"y": 0.5123,
|
| 316 |
+
"z": -0.5868,
|
| 317 |
+
"visibility": 1
|
| 318 |
},
|
| 319 |
{
|
| 320 |
"id": 2,
|
| 321 |
"name": "LEFT_EYE",
|
| 322 |
+
"x": 0.5553,
|
| 323 |
+
"y": 0.5111,
|
| 324 |
+
"z": -0.5867,
|
| 325 |
+
"visibility": 0.9999
|
| 326 |
},
|
| 327 |
{
|
| 328 |
"id": 3,
|
| 329 |
"name": "LEFT_EYE_OUTER",
|
| 330 |
+
"x": 0.5596,
|
| 331 |
+
"y": 0.5099,
|
| 332 |
+
"z": -0.5867,
|
| 333 |
+
"visibility": 0.9999
|
| 334 |
},
|
| 335 |
{
|
| 336 |
"id": 4,
|
| 337 |
"name": "RIGHT_EYE_INNER",
|
| 338 |
+
"x": 0.5385,
|
| 339 |
+
"y": 0.5137,
|
| 340 |
+
"z": -0.5845,
|
| 341 |
+
"visibility": 1
|
| 342 |
},
|
| 343 |
{
|
| 344 |
"id": 5,
|
| 345 |
"name": "RIGHT_EYE",
|
| 346 |
+
"x": 0.5341,
|
| 347 |
+
"y": 0.5134,
|
| 348 |
+
"z": -0.5847,
|
| 349 |
+
"visibility": 1
|
| 350 |
},
|
| 351 |
{
|
| 352 |
"id": 6,
|
| 353 |
"name": "RIGHT_EYE_OUTER",
|
| 354 |
+
"x": 0.5296,
|
| 355 |
+
"y": 0.513,
|
| 356 |
+
"z": -0.5849,
|
| 357 |
+
"visibility": 1
|
| 358 |
},
|
| 359 |
{
|
| 360 |
"id": 7,
|
| 361 |
"name": "LEFT_EAR",
|
| 362 |
+
"x": 0.5626,
|
| 363 |
+
"y": 0.5054,
|
| 364 |
+
"z": -0.493,
|
| 365 |
+
"visibility": 0.9999
|
| 366 |
},
|
| 367 |
{
|
| 368 |
"id": 8,
|
| 369 |
"name": "RIGHT_EAR",
|
| 370 |
+
"x": 0.5201,
|
| 371 |
+
"y": 0.508,
|
| 372 |
+
"z": -0.4836,
|
| 373 |
+
"visibility": 1
|
| 374 |
},
|
| 375 |
{
|
| 376 |
"id": 9,
|
| 377 |
"name": "MOUTH_LEFT",
|
| 378 |
+
"x": 0.552,
|
| 379 |
+
"y": 0.521,
|
| 380 |
+
"z": -0.5366,
|
| 381 |
+
"visibility": 1
|
| 382 |
},
|
| 383 |
{
|
| 384 |
"id": 10,
|
| 385 |
"name": "MOUTH_RIGHT",
|
| 386 |
+
"x": 0.5369,
|
| 387 |
+
"y": 0.5218,
|
| 388 |
+
"z": -0.5344,
|
| 389 |
+
"visibility": 1
|
| 390 |
},
|
| 391 |
{
|
| 392 |
"id": 11,
|
| 393 |
"name": "LEFT_SHOULDER",
|
| 394 |
+
"x": 0.602,
|
| 395 |
+
"y": 0.5248,
|
| 396 |
+
"z": -0.3651,
|
| 397 |
+
"visibility": 1
|
| 398 |
},
|
| 399 |
{
|
| 400 |
"id": 12,
|
| 401 |
"name": "RIGHT_SHOULDER",
|
| 402 |
+
"x": 0.4712,
|
| 403 |
+
"y": 0.5315,
|
| 404 |
+
"z": -0.3288,
|
| 405 |
+
"visibility": 1
|
| 406 |
},
|
| 407 |
{
|
| 408 |
"id": 13,
|
| 409 |
"name": "LEFT_ELBOW",
|
| 410 |
+
"x": 0.584,
|
| 411 |
+
"y": 0.5799,
|
| 412 |
+
"z": -0.3018,
|
| 413 |
+
"visibility": 0.9806
|
| 414 |
},
|
| 415 |
{
|
| 416 |
"id": 14,
|
| 417 |
"name": "RIGHT_ELBOW",
|
| 418 |
+
"x": 0.4933,
|
| 419 |
+
"y": 0.5926,
|
| 420 |
+
"z": -0.2602,
|
| 421 |
+
"visibility": 0.9898
|
| 422 |
},
|
| 423 |
{
|
| 424 |
"id": 15,
|
| 425 |
"name": "LEFT_WRIST",
|
| 426 |
+
"x": 0.5475,
|
| 427 |
+
"y": 0.6287,
|
| 428 |
+
"z": -0.3638,
|
| 429 |
+
"visibility": 0.968
|
| 430 |
},
|
| 431 |
{
|
| 432 |
"id": 16,
|
| 433 |
"name": "RIGHT_WRIST",
|
| 434 |
+
"x": 0.5229,
|
| 435 |
+
"y": 0.6379,
|
| 436 |
+
"z": -0.3363,
|
| 437 |
+
"visibility": 0.98
|
| 438 |
},
|
| 439 |
{
|
| 440 |
"id": 17,
|
| 441 |
"name": "LEFT_PINKY",
|
| 442 |
+
"x": 0.5475,
|
| 443 |
+
"y": 0.6448,
|
| 444 |
+
"z": -0.3947,
|
| 445 |
+
"visibility": 0.9426
|
| 446 |
},
|
| 447 |
{
|
| 448 |
"id": 18,
|
| 449 |
"name": "RIGHT_PINKY",
|
| 450 |
+
"x": 0.529,
|
| 451 |
+
"y": 0.6524,
|
| 452 |
+
"z": -0.3639,
|
| 453 |
+
"visibility": 0.9546
|
| 454 |
},
|
| 455 |
{
|
| 456 |
"id": 19,
|
| 457 |
"name": "LEFT_INDEX",
|
| 458 |
+
"x": 0.5399,
|
| 459 |
+
"y": 0.6458,
|
| 460 |
+
"z": -0.4222,
|
| 461 |
+
"visibility": 0.9451
|
| 462 |
},
|
| 463 |
{
|
| 464 |
"id": 20,
|
| 465 |
"name": "RIGHT_INDEX",
|
| 466 |
+
"x": 0.5351,
|
| 467 |
+
"y": 0.6513,
|
| 468 |
+
"z": -0.3988,
|
| 469 |
+
"visibility": 0.958
|
| 470 |
},
|
| 471 |
{
|
| 472 |
"id": 21,
|
| 473 |
"name": "LEFT_THUMB",
|
| 474 |
+
"x": 0.5387,
|
| 475 |
+
"y": 0.6405,
|
| 476 |
+
"z": -0.3737,
|
| 477 |
+
"visibility": 0.9237
|
| 478 |
},
|
| 479 |
{
|
| 480 |
"id": 22,
|
| 481 |
"name": "RIGHT_THUMB",
|
| 482 |
+
"x": 0.5338,
|
| 483 |
+
"y": 0.646,
|
| 484 |
+
"z": -0.3491,
|
| 485 |
+
"visibility": 0.9522
|
| 486 |
},
|
| 487 |
{
|
| 488 |
"id": 23,
|
| 489 |
"name": "LEFT_HIP",
|
| 490 |
+
"x": 0.5697,
|
| 491 |
+
"y": 0.5977,
|
| 492 |
+
"z": -0.0158,
|
| 493 |
+
"visibility": 1
|
| 494 |
},
|
| 495 |
{
|
| 496 |
"id": 24,
|
| 497 |
"name": "RIGHT_HIP",
|
| 498 |
+
"x": 0.5028,
|
| 499 |
+
"y": 0.5995,
|
| 500 |
+
"z": 0.0155,
|
| 501 |
+
"visibility": 1
|
| 502 |
},
|
| 503 |
{
|
| 504 |
"id": 25,
|
| 505 |
"name": "LEFT_KNEE",
|
| 506 |
+
"x": 0.5888,
|
| 507 |
+
"y": 0.6708,
|
| 508 |
+
"z": -0.0782,
|
| 509 |
+
"visibility": 0.9769
|
| 510 |
},
|
| 511 |
{
|
| 512 |
"id": 26,
|
| 513 |
"name": "RIGHT_KNEE",
|
| 514 |
+
"x": 0.4641,
|
| 515 |
+
"y": 0.6745,
|
| 516 |
+
"z": -0.0431,
|
| 517 |
+
"visibility": 0.9759
|
| 518 |
},
|
| 519 |
{
|
| 520 |
"id": 27,
|
| 521 |
"name": "LEFT_ANKLE",
|
| 522 |
+
"x": 0.6158,
|
| 523 |
+
"y": 0.7507,
|
| 524 |
+
"z": -0.0037,
|
| 525 |
+
"visibility": 0.9864
|
| 526 |
},
|
| 527 |
{
|
| 528 |
"id": 28,
|
| 529 |
"name": "RIGHT_ANKLE",
|
| 530 |
+
"x": 0.4338,
|
| 531 |
+
"y": 0.7489,
|
| 532 |
+
"z": 0.0473,
|
| 533 |
+
"visibility": 0.9817
|
| 534 |
},
|
| 535 |
{
|
| 536 |
"id": 29,
|
| 537 |
"name": "LEFT_HEEL",
|
| 538 |
+
"x": 0.6155,
|
| 539 |
+
"y": 0.7593,
|
| 540 |
+
"z": -0.0068,
|
| 541 |
+
"visibility": 0.8259
|
| 542 |
},
|
| 543 |
{
|
| 544 |
"id": 30,
|
| 545 |
"name": "RIGHT_HEEL",
|
| 546 |
+
"x": 0.4388,
|
| 547 |
+
"y": 0.7566,
|
| 548 |
+
"z": 0.0478,
|
| 549 |
+
"visibility": 0.8404
|
| 550 |
},
|
| 551 |
{
|
| 552 |
"id": 31,
|
| 553 |
"name": "LEFT_FOOT_INDEX",
|
| 554 |
+
"x": 0.6305,
|
| 555 |
+
"y": 0.7788,
|
| 556 |
+
"z": -0.1656,
|
| 557 |
+
"visibility": 0.9763
|
| 558 |
},
|
| 559 |
{
|
| 560 |
"id": 32,
|
| 561 |
"name": "RIGHT_FOOT_INDEX",
|
| 562 |
+
"x": 0.4196,
|
| 563 |
+
"y": 0.7767,
|
| 564 |
+
"z": -0.0952,
|
| 565 |
+
"visibility": 0.978
|
| 566 |
}
|
| 567 |
]
|
| 568 |
},
|
| 569 |
"3_Mid-Backswing": {
|
| 570 |
+
"score": 10,
|
| 571 |
"comments": [
|
| 572 |
"Đạt chuẩn"
|
| 573 |
],
|
|
|
|
| 576 |
{
|
| 577 |
"id": 0,
|
| 578 |
"name": "NOSE",
|
| 579 |
+
"x": 0.5452,
|
| 580 |
+
"y": 0.5194,
|
| 581 |
+
"z": -0.5827,
|
| 582 |
+
"visibility": 1
|
| 583 |
},
|
| 584 |
{
|
| 585 |
"id": 1,
|
| 586 |
"name": "LEFT_EYE_INNER",
|
| 587 |
+
"x": 0.5509,
|
| 588 |
+
"y": 0.5123,
|
| 589 |
+
"z": -0.5868,
|
| 590 |
+
"visibility": 1
|
| 591 |
},
|
| 592 |
{
|
| 593 |
"id": 2,
|
| 594 |
"name": "LEFT_EYE",
|
| 595 |
+
"x": 0.5553,
|
| 596 |
+
"y": 0.5111,
|
| 597 |
+
"z": -0.5867,
|
| 598 |
+
"visibility": 0.9999
|
| 599 |
},
|
| 600 |
{
|
| 601 |
"id": 3,
|
| 602 |
"name": "LEFT_EYE_OUTER",
|
| 603 |
+
"x": 0.5596,
|
| 604 |
+
"y": 0.5099,
|
| 605 |
+
"z": -0.5867,
|
| 606 |
+
"visibility": 0.9999
|
| 607 |
},
|
| 608 |
{
|
| 609 |
"id": 4,
|
| 610 |
"name": "RIGHT_EYE_INNER",
|
| 611 |
+
"x": 0.5385,
|
| 612 |
+
"y": 0.5137,
|
| 613 |
+
"z": -0.5845,
|
| 614 |
+
"visibility": 1
|
| 615 |
},
|
| 616 |
{
|
| 617 |
"id": 5,
|
| 618 |
"name": "RIGHT_EYE",
|
| 619 |
+
"x": 0.5341,
|
| 620 |
+
"y": 0.5134,
|
| 621 |
+
"z": -0.5847,
|
| 622 |
+
"visibility": 1
|
| 623 |
},
|
| 624 |
{
|
| 625 |
"id": 6,
|
| 626 |
"name": "RIGHT_EYE_OUTER",
|
| 627 |
+
"x": 0.5296,
|
| 628 |
+
"y": 0.513,
|
| 629 |
+
"z": -0.5849,
|
| 630 |
+
"visibility": 1
|
| 631 |
},
|
| 632 |
{
|
| 633 |
"id": 7,
|
| 634 |
"name": "LEFT_EAR",
|
| 635 |
+
"x": 0.5626,
|
| 636 |
+
"y": 0.5054,
|
| 637 |
+
"z": -0.493,
|
| 638 |
+
"visibility": 0.9999
|
| 639 |
},
|
| 640 |
{
|
| 641 |
"id": 8,
|
| 642 |
"name": "RIGHT_EAR",
|
| 643 |
+
"x": 0.5201,
|
| 644 |
+
"y": 0.508,
|
| 645 |
+
"z": -0.4836,
|
| 646 |
+
"visibility": 1
|
| 647 |
},
|
| 648 |
{
|
| 649 |
"id": 9,
|
| 650 |
"name": "MOUTH_LEFT",
|
| 651 |
+
"x": 0.552,
|
| 652 |
+
"y": 0.521,
|
| 653 |
+
"z": -0.5366,
|
| 654 |
+
"visibility": 1
|
| 655 |
},
|
| 656 |
{
|
| 657 |
"id": 10,
|
| 658 |
"name": "MOUTH_RIGHT",
|
| 659 |
+
"x": 0.5369,
|
| 660 |
+
"y": 0.5218,
|
| 661 |
+
"z": -0.5344,
|
| 662 |
+
"visibility": 1
|
| 663 |
},
|
| 664 |
{
|
| 665 |
"id": 11,
|
| 666 |
"name": "LEFT_SHOULDER",
|
| 667 |
+
"x": 0.602,
|
| 668 |
+
"y": 0.5248,
|
| 669 |
+
"z": -0.3651,
|
| 670 |
+
"visibility": 1
|
| 671 |
},
|
| 672 |
{
|
| 673 |
"id": 12,
|
| 674 |
"name": "RIGHT_SHOULDER",
|
| 675 |
+
"x": 0.4712,
|
| 676 |
+
"y": 0.5315,
|
| 677 |
+
"z": -0.3288,
|
| 678 |
+
"visibility": 1
|
| 679 |
},
|
| 680 |
{
|
| 681 |
"id": 13,
|
| 682 |
"name": "LEFT_ELBOW",
|
| 683 |
+
"x": 0.584,
|
| 684 |
+
"y": 0.5799,
|
| 685 |
+
"z": -0.3018,
|
| 686 |
+
"visibility": 0.9806
|
| 687 |
},
|
| 688 |
{
|
| 689 |
"id": 14,
|
| 690 |
"name": "RIGHT_ELBOW",
|
| 691 |
+
"x": 0.4933,
|
| 692 |
+
"y": 0.5926,
|
| 693 |
+
"z": -0.2602,
|
| 694 |
+
"visibility": 0.9898
|
| 695 |
},
|
| 696 |
{
|
| 697 |
"id": 15,
|
| 698 |
"name": "LEFT_WRIST",
|
| 699 |
+
"x": 0.5475,
|
| 700 |
+
"y": 0.6287,
|
| 701 |
+
"z": -0.3638,
|
| 702 |
+
"visibility": 0.968
|
| 703 |
},
|
| 704 |
{
|
| 705 |
"id": 16,
|
| 706 |
"name": "RIGHT_WRIST",
|
| 707 |
+
"x": 0.5229,
|
| 708 |
+
"y": 0.6379,
|
| 709 |
+
"z": -0.3363,
|
| 710 |
+
"visibility": 0.98
|
| 711 |
},
|
| 712 |
{
|
| 713 |
"id": 17,
|
| 714 |
"name": "LEFT_PINKY",
|
| 715 |
+
"x": 0.5475,
|
| 716 |
+
"y": 0.6448,
|
| 717 |
+
"z": -0.3947,
|
| 718 |
+
"visibility": 0.9426
|
| 719 |
},
|
| 720 |
{
|
| 721 |
"id": 18,
|
| 722 |
"name": "RIGHT_PINKY",
|
| 723 |
+
"x": 0.529,
|
| 724 |
+
"y": 0.6524,
|
| 725 |
+
"z": -0.3639,
|
| 726 |
+
"visibility": 0.9546
|
| 727 |
},
|
| 728 |
{
|
| 729 |
"id": 19,
|
| 730 |
"name": "LEFT_INDEX",
|
| 731 |
+
"x": 0.5399,
|
| 732 |
+
"y": 0.6458,
|
| 733 |
+
"z": -0.4222,
|
| 734 |
+
"visibility": 0.9451
|
| 735 |
},
|
| 736 |
{
|
| 737 |
"id": 20,
|
| 738 |
"name": "RIGHT_INDEX",
|
| 739 |
+
"x": 0.5351,
|
| 740 |
+
"y": 0.6513,
|
| 741 |
+
"z": -0.3988,
|
| 742 |
+
"visibility": 0.958
|
| 743 |
},
|
| 744 |
{
|
| 745 |
"id": 21,
|
| 746 |
"name": "LEFT_THUMB",
|
| 747 |
+
"x": 0.5387,
|
| 748 |
+
"y": 0.6405,
|
| 749 |
+
"z": -0.3737,
|
| 750 |
+
"visibility": 0.9237
|
| 751 |
},
|
| 752 |
{
|
| 753 |
"id": 22,
|
| 754 |
"name": "RIGHT_THUMB",
|
| 755 |
+
"x": 0.5338,
|
| 756 |
+
"y": 0.646,
|
| 757 |
+
"z": -0.3491,
|
| 758 |
+
"visibility": 0.9522
|
| 759 |
},
|
| 760 |
{
|
| 761 |
"id": 23,
|
| 762 |
"name": "LEFT_HIP",
|
| 763 |
+
"x": 0.5697,
|
| 764 |
+
"y": 0.5977,
|
| 765 |
+
"z": -0.0158,
|
| 766 |
+
"visibility": 1
|
| 767 |
},
|
| 768 |
{
|
| 769 |
"id": 24,
|
| 770 |
"name": "RIGHT_HIP",
|
| 771 |
+
"x": 0.5028,
|
| 772 |
+
"y": 0.5995,
|
| 773 |
+
"z": 0.0155,
|
| 774 |
+
"visibility": 1
|
| 775 |
},
|
| 776 |
{
|
| 777 |
"id": 25,
|
| 778 |
"name": "LEFT_KNEE",
|
| 779 |
+
"x": 0.5888,
|
| 780 |
+
"y": 0.6708,
|
| 781 |
+
"z": -0.0782,
|
| 782 |
+
"visibility": 0.9769
|
| 783 |
},
|
| 784 |
{
|
| 785 |
"id": 26,
|
| 786 |
"name": "RIGHT_KNEE",
|
| 787 |
+
"x": 0.4641,
|
| 788 |
+
"y": 0.6745,
|
| 789 |
+
"z": -0.0431,
|
| 790 |
+
"visibility": 0.9759
|
| 791 |
},
|
| 792 |
{
|
| 793 |
"id": 27,
|
| 794 |
"name": "LEFT_ANKLE",
|
| 795 |
+
"x": 0.6158,
|
| 796 |
+
"y": 0.7507,
|
| 797 |
+
"z": -0.0037,
|
| 798 |
+
"visibility": 0.9864
|
| 799 |
},
|
| 800 |
{
|
| 801 |
"id": 28,
|
| 802 |
"name": "RIGHT_ANKLE",
|
| 803 |
+
"x": 0.4338,
|
| 804 |
+
"y": 0.7489,
|
| 805 |
+
"z": 0.0473,
|
| 806 |
+
"visibility": 0.9817
|
| 807 |
},
|
| 808 |
{
|
| 809 |
"id": 29,
|
| 810 |
"name": "LEFT_HEEL",
|
| 811 |
+
"x": 0.6155,
|
| 812 |
+
"y": 0.7593,
|
| 813 |
+
"z": -0.0068,
|
| 814 |
+
"visibility": 0.8259
|
| 815 |
},
|
| 816 |
{
|
| 817 |
"id": 30,
|
| 818 |
"name": "RIGHT_HEEL",
|
| 819 |
+
"x": 0.4388,
|
| 820 |
+
"y": 0.7566,
|
| 821 |
+
"z": 0.0478,
|
| 822 |
+
"visibility": 0.8404
|
| 823 |
},
|
| 824 |
{
|
| 825 |
"id": 31,
|
| 826 |
"name": "LEFT_FOOT_INDEX",
|
| 827 |
+
"x": 0.6305,
|
| 828 |
+
"y": 0.7788,
|
| 829 |
+
"z": -0.1656,
|
| 830 |
+
"visibility": 0.9763
|
| 831 |
},
|
| 832 |
{
|
| 833 |
"id": 32,
|
| 834 |
"name": "RIGHT_FOOT_INDEX",
|
| 835 |
+
"x": 0.4196,
|
| 836 |
+
"y": 0.7767,
|
| 837 |
+
"z": -0.0952,
|
| 838 |
+
"visibility": 0.978
|
| 839 |
}
|
| 840 |
]
|
| 841 |
},
|
| 842 |
"4_Top": {
|
| 843 |
+
"score": 10,
|
| 844 |
"comments": [
|
| 845 |
+
"Đạt chuẩn"
|
| 846 |
],
|
| 847 |
"data": {
|
| 848 |
+
"lead_arm_angle": 161.36934184577666,
|
| 849 |
+
"shoulder_tilt": 0.006613552570343018
|
| 850 |
},
|
| 851 |
"raw_landmarks": [
|
| 852 |
{
|
| 853 |
"id": 0,
|
| 854 |
"name": "NOSE",
|
| 855 |
+
"x": 0.5452,
|
| 856 |
+
"y": 0.5194,
|
| 857 |
+
"z": -0.5827,
|
| 858 |
+
"visibility": 1
|
| 859 |
},
|
| 860 |
{
|
| 861 |
"id": 1,
|
| 862 |
"name": "LEFT_EYE_INNER",
|
| 863 |
+
"x": 0.5509,
|
| 864 |
+
"y": 0.5123,
|
| 865 |
+
"z": -0.5868,
|
| 866 |
+
"visibility": 1
|
| 867 |
},
|
| 868 |
{
|
| 869 |
"id": 2,
|
| 870 |
"name": "LEFT_EYE",
|
| 871 |
+
"x": 0.5553,
|
| 872 |
+
"y": 0.5111,
|
| 873 |
+
"z": -0.5867,
|
| 874 |
+
"visibility": 0.9999
|
| 875 |
},
|
| 876 |
{
|
| 877 |
"id": 3,
|
| 878 |
"name": "LEFT_EYE_OUTER",
|
| 879 |
+
"x": 0.5596,
|
| 880 |
+
"y": 0.5099,
|
| 881 |
+
"z": -0.5867,
|
| 882 |
+
"visibility": 0.9999
|
| 883 |
},
|
| 884 |
{
|
| 885 |
"id": 4,
|
| 886 |
"name": "RIGHT_EYE_INNER",
|
| 887 |
+
"x": 0.5385,
|
| 888 |
+
"y": 0.5137,
|
| 889 |
+
"z": -0.5845,
|
| 890 |
+
"visibility": 1
|
| 891 |
},
|
| 892 |
{
|
| 893 |
"id": 5,
|
| 894 |
"name": "RIGHT_EYE",
|
| 895 |
+
"x": 0.5341,
|
| 896 |
+
"y": 0.5134,
|
| 897 |
+
"z": -0.5847,
|
| 898 |
+
"visibility": 1
|
| 899 |
},
|
| 900 |
{
|
| 901 |
"id": 6,
|
| 902 |
"name": "RIGHT_EYE_OUTER",
|
| 903 |
+
"x": 0.5296,
|
| 904 |
+
"y": 0.513,
|
| 905 |
+
"z": -0.5849,
|
| 906 |
+
"visibility": 1
|
| 907 |
},
|
| 908 |
{
|
| 909 |
"id": 7,
|
| 910 |
"name": "LEFT_EAR",
|
| 911 |
+
"x": 0.5626,
|
| 912 |
+
"y": 0.5054,
|
| 913 |
+
"z": -0.493,
|
| 914 |
+
"visibility": 0.9999
|
| 915 |
},
|
| 916 |
{
|
| 917 |
"id": 8,
|
| 918 |
"name": "RIGHT_EAR",
|
| 919 |
+
"x": 0.5201,
|
| 920 |
+
"y": 0.508,
|
| 921 |
+
"z": -0.4836,
|
| 922 |
+
"visibility": 1
|
| 923 |
},
|
| 924 |
{
|
| 925 |
"id": 9,
|
| 926 |
"name": "MOUTH_LEFT",
|
| 927 |
+
"x": 0.552,
|
| 928 |
+
"y": 0.521,
|
| 929 |
+
"z": -0.5366,
|
| 930 |
+
"visibility": 1
|
| 931 |
},
|
| 932 |
{
|
| 933 |
"id": 10,
|
| 934 |
"name": "MOUTH_RIGHT",
|
| 935 |
+
"x": 0.5369,
|
| 936 |
+
"y": 0.5218,
|
| 937 |
+
"z": -0.5344,
|
| 938 |
+
"visibility": 1
|
| 939 |
},
|
| 940 |
{
|
| 941 |
"id": 11,
|
| 942 |
"name": "LEFT_SHOULDER",
|
| 943 |
+
"x": 0.602,
|
| 944 |
+
"y": 0.5248,
|
| 945 |
+
"z": -0.3651,
|
| 946 |
+
"visibility": 1
|
| 947 |
},
|
| 948 |
{
|
| 949 |
"id": 12,
|
| 950 |
"name": "RIGHT_SHOULDER",
|
| 951 |
+
"x": 0.4712,
|
| 952 |
+
"y": 0.5315,
|
| 953 |
+
"z": -0.3288,
|
| 954 |
+
"visibility": 1
|
| 955 |
},
|
| 956 |
{
|
| 957 |
"id": 13,
|
| 958 |
"name": "LEFT_ELBOW",
|
| 959 |
+
"x": 0.584,
|
| 960 |
+
"y": 0.5799,
|
| 961 |
+
"z": -0.3018,
|
| 962 |
+
"visibility": 0.9806
|
| 963 |
},
|
| 964 |
{
|
| 965 |
"id": 14,
|
| 966 |
"name": "RIGHT_ELBOW",
|
| 967 |
+
"x": 0.4933,
|
| 968 |
+
"y": 0.5926,
|
| 969 |
+
"z": -0.2602,
|
| 970 |
+
"visibility": 0.9898
|
| 971 |
},
|
| 972 |
{
|
| 973 |
"id": 15,
|
| 974 |
"name": "LEFT_WRIST",
|
| 975 |
+
"x": 0.5475,
|
| 976 |
+
"y": 0.6287,
|
| 977 |
+
"z": -0.3638,
|
| 978 |
+
"visibility": 0.968
|
| 979 |
},
|
| 980 |
{
|
| 981 |
"id": 16,
|
| 982 |
"name": "RIGHT_WRIST",
|
| 983 |
+
"x": 0.5229,
|
| 984 |
+
"y": 0.6379,
|
| 985 |
+
"z": -0.3363,
|
| 986 |
+
"visibility": 0.98
|
| 987 |
},
|
| 988 |
{
|
| 989 |
"id": 17,
|
| 990 |
"name": "LEFT_PINKY",
|
| 991 |
+
"x": 0.5475,
|
| 992 |
+
"y": 0.6448,
|
| 993 |
+
"z": -0.3947,
|
| 994 |
+
"visibility": 0.9426
|
| 995 |
},
|
| 996 |
{
|
| 997 |
"id": 18,
|
| 998 |
"name": "RIGHT_PINKY",
|
| 999 |
+
"x": 0.529,
|
| 1000 |
+
"y": 0.6524,
|
| 1001 |
+
"z": -0.3639,
|
| 1002 |
+
"visibility": 0.9546
|
| 1003 |
},
|
| 1004 |
{
|
| 1005 |
"id": 19,
|
| 1006 |
"name": "LEFT_INDEX",
|
| 1007 |
+
"x": 0.5399,
|
| 1008 |
+
"y": 0.6458,
|
| 1009 |
+
"z": -0.4222,
|
| 1010 |
+
"visibility": 0.9451
|
| 1011 |
},
|
| 1012 |
{
|
| 1013 |
"id": 20,
|
| 1014 |
"name": "RIGHT_INDEX",
|
| 1015 |
+
"x": 0.5351,
|
| 1016 |
+
"y": 0.6513,
|
| 1017 |
+
"z": -0.3988,
|
| 1018 |
+
"visibility": 0.958
|
| 1019 |
},
|
| 1020 |
{
|
| 1021 |
"id": 21,
|
| 1022 |
"name": "LEFT_THUMB",
|
| 1023 |
+
"x": 0.5387,
|
| 1024 |
+
"y": 0.6405,
|
| 1025 |
+
"z": -0.3737,
|
| 1026 |
+
"visibility": 0.9237
|
| 1027 |
},
|
| 1028 |
{
|
| 1029 |
"id": 22,
|
| 1030 |
"name": "RIGHT_THUMB",
|
| 1031 |
+
"x": 0.5338,
|
| 1032 |
+
"y": 0.646,
|
| 1033 |
+
"z": -0.3491,
|
| 1034 |
+
"visibility": 0.9522
|
| 1035 |
},
|
| 1036 |
{
|
| 1037 |
"id": 23,
|
| 1038 |
"name": "LEFT_HIP",
|
| 1039 |
+
"x": 0.5697,
|
| 1040 |
+
"y": 0.5977,
|
| 1041 |
+
"z": -0.0158,
|
| 1042 |
+
"visibility": 1
|
| 1043 |
},
|
| 1044 |
{
|
| 1045 |
"id": 24,
|
| 1046 |
"name": "RIGHT_HIP",
|
| 1047 |
+
"x": 0.5028,
|
| 1048 |
+
"y": 0.5995,
|
| 1049 |
+
"z": 0.0155,
|
| 1050 |
+
"visibility": 1
|
| 1051 |
},
|
| 1052 |
{
|
| 1053 |
"id": 25,
|
| 1054 |
"name": "LEFT_KNEE",
|
| 1055 |
+
"x": 0.5888,
|
| 1056 |
+
"y": 0.6708,
|
| 1057 |
+
"z": -0.0782,
|
| 1058 |
+
"visibility": 0.9769
|
| 1059 |
},
|
| 1060 |
{
|
| 1061 |
"id": 26,
|
| 1062 |
"name": "RIGHT_KNEE",
|
| 1063 |
+
"x": 0.4641,
|
| 1064 |
+
"y": 0.6745,
|
| 1065 |
+
"z": -0.0431,
|
| 1066 |
+
"visibility": 0.9759
|
| 1067 |
},
|
| 1068 |
{
|
| 1069 |
"id": 27,
|
| 1070 |
"name": "LEFT_ANKLE",
|
| 1071 |
+
"x": 0.6158,
|
| 1072 |
+
"y": 0.7507,
|
| 1073 |
+
"z": -0.0037,
|
| 1074 |
+
"visibility": 0.9864
|
| 1075 |
},
|
| 1076 |
{
|
| 1077 |
"id": 28,
|
| 1078 |
"name": "RIGHT_ANKLE",
|
| 1079 |
+
"x": 0.4338,
|
| 1080 |
+
"y": 0.7489,
|
| 1081 |
+
"z": 0.0473,
|
| 1082 |
+
"visibility": 0.9817
|
| 1083 |
},
|
| 1084 |
{
|
| 1085 |
"id": 29,
|
| 1086 |
"name": "LEFT_HEEL",
|
| 1087 |
+
"x": 0.6155,
|
| 1088 |
+
"y": 0.7593,
|
| 1089 |
+
"z": -0.0068,
|
| 1090 |
+
"visibility": 0.8259
|
| 1091 |
},
|
| 1092 |
{
|
| 1093 |
"id": 30,
|
| 1094 |
"name": "RIGHT_HEEL",
|
| 1095 |
+
"x": 0.4388,
|
| 1096 |
+
"y": 0.7566,
|
| 1097 |
+
"z": 0.0478,
|
| 1098 |
+
"visibility": 0.8404
|
| 1099 |
},
|
| 1100 |
{
|
| 1101 |
"id": 31,
|
| 1102 |
"name": "LEFT_FOOT_INDEX",
|
| 1103 |
+
"x": 0.6305,
|
| 1104 |
+
"y": 0.7788,
|
| 1105 |
+
"z": -0.1656,
|
| 1106 |
"visibility": 0.9763
|
| 1107 |
},
|
| 1108 |
{
|
| 1109 |
"id": 32,
|
| 1110 |
"name": "RIGHT_FOOT_INDEX",
|
| 1111 |
+
"x": 0.4196,
|
| 1112 |
+
"y": 0.7767,
|
| 1113 |
+
"z": -0.0952,
|
| 1114 |
+
"visibility": 0.978
|
| 1115 |
}
|
| 1116 |
]
|
| 1117 |
},
|
| 1118 |
"5_Mid-Downswing": {
|
| 1119 |
+
"score": 10,
|
| 1120 |
"comments": [
|
| 1121 |
"Đạt chuẩn"
|
| 1122 |
],
|
|
|
|
| 1125 |
{
|
| 1126 |
"id": 0,
|
| 1127 |
"name": "NOSE",
|
| 1128 |
+
"x": 0.5452,
|
| 1129 |
+
"y": 0.5194,
|
| 1130 |
+
"z": -0.5827,
|
| 1131 |
+
"visibility": 1
|
| 1132 |
},
|
| 1133 |
{
|
| 1134 |
"id": 1,
|
| 1135 |
"name": "LEFT_EYE_INNER",
|
| 1136 |
+
"x": 0.5509,
|
| 1137 |
+
"y": 0.5123,
|
| 1138 |
+
"z": -0.5868,
|
| 1139 |
+
"visibility": 1
|
| 1140 |
},
|
| 1141 |
{
|
| 1142 |
"id": 2,
|
| 1143 |
"name": "LEFT_EYE",
|
| 1144 |
+
"x": 0.5553,
|
| 1145 |
+
"y": 0.5111,
|
| 1146 |
+
"z": -0.5867,
|
| 1147 |
+
"visibility": 0.9999
|
| 1148 |
},
|
| 1149 |
{
|
| 1150 |
"id": 3,
|
| 1151 |
"name": "LEFT_EYE_OUTER",
|
| 1152 |
+
"x": 0.5596,
|
| 1153 |
+
"y": 0.5099,
|
| 1154 |
+
"z": -0.5867,
|
| 1155 |
+
"visibility": 0.9999
|
| 1156 |
},
|
| 1157 |
{
|
| 1158 |
"id": 4,
|
| 1159 |
"name": "RIGHT_EYE_INNER",
|
| 1160 |
+
"x": 0.5385,
|
| 1161 |
+
"y": 0.5137,
|
| 1162 |
+
"z": -0.5845,
|
| 1163 |
+
"visibility": 1
|
| 1164 |
},
|
| 1165 |
{
|
| 1166 |
"id": 5,
|
| 1167 |
"name": "RIGHT_EYE",
|
| 1168 |
+
"x": 0.5341,
|
| 1169 |
+
"y": 0.5134,
|
| 1170 |
+
"z": -0.5847,
|
| 1171 |
+
"visibility": 1
|
| 1172 |
},
|
| 1173 |
{
|
| 1174 |
"id": 6,
|
| 1175 |
"name": "RIGHT_EYE_OUTER",
|
| 1176 |
+
"x": 0.5296,
|
| 1177 |
+
"y": 0.513,
|
| 1178 |
+
"z": -0.5849,
|
| 1179 |
+
"visibility": 1
|
| 1180 |
},
|
| 1181 |
{
|
| 1182 |
"id": 7,
|
| 1183 |
"name": "LEFT_EAR",
|
| 1184 |
+
"x": 0.5626,
|
| 1185 |
+
"y": 0.5054,
|
| 1186 |
+
"z": -0.493,
|
| 1187 |
+
"visibility": 0.9999
|
| 1188 |
},
|
| 1189 |
{
|
| 1190 |
"id": 8,
|
| 1191 |
"name": "RIGHT_EAR",
|
| 1192 |
+
"x": 0.5201,
|
| 1193 |
+
"y": 0.508,
|
| 1194 |
+
"z": -0.4836,
|
| 1195 |
+
"visibility": 1
|
| 1196 |
},
|
| 1197 |
{
|
| 1198 |
"id": 9,
|
| 1199 |
"name": "MOUTH_LEFT",
|
| 1200 |
+
"x": 0.552,
|
| 1201 |
+
"y": 0.521,
|
| 1202 |
+
"z": -0.5366,
|
| 1203 |
+
"visibility": 1
|
| 1204 |
},
|
| 1205 |
{
|
| 1206 |
"id": 10,
|
| 1207 |
"name": "MOUTH_RIGHT",
|
| 1208 |
+
"x": 0.5369,
|
| 1209 |
+
"y": 0.5218,
|
| 1210 |
+
"z": -0.5344,
|
| 1211 |
+
"visibility": 1
|
| 1212 |
},
|
| 1213 |
{
|
| 1214 |
"id": 11,
|
| 1215 |
"name": "LEFT_SHOULDER",
|
| 1216 |
+
"x": 0.602,
|
| 1217 |
+
"y": 0.5248,
|
| 1218 |
+
"z": -0.3651,
|
| 1219 |
+
"visibility": 1
|
| 1220 |
},
|
| 1221 |
{
|
| 1222 |
"id": 12,
|
| 1223 |
"name": "RIGHT_SHOULDER",
|
| 1224 |
+
"x": 0.4712,
|
| 1225 |
+
"y": 0.5315,
|
| 1226 |
+
"z": -0.3288,
|
| 1227 |
+
"visibility": 1
|
| 1228 |
},
|
| 1229 |
{
|
| 1230 |
"id": 13,
|
| 1231 |
"name": "LEFT_ELBOW",
|
| 1232 |
+
"x": 0.584,
|
| 1233 |
+
"y": 0.5799,
|
| 1234 |
+
"z": -0.3018,
|
| 1235 |
+
"visibility": 0.9806
|
| 1236 |
},
|
| 1237 |
{
|
| 1238 |
"id": 14,
|
| 1239 |
"name": "RIGHT_ELBOW",
|
| 1240 |
+
"x": 0.4933,
|
| 1241 |
+
"y": 0.5926,
|
| 1242 |
+
"z": -0.2602,
|
| 1243 |
+
"visibility": 0.9898
|
| 1244 |
},
|
| 1245 |
{
|
| 1246 |
"id": 15,
|
| 1247 |
"name": "LEFT_WRIST",
|
| 1248 |
+
"x": 0.5475,
|
| 1249 |
+
"y": 0.6287,
|
| 1250 |
+
"z": -0.3638,
|
| 1251 |
+
"visibility": 0.968
|
| 1252 |
},
|
| 1253 |
{
|
| 1254 |
"id": 16,
|
| 1255 |
"name": "RIGHT_WRIST",
|
| 1256 |
+
"x": 0.5229,
|
| 1257 |
+
"y": 0.6379,
|
| 1258 |
+
"z": -0.3363,
|
| 1259 |
+
"visibility": 0.98
|
| 1260 |
},
|
| 1261 |
{
|
| 1262 |
"id": 17,
|
| 1263 |
"name": "LEFT_PINKY",
|
| 1264 |
+
"x": 0.5475,
|
| 1265 |
+
"y": 0.6448,
|
| 1266 |
+
"z": -0.3947,
|
| 1267 |
+
"visibility": 0.9426
|
| 1268 |
},
|
| 1269 |
{
|
| 1270 |
"id": 18,
|
| 1271 |
"name": "RIGHT_PINKY",
|
| 1272 |
+
"x": 0.529,
|
| 1273 |
+
"y": 0.6524,
|
| 1274 |
+
"z": -0.3639,
|
| 1275 |
+
"visibility": 0.9546
|
| 1276 |
},
|
| 1277 |
{
|
| 1278 |
"id": 19,
|
| 1279 |
"name": "LEFT_INDEX",
|
| 1280 |
+
"x": 0.5399,
|
| 1281 |
+
"y": 0.6458,
|
| 1282 |
+
"z": -0.4222,
|
| 1283 |
+
"visibility": 0.9451
|
| 1284 |
},
|
| 1285 |
{
|
| 1286 |
"id": 20,
|
| 1287 |
"name": "RIGHT_INDEX",
|
| 1288 |
+
"x": 0.5351,
|
| 1289 |
+
"y": 0.6513,
|
| 1290 |
+
"z": -0.3988,
|
| 1291 |
+
"visibility": 0.958
|
| 1292 |
},
|
| 1293 |
{
|
| 1294 |
"id": 21,
|
| 1295 |
"name": "LEFT_THUMB",
|
| 1296 |
+
"x": 0.5387,
|
| 1297 |
+
"y": 0.6405,
|
| 1298 |
+
"z": -0.3737,
|
| 1299 |
+
"visibility": 0.9237
|
| 1300 |
},
|
| 1301 |
{
|
| 1302 |
"id": 22,
|
| 1303 |
"name": "RIGHT_THUMB",
|
| 1304 |
+
"x": 0.5338,
|
| 1305 |
+
"y": 0.646,
|
| 1306 |
+
"z": -0.3491,
|
| 1307 |
+
"visibility": 0.9522
|
| 1308 |
},
|
| 1309 |
{
|
| 1310 |
"id": 23,
|
| 1311 |
"name": "LEFT_HIP",
|
| 1312 |
+
"x": 0.5697,
|
| 1313 |
+
"y": 0.5977,
|
| 1314 |
+
"z": -0.0158,
|
| 1315 |
+
"visibility": 1
|
| 1316 |
},
|
| 1317 |
{
|
| 1318 |
"id": 24,
|
| 1319 |
"name": "RIGHT_HIP",
|
| 1320 |
+
"x": 0.5028,
|
| 1321 |
+
"y": 0.5995,
|
| 1322 |
+
"z": 0.0155,
|
| 1323 |
+
"visibility": 1
|
| 1324 |
},
|
| 1325 |
{
|
| 1326 |
"id": 25,
|
| 1327 |
"name": "LEFT_KNEE",
|
| 1328 |
+
"x": 0.5888,
|
| 1329 |
+
"y": 0.6708,
|
| 1330 |
+
"z": -0.0782,
|
| 1331 |
+
"visibility": 0.9769
|
| 1332 |
},
|
| 1333 |
{
|
| 1334 |
"id": 26,
|
| 1335 |
"name": "RIGHT_KNEE",
|
| 1336 |
+
"x": 0.4641,
|
| 1337 |
+
"y": 0.6745,
|
| 1338 |
+
"z": -0.0431,
|
| 1339 |
+
"visibility": 0.9759
|
| 1340 |
},
|
| 1341 |
{
|
| 1342 |
"id": 27,
|
| 1343 |
"name": "LEFT_ANKLE",
|
| 1344 |
+
"x": 0.6158,
|
| 1345 |
+
"y": 0.7507,
|
| 1346 |
+
"z": -0.0037,
|
| 1347 |
+
"visibility": 0.9864
|
| 1348 |
},
|
| 1349 |
{
|
| 1350 |
"id": 28,
|
| 1351 |
"name": "RIGHT_ANKLE",
|
| 1352 |
+
"x": 0.4338,
|
| 1353 |
+
"y": 0.7489,
|
| 1354 |
+
"z": 0.0473,
|
| 1355 |
+
"visibility": 0.9817
|
| 1356 |
},
|
| 1357 |
{
|
| 1358 |
"id": 29,
|
| 1359 |
"name": "LEFT_HEEL",
|
| 1360 |
+
"x": 0.6155,
|
| 1361 |
+
"y": 0.7593,
|
| 1362 |
+
"z": -0.0068,
|
| 1363 |
+
"visibility": 0.8259
|
| 1364 |
},
|
| 1365 |
{
|
| 1366 |
"id": 30,
|
| 1367 |
"name": "RIGHT_HEEL",
|
| 1368 |
+
"x": 0.4388,
|
| 1369 |
+
"y": 0.7566,
|
| 1370 |
+
"z": 0.0478,
|
| 1371 |
+
"visibility": 0.8404
|
| 1372 |
},
|
| 1373 |
{
|
| 1374 |
"id": 31,
|
| 1375 |
"name": "LEFT_FOOT_INDEX",
|
| 1376 |
+
"x": 0.6305,
|
| 1377 |
+
"y": 0.7788,
|
| 1378 |
+
"z": -0.1656,
|
| 1379 |
+
"visibility": 0.9763
|
| 1380 |
},
|
| 1381 |
{
|
| 1382 |
"id": 32,
|
| 1383 |
"name": "RIGHT_FOOT_INDEX",
|
| 1384 |
+
"x": 0.4196,
|
| 1385 |
+
"y": 0.7767,
|
| 1386 |
+
"z": -0.0952,
|
| 1387 |
+
"visibility": 0.978
|
| 1388 |
}
|
| 1389 |
]
|
| 1390 |
},
|
| 1391 |
"6_Impact": {
|
| 1392 |
+
"score": 10,
|
| 1393 |
"comments": [
|
| 1394 |
"Đạt chuẩn"
|
| 1395 |
],
|
| 1396 |
"data": {
|
| 1397 |
+
"hip_openness": 0.06694477796554565
|
| 1398 |
},
|
| 1399 |
"raw_landmarks": [
|
| 1400 |
{
|
| 1401 |
"id": 0,
|
| 1402 |
"name": "NOSE",
|
| 1403 |
+
"x": 0.5452,
|
| 1404 |
+
"y": 0.5194,
|
| 1405 |
+
"z": -0.5827,
|
| 1406 |
+
"visibility": 1
|
| 1407 |
},
|
| 1408 |
{
|
| 1409 |
"id": 1,
|
| 1410 |
"name": "LEFT_EYE_INNER",
|
| 1411 |
+
"x": 0.5509,
|
| 1412 |
+
"y": 0.5123,
|
| 1413 |
+
"z": -0.5868,
|
| 1414 |
+
"visibility": 1
|
| 1415 |
},
|
| 1416 |
{
|
| 1417 |
"id": 2,
|
| 1418 |
"name": "LEFT_EYE",
|
| 1419 |
+
"x": 0.5553,
|
| 1420 |
+
"y": 0.5111,
|
| 1421 |
+
"z": -0.5867,
|
| 1422 |
+
"visibility": 0.9999
|
| 1423 |
},
|
| 1424 |
{
|
| 1425 |
"id": 3,
|
| 1426 |
"name": "LEFT_EYE_OUTER",
|
| 1427 |
+
"x": 0.5596,
|
| 1428 |
+
"y": 0.5099,
|
| 1429 |
+
"z": -0.5867,
|
| 1430 |
+
"visibility": 0.9999
|
| 1431 |
},
|
| 1432 |
{
|
| 1433 |
"id": 4,
|
| 1434 |
"name": "RIGHT_EYE_INNER",
|
| 1435 |
+
"x": 0.5385,
|
| 1436 |
+
"y": 0.5137,
|
| 1437 |
+
"z": -0.5845,
|
| 1438 |
+
"visibility": 1
|
| 1439 |
},
|
| 1440 |
{
|
| 1441 |
"id": 5,
|
| 1442 |
"name": "RIGHT_EYE",
|
| 1443 |
+
"x": 0.5341,
|
| 1444 |
+
"y": 0.5134,
|
| 1445 |
+
"z": -0.5847,
|
| 1446 |
+
"visibility": 1
|
| 1447 |
},
|
| 1448 |
{
|
| 1449 |
"id": 6,
|
| 1450 |
"name": "RIGHT_EYE_OUTER",
|
| 1451 |
+
"x": 0.5296,
|
| 1452 |
+
"y": 0.513,
|
| 1453 |
+
"z": -0.5849,
|
| 1454 |
+
"visibility": 1
|
| 1455 |
},
|
| 1456 |
{
|
| 1457 |
"id": 7,
|
| 1458 |
"name": "LEFT_EAR",
|
| 1459 |
+
"x": 0.5626,
|
| 1460 |
+
"y": 0.5054,
|
| 1461 |
+
"z": -0.493,
|
| 1462 |
+
"visibility": 0.9999
|
| 1463 |
},
|
| 1464 |
{
|
| 1465 |
"id": 8,
|
| 1466 |
"name": "RIGHT_EAR",
|
| 1467 |
+
"x": 0.5201,
|
| 1468 |
+
"y": 0.508,
|
| 1469 |
+
"z": -0.4836,
|
| 1470 |
+
"visibility": 1
|
| 1471 |
},
|
| 1472 |
{
|
| 1473 |
"id": 9,
|
| 1474 |
"name": "MOUTH_LEFT",
|
| 1475 |
+
"x": 0.552,
|
| 1476 |
+
"y": 0.521,
|
| 1477 |
+
"z": -0.5366,
|
| 1478 |
+
"visibility": 1
|
| 1479 |
},
|
| 1480 |
{
|
| 1481 |
"id": 10,
|
| 1482 |
"name": "MOUTH_RIGHT",
|
| 1483 |
+
"x": 0.5369,
|
| 1484 |
+
"y": 0.5218,
|
| 1485 |
+
"z": -0.5344,
|
| 1486 |
+
"visibility": 1
|
| 1487 |
},
|
| 1488 |
{
|
| 1489 |
"id": 11,
|
| 1490 |
"name": "LEFT_SHOULDER",
|
| 1491 |
+
"x": 0.602,
|
| 1492 |
+
"y": 0.5248,
|
| 1493 |
+
"z": -0.3651,
|
| 1494 |
+
"visibility": 1
|
| 1495 |
},
|
| 1496 |
{
|
| 1497 |
"id": 12,
|
| 1498 |
"name": "RIGHT_SHOULDER",
|
| 1499 |
+
"x": 0.4712,
|
| 1500 |
+
"y": 0.5315,
|
| 1501 |
+
"z": -0.3288,
|
| 1502 |
+
"visibility": 1
|
| 1503 |
},
|
| 1504 |
{
|
| 1505 |
"id": 13,
|
| 1506 |
"name": "LEFT_ELBOW",
|
| 1507 |
+
"x": 0.584,
|
| 1508 |
+
"y": 0.5799,
|
| 1509 |
+
"z": -0.3018,
|
| 1510 |
+
"visibility": 0.9806
|
| 1511 |
},
|
| 1512 |
{
|
| 1513 |
"id": 14,
|
| 1514 |
"name": "RIGHT_ELBOW",
|
| 1515 |
+
"x": 0.4933,
|
| 1516 |
+
"y": 0.5926,
|
| 1517 |
+
"z": -0.2602,
|
| 1518 |
+
"visibility": 0.9898
|
| 1519 |
},
|
| 1520 |
{
|
| 1521 |
"id": 15,
|
| 1522 |
"name": "LEFT_WRIST",
|
| 1523 |
+
"x": 0.5475,
|
| 1524 |
+
"y": 0.6287,
|
| 1525 |
+
"z": -0.3638,
|
| 1526 |
+
"visibility": 0.968
|
| 1527 |
},
|
| 1528 |
{
|
| 1529 |
"id": 16,
|
| 1530 |
"name": "RIGHT_WRIST",
|
| 1531 |
+
"x": 0.5229,
|
| 1532 |
+
"y": 0.6379,
|
| 1533 |
+
"z": -0.3363,
|
| 1534 |
+
"visibility": 0.98
|
| 1535 |
},
|
| 1536 |
{
|
| 1537 |
"id": 17,
|
| 1538 |
"name": "LEFT_PINKY",
|
| 1539 |
+
"x": 0.5475,
|
| 1540 |
+
"y": 0.6448,
|
| 1541 |
+
"z": -0.3947,
|
| 1542 |
+
"visibility": 0.9426
|
| 1543 |
},
|
| 1544 |
{
|
| 1545 |
"id": 18,
|
| 1546 |
"name": "RIGHT_PINKY",
|
| 1547 |
+
"x": 0.529,
|
| 1548 |
+
"y": 0.6524,
|
| 1549 |
+
"z": -0.3639,
|
| 1550 |
+
"visibility": 0.9546
|
| 1551 |
},
|
| 1552 |
{
|
| 1553 |
"id": 19,
|
| 1554 |
"name": "LEFT_INDEX",
|
| 1555 |
+
"x": 0.5399,
|
| 1556 |
+
"y": 0.6458,
|
| 1557 |
+
"z": -0.4222,
|
| 1558 |
+
"visibility": 0.9451
|
| 1559 |
},
|
| 1560 |
{
|
| 1561 |
"id": 20,
|
| 1562 |
"name": "RIGHT_INDEX",
|
| 1563 |
+
"x": 0.5351,
|
| 1564 |
+
"y": 0.6513,
|
| 1565 |
+
"z": -0.3988,
|
| 1566 |
+
"visibility": 0.958
|
| 1567 |
},
|
| 1568 |
{
|
| 1569 |
"id": 21,
|
| 1570 |
"name": "LEFT_THUMB",
|
| 1571 |
+
"x": 0.5387,
|
| 1572 |
+
"y": 0.6405,
|
| 1573 |
+
"z": -0.3737,
|
| 1574 |
+
"visibility": 0.9237
|
| 1575 |
},
|
| 1576 |
{
|
| 1577 |
"id": 22,
|
| 1578 |
"name": "RIGHT_THUMB",
|
| 1579 |
+
"x": 0.5338,
|
| 1580 |
+
"y": 0.646,
|
| 1581 |
+
"z": -0.3491,
|
| 1582 |
+
"visibility": 0.9522
|
| 1583 |
},
|
| 1584 |
{
|
| 1585 |
"id": 23,
|
| 1586 |
"name": "LEFT_HIP",
|
| 1587 |
+
"x": 0.5697,
|
| 1588 |
+
"y": 0.5977,
|
| 1589 |
+
"z": -0.0158,
|
| 1590 |
+
"visibility": 1
|
| 1591 |
},
|
| 1592 |
{
|
| 1593 |
"id": 24,
|
| 1594 |
"name": "RIGHT_HIP",
|
| 1595 |
+
"x": 0.5028,
|
| 1596 |
+
"y": 0.5995,
|
| 1597 |
+
"z": 0.0155,
|
| 1598 |
+
"visibility": 1
|
| 1599 |
},
|
| 1600 |
{
|
| 1601 |
"id": 25,
|
| 1602 |
"name": "LEFT_KNEE",
|
| 1603 |
+
"x": 0.5888,
|
| 1604 |
+
"y": 0.6708,
|
| 1605 |
+
"z": -0.0782,
|
| 1606 |
+
"visibility": 0.9769
|
| 1607 |
},
|
| 1608 |
{
|
| 1609 |
"id": 26,
|
| 1610 |
"name": "RIGHT_KNEE",
|
| 1611 |
+
"x": 0.4641,
|
| 1612 |
+
"y": 0.6745,
|
| 1613 |
+
"z": -0.0431,
|
| 1614 |
+
"visibility": 0.9759
|
| 1615 |
},
|
| 1616 |
{
|
| 1617 |
"id": 27,
|
| 1618 |
"name": "LEFT_ANKLE",
|
| 1619 |
+
"x": 0.6158,
|
| 1620 |
+
"y": 0.7507,
|
| 1621 |
+
"z": -0.0037,
|
| 1622 |
+
"visibility": 0.9864
|
| 1623 |
},
|
| 1624 |
{
|
| 1625 |
"id": 28,
|
| 1626 |
"name": "RIGHT_ANKLE",
|
| 1627 |
+
"x": 0.4338,
|
| 1628 |
+
"y": 0.7489,
|
| 1629 |
+
"z": 0.0473,
|
| 1630 |
+
"visibility": 0.9817
|
| 1631 |
},
|
| 1632 |
{
|
| 1633 |
"id": 29,
|
| 1634 |
"name": "LEFT_HEEL",
|
| 1635 |
+
"x": 0.6155,
|
| 1636 |
+
"y": 0.7593,
|
| 1637 |
+
"z": -0.0068,
|
| 1638 |
+
"visibility": 0.8259
|
| 1639 |
},
|
| 1640 |
{
|
| 1641 |
"id": 30,
|
| 1642 |
"name": "RIGHT_HEEL",
|
| 1643 |
+
"x": 0.4388,
|
| 1644 |
+
"y": 0.7566,
|
| 1645 |
+
"z": 0.0478,
|
| 1646 |
+
"visibility": 0.8404
|
| 1647 |
},
|
| 1648 |
{
|
| 1649 |
"id": 31,
|
| 1650 |
"name": "LEFT_FOOT_INDEX",
|
| 1651 |
+
"x": 0.6305,
|
| 1652 |
+
"y": 0.7788,
|
| 1653 |
+
"z": -0.1656,
|
| 1654 |
+
"visibility": 0.9763
|
| 1655 |
},
|
| 1656 |
{
|
| 1657 |
"id": 32,
|
| 1658 |
"name": "RIGHT_FOOT_INDEX",
|
| 1659 |
+
"x": 0.4196,
|
| 1660 |
+
"y": 0.7767,
|
| 1661 |
+
"z": -0.0952,
|
| 1662 |
+
"visibility": 0.978
|
| 1663 |
}
|
| 1664 |
]
|
| 1665 |
},
|
| 1666 |
"7_Mid-Follow-Through": {
|
| 1667 |
+
"score": 10,
|
| 1668 |
"comments": [
|
| 1669 |
"Đạt chuẩn"
|
| 1670 |
],
|
|
|
|
| 1673 |
{
|
| 1674 |
"id": 0,
|
| 1675 |
"name": "NOSE",
|
| 1676 |
+
"x": 0.5185,
|
| 1677 |
+
"y": 0.5218,
|
| 1678 |
+
"z": -0.7834,
|
| 1679 |
+
"visibility": 1
|
| 1680 |
},
|
| 1681 |
{
|
| 1682 |
"id": 1,
|
| 1683 |
"name": "LEFT_EYE_INNER",
|
| 1684 |
+
"x": 0.5254,
|
| 1685 |
+
"y": 0.5169,
|
| 1686 |
+
"z": -0.7878,
|
| 1687 |
+
"visibility": 0.9999
|
| 1688 |
},
|
| 1689 |
{
|
| 1690 |
"id": 2,
|
| 1691 |
"name": "LEFT_EYE",
|
| 1692 |
+
"x": 0.5293,
|
| 1693 |
+
"y": 0.5165,
|
| 1694 |
+
"z": -0.7876,
|
| 1695 |
+
"visibility": 0.9999
|
| 1696 |
},
|
| 1697 |
{
|
| 1698 |
"id": 3,
|
| 1699 |
"name": "LEFT_EYE_OUTER",
|
| 1700 |
+
"x": 0.5333,
|
| 1701 |
+
"y": 0.5159,
|
| 1702 |
+
"z": -0.7876,
|
| 1703 |
+
"visibility": 0.9999
|
| 1704 |
},
|
| 1705 |
{
|
| 1706 |
"id": 4,
|
| 1707 |
"name": "RIGHT_EYE_INNER",
|
| 1708 |
+
"x": 0.5153,
|
| 1709 |
+
"y": 0.5161,
|
| 1710 |
+
"z": -0.7822,
|
| 1711 |
+
"visibility": 0.9999
|
| 1712 |
},
|
| 1713 |
{
|
| 1714 |
"id": 5,
|
| 1715 |
"name": "RIGHT_EYE",
|
| 1716 |
+
"x": 0.5121,
|
| 1717 |
+
"y": 0.5152,
|
| 1718 |
+
"z": -0.7824,
|
| 1719 |
+
"visibility": 0.9999
|
| 1720 |
},
|
| 1721 |
{
|
| 1722 |
"id": 6,
|
| 1723 |
"name": "RIGHT_EYE_OUTER",
|
| 1724 |
+
"x": 0.5089,
|
| 1725 |
+
"y": 0.5142,
|
| 1726 |
+
"z": -0.7825,
|
| 1727 |
+
"visibility": 0.9999
|
| 1728 |
},
|
| 1729 |
{
|
| 1730 |
"id": 7,
|
| 1731 |
"name": "LEFT_EAR",
|
| 1732 |
+
"x": 0.5396,
|
| 1733 |
+
"y": 0.5104,
|
| 1734 |
+
"z": -0.6658,
|
| 1735 |
+
"visibility": 0.9999
|
| 1736 |
},
|
| 1737 |
{
|
| 1738 |
"id": 8,
|
| 1739 |
"name": "RIGHT_EAR",
|
| 1740 |
+
"x": 0.504,
|
| 1741 |
+
"y": 0.5087,
|
| 1742 |
+
"z": -0.6424,
|
| 1743 |
+
"visibility": 0.9999
|
| 1744 |
},
|
| 1745 |
{
|
| 1746 |
"id": 9,
|
| 1747 |
"name": "MOUTH_LEFT",
|
| 1748 |
+
"x": 0.5245,
|
| 1749 |
+
"y": 0.5241,
|
| 1750 |
+
"z": -0.7244,
|
| 1751 |
+
"visibility": 1
|
| 1752 |
},
|
| 1753 |
{
|
| 1754 |
"id": 10,
|
| 1755 |
"name": "MOUTH_RIGHT",
|
| 1756 |
+
"x": 0.5115,
|
| 1757 |
+
"y": 0.5228,
|
| 1758 |
+
"z": -0.7182,
|
| 1759 |
+
"visibility": 1
|
| 1760 |
},
|
| 1761 |
{
|
| 1762 |
"id": 11,
|
| 1763 |
"name": "LEFT_SHOULDER",
|
| 1764 |
+
"x": 0.5781,
|
| 1765 |
+
"y": 0.5309,
|
| 1766 |
+
"z": -0.509,
|
| 1767 |
+
"visibility": 1
|
| 1768 |
},
|
| 1769 |
{
|
| 1770 |
"id": 12,
|
| 1771 |
"name": "RIGHT_SHOULDER",
|
| 1772 |
+
"x": 0.4549,
|
| 1773 |
+
"y": 0.5223,
|
| 1774 |
+
"z": -0.3961,
|
| 1775 |
+
"visibility": 1
|
| 1776 |
},
|
| 1777 |
{
|
| 1778 |
"id": 13,
|
| 1779 |
"name": "LEFT_ELBOW",
|
| 1780 |
+
"x": 0.5468,
|
| 1781 |
+
"y": 0.5848,
|
| 1782 |
+
"z": -0.4442,
|
| 1783 |
+
"visibility": 0.9891
|
| 1784 |
},
|
| 1785 |
{
|
| 1786 |
"id": 14,
|
| 1787 |
"name": "RIGHT_ELBOW",
|
| 1788 |
+
"x": 0.4525,
|
| 1789 |
+
"y": 0.5773,
|
| 1790 |
+
"z": -0.2462,
|
| 1791 |
+
"visibility": 0.981
|
| 1792 |
},
|
| 1793 |
{
|
| 1794 |
"id": 15,
|
| 1795 |
"name": "LEFT_WRIST",
|
| 1796 |
+
"x": 0.4879,
|
| 1797 |
+
"y": 0.6283,
|
| 1798 |
+
"z": -0.5367,
|
| 1799 |
+
"visibility": 0.9831
|
| 1800 |
},
|
| 1801 |
{
|
| 1802 |
"id": 16,
|
| 1803 |
"name": "RIGHT_WRIST",
|
| 1804 |
+
"x": 0.4552,
|
| 1805 |
+
"y": 0.6304,
|
| 1806 |
+
"z": -0.325,
|
| 1807 |
+
"visibility": 0.9735
|
| 1808 |
},
|
| 1809 |
{
|
| 1810 |
"id": 17,
|
| 1811 |
"name": "LEFT_PINKY",
|
| 1812 |
+
"x": 0.4762,
|
| 1813 |
+
"y": 0.6445,
|
| 1814 |
+
"z": -0.5803,
|
| 1815 |
+
"visibility": 0.9634
|
| 1816 |
},
|
| 1817 |
{
|
| 1818 |
"id": 18,
|
| 1819 |
"name": "RIGHT_PINKY",
|
| 1820 |
+
"x": 0.4492,
|
| 1821 |
+
"y": 0.6466,
|
| 1822 |
+
"z": -0.3501,
|
| 1823 |
+
"visibility": 0.9438
|
| 1824 |
},
|
| 1825 |
{
|
| 1826 |
"id": 19,
|
| 1827 |
"name": "LEFT_INDEX",
|
| 1828 |
+
"x": 0.4699,
|
| 1829 |
+
"y": 0.6432,
|
| 1830 |
+
"z": -0.613,
|
| 1831 |
+
"visibility": 0.9661
|
| 1832 |
},
|
| 1833 |
{
|
| 1834 |
"id": 20,
|
| 1835 |
"name": "RIGHT_INDEX",
|
| 1836 |
+
"x": 0.4545,
|
| 1837 |
+
"y": 0.646,
|
| 1838 |
+
"z": -0.4028,
|
| 1839 |
+
"visibility": 0.9496
|
| 1840 |
},
|
| 1841 |
{
|
| 1842 |
"id": 21,
|
| 1843 |
"name": "LEFT_THUMB",
|
| 1844 |
+
"x": 0.4734,
|
| 1845 |
+
"y": 0.6373,
|
| 1846 |
+
"z": -0.548,
|
| 1847 |
+
"visibility": 0.9436
|
| 1848 |
},
|
| 1849 |
{
|
| 1850 |
"id": 22,
|
| 1851 |
"name": "RIGHT_THUMB",
|
| 1852 |
+
"x": 0.4594,
|
| 1853 |
+
"y": 0.6403,
|
| 1854 |
+
"z": -0.3459,
|
| 1855 |
+
"visibility": 0.9429
|
| 1856 |
},
|
| 1857 |
{
|
| 1858 |
"id": 23,
|
| 1859 |
"name": "LEFT_HIP",
|
| 1860 |
+
"x": 0.5592,
|
| 1861 |
+
"y": 0.5928,
|
| 1862 |
+
"z": -0.0226,
|
| 1863 |
+
"visibility": 1
|
| 1864 |
},
|
| 1865 |
{
|
| 1866 |
"id": 24,
|
| 1867 |
"name": "RIGHT_HIP",
|
| 1868 |
+
"x": 0.4926,
|
| 1869 |
+
"y": 0.5922,
|
| 1870 |
+
"z": 0.0225,
|
| 1871 |
+
"visibility": 1
|
| 1872 |
},
|
| 1873 |
{
|
| 1874 |
"id": 25,
|
| 1875 |
"name": "LEFT_KNEE",
|
| 1876 |
+
"x": 0.5813,
|
| 1877 |
+
"y": 0.6704,
|
| 1878 |
+
"z": -0.1068,
|
| 1879 |
+
"visibility": 0.99
|
| 1880 |
},
|
| 1881 |
{
|
| 1882 |
"id": 26,
|
| 1883 |
"name": "RIGHT_KNEE",
|
| 1884 |
+
"x": 0.4566,
|
| 1885 |
+
"y": 0.6723,
|
| 1886 |
+
"z": -0.0681,
|
| 1887 |
+
"visibility": 0.9901
|
| 1888 |
},
|
| 1889 |
{
|
| 1890 |
"id": 27,
|
| 1891 |
"name": "LEFT_ANKLE",
|
| 1892 |
+
"x": 0.6169,
|
| 1893 |
+
"y": 0.7513,
|
| 1894 |
+
"z": 0.0031,
|
| 1895 |
+
"visibility": 0.996
|
| 1896 |
},
|
| 1897 |
{
|
| 1898 |
"id": 28,
|
| 1899 |
"name": "RIGHT_ANKLE",
|
| 1900 |
+
"x": 0.4363,
|
| 1901 |
+
"y": 0.7491,
|
| 1902 |
+
"z": 0.0811,
|
| 1903 |
+
"visibility": 0.9901
|
| 1904 |
},
|
| 1905 |
{
|
| 1906 |
"id": 29,
|
| 1907 |
"name": "LEFT_HEEL",
|
| 1908 |
+
"x": 0.6177,
|
| 1909 |
+
"y": 0.7608,
|
| 1910 |
+
"z": 0.0015,
|
| 1911 |
+
"visibility": 0.9118
|
| 1912 |
},
|
| 1913 |
{
|
| 1914 |
"id": 30,
|
| 1915 |
"name": "RIGHT_HEEL",
|
| 1916 |
+
"x": 0.4425,
|
| 1917 |
+
"y": 0.7565,
|
| 1918 |
+
"z": 0.0854,
|
| 1919 |
+
"visibility": 0.8768
|
| 1920 |
},
|
| 1921 |
{
|
| 1922 |
"id": 31,
|
| 1923 |
"name": "LEFT_FOOT_INDEX",
|
| 1924 |
+
"x": 0.6328,
|
| 1925 |
+
"y": 0.7787,
|
| 1926 |
+
"z": -0.1983,
|
| 1927 |
+
"visibility": 0.9912
|
| 1928 |
},
|
| 1929 |
{
|
| 1930 |
"id": 32,
|
| 1931 |
"name": "RIGHT_FOOT_INDEX",
|
| 1932 |
+
"x": 0.4208,
|
| 1933 |
+
"y": 0.7775,
|
| 1934 |
+
"z": -0.0891,
|
| 1935 |
+
"visibility": 0.9855
|
| 1936 |
}
|
| 1937 |
]
|
| 1938 |
},
|
| 1939 |
"8_Finish": {
|
| 1940 |
+
"score": 10,
|
| 1941 |
"comments": [
|
| 1942 |
"Đạt chuẩn"
|
| 1943 |
],
|
|
|
|
| 1946 |
{
|
| 1947 |
"id": 0,
|
| 1948 |
"name": "NOSE",
|
| 1949 |
+
"x": 0.6068,
|
| 1950 |
+
"y": 0.4777,
|
| 1951 |
+
"z": -0.1523,
|
| 1952 |
"visibility": 0.9998
|
| 1953 |
},
|
| 1954 |
{
|
| 1955 |
"id": 1,
|
| 1956 |
"name": "LEFT_EYE_INNER",
|
| 1957 |
+
"x": 0.5992,
|
| 1958 |
+
"y": 0.4706,
|
| 1959 |
+
"z": -0.1289,
|
| 1960 |
+
"visibility": 0.9997
|
| 1961 |
},
|
| 1962 |
{
|
| 1963 |
"id": 2,
|
| 1964 |
"name": "LEFT_EYE",
|
| 1965 |
+
"x": 0.5978,
|
| 1966 |
+
"y": 0.4703,
|
| 1967 |
+
"z": -0.1289,
|
| 1968 |
+
"visibility": 0.9996
|
| 1969 |
},
|
| 1970 |
{
|
| 1971 |
"id": 3,
|
| 1972 |
"name": "LEFT_EYE_OUTER",
|
| 1973 |
+
"x": 0.5965,
|
| 1974 |
+
"y": 0.4699,
|
| 1975 |
+
"z": -0.1289,
|
| 1976 |
+
"visibility": 0.9996
|
| 1977 |
},
|
| 1978 |
{
|
| 1979 |
"id": 4,
|
| 1980 |
"name": "RIGHT_EYE_INNER",
|
| 1981 |
+
"x": 0.5997,
|
| 1982 |
+
"y": 0.4707,
|
| 1983 |
+
"z": -0.1741,
|
| 1984 |
"visibility": 0.9999
|
| 1985 |
},
|
| 1986 |
{
|
| 1987 |
"id": 5,
|
| 1988 |
"name": "RIGHT_EYE",
|
| 1989 |
+
"x": 0.5986,
|
| 1990 |
+
"y": 0.4704,
|
| 1991 |
+
"z": -0.1742,
|
| 1992 |
"visibility": 0.9999
|
| 1993 |
},
|
| 1994 |
{
|
| 1995 |
"id": 6,
|
| 1996 |
"name": "RIGHT_EYE_OUTER",
|
| 1997 |
+
"x": 0.5975,
|
| 1998 |
+
"y": 0.4703,
|
| 1999 |
+
"z": -0.1743,
|
| 2000 |
"visibility": 0.9999
|
| 2001 |
},
|
| 2002 |
{
|
| 2003 |
"id": 7,
|
| 2004 |
"name": "LEFT_EAR",
|
| 2005 |
+
"x": 0.5836,
|
| 2006 |
+
"y": 0.4712,
|
| 2007 |
+
"z": 0.0026,
|
| 2008 |
+
"visibility": 0.9993
|
| 2009 |
},
|
| 2010 |
{
|
| 2011 |
"id": 8,
|
| 2012 |
"name": "RIGHT_EAR",
|
| 2013 |
+
"x": 0.5842,
|
| 2014 |
+
"y": 0.4726,
|
| 2015 |
+
"z": -0.2109,
|
| 2016 |
+
"visibility": 0.9998
|
| 2017 |
},
|
| 2018 |
{
|
| 2019 |
"id": 9,
|
| 2020 |
"name": "MOUTH_LEFT",
|
| 2021 |
+
"x": 0.6044,
|
| 2022 |
+
"y": 0.4839,
|
| 2023 |
+
"z": -0.0992,
|
| 2024 |
+
"visibility": 0.9989
|
| 2025 |
},
|
| 2026 |
{
|
| 2027 |
"id": 10,
|
| 2028 |
"name": "MOUTH_RIGHT",
|
| 2029 |
+
"x": 0.6038,
|
| 2030 |
+
"y": 0.4836,
|
| 2031 |
+
"z": -0.1613,
|
| 2032 |
+
"visibility": 0.9995
|
| 2033 |
},
|
| 2034 |
{
|
| 2035 |
"id": 11,
|
| 2036 |
"name": "LEFT_SHOULDER",
|
| 2037 |
+
"x": 0.5753,
|
| 2038 |
+
"y": 0.5054,
|
| 2039 |
+
"z": 0.1657,
|
| 2040 |
+
"visibility": 0.9995
|
| 2041 |
},
|
| 2042 |
{
|
| 2043 |
"id": 12,
|
| 2044 |
"name": "RIGHT_SHOULDER",
|
| 2045 |
+
"x": 0.5237,
|
| 2046 |
+
"y": 0.5001,
|
| 2047 |
+
"z": -0.2612,
|
| 2048 |
+
"visibility": 0.9998
|
| 2049 |
},
|
| 2050 |
{
|
| 2051 |
"id": 13,
|
| 2052 |
"name": "LEFT_ELBOW",
|
| 2053 |
+
"x": 0.5994,
|
| 2054 |
+
"y": 0.5328,
|
| 2055 |
+
"z": 0.4623,
|
| 2056 |
+
"visibility": 0.3608
|
| 2057 |
},
|
| 2058 |
{
|
| 2059 |
"id": 14,
|
| 2060 |
"name": "RIGHT_ELBOW",
|
| 2061 |
+
"x": 0.4355,
|
| 2062 |
+
"y": 0.4992,
|
| 2063 |
+
"z": -0.5334,
|
| 2064 |
+
"visibility": 0.9872
|
| 2065 |
},
|
| 2066 |
{
|
| 2067 |
"id": 15,
|
| 2068 |
"name": "LEFT_WRIST",
|
| 2069 |
+
"x": 0.6319,
|
| 2070 |
+
"y": 0.5231,
|
| 2071 |
+
"z": 0.6471,
|
| 2072 |
+
"visibility": 0.7541
|
| 2073 |
},
|
| 2074 |
{
|
| 2075 |
"id": 16,
|
| 2076 |
"name": "RIGHT_WRIST",
|
| 2077 |
+
"x": 0.4696,
|
| 2078 |
+
"y": 0.4648,
|
| 2079 |
+
"z": -0.731,
|
| 2080 |
+
"visibility": 0.9858
|
| 2081 |
},
|
| 2082 |
{
|
| 2083 |
"id": 17,
|
| 2084 |
"name": "LEFT_PINKY",
|
| 2085 |
+
"x": 0.6377,
|
| 2086 |
+
"y": 0.5218,
|
| 2087 |
+
"z": 0.7003,
|
| 2088 |
+
"visibility": 0.6758
|
| 2089 |
},
|
| 2090 |
{
|
| 2091 |
"id": 18,
|
| 2092 |
"name": "RIGHT_PINKY",
|
| 2093 |
+
"x": 0.4823,
|
| 2094 |
+
"y": 0.4618,
|
| 2095 |
+
"z": -0.7776,
|
| 2096 |
+
"visibility": 0.9699
|
| 2097 |
},
|
| 2098 |
{
|
| 2099 |
"id": 19,
|
| 2100 |
"name": "LEFT_INDEX",
|
| 2101 |
+
"x": 0.6416,
|
| 2102 |
+
"y": 0.5167,
|
| 2103 |
+
"z": 0.6675,
|
| 2104 |
+
"visibility": 0.6994
|
| 2105 |
},
|
| 2106 |
{
|
| 2107 |
"id": 20,
|
| 2108 |
"name": "RIGHT_INDEX",
|
| 2109 |
+
"x": 0.4931,
|
| 2110 |
+
"y": 0.4624,
|
| 2111 |
+
"z": -0.7546,
|
| 2112 |
+
"visibility": 0.9677
|
| 2113 |
},
|
| 2114 |
{
|
| 2115 |
"id": 21,
|
| 2116 |
"name": "LEFT_THUMB",
|
| 2117 |
+
"x": 0.6412,
|
| 2118 |
+
"y": 0.518,
|
| 2119 |
+
"z": 0.6395,
|
| 2120 |
+
"visibility": 0.6996
|
| 2121 |
},
|
| 2122 |
{
|
| 2123 |
"id": 22,
|
| 2124 |
"name": "RIGHT_THUMB",
|
| 2125 |
+
"x": 0.4919,
|
| 2126 |
+
"y": 0.4654,
|
| 2127 |
+
"z": -0.7241,
|
| 2128 |
+
"visibility": 0.9442
|
| 2129 |
},
|
| 2130 |
{
|
| 2131 |
"id": 23,
|
| 2132 |
"name": "LEFT_HIP",
|
| 2133 |
+
"x": 0.5815,
|
| 2134 |
+
"y": 0.6089,
|
| 2135 |
+
"z": 0.1371,
|
| 2136 |
+
"visibility": 0.9998
|
| 2137 |
},
|
| 2138 |
{
|
| 2139 |
"id": 24,
|
| 2140 |
"name": "RIGHT_HIP",
|
| 2141 |
+
"x": 0.5528,
|
| 2142 |
+
"y": 0.6094,
|
| 2143 |
+
"z": -0.1373,
|
| 2144 |
+
"visibility": 0.9999
|
| 2145 |
},
|
| 2146 |
{
|
| 2147 |
"id": 25,
|
| 2148 |
"name": "LEFT_KNEE",
|
| 2149 |
+
"x": 0.6245,
|
| 2150 |
+
"y": 0.6746,
|
| 2151 |
+
"z": 0.2873,
|
| 2152 |
+
"visibility": 0.8154
|
| 2153 |
},
|
| 2154 |
{
|
| 2155 |
"id": 26,
|
| 2156 |
"name": "RIGHT_KNEE",
|
| 2157 |
+
"x": 0.5476,
|
| 2158 |
+
"y": 0.6807,
|
| 2159 |
+
"z": -0.192,
|
| 2160 |
+
"visibility": 0.988
|
| 2161 |
},
|
| 2162 |
{
|
| 2163 |
"id": 27,
|
| 2164 |
"name": "LEFT_ANKLE",
|
| 2165 |
+
"x": 0.6165,
|
| 2166 |
+
"y": 0.7466,
|
| 2167 |
+
"z": 0.4796,
|
| 2168 |
+
"visibility": 0.9565
|
| 2169 |
},
|
| 2170 |
{
|
| 2171 |
"id": 28,
|
| 2172 |
"name": "RIGHT_ANKLE",
|
| 2173 |
+
"x": 0.4303,
|
| 2174 |
+
"y": 0.7406,
|
| 2175 |
+
"z": -0.1284,
|
| 2176 |
+
"visibility": 0.9948
|
| 2177 |
},
|
| 2178 |
{
|
| 2179 |
"id": 29,
|
| 2180 |
"name": "LEFT_HEEL",
|
| 2181 |
+
"x": 0.6072,
|
| 2182 |
+
"y": 0.7583,
|
| 2183 |
+
"z": 0.4922,
|
| 2184 |
+
"visibility": 0.927
|
| 2185 |
},
|
| 2186 |
{
|
| 2187 |
"id": 30,
|
| 2188 |
"name": "RIGHT_HEEL",
|
| 2189 |
+
"x": 0.4063,
|
| 2190 |
+
"y": 0.7377,
|
| 2191 |
+
"z": -0.1253,
|
| 2192 |
+
"visibility": 0.9657
|
| 2193 |
},
|
| 2194 |
{
|
| 2195 |
"id": 31,
|
| 2196 |
"name": "LEFT_FOOT_INDEX",
|
| 2197 |
+
"x": 0.6557,
|
| 2198 |
+
"y": 0.7717,
|
| 2199 |
+
"z": 0.4193,
|
| 2200 |
+
"visibility": 0.947
|
| 2201 |
},
|
| 2202 |
{
|
| 2203 |
"id": 32,
|
| 2204 |
"name": "RIGHT_FOOT_INDEX",
|
| 2205 |
+
"x": 0.428,
|
| 2206 |
+
"y": 0.7812,
|
| 2207 |
+
"z": -0.2448,
|
| 2208 |
+
"visibility": 0.99
|
| 2209 |
}
|
| 2210 |
]
|
| 2211 |
}
|
| 2212 |
},
|
| 2213 |
+
"overall_score": 10,
|
| 2214 |
+
"view_angle": "Face-on (Trực diện)"
|
| 2215 |
},
|
| 2216 |
"coaching": {
|
| 2217 |
+
"video_id": "d907f221-0b2f-44cd-9af8-cb4921bb13bb",
|
| 2218 |
+
"final_score": 10,
|
| 2219 |
"skill_level": "Professional / Low Handicap",
|
| 2220 |
"key_faults": [
|
| 2221 |
+
"[1_Address] Đạt chuẩn",
|
| 2222 |
"[2_Toe-up] Đạt chuẩn",
|
| 2223 |
"[3_Mid-Backswing] Đạt chuẩn",
|
| 2224 |
+
"[4_Top] Đạt chuẩn",
|
| 2225 |
"[5_Mid-Downswing] Đạt chuẩn",
|
| 2226 |
"[6_Impact] Đạt chuẩn",
|
| 2227 |
"[7_Mid-Follow-Through] Đạt chuẩn",
|
| 2228 |
"[8_Finish] Đạt chuẩn"
|
| 2229 |
],
|
| 2230 |
+
"recommended_drills": [],
|
| 2231 |
+
"summary": "Cú swing của bạn đạt 10.0/10. Kỹ thuật rất chuẩn, hãy tiếp tục duy trì!"
|
|
|
|
|
|
|
| 2232 |
}
|
| 2233 |
}
|
models_v1/mobilenet_v2.pth.tar
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:ecbe2b568c8602549fa9e1d5833c63848f490a48d92e5d224d1eb2063e152cf8
|
| 3 |
+
size 14205652
|
models_v1/swingnet_1800.pth.tar
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:6331e303a9e86d0c19f183899f958bf2a71cf5a7070d46899e25e1ac877b23d4
|
| 3 |
+
size 63280059
|
src/eval.py
CHANGED
|
@@ -60,7 +60,7 @@ if __name__ == '__main__':
|
|
| 60 |
bidirectional=True,
|
| 61 |
dropout=False)
|
| 62 |
|
| 63 |
-
save_dict = torch.load('
|
| 64 |
model.load_state_dict(save_dict['model_state_dict'])
|
| 65 |
model.cuda()
|
| 66 |
model.eval()
|
|
|
|
| 60 |
bidirectional=True,
|
| 61 |
dropout=False)
|
| 62 |
|
| 63 |
+
save_dict = torch.load('models_v1/swingnet_1800.pth.tar')
|
| 64 |
model.load_state_dict(save_dict['model_state_dict'])
|
| 65 |
model.cuda()
|
| 66 |
model.eval()
|
src/model.py
CHANGED
|
@@ -18,7 +18,7 @@ class EventDetector(nn.Module):
|
|
| 18 |
# Get the directory of the current script (src/)
|
| 19 |
current_script_directory = os.path.dirname(os.path.abspath(__file__))
|
| 20 |
# Path to models folder (outside src/)
|
| 21 |
-
relative_directory = '../
|
| 22 |
|
| 23 |
# Construct the absolute path
|
| 24 |
model_dir = os.path.normpath(os.path.join(current_script_directory, relative_directory))
|
|
|
|
| 18 |
# Get the directory of the current script (src/)
|
| 19 |
current_script_directory = os.path.dirname(os.path.abspath(__file__))
|
| 20 |
# Path to models folder (outside src/)
|
| 21 |
+
relative_directory = '../models_v1/mobilenet_v2.pth.tar'
|
| 22 |
|
| 23 |
# Construct the absolute path
|
| 24 |
model_dir = os.path.normpath(os.path.join(current_script_directory, relative_directory))
|