基于KNN分类器的人体姿势识别算法

本算法利用KNN分类器对输入视频中的人体姿势进行检测和分类,输出每一帧的动作类型,并绘制头部关键点。

算法流程

  1. 初始化MediaPipe的人体姿势模型。
  2. 加载动作数据集,并将数据集合并为一个大的数据集。
  3. 训练KNN分类器。
  4. 处理视频文件中的每一帧: a. 读取一帧。 b. 将帧转换为RGB格式。 c. 处理人体姿势检测。 d. 判断是否检测到人体。 e. 获取关键点的信息,并计算角度。 f. 将数据输入KNN分类器进行预测。 g. 在输出图片上显示角度值和动作类型。 h. 绘制头部关键点。 i. 将帧写入输出视频文件。 j. 显示当前帧的结果。 k. 检测是否按下q键退出。
  5. 释放资源。

复杂度分析

时间复杂度: 算法的时间复杂度主要来自于人体姿势检测和KNN分类器的训练和预测过程,其中人体姿势检测的时间复杂度为O(n),KNN分类器的训练和预测的时间复杂度为O(m^2),其中n为关键点的数量,m为数据集的大小。因此,算法的时间复杂度为O(nm^2)。

空间复杂度: 算法的空间复杂度主要来自于存储动作数据集和KNN分类器,其中动作数据集的空间复杂度为O(mn),KNN分类器的空间复杂度为O(m^2),其中n为关键点的数量,m为数据集的大小。因此,算法的空间复杂度为O(mn + m^2)。

代码示例

import cv2
import mediapipe as mp
import math
import pandas as pd
from sklearn.neighbors import KNeighborsClassifier
i=0
# 初始化MediaPipe的人体姿势模型
mp_drawing = mp.solutions.drawing_utils
mp_pose = mp.solutions.pose

# 打开输入视频文件
cap = cv2.VideoCapture('9.mp4')

# 获取输入视频的帧率和分辨率
fps = int(cap.get(cv2.CAP_PROP_FPS))
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))

# 创建输出视频文件
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter('9_1.mp4', fourcc, fps, (width, height))

# 加载动作数据集
warmup_df = pd.read_csv('dataset_warm-up.csv')
combat_df = pd.read_csv('dataset_SHIZHAN POSE.csv')
attack_df = pd.read_csv('dataset_hit.csv')
respect_df = pd.read_csv('dataset_respect.csv')
gongbu_df = pd.read_csv('dataset_gongbu.csv')

# 将数据集合并为一个大的数据集
data = pd.concat([warmup_df, combat_df, attack_df, respect_df,gongbu_df], ignore_index=True)

# 训练KNN分类器
knn = KNeighborsClassifier(n_neighbors=3)
knn.fit(data[['angle1','angle2','angle3', 'angle4','angle5' ,'angle6', "angle7","angle8","angle9","angle10","angle11"]], data['label'])

