☰
YOLOv5目标检测实战:52类扑克牌数据集全解析
2026/10/7 1:18:20 网站建设 项目流程

简介:扑克牌图像检测数据集(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 到 51;x_center、y_center、width、height 全部是归一化到 0 到 1 之间的小数,分别表示目标中心点横坐标、中心点纵坐标、目标宽度、目标高度,归一化的分母是图像的宽和高。这一点和 VOC 格式、COCO 格式完全不同,VOC 存的是左上角和右下角的像素坐标,COCO 存的是左上角坐标加宽高像素值,所以不要混着用。

我一般会在拿到数据后做的第一件事,就是随机抽几个标签文件,打开确认两点:第一,每一行的 class_id 是否都在 0 到 51 这个区间内;第二,x_center + width / 2是否小于等于 1,y_center + height / 2是否小于等于 1。如果出现大于 1 的情况,说明坐标越界,通常是转换脚本的问题,这个数据集如果直接使用不会出现这种情况,但如果你后续要自己扩充数据,这一点必须检查。

同时,项目里附带了一个类别的 TXT 字典文件,这个文件的作用是把类别 ID 和具体牌面文字对应起来。比如 ID 0 可能对应梅花 A,ID 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 个 epoch,Loss 掉得很漂亮,验证集 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 帧的检测结果按类别做投票,每一类只保留出现次数最多的边界框,再更新到画面显示上。这个技巧在扑克牌这种目标尺度变化小的场景里效果很稳定,不需要引入跟踪模型。另外一个实用技巧是,用验证集里表现最差的那几个类别单独生成困难样本集,比如牌面有反光、手指遮挡、斜角比较大的情况,给这批样本单独跑一遍可视化,确认模型预测的结果,再决定要不要把它们纳入训练集的增强策略中,比如增加随机旋转和亮度扰动。

从实践经验来看,这份数据集把最繁琐的数据整理工作提前做完了,你把时间花在训练策略和推理部署上会更值。从那以后,我每次拿到一个新的目标检测数据集,都会先强制走一遍可视化加类别分布统计这个流程,确认标签没大问题之后再动手训练,这个习惯帮我省下了不少返工的时间。希望这些拆解对你有帮助,祝训练顺利。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询