简介:这是一份面向计算机视觉初学者与目标检测开发者的扑克牌识别数据集,可用于训练模型同时识别牌面数字与花色,适用于棋牌类应用、智能发牌、图像分类教学等场景。资源包共1003个文件,包含501张jpg原始图像、501个txt标注文件以及1个yaml配置文件,压缩包约11.82MB,标注采用YOLO v11格式,可直接接入主流检测框架进行训练与验证。据描述,该数据集在测试中正确识别率可达99.3%,覆盖多种牌面与花色组合,样本命名清晰,便于按类别划分训练集与验证集。目前已有762人学习下载,适合需要快速搭建扑克牌检测基线、验证模型效果或进行数据增强实验的读者参考使用。
1. 扑克牌识别数据集:501 张原图与 99.3% 准确率背后的落地账
做棋牌类视觉项目的人多半遇到过同一个尴尬:模型在实验室里跑得挺欢,一换到真实牌桌就翻车——反光、遮挡、牌面角度偏一点,数字和花色就认错。这套扑克牌识别数据集就是冲着这个痛点来的,501 张原始图,按 YOLO v11 格式标注,官方给出的正确识别率能到 99.3%。它解决的不是"能不能检测到牌"这种初级问题,而是"数字和花色能不能同时稳定识别"这个真正卡住落地的环节。适合谁用?做棋牌辅助工具、发牌机视觉、牌局记录仪、教学演示的开发者,以及想拿一个干净的小规模多类别数据集练手 YOLO v11 训练流程的人。501 张不算多,但胜在标注质量集中、类别定义清晰,属于那种"拿来就能跑通、跑通就能看到效果"的资源,而不是动辄几万张却要花一周清洗的烫手山芋。
2. YOLO v11 标注格式拆解:从文件名到标签的对应关系
2.1 为什么这套数据用 YOLO v11 而不是 COCO
先说选型理由。YOLO 系列的标注格式是"一图一 txt",每行class_id x_center y_center width height,坐标全部归一化到 0~1。这套扑克牌数据走的就是这个格式,好处很直接:Ultralytics 的yolo命令直接吃,不用写转换脚本,训练配置里data.yaml指一下路径就能开跑。COCO 的 JSON 虽然信息更全(带分割、关键点),但对纯检测任务来说是过度设计,解析还得引 pycocotools,多一层依赖多一层坑。
从项目正文给的文件名能看出标注流程的痕迹。像test_find_changes_by_template_no_match_png_jpg.rf.79a34afbf53dd8d6d2ed906317581bf1.jpg这种,前缀test_find_changes_by_template_no_match说明它来自某个模板匹配的测试环节,.rf.后面那串哈希是标注工具(常见的是 Roboflow 导出)自动加的去重标识。player_skdnsauehrfusefh_png_jpg.rf.a14a973a54a3b0b0402c378e1877cbf6.jpg里的player_前缀则指向牌局中的玩家视角图。这些命名不是随便起的,它反映了数据采集时的场景分组——模板匹配测试图和玩家视角图混在一起,训练时如果按前缀做分层抽样,能避免某一类场景过拟合。
2.2 目录结构与 data.yaml 的写法
拿到数据集后,标准目录长这样:
poker_dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ └── data.yamldata.yaml是训练的入口配置,写法如下:
# data.yaml path: ./poker_dataset # 数据集根目录 train: images/train # 训练集图片路径(相对 path) val: images/val # 验证集图片路径 test: images/test # 测试集图片路径 # 类别数:数字 13 类 + 花色 4 类,具体以实际标注为准 nc: 17 names: 0: ace 1: two 2: three 3: four 4: five 5: six 6: seven 7: eight 8: nine 9: ten 10: jack 11: queen 12: king 13: spade 14: heart 15: club 16: diamond这里有个关键点:nc和names必须和标注文件里的class_id严格对应。如果标注时把数字和花色合并成一个类别(比如"红桃 A"算一类),那nc就是 52;如果拆成数字和花色两个独立维度,就是 17 类。从"可识别数字和花色"这个描述看,更可能是拆开标注的,因为合并成 52 类会让每类样本数骤降到个位数,501 张图根本撑不住。拆成 17 类后,每类平均有 29 张图,虽然还是偏少,但配合数据增强能凑合。
提示:改
data.yaml前先用grep -r "class" labels/train/ | head看一眼实际标注的类别 ID 分布,别照着模板硬填。
2.3 标签文件校验:三行脚本查归一化越界
标注数据最常见的暗病是坐标越界——x_center或width超过 1,训练时 YOLO 会直接报错或者静默丢弃。跑训练前花十秒校验一遍:
# check_labels.py import os import glob label_dir = "./poker_dataset/labels/train" bad_files = [] for txt_path in glob.glob(os.path.join(label_dir, "*.txt")): with open(txt_path, "r") as f: for line_no, line in enumerate(f, 1): parts = line.strip().split() if len(parts) != 5: bad_files.append((txt_path, line_no, "字段数不对")) continue cls_id, x, y, w, h = parts # 归一化坐标必须在 0~1 之间 for name, val in [("x", x), ("y", y), ("w", w), ("h", h)]: v = float(val) if v < 0 or v > 1: bad_files.append((txt_path, line_no, f"{name}={v} 越界")) if bad_files: for bf in bad_files[:20]: print(bf) print(f"共 {len(bad_files)} 处问题") else: print("标签校验通过")逻辑说明:逐行读每个 txt,先检查字段数是不是 5(类别 + 4 个坐标),再检查四个坐标值是否落在 0~1。参数上,label_dir换成你的实际路径即可。如果输出一堆越界记录,说明标注工具导出时坐标系搞错了(比如用了像素坐标没归一化),这种数据直接训练会浪费 GPU 时间。
3. 用 Ultralytics 跑通训练:从环境到 99.3% 的复现路径
3.1 环境安装与版本对齐
YOLO v11 在 Ultralytics 8.3.x 之后的版本里支持,装的时候别用太老的包:
# 建议 Python 3.9+ pip install ultralytics==8.3.0 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121ultralytics这个包把训练、验证、导出全包了,不用单独装 darknet 那套。CUDA 版本按自己显卡驱动选,cu121对应 CUDA 12.1,30 系和 40 系卡都稳。装完跑一句yolo checks确认环境,它会打印出 PyTorch 版本、CUDA 可用性、以及当前 ultralytics 版本。
3.2 训练命令与关键参数
一条命令开跑:
yolo detect train \ data=./poker_dataset/data.yaml \ model=yolo11n.pt \ epochs=150 \ imgsz=640 \ batch=16 \ lr0=0.01 \ patience=30 \ project=runs/poker \ name=exp1逐个说参数。model=yolo11n.pt选的是 nano 版,501 张图用大模型纯属浪费,n 版参数量小、收敛快,适合小数据集。epochs=150是上限,配合patience=30做早停——30 轮验证集指标不涨就停,避免过拟合。imgsz=640是输入分辨率,扑克牌在图中占比通常不小,640 够用;如果牌面很小(比如整张桌子远景),可以提到 1280,但显存翻倍。batch=16是 8G 显存的安全值,12G 以上可以拉到 32。lr0=0.01是初始学习率,小数据集别设太大,否则前期震荡。
训练过程中重点看mAP50和mAP50-95两个指标。99.3% 这个数字大概率指的是mAP50(IoU 阈值 0.5 时的平均精度),因为扑克牌检测框比较规整,IoU 容易做高。如果mAP50到 0.99 但mAP50-95只有 0.7 左右,说明框的位置精度还有提升空间,可以试试加mosaic=0关掉马赛克增强,让模型更关注单张图的细节。
3.3 数据增强配置:小数据集的救命稻草
501 张图直接训,过拟合几乎是必然。Ultralytics 默认开了 mosaic、mixup、HSV 增强,但默认参数不一定适合扑克牌。建议在命令行里显式调几个:
yolo detect train \ data=./poker_dataset/data.yaml \ model=yolo11n.pt \ epochs=150 \ imgsz=640 \ batch=16 \ hsv_h=0.015 \ hsv_s=0.7 \ hsv_v=0.4 \ degrees=15 \ translate=0.1 \ scale=0.5 \ fliplr=0.5 \ mosaic=1.0 \ mixup=0.1hsv_h=0.015是色调扰动幅度,扑克牌红黑分明,色调别动太大,0.015 足够。hsv_s=0.7和hsv_v=0.4分别调饱和度和亮度,模拟不同光照。degrees=15允许旋转 15 度,牌桌视角偏一点能扛住。fliplr=0.5水平翻转概率,注意:扑克牌翻转后数字会镜像,但花色对称性不同(红桃翻转还是红桃,黑桃翻转还是黑桃),所以翻转对花色识别无害,对数字识别可能引入噪声——如果发现数字类别混淆严重,把fliplr降到 0.2。mosaic=1.0是四图拼接,小数据集必备,但训练后期建议关掉(mosaic=0),让模型适应单图分布。
3.4 验证与推理:确认 99.3% 是不是真的
训练完先跑验证:
yolo detect val \ model=runs/poker/exp1/weights/best.pt \ data=./poker_dataset/data.yaml \ imgsz=640 \ conf=0.25 \ iou=0.5conf=0.25是置信度阈值,低于这个的检测框不算数。iou=0.5是 NMS 的 IoU 阈值,重叠超过 50% 的框会被合并。验证输出会打印每个类别的 precision、recall、mAP,重点看数字类和花色类有没有明显短板——如果某个花色(比如梅花)的 recall 特别低,说明该类样本太少,得补数据。
推理单张图:
yolo detect predict \ model=runs/poker/exp1/weights/best.pt \ source=./test_image.jpg \ conf=0.3 \ save=True结果图存在runs/detect/predict/下,框上会标类别和置信度。拿几张没参与训练的牌桌图试,如果数字和花色都能框对,那 99.3% 这个数字在你的场景下就站得住。
4. 避坑与排查:501 张图训练时最容易翻车的五件事
4.1 现象:训练 loss 不降,mAP 一直卡在 0.1 以下
原因:data.yaml里的nc和实际标注类别数对不上,或者names顺序错了。YOLO 不会报错,但会把所有类别当同一类学,loss 自然降不下去。
解决:跑一句python -c "import glob; ids=set(); [ids.update([int(l.split()[0]) for l in open(f)]) for f in glob.glob('labels/train/*.txt')]; print(sorted(ids))",打印出实际用到的 class_id 集合,和data.yaml的names逐一对齐。多一个少一个都改。
4.2 现象:验证集 mAP 很高,但拿新图推理全是错框
原因:训练集和验证集来自同一批场景(比如都是模板匹配图),模型学到了场景特征而不是牌面特征。项目正文里那些test_find_changes_by_template_no_match前缀的图如果全堆在训练集,验证集又抽的是同类图,指标就是虚的。
解决:按文件名前缀做分层抽样,确保player_前缀的图在训练集和验证集里都有。手动分也行,写个脚本按前缀分组再按 8:2 切。
4.3 现象:花色识别准,数字识别差(或者反过来)
原因:数字和花色的视觉特征差异大,模型容量不够时会出现"偏科"。nano 版模型对细粒度分类(A 和 4 的差异)确实吃力。
解决:换yolo11s.pt或yolo11m.pt试一轮,参数量上去了细粒度分类会好。另一个办法是把数字和花色拆成两个检测头分别训,但这就得改模型结构了,成本高,先试换模型。
4.4 现象:训练到 50 轮左右 mAP 突然掉下去
原因:学习率没降下来,模型在最优解附近震荡。默认余弦退火策略在 150 轮下可能后期才降,但早停 patience 设太小的话会在掉下去之前就停了。
解决:把patience提到 50,或者显式加cos_lr=True让学习率按余弦曲线降。如果已经掉了,从best.pt恢复训练:yolo detect train resume model=runs/poker/exp1/weights/last.pt。
4.5 现象:推理时同一张牌被框了两次
原因:NMS 的iou阈值设太高(比如 0.9),重叠框没被合并。扑克牌检测框通常比较紧凑,两个框重叠超过 0.5 就该合并。
解决:推理时把iou降到 0.5 甚至 0.45。如果还不行,检查是不是标注时同一张牌标了两个框——用校验脚本查labels/里有没有同一张图同一位置出现两行几乎相同的坐标。
5. 进阶技巧:用 TTA 和类别平衡把 99.3% 再往上顶一顶
训练跑通之后,如果想把准确率从 99.3% 再往上推,有两个不费劲但有效的招。第一个是 TTA(测试时增强),推理时把图翻转、缩放几次,综合多次结果:
yolo detect predict \ model=runs/poker/exp1/weights/best.pt \ source=./test_image.jpg \ augment=True \ conf=0.3augment=True会开 TTA,代价是推理速度慢 2~3 倍,但 mAP 通常能涨 0.5~1 个点。对离线分析场景(比如牌局回放)完全值得,对实时发牌机就得权衡了。
第二个是类别平衡。501 张图里,某些牌(比如大小王如果标了的话)可能只有几张,训练时会被淹没。Ultralytics 支持在data.yaml里给每个类别配权重,但更简单的做法是过采样——把稀有类别的图复制几份到训练集,文件名加_dup后缀避免覆盖。我一般会先跑一遍yolo detect val看每个类别的 recall,recall 低于 0.8 的类别就补图,补到该类至少 30 张。
还有一个容易被忽略的点:验证集和测试集的划分。501 张图如果按 8:1:1 切,测试集只有 50 张,统计意义太弱。我习惯按 7:1.5:1.5 切,测试集留 75 张左右,跑出来的 99.3% 才更有说服力。切完之后一定确认三个集合里数字和花色的分布大致均匀,别出现"测试集里全是红桃"这种乌龙。
从那以后我每次拿到新数据集,第一件事不是急着训,而是先跑标签校验脚本、再看类别分布、最后按前缀分层切分——这三步走完再开 GPU,能省下大量返工时间。希望这套扑克牌数据集和上面的流程,能帮你把棋牌视觉项目的第一公里跑顺。
本文还有配套的精品资源,点击获取