使用 MediaPipe 和 KNN 识别视频中的人体动作
这个代码使用 MediaPipe 和 KNN 分类器来识别视频中的人体动作。
首先,代码导入必要的库,包括 cv2 用于图像处理,mediapipe 用于人体姿势检测,pandas 用于数据处理,以及 sklearn.neighbors 用于 KNN 分类器。
接下来,初始化 MediaPipe 的人体姿势模型,并打开输入视频文件。代码获取视频的帧率和分辨率,并创建一个输出视频文件。
然后,代码加载动作数据集,包括热身、格斗、攻击、尊重和公布动作。这些数据集中包含了不同动作的姿势数据。
接着,代码将所有数据集合并为一个大的数据集,并使用 KNN 分类器进行训练。KNN 分类器根据最近邻的训练样本对测试样本进行分类。
最后,代码逐帧处理视频文件。对于每一帧,代码使用 MediaPipe 检测人体姿势,获取关键点坐标信息,并将这些信息输入 KNN 分类器进行预测。最后,代码将动作类型显示在输出视频中。
如果检测到人体,代码会绘制人体姿势并显示动作类型;如果未检测到人体,则会显示"No body detected"。
import cv2
import mediapipe as mp
import pandas as pd
from sklearn.neighbors import KNeighborsClassifier
# 初始化 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_1.csv')
combat_df = pd.read_csv('dataset_3.csv')
attack_df = pd.read_csv('dataset_2.csv')
respect_df = pd.read_csv('dataset_4.csv')
gongbu_df = pd.read_csv('dataset_5.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.iloc[:, :-1], 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)
# 获取人体姿势信息
pose_data = []
keypoints = [0, 11, 12, 13, 14, 15, 16, 23, 24, 25, 26, 27, 28] # 需要的关键点的索引
for i in keypoints:
landmark = results.pose_landmarks.landmark[i]
if landmark.visibility < 0.5: # 如果关键点可见度小于 0.5,则跳过
continue
pose_data.append(landmark.x)
pose_data.append(landmark.y)
# pose_data.append(landmark.z if landmark.z is not None else 0)
# 将姿势信息输入 KNN 分类器进行预测
label = knn.predict([pose_data])
# 在输出图片上显示动作类型
cv2.putText(frame, label[0], (5, 60),
cv2.FONT_HERSHEY_SIMPLEX, 1.1, (255, 100, 100), 2)
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()
这个错误不是视频读取问题,而是与线程池相关的问题。可能是线程池控制器(threadpoolctl)的版本问题或配置问题导致的。可以尝试更新线程池控制器或者检查配置文件是否正确。也可以尝试在代码中禁用线程池控制器,例如:
import os
os.environ['THREADPOOLCTL_VERSION'] = '0.0.0' # 禁用线程池控制器
将这行代码加入到程序开头即可禁用线程池控制器。但是请注意,禁用线程池控制器可能会影响程序的性能和稳定性,所以最好还是尝试更新或修复线程池控制器。
原文地址: https://www.cveoy.top/t/topic/gNvr 著作权归作者所有。请勿转载和采集!