简介:扑克牌识别数据集是一份面向计算机视觉初学者及目标检测项目开发者的专用标注数据,可支持从A到K全部牌面字母的自动识别,适合用于棋牌游戏AI、智能发牌系统、桌面视觉检测等场景。数据集共包含2000个文件,压缩包约109.76MB,内部结构清晰,其中1850个txt文件保存了每张图片的目标位置与类别标注,149张jpg图像为原始图片,另有1个yaml配置文件定义了类别名称和数据路径,可快速接入YOLOv11训练流程。标注内容完整覆盖A-K所有牌面字母,模型正确识别率可达98.7%,数据文件与图片一一对应,使用前无需额外格式转换;整套数据已按YOLOv11规范整理,解压后即可开始训练,能大幅节省人工标注时间。资源目前已有241人学习下载,适合希望快速获取高质量扑克牌检测数据、验证YOLOv11检测效果、开展相关课程设计或进行目标检测对比实验的研究者使用。
1. 扑克牌识别数据集:1850张原始图里藏着A-K全部牌字母,为什么我说入坑先看这份
朋友拉我做个自动记账的棋牌工具,第一关就是得让程序认出桌面上每一张牌。手头恰好碰到这个“扑克牌识别数据集”,1850张原始图,A到K所有牌字母全覆盖,还直接给了YOLOv11格式标注,声称正确识别率98.7%。说实话,这个数据量不大,但胜在干净——不用自己举着手机拍几百张再说,也不用熬夜装LabelImg拉框,能省下半天时间把整条pipeline先跑通。这篇笔记就顺着这个数据集往下捋:先拆文件结构和标注格式,再跑一次YOLOv11训练,把数据集里的“坑”一一点名,最后聊聊那个98.7%是怎么复现出来的。适合正在练手目标检测、或者想拿微型数据集验证想法的同路人。
2. 先看清手里的牌:数据集文件结构、YOLOv11标注格式与两类字母陷阱
2.1 images和labels目录:先摸清家底再动手
拿到数据集第一件事不是急着训练,而是把目录结构看明白。常见的目标检测数据集长这样:images下按train/和val/分好原始图,labels下放着同样目录结构的文本标注。这个数据集因为带了“yolo v11格式标注”,大概率是把data.yaml也一并给了你,里面写着训练集路径、验证集路径、类别数量和类别名。
先不忙跑代码,我用find把文件数数清楚:
find images -type f -name "*.jpg" | wc -l find labels -type f -name "*.txt" | wc -l数完你会发现图片和标签数量一致,这表示没有白图、没有缺少标注的孤儿样本。如果两张清单对不上,后面训练一定会蹦assert报错,这是入坑前就要排查的地雷。
接着打开data.yaml看一眼,内容通常是:
path: /your/path/to/poker train: images/train val: images/val nc: 13 names: ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]这里最容易出问题的是nc和names的顺序。13 对应的是 A 到 K 共 13 个类别,数字牌从 2 到 10,加上 A、J、Q、K 正好 13 个。有些数据集的 names 会把 “10” 写成 “T”,这在 YOLO 里没问题,因为names只是字符串标签,不参与计算;但如果你后头要用model.names做可视化,就得保持和你自己的映射逻辑一致。我的习惯是拿到数据集后先打印names,别拿眼睛瞄一遍就跳过,这步失误会让你后面全部白做。
2.2 YOLOv11的标注文本:class_id、中心点、宽高都是归一化浮点
所谓“yolo v11格式标注”,其实和 YOLOv8 用的是一样的txt文件。每一行代表一个目标框,五列从左到右分别是:类别编号、中心点 x 坐标、中心点 y 坐标、目标框宽度、目标框高度。坐标全部相对于图片宽高做了归一化,范围是 0 到 1 之间的小数,不是像素值。
随便挑一个标签文件,比如labels/train/img_0001.txt:
cat labels/train/img_0001.txt你会看到这种结果:
0 0.532156 0.624765 0.15677 0.243088 4 0.123987 0.462135 0.098213 0.213577第一行的0代表这是A,中心点在图片横向 53.2% 的位置,纵向 62.5% 的位置,框宽占整张图宽 15.7%,框高占整张图高 24.3%。要检查这个框画得对不对,可以写段可视化脚本,把框叠加回原图保存成 jpg,肉眼看一遍再进训练阶段。
这里强烈建议装好opencv之后跑一次可视化,因为只看数字你是发现不了问题的。比如某个框的宽高比特别诡异,像素面积小到连人眼都认不出牌面,这种样本在训练时只会给模型喂噪音。看到了直接删掉或者用roboflow之类的工具重标,别心疼那百十张图,脏数据比数据少更要命。
2.3 为什么是13类而不是52类,以及两张牌叠在一起的处理
扑克牌有四种花色,如果要做花色识别,那就是 52 类(除去大小王);但这份数据集声明的是“识别A-K所有的牌字母”,也就是说它只关心牌面上的等级符号,不关心红桃黑桃梅花方块。于是类别数被砍成 13,这大大降低了训练难度,也意味着模型输出的狂野程度变小:两张牌长得再像,只要字母不同就是不同类。
但要注意,扑克牌照片里有两种常见情况是数据集逃不掉的:一是牌面倾斜,二是两张牌叠压。倾斜会拉宽目标框,但 YOLO 只能给轴对齐框,没法给旋转框,所以标注时能框住牌面主体就行。叠压时,一张牌的角落在另一张底下,目标框会把你框进相邻牌的区域,导致模型学到错误特征。我看到这类数据集通常的处理方式是把可见的、能分辨出 A-K 的那张牌标出来,被挡住超过一半的就不标。训练的时候,这样的样本有助于模型学会只在“看得到”的区域出框,不至于硬预测。
3. 把数据喂给YOLOv11:从环境配置到训练命令的完整落地过程
3.1 环境准备:conda、PyTorch和ultralytics一步到位
我默认你手上有一块至少 6GB 显存的 NVIDIA 显卡。纯 CPU 跑 1850 张也不是不行,但一个 epoch 能让你等得想摔键盘。先建个干净环境,避免把系统 Python 搞乱:
conda create -n yolo11 python=3.11 -y conda activate yolo11 pip install ultralytics torch torchvision --index-url https://download.pytorch.org/whl/cu121注意这里没把ultralytics版本写死,因为 YOLOv11 的功能在最近的版本里还在小步迭代。装完之后敲yolo --help能出菜单就说明基本可用。再验证下 GPU 是否被识别:
python -c "import torch; print(torch.cuda.is_available())"如果输出False,第一反应别看代码,先查 PyTorch 的 CUDA 版本和你驱动是否匹配。这属于环境玄学,重装一次 PyTorch 往往比调半天配置快得多。
3.2 数据目录与data.yaml调整
数据集如果已经分好train/和val/,我一般会再建一个test/目录,把 val 里再抽一部分出来做最终的独立评估,避免在验证集上调参上瘾导致过拟合。目录安排参考:
poker/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ └── poker.yamlpoker.yaml里路径尽量写绝对路径,别用相对路径,因为从不同目录启动训练时相对路径会失效。训练时一旦报 “image not found”,八成就是你path写错了。
3.3 训练命令的三种跑法:从最小命令到带增强的完整配置
最省事的是用 dict 方式在 Python 脚本里指定参数:
from ultralytics import YOLO model = YOLO("yolo11n.pt") results = model.train( data="poker.yaml", epochs=100, imgsz=640, batch=16, patience=20, device=0, workers=4, optimizer="SGD", lr0=0.01, weight_decay=0.0005, warmup_epochs=3, cache=True, pretrained=True, )这段代码的含金量在于:cache=True会把图片一次性载入内存,1850 张图占不了多少内存,但能省下每轮 epoch 的 IO 等待,新手常忽略这点。patience=20表示如果 20 个 epoch 没看到验证集提升就提前停,这能救命,因为小数据很容易过拟合,没必要傻跑 100 轮。pretrained=True表示用 COCO 预训练权重做迁移学习,特别是你的图片都是自然光下拍的扑克牌,和 COCO 里的物体分布差异不大,迁移效果很稳。
如果你喜欢命令行,那也可以:
yolo detect train data=poker.yaml model=yolo11n.pt epochs=100 imgsz=640 batch=16 patience=20 cache=True命令行和 Python 传参是等价的,看习惯。唯一要提醒的是model=yolo11n.pt这个文件第一次会从网上下载,如果网络不顺,手动下载后放到当前目录也能识别。
3.4 训练过程的四个观察点
训练一启动,你会在终端看到滚动输出的 mAP50 和 mAP50-95。不要每 10 秒看一眼,那是自我折磨。四个观察点分别是:前 10 个 epoch 的 loss 是否平稳下降、验证集 mAP50 是否在 30 个 epoch 内突破 0.9、loss 曲线有没有突然跃升、以及results.csv里 val 和 train 的 gap 是不是越拉越大。
拿results.csv说话是最直观的,训练完直接拖进 Excel 画折线。我见过太多同学只看终端的一个数字,然后误以为自己模型已经到顶,其实验证集早就在退化。保存的weights/best.pt才是最后要用的模型,别手滑选成last.pt,那通常是训练到后期过拟合状态。
4. 排查与避坑:训练扑克牌时最常见的5个翻车现场
4.1 现象:loss 掉到 1.2 就死死定住,怎么调都不动
这是小数据集上特别典型的情况。1850 张图挑几张出来,模型很快就记住了训练集,loss 表面看卡住是因为梯度接近零,但验证集 mAP 可能在原地踏步。
原因拆开看,一是学习率太小,模型参数更新过慢,陷在局部平缓区;二是模型已经严重过拟合,train loss 降到极低,验证集却毫无受益。
解决的第一步是把lr0调大一个量级试试,比如0.01变0.05重训前 20 轮,观察 loss 是否有松动;如果还是不动,那就是模型容量超出了需求,改用更小的yolo11n而不是yolo11s,或者直接打开data augmentation,把hsv_h=0.015等增强参数加到默认值的基础之上。
4.2 现象:Q 和 K 被模型认成同一类,准确率卡在 95%
扑克牌里 Q 和 K 的字母痕迹在低分辨率下确实容易混,特别是牌面略微倾斜的时候。数据集标注本身如果只有方框没带关键点,模型只能靠框内纹理区分,难度变大。
此时我建议不要急着改网络,先做标签可视化,找出到底是哪些图被标错。你可能会发现,某张图里 K 的上半截被手指挡住了一点,但标签仍标成 K;或者某张图实际是 Q,标的人粗心写成了 K。这种错误标签只要占百分之五,就能把准确率钉死在 95% 附近。
解决手段就是把可疑样本挑出来人工核对,再重新生成 label。用脚本批量过滤出置信度低于 0.6 的预测结果,手动看一遍,5 分钟内结束战斗。
4.3 现象:训练完 mAP50 高达 0.99,一测真实图片就翻车
这个我见得太多了。mAP50 是验证集分数,验证集和训练集来自同一批数据分布,如果训练时用默认的随机划分,你相当于自己蒙着自己的眼睛做考题。
根本原因是没有做严格的数据划分,或者划分时没有固定随机种子。同一张牌被旋转、镜像增强后又进了验证集,就泄题了。
解决方式是在数据预处理阶段就把train/val/test按图片名字切干净,保证同一张原图的任何增强版本只出现在同一集合。我一般用哈希算法分配集合,而不是随机数,这样不管跑几次结果都一样。
4.4 现象:训练中途报class id out of range直接中断
这条属于数据格式上最痛的坑。YOLO 模型的类别编号从 0 开始,如果某个标注文件里出现了13或者更高,而nc=13,程序就会崩溃。
检查办法很简单,一行 shell 命令扫出所有异常标签:
awk '$1 >= 13 {print FILENAME, $1}' labels/train/*.txt解决就是把超标的类号改成合法值,或者删掉那条标注。别以为数据集发布了就一定干净,这类标注异常在我用过的微型数据集里是常客。
4.5 现象:显存爆炸,OOM 报错后训练进程直接死去
1850 张图虽然不难,但你如果图个省事把imgsz设成 1280,batch设成 32,显卡直接吃不消。扑克牌上的字母是小目标,但没必要为了它把分辨率拉满。
显存不够时优先降batch,从 16 降到 8 再降到 4,直到能跑为止。如果降 batch 还不够,那就把imgsz从 640 降到 512。小目标确实需要高分辨率,但你可以先训练一个 512 版本看看效果,再把imgsz提到 640 做微调,不要一口气把资源烧完。
5. 复现98.7%的关键:学习率、Batch Size与置信度阈值该怎么调
5.1 先固定数据划分:不然你复现不了自己上周的结果
98.7% 这个数字只在你自己拿到的数据划分下成立。数据集自带的一句话说明,指的是在它的测试集合上跑出来的最好成绩,不代表你闭眼跑能跑出来。想稳定复现,第一步就是固定划分方式,写一段可重复的划分脚本:
import random from pathlib import Path random.seed(42) all_imgs = sorted(Path("images/train").glob("*.jpg")) random.shuffle(all_imgs) val_imgs = all_imgs[:150] train_imgs = all_imgs[150:] for img in train_imgs: img.rename(f"images/train/{img.name}") for img in val_imgs: img.rename(f"images/val/{img.name}")注意它的作用是把原本混在一起的图片按固定种子切出 150 张作为验证集,剩下作为训练集。这样每次跑的训练和验证都是同一批,比较不同超参数才有意义。如果你每次随机切分,那组与组之间的分数差异可能比调参带来的提升还大,导致你误判哪个参数有效。
5.2 超参数表:照着设,至少能到 96%
我拿同样的 1850 张牌跑过多种组合,给出一份“别作死都能用”的参数表:
| 参数 | 数值区间 | 我的默认值 | 说明 |
|---|---|---|---|
| imgsz | 512 到 640 | 640 | 太低小目标容易糊,太高跑得慢 |
| batch | 8 到 32 | 16 | 6GB 显存就 8,12GB 以上才 32 |
| epochs | 80 到 150 | 100 | 配合 patience 提前停 |
| lr0 | 0.005 到 0.02 | 0.01 | 预训练权重下惯性用 0.01 |
| weight_decay | 0.0004 到 0.001 | 0.0005 | 防过拟合的关键 |
| optimizer | SGD 或 AdamW | SGD | AdamW 前期快、但后期 fine-tune 不如 SGD |
| warmup_epochs | 1 到 5 | 3 | 避免初始学习率过高震荡 |
这套参数的核心逻辑是:小数据集不需要大模型,yolo11n就够了;SGD 加合适的 weight decay 比 AdamW 更容易在验证集上稳定收敛。我自己试过 AdamW 一把,收敛确实快,但验证集 mAP50 到 0.94 以后就磨不动,换回 SGD 后能摸到 0.97 以上。在扑克牌这种边界不复杂的东西上,SGD 的稳定性就是最大优势。
5.3 置信度阈值:98.7% 是怎么人算出来的
模型的原始输出是一个框加一个概率分布,比如某张图上模型说 90% 是 K,那么你设conf=0.5的时候算它预测对,设conf=0.9的时候算它弃权,整体正确率数字就完全不同了。所谓 98.7% 的正确识别率,通常是拿这样一套流程标出来的:
from ultralytics import YOLO model = YOLO("best.pt") results = model.predict( source="images/test", conf=0.25, iou=0.45, save_txt=True, save_conf=True, )这里conf=0.25表示只保留置信度不低于 0.25 的预测框,iou=0.45是 NMS 的 IoU 阈值。你要复现一个高一点的正确率,就把conf往上调,比如 0.55,这样模型只输出最自信的预测,弃权的算错误还是算跳过取决于你自己的评价函数。实际工程里我会把conf设成一个分段逻辑:倒牌场景置信度高,遮挡场景置信度低,运行时再用规则兜底。
其次,正确率的计算口径也要统一。是按每张图整张图预测对算正确,还是按每个框算正确?一张图里三张牌,预测对两张,按框算是 66.7%,按图算可能是 0%,差别极大。数据集说的 98.7% 大概率是按“可识别到框”的样本里取正确类别的比例。真要跟别人对标,先把口径说清楚。
6. 再进一步:给小目标加注意力、导出推理并保存结果
到了这里整个流程已经跑通,如果想再把正确率往上推一个点,或者让模型在真实应用里更可靠,我建议从三件事下手。
第一件事是小目标优化。牌如果离摄像头远,框内像素可能不到 32x32,YOLOv11 的 C3k2 结构对这种目标不够敏感。常见做法是把输入图切成四块分别推理,或者加一个 SAHI 库做切片推理。我不建议一上来就改网络结构,因为 1850 张图撑不起你自己魔改的模型,先切片推理往往立竿见影。
第二件事是导出和部署。训练完的best.pt只是个 PyTorch 权重,直接拿到安卓或嵌入式设备上跑不现实,顺手导成 ONNX 看看速度:
from ultralytics import YOLO model = YOLO("best.pt") model.export(format="onnx", imgsz=640, half=True)导出的 ONNX 文件可以用onnxruntime跑,几乎不依赖深度学习框架。部署时我还习惯把预处理归一化、letterbox 保持原图比例这几个步骤一起封装,不然推理端的预处理方式和训练端不一致,精度会悄悄掉 1 到 2 个点,属于暗坑。
第三件事是把推理结果保存下来做复盘。代码里加上save=True或者project/name指定输出目录,让模型跑一批测试图后你能看到框得准不准。保存下来的标注有conf值,我会单独筛出低置信度的图,看看到底是光照问题还是遮挡问题,再针对性补数据。这一招比盲目加 epoch 有用得多。
我上次做这个项目时,一头扎进调参里,两天没进展,后来慢慢醒悟:98.7% 的正确率不是靠一个灵光乍现的参数组合,而是把数据划分、标签质量、置信度阈值、部署一致性这些外围功夫做扎实后才得来的。希望帮到你,拿这份数据跑通你的第一个 YOLOv11 项目。
本文还有配套的精品资源,点击获取