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): angle = math.degrees(math.atan2(c[1]-b[1], c[0]-b[0]) - math.atan2(a[1]-b[1], a[0]-b[0])) angle = angle + 360 if angle < 0 else angle return angle

定义标签与颜色对应字典

label_color_dict = {'warm-up': (0, 255, 0), 'SHIZHAN POSE': (255, 0, 0), 'hit': (0, 0, 255), 'respect': (255, 255, 0), 'gongbu': (0, 255, 255)}

读取第一帧

ret, frame = cap.read()

获取视频帧率

fps = cap.get(cv2.CAP_PROP_FPS)

初始化角度列表

angle_list = []

循环读取视频帧

while ret: # 将帧转换为灰度图像 gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

# 使用Haar级联分类器检测人脸
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
faces = face_cascade.detectMultiScale(gray, 1.3, 5)

# 遍历每个检测到的人脸
for (x,y,w,h) in faces:
    # 绘制人脸矩形框
    cv2.rectangle(frame,(x,y),(x+w,y+h),(255,0,0),2)
    
    # 获取人脸ROI
    roi_gray = gray[y:y+h, x:x+w]
    roi_color = frame[y:y+h, x:x+w]
    
    # 使用Hough变换检测人脸关键点
    circles = cv2.HoughCircles(roi_gray,cv2.HOUGH_GRADIENT,1,20,param1=50,param2=30,minRadius=0,maxRadius=0)
    
    # 如果检测到关键点
    if circles is not None:
        # 将关键点坐标转换为整数
        circles = np.round(circles[0, :]).astype("int")
        
        # 遍历每个关键点
        for (x, y, r) in circles:
            # 绘制关键点圆圈
            cv2.circle(roi_color, (x, y), r, (0, 255, 0), 4)
            
            # 计算角度并添加到角度列表
            if len(circles) == 3:
                angle1 = calculate_angle(circles[0], circles[1], circles[2])
                angle2 = calculate_angle(circles[1], circles[0], circles[2])
                angle3 = calculate_angle(circles[2], circles[0], circles[1])
                angle4 = calculate_angle(circles[0], circles[2], circles[1])
                angle5 = calculate_angle(circles[0], circles[2], circles[0])
                angle5_1 = calculate_angle(circles[1], circles[2], circles[1])
                angle6 = calculate_angle(circles[0], circles[1], circles[0])
                angle7 = calculate_angle(circles[1], circles[0], circles[1])
                angle8 = calculate_angle(circles[0], circles[2], circles[2])
                angle9 = calculate_angle(circles[2], circles[0], circles[2])
                angle10 = calculate_angle(circles[1], circles[2], circles[2])
                angle11 = calculate_angle(circles[2], circles[1], circles[1])
                
                angle_list.append([angle1, angle2, angle3, angle4, angle5, angle5_1, angle6, angle7, angle8, angle9, angle10, angle11])
                
                # 如果角度列表长度大于等于10
                if len(angle_list) >= 10:
                    # 将角度列表转换为DataFrame
                    df = pd.DataFrame(angle_list, columns=['angle1','angle2','angle3', 'angle4','angle5','angle5_1' ,'angle6', 'angle7','angle8','angle9','angle10','angle11'])
                    
                    # 预测动作标签
                    label = knn.predict(df)[0]
                    
                    # 获取标签对应的颜色
                    color = label_color_dict[label]
                    
                    # 在帧上绘制标签
                    cv2.putText(frame, label, (x, y-10), cv2.FONT_HERSHEY_SIMPLEX, 1, color, 2)
                    
                    # 删除角度列表前面的元素
                    angle_list.pop(0)
                    
# 显示帧
cv2.imshow('frame', frame)

# 如果按下q键,退出循环
if cv2.waitKey(1) & 0xFF == ord('q'):
    break

# 读取下一帧
ret, frame = cap.read()

# 控制播放速度
cv2.waitKey(int(1000/fps))

释放视频流

cap.release()

关闭所有窗口

cv2.destroyAllWindows()

动作识别:使用KNN分类器和OpenCV实时识别动作

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

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