
简介扑克牌识别数据集面向计算机视觉与YOLO目标检测开发者覆盖A、2~10、J、Q、K共13类牌面字符基于1850张原始图像构建标注正确识别率可达98.7%可直接用于扑克牌识别、棋牌游戏辅助、智能理牌等场景的模型训练与算法验证。压缩包共2000个文件约109.76MB包含1850个txt格式的YOLO标注文件、149张jpg原图以及1个yaml数据集配置文件txt文件记录每张图的边界框与类别信息yaml文件定义类别名称与路径整体结构简洁适配YOLO v11训练流程训练集与验证集也可按需灵活划分。目前已有241人浏览学习适合需要高质量扑克牌数据集进行目标检测实战研究的初学者和工程师。用户下载后可直接按标准格式开始训练无需额外转换标注能够节省数据清洗与标注时间快速验证模型在牌面识别任务上的效果。1. 从牌桌到生产线为什么一个扑克牌数据集值得认真拆扑克牌识别看起来是个玩具项目但真正动手做过的人知道它把计算机视觉里最难啃的几块骨头全占了A-K 一共 13 类牌面花色和数字的组合导致类间差异极小黑桃 K 和红心 K 仅靠左上角一个像素级的颜色区别牌面反光、倾斜透视、手指遮挡、背景纹理干扰每一个都是真实场景里必然遇到的脏数据。这个数据集给了 1850 张原始图和 YOLO v11 格式标注声称正确识别率可达 98.7%对做目标检测的工程师来说它是一个拿来即用的基准测试集适合验证检测器在细粒度分类上的表现也适合做模型压缩、蒸馏或部署前的压力测试。无论你是刚接触 YOLO 系列的新手还是想评估 v11 在小目标、高相似类别上能力的熟手这份数据都值得花一下午跑通并分析失败样本。2. 数据集解剖与 YOLO v11 标注格式对齐2.1 目录结构与原始图像分布数据集的核心是 1850 张 JPG 原始图文件名是典型的 Roboflow 导出格式比如IMG_1838-2_jpeg_jpg.rf.49d668fbd2c444292eb9c376407174f5.jpg其中rf表示该图经过 Roboflow 平台处理后面的十六进制串是图片的唯一标识。这种命名方式有一个实际好处每张图的增强历史、原始来源都可以通过前缀回溯排查数据泄露时很有用。常见的目录组织方式是poker_dataset/ ├── train/ │ ├── images/ │ └── labels/ ├── valid/ │ ├── images/ │ └── labels/ └── test/ ├── images/ └── labels/train / valid / test 的划分比例通常是 70% / 20% / 10%也就是大约 1295 / 370 / 185 张。实际使用时先跑一遍find . -name *.jpg | wc -l确认数量再检查 labels 目录下有没有漏标的空文件。2.2 标签文件与类别映射YOLO v11 延续了 YOLO 系列的标注格式每个 txt 文件对应一张同名图片每行代表一个目标五个数值依次是class_id x_center y_center width height其中坐标全部归一化到 0-1 区间。类别编号从 0 开始映射到具体的牌面字符数据集的data.yaml中通常会给出完整列表。对于扑克牌识别一个合理的poker.yaml配置如下path: ./poker_dataset train: train/images val: valid/images test: test/images nc: 13 names: 0: A 1: 2 2: 3 3: 4 4: 5 5: 6 6: 7 7: 8 8: 9 9: 10 10: J 11: Q 12: K这里的 nc13 是关键它对应 A、2-10、J、Q、K 五个字母加八个数字共 13 个类别。很多人在训练时遇到维度不匹配的报错往往就是 names 列表长度和 nc 不一致或者标注文件里的 class_id 超出了 0-12 的范围。2.3 标注质量验证的三个快速命令拿到数据集后不要直接开训先做一轮完整性检查。下面这组命令可以快速发现标注是否存在越界、空文件或类别偏移# 统计每个类别在训练集中的样本数 awk {print $1} train/labels/*.txt | sort | uniq -c # 找出空标注文件这些文件会导致训练时该图被跳过 find train/labels -name *.txt -size 0 # 检查有无坐标越界的标注正常应在0-1之间越界即标注错误 awk {if ($30 || $40 || $50 || $60 || $31 || $41 || $51 || $61) print FILENAME, $0} train/labels/*.txt | head -20第一段代码统计类别分布如果某个类别的样本数量为 0说明数据集存在类别不均衡训练时需要开启class_weights或适当增加该类别的增强概率。第二段命令查找空文件空标注通常是标注工具中途退出导致的训练时不会报错但会浪费一个批次的位置。第三段代码检查归一化坐标是否越界如果出现大于 1 的数值说明标注环节用了绝对像素坐标而没有做归一化这类样本必须剔除或修正否则会让损失函数出现 NaN。数据集的实际难点不在数量而在类间相似度。A 和 4 在牌面设计上形态接近J 和 Q 的区别只有角落里的字母和人物姿态这类细粒度差异要求增强策略必须包含轻微旋转和色调扰动但不能做水平翻转——一旦翻转牌的左右结构颠倒类别语义会被破坏比如红心朝左变成了朝右原本的 J 就可能被模型识别成 Q。3. YOLO v11 训练的前置配置与超参数选择3.1 模型选型n、s、m 还是 lYOLO v11 官方提供了 n、s、m、l、x 五种尺度对应不同的参数量和推理速度。扑克牌识别属于单目标小类别任务输入分辨率通常设为 640x640 即可覆盖牌面主体。对于 1850 张的小数据集直接上 x 或 l 会很快过拟合验证集的 mAP 不会随训练轮次上升反而下降。我一般会先用 v11n 或 v11s 做基线观察 loss 曲线和 mAP 走势再决定是否升级到更大模型。如果部署目标是手机端或边缘设备v11n 的权重只有 5-6 MB推理一张图在 CPU 上约 20-30ms识别精度在 98% 左右如果目标是桌面端或服务器v11m 的精度能到 98.7% 但推理速度会慢 3-4 倍。这个数据集的生产者给出 98.7% 的精度大概率是在 v11m 或 v11l 上取得的复现时需要注意权重初始化。3.2 训练参数配置文件YOLO v11 的训练入口是yolo train对应的参数可以通过命令行直接传也可以写在配置文件里。下面是一份针对该数据集的推荐配置# poker_train.yaml task: detect mode: train model: yolo11s.pt data: poker.yaml epochs: 200 patience: 30 batch: 16 imgsz: 640 optimizer: SGD lr0: 0.01 lrf: 0.01 momentum: 0.937 weight_decay: 0.0005 warmup_epochs: 3.0 warmup_momentum: 0.8 warmup_bias_lr: 0.1 box: 7.5 cls: 0.5 dfl: 1.5 augment: true mosaic: 1.0 mixup: 0.1 fliplr: 0.0 flipud: 0.0 degrees: 10.0 translate: 0.1 scale: 0.5 hsv_h: 0.015 hsv_s: 0.7 hsv_v: 0.4重点解释几个参数fliplr和flipud必须设为 0.0因为扑克牌是强方向性目标翻转会直接改变类别degrees: 10.0允许 10 度以内的旋转能模拟牌面摆放不水平的情况mosaic: 1.0开启马赛克增强但小数据集上 mosaic 生成的花屏图像过多时会造成标签错位建议设为 0.8-1.0 并配合close_mosaic在训练后期自动关闭mixup: 0.1是图片混合增强对细粒度分类帮助有限设大了反而让模型学到混合伪影。box、cls、dfl是 YOLO 的三个损失权重默认值 7.5 / 0.5 / 1.5 在这个任务上表现良好不建议新手改动。3.3 数据划分时的注意事项很多人拿到数据集后直接把 train / valid / test 当成品用但需要注意Roboflow 导出的 valid 和 test 划分是随机的如果同一张牌比如黑桃 A的多个角度照片同时出现在 train 和 valid 里验证集的分数会被高估。为了得到可靠的 98.7% 评估建议按「同一张物理牌的不同照片」做分组划分。具体做法是把文件名前缀中IMG_20220316_142217这类原始拍摄 ID 提取出来作为 group key用sklearn.model_selection.GroupShuffleSplit按组划分确保同一张牌的多视角照片不会跨集合出现。这个细节是复现高精度数字的关键直接随机划分得到的 mAP 会虚高 2-3 个百分点上线后遇到新牌面时精度会明显下降。4. 启动训练、评估指标与失败模式排查4.1 训练命令与日志监控配置就绪后在终端执行以下命令启动训练yolo train modelyolo11s.pt datapoker.yaml epochs200 batch16 imgsz640 projectpoker_runs nameexp1训练过程中重点看两个指标box_loss和cls_loss。box_loss 是边界框回归损失扑克牌目标大且方正这个损失会下降得很快cls_loss 是分类损失A-K 的区分类别全在这里体现。如果 cls_loss 在训练 50 轮后仍然在 0.5 以上震荡说明模型没有学会区分相似牌面这时要检查增强配置是否翻转了图片或者类别样本是否严重不均。训练结束后在poker_runs/exp1/目录下会生成weights/best.pt和weights/last.pt。best.pt是验证集 mAP 最高时的权重last.pt是最后一个 epoch 的权重部署时必须用best.pt。两个文件大小应该一致如果best.pt文件大小明显小于last.pt说明模型在后期发生了退化表现为验证集 loss 反弹、mAP 下降这是过拟合的典型信号此时减少 epochs 或加大weight_decay即可。4.2 mAP 指标的三层拆解验证阶段运行yolo valyolo val modelruns/poker/exp1/weights/best.pt datapoker.yaml输出会给出 mAP50、mAP50-95 和每个类别的 AP。扑克牌识别里真正有区分度的指标是 mAP50-95因为它对边界框和分类同时打分数值低于 0.95 而 mAP50 很高说明模型在精确定位上还有欠缺——牌面检测虽然找到了目标但框的位置偏移了几个像素这在后续做牌面截取和 OCR 时会有影响。按类别查看 AP 分布时最容易翻车的是 J 和 Q。这两个类别在数据集中如果出现次数不足 5%AP 可能会低到 0.7 以下。处理方式有两个一是给 J、Q 增加过采样在训练时把它们重复送入数据的概率提高二是使用 YOLO v11 的class_weights参数但该参数在官方代码中默认为关闭需要在训练脚本中手动传入按类别样本比例计算的权重向量。4.3 一个典型的翻车现场与修复我在第一次训练这个数据集时遇到了精度停留在 96% 上不去的情况排查下来发现是fliplr忘记关掉。水平翻转后数据集中原本向右倾斜的牌面变成了向左导致模型的角点检测混乱。修复后的训练曲线立刻改善# 训练时用以下方式覆盖默认增强 yolo train modelyolo11s.pt datapoker.yaml fliplr0.0 flipud0.0 degrees10此外如果发现训练过程中显存溢出batch size 过大的报错优先降低 batch 而不是降低imgsz。640 的分辨率对牌面识别来说已经是最低限度降低到 416 虽然能跑但小字母的纹理细节会丢失最终精度可能下降 5 个百分点以上。5. 推理部署与牌面比对的后处理技巧5.1 从检测框到牌面标签的完整流程YOLO 模型输出的是类别 ID 和边界框但在实际业务中通常还要叠加一层后处理确认检测到的是「有效的牌」还是「干扰物」。扑克牌边缘的白色边框在光照过曝时会和桌面融为一体模型可能给出一堆置信度低于 0.5 的虚检框。我通常在推理脚本里设置两重过滤from ultralytics import YOLO import numpy as np model YOLO(runs/poker/exp1/weights/best.pt) results model.predict( sourcetest/images, conf0.25, iou0.45, imgsz640, verboseFalse ) for r in results: boxes r.boxes for i in range(len(boxes)): cls_id int(boxes.cls[i].item()) conf boxes.conf[i].item() xyxy boxes.xyxy[i].cpu().numpy() # 第一重过滤置信度阈值 if conf 0.35: continue # 第二重过滤宽高比合理性 x1, y1, x2, y2 xyxy w, h x2 - x1, y2 - y1 if w 20 or h 30: continue if abs(w - h) / max(w, h) 0.8: continue label model.names[cls_id] print(f牌面: {label}, 置信度: {conf:.3f}, 坐标: ({int(x1)}, {int(y1)}, {int(w)}, {int(h)}))这段代码先用conf0.25做全局置信度阈值输出候选框然后在循环里对每个框做二次筛选。宽高比过滤很关键一张正常的扑克牌宽高比在 0.6-0.7 左右如果框是正方形或细长条大概率是误检。两个小技巧值得记一下imgsz640要与训练时一致否则检测精度会下降verboseFalse关闭逐张打印处理大批量图片时能省去大量无关输出。5.2 用置信度矩阵做误差分析如果想复现或验证 98.7% 的正确识别率光看 mAP 还不够需要统计每个类别的混淆情况。YOLO 的 val 输出会生成混淆矩阵图但它是基于像素级的 IoU 匹配对牌面识别来说不够直观。更直接的做法是写一个批处理脚本把每张测试图的 top-1 预测和真实标签做对比from pathlib import Path from collections import Counter def evaluate_predictions(pred_dir, label_dir): # pred_dir 中是每张图的预测类别 # label_dir 中是每张图的真实类别 correct 0 total 0 confusion Counter() for lbl_file in Path(label_dir).glob(*.txt): total 1 pred (Path(pred_dir) / lbl_file.name).read_text().strip() true lbl_file.read_text().strip() if pred true: correct 1 else: confusion[(true, pred)] 1 accuracy correct / total print(f图片级准确率: {accuracy:.4f}) for (true, pred), cnt in confusion.most_common(5): print(f混淆: {true} - {pred}, 次数: {cnt}) evaluate_predictions(pred_results, test/labels)如果混淆集中出现在同花色的邻近数字比如 7 和 8、J 和 Q说明模型在低分辨率下丢失了牌面角落的细节此时不需要换模型把输入分辨率提高到 768 或 896 往往就能解决。如果混淆分布在相隔较远的类别比如 A 和 10那大概率是标注错误——检查原图就会发现 A 的顶部尖角被框截断了这种 case 在数据集中通常有十几张手动修正标注比调整模型参数更高效。5.3 多卡训练时的数据并行如果手头有多张 GPU可以参考下面的命令加速训练yolo train modelyolo11s.pt datapoker.yaml epochs200 device0,1device0,1表示使用 0 号和 1 号 GPU 并行训练batch 会被平分到两块卡上每张卡各占一半。多卡训练时 warmup 轮次需要稍微增加因为每个 batch 看到的有效样本变少了学习率预热不足会让早期的 loss 曲线抖动明显。这个数据集的最后一个实用技巧训练完成后用训练集的标注统计 J、Q、A 三个类别的尺寸分布。因为这三类牌的角落字母笔画最复杂如果它们的平均框面积小于整体平均框面积说明数据集中存在大量远距离拍摄的小尺寸牌面部署时要考虑开启 YOLO v11 的multi_scale推理即在测试时对输入图像做 0.8、1.0、1.2 三种尺度的缩放并合并预测结果能额外提升 1-2 个百分点的识别率。实测下来这个数据集在 640 分辨率、v11s 模型上的图片级准确率稳定在 98% 左右按上述后处理流程走一遍配合 0.35 的置信度阈值和宽度过滤2000 张连续视频帧的漏检率可以压到个位数。本文还有配套的精品资源点击获取