深度学习篇---姿态检测实现
·
文章目录
前言
坐姿检测可以通过传统机器学习或深度学习方法实现。下面我将详细介绍两种方法,并提供相应的Python实现代码。
一、基于传统机器学习的方法
方法概述
特征提取
特征提取:从姿势关键点中提取特征(角度、距离等)
分类模型
分类模型:使用机器学习分类器判断坐姿是否正确
实现代码
import cv2
import mediapipe as mp
import numpy as np
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import joblib
# 数据收集和特征提取
class PostureDataCollector:
def __init__(self):
self.mp_pose = mp.solutions.pose
self.pose = self.mp_pose.Pose()
self.dataset = []
self.labels = []
def extract_features(self, landmarks):
"""从关键点中提取特征"""
features = []
# 获取关键点坐标
left_shoulder = landmarks[11][1:3]
right_shoulder = landmarks[12][1:3]
left_ear = landmarks[7][1:3]
right_ear = landmarks[8][1:3]
left_hip = landmarks[23][1:3]
right_hip = landmarks[24][1:3]
# 计算中点
shoulder_mid = np.mean([left_shoulder, right_shoulder], axis=0)
ear_mid = np.mean([left_ear, right_ear], axis=0)
hip_mid = np.mean([left_hip, right_hip], axis=0)
# 1. 脊柱角度 (肩膀-髋部-垂直线)
spine_angle = self.calculate_angle(
(shoulder_mid[0], shoulder_mid[1] - 100),
shoulder_mid,
hip_mid
)
features.append(spine_angle)
# 2. 颈部角度 (耳朵-肩膀-水平线)
neck_angle = self.calculate_angle(
(ear_mid[0] - 100, ear_mid[1]),
ear_mid,
shoulder_mid
)
features.append(neck_angle)
# 3. 肩膀倾斜度
shoulder_slope = (right_shoulder[1] - left_shoulder[1]) / (
right_shoulder[0] - left_shoulder[0] + 1e-6)
features.append(shoulder_slope)
# 4. 耳朵到肩膀的距离
ear_to_shoulder = np.linalg.norm(ear_mid - shoulder_mid)
features.append(ear_to_shoulder)
# 5. 肩膀到髋部的距离
shoulder_to_hip = np.linalg.norm(shoulder_mid - hip_mid)
features.append(shoulder_to_hip)
return np.array(features)
def calculate_angle(self, a, b, c):
"""计算三个点之间的角度"""
a, b, c = np.array(a), np.array(b), np.array(c)
radians = np.arctan2(c[1]-b[1], c[0]-b[0]) - np.arctan2(a[1]-b[1], a[0]-b[0])
angle = np.abs(radians * 180.0 / np.pi)
return angle if angle <= 180 else 360 - angle
def collect_data(self, img, label):
"""收集数据并提取特征"""
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
results = self.pose.process(img_rgb)
if results.pose_landmarks:
landmarks = []
for id, lm in enumerate(results.pose_landmarks.landmark):
h, w = img.shape[:2]
landmarks.append([id, int(lm.x * w), int(lm.y * h), lm.z])
features = self.extract_features(landmarks)
self.dataset.append(features)
self.labels.append(label)
return True
return False
# 训练机器学习模型
def train_model(X, y):
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 使用随机森林分类器
model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X_train, y_train)
# 评估模型
y_pred = model.predict(X_test)
print(f"Accuracy: {accuracy_score(y_test, y_pred):.2f}")
# 保存模型
joblib.dump(model, 'posture_model.pkl')
return model
# 使用训练好的模型进行坐姿检测
class MLPostureDetector:
def __init__(self, model_path):
self.mp_pose = mp.solutions.pose
self.pose = self.mp_pose.Pose()
self.model = joblib.load(model_path)
self.data_collector = PostureDataCollector()
def detect(self, img):
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
results = self.pose.process(img_rgb)
if results.pose_landmarks:
landmarks = []
for id, lm in enumerate(results.pose_landmarks.landmark):
h, w = img.shape[:2]
landmarks.append([id, int(lm.x * w), int(lm.y * h), lm.z])
features = self.data_collector.extract_features(landmarks)
prediction = self.model.predict([features])[0]
# 可视化结果
cv2.putText(img, f"Posture: {'Good' if prediction == 1 else 'Bad'}",
(10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7,
(0, 255, 0) if prediction == 1 else (0, 0, 255), 2)
return img, prediction
return img, None
# 数据收集示例
def collect_training_data():
collector = PostureDataCollector()
cap = cv2.VideoCapture(0)
print("Collecting GOOD posture data - Sit straight (Press 'g' to capture)")
print("Collecting BAD posture data - Slouch (Press 'b' to capture)")
print("Press 'q' to finish and train model")
while True:
_, img = cap.read()
cv2.imshow("Data Collection", img)
key = cv2.waitKey(1)
if key == ord('g'): # 收集良好坐姿数据
if collector.collect_data(img, 1):
print("Good posture sample collected")
elif key == ord('b'): # 收集不良坐姿数据
if collector.collect_data(img, 0):
print("Bad posture sample collected")
elif key == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
# 训练模型
if len(collector.dataset) > 0:
X = np.array(collector.dataset)
y = np.array(collector.labels)
train_model(X, y)
# 使用模型检测示例
def run_detection():
detector = MLPostureDetector('posture_model.pkl')
cap = cv2.VideoCapture(0)
while True:
_, img = cap.read()
img, posture = detector.detect(img)
cv2.imshow("Posture Detection", img)
if cv2.waitKey(1) == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
if __name__ == "__main__":
# 第一步: 收集数据
# collect_training_data()
# 第二步: 使用训练好的模型检测
run_detection()
二、基于深度学习的方法
方法概述
端到端学习
端到端学习:直接使用原始图像作为输入
卷积神经网络
卷积神经网络:自动学习坐姿特征
迁移学习
迁移学习:使用预训练模型提高性能
实现代码
import cv2
import numpy as np
import tensorflow as tf
from tensorflow.keras import layers, models, applications
from tensorflow.keras.preprocessing.image import ImageDataGenerator
import os
from sklearn.model_selection import train_test_split
# 数据准备
class PostureDataset:
def __init__(self, data_dir, img_size=(224, 224)):
self.data_dir = data_dir
self.img_size = img_size
self.classes = ['good', 'bad']
self.data = []
self.labels = []
def load_data(self):
for class_idx, class_name in enumerate(self.classes):
class_dir = os.path.join(self.data_dir, class_name)
for img_name in os.listdir(class_dir):
img_path = os.path.join(class_dir, img_name)
img = cv2.imread(img_path)
img = cv2.resize(img, self.img_size)
self.data.append(img)
self.labels.append(class_idx)
self.data = np.array(self.data)
self.labels = np.array(self.labels)
return self.data, self.labels
# 构建深度学习模型
def build_model(input_shape, num_classes):
# 使用预训练的MobileNetV2作为基础模型
base_model = applications.MobileNetV2(
input_shape=input_shape,
include_top=False,
weights='imagenet'
)
# 冻结基础模型权重
base_model.trainable = False
# 添加自定义层
model = models.Sequential([
base_model,
layers.GlobalAveragePooling2D(),
layers.Dense(128, activation='relu'),
layers.Dropout(0.5),
layers.Dense(num_classes, activation='softmax')
])
model.compile(
optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
return model
# 数据增强
def create_datagen():
return ImageDataGenerator(
rotation_range=15,
width_shift_range=0.1,
height_shift_range=0.1,
shear_range=0.1,
zoom_range=0.1,
horizontal_flip=True,
fill_mode='nearest'
)
# 训练模型
def train_deep_learning_model():
# 准备数据
dataset = PostureDataset('posture_dataset')
X, y = dataset.load_data()
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42)
# 数据归一化
X_train = X_train / 255.0
X_test = X_test / 255.0
# 构建模型
model = build_model(X_train[0].shape, len(dataset.classes))
# 数据增强
datagen = create_datagen()
train_generator = datagen.flow(X_train, y_train, batch_size=32)
# 训练模型
history = model.fit(
train_generator,
epochs=20,
validation_data=(X_test, y_test)
)
# 保存模型
model.save('posture_cnn.h5')
return model
# 使用深度学习模型进行坐姿检测
class DeepPostureDetector:
def __init__(self, model_path):
self.model = tf.keras.models.load_model(model_path)
self.mp_pose = mp.solutions.pose
self.pose = self.mp_pose.Pose()
self.img_size = (224, 224)
def detect(self, img):
# 预处理图像
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img_resized = cv2.resize(img_rgb, self.img_size)
img_normalized = img_resized / 255.0
img_expanded = np.expand_dims(img_normalized, axis=0)
# 预测
prediction = self.model.predict(img_expanded)
class_idx = np.argmax(prediction)
confidence = np.max(prediction)
# 可视化结果
label = "Good" if class_idx == 0 else "Bad"
color = (0, 255, 0) if class_idx == 0 else (0, 0, 255)
cv2.putText(img, f"Posture: {label} ({confidence:.2f})",
(10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, color, 2)
return img, class_idx
# 实时检测示例
def run_deep_detection():
detector = DeepPostureDetector('posture_cnn.h5')
cap = cv2.VideoCapture(0)
while True:
_, img = cap.read()
img, posture = detector.detect(img)
cv2.imshow("Deep Posture Detection", img)
if cv2.waitKey(1) == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
if __name__ == "__main__":
# 第一步: 训练模型 (需要先准备数据集)
# train_deep_learning_model()
# 第二步: 使用训练好的模型检测
run_deep_detection()
三、方法比较与选择
方法 优点 缺点 适用场景
传统机器学习
优点
- 需要较少数据
- 训练速度快
- 可解释性强
缺点
- 依赖特征工程
- 性能有限
应用场景
- 快速原型开发
- 资源受限环境
深度学习
优点
- 自动特征提取
- 更高的准确率
- 端到端学习
缺点
- 需要大量数据
- 计算资源需求高
- 训练时间长 高精度要求
复杂姿态检测
复杂姿势检测
四、实际应用建议
从小规模开始
从小规模开始:先尝试传统机器学习方法,验证概念可行性
数据收集
数据收集:收集多样化的坐姿数据(不同体型、光照条件等)
模型优化:
尝试不同的网络架构(ResNet, EfficientNet等)
调整超参数
使用数据增强提高泛化能力
部署考虑:
使用TensorFlow Lite或ONNX优化模型以便在移动端部署
考虑模型量化以减少计算资源需求
五、扩展方向
多类别分类
多类别分类:不仅判断好坏,还能识别具体问题(如头部前倾、驼背等)
时序模型
时序模型:使用LSTM或Transformer处理视频序列,提高检测稳定性
3D姿态估计
3D姿势估计:使用3D卷积网络或点云处理更精确的姿势信息
集成其他传感器
集成其他传感器:结合压力传感器或IMU数据提高准确性
以上两种方法都可以有效实现坐姿检测,选择哪种方法取决于你的具体需求、可用数据和计算资源。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

所有评论(0)