现在需要识别人物的肢体(姿态/骨骼关键点),即所谓的「姿态估计(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:
break
results = model(frame)
annotated_frame = results[0].plot() # 画出骨骼关键点
cv2.imshow("Pose Estimation", annotated_frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.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:
break
frame_id += 1
display_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] / 416
scale_y = frame.shape[0] / 416
keypoints *= [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'):
break
cap.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] > 0
if all(valid(i) for i in [11, 12, 13, 14]):
hip_y = (y(11) + y(12)) / 2
knee_y = (y(13) + y(14)) / 2
if knee_y < hip_y - 20: # 蹲下,膝盖高于髋
return "蹲下"
if all(valid(i) for i in [15, 16]):
ankle_avg_y = (y(15) + y(16)) / 2
if ankle_avg_y < 300: # 跳跃(需要根据视频画面高度调整)
return "跳跃"
if all(valid(i) for i in [5, 6, 9, 10]):
arm_len = (distance(5, 9) + distance(6, 10)) / 2
if 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
序列做样本,结合标签训练自己的动作分类模型。