基于KNN的手势识别系统:Python实现

本项目使用Python开发了一个基于KNN算法的手势识别系统。系统通过摄像头采集图像,识别手势,并根据预训练的模型预测手势类别。

步骤:

  1. 数据准备:

    • 加载动作数据集:warmup_df, combat_df, attack_df, respect_df, gongbu_df,每个数据集包含手势图像和对应的动作标签。
    • 数据清洗:删除每个小数据集中偏离平均值超过2倍标准差的样本。
    • 将数据集合并为一个大的数据集 data
  2. 数据可视化:

    • 可视化数据集,展示每个图像及其对应的动作标签。
  3. 特征提取:

    • 定义函数 extract_features,用于提取手势图像的特征。本项目中,特征是手部轮廓点的角度差。
  4. 模型训练:

    • 训练KNN模型,使用提取的特征和动作标签。
  5. 测试:

    • 打开摄像头,实时捕获图像。
    • 使用OpenCV进行人脸检测,找到人脸区域。
    • 在人脸区域进行手部检测,找到手部区域。
    • 对手部区域进行预处理:
      • 调整大小
      • 高斯模糊
      • 二值化
      • Canny边缘检测
    • 计算手部轮廓点的角度差,作为特征。
    • 使用训练好的KNN模型预测手势类别。
    • 在图像上显示预测结果。

代码:

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)

# 可视化数据集
print('可视化数据集')
for i in range(len(data)):
    img_path = data['img_path'][i]
    img = cv2.imread(img_path)
    img = cv2.resize(img, (400, 400))
    cv2.putText(img, data['action'][i], (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
    cv2.imshow('Dataset', img)
    if cv2.waitKey(0) & 0xFF == ord('q'):
        break
cv2.destroyAllWindows()

# 特征提取函数
def extract_features(df):
    features = []
    for i in range(len(df)):
        angles = df.iloc[i][['angle1','angle2','angle3', 'angle4','angle5','angle5_1' ,'angle6', 'angle7','angle8','angle9','angle10','angle11']]
        # 计算角度差
        diff_angles = []
        for j in range(len(angles) - 1):
            diff_angles.append(angles[j+1] - angles[j])
        features.append(diff_angles)
    return features

# 特征提取
print('特征提取')
X = extract_features(data)
y = data['action']

# 训练KNN模型
print('训练模型')
knn = KNeighborsClassifier(n_neighbors=neighbors)
knn.fit(X, y)

# 测试
print('开始测试')
cap = cv2.VideoCapture(0)
angles = []
while(True):
    # 读取摄像头的帧
    ret, frame = cap.read()

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

    # 显示摄像头的帧
    cv2.imshow('frame',gray)

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

    # 人脸检测
    face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
    faces = face_cascade.detectMultiScale(gray, 1.3, 5)

    # 如果检测到人脸
    if len(faces) > 0:
        # 取第一个人脸
        (x,y,w,h) = faces[0]

        # 将人脸部分提取出来
        face_roi = gray[y:y+h, x:x+w]

        # 手部检测
        hand_cascade = cv2.CascadeClassifier('hand_cascade.xml')
        hands = hand_cascade.detectMultiScale(face_roi, 1.3, 5)

        # 如果检测到手部
        if len(hands) > 0:
            # 取第一个手部
            (hx,hy,hw,hh) = hands[0]

            # 将手部部分提取出来
            hand_roi = face_roi[hy:hy+hh, hx:hx+hw]

            # 手势识别
            hand_roi = cv2.resize(hand_roi, (100, 100))
            hand_roi = cv2.GaussianBlur(hand_roi, (5, 5), 0)
            _, hand_roi = cv2.threshold(hand_roi, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
            hand_roi = cv2.Canny(hand_roi, 100, 200)
            contours, _ = cv2.findContours(hand_roi, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
            if len(contours) > 0:
                cnt = max(contours, key=cv2.contourArea)
                hull = cv2.convexHull(cnt)
                cv2.drawContours(hand_roi, [hull], 0, 255, 2)
                cnt = cnt.reshape(cnt.shape[0], cnt.shape[2])
                angles = []
                for i in range(cnt.shape[0]):
                    x1, y1 = cnt[i-1]
                    x2, y2 = cnt[i]
                    x3, y3 = cnt[(i+1)%cnt.shape[0]]
                    angle = math.degrees(math.atan2(y2-y1, x2-x1) - math.atan2(y3-y2, x3-x2))
                    angles.append(angle)
                angles = np.array(angles)
                diff_angles = []
                for i in range(len(angles) - 1):
                    diff_angles.append(angles[i+1] - angles[i])
                diff_angles = np.array([diff_angles])
                action = knn.predict(diff_angles)
                cv2.putText(frame, action[0], (x, y), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)

    # 显示结果
    cv2.imshow('frame',frame)

# 释放摄像头并关闭所有窗口
cap.release()
cv2.destroyAllWindows()

注意:

  • 该代码需要OpenCV库,可以使用 pip install opencv-python 安装。
  • 需要准备动作数据集,并将其保存在 dataset_warm-up.csv, dataset_SHIZHAN POSE.csv, dataset_hit.csv, dataset_respect.csv, dataset_gongbu.csv 文件中。
  • 需要使用 haarcascade_frontalface_default.xmlhand_cascade.xml 人脸和手部检测器,可以从OpenCV官方网站下载。
基于KNN的手势识别系统:Python实现

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

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