击剑动作识别程序 - 基于MediaPipe和KNN的实时动作分析
import cv2
import mediapipe as mp
import math
import numpy as np
import pandas as pd
from sklearn.neighbors import KNeighborsClassifier
# 一些全局变量
label = [' '] # 识别输出标签
posese = '' # 视频输出标签
i = 0
t = 30 # 后处理帧数
posese_a = ''
posese_b = ''
version = 'V7.0'
a = 1.2 # 辅助拟合精度
distance_threshold = 121 # 设置KNN距离阈值
neighbors = 2 # 邻居
input_path = ''
# 初始化MediaPipe的人体姿势模型
mp_drawing = mp.solutions.drawing_utils
mp_pose = mp.solutions.pose
# # 打开输入视频文件
# cap = cv2.VideoCapture('5.mp4')
import tkinter as tk
from tkinter import filedialog
# 修改distance_threshold
def set_distance_threshold(value):
global distance_threshold
distance_threshold = int(value)
# 创建窗口
root = tk.Tk()
root.withdraw()
# 显示使用说明信息
info = '欢迎使用击剑动作识别程序V6.2(作者:冯楠20201888)
请选择输入视频文件
支持格式:*.mp4, *.avi
点击确认选择文件'
tk.messagebox.showinfo('使用说明', info)
# 定义选择文件函数
def select_file():
global input_path
root3 = tk.Tk()
root3.title('选择文件')
input_path = filedialog.askopenfilename(title='选择输入视频文件', filetypes=[('视频文件', '*.mp4;*.avi'), ('所有文件', '*.*')])
root3.destroy()
if not input_path:
tk.messagebox.showerror('错误', '未选择输入视频文件!')
root3.destroy()
return
# 更新标签显示选择的文件路径
file_label.config(text=input_path)
def closeit():
root2.destroy()
# 创建窗口2
root2 = tk.Tk()
root2.title('选择文件,调整参数')
root2.geometry('400x600')
# 创建标题
file_titles = tk.Label(root2, text='击剑动作识别程序', font=('宋体', 18))
file_titles.pack(pady=20)
# 创建标签
file_label = tk.Label(root2, text='未选择文件')
file_label.pack(pady=20)
file_label.config(bg='#e9ccd3')
select_button = tk.Button(root2, text='选择文件', command=select_file)
select_button.pack(pady=10)
# 创建标题
file_titles = tk.Label(root2, text='参数调整', font=('微软雅黑', 13))
file_titles.pack(pady=20)
# 创建滑动条
scale = tk.Scale(root2, from_=0, to=200, orient=tk.HORIZONTAL, length=150, label='距离阈值', command=set_distance_threshold)
scale.set(distance_threshold)
scale.pack()
def set_neighbors(val):
global neighbors
neighbors = int(val)
# 创建滑动条
scale = tk.Scale(root2, from_=1, to=10, orient=tk.HORIZONTAL, length=150, label='邻居数量', command=set_neighbors)
scale.set(neighbors)
scale.pack()
# 创建按钮
run_button = tk.Button(root2, text='运行', command=closeit)
run_button.pack(pady=20)
# 创建标签
file_name = tk.Label(root2, text=f"作者:冯楠2020188 物联网2班\n指导教师:朱勇\n版本:{version}", font=("Arial", 14))
file_name.pack(pady=20)
# 关闭窗口
root.destroy()
# 运行窗口
root2.attributes('-topmost', True) # 窗口在最前
root2.mainloop()
# 打开输入视频文件
print('打开输入视频文件')
cap = cv2.VideoCapture(input_path)
# 获取输入视频的帧率和分辨率
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(f"{input_path}_OUT.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')
# 数据清洗
# 将每个小数据集中偏离平均值超过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']) # 将训练后的KNN可视化内容:# 定义一个函数,将训练后的KNN可视化
def knn_visualization(knn, data):
# 获取数据集中的所有标签
labels = data['label'].unique()
# 创建一个空白图像
img = np.zeros((500, 500, 3), np.uint8)
# 遍历图像的所有像素点
for i in range(img.shape[0]):
for j in range(img.shape[1]):
# 获取当前像素点的坐标
x = float(j) / img.shape[1]
y = 1.0 - float(i) / img.shape[0]
# 将坐标转换为特征向量
features = np.array([x, y])
# 使用KNN分类器对特征向量进行分类
label = knn.predict([features])[0]
# 将分类结果转换为颜色
color = (0, 0, 0)
for k in range(len(labels)):
if label == labels[k]:
color = (int(255 * (k + 1) / len(labels)), int(255 * (k + 1) / len(labels)), int(255 * (k + 1) / len(labels)))
break
# 将当前像素点的颜色设置为分类结果的颜色
img[i, j] = color
# 显示可视化结果
cv2.imshow('KNN可视化', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 显示KNN分类器的可视化结果
knn_visualization(knn, data)
原文地址: https://www.cveoy.top/t/topic/gQ0M 著作权归作者所有。请勿转载和采集!