| import os |
| import argparse |
| from ultralytics import YOLO |
| import cv2 |
| from pathlib import Path |
|
|
| |
| COCO_BODY_17 = [ |
| "nose", "left_eye", "right_eye", "left_ear", "right_ear", |
| "left_shoulder", "right_shoulder", "left_elbow", "right_elbow", |
| "left_wrist", "right_wrist", "left_hip", "right_hip", |
| "left_knee", "right_knee", "left_ankle", "right_ankle" |
| ] |
|
|
| FEET_6_LABELS = [ |
| "left_heel", "left_big_toe", "left_little_toe", |
| "right_heel", "right_big_toe", "right_little_toe" |
| ] |
|
|
| ALL_KEYPOINTS = COCO_BODY_17 + FEET_6_LABELS |
|
|
| def run_inference(frames_dir, labels_dir, model_path, img_width=1920, img_height=1080): |
| """Run YOLO pose inference on all frames and save labels.""" |
| model = YOLO(model_path) |
| os.makedirs(labels_dir, exist_ok=True) |
| |
| frame_files = sorted([f for f in os.listdir(frames_dir) if f.endswith('.jpg')]) |
| print(f"Running inference on {len(frame_files)} frames...") |
|
|
| for idx, frame_file in enumerate(frame_files): |
| frame_path = os.path.join(frames_dir, frame_file) |
| results = model(frame_path, verbose=False) |
|
|
| label_file = os.path.join(labels_dir, frame_file.replace('.jpg', '.txt')) |
|
|
| with open(label_file, 'w') as f: |
| for result in results: |
| if result.keypoints is not None: |
| for kp in result.keypoints.data: |
| kp_np = kp.cpu().numpy() |
|
|
| |
| valid_kp = kp_np[kp_np[:, 2] > 0] |
| if len(valid_kp) == 0: |
| continue |
|
|
| x_min, y_min = valid_kp[:, 0].min(), valid_kp[:, 1].min() |
| x_max, y_max = valid_kp[:, 0].max(), valid_kp[:, 1].max() |
| bbox_x = (x_min + x_max) / 2 / img_width |
| bbox_y = (y_min + y_max) / 2 / img_height |
| bbox_w = (x_max - x_min) / img_width |
| bbox_h = (y_max - y_min) / img_height |
|
|
| |
| line = f"0 {bbox_x:.6f} {bbox_y:.6f} {bbox_w:.6f} {bbox_h:.6f}" |
| for kp_point in kp_np: |
| x_norm = kp_point[0] / img_width |
| y_norm = kp_point[1] / img_height |
| conf = kp_point[2] |
| line += f" {x_norm:.6f} {y_norm:.6f} {conf:.2f}" |
| f.write(line + "\n") |
|
|
| if (idx + 1) % 50 == 0: |
| print(f"Processed {idx + 1}/{len(frame_files)} frames") |
|
|
| print(f"✅ Inference complete. Labels saved to {labels_dir}") |
|
|
| if __name__ == "__main__": |
| parser = argparse.ArgumentParser() |
| parser.add_argument("--frames", required=True, help="Directory containing JPEG frames") |
| parser.add_argument("--labels", required=True, help="Output directory for labels") |
| parser.add_argument("--model", required=True, help="Path to YOLO weights (.pt)") |
| parser.add_argument("--width", type=int, default=1920) |
| parser.add_argument("--height", type=int, default=1080) |
| args = parser.parse_args() |
| |
| run_inference(args.frames, args.labels, args.model, args.width, args.height) |
|
|