目录

摘要:本文记录了一个从零开始的端侧麻将牌识别项目全流程。基于YOLOv8n训练了支持42类牌面识别的轻量化模型,通过TensorFlow Lite部署至Android端,在普通手机上实现40ms级实时推理。文章详细阐述了数据清洗、模型训练、端侧优化及关键代码实现,并分享了实际开发中的踩坑经验。项目源码及模型已开源,供技术交流。

一、数据处理

二、模型训练

三、安卓部署

3.1 模型集成

3.2 后处理(NMS实现)

3.3 实时预览与优化

四、效果展示

五、实现的功能

六、踩坑与心得

七、项目结构与环境

八、声明


 

摘要:本文记录了一个从零开始的端侧麻将牌识别项目全流程。基于YOLOv8n训练了支持42类牌面识别的轻量化模型,通过TensorFlow Lite部署至Android端,在普通手机上实现40ms级实时推理。文章详细阐述了数据清洗、模型训练、端侧优化及关键代码实现,并分享了实际开发中的踩坑经验。项目源码及模型已开源,供技术交流。


一、数据处理

数据来源为多个公开麻将数据集(含标注图片)。原始数据存在格式不统一、标注噪声等问题,主要处理工作如下:

  • 格式统一:将COCO、VOC等不同格式统一转为YOLO格式(class_id x_center y_center width height归一化坐标)。

  • 清洗去重:通过脚本剔除边界框偏移超过20%、类别名称不一致(如“五万”与“5w”)的样本,共过滤约300张低质量图片。

  • 合并增强:最终得到1.8万张标注图片,覆盖白天/夜晚/暖光、俯拍/斜拍、牌面不同程度磨损等场景,按8:1:1划分训练/验证/测试集。

清洗示例:原始数据中存在同一张图片在不同数据集中重复的情况,基于MD5哈希去重后保

证了训练集与测试集无重叠。


二、模型训练

采用YOLOv8n作为基模型(兼顾精度与速度),训练配置如下:

参数 取值
输入分辨率 640×640
优化器 AdamW
初始学习率 0.001
学习率调度 Cosine annealing
数据增强 Mosaic, MixUp, HSV调整
训练轮数 100
批量大小 64

最终在验证集上的性能:

  • mAP50 = 94.6%

  • mAP50-95 = 0.745

模型支持标准麻将牌面全类别识别(万、筒、条、字牌共42类)。

轻量化处理:训练后将模型导出为TensorFlow Lite格式,并应用动态范围量化,模型体积从6.2MB压缩至2.1MB,推理速度提升约30%,同时精度下降小于0.5%。


三、安卓部署

3.1 模型集成

在Android Studio中引入TFLite依赖(build.gradle):

gradle

dependencies {
    implementation 'org.tensorflow:tensorflow-lite:2.14.0'
    implementation 'org.tensorflow:tensorflow-lite-gpu:2.14.0'
}

模型加载与推理核心代码(Kotlin):

kotlin

class TFLiteHelper(context: Context) {
    private var interpreter: Interpreter

    init {
        val model = loadModelFile(context)
        val options = Interpreter.Options().apply {
            setNumThreads(4)                      // CPU多线程
            addDelegate(CompatibilityList().delegates.firstOrNull()) // GPU委托自动启用
        }
        interpreter = Interpreter(model, options)
    }

    fun predict(bitmap: Bitmap): List<Detection> {
        val input = preprocess(bitmap)  // 转换为ByteBuffer,归一化
        val output = Array(1) { Array(25200) { FloatArray(42 + 5) } }
        interpreter.run(input, output)
        return postprocess(output, bitmap.width, bitmap.height)
    }
}

3.2 后处理(NMS实现)

YOLOv8导出TFLite后不包含NMS,需在App端实现:

kotlin

fun postprocess(output: Array<Array<FloatArray>>, imgW: Int, imgH: Int): List<Detection> {
    val detections = mutableListOf<Detection>()
    for (i in 0 until 25200) {
        val conf = output[0][i][4]
        if (conf > 0.25) {
            val classScores = output[0][i].sliceArray(5 until output[0][i].size)
            val (cls, score) = classScores.withIndex().maxByOrNull { it.value }!!
            if (score > 0.5) {
                val x = output[0][i][0] * imgW
                val y = output[0][i][1] * imgH
                val w = output[0][i][2] * imgW
                val h = output[0][i][3] * imgH
                detections.add(Detection(cls, score, RectF(x - w/2, y - h/2, x + w/2, y + h/2)))
            }
        }
    }
    return nonMaxSuppression(detections, 0.45)   // 自定义NMS
}

3.3 实时预览与优化

  • 使用CameraXImageAnalysis分析流,设置setBackpressureStrategy(STRATEGY_KEEP_ONLY_LATEST)避免帧积压。

  • 推理耗时:CPU约300ms(测试机型:红米k70pro)。

  • 帧率控制:每帧推理完成后立即绘制,维持实时性。


四、效果展示

场景 光线条件 识别准确率(mAP50) 平均推理时间(cup)
俯拍 正常日光 95.2% 200ms
斜拍 暖色灯光 93.1% 200ms
俯拍 弱光 88.5% 200ms


图中展示了摄像头实时识别牌面、识别框跟随、手牌类别统计等功能。


五、实现的功能

  • 摄像头实时识别牌面,支持全类别识别

  • 手牌状态的本地识别与统计

  • 作为端侧AI图像识别的功能演示,验证YOLOv8在移动端的部署流程

当前限制:牌河区域自动识别尚未集成(后续可扩展),其他基础功能已跑通。


六、踩坑与心得

  1. TFLite与YOLOv8的后处理
    导出时若直接使用model.export(format="tflite"),得到的模型不包含NMS。需要在移动端重新实现,且注意输出张量的维度顺序([1, 25200, 47]),否则解析会出错。

  2. 坐标映射偏差
    CameraX返回的ImageProxy与预览视图尺寸不一致,需通过Matrix变换将检测框正确映射到屏幕坐标。最终采用imageProxy.image?.let { image -> }获取原始宽高,结合预览View的缩放比例进行转换。

  3. GPU委托兼容性
    部分老机型(Android 8以下)GPU委托失败,需增加回退机制:try { interpreter.useGpuDelegate() } catch(e: Exception) { interpreter.useCpu() }

  4. 数据增强对泛化性的影响
    加入Mosaic和MixUp后,弱光下识别率明显提升,但模型对极端磨损牌面仍有混淆,后续计划针对这类样本做离线增强。


七、项目结构与环境

运行步骤

  1. 用Android Studio打开项目,同步Gradle。

  2. model.tflite放入app/src/main/assets/目录。

  3. 连接Android设备(需支持Camera2 API),点击Run即可。

开发环境

  • 训练:Python 3.10, PyTorch 2.0, Ultralytics YOLOv8.0

  • 部署:Android Studio Hedgehog, minSdk 24, targetSdk 34, TensorFlow Lite 2.14

开源资源

  • 完整Android Studio源码(模型加载、相机预览、识别绘制、逻辑处理)

  • 转换好的TFLite模型(可替换)


八、声明

本项目仅用于计算机视觉与端侧模型部署的技术学习,所有数据均为公开数据集,不涉及任何实际场景应用。

 

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