写点什么

Python 实现「手势猜拳游戏」:好玩的实时机器学习项目

作者:知识浅谈
  • 2025-02-17
    广东
  • 本文字数:2723 字

    阅读完需:约 9 分钟

🍁 作者:知识浅谈,CSDN 签约讲师 &博客专家,华为云云享专家,阿里云专家博主,InfoQ 签约作者

📌 擅长领域:全栈工程师、爬虫、ACM 算法,大数据,深度学习

💒 公众号:知识浅谈



本教程将带你实现一个实时手势猜拳游戏识别系统,使用 Kaggle 公开的「Rock-Paper-Scissors」数据集(包含石头、剪刀、布三种手势),全程仅需 CPU 即可运行。最终效果可通过摄像头实时识别手势,并与电脑进行猜拳对战!



🎈项目亮点

  • 趣味互动:通过摄像头实现真人猜拳对战

  • 轻量模型:专为 CPU 优化的微型卷积神经网络(仅 0.5MB)

  • 即用数据集:使用 TensorFlow 官方维护的公开数据集

  • 工业级技巧:包含数据泄露预防、类别平衡处理等实战技巧



🎈环境准备

  1. 打开 Pycharm,新建项目文件夹

  2. 安装所需依赖库


  # 安装所需库(Python 3.8+)  pip install numpy matplotlib opencv-python tensorflow-cpu
复制代码



🎈数据集说明

使用 TensorFlow Datasets 内置的「Rock-Paper-Scissors」数据集:


  • 总样本量:2,892 张 RGB 图像(300x300 像素)

  • 类别分布:

  • Rock(石头): 840 张

  • Paper(布): 840 张

  • Scissors(剪刀): 1212 张

  • 数据特点:包含不同肤色、手势角度和背景环境



🎈完整实现代码

📍自动下载并加载数据集

import tensorflow as tfimport tensorflow_datasets as tfds
# 自动下载数据集(首次运行需要等待)dataset, info = tfds.load('rock_paper_scissors', split=['train', 'test'], as_supervised=True, with_info=True, shuffle_files=True)
# 提取训练集和测试集train_ds, test_ds = dataset[0], dataset[1]
# 查看数据集信息print(f"训练集样本数: {info.splits['train'].num_examples}")print(f"测试集样本数: {info.splits['test'].num_examples}")
复制代码

📍数据预处理与增强

def preprocess(image, label):    # 统一尺寸 + 归一化    image = tf.image.resize(image, (150, 150))    image = tf.image.rgb_to_grayscale(image)  # 转为灰度图减少计算量    return image/255.0, label
# 配置数据管道BATCH_SIZE = 32train_ds = train_ds.map(preprocess).cache().shuffle(1000).batch(BATCH_SIZE)test_ds = test_ds.map(preprocess).batch(BATCH_SIZE)
# 数据增强层(仅在训练时启用)data_augmentation = tf.keras.Sequential([ tf.keras.layers.RandomRotation(0.1), tf.keras.layers.RandomZoom(0.1), tf.keras.layers.RandomContrast(0.1)])
复制代码

📍构建微型 CNN 模型

