
简介扑克牌图像检测数据集YOLOV5目录格式专为目标检测项目设计涵盖52种扑克牌类别面向需要现成训练/验证数据的算法工程师与学习者。图像为720×720 RGB格式训练集含16000张图片及对应txt标注验证集含4000张图片及标签类别字典文件一并提供无需额外格式转换即可接入YOLOV5训练流程。资源包共2000个文件以txt标注文件和类别字典为主另附一个可直接运行的Python可视化脚本随机传入图片即可绘制边界框并保存结果便于快速核验标注质量。压缩包整体约947.74MB目录结构清晰适合目标检测入门实践、模型调参与扑克牌识别场景落地。已有134人学习可作为起步参考。1. 目标检测数据集长什么样52 类扑克牌为什么拿 YOLOv5 目录直接开跑做目标检测的同行应该都有过这种经历模型结构调好了loss 也正常下降结果训练集和验证集是自己拿脚本现切的标签格式一会儿是 XML 一会儿是 TXT坐标一会儿归一化一会儿像素值跑起来全是坑。这份扑克牌数据集最大的价值就是它已经按 YOLOv5 的标准目录格式整理好了训练集 16000 张、验证集 4000 张52 个类别对应扑克牌四种花色从 A 到 K 的全部牌型图像分辨率固定 720×720 的 RGB拿过来配一个 YAML 就能跑训练。对于想入门 YOLOv5 训练自己的数据集又不想在数据整理上消耗太多时间的人来说这是非常合适的起步资源。它解决的就是「数据准备」这一环不用再写转换脚本、不用对坐标单位做二次处理直接进入模型训练和调参阶段。2. 拆目录结构与标签格式YOLOv5 的“约定优于配置”具体指什么2.1 训练集、验证集与图像、标签的同名对应规则YOLOv5 的数据组织方式在工程上非常朴素图像放在 images 目录下标签放在 labels 目录下训练集和验证集分开而且图像文件名与标签文件名必须完全一致区别只在扩展名。这一点看似简单实际是新手最容易翻车的地方。举例来说训练集里有一张图片叫318686725.jpg那么对应的标签文件必须是318686725.txt放在labels/train/下里面写这张图里所有目标的类别和边界框信息。如果文件名对不上训练时 YOLOv5 会直接跳过这张图表现为训练集数量比预期少或者干脆报No labels found in ...之类的错误。这份数据集采用的就是这种结构目录名datasets/images/train、datasets/images/val、datasets/labels/train、datasets/labels/val这样的层级。按 YOLOv5 的传统惯例我的建议是你拿到数据后先别急着改目录保持原样只在外层新建一个指向它的软链接或者直接把数据集放在 YOLOv5 仓库的../datasets同级位置训练时路径直接写数据集根目录即可。如果一定要移动位置注意整个 images 和 labels 的相对关系不能变否则重新划分的工作量远比想象中大。2.2 标签 TXT 的归一化坐标与 52 类别 ID 映射每张扑克牌图片对应的标签 TXT 文件里每一行代表一个目标格式是固定的五个字段class_id x_center y_center width height。其中 class_id 是整数从 0 开始计数52 种类别就是 0 到 51x_center、y_center、width、height 全部是归一化到 0 到 1 之间的小数分别表示目标中心点横坐标、中心点纵坐标、目标宽度、目标高度归一化的分母是图像的宽和高。这一点和 VOC 格式、COCO 格式完全不同VOC 存的是左上角和右下角的像素坐标COCO 存的是左上角坐标加宽高像素值所以不要混着用。我一般会在拿到数据后做的第一件事就是随机抽几个标签文件打开确认两点第一每一行的 class_id 是否都在 0 到 51 这个区间内第二x_center width / 2是否小于等于 1y_center height / 2是否小于等于 1。如果出现大于 1 的情况说明坐标越界通常是转换脚本的问题这个数据集如果直接使用不会出现这种情况但如果你后续要自己扩充数据这一点必须检查。同时项目里附带了一个类别的 TXT 字典文件这个文件的作用是把类别 ID 和具体牌面文字对应起来。比如 ID 0 可能对应梅花 AID 1 对应梅花 2以此类推。这个字典在配置 YAML 的 names 字段时会用到下面第 3 章会具体写怎么用。2.3 720×720 固定分辨率对训练 batch-size 和锚框的影响图像分辨率统一是 720×720这是一个对训练非常友好的设定。YOLOv5 默认会把输入 resize 到 640×640 再送进网络你的数据是 720×720等比缩放到 640×640 不会有形变也不需要多余的信箱填充算是在数据层面就规避了letterbox带来的黑边问题。另外统一分辨率意味着同一张图里的目标尺度分布相对稳定在设置初始锚框时可以直接沿用 YOLOv5 默认的锚框只依靠训练过程中的autoanchor机制做微调即可省去手动估算锚框的步骤。需要注意的一个点是训练时如果显存不够想把输入尺寸降到 512×512那么原来 720×720 下标注的归一化坐标不受影响因为归一化坐标跟绝对像素无关降分辨率后标签仍然有效。这点也是 YOLO 格式相对于 VOC 像素坐标的一个优势。3. 改成自己训练的配置生成 YAML 与划分训练/验证集3.1 手写 data.yaml路径、nc、names 三个核心字段把数据集直接拿来训练第一步是准备好数据集配置文件。YOLOv5 训练时会读取一个 YAML 文件里面至少要有三块信息数据集的根路径、类别总数 nc、类别名称列表 names。针对这个扑克牌数据集配置大概长这样# data.yaml path: /home/yourname/datasets/poker # 数据集根目录按你的实际路径修改 train: images/train # 相对于 path 的训练图像目录 val: images/val # 相对于 path 的验证图像目录 nc: 52 # 类别数量四种花色 × 13 个牌面 names: 0: club_A 1: club_2 2: club_3 3: club_4 4: club_5 5: club_6 6: club_7 7: club_8 8: club_9 9: club_10 10: club_J 11: club_Q 12: club_K # 以下按实际字典文件顺序补充完整 # diamond_A, diamond_2 ... spade_K 共 52 项这里的path字段在 YOLOv5 v5.0 之后的版本里普遍支持它可以让train和val使用相对路径避免每次改机器都要重写一遍绝对路径。nc和数据集中实际的类别数必须一致这里就是 52不能写成 13也不能把大小王也算进去因为这份数据只有 52 种牌型。names这个列表建议直接按照附带的类别字典文件里的顺序全部复制过来不要自己重新排序。names 的索引顺序决定了模型预测输出里每个 ID 对应的含义如果这里和标签文件里的 class_id 对应错位训练出来的模型在推理阶段会把黑桃 A 识别成红桃 10 之类而且 Loss 看起来还是正常的属于比较隐蔽的错误。3.2 验证集划分是否合理how 4000 张能代表整体分布拿到数据后很多人会忽略一个检查步骤验证集是否和训练集同分布。这个数据集的训练集 16000 张、验证集 4000 张比例接近 4:1从数量上讲验证集足够大计算出来的 mAP 指标不会因为验证集样本太少而剧烈抖动。但要注意一点如果验证集中某一种花色的牌特别少或者某种牌面完全缺失那么 mAP 会被整体拉低但这种拉低不一定是模型的问题而是验证集分布的问题后续做模型对比时容易误判。我的习惯是在正式训练前写一段小脚本统计训练集和验证集每个类别的样本数量画一个分布直方图。如果发现某张牌的样本数量出现极端偏差再决定是补样本还是调整验证集划分。对于这份扑克牌数据集按它的描述是均匀覆盖 52 类一般不会有这种问题但验证这一步花不了两分钟值得做一下。顺便也能确认标签文件里没有空文件空标签文件在训练时会导致该图片被当作背景样本如果数量过多会干扰模型收敛。3.3 直接开启 YOLOv5 训练命令行参数与训练产物配置好 YAML 之后训练命令基本是固定套路。以 YOLOv5 官方的train.py为例在 PyTorch 环境下执行python train.py \ --data /path/to/your/data.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 100 \ --device 0参数含义分别解释一下--data指向刚才写好的 YAML 文件--weights选择预训练权重如果机器性能一般用yolov5s.pt起步性价比最高显存不足的话可以降到yolov5n.pt--img 640是训练输入尺寸原始图像 720×720 会被缩放到 640×640这个缩放是等比例的不会变形--batch 16按单卡 16 张图计算实际需要根据显存调整如果爆显存就往下降--device 0指定 GPU 编号。训练完成后runs/train/exp目录下会生成weights/best.pt和weights/last.pt两个权重文件。best.pt是在验证集上 mAP 最高的那个 checkpoint做推理或者导出部署用best.pt就行千万不要图省事直接用last.pt它在最后几个 epoch 可能已经过拟合精度不如best.pt。4. 可视化脚本 show.py边界框到底对不对看一眼才知道4.1 脚本设计逻辑读取标签、绘制矩形、不依赖额外配置项目里附带的show.py是这个数据集的一个加分项。它的作用是随机读取一张图片和对应的标签文件在图像上把每个目标的边界框画出来然后保存到当前目录。为什么说这个脚本值得先跑一遍因为标签格式对不对光看坐标数值很难发现规律性问题但把框画在图上一眼就能看出来坐标是不是偏离了牌面区域哪些类别标注重叠哪些目标小到几乎看不见。按照常见做法这个脚本的流程大概是从图片路径取到文件名去对应的 labels 目录找同名 txt 文件解析每一行的五个数值把归一化的 x_center、y_center、width、height 换算回像素坐标最后用 OpenCV 的rectangle函数画框并在框左上角写上类别名称。整个逻辑不复杂关键是省去了自己从零写一遍匹配逻辑的工作。4.2 随机抽 30 张检查坐标、类别、遮挡这三个观察点运行可视化脚本之后我建议你在生成的图片里随机挑 30 张左右做人工检查。检查集中在这三方面第一边界框是否紧贴扑克牌边缘如果框明显比牌面大一圈说明标注包含了不少背景后续训练出来的预测框也会偏大做 NMS 时容易把相邻的牌合并掉第二类别文字是否和牌面一致比如红桃 7 的框上不能写着方块 7第三牌与牌互相遮挡时标注是只标了可见部分还是标了全部牌面这决定了模型在遮挡场景下的学习目标。这里多说一句扑克牌检测和行人检测、车辆检测不太一样牌面是近乎刚体的目标旋转和缩放模式非常有限所以标注质量的高低对最终 mAP 的影响会被放大。框偏了哪怕几个像素在 720×720 的图上看起来不明显但换算到 mAP 的 IoU 计算时0.5 和 0.75 阈值下的结果会差出不少。这也是为什么我一再强调先可视化、再训练的流程。4.3 可视化工具对换数据集后的可复用性show.py这个脚本还有一个隐藏价值它不绑定扑克牌这个具体数据集。只要你把脚本里的图片目录、标签目录、类别字典三个变量改成你自己的路径它完全可以复用到其他 YOLO 格式的数据集上。我经常拿这种通用可视化脚本去检查从网上下载的数据集尤其是那些来源不明、没有说明文档的数据集。跑一遍可视化比看十遍 README 都管用。实际改动非常小核心就是修改两个目录常量和一个类别列表# show.py 关键配置部分按需修改 image_dir datasets/images/val label_dir datasets/labels/val class_names [] # 从类别 txt 字典文件逐行读取填充 # 读取标签 with open(label_path, r) as f: lines f.readlines() for line in lines: cid, cx, cy, w, h line.split() # 归一化坐标转像素坐标 cx, cy, w, h float(cx), float(cy), float(w), float(h) x1 int((cx - w / 2) * img_width) y1 int((cy - h / 2) * img_height) x2 int((cx w / 2) * img_width) y2 int((cy h / 2) * img_height) # 用 cv2.rectangle 绘制边界框这段代码里的坐标转换是 YOLO 格式转像素坐标的标准写法x1, y1是左上角x2, y2是右下角画框时 OpenCV 要求这两个点必须是整数。如果你后续要在自己的脚本里做类似转换这四行就是最核心的复用片段。5. 避坑排查标签、归一化、划分、脚本的四个翻车现场5.1 类别 ID 对不上 names 顺序Loss 正常但预测全错现象训练了 50 个 epochLoss 掉得很漂亮验证集 mAP 看起来也不低但拿训练好的权重去推理一张只有红桃 K 的图片模型输出的是方块 3。原因标签 txt 里的 class_id 和 data.yaml 里 names 列表的索引顺序不一致。比如你手动改过 names 的顺序或者类别字典文件的顺序和标签文件构建时的顺序不是同一个版本模型学到的 ID 到牌面的映射关系就是错的。解决重新回到类别字典 txt 文件用它作为唯一事实来源把 data.yaml 里的 names 按字典的原始顺序重新生成一遍。然后随机抽 50 张验证集图片可视化确认每张图上画出的类别文字和实际牌面一致后再重新训练。5.2 标签文件里出现空行或多余空格训练时报错或者少了目标现象训练刚开始就报assert len(line.split()) 5之类的错误或者训练没报错但某个类别的 recall 一直很低。原因标签 txt 文件里存在空白行或者行尾有多余的空格。YOLOv5 读标签时会按每行五个字段来解析空行会直接导致解析失败而多余空格在正常情况下 OpenCV 读取没问题但某些自定义读取脚本里会计算出错的坐标。解决训练前统一跑一遍清洗脚本把所有标签文件重新写一遍每行按class_id x_center y_center width height的单空格格式输出最后一行补一个换行符空行全部删除。这种清洗脚本花 10 分钟就能写好但能省下后面排查数据问题的半天时间。5.3 训练集和验证集有重叠图片mAP 虚高现象验证集 mAP 到 90 以上但你心里清楚这个任务没那么简单换到真实场景里效果明显缩水。原因数据划分时没有做去重同一张图片既出现在images/train里又出现在images/val里模型在训练时已经见过验证集的内容mAP 指标失去参考意义。这种情况在从网上下载混合数据集时很容易出现特别是数据来自多个来源又合并到一起的时候。解决写一个文件名校验脚本将 train 和 val 文件名各存到一个 Set 里取交集。交集不为空就说明有重叠需要把这部分重叠文件从训练集中移除并重新划分。这个数据集原始划分大概率没有这个问题但你如果自己重新整合数据这一步不能省。5.4 show.py 运行后没有输出图片或报找不到文件现象脚本运行后控制台没有任何提示当前目录也没有生成图片或者报No such file or directory的错误。原因脚本内部读取标签时用了一个固定路径前缀而你把数据集移到了新位置目录常量没同步更新。另一个常见原因是图片文件名和标签文件名的后缀不匹配比如图片是.jpg脚本里却拼接了.png的路径。解决先确认show.py里的基路径是否指向当前数据集根目录再确认图片目录里的实际扩展名是.jpg还是.png。最稳妥的做法是打印两个路径核对一下python -c import os; print(os.path.exists(datasets/images/val)); print(os.path.exists(datasets/labels/val))如果输出True之后再跑show.py一般不会再出路径问题。6. 再进一步扑克牌检测换到视频牌桌场景时怎么迁移这套数据集按 52 类分类来理解的话本质上是一个分布相对规整的识别任务。我自己最常用的扩展方式是把训练好的模型接到视频帧序列上做一个连续帧的检测与计数而不只是单张图片的分类。这样做的思路其实很直白如果模型对静态图片里的牌面能稳定输出边界框和类别那么对视频里每隔几帧出现同一张牌的检测结果做时序平滑就能把单帧误检的噪声消掉。最简单的时序处理办法是维护一个滑动窗口对连续 5 帧的检测结果按类别做投票每一类只保留出现次数最多的边界框再更新到画面显示上。这个技巧在扑克牌这种目标尺度变化小的场景里效果很稳定不需要引入跟踪模型。另外一个实用技巧是用验证集里表现最差的那几个类别单独生成困难样本集比如牌面有反光、手指遮挡、斜角比较大的情况给这批样本单独跑一遍可视化确认模型预测的结果再决定要不要把它们纳入训练集的增强策略中比如增加随机旋转和亮度扰动。从实践经验来看这份数据集把最繁琐的数据整理工作提前做完了你把时间花在训练策略和推理部署上会更值。从那以后我每次拿到一个新的目标检测数据集都会先强制走一遍可视化加类别分布统计这个流程确认标签没大问题之后再动手训练这个习惯帮我省下了不少返工的时间。希望这些拆解对你有帮助祝训练顺利。本文还有配套的精品资源点击获取