news 2026/8/31 18:32:41

舌苔图像数据集构建指南:从标注到语义分割训练实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
舌苔图像数据集构建指南:从标注到语义分割训练实践

简介:这份舌苔数据集面向中医图像识别与深度学习研究者,聚焦中医舌诊中舌苔颜色、质地、厚度等特征的自动分类与标注,高分辨率原图能较好保留舌苔纹理细节。压缩包内含 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.txt

images目录存放统一处理后的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,这块我统一走了一套预处理流程:

  1. 读取原始图像,先做白平衡校正,减少不同光源带来的色偏
  2. 按短边等比缩放,使短边达到512像素
  3. 中心裁剪到512x512
  4. 保存时统一用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_names=None): with open(json_path, 'r', encoding='utf-8') as f: data = json.load(f) mask = np.zeros(img_size, dtype=np.uint8) for idx, shape in enumerate(data['shapes']): points = np.array(shape['points'], dtype=np.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 python=3.9 conda activate labelme pip install labelme

启动直接用labelme命令即可。如果遇到界面打不开,大多数情况是PyQt5相关依赖没装好,常规做法是重装依赖。

日常标注中几个高频操作的快捷键很实用,用好了效率能提一大截:

  • w:开始画多边形
  • Ctrl+Z:撤销上一个点
  • Ctrl+S:保存当前标注
  • D:切换到下一张图
  • A:切换到上一张图

5.2 标注和训练环节的几个常见问题

我把整个流程里遇到典型问题整理成一张表,方便对应排查。

问题可能原因解决方案
JSON文件打不开标注时程序异常退出,文件不完整重新标注,或手动修复JSON格式
生成的mask全黑类别编号没对上检查class_names顺序与标注名是否一致
训练时图片加载失败文件名带中文或路径含特殊字符统一改为数字文件名
验证集指标虚高同源图片划分不干净按采集对象分组划分
分割边缘毛刺多多边形点太密但标注不精确适当增加多边形点数,提高标注精度
labelme标注时图片加载不出来图片格式不受支持或文件损坏统一转为JPG格式存放

5.3 一个特别容易被忽视的坑:JSON里的imagePath

labelme在保存JSON时,会在内部记录原始图片路径,即imagePath字段。如果你在标注后移动了图片文件或改了文件名,再用labelme打不开JSON,原因就在这里。

解决方案有两种:一是用文本编辑器打开JSON,手动更新imagePath为正确的文件名;二是写一个批量脚本,遍历所有JSON文件并修改这个字段。这块看似不起眼,但一旦你处理上百个文件就会非常费时间,建议从第一天就保持图片和JSON同名同目录。

另一个容易踩的坑是标注类别名用中文。倒不是完全不能用,但后续转mask、训练、可视化等环节,只要有一处编码没处理好就容易出问题。建议统一用拼音或英文做类别名,显示中文标签的需求可以放到后处理阶段实现。

最后补一句个人的实际心得

整理这套舌苔数据集前后花了几周时间,真正耗时的地方不是标注本身,而是反复检查和修正标准。如果当初在采集阶段就严格控制光源、固定拍摄距离、做好白平衡,后面很多图像增强和预处理的功夫都能省下来。数据质量永远是模型效果的天花板,这个体会在做任何医学图像项目时都适用。标注阶段多花的时间,最后都会以模型精度的形式给你回报。

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/31 18:32:13

数据库系统Lab作业全流程指南:从解压到查询优化与事务控制

简介:本资源为西安交通大学计算机专业《数据库系统》课程配套实验作业完整实现包,面向高校数据库初学者与实践者,聚焦数据库设计、SQL编程及应用集成三大核心能力训练。压缩包共37个文件,含11个Python脚本(涵盖连接管理…

作者头像 李华
网站建设 2026/8/31 18:30:42

元初混沌体系 第三卷 卫星互联网全域周天拓扑体系:第七十一篇 高轨统筹层拓扑安全结界划分体系

第七十一篇 高轨统筹层拓扑安全结界划分体系承启前置 篇章立论前文第七十篇完成高轨轨道拥堵周天拓扑分流方案永久定型,通过三维立体轨道扩容、横向相位错峰疏解、三层联动流量泄压、动态资源循环复用体系,彻底根治西方高轨轨道无序堆叠、资源内卷、拥堵…

作者头像 李华
网站建设 2026/8/31 18:28:57

2026编程两大核心原则全链路落地:代码降本增效与避坑实操方案

真正拉开程序员差距的从来不是代码编写速度,而是编码思维与原则的落地能力。2026年数字化开发场景下,多数开发者陷入重复编码、代码可读性差、后期维护成本高的困境,掌握DRY避免重复、别让我思考两大核心编程原则,可实现代码轻量化…

作者头像 李华
网站建设 2026/8/31 18:28:18

AI 数字人一体机 本地云端双部署选型实战指南|蓝速科技

很多 AI 数字人一体机项目因部署架构与现场条件错配,出现卡顿、交互失效等问题。蓝速科技从网络勘测、成本测算、安全合规、混合部署多维度拆解选型逻辑,帮助项目方结合现场实际,选出适配的部署方案,规避项目交付风险。如何通过网…

作者头像 李华
网站建设 2026/8/31 18:27:59

爱奇艺C++校招笔试复盘:字符串、链表与底层基础全解析

爱奇艺2018秋季校招的C工程师笔试,我印象里第三场是十月中旬的那批。当时在线笔试系统用的还是牛客网那套,一共三道编程题加一堆选择填空,时间卡得比较紧。现在回头看,那场笔试题的风格很有代表性:不堆偏题怪题&#x…

作者头像 李华
网站建设 2026/8/31 18:26:58

C语言BMP图像读写源码解析:字节对齐与像素处理

简介:面向初学者的C语言图像读写演示工程,基于Visual Studio开发,全程不依赖任何第三方图像库。源码围绕图像文件读取、像素解析与写回展开,能让读者直接接触二进制文件I/O、文件头部信息解析以及内存中RGB/灰度像素的读写方法&am…

作者头像 李华