OpenCV 人体姿态检测实战指南
目录
简介
人体姿态检测是计算机视觉中的一个重要任务,它可以识别和分析图片中人体的关键点位置,广泛应用于姿势分析、健康评估、运动指导等领域。本文将详细介绍如何使用 OpenCV 和 MediaPipe 实现图片中的人体姿态检测。
效果
输入图片
姿态检测效果图
技术栈
- OpenCV:图像处理
- MediaPipe:人体姿态检测模型
- Python:编程语言
- NumPy:数值计算
[在这里插入人体姿态检测效果图]
建议截图:展示检测到的人体关键点和骨架连接
环境配置
1. 安装必要的库
# requirements.txt
opencv-python==4.8.0
mediapipe==0.10.0
numpy==1.24.0
安装命令:
pip install -r requirements.txt
2. 基本环境检查
import cv2
import mediapipe as mp
import numpy as np
def check_environment():
print(f"OpenCV Version: {cv2.__version__}")
print(f"MediaPipe Version: {mp.__version__}")
print(f"NumPy Version: {np.__version__}")
check_environment()
基础知识
1. 人体关键点
MediaPipe Pose 模型可以检测 33 个人体关键点:
- 0-10:面部关键点
- 11-22:上半身关键点
- 23-32:下半身关键点
[在这里插入人体关键点示意图]
建议截图:标注好的人体关键点索引图
2. 坐标系统
- x, y:2D 图像坐标(像素)
- z:深度信息(相对值)
- visibility:可见性分数
- presence:存在性分数
实现方案
1. 基础实现
import cv2
import mediapipe as mp
import numpy as np
class PoseDetector:
def __init__(self, static_image_mode=True,
model_complexity=1,
smooth_landmarks=True,
min_detection_confidence=0.5):
"""
初始化姿态检测器
"""
self.static_image_mode = static_image_mode
self.model_complexity = model_complexity
self.smooth_landmarks = smooth_landmarks
self.min_detection_confidence = min_detection_confidence
self.mp_pose = mp.solutions.pose
self.pose = self.mp_pose.Pose(
static_image_mode=self.static_image_mode,
model_complexity=self.model_complexity,
smooth_landmarks=self.smooth_landmarks,
min_detection_confidence=self.min_detection_confidence
)
self.mp_draw = mp.solutions.drawing_utils
def find_pose(self, img, draw=True):
"""
检测姿态并绘制关键点和连接线
"""
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
self.results = self.pose.process(img_rgb)
if self.results.pose_landmarks:
if draw:
self.mp_draw.draw_landmarks(
img,
self.results.pose_landmarks,
self.mp_pose.POSE_CONNECTIONS
)
return img
def find_position(self, img, draw=True):
"""
获取所有关键点的位置
"""
lm_list = []
if self.results.pose_landmarks:
for id, lm in enumerate(self.results.pose_landmarks.landmark):
h, w, c = img.shape
cx, cy = int(lm.x * w), int(lm.y * h)
lm_list.append([id, cx, cy, lm.visibility])
if draw:
cv2.circle(img, (cx, cy), 5, (255, 0, 0), cv2.FILLED)
return lm_list
2. 图片处理示例
def process_image(image_path):
# 读取图片
img = cv2.imread(image_path)
if img is None:
raise ValueError("无法读取图片")
# 创建检测器
detector = PoseDetector()
# 检测姿态
img = detector.find_pose(img)
lm_list = detector.find_position(img)
# 保存结果
output_path = "output_" + image_path.split("/")[-1]
cv2.imwrite(output_path, img)
return lm_list
def main():
# 处理单张图片
image_path = "example.jpg"
try:
lm_list = process_image(image_path)
print(f"检测到 {len(lm_list)} 个关键点")
except Exception as e:
print(f"处理图片时出错: {str(e)}")
if __name__ == "__main__":
main()
代码实战
1. 角度计算
def calculate_angle(self, point1, point2, point3):
"""
计算三个点形成的角度
"""
point1 = np.array(point1)
point2 = np.array(point2)
point3 = np.array(point3)
radians = np.arctan2(point3[1]-point2[1], point3[0]-point2[0]) - \
np.arctan2(point1[1]-point2[1], point1[0]-point2[0])
angle = np.abs(radians*180.0/np.pi)
if angle > 180.0:
angle = 360-angle
return angle
2. 姿势分析示例
def analyze_pose(self, lm_list):
"""
分析图片中的姿势
"""
if len(lm_list) < 33:
return "未检测到姿势"
# 计算手臂角度
right_elbow_angle = self.calculate_angle(
[lm_list[12][1:3]], # 右肩
[lm_list[14][1:3]], # 右肘
[lm_list[16][1:3]] # 右手腕
)
# 判断姿势
if right_elbow_angle > 150:
return "手臂伸展"
elif right_elbow_angle < 30:
return "手臂弯曲"
else:
return "中间位置"
优化技巧
1. 性能优化
# 1. 调整图片大小
def resize_image(image, max_size=1024):
h, w = image.shape[:2]
if max(h, w) > max_size:
scale = max_size / max(h, w)
new_size = (int(w * scale), int(h * scale))
return cv2.resize(image, new_size, interpolation=cv2.INTER_AREA)
return image
# 2. 使用GPU加速(如果可用)
if cv2.cuda.getCudaEnabledDeviceCount() > 0:
gpu_image = cv2.cuda_GpuMat()
2. 准确度优化
def enhance_image(image):
"""
图像增强处理
"""
# 亮度和对比度调整
alpha = 1.2 # 对比度
beta = 10 # 亮度
enhanced = cv2.convertScaleAbs(image, alpha=alpha, beta=beta)
# 降噪
denoised = cv2.fastNlMeansDenoisingColored(enhanced)
return denoised
应用场景
-
姿势评估
- 瑜伽姿势分析
- 运动姿势评估
- 体态分析
-
健康检查
- 脊椎姿态评估
- 站姿分析
- 步态分析
-
人体测量
- 人体尺寸测量
- 体态评估
- 姿势矫正
常见问题
1. 检测不准确
问题:姿态检测结果不准确
解决方案:
- 确保图片质量良好
- 调整图片亮度和对比度
- 选择合适的拍摄角度
2. 性能问题
问题:处理大图片速度慢
解决方案:
- 压缩图片尺寸
- 使用GPU加速
- 优化处理流程
3. 遮挡处理
问题:部分身体被遮挡时检测失败
解决方案:
- 选择更好的拍摄角度
- 确保光线充足
- 调整检测参数
进阶开发
1. 批量图片处理
def process_image_batch(image_dir):
"""
批量处理图片
"""
detector = PoseDetector()
results = {}
for image_file in os.listdir(image_dir):
if image_file.lower().endswith(('.png', '.jpg', '.jpeg')):
image_path = os.path.join(image_dir, image_file)
try:
img = cv2.imread(image_path)
if img is None:
continue
# 处理图片
img = detector.find_pose(img)
lm_list = detector.find_position(img)
# 保存结果
output_path = os.path.join("output", image_file)
cv2.imwrite(output_path, img)
results[image_file] = len(lm_list)
except Exception as e:
print(f"处理 {image_file} 时出错: {str(e)}")
return results
2. 姿势分类
class PoseClassifier:
def __init__(self):
self.pose_detector = PoseDetector()
self.pose_templates = {}
def add_template(self, name, keypoints):
"""
添加姿势模板
"""
self.pose_templates[name] = keypoints
def classify_pose(self, image):
"""
对图片中的姿势进行分类
"""
img = self.pose_detector.find_pose(image)
lm_list = self.pose_detector.find_position(img)
if not lm_list:
return None
# 计算与模板的相似度
return self.match_pose(lm_list)
结语
OpenCV 和 MediaPipe 的组合为实现图片中的人体姿态检测提供了强大的工具。通过本文的学习,你应该已经掌握了:
- 基础的姿态检测实现
- 关键点提取和分析
- 图片处理优化技巧
- 实际应用开发方法
建议在实践中:
- 注意图片质量
- 合理处理异常情况
- 考虑性能优化
- 结合实际应用需求