简介这份舌苔数据集面向中医图像识别与深度学习研究者聚焦中医舌诊中舌苔颜色、质地、厚度等特征的自动分类与标注高分辨率原图能较好保留舌苔纹理细节。压缩包内含 2000 个 JSON 标注文件并配有相应 512×512 像素原图整包约 206MB数据涵盖黑苔、地图舌、白厚腻苔、紫苔、红厚腻苔、红舌黄腻苔等多种典型证型可直接用于训练 CNN 实现分类、分割或目标检测也可为分割模型提供像素级监督信息。JSON 中保存了区域标注与类别信息文件名也能直观区分不同舌苔类型便于使用 Python、PyTorch 或 TensorFlow 进行数据预处理、数据增强与模型迭代调优。目前已有 2453 人学习下载对希望将中医舌诊数字化、构建辅助诊断模型的开发者而言这是一份标注规范、类别清晰、可直接上手实践的高质量基础数据集。 最近把手头这套舌苔图像数据集完整整理了一遍两千多张样本图全部统一成512x512分辨率原图配上labelme标注好的JSON标签一起存放。这套东西的定位很明确给中医舌诊客观化、计算机视觉辅助诊断这类方向做训练数据。整理过程中踩了不少坑从标注规范到格式转换都走了一遍完整流程正好有朋友问起数据集细节就把整个构建思路、操作路径和复用方案系统写出来方便准备做类似医学图像数据集的人直接参考。这套数据适合两类人一是想用深度学习做舌象分割、舌诊辅助判断的CV开发者二是需要把raw图像整理成可训练数据集的初学者尤其是对labelme标注、JSON转mask、模型输入规范这些链路不熟的朋友。数据本身包含舌体区域的多边形标注可以直接拿来训练语义分割模型也可以在此基础上扩展成分类或检测任务。1. 为什么要整理这套舌苔数据集1.1 舌诊客观化的直接需求中医舌诊讲究“望舌质、察舌苔”但传统方式依赖医生肉眼观察结果描述主观性强不同医生之间对同一舌象的判断常常有偏差。这个问题在临床带教、远程问诊、健康管理场景下尤其明显。让深度学习模型自动完成舌体分割、舌苔区域提取、舌色苔色识别就成了一个非常接地气的落地方向。可是真做起来才发现公开渠道几乎没有像样的舌苔分割数据集。医疗数据本身涉及隐私采集门槛高很多实验室的数据又不公开直接导致想训练一个分割模型都找不到合适的训练语料。所以自己构建一套包含原始图像和像素级标签的舌苔数据集是绕不开的基础工作。1.2 两千多张图够不够用为什么定512x512医学图像数据集的规模普遍偏小这是行业常态。两千多张图对于语义分割任务来说属于“起步可用”的规模如果只做二分类区分有没有某种舌象特征或者基础分割配合数据增强和后处理完全可以把模型训练到能用的程度。分辨率选了512x512不是拍脑袋定的。舌苔图像的特点是纹理细节重要但整体结构并不复杂不需要像自然图像那样动辄上千的分辨率。512x512在保留舌面纹理细节、舌苔薄厚变化这些关键信息的同时显存开销可控。拿一张NVIDIA GTX 1080Ti或RTX 3060级别的显卡来说batch size设到8左右跑一个U-Net基本没有压力。如果直接用原始相机照片训练分辨率跨度太大还要处理统一尺寸的问题反而多一层麻烦。1.3 labelme标签为什么值得用labelme是语义分割标注里最常用的工具之一它生成的是JSON格式的矢量标注文件里面记录的是多边形关键点坐标而不是直接输出mask图。这个设计有它的好处多边形可以反复编辑修改某个点不影响整张图标签信息里可以附加额外的属性字段后续想转换成mask、COCO格式还是YOLO格式都很方便。很多人在标注工具选型上纠结过labelme和labelimg。简单说labelimg适合画矩形框做目标检测labelme适合画多边形做像素级分割。舌苔区域本身形状不规则舌体边缘、舌苔覆盖区域都不是标准矩形直接画框会引入大量背景噪声所以多边形标注是必然选择。2. 数据集结构与标注规范2.1 目录结构设计数据集整体存放结构如下这个结构也是我实际在用的简单直观方便写脚本批量处理。tongue_dataset/ ├── images/ │ ├── 001.jpg │ ├── 002.jpg │ └── ... ├── labels/ │ ├── 001.json │ ├── 002.json │ └── ... ├── class_names.txt ├── train.txt ├── val.txt └── test.txtimages目录存放统一处理后的512x512原图labels目录存放同名JSON文件一一对应。train.txt、val.txt、test.txt记录划分好的样本名训练时直接读这些列表文件即可不用重复搬动图片文件。有个细节值得提一下文件命名统一用数字序号不要用中文名也不要带空格。之前在整理一批数据时文件名里有中文和空格训练时每次加载图片都要处理编码问题数据管道的稳定性受影响后来全部改成纯数字再没出过幺蛾子。2.2 labelme标注的类别设计舌苔数据集的标注类别设计要贴合中医诊断的维度。我实际用的类别主要包括以下几类tongue_body舌体区域整个舌头的轮廓tongue_coating舌苔覆盖区域crack裂纹舌面上的裂纹纹理tooth_mark齿痕舌体边缘的牙齿压痕ecchymosis瘀斑舌面上的瘀点瘀斑其中舌体和舌苔是最核心的类别裂纹、齿痕、瘀斑是扩展类别。如果你只是想跑通一个分割模型建议第一版只标舌体和舌苔两个类别把数据规模和质量做扎实再慢慢扩。有一点要特别提醒舌苔和舌体不是互斥关系。舌苔覆盖在舌体之上两个类别在空间上是重叠的。如果按照严格的语义分割要求每个像素只能有一个类别那就需要定义优先级。我的做法是“舌质”指没有舌苔覆盖的舌体区域“舌苔”指有舌苔覆盖的区域在标注时先画舌体外轮廓再画舌苔区域生成mask时用舌体减去舌苔得到干净的舌质区域这样能同时保留多层信息。2.3 512x512图像的处理细节原始采集到的图片不可能天然就是512x512这块我统一走了一套预处理流程读取原始图像先做白平衡校正减少不同光源带来的色偏按短边等比缩放使短边达到512像素中心裁剪到512x512保存时统一用JPEG格式质量参数设为95采用缩放加中心裁剪而不是直接拉伸是为了保持舌体比例不变。直接拉伸会把舌头压扁或拉长舌形特征变形模型学到的特征就有偏差。关于图像通道这套数据是标准的三通道RGB图像。为什么强调通道因为有些医学图像是灰度图或特殊成像模态而舌诊图像依赖颜色信息来判断舌色、苔色必须保留RGB三通道。模型输入层也相应设置为3通道常见的ResNet、U-Net结构默认就支持完全兼容。3. 从原始标注到可训练数据的关键步骤3.1 标注质量检查两千多张图标注完成后逐张人工检查不现实但也不能直接拿去训练。我用脚本做了几项自动化检查检查JSON文件能否正常解析有没有损坏检查多边形点数量小于3个点的多边形直接标记为异常检查标注框是否超出图像边界检查是否存在空标注只有图片没有标注内容实际操作时发现最常出现的问题就是多边形边界超出图像范围。用labelme标注时如果图像比较大缩放到屏幕外后很容易把点打到画布外面生成的坐标超出图像尺寸。这类问题必须批量筛查出来否则转mask时会出现索引越界。3.2 JSON转mask的方法labelme的JSON格式不能直接拿来训练分割模型要转成单通道的mask图每个像素值对应一个类别编号。核心转换逻辑如下import json import numpy as np import cv2 from labelme import utils def json_to_mask(json_path, img_size(512, 512), class_namesNone): with open(json_path, r, encodingutf-8) as f: data json.load(f) mask np.zeros(img_size, dtypenp.uint8) for idx, shape in enumerate(data[shapes]): points np.array(shape[points], dtypenp.int32) label shape[label] class_id class_names.index(label) if label in class_names else 0 cv2.fillPoly(mask, [points], class_id) return mask这段代码的核心是用cv2.fillPoly把多边形填充成掩码。注意labelme官方还提供了一个utils.shapes_to_label方法内部逻辑差不多但自己写一遍能更好理解数据流。转换过程中一个容易忽略的坑labelme JSON中记录的是多边形在原始图片上的坐标如果你的原图在标注后做过resize坐标也需要同步缩放。这套数据是先统一成512x512再做标注所以坐标天然对应省了一件事。3.3 数据划分与增强数据划分时要特别注意一个原则同一个人的多张相似图片不能同时出现在训练集和验证集中。舌苔图像往往是一个人在不同时间采集的连续样本亮度和舌象状态很接近如果划分不干净模型会“记住”特定人的特征验证集指标虚高泛化能力却很差。我按大约7:2:1的比例划分训练集、验证集、测试集同时保证同一人不同时间的样本划分在同一个集合内。数据增强方面舌苔图像有其特殊性。随机旋转、水平翻转、缩放这些常规操作没问题但颜色类增强要非常克制。舌诊依赖颜色判断如果过度调整亮度、对比度、色相模型学到的是“增强后的舌头颜色”而不是真实舌头颜色。我实际用的增强策略是旋转范围±10度亮度调整范围0.8到1.2仅此而已不做饱和度、色相的大幅扰动。4. 基于这套数据集直接跑起来的模型训练路径4.1 分割模型选型有了JSON转换后的mask最直接的任务就是语义分割。几个常见选择的适用场景不同U-Net经典医学分割网络参数量适中两三百张训练图就能正常收敛是当之无愧的第一选择DeepLabV3分割精度更高边界更平滑但对训练数据量和调参水平要求更高nnUNet自动化程度极高自带数据预处理、网络配置和训练流程但配置复杂且默认流程在设计上更偏向CT、MRI这类医疗影像直接跑舌苔图像需要适配我的建议是先用U-Net跑通基线验证数据质量再逐步尝试更复杂的模型。4.2 从分割到分类和检测的扩展分割模型输出的mask其实还能二次利用。比如要做一个“舌苔厚度分级”的分类任务可以先用分割模型把舌苔区域裁出来再训练一个轻量分类模型。这样比直接让分类模型全图判断更准确因为排除了背景干扰。如果要做目标检测可以把分割mask的外接矩形提取出来转成YOLO需要的txt格式。不过舌体检测的直接价值有限更推荐直接做分割。分割本身已经提供了比检测更丰富的信息从这个角度来说这套数据更偏语义分割场景。4.3 训练参数参考我把实际训练中效果比较稳定的参数组合列在这里按这个配比起步不会出大问题。参数项参考值备注输入尺寸512x512与原图分辨率一致损失函数DiceLoss CrossEntropyLoss比例为7:3优化器AdamW初始学习率1e-4学习率策略CosineAnnealing最小学习率1e-6训练轮数100配合早停策略Batch Size8视显存大小调整数据增强旋转±10度、水平翻转、亮度微调注意不要过度调色评估指标主要看Dice系数和IoU。对于二分类舌头分割任务Dice达到0.95以上比较理想舌苔分割的难度稍高Dice达到0.85以上已经可用。5. 常见问题与排查技巧实录5.1 labelme安装和使用高频问题labelme的安装本身不算麻烦但在不同环境下确实容易踩坑。早期版本依赖Python的某些包版本冲突多建议直接用conda创建独立环境Python版本3.8到3.10之间都比较稳然后执行安装conda create -n labelme python3.9 conda activate labelme pip install labelme启动直接用labelme命令即可。如果遇到界面打不开大多数情况是PyQt5相关依赖没装好常规做法是重装依赖。日常标注中几个高频操作的快捷键很实用用好了效率能提一大截w开始画多边形CtrlZ撤销上一个点CtrlS保存当前标注D切换到下一张图A切换到上一张图5.2 标注和训练环节的几个常见问题我把整个流程里遇到典型问题整理成一张表方便对应排查。问题可能原因解决方案JSON文件打不开标注时程序异常退出文件不完整重新标注或手动修复JSON格式生成的mask全黑类别编号没对上检查class_names顺序与标注名是否一致训练时图片加载失败文件名带中文或路径含特殊字符统一改为数字文件名验证集指标虚高同源图片划分不干净按采集对象分组划分分割边缘毛刺多多边形点太密但标注不精确适当增加多边形点数提高标注精度labelme标注时图片加载不出来图片格式不受支持或文件损坏统一转为JPG格式存放5.3 一个特别容易被忽视的坑JSON里的imagePathlabelme在保存JSON时会在内部记录原始图片路径即imagePath字段。如果你在标注后移动了图片文件或改了文件名再用labelme打不开JSON原因就在这里。解决方案有两种一是用文本编辑器打开JSON手动更新imagePath为正确的文件名二是写一个批量脚本遍历所有JSON文件并修改这个字段。这块看似不起眼但一旦你处理上百个文件就会非常费时间建议从第一天就保持图片和JSON同名同目录。另一个容易踩的坑是标注类别名用中文。倒不是完全不能用但后续转mask、训练、可视化等环节只要有一处编码没处理好就容易出问题。建议统一用拼音或英文做类别名显示中文标签的需求可以放到后处理阶段实现。最后补一句个人的实际心得整理这套舌苔数据集前后花了几周时间真正耗时的地方不是标注本身而是反复检查和修正标准。如果当初在采集阶段就严格控制光源、固定拍摄距离、做好白平衡后面很多图像增强和预处理的功夫都能省下来。数据质量永远是模型效果的天花板这个体会在做任何医学图像项目时都适用。标注阶段多花的时间最后都会以模型精度的形式给你回报。本文还有配套的精品资源点击获取