人体动作识别 - 基于OpenPose和KNN的Python实现
import cv2
import math
import numpy as np
import pandas as pd
from sklearn.neighbors import KNeighborsClassifier
neighbors = 2 # 邻居数量
# 加载动作数据集
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')
# 数据清洗
# 将每个小数据集中偏离平均值超过2倍标准差的样本删除
print('数据清洗')
for df in [warmup_df, combat_df, attack_df, respect_df, gongbu_df]:
df.drop(df[(np.abs(df[['angle1','angle2','angle3', 'angle4','angle5','angle5_1' ,'angle6', 'angle7','angle8','angle9','angle10','angle11']] - df[['angle1','angle2','angle3', 'angle4','angle5','angle5_1' ,'angle6', 'angle7','angle8','angle9','angle10','angle11']].mean()) > 2 * df[['angle1','angle2','angle3', 'angle4','angle5' ,'angle6', 'angle7','angle8','angle9','angle10','angle11']].std()).any(axis=1)].index, inplace=True)
# 将数据集合并为一个大的数据集
data = pd.concat([warmup_df, combat_df, attack_df, respect_df, gongbu_df], ignore_index=True)
# 训练KNN分类器
print('开始训练knn')
knn = KNeighborsClassifier(n_neighbors=neighbors, weights='distance', metric='manhattan')
knn.fit(data[['angle1','angle2','angle3', 'angle4','angle5','angle5_1' ,'angle6', 'angle7','angle8','angle9','angle10','angle11']], data['label'])
# 加载测试视频
cap = cv2.VideoCapture('test.mp4')
# 定义角度计算函数
def calculate_angle(a, b, c):
a = np.array(a)
b = np.array(b)
c = np.array(c)
radians = math.atan2(c[1]-b[1], c[0]-b[0]) - math.atan2(a[1]-b[1], a[0]-b[0])
angle = np.abs(radians*180.0/math.pi)
if angle > 180.0:
angle = 360-angle
return angle
# 定义骨骼坐标点
points = {
0: (0, 1),
1: (1, 2),
2: (3, 4),
3: (4, 5),
4: (2, 6),
5: (6, 7),
6: (2, 8),
7: (8, 9),
8: (2, 10),
9: (10, 11),
10: (5, 11),
11: (7, 11),
12: (5, 6),
13: (5, 0),
14: (6, 0),
15: (3, 0),
16: (4, 0)
}
# 开始检测动作
while True:
ret, frame = cap.read()
if not ret:
break
# 加载OpenPose模型
net = cv2.dnn.readNetFromTensorflow("pose_iter_160000.caffemodel", "pose_deploy_linevec_faster_4_stages.prototxt")
# 图像预处理
blob = cv2.dnn.blobFromImage(frame, 1.0 / 255, (368, 368), (0, 0, 0), swapRB=False, crop=False)
net.setInput(blob)
# 进行前向推理
out = net.forward()
# 解析预测结果
H, W = frame.shape[:2]
points_list = []
for i in range(18):
# 提取关键点的置信度
confidence = out[0, i, :, 2]
# 找到置信度最高的点
idx = np.argmax(confidence)
# 获取该点的坐标
x, y = int(out[0, i, idx, 0] * W), int(out[0, i, idx, 1] * H)
points_list.append((x, y))
# 计算角度
angles = []
for i, j in points.values():
if points_list[i] and points_list[j]:
angles.append(calculate_angle(points_list[i], points_list[j], points_list[0]))
else:
angles.append(0)
# 进行动作分类
label = knn.predict([angles])[0]
# 在图像上绘制动作标签
cv2.putText(frame, label, (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
# 在图像上绘制骨骼连线
for i, j in points.values():
if points_list[i] and points_list[j]:
cv2.line(frame, points_list[i], points_list[j], (0, 255, 0), 2)
# 显示结果
cv2.imshow('Action Detection', frame)
if cv2.waitKey(1) == ord('q'):
break
# 释放资源
cap.release()
cv2.destroyAllWindows()
原文地址: https://www.cveoy.top/t/topic/gQ1a 著作权归作者所有。请勿转载和采集!