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()
人体动作识别 - 基于OpenPose和KNN的Python实现

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

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