現在需要識別人物的肢體(姿態/骨骼關鍵點),即所謂的「姿態估計(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
序列做樣本,結合標簽訓練自己的動作分類模型。
-
?