资讯动态

石头剪刀布手势检测数据集:YOLO训练流程验证与避坑指南

发布时间:2026/10/27 18:01:09 来源:尧图企业网站定制
简介这份资源面向计算机视觉入门与YOLO目标检测实战的学习者提供一套可直接用于训练的石头剪刀布手势检测数据集解决手势识别任务中数据采集与标注耗时的问题。压缩包共2000个文件以1999个txt标注文件和1个Python可视化脚本为主整体约209.75MB数据按YOLOv5目录结构组织标注采用classes与x_centre、y_centre、w、h的相对坐标格式涵盖石头、剪刀、布三个类别。其中训练集含6455张图片及对应标签验证集含880张图片及对应标签划分完整可直接投入训练。配套的show.py脚本无需修改即可运行随机传入一张图片便能绘制边界框并保存到当前目录方便快速核验标注质量。目前已有177人学习适合希望快速上手手势检测、验证模型效果或开展课程实践的中级开发者参考使用。1. 石头剪刀布手势检测数据集从能跑通到能复现的第一道坎石头剪刀布手势检测这个场景看起来像是玩具但它其实是检验一套 YOLO 训练流程是否完整的试金石。原因很简单类别只有三个石头、剪刀、布目标单一、背景可控、样本容易采集但真正动手做的时候你会发现划分比例、类别文件格式、标注一致性、可视化验证这几步每一步都能让新手卡上半天。我见过太多人拿到一份划分好的数据集之后直接train.py一跑结果 mAP 死活上不去最后发现是 class 文件和标注对不上或者验证集里混进了训练集的近重复帧。这份数据集的价值不在于手势本身有多难而在于它把划分好的数据集 类别 class 文件 数据可视化脚本这三件套打包齐了。对刚入门 YOLO 的人来说这意味着你不用从零去爬图、标注、划分可以直接跳到训练和调参环节对已经做过几个项目的老手来说这套结构可以当作模板套用到自己的新类别上。我一般会把这类数据集当成流程验证集——先用它把整条链路跑通确认环境、格式、评估指标都没问题再换自己的数据。需要提前说清楚的是石头剪刀布三个类别在视觉上存在天然混淆。石头握拳和布摊掌在低分辨率下边缘特征差异不大剪刀伸两指在侧向角度时容易和石头混。这不是数据集的问题而是这个任务本身的难点后面调参和增强策略都要围绕这一点来设计。2. 数据集目录结构与 class 文件的正确打开方式2.1 一份划分好的数据集应该长什么样拿到数据集之后第一件事不是急着训练而是把目录结构看清楚。常见的 YOLO 格式数据集目录大致是这样组织的dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ ├── classes.txt └── data.yaml这里有几个容易翻车的点。第一images和labels必须严格对应文件名不含扩展名要一一匹配否则训练时 YOLO 会直接跳过找不到标签的图片你看到的 loss 曲线会莫名其妙地太平滑。第二classes.txt和data.yaml里的类别顺序必须一致索引从 0 开始。石头剪刀布三个类别常见写法是rock scissors paper注意顺序很多人想当然写成 rock/paper/scissors结果标注文件里的 0/1/2 和 class 文件对不上训练出来的模型把石头识别成布这种错误在推理阶段才暴露排查起来非常费时间。2.2 class 文件与 data.yaml 的对应关系classes.txt是纯文本每行一个类别名。data.yaml则是 YOLO 训练时真正读取的配置文件典型内容如下path: ./dataset train: images/train val: images/val test: images/test nc: 3 names: 0: rock 1: scissors 2: papernc是类别数量names是索引到类别名的映射。这里的关键是names里的索引必须和标注文件里每行开头的数字对应。标注文件.txt每行格式是class_id x_center y_center width height全部归一化到 0-1 之间。如果你发现训练时提示 Label class X exceeds nc基本就是 class 文件和标注对不上或者 nc 写错了。提示改完data.yaml之后建议用可视化脚本先抽查几张图确认框的位置和类别都正确再开始训练。这一步花两分钟能省掉后面两小时的排查。2.3 用可视化脚本做训练前的最后一道检查数据可视化脚本的作用不只是看看图而是验证三件事标注框位置是否正确、类别索引是否和 class 文件一致、图片和标签是否一一对应。一个最小可用的可视化脚本大概长这样import cv2 import os import random # 配置路径和类别 img_dir dataset/images/train label_dir dataset/labels/train classes [rock, scissors, paper] colors [(0, 0, 255), (0, 255, 0), (255, 0, 0)] # 每个类别一个颜色 # 随机抽 9 张图做网格展示 samples random.sample(os.listdir(img_dir), 9) for i, fname in enumerate(samples): img cv2.imread(os.path.join(img_dir, fname)) h, w img.shape[:2] label_path os.path.join(label_dir, fname.replace(.jpg, .txt)) if not os.path.exists(label_path): print(f缺失标签: {fname}) continue with open(label_path) as f: for line in f: cid, x, y, bw, bh map(float, line.split()) # 归一化坐标转像素坐标 x1 int((x - bw / 2) * w) y1 int((y - bh / 2) * h) x2 int((x bw / 2) * w) y2 int((y bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), colors[int(cid)], 2) cv2.putText(img, classes[int(cid)], (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.6, colors[int(cid)], 2) cv2.imwrite(fcheck_{i}.jpg, img)这段代码的逻辑很直接读图、读对应标签、把归一化坐标还原成像素坐标、画框、写类别名。参数上colors数组的长度要和类别数一致classes的顺序要和data.yaml里的names完全一致。跑完之后看生成的check_*.jpg如果框的位置明显偏移说明标注时的坐标系有问题如果类别名和实际手势对不上说明 class 索引错了。我一般会额外加一步统计每个类别的框数量看看三个类别是否严重不平衡。石头剪刀布这种场景如果采集时没控制好很容易出现某一类特别多的情况后面训练时就要考虑用copy_paste或者类别权重来平衡。3. 用这份数据集跑通 YOLO 训练命令、参数与验证3.1 环境准备与最小训练命令假设你已经装好了 ultralytics 包YOLOv8/v11 系列通用最小训练命令如下yolo detect train \ datadataset/data.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ projectruns/rock_paper_scissors \ nameexp1逐项说明data指向你的 yaml 文件model用 nano 版本先跑通确认流程没问题再换 s/m/lepochs100对这个小数据集通常够用但要看早停imgsz640是标准输入尺寸如果你的图片本身分辨率很低比如 320×240可以降到 416 或 320 加速batch16在 8G 显存上比较稳显存不够就降到 8。训练过程中重点看三个指标box_loss是否稳定下降、mAP50是否在 50 个 epoch 后趋于平缓、val和train的 loss 差距是否过大。如果valloss 早早开始上升而train还在降说明过拟合了这时候要么加数据增强要么减模型复杂度。3.2 针对石头剪刀布的三个关键调参方向这个任务的特殊性在于类别间视觉差异小所以默认增强策略需要针对性调整。我一般会改这几个参数yolo detect train \ datadataset/data.yaml \ modelyolov8s.pt \ epochs150 \ imgsz640 \ batch16 \ degrees15 \ translate0.1 \ scale0.3 \ fliplr0.5 \ mosaic1.0 \ mixup0.1 \ copy_paste0.1degrees15做小角度旋转因为手势在自然场景下不会大幅倾斜scale0.3允许一定缩放模拟手离镜头远近的变化fliplr0.5水平翻转要谨慎——石头剪刀布的手势左右翻转后语义不变所以可以开但如果你做的是左右手区分的任务就不能开。mosaic1.0和mixup0.1是 YOLO 的默认强增强对小数据集有帮助但mixup太高会让小目标更难学0.1 左右比较稳。注意copy_paste在检测任务里不是所有版本都默认支持如果报错就删掉这一行不影响主流程。3.3 训练后的验证与推理检查训练完成后先别急着导出模型用验证集跑一遍yolo detect val \ modelruns/rock_paper_scissors/exp1/weights/best.pt \ datadataset/data.yaml \ imgsz640 \ conf0.25 \ iou0.5看输出的mAP50和mAP50-95。石头剪刀布这种三分类任务如果数据集质量过关mAP50应该在 0.9 以上。如果低于 0.8优先检查验证集里是否有训练集没出现过的背景或光照条件。conf0.25是推理置信度阈值验证时可以调低到 0.1 看看有没有漏检但实际部署时一般用 0.25-0.4。推理单张图片yolo detect predict \ modelruns/rock_paper_scissors/exp1/weights/best.pt \ sourcetest_image.jpg \ conf0.3 \ saveTrue如果推理结果里出现石头和布同时框在同一只手上的情况说明 NMS 的iou阈值需要调整或者训练时类别混淆太严重需要回头检查标注质量。4. 避坑与排查石头剪刀布数据集最常见的五个翻车点4.1 现象训练 loss 正常下降但 mAP 始终在 0.5 以下原因标注文件里的类别索引和data.yaml的names顺序不一致。比如标注时用的是 0rock, 1paper, 2scissors但 yaml 里写的是 0rock, 1scissors, 2paper。模型学到的特征和评估时的类别对不上mAP 自然上不去。解决用可视化脚本抽查 20 张图逐张确认框上的类别名和实际手势一致。如果不一致要么改 yaml要么批量改标注文件。批量改标注可以用一行 Python# 把类别 1 和 2 互换 import os label_dir dataset/labels/train for f in os.listdir(label_dir): path os.path.join(label_dir, f) lines open(path).readlines() new_lines [] for line in lines: parts line.split() if parts[0] 1: parts[0] 2 elif parts[0] 2: parts[0] 1 new_lines.append( .join(parts) \n) open(path, w).writelines(new_lines)4.2 现象验证集 mAP 很高但实际拍照推理时频繁误检原因验证集和训练集来自同一批采集数据背景、光照、手部姿态高度相似模型过拟合到了采集环境。实际使用时换了背景或光照性能就崩了。解决在划分数据集时确保验证集包含不同背景、不同光照、不同人的样本。如果原始数据没有这个多样性可以在训练时加大hsv_h、hsv_s、hsv_v这几个颜色增强参数模拟光照变化。我一般会把hsv_v调到 0.5 左右让模型对亮度变化更鲁棒。4.3 现象石头和布互相误检剪刀识别率明显偏低原因石头握拳和布摊掌在低分辨率下轮廓差异小剪刀伸两指的样本量可能偏少或者标注时剪刀的框画得不准。解决先统计三个类别的标注框数量如果剪刀明显少用copy_paste增强或者手动补充样本。另外检查剪刀的标注框是否把伸出的两指完整框住如果只框了手掌部分模型学到的特征就不完整。可以在可视化脚本里专门把剪刀的图筛出来看一遍。4.4 现象训练时报 No labels found in ... 或 Label class exceeds nc原因图片和标签文件名不匹配或者标签文件里有超出nc范围的类别索引。常见于手动划分数据集时复制图片忘了复制对应标签或者标签文件里混入了其他数据集的类别。解决写一个检查脚本遍历所有图片确认同名标签文件存在并检查每行第一个数字是否小于ncimport os img_dir dataset/images/train label_dir dataset/labels/train nc 3 for f in os.listdir(img_dir): label_path os.path.join(label_dir, f.rsplit(., 1)[0] .txt) if not os.path.exists(label_path): print(f缺失标签: {f}) continue for line in open(label_path): cid int(line.split()[0]) if cid nc: print(f非法类别 {cid} 在 {label_path})4.5 现象推理速度远低于预期单帧超过 100ms原因模型用了 s 或 m 版本输入尺寸设成了 1280或者没有导出成推理优化格式。石头剪刀布这种简单任务nano 版本在 640 输入下普通 GPU 上单帧应该在 10ms 以内。解决先换yolov8n.pt重新训练确认精度损失可接受。然后把imgsz降到 416 或 320对手势检测这种目标较大的任务精度损失通常很小。如果还要更快导出 ONNX 或 TensorRTyolo export modelbest.pt formatengine halfTrue imgsz640halfTrue启用 FP16速度能再提升 30% 左右。注意 TensorRT 导出需要对应版本的 CUDA 和 TensorRT 环境版本不匹配会报错这是另一个常见的坑。5. 把这份数据集用出最大价值三个进阶技巧5.1 用可视化脚本做标注质量审计大部分人把可视化脚本当成看一眼的工具其实它可以做成标注质量审计流水线。我的做法是在脚本里加统计逻辑输出每个类别的框数量、平均框面积、宽高比分布。如果某个类别的平均框面积明显偏小说明标注时可能只框了局部如果宽高比分布出现异常峰值说明标注风格不一致。这些统计信息比肉眼看图更能发现问题。import os from collections import defaultdict stats defaultdict(list) label_dir dataset/labels/train for f in os.listdir(label_dir): for line in open(os.path.join(label_dir, f)): cid, x, y, bw, bh map(float, line.split()) stats[int(cid)].append((bw, bh)) for cid, boxes in stats.items(): avg_w sum(b[0] for b in boxes) / len(boxes) avg_h sum(b[1] for b in boxes) / len(boxes) print(f类别 {cid}: 数量{len(boxes)}, 平均宽{avg_w:.3f}, 平均高{avg_h:.3f})跑完这个统计如果三个类别的平均宽高差异很大比如剪刀的框明显比石头窄这是正常的手势形状不同但如果同一类别内部方差很大说明标注标准不统一需要回头统一标注规范。5.2 用这份数据集做模型选型对比石头剪刀布数据集规模小、类别少非常适合用来做模型选型实验。我一般会固定其他参数只换模型跑一组对比模型输入尺寸mAP50单帧推理时间 (GPU)模型大小yolov8n6400.928ms6MByolov8s6400.9515ms22MByolov8m6400.9632ms50MByolov8n4160.905ms6MB这张表是我自己在类似任务上的经验值具体数字会因硬件和数据集细节有波动。但趋势是明确的nano 到 small 的精度提升明显small 到 medium 提升有限但速度降一倍。如果部署在边缘设备上nano 416 输入通常是性价比最高的选择。5.3 把类别文件做成可复用的模板这份数据集的classes.txt和data.yaml结构可以直接套用到任何新的三分类检测任务上。我的习惯是每做一个新项目先复制这套目录结构改classes.txt和data.yaml然后用同一个可视化脚本检查标注用同一套训练命令跑 baseline。这样每次新项目的启动时间能压缩到半小时以内剩下的时间全部花在数据质量和调参上。最后说一个我踩过的坑有一次我拿到一份划分好的数据集直接开训结果 mAP 只有 0.6。排查了半天才发现验证集里有几张图和训练集是同一场景的连续帧几乎一模一样。模型在验证集上相当于背答案但换到真实场景就崩了。从那以后我拿到任何划分好的数据集第一件事就是用感知哈希或者简单的像素差异检查训练集和验证集有没有近重复样本。这个习惯帮我省了很多次精度虚高的误判。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