深度学习篇---姿态检测实现
文章目录
- 前言
- 一、基于传统机器学习的方法
- 方法概述
- 特征提取
- 分类模型
- 实现代码
- 二、基于深度学习的方法
- 方法概述
- 端到端学习
- 卷积神经网络
- 迁移学习
- 实现代码
- 三、方法比较与选择
- 传统机器学习
- 优点
- 缺点
- 应用场景
- 深度学习
- 优点
- 缺点
- 复杂姿态检测
- 四、实际应用建议
- 从小规模开始
- 数据收集
- 模型优化:
- 调整超参数
- 部署考虑:
- 五、扩展方向
- 多类别分类
- 时序模型
- 3D姿态估计
- 集成其他传感器
前言
坐姿检测可以通过传统机器学习或深度学习方法实现。下面我将详细介绍两种方法,并提供相应的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.poseself.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 - angledef 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 Truereturn 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.poseself.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, predictionreturn 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'):breakcap.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'):breakcap.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_dirself.img_size = img_sizeself.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.0X_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.poseself.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.0img_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'):breakcap.release()cv2.destroyAllWindows()if __name__ == "__main__":# 第一步: 训练模型 (需要先准备数据集)# train_deep_learning_model()# 第二步: 使用训练好的模型检测run_deep_detection()
三、方法比较与选择
方法 优点 缺点 适用场景
传统机器学习
优点
- 需要较少数据
- 训练速度快
- 可解释性强
缺点
- 依赖特征工程
- 性能有限
应用场景
- 快速原型开发
- 资源受限环境
深度学习
优点
- 自动特征提取
- 更高的准确率
- 端到端学习
缺点
- 需要大量数据
- 计算资源需求高
- 训练时间长 高精度要求
复杂姿态检测
复杂姿势检测
四、实际应用建议
从小规模开始
从小规模开始:先尝试传统机器学习方法,验证概念可行性
数据收集
数据收集:收集多样化的坐姿数据(不同体型、光照条件等)
模型优化:
尝试不同的网络架构(ResNet, EfficientNet等)
调整超参数
使用数据增强提高泛化能力
部署考虑:
使用TensorFlow Lite或ONNX优化模型以便在移动端部署
考虑模型量化以减少计算资源需求
五、扩展方向
多类别分类
多类别分类:不仅判断好坏,还能识别具体问题(如头部前倾、驼背等)
时序模型
时序模型:使用LSTM或Transformer处理视频序列,提高检测稳定性
3D姿态估计
3D姿势估计:使用3D卷积网络或点云处理更精确的姿势信息
集成其他传感器
集成其他传感器:结合压力传感器或IMU数据提高准确性
以上两种方法都可以有效实现坐姿检测,选择哪种方法取决于你的具体需求、可用数据和计算资源。