import cv2
import mediapipe as mp
import math
import pandas as pd

# 初始化MediaPipe的人体姿势模型
mp_drawing = mp.solutions.drawing_utils
mp_pose = mp.solutions.pose

# 打开输入视频文件
cap = cv2.VideoCapture('6.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))

# 读取存放骨骼角度信息的csv文件
warm_up_df = pd.read_csv('warm_up.csv')
combat_pose_df = pd.read_csv('combat_pose.csv')
attack_df = pd.read_csv('attack.csv')
respect_df = pd.read_csv('respect.csv')

# 处理视频文件中的每一帧
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]

            # 计算腿与右手的角度
            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.y))

            # 获取右肩、右肘和右手腕
            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))

            # 判断当前动作
            if (angle >= -16.5 and angle <= -8) and (angle_dr > 179 and angle_dr <= 186 or angle_dl > 182 and angle_dl <= 191):
                poses = 'warm-up'
                df = warm_up_df
            elif (angle > -20 and angle <= 5) and ((angle_dr > 130.5 and angle_dr <= 155) or (angle_dr > 205 and angle_dr <= 212)) and ((angle_tr > 239 and angle_tr <= 260) or (angle_tr > 147 and angle_tr <= 170)):
                poses = 'combat pose'
                df = combat_pose_df
            elif (angle > -20 and angle <= 5) and ((angle_tr > -175 and angle_tr <= -165) or (angle_tr > 115 and angle_tr <= 135)):
                poses = 'attack'
                df = attack_df
            elif (angle > -20 and angle <= 5) and (angle_tr > -43 and angle_tr <= -31 or angle_tr > -5 and angle_tr <= -1 or angle_tr > 54 and angle_tr <= 56):
                poses = 'respect'
                df = respect_df
            else:
                poses = ''

            # 在输出图片上显示角度值和动作
            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, poses, (600, 450),
                        cv2.FONT_HERSHEY_SIMPLEX, 0.5, (100, 225, 225), 2)

            # 判断当前帧是否属于当前动作
            if not df.empty:
                current_frame = results.pose_landmarks.landmark
                current_frame_data = []
                for landmark in current_frame:
                    current_frame_data.append(landmark.x)
                    current_frame_data.append(landmark.y)
                    current_frame_data.append(landmark.z)
                current_frame_df = pd.DataFrame([current_frame_data])
                similarity = df.subtract(current_frame_df).abs().sum().sum()
                if similarity < 200:
                    cv2.putText(frame, poses, (5, 20),
                                cv2.FONT_HERSHEY_COMPLEX_SMALL, 1.5, (225, 100, 225), 2)

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

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

代码运行后NameError: name 'df' is not defined报错解决内容:在程序中,如果当前帧被判断为某个动作,会根据该动作对应的数据集(即存放骨骼角度信息的csv文件)来判断当前帧是否属于该动作。如果属于,会在输出图片上显示该动作名称。

在判断当前帧是否属于某个动作时,需要使用变量df来存储对应的数据集。但是,在程序中,有可能没有对应的数据集,或者程序中还没有定义该变量,就会导致该报错。

解决方法是在程序中定义变量df,并在每个判断语句中进行赋值,以确保变量df在程序中始终存在。例如,在判断当前动作为“warm-up”时,可以添加以下代码:

df = warm_up_df

这样,即使程序中没有定义变量df,也不会报错。

Python MediaPipe 人体姿态检测识别动作

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

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