现在需要识别人物的肢体(姿态/骨骼关键点),即所谓的「姿态估计(pose estimation)」,以下是一些主流、训练好可直接使用的开源模型推荐,支持多人识别与骨骼关键点检测,适合你后续用于游戏人物识别、交互、动作捕捉等场景:
✅ 推荐姿态识别模型(已训练好)
模型名称 | 框架 | 支持多人 | 关键点数量 | 优势 | 预训练模型 |
---|---|---|---|---|---|
OpenPose | Caffe / PyTorch | ✅ 是 | COCO:18个 | 开源先驱,稳定 | ✅ |
MediaPipe Pose | ❌ 单人 | 33个 | 极快、跨平台、轻量 | ✅ | |
YOLOv8-Pose | Ultralytics | ✅ 是 | COCO:17个 | YOLO框架下最简单、集成好 | ✅ |
MMPose | PyTorch | ✅ 是 | 自定义 | 精度高、支持多种后端 | ✅ |
✅ 最推荐:YOLOv8-Pose(Ultralytics 出品)
之前已经使用 YOLOv8 检测人物,所以最推荐你用它的姿态版本 yolov8n-pose.pt
,上手最快,兼容性最好。
🔧 安装
pip install ultralytics
📦 下载模型
Ultralytics 官方已训练好模型,可以使用以下模型之一:
# 模型文件将自动下载,无需手动操作
yolov8n-pose.pt # 最快(轻量)
yolov8s-pose.pt # 较准
yolov8m-pose.pt # 精度更高
yolov8l-pose.pt # 更大模型
✅ 示例代码:YOLOv8-Pose 实时检测人物骨骼
from ultralytics import YOLO
import cv2# 加载模型
model = YOLO('yolov8n-pose.pt') # 或 yolov8m-pose.pt 等# 打开视频(可用手机视频流)
cap = cv2.VideoCapture('/path/to/your/video.mp4')while cap.isOpened():ret, frame = cap.read()if not ret:breakresults = model(frame)annotated_frame = results[0].plot() # 画出骨骼关键点cv2.imshow("Pose Estimation", annotated_frame)if cv2.waitKey(1) & 0xFF == ord('q'):breakcap.release()
cv2.destroyAllWindows()
这段代码使用了 yolov8n-pose.pt
(YOLOv8 的轻量级姿态识别模型),但在播放视频过程中卡顿,很可能是由于以下原因造成的:
✅ 卡顿可能原因分析
原因类别 | 说明 |
---|---|
模型性能瓶颈 | yolov8n-pose.pt 虽然是最小模型,但仍可能对低配 CPU 压力大 |
显示速度瓶颈 | cv2.imshow() 是同步操作,每帧都等待窗口刷新(受屏幕刷新率、OpenCV渲染影响) |
视频分辨率过高 | 如果视频是 1080P 或更高,会加重解码和模型推理的负担 |
无硬件加速 | YOLOv8 默认使用 CPU 推理,若没有启用 GPU,会慢很多 |
✅ 优化方案
✅ 1. 设置模型为半精度模式(加速推理)
model.half() # 仅在 CUDA/GPU 可用时有效(需确保模型也支持)
✅ 2. 降低输入图像尺寸
results = model(frame, imgsz=416) # 默认是 640,可改为 416 提高速度
✅ 3. 使用线程预读取视频帧(避免显示阻塞)
可以用 cv2.VideoCapture
配合线程读取帧(如需我提供代码也可说)。
✅ 4. 保存视频结果,避免实时显示卡顿
如果你主要是处理分析而不是观看,可以改为保存视频(显示太慢):
out = cv2.VideoWriter("pose_output.mp4", cv2.VideoWriter_fourcc(*'mp4v'), 20, (frame.shape[1], frame.shape[0])) while cap.isOpened(): ret, frame = cap.read() if not ret: break results = model(frame, imgsz=416) annotated_frame = results[0].plot() out.write(annotated_frame) out.release() cap.release()
✅ 5. 确认是否使用 GPU
如果你安装的是 ultralytics
的默认版本,它会自动调用 CUDA(如果有 GPU),否则使用 CPU:
import torch print("CUDA:", torch.cuda.is_available())
如果你没有用 GPU,但机器上有显卡,建议配置 PyTorch 的 CUDA 支持版本(我可以帮你装)。
✅ 6. 使用 TensorRT / OpenVINO 加速模型(高级优化)
适用于部署阶段,你可以将 YOLOv8 模型导出为:
yolo export model=yolov8n-pose.pt format=onnx
yolo export model=yolov8n-pose.pt format=tensorrt
✅ 总结推荐
方案 | 推荐程度 | 说明 |
---|---|---|
降低 imgsz=416 | ⭐⭐⭐⭐ | 简单直接,提升明显 |
保存视频而非显示 | ⭐⭐⭐⭐ | 避免实时显示阻塞 |
使用 GPU 加速 | ⭐⭐⭐⭐⭐ | 最大性能提升 |
导出为 TensorRT 加速 | ⭐⭐⭐ | 部署时推荐,高性能 |
🧪【优化版代码】(使用小模型、降分辨率、GPU、帧跳过)
import cv2
import numpy as np
from ultralytics import YOLO
from filterpy.kalman import KalmanFilter
import torch# 加载 YOLOv8 Nano Pose 模型
model = YOLO("yolov8n-pose.pt")
if torch.cuda.is_available():model.to('cuda')# 打开视频流
cap = cv2.VideoCapture('/Users/lianying/Desktop/yolo/和平精英/hpjy3.mp4')# 输出视频保存(可选)
out = cv2.VideoWriter("pose_output3.mp4", cv2.VideoWriter_fourcc(*'mp4v'), 25,(int(cap.get(3)), int(cap.get(4))))# 初始化卡尔曼滤波器
kf = KalmanFilter(dim_x=4, dim_z=2)
kf.x = np.array([0, 0, 0, 0])
kf.F = np.array([[1, 0, 1, 0],[0, 1, 0, 1],[0, 0, 1, 0],[0, 0, 0, 1]])
kf.H = np.array([[1, 0, 0, 0],[0, 1, 0, 0]])
kf.P *= 1000.0
kf.R = 5
kf.Q = np.eye(4)skeleton = [(5, 7), (7, 9), (6, 8), (8, 10), (11, 13), (13, 15),(12, 14), (14, 16), (5, 6), (11, 12), (0, 1), (1, 2),(2, 3), (3, 4)]frame_id = 0
skip_rate = 1 # 每隔几帧识别一次while True:ret, frame = cap.read()if not ret:breakframe_id += 1display_frame = frame.copy()# 降低分辨率处理resized = cv2.resize(frame, (416, 416))if frame_id % skip_rate == 0:results = model(resized, imgsz=416)[0]for pose in results.keypoints:keypoints = pose.xy[0].cpu().numpy()# 坐标映射回原图scale_x = frame.shape[1] / 416scale_y = frame.shape[0] / 416keypoints *= [scale_x, scale_y]cx, cy = keypoints[5:7].mean(axis=0)kf.predict()kf.update(np.array([cx, cy]))cx_kf, cy_kf = int(kf.x[0]), int(kf.x[1])cv2.circle(display_frame, (cx_kf, cy_kf), 5, (255, 0, 0), -1)for x, y in keypoints:cv2.circle(display_frame, (int(x), int(y)), 3, (0, 255, 0), -1)for i, j in skeleton:if keypoints[i][0] > 0 and keypoints[j][0] > 0:pt1 = tuple(np.int32(keypoints[i]))pt2 = tuple(np.int32(keypoints[j]))cv2.line(display_frame, pt1, pt2, (0, 255, 255), 2)cv2.imshow("Pose Tracking", display_frame)out.write(display_frame) # 如果需要保存if cv2.waitKey(1) & 0xFF == ord('q'):breakcap.release()
out.release()
cv2.destroyAllWindows()
yolo8模型训练+实时识别目标+骨骼关键点识别(和平精英敌人)
🎯添加动作识别(比如:蹲下、跳跃、开枪)
✅ 第一步:用关键点判断动作(规则法)
我们先用一种 简单有效的规则法,通过人体关键点的位置和角度判断动作。
🎯 支持识别的动作
动作 | 判定逻辑 |
---|---|
蹲下 | 膝盖高度接近或低于髋部 |
跳跃 | 脚部 Y 坐标明显上升 |
开枪 | 手部(腕)前伸、肩膀抬高 |
✅ 第二步:代码示例(集成到 YOLOv8 Pose 结果中)
以下是 在你现有代码基础上添加动作识别逻辑 的修改版:
def detect_action(keypoints):"""简单规则:根据关键点判断人物动作关键点索引说明(COCO格式):0:鼻 1:左眼 2:右眼 3:左耳 4:右耳5:左肩 6:右肩 7:左肘 8:右肘9:左腕 10:右腕 11:左髋 12:右髋13:左膝 14:右膝 15:左脚踝 16:右脚踝"""def y(i): # 返回某关键点y坐标return keypoints[i][1]def distance(p1, p2):return np.linalg.norm(keypoints[p1] - keypoints[p2])# 获取关键点存在性(某些关键点可能检测失败)valid = lambda i: keypoints[i][0] > 0 and keypoints[i][1] > 0if all(valid(i) for i in [11, 12, 13, 14]):hip_y = (y(11) + y(12)) / 2knee_y = (y(13) + y(14)) / 2if knee_y < hip_y - 20: # 蹲下,膝盖高于髋return "蹲下"if all(valid(i) for i in [15, 16]):ankle_avg_y = (y(15) + y(16)) / 2if ankle_avg_y < 300: # 跳跃(需要根据视频画面高度调整)return "跳跃"if all(valid(i) for i in [5, 6, 9, 10]):arm_len = (distance(5, 9) + distance(6, 10)) / 2if arm_len > 120: # 手臂伸直的距离(根据画面缩放调整)return "开枪"return None
✅ 整合到主循环中
你只需在你的 YOLOv8 主循环中这样调用:
for pose in results.keypoints:keypoints = pose.xy[0].cpu().numpy()# 调用动作识别函数action = detect_action(keypoints)if action:cv2.putText(frame, f"动作: {action}", (30, 60),cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
✅ 显示完整融合效果
你运行时将能看到:
-
骨架识别 ✅
-
人物动作识别并显示到屏幕 ✅
📌 提升建议(如需更准)
-
基于时序特征:
-
使用
LSTM
或Transformer
模型,对连续帧的关键点数据进行训练。 -
比如:开枪=“手臂突然向前伸+ recoil 反弹动作”。
-
-
自定义动作数据集:
-
用
keypoints
序列做样本,结合标签训练自己的动作分类模型。
-