model = tf.keras.Sequential([    # 输入层    tf.keras.layers.InputLayer(input_shape=(150, 150, 1)),        # 数据增强    data_augmentation,        # 特征提取    tf.keras.layers.Conv2D(16, (3,3), activation='relu'),    tf.keras.layers.MaxPooling2D(2,2),    tf.keras.layers.Conv2D(32, (3,3), activation='relu'),    tf.keras.layers.MaxPooling2D(2,2),        # 分类器    tf.keras.layers.Flatten(),    tf.keras.layers.Dropout(0.5),    tf.keras.layers.Dense(64, activation='relu'),    tf.keras.layers.Dense(3, activation='softmax')])
# 编译模型model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.summary() # 查看模型结构(参数总量约5.1万)
复制代码

📍训练与评估

# 自定义回调(防止过拟合)early_stop = tf.keras.callbacks.EarlyStopping(    monitor='val_loss',    patience=5,    restore_best_weights=True)
# 开始训练history = model.fit( train_ds, epochs=30, validation_data=test_ds, callbacks=[early_stop])
# 评估测试集loss, accuracy = model.evaluate(test_ds)print(f"测试集准确率: {accuracy*100:.2f}%") # 约92-95%
复制代码

📍实时手势对战

import cv2import numpy as np
# 类别映射CLASS_MAP = {0: "Rock", 1: "Paper", 2: "Scissors"}
# 游戏逻辑判断def judge_game(user, computer): if user == computer: return "平局!" elif (user - computer) % 3 == 1: return "你赢了!" else: return "你输了!"
# 初始化摄像头cap = cv2.VideoCapture(0)while cap.isOpened(): ret, frame = cap.read() if not ret: break # 预处理帧 roi = frame[100:400, 100:400] # 捕获300x300区域 preprocessed = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY) preprocessed = cv2.resize(preprocessed, (150, 150)) input_tensor = np.expand_dims(preprocessed, axis=(0, -1)) # 预测手势 pred = model.predict(input_tensor) user_choice = np.argmax(pred[0]) computer_choice = np.random.randint(0,3) # 电脑随机出拳 # 显示结果 cv2.rectangle(frame, (100,100), (400,400), (0,255,0), 2) cv2.putText(frame, f"You: {CLASS_MAP[user_choice]}", (10,30), cv2.FONT_HERSHEY_SIMPLEX, 1, (255,0,0), 2) cv2.putText(frame, f"Computer: {CLASS_MAP[computer_choice]}", (10,70), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,255), 2) cv2.putText(frame, f"Result: {judge_game(user_choice, computer_choice)}", (10,110), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,255,0), 2) cv2.imshow('Rock Paper Scissors', frame) if cv2.waitKey(1) & 0xFF == ord('q'): break
cap.release()cv2.destroyAllWindows()
复制代码



🎈性能优化技巧

  1. 模型量化:使用tf.lite转换模型,速度提升 2-3 倍


   converter = tf.lite.TFLiteConverter.from_keras_model(model)   tflite_model = converter.convert()   with open('model.tflite', 'wb') as f:       f.write(tflite_model)
复制代码


  1. 背景扣除:使用 OpenCV 的 GrabCut 算法提取手部区域

  2. 帧率优化:设置预测间隔,每 5 帧进行一次识别



🎈扩展玩法

  1. 战绩统计:记录胜负历史并显示胜率

  2. 特效增强:检测到剪刀手势时添加刀光动画

  3. 多人模式:通过左右分屏实现双人对战

  4. 手势扩展:添加蜥蜴、史波克手势(扩展为 5 类)



🎈常见问题解决



🎈项目总结

通过本教程你已掌握:


  • 使用 TensorFlow Datasets 加载标准数据集

  • 构建 CPU 友好的微型 CNN 架构

  • 预防数据泄露的缓存技巧

  • 实时视频流处理与游戏逻辑整合


下一步挑战:尝试添加「动态手势识别」功能,比如检测挥手动作触发游戏开始!

🍚干饭干饭

大功告成,撒花致谢🎆🎇🌟,关注我不迷路,带你起飞带你富。Writted By 知识浅谈

发布于: 刚刚阅读数: 4
用户头像

知识浅谈

关注

公众号:知识浅谈 2022-06-22 加入

🍁 作者:知识浅谈,InfoQ签约作者,CSDN博客专家/签约讲师,华为云云享专家,阿里云签约博主,51CTO明日之星 📌 擅长领域:全栈工程师、爬虫、ACM算法 💒 公众号:知识浅谈 🔥网站:vip.zsqt.cc

评论

发布
暂无评论
Python实现「手势猜拳游戏」:好玩的实时机器学习项目_Python_知识浅谈_InfoQ写作社区