# 处理视频文件中的每一帧
with mp_pose.Pose(min_detection_confidence=0.5, min_tracking_confidence=0.5) as pose:
    while cap.isOpened():
        # 读取一帧
        ret, frame = cap.read()
        if not ret:
            break

        # 将帧转换为RGB格式
        image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

        # 处理人体姿势检测
        results = pose.process(image)

        # 判断是否检测到人体
        if results.pose_landmarks:
            # 绘制人体骨架
            mp_drawing.draw_landmarks(
                frame, results.pose_landmarks, mp_pose.POSE_CONNECTIONS)

            # 获取右膝、右踝和右手腕关键点的信息
            right_knee = results.pose_landmarks.landmark[mp_pose.PoseLandmark.RIGHT_KNEE]
            right_ankle = results.pose_landmarks.landmark[mp_pose.PoseLandmark.RIGHT_ANKLE]
            right_wrist = results.pose_landmarks.landmark[mp_pose.PoseLandmark.RIGHT_WRIST]

            # 获取左肩、左肘和左手腕关键点的信息
            left_shoulder = results.pose_landmarks.landmark[mp_pose.PoseLandmark.LEFT_SHOULDER]
            left_elbow = results.pose_landmarks.landmark[mp_pose.PoseLandmark.LEFT_ELBOW]
            left_wrist = results.pose_landmarks.landmark[mp_pose.PoseLandmark.LEFT_WRIST]

            # 获取右肩、右肘和右手腕关键点的信息
            right_shoulder = results.pose_landmarks.landmark[mp_pose.PoseLandmark.RIGHT_SHOULDER]
            right_elbow = results.pose_landmarks.landmark[mp_pose.PoseLandmark.RIGHT_ELBOW]
            right_wrist = results.pose_landmarks.landmark[mp_pose.PoseLandmark.RIGHT_WRIST]

            # 获取左臀、左膝和左踝关键点的信息
            left_hip = results.pose_landmarks.landmark[mp_pose.PoseLandmark.LEFT_HIP]
            left_knee = results.pose_landmarks.landmark[mp_pose.PoseLandmark.LEFT_KNEE]
            left_ankle = results.pose_landmarks.landmark[mp_pose.PoseLandmark.LEFT_ANKLE]

            # 获取右臀、右膝和右踝关键点的信息
            right_hip = results.pose_landmarks.landmark[mp_pose.PoseLandmark.RIGHT_HIP]
            right_knee = results.pose_landmarks.landmark[mp_pose.PoseLandmark.RIGHT_KNEE]
            right_ankle = results.pose_landmarks.landmark[mp_pose.PoseLandmark.RIGHT_ANKLE]

            # 获取左肩、左肘和左手腕关键点的信息 new
            left_shoulder = results.pose_landmarks.landmark[mp_pose.PoseLandmark.LEFT_SHOULDER]
            left_elbow = results.pose_landmarks.landmark[mp_pose.PoseLandmark.LEFT_ELBOW]
            left_wrist = results.pose_landmarks.landmark[mp_pose.PoseLandmark.LEFT_WRIST]

            # 计算腿与右手的角度
            angle = math.degrees(math.atan2(right_wrist.y - right_ankle.y, right_wrist.x - right_ankle.x) -
                                 math.atan2(right_knee.y - right_ankle.y, right_knee.x - right_ankle.x))

            # 获取左肩、左肘和左手腕
            angle1 = math.degrees(math.atan2(right_wrist.y - right_ankle.y, right_wrist.x - right_ankle.x) -
                                  math.atan2(right_knee.y - right_ankle.y, right_knee.x - right_ankle.x))

            # 获取左臀、左膝和左踝
            angle_dl = math.degrees(math.atan2(left_ankle.y - left_knee.y, left_ankle.x - left_knee.x) -
                                    math.atan2(left_hip.y - left_knee.y, left_hip.x - left_knee.x))

            # 获取右臀、右膝和右踝
            angle_dr = math.degrees(math.atan2(right_ankle.y - right_knee.y, right_ankle.x - right_knee.x) -
                                    math.atan2(right_hip.y - right_knee.y, right_hip.x - right_knee.x))

            # 获取右肩、右肘和右手腕
            angle_tr = math.degrees(math.atan2(right_wrist.y - right_elbow.y, right_wrist.x - right_elbow.x) -
                                    math.atan2(right_shoulder.y - right_elbow.y, right_shoulder.x - right_elbow.x))

            # 获取左肩、左肘和左手腕 new
            angle_tl = math.degrees(math.atan2(left_wrist.y - left_elbow.y, left_wrist.x - left_elbow.x) -
                                    math.atan2(left_shoulder.y - left_elbow.y, left_shoulder.x - left_elbow.x))


            ##############
            #获取左髋、左膝和左踝关键点的信息
            left_hip = results.pose_landmarks.landmark[mp_pose.PoseLandmark.LEFT_HIP]
            left_knee = results.pose_landmarks.landmark[mp_pose.PoseLandmark.LEFT_KNEE]
            left_ankle = results.pose_landmarks.landmark[mp_pose.PoseLandmark.LEFT_ANKLE]

            # 获取左髋、左膝和左踝的角度
            angle_lka = math.degrees(math.atan2(left_ankle.y - left_knee.y, left_ankle.x - left_knee.x) -
                                     math.atan2(left_hip.y - left_knee.y, left_hip.x - left_knee.x))

            # 获取腰部、左髋和左肩的角度
            waist = results.pose_landmarks.landmark[12]
            angle_hls = math.degrees(math.atan2(left_shoulder.y - waist.y, left_shoulder.x - waist.x) -
                                     math.atan2(left_hip.y - waist.y, left_hip.x - waist.x))

            # 获取右髋、右膝和右踝关键点的信息
            right_hip = results.pose_landmarks.landmark[mp_pose.PoseLandmark.RIGHT_HIP]
            right_knee = results.pose_landmarks.landmark[mp_pose.PoseLandmark.RIGHT_KNEE]
            right_ankle = results.pose_landmarks.landmark[mp_pose.PoseLandmark.RIGHT_ANKLE]

            # 获取右髋、右膝和右踝的角度
            angle_rka = math.degrees(math.atan2(right_ankle.y - right_knee.y, right_ankle.x - right_knee.x) -
                                     math.atan2(right_hip.y - right_knee.y, right_hip.x - right_knee.y))

            # 获取腰部、右髋和右肩的角度
            angle_hrs = math.degrees(math.atan2(right_shoulder.y - waist.y, right_shoulder.x - waist.x) -
                                     math.atan2(right_hip.y - waist.y, right_hip.x - waist.y))
            ##################
            # 获取鼻子、右肩和右手腕关键点的信息
            nose = results.pose_landmarks.landmark[mp_pose.PoseLandmark.NOSE]
            right_shoulder = results.pose_landmarks.landmark[mp_pose.PoseLandmark.RIGHT_SHOULDER]
            right_wrist = results.pose_landmarks.landmark[mp_pose.PoseLandmark.RIGHT_WRIST]

            # 获取鼻子、右肩和右手腕的角度
            angle_nwr = math.degrees(math.atan2(right_wrist.y - nose.y, right_wrist.x - nose.x) -
                                     math.atan2(right_shoulder.y - nose.y, right_shoulder.x - nose.x))


            # 将数据输入KNN分类器进行预测


            label = knn.predict([[angle, angle1, angle_dl, angle_dr, angle_tr, angle_tl,angle_lka,angle_hls,angle_rka,angle_hrs,angle_nwr]])



            # 在输出图片上显示角度值和动作类型
            # cv2.putText(frame, "Angle: {:.2f}".format(angle), (5, 43),
            #             cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
            #
            # cv2.putText(frame, "Angle_tr: {:.2f}".format(angle_tr), (5, 60),
            #             cv2.FONT_HERSHEY_SIMPLEX, 0.5, (100, 15, 255), 2)
            #
            # cv2.putText(frame, "Angle_dr: {:.2f}".format(angle_dr), (5, 80),
            #             cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 100, 255), 2)

            cv2.putText(frame, label[0], (5, 60),
                        cv2.FONT_HERSHEY_SIMPLEX, 1.1, (255, 100, 100), 2)
            # 绘制头部关键点
            nose = results.pose_landmarks.landmark[mp_pose.PoseLandmark.NOSE]
            x, y = int(nose.x * width), int(nose.y * height)
            cv2.circle(frame, (x, y), 20, (220, 200, 100), -1)

        else:
            # 如果未检测到人体,则跳过本帧处理
            cv2.putText(frame, "No body detected", (50, 50),
                        cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)

        # 将帧写入输出视频文件
        out.write(frame)

        # 显示当前帧的结果
        cv2.imshow('MediaPipe Pose Detection press q exit', frame)

        # 检测是否按下q键退出
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

# 释放资源
cap.release()
out.release()
cv2.destroyAllWindows()
基于KNN分类器的人体姿势识别算法:对视频中动作进行检测和分类

原文地址: https://www.cveoy.top/t/topic/gL0C 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录