免费获取学习方案
ARTICLE DETAIL

资讯详情

深耕编程基础知识与建站技术分享的一线实战洞察。

基于YOLO的麻将牌识别:从数据集构建到模型部署全流程实战

基于YOLO的麻将牌识别:从数据集构建到模型部署全流程实战 简介本资源是一个面向计算机视觉开发者与深度学习实践者的麻将牌图像识别项目基于YOLOv11框架实现真实场景下麻将牌的检测与分类解决复杂光照、多角度、杂乱背景等实际部署难题适用于智能棋牌设备开发、AI游戏辅助、教学实验及工业质检等场景。压缩包共31个文件包含10个Jupyter Notebook涵盖数据标注转换、COCO格式处理、手动调参、灰度化预处理及YOLO推理全流程、9个ONNX模型适配边缘部署、4个PyTorch训练权重nano/small/medium/large四类模型、2个Python工具脚本支持YOLO转ONNX/CoreML、以及说明文档与XML模板等整体大小为471.12MB。已有450人学习下载。用户可直接复用完整训练-推理-部署链路从数据增强、标签调整到多格式模型导出配套脚本开箱即用Notebook代码逐模块注释清晰特别适合希望快速落地轻量级CV应用的中级开发者与课程实践者。1. 项目缘起从“看牌”到“识牌”的自动化需求作为一名长期混迹于科技与生活交叉领域的开发者我最近被一个看似“不务正业”但极具挑战性的项目给迷住了用深度学习让计算机“看懂”麻将牌。这听起来可能有点娱乐性质但其背后的技术逻辑和应用场景远比想象中要丰富。无论是开发一款智能记牌、辅助分析的手机应用还是为线下棋牌室构建自动结算系统甚至是用于麻将教学或AI对战机器人的视觉感知模块麻将牌的精准识别都是一个绕不开的核心技术点。这个项目的核心就是利用计算机视觉和深度学习特别是YOLOYou Only Look Once这一目标检测框架来定位并识别图像或视频流中的每一张麻将牌。它要解决的远不止是“这是什么牌”这么简单。在实际场景中麻将牌可能以各种角度堆叠、部分遮挡、光照不均甚至牌面有磨损这对算法的鲁棒性提出了很高的要求。网络上关于通用物体检测的教程很多但针对麻将这种具有固定类别筒、条、万、字、花且同类牌面图案相似度极高的特定目标直接套用通用模型往往效果不佳。这正是我们需要从头构建一个专用麻将数据集并针对性地进行模型训练的原因。本文将从一个实践者的角度完整分享我构建“麻将识别”系统的全过程。我会重点拆解三个核心环节第一如何从零开始采集、标注一个高质量、高可用的麻将图像数据集这是所有后续工作的基石第二如何基于YOLO框架进行模型选型、训练和调优让模型真正学会区分“一筒”和“九筒”第三如何将训练好的模型部署到实际应用环境中并处理各种边界情况。整个过程会穿插大量我在实操中踩过的坑和总结的经验希望能为同样对特定领域目标检测感兴趣的朋友提供一份可直接参考的“实战手册”。2. 基石构建打造一个“教科书级”的麻将图像数据集数据集的质量直接决定了模型性能的天花板。对于麻将识别我们需要的是一个能够覆盖各种真实场景下麻将牌形态的数据集而不是在理想条件下拍摄的“样板照”。2.1 数据采集模拟真实世界的复杂性采集数据的第一步是明确需求。我们的目标不仅是识别单张孤立的、正面朝上的麻将牌更要能处理牌桌上常见的复杂情况。采集设备与设置我使用了普通的智能手机iPhone和安卓均有和一台数码单反进行拍摄以覆盖不同的图像质量。关键在于模拟多样化的环境光照变化在自然光白天、傍晚、室内白炽灯、暖光灯、以及光线较暗的环境下分别拍摄。特别注意避免强光直射造成的反光尤其是麻将牌的光滑表面。背景复杂程度准备了纯色背景布作为简单背景、木质麻将桌、布艺桌布、以及带有杂乱物品的桌面如茶杯、烟灰缸等多种背景。拍摄角度与姿态除了标准的垂直俯拍还以30度、45度等倾斜角度拍摄模拟玩家坐姿的视角。同时故意将部分牌侧立、堆叠、半遮挡以增加数据的多样性。牌面状态使用了新旧不同的几副麻将牌包括牌面有轻微磨损、污渍的这能极大地提升模型对非理想条件的适应能力。采集策略我采用了“分步采集法”。首先对每一类牌如从一筒到九筒进行单张多角度、多光照的“标准照”采集确保每个类别有清晰的基础样本。然后进行“组合拍摄”将多张牌随机散落在桌面上拍摄模拟开局理牌的状态。最后进行“对局模拟拍摄”在四人牌局进行中从不同角度拍摄牌河、手牌部分和已碰/杠的牌组。注意在采集“组合”和“对局”图像时务必记录或事后可推断每张牌在图像中的具体位置和类别为后续标注做准备。一个笨但有效的方法是在拍摄完一张复杂场景后立即用手机备忘录画个草图标记大概位置和牌名。2.2 数据标注精细化的边界框与类别定义采集到的原始图像必须经过标注才能用于训练。我选择使用LabelImg或CVAT这类开源标注工具。标注的核心是两点边界框Bounding Box和类别标签Class Label。类别体系设计这是麻将数据集的特殊性所在。不能简单地标为“麻将牌”。一个合理的类别体系需要细分到每一张独立的牌。我采用的体系如下数字牌1tong,2tong, ...,9tong1tiao,2tiao, ...,9tiao1wan,2wan, ...,9wan。注意“条”有时也叫“索”在数据集中需统一。字牌dong,nan,xi,bei,zhong,fa,bai东、南、西、北、中、发、白。花牌如果规则包含chun,xia,qiu,dong,mei,lan,zhu,ju春、夏、秋、冬、梅、兰、竹、菊。 总共约34-42个类别取决于是否包含花牌。类别名称最好使用英文或拼音避免在训练脚本中出现编码问题。标注实操要点边界框紧密度框体应紧紧贴合牌的四边但不必过于精确到像素级留出1-2个像素的余量是可以接受的这有助于模型学习一定的空间容错。遮挡与截断处理对于被遮挡的牌框出可见部分并正常赋予类别标签。对于只露出一小部分的牌如少于1/4可以考虑不标注或根据项目需求决定如果需求就是检测任意露出的牌角则需要标注。数据格式YOLO格式的标注文件.txt是主流。每行表示一个对象格式为class_id x_center y_center width height。坐标和宽高都是相对于图像宽度和高度的归一化值0到1之间。务必确保标注工具导出的是此格式。标注一致性同一个类别在不同图像中的标签必须完全一致。建议先制定一个标注规范文档所有参与标注的人员共同遵守。2.3 数据集划分与增强提升模型泛化能力将标注好的数据随机打乱按7:2:1的比例划分为训练集Train、验证集Validation和测试集Test。验证集用于训练过程中监控模型表现、调整超参数、进行早停Early Stopping以防止过拟合测试集则用于最终评估模型的泛化能力在训练过程中绝对不可使用。数据增强Data Augmentation是提升数据集“虚拟”规模、让模型更鲁棒的关键技术。我直接在训练管道中集成了以下增强策略几何变换随机水平翻转对麻将牌很有用因为牌本身不是完全对称的但翻转可以模拟左右手玩家的视角、小幅度的旋转±15度、缩放和裁剪。色彩抖动调整图像的亮度、对比度、饱和度和色调。这能极大地模拟不同光照和手机相机自动白平衡带来的颜色差异。模拟噪声添加高斯噪声、椒盐噪声模拟低光照下的图像噪点或传输压缩带来的失真。Mosaic增强这是YOLO系列常用的一种增强将四张训练图像拼接成一张让模型学习在不同位置、不同尺度下检测目标对小目标检测尤其有效。经过以上步骤我最终构建了一个包含约5000张图像、超过60000个标注框的麻将数据集。这个规模对于34个类别的检测任务来说是一个比较扎实的起点。3. 模型核心YOLO框架的选择、训练与调优实战有了高质量的数据集下一步就是选择并训练模型。YOLO系列因其速度和精度的良好平衡成为实时目标检测的首选。3.1 YOLO版本选型与环境配置YOLO版本迭代很快从YOLOv5到YOLOv8再到最新的YOLOv11社区活跃度很高。我的选型考虑是平衡性能、易用性和社区支持。YOLOv5虽然非官方但其PyTorch实现非常成熟文档丰富训练和部署极其简单是快速上手的绝佳选择。YOLOv8Ultralytics公司官方维护不仅支持检测还支持分割、分类、姿态估计API设计更现代精度通常比v5有提升。YOLOv11最新版本在速度和精度上可能有进一步优化但作为新版本其稳定性和社区资源可能稍逊于v5/v8。考虑到项目的稳定性和我的熟悉程度我最终选择了YOLOv8。它的安装非常简单pip install ultralytics一行命令就完成了核心库的安装。它内置了训练、验证、预测和导出的全套命令行工具和Python API对新手非常友好。3.2 训练配置与参数解析YOLOv8的训练可以通过一个配置文件data.yaml和几条命令来启动。data.yaml文件定义了数据集的路径和类别信息。# data.yaml path: /path/to/your/mahjong_dataset # 数据集根目录 train: images/train # 训练集图像路径相对path val: images/val # 验证集图像路径 test: images/test # 测试集图像路径 nc: 34 # 类别数量例如34不含花牌 names: [1tong, 2tong, ..., 9wan, dong, nan, xi, bei, zhong, fa, bai] # 类别名称列表关键的训练命令如下yolo taskdetect modetrain modelyolov8n.pt datadata.yaml epochs100 imgsz640 batch16这里有几个重要参数需要理解其背后的“为什么”modelyolov8n.pt指定预训练模型。n代表“nano”是体积最小、速度最快的模型还有s(small),m(medium),l(large),x(extra large)等尺寸。对于麻将识别牌面图案特征相对复杂但固定我建议从yolov8s.pt或yolov8m.pt开始它们在精度和速度上有更好的平衡。使用预训练权重在COCO等大型数据集上训练过进行迁移学习可以极大加速收敛并提升最终性能。epochs100训练轮数。这不是一个固定值需要配合早停Early Stopping使用。我通常设置一个较大的值如300但通过监控验证集损失当其在连续一定轮数如patience50不再下降时自动停止训练避免过拟合。imgsz640输入图像的尺寸。YOLO会将所有图像缩放到此尺寸进行训练。更大的尺寸如1280能保留更多细节可能提升对小目标的检测精度如远处的牌但会显著增加显存消耗和训练时间。对于麻将牌这种在图像中通常占比不小的目标640是一个性价比很高的选择。batch16批量大小。取决于你的GPU显存。更大的Batch Size通常能使训练更稳定收敛更快但需要更多显存。如果出现CUDA out of memory错误需要降低batch或imgsz。3.3 训练过程监控与调优技巧启动训练后Ultralytics会启动一个本地Web页面默认http://localhost:8888展示训练指标这是非常直观的调试工具。需要重点关注的指标损失函数Box, Cls, Dfl总损失应持续下降并趋于平缓。如果训练损失下降但验证损失上升是典型的过拟合信号。mAP0.5 (mAP50)和mAP0.5:0.95 (mAP50-95)这是衡量检测精度的核心指标。mAP50是交并比IoU阈值为0.5时的平均精度更宽松mAP50-95是在多个IoU阈值0.5到0.95步长0.05下的平均值更严格。我们的目标是看到这两个指标在验证集上稳步提升。精确率Precision和召回率Recall精确率高意味着“说是麻将牌的基本都是真的”召回率高意味着“真的麻将牌基本都被找出来了”。在麻将场景下我们可能更追求高召回率不希望漏掉任何一张牌即使因此多了一些误检后续可以通过逻辑规则过滤。常见的调优手段学习率lr0这是最重要的超参数之一。默认值通常不错但如果训练初期损失震荡剧烈或下降缓慢可以尝试调低。YOLOv8支持学习率预热warmup_epochs和余弦退火调度一般无需手动调整。数据增强强度如果模型在训练集上表现很好但在验证集上差过拟合可以增强数据增强如增加旋转角度、色彩抖动幅度。如果模型在简单验证集上都表现不佳欠拟合可以减弱增强或检查数据质量。模型结构如果yolov8s精度不够可以尝试yolov8m。更大的模型容量意味着更强的特征提取能力但也需要更多数据和更长的训练时间。针对麻将的优化由于麻将牌形状、大小相对固定可以尝试调整锚框Anchor的尺寸。YOLOv8是Anchor-Free的但我们可以通过分析训练集中所有标注框的宽高分布来验证默认设定是否合适。使用工具分析后如果发现我们的牌框宽高比非常集中比如都在0.8到1.2之间接近正方形那么模型默认的锚框设定通常是适用的。在我的训练中使用yolov8m.pt在5000张图像的数据集上训练了约150个epoch早停触发最终在测试集上达到了mAP50-95: 0.92mAP50更是超过了0.98这意味着模型对于麻将牌的检测和分类已经非常准确。4. 推理部署与实战让模型在真实场景中跑起来训练出一个指标漂亮的模型只是第一步如何将它集成到实际应用中并稳定可靠地工作是更大的挑战。4.1 模型导出与优化训练完成后得到的最佳模型是best.ptPyTorch格式。为了在不同平台部署我们需要将其导出为更高效的格式。yolo export modelpath/to/best.pt formatonnx # 导出为ONNX格式 # 或者 yolo export modelpath/to/best.pt formatengine # 需要TensorRT环境导出为TensorRT引擎ONNX一种开放的模型交换格式被OpenCV、ONNX Runtime等多种推理框架支持是跨平台部署的优选。TensorRTNVIDIA GPU上的极致推理优化引擎能大幅提升推理速度。如果生产环境是固定的NVIDIA GPU服务器强烈推荐此格式。OpenVINO针对Intel CPU和集成显卡的优化格式。CoreML针对苹果设备iOS/macOS的格式。我通常先导出为ONNX因为它通用性最强。可以使用netron.app网站可视化ONNX模型结构确保导出正确。4.2 编写推理脚本以下是一个使用YOLOv8的Python API进行实时摄像头推理的简化示例from ultralytics import YOLO import cv2 # 加载训练好的模型 model YOLO(path/to/best.pt) # 或 path/to/best.onnx # 打开摄像头 cap cv2.VideoCapture(0) while True: ret, frame cap.read() if not ret: break # 执行推理 results model(frame, imgsz640, conf0.5) # conf为置信度阈值 # 解析结果 for result in results: boxes result.boxes.xyxy.cpu().numpy() # 边界框 [x1, y1, x2, y2] confidences result.boxes.conf.cpu().numpy() # 置信度 class_ids result.boxes.cls.cpu().numpy().astype(int) # 类别ID for box, conf, cls_id in zip(boxes, confidences, class_ids): x1, y1, x2, y2 map(int, box) label f{model.names[cls_id]} {conf:.2f} # 绘制框和标签 cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(frame, label, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2) # 显示结果 cv2.imshow(Mahjong Detection, frame) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()4.3 实战中的挑战与解决方案在实际部署中你会遇到训练时未曾遇到的问题光照突变与反光这是最大的挑战。即使数据增强包含了亮度变化强烈的点光源反光仍可能让模型“失明”。解决方案在图像预处理阶段加入抗反光处理。可以尝试使用CLAHE对比度受限的自适应直方图均衡化来增强局部对比度或者采用高动态范围HDR成像技术融合多张不同曝光的图像。更工程化的做法是在硬件上想办法比如使用偏振镜或调整光源位置形成漫反射光。密集遮挡与重叠牌局中牌堆叠、紧挨着的情况非常普遍。解决方案YOLO本身具备一定的重叠目标检测能力。可以尝试调低非极大值抑制NMS的IoU阈值如从默认的0.45降到0.3让模型保留更多重叠的检测框。但这会增加误检需要后续结合麻将牌的物理尺寸和排列规则进行逻辑过滤。推理速度与资源限制在手机或树莓派等边缘设备上运行需要轻量化模型。解决方案训练时选择yolov8n或yolov8s这类小模型。导出时使用量化技术如INT8量化可以大幅减少模型体积和提升推理速度同时精度损失很小。TensorRT和ONNX Runtime都支持量化。误检与漏检的后处理解决方案利用领域知识进行后处理。例如尺寸过滤检测到的框的宽高比应在一定范围内接近1:1.5左右取决于牌的实际比例。空间关系麻将牌通常摆放在桌面上其底边y坐标应该相近在同一水平线上。逻辑一致性同一副牌中同类牌的数量是有限的如每种数字牌最多4张。可以设置一个简单的计数逻辑对明显超出合理数量的检测结果进行抑制或重新评分。5. 项目总结与未来可扩展方向通过这个完整的项目流程我们实现了一个从数据采集到模型部署的端到端麻将识别系统。回顾整个过程最深的体会是数据决定了上限调优逼近了上限而工程化处理决定了系统在实际中的下限。构建一个覆盖各种 corner case 的数据集所花费的精力远大于模型训练本身。而模型训练出来后的反光、遮挡等问题又需要结合传统的图像处理方法和领域知识去解决这正是一个典型AI落地项目的缩影。这个项目还有非常多可以深化和扩展的方向3D姿态估计不仅识别是什么牌还能估计牌的旋转角度和3D位置这对于机器人抓取摆牌至关重要。序列分析与决策结合OCR识别出的牌面序列构建一个简单的麻将AI分析听牌、计算番型甚至做出出牌建议。跨域自适应我们的模型在自家麻将牌上表现很好但换一副风格迥异的麻将比如日式麻将、塑料牌 vs. 骨牌可能效果会下降。可以研究领域自适应Domain Adaptation技术用少量新数据快速适配新牌具。端侧部署优化将模型进一步量化、裁剪并利用TensorFlow Lite、Core ML或NCNN等框架部署到安卓/iOS手机APP中实现离线实时识别。麻将识别只是计算机视觉在特定垂直领域的一个有趣应用。这套方法论——从定义问题、构建特定数据集、选择并调优模型、到解决实际部署难题——完全可以迁移到其他类似的细粒度物体识别项目上比如扑克牌识别、工业零件分拣、商品SKU识别等。希望这份详尽的实践记录能为你开启自己的目标检测项目提供一份扎实的参考。本文还有配套的精品资源点击获取
返回列表