引言
随着计算机视觉技术的发展,姿态估计已经成为一项重要的研究领域,广泛应用于动作识别、虚拟现实、体育训练等多个场景。本文将介绍一个基于 OpenCV 和自定义姿态检测器的实时姿态跟踪系统。我们将从代码结构、功能实现以及关键知识点等方面进行详细讲解。
技术栈
- OpenCV:用于视频捕获和图像处理。
- 自定义姿态检测器:用于人体姿态估计。
代码结构
整个系统的代码分为几个部分:
- PoseDetector 类:负责姿态检测。
- PoseTracking 类:负责视频捕获和姿态跟踪。
- 主程序:初始化并运行姿态跟踪系统。
PoseDetector 类
首先,我们需要一个姿态检测器类来处理姿态检测。假设这个类已经实现,并且提供了 detect_pose_landmarks
方法来检测姿态关键点。
# utils/pose_detector.py
import cv2
class PoseDetector:
def __init__(self):
# 初始化姿态检测模型
self.mp_pose = mp.solutions.pose
self.pose = self.mp_pose.Pose()
def detect_pose_landmarks(self, img, show_pose_connections=True, show_landmarks=True, show_landmarks_id=True):
# 将图像转换为 RGB 格式
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 检测姿态关键点
results = self.pose.process(img_rgb)
if results.pose_landmarks:
# 绘制姿态连接线
if show_pose_connections:
mp_drawing.draw_landmarks(img, results.pose_landmarks, self.mp_pose.POSE_CONNECTIONS)
# 绘制姿态关键点
if show_landmarks:
for idx, landmark in enumerate(results.pose_landmarks.landmark):
h, w, c = img.shape
cx, cy = int(landmark.x * w), int(landmark.y * h)
cv2.circle(img, (cx, cy), 5, (0, 255, 0), cv2.FILLED)
# 显示关键点 ID
if show_landmarks_id:
cv2.putText(img, str(idx), (cx+5, cy+5), cv2.FONT_HERSHEY_PLAIN, 1, (0, 0, 255), 1)
# 返回姿态关键点字典
landmarks_dict = {}
if results.pose_landmarks:
for idx, landmark in enumerate(results.pose_landmarks.landmark):
landmarks_dict[idx] = {
'x': landmark.x,
'y': landmark.y,
'z': landmark.z,
'visibility': landmark.visibility
}
return landmarks_dict
PoseTracking 类
接下来,我们实现 PoseTracking
类,负责视频捕获和姿态跟踪。
import cv2
import time
from utils.pose_detector import PoseDetector
class PoseTracking:
"""
姿态跟踪
"""
def __init__(self):
# 初始化视频捕获设备
self.cap = cv2.VideoCapture(1)
# 初始化姿态检测器
self.pose_detector = PoseDetector()
def run(self):
# 记录上次帧的时间
last_time = time.time()
while self.cap.isOpened():
# 读取一帧图像
success, img = self.cap.read()
if not success:
break
# 检测姿态关键点
pose_landmarks_dict = self.pose_detector.detect_pose_landmarks(
img=img,
show_pose_connections=True,
show_landmarks=True,
show_landmarks_id=True
)
print(pose_landmarks_dict)
# 计算当前帧率
current_time = time.time()
fps = round(1.0 / (current_time - last_time), 2)
last_time = current_time
# 在图像上显示帧率
cv2.putText(img=img, text=f'fps: {fps}', org=(10, 20), fontFace=cv2.FONT_HERSHEY_SIMPLEX,
fontScale=0.6, color=(0, 0, 0), thickness=2)
# 显示图像
cv2.imshow('img', img)
# 按 'q' 键退出循环
if cv2.waitKey(1) & 0xff == ord('q'):
break
# 释放视频捕获设备
self.cap.release()
if __name__ == '__main__':
pt = PoseTracking()
pt.run()
代码详解
初始化
def __init__(self):
self.cap = cv2.VideoCapture(1)
self.pose_detector = PoseDetector()
cv2.VideoCapture(1)
:初始化视频捕获设备,参数1
表示连接到第二个摄像头(默认第一个摄像头为0
)。self.pose_detector = PoseDetector()
:初始化姿态检测器。
主循环
def run(self):
last_time = time.time()
while self.cap.isOpened():
success, img = self.cap.read()
if not success:
break
last_time = time.time()
:记录上次帧的时间。while self.cap.isOpened()
:进入主循环,直到视频捕获设备关闭。success, img = self.cap.read()
:读取一帧图像,success
表示读取是否成功,img
是读取到的图像。
姿态检测
pose_landmarks_dict = self.pose_detector.detect_pose_landmarks(
img=img,
show_pose_connections=True,
show_landmarks=True,
show_landmarks_id=True
)
print(pose_landmarks_dict)
self.pose_detector.detect_pose_landmarks(...)
:调用姿态检测器的detect_pose_landmarks
方法,传入图像和其他参数,返回姿态关键点字典。print(pose_landmarks_dict)
:打印姿态关键点字典,用于调试。
计算帧率
current_time = time.time()
fps = round(1.0 / (current_time - last_time), 2)
last_time = current_time
current_time = time.time()
:记录当前时间。fps = round(1.0 / (current_time - last_time), 2)
:计算帧率。last_time = current_time
:更新上次时间。
显示帧率和图像
cv2.putText(img=img, text=f'fps: {fps}', org=(10, 20), fontFace=cv2.FONT_HERSHEY_SIMPLEX,
fontScale=0.6, color=(0, 0, 0), thickness=2)
cv2.imshow('img', img)
cv2.putText(...)
:在图像上显示帧率。cv2.imshow('img', img)
:显示图像。
退出条件
if cv2.waitKey(1) & 0xff == ord('q'):
break
cv2.waitKey(1) & 0xff == ord('q')
:等待按键输入,按q
键退出循环。
释放资源
self.cap.release()
self.cap.release()
:释放视频捕获设备。
总结
本文详细介绍了如何使用 OpenCV 和自定义姿态检测器实现一个实时姿态跟踪系统。通过本文的学习,你将能够理解姿态检测的基本原理,并掌握如何在实际项目中应用这些技术。