基于OpenCV和MediaPipe的石头剪刀布手势识别系统

本项目使用OpenCV和MediaPipe实现石头剪刀布手势识别。项目分为数据采集、模型训练和实时识别三个部分。

数据采集

  1. 打开摄像头并设置分辨率。
  2. 读取摄像头的每一帧图像。
  3. 检测手的关键点。
  4. 根据手的关键点,判断手势类型(石头、剪刀或布)。
  5. 将手势类型和对应的图像保存到本地。

代码示例:

import cv2
import os

# 打开摄像头
cap = cv2.VideoCapture(0)

# 设置分辨率
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)

# 创建目录
data_dir = './data'
if not os.path.exists(data_dir):
    os.makedirs(data_dir)

# 采集数据
gesture_names = ['rock', 'paper', 'scissors']
for gesture_name in gesture_names:
    gesture_dir = os.path.join(data_dir, gesture_name)
    if not os.path.exists(gesture_dir):
        os.makedirs(gesture_dir)
    print(f'Collecting data for {gesture_name} gesture...')
    for i in range(200):
        ret, frame = cap.read()
        if not ret:
            print('Failed to read frame from camera!')
            break
        img_path = os.path.join(gesture_dir, f'{gesture_name}_{i}.jpg')
        cv2.imwrite(img_path, frame)
        cv2.imshow('Collecting Data', frame)
        if cv2.waitKey(10) == ord('q'):
            break
    print(f'Data collection for {gesture_name} gesture finished!')

cap.release()
cv2.destroyAllWindows()

模型训练

  1. 加载数据集。
  2. 构建模型。
  3. 训练模型。
  4. 评估模型性能。

代码示例:

import tensorflow as tf
from tensorflow.keras.preprocessing.image import ImageDataGenerator

# 加载数据集
train_dir = './data'
train_datagen = ImageDataGenerator(
    rescale=1./255,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True,
    validation_split=0.2
)
train_generator = train_datagen.flow_from_directory(
    train_dir,
    target_size=(224, 224),
    batch_size=32,
    class_mode='categorical',
    subset='training'
)
validation_generator = train_datagen.flow_from_directory(
    train_dir,
    target_size=(224, 224),
    batch_size=32,
    class_mode='categorical',
    subset='validation'
)

# 构建模型
model = tf.keras.models.Sequential([
    tf.keras.layers.Conv2D(32, (3, 3), activation='relu', input_shape=(224, 224, 3)),
    tf.keras.layers.MaxPooling2D((2, 2)),
    tf.keras.layers.Conv2D(64, (3, 3), activation='relu'),
    tf.keras.layers.MaxPooling2D((2, 2)),
    tf.keras.layers.Conv2D(128, (3, 3), activation='relu'),
    tf.keras.layers.MaxPooling2D((2, 2)),
    tf.keras.layers.Conv2D(256, (3, 3), activation='relu'),
    tf.keras.layers.MaxPooling2D((2, 2)),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(128, activation='relu'),
    tf.keras.layers.Dropout(0.5),
    tf.keras.layers.Dense(3, activation='softmax')
])

# 编译模型
model.compile(
    optimizer='adam',
    loss='categorical_crossentropy',
    metrics=['accuracy']
)

# 训练模型
history = model.fit(
    train_generator,
    epochs=10,
    validation_data=validation_generator
)

# 评估模型性能
test_generator = train_datagen.flow_from_directory(
    train_dir,
    target_size=(224, 224),
    batch_size=32,
    class_mode='categorical',
    shuffle=False
)
test_loss, test_acc = model.evaluate(test_generator)
print(f'Test loss: {test_loss}, Test accuracy: {test_acc}')

实时识别

  1. 打开摄像头并设置分辨率。
  2. 读取摄像头的每一帧图像。
  3. 检测手的关键点。
  4. 根据手的关键点,判断手势类型(石头、剪刀或布)。
  5. 显示识别结果。

代码示例:

import cv2
import mediapipe as mp
import tensorflow as tf

# 打开摄像头
cap = cv2.VideoCapture(0)

# 设置分辨率
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)

# 加载模型
model = tf.keras.models.load_model('./model.h5')

# 初始化关键点检测器
mp_hands = mp.solutions.hands.Hands(
    static_image_mode=False,
    max_num_hands=1,
    min_detection_confidence=0.5,
    min_tracking_confidence=0.5
)

# 定义手势类别
gesture_names = ['rock', 'paper', 'scissors']

while True:
    ret, frame = cap.read()
    if not ret:
        print('Failed to read frame from camera!')
        break

    # 检测手的关键点
    rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    results = mp_hands.process(rgb)
    if results.multi_hand_landmarks:
        hand_landmarks = results.multi_hand_landmarks[0]
        hand_points = []
        for point in hand_landmarks.landmark:
            hand_points.append((point.x, point.y))
        hand_points = tf.expand_dims(hand_points, axis=0)

        # 预测手势类别
        prediction = model.predict(hand_points)
        gesture_idx = tf.argmax(prediction, axis=1).numpy()[0]
        gesture_name = gesture_names[gesture_idx]

        # 在图像上显示识别结果
        font = cv2.FONT_HERSHEY_SIMPLEX
        font_scale = 1
        color = (0, 255, 0)
        thickness = 2
        cv2.putText(frame, gesture_name, (50, 50), font, font_scale, color, thickness)

    cv2.imshow('Real-time Gesture Recognition', frame)
    if cv2.waitKey(10) == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

结论

基于OpenCV和MediaPipe实现石头剪刀布的识别,可以通过收集数据、训练模型和实时识别实现。这个项目可以用来展示计算机视觉和机器学习的应用,也可以作为一个有趣的玩具项目。

基于OpenCV和MediaPipe的石头剪刀布手势识别系统

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

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