资讯动态

牙齿病变分割数据集:6类标注与json转mask/COCO指南

发布时间:2026/10/28 4:39:00 来源:尧图企业网站定制
简介面向牙齿分割与牙齿病变检测的标注数据集说明文档适合医学图像分割学习者及需要龋齿、牙结石、炎症等病灶数据的算法开发者参考。资源包为1个docx文件约2.22MB集中整理数据集构成、标注类别与使用限制便于在下载前判断数据是否匹配任务。数据集含2616张jpg图像及对应labelme格式json采用多边形标注共6类Tooth、Caries、Cavity、Crack、calculus、inflamation并列出各类数量其中Tooth 1709、Caries 2913、Cavity 1099、Crack 139、calculus 1207、inflamation 620可用于评估类别分布与标注均衡性。文档还注明标注工具为labelme 5.5.0部分牙齿未标注但不影响病变检测json需自行转换为mask、YOLO或COCO格式后再用于语义或实例分割且不对训练模型精度作保证。已有122人学习可作为牙齿病变数据筛选、标注规则核对与格式转换准备的参考并帮助读者评估后续训练与数据清洗成本。1. 一句话说清牙齿病变分割数据集到底是个什么东西想快速搞懂“数据集”这个词最好的办法是把它当成一本带答案的练习册图片是题目标注是答案。这份牙齿分割与牙齿病变分割数据集就是 2616 张牙齿影像配 2616 份标注答案答案用 labelme 5.5.0 存成 json 文件一共圈出 6 个类别——牙齿本身以及龋齿、龋洞、裂纹、牙结石、炎症五种病变。它的价值不在于“有图”而在于“图上的每一处异常都被人用多边形描过边”。很多人第一次接触“数据集”会以为是下载下来就能直接喂给模型的压缩包结果解压一看全是 json瞬间懵住。搞懂这份数据集的构成逻辑你就同时搞懂了图像分割任务里“标注”到底在标什么。2. 为什么这份数据集长这样从“有些牙齿没标”说起2.1 标注目标是病变不是给每颗牙点名一份数据集的标注范围从来不是由“图里有什么”决定的而是由“你想让模型学会什么”决定的。这份数据的用途写得很直白主要检查病变。所以在标注资源有限的前提下标注者把多边形优先画在了龋齿、龋洞、裂纹、结石、炎症这些需要被报出来的位置上。健康的、清晰的、没什么可说的牙面标不标对“找病灶”这件事影响很小。打个比方体检报告不是把你全身每一寸皮肤都描述一遍而是把异常项单独列出来你不会因为报告没写“左胳膊正常”就觉得这份报告不完整。这个选择带来一个必须记住的副作用Tooth 类的标注数是 1709而图片总数是 2616。也就是说有相当一部分图片里的牙齿根本没有被圈出来。如果你拿这份数据去训一个“把每颗牙都分割出来”的模型模型会学到一个奇怪的规律——有些牙该输出有些牙不该输出。召回率怎么调都上不去很多人卡在这里还以为是模型结构的问题。2.2 一份 json 里到底装了什么labelme 的 json 是一种“自描述”的文件它不只记录形状还记录这个形状叫什么。打开一份 json你能看到图片文件名、图片的宽和高、以及一个 shapes 数组数组里每一项包含类别名 label、一堆顶点坐标 points、还有形状类型 shape_type。它不存 mask 图片也不存原图本身只存原图的文件名。这意味着 jpg 和 json 必须成对管理删一个、挪一个配对关系就断了。这也解释了数据集为什么特别注明“不包含 mask 文件”。mask 是从 json 现场生成的属于派生产物json 才是原始记录里面多了类别名这一层信息。你手上握的是“原始记录”而不是“加工好的成品”灵活度高但要多走一步。很多人下载完发现没有 mask第一反应是“数据不全”其实恰恰相反——有 json 才叫全mask 随时能画出来反过来却不行。2.3 2616 张、6 个类别是怎么定下来的类别不是随手凑的。龋齿、龋洞、裂纹、牙结石、炎症是口腔影像里最常见的几类可观察异常而且都有一个共同特征它们能被多边形圈出来圈出来之后对判断有意义。这一点很关键——标注类别必须“可描边”。像“牙齿敏感”这种描述性、不可见的问题就没法做成分割标签硬要标只会让标注者互相打架。2616 张这个量级也值得说道。它足够跑通一整条流程、足够做迁移学习的微调、足够验证一个想法是否成立但它不足以从零训练一个大模型。把它当成“起步数据”而不是“终极数据”心态会稳很多。用一句话概括这份数据的性格目标明确、范围克制、留了缺口需要使用者自己补齐后半程。3. 六类标注拆开看Tooth、Caries、Cavity、Crack、calculus、inflamation3.1 六个标签各自对应什么Tooth 是牙体轮廓也就是“这是牙”的那一层底色。它本身不是病但它提供了位置上下文——病变总是长在牙上的知道牙在哪模型判断“这块阴影是不是病灶”时就有了参照系。剩下的五类是病变Caries 指龋坏区域倾向于描述“正在蛀”的那一片Cavity 指已经形成的龋洞是缺损的结果Crack 是牙体上的裂纹calculus 是牙结石通常附着在牙面靠近牙龈的位置inflamation 是炎症区域多表现为牙龈边缘的红肿范围。Caries 和 Cavity 是最容易混的一对。通俗地说Caries 是“蛀的过程”Cavity 是“蛀出来的坑”。同一个位置早期只有龋坏、还没成洞那就只标 Caries等到组织塌陷形成明显缺损才额外标 Cavity。两者可以同时出现在一颗牙上也可以只出现一个。搞不清这一点你在做类别统计和后处理阈值时会一路错下去。3.2 数量分布藏着什么信号把六类的标注数摆在一起能读出很多信息类别标注数占总标注比例直观解读Tooth170922.2%只圈了部分牙非全量Caries291337.9%数量最多单图可多个Cavity109914.3%成洞比例不低Crack1391.8%典型稀有类calculus120715.7%分布较均匀inflamation6208.1%中等偏少六类合计 7687 个标注平均每张图 2.94 个。注意 Caries 的 2913 已经超过了图片总数 2616这直接说明同一张图里可以存在多个龋齿多边形。这个细节看起来小但它决定了你转换格式时不能用“一张图一个标签”的思路去做。Crack 只有 139 个占比不到 2%是标准的稀有类训练时如果不做重采样或者损失加权模型大概率会直接学会“永远预测没有裂纹”准确率还挺好看实际一个都找不出来。这类问题在数据分布上写得明明白白只是很多人不看。3.3 polygon 到底比矩形框强在哪这份数据全部用多边形polygon标注没有用矩形框。区别很实在病变的形状是不规则的龋坏边缘是锯齿状的结石是沿着牙面铺开的一条用矩形框去套框里必然混进大量正常组织。多边形能贴着真实边界走边界精度高得多做语义分割、实例分割时这就是刚需。代价也很直接——标注成本高一个不规则区域可能要点击几十个顶点。多边形还有个隐藏好处它保留了“形状”信息。裂纹是细长的龋洞是团块状的这些形态特征在矩形框里会被抹平在多边形里则完整保留。反过来如果你要做的是目标检测多边形还得先算外接矩形降级成框形状优势就丢了。所以这份数据天生偏向分割任务而不是检测任务这一点在选择模型之前就该想清楚。4. 格式这道坎json、mask、YOLO、COCO 到底差在哪4.1 json 不是 mask同一份答案的两种写法很多人第一次打开 labelme 的 json会觉得“这不就是一坨坐标吗怎么训练”。这里要建立一个认知json 是“原始答案的记录方式”mask 是“模型能吃的答案形式”两者描述的是同一件事只是表达不同。json 用“类别名 一串顶点坐标”来描述一个区域mask 用“一张和原图同样大小的图每个像素填一个类别编号”来描述同一个区域。前者方便人看和改后者方便机器算。举个具体例子一个龋齿区域在 json 里可能是 30 个坐标点写起来像[[120, 88], [131, 92], ...]转成 mask 之后就是一张 512×512 的灰度图龋齿覆盖的像素全部填 2假设龋齿的编号是 2其余填 0。同一个区域前一种写法人能编辑后一种写法损失函数能直接算。数据集只给了 json等于把“画成 mask”这一步留给了你这一步不难但必须自己走。4.2 转成 YOLO 还是 COCO取决于你要做什么任务三个目标格式对应三类任务别混着选。转成 mask单通道类别索引图是为了语义分割——只关心“这个像素是什么类别”不区分是哪一颗牙上的病灶。转成 COCO 是为了实例分割——既要类别也要区分“这是第几个独立个体”每颗牙、每个病灶都是独立实例。转成 YOLO 是为了目标检测——只要外接矩形加类别不关心形状。这里有个容易忽略的点这份数据是 polygon转 COCO 是“平移”几乎不丢信息因为 COCO 的 segmentation 字段本身就存多边形顶点转 YOLO 是“降级”多边形要被压成外接矩形细长的裂纹压完可能变成一条又宽又扁的框框里大半是正常组织。所以如果你的任务是裂纹检测尽量别走 YOLO 这条路走 COCO 或 mask 更靠谱。格式选择不是技术偏好问题是信息保真度问题。4.3 转换时最容易翻车的几个地方先看怎么读一份 json确认你手上的数据长什么样import json # 读入单个标注文件先搞清楚里面有什么 with open(sample.json, r, encodingutf-8) as f: data json.load(f) print(data[imagePath], data[imageWidth], data[imageHeight]) # 原图名与尺寸 for shape in data[shapes]: label shape[label] # 类别名字符串大小写敏感 points shape[points] # 顶点列表像素坐标相对原图左上角 shape_type shape[shape_type] # 这份数据里基本都是 polygon print(label, shape_type, len(points))imagePath是原图文件名用来和 jpg 配对imageWidth和imageHeight是生成 mask 时的画布尺寸一定不能凭感觉写死成 512 或者 1024尺寸对不上mask 和原图就错位了points是像素坐标而不是归一化坐标转 YOLO 时要自己除以宽高shape_type要检查万一混进了矩形或者圆形多边形填充的逻辑会直接报错或者画出乱七八糟的东西。再看怎么把多边形填成 maskimport json import numpy as np from PIL import Image, ImageDraw # 类别到像素值的固定映射顺序一旦定下就不要随手改 CLASS_TO_ID {Tooth: 1, Caries: 2, Cavity: 3, Crack: 4, calculus: 5, inflamation: 6} with open(sample.json, r, encodingutf-8) as f: data json.load(f) mask Image.new(L, (data[imageWidth], data[imageHeight]), 0) # 0 表示背景 draw ImageDraw.Draw(mask) for s in data[shapes]: poly [tuple(p) for p in s[points]] if len(poly) 3: # 少于三个点围不成面直接跳过 draw.polygon(poly, fillCLASS_TO_ID[s[label]]) mask.save(sample_mask.png)这段逻辑很短但藏着三个坑。第一CLASS_TO_ID必须全数据集统一不能这张图 Tooth 是 1、那张图 Tooth 是 2否则模型学到的是噪声。第二画图顺序有讲究如果先画病变、后画 ToothTooth 的填充会把病变区域整片盖掉因为后画的覆盖先画的正确顺序是先铺 Tooth 打底再叠病变。第三fill用的是类别编号而不是类别名编号必须和你的训练配置里的类别列表完全对齐错一位整批数据的标签含义就全错位了这种错误训练时不会报错只会让你莫名其妙地训不出效果。5. 常见误区与易混概念这几个词千万别混着用5.1 牙齿分割不等于病变检测这两个词在搜索里经常一起出现但它们是两件事。牙齿分割问的是“牙在哪、边界在哪”输出的是牙体轮廓病变检测问的是“哪里有异常、是什么异常”输出的是病灶区域和类别。一份数据可以只做前者也可以只做后者而这份数据明显偏向后者——Tooth 只标了 1709 个病变标注却有 5978 个。为什么容易混因为两者都叫“分割”都用多边形都输出 mask。区分方法很简单看你的模型输出想要什么如果你要统计“这颗牙的面积占多少”那需要完整的牙体轮廓这份数据给不了如果你要输出“左上第三颗牙的咬合面有龋坏”那这份数据正合适。目标不同同一份数据的好坏评价就完全不同。5.2 标注数量不等于图片数量看到“Caries count 2913”和“图片 2616 张”很多人下意识觉得数字对不上就是标错了。其实这两个统计口径根本不同前者是多边形个数后者是文件个数。一张图里有三处龋坏就贡献三个 Caries 标注。为什么容易混因为大部分入门数据集是按“一张图一个标签”组织的分类数据集习惯了那个范式看到分割数据的统计方式就转不过弯。区分方法看总数。六类相加 7687除以 2616 得到 2.94这个数字告诉你平均每张图有将近三个标注对象。做数据增强、划分训练集时要按图片划分而不是按标注划分否则同一张图的多个多边形会被拆到训练集和验证集里造成信息泄漏验证指标虚高——这是血泪经验里最常见的一条。5.3 “有牙没标”不等于“数据脏”数据集说明里那句“部分牙齿没有标注”很多人读完心里就打鼓觉得这数据是不是不能用。恰恰相反这是一句诚实的说明而且它和标注目的是自洽的目标是查病变没病变的牙不标不影响任务。真正脏的数据是“标了但标错”而这里是“该标的标了不该标的没标”。为什么容易混因为大家默认“标注完整”等于“质量高”。但在分割任务里完整性是相对于任务定义的不是绝对的。区分方法拿几张图打开 labelme 看一眼确认病变区域确实被圈住了、边界贴合那就没问题。如果你是做全牙分割那这份数据确实不满足你的完整性要求这时候该换数据而不是抱怨数据脏。5.4 语义分割、实例分割、目标检测别乱选这三个词经常被当成同义词用实际上它们对数据的要求完全不同。语义分割只区分像素类别所有龋齿像素都是同一个颜色实例分割要区分“第几个”这颗牙的龋齿和那颗牙的龋齿是两个对象目标检测只输出外接矩形和类别不管形状。为什么容易混因为这份数据三种都能转转完都能训看起来差不多。区分方法看业务需求如果只需要输出“这张图有没有龋齿”甚至不用分割分类就够如果要输出“有几处、分别在哪”那必须实例分割如果只是粗略框出位置给医生看检测就够用。用分割数据去做检测是“高射炮打蚊子”用检测数据去做分割则根本做不了——多边形能降级成框框升不回多边形。5.5 labelme 的 json 不是“标注完就能训练”这是新手最容易踩的坑以为标注工具导出的文件就是训练输入。不是。json 是中间态它需要一步转换才能变成模型认识的张量。这一步在数据集说明里写得很清楚——“需自己转成 mask 或者 yolo 格式或者 coco 格式”。为什么容易混因为标注工具用起来太顺了画完点保存看着一堆文件生成会误以为流程结束了。区分方法看你的训练脚本第一个数据加载函数在读什么。如果它读的是 png 或者 txt那 json 就是原料不是成品如果它直接读 json那说明你自己写了转换逻辑在里面。搞清楚这一步在哪儿发生比搞清楚模型结构重要得多因为格式错了模型再好也训不出东西。6. 什么时候用它、什么时候别碰一份判断清单先给结论这份数据适合“验证一个牙齿病变检测的想法能不能跑通”不适合“直接交付一个高精度临床模型”。它更像一块试验田而不是成品粮仓。判断自己该不该用它看下面这张表比看任何介绍都直接你的情况适不适合用原因想跑通分割流程、验证想法适合2616 张、6 类、标注规范够用想做龋齿/结石的类别不平衡实验适合Crack 仅 139 个天然的不平衡样本想做全牙实例分割不适合Tooth 只标了 1709 个非全量想要开箱即用的 mask 文件不适合只给 json需自行转换想要现成的高精度权重不适合发布方明确不对精度作任何保证想研究裂纹这种细长目标谨慎样本极少转 YOLO 还会丢形状具体到操作层面我自己的习惯是这样拿到手先不急着写训练脚本先抽 20 张图用 labelme 打开确认病变区域的边界贴合、类别名没写错、json 和 jpg 配对没断。然后写一个统计脚本把六类的标注数、每张图的标注数分布、图片尺寸分布全部打出来看清楚长尾有多长。接着固定一份类别映射表把它写进配置文件所有转换脚本都从这份配置读绝不在代码里手写数字。最后按图片划训练集和验证集划完再检查一遍有没有同一张图的多个多边形被拆散。这套流程听起来啰嗦但我吃过亏。早些年接手一个模拟项目图省事直接在脚本里写死了类别编号后来加了一类新数据用的是新编号旧数据还是旧编号训练 loss 一路震荡查了两天才发现是标签错位。从那以后我每次处理多类别分割数据都强制走一遍“固定映射表 抽样可视化 统计校验”三步宁可慢半天也不愿意再经历一次那种查不出原因的玄学调参。反过来说也别把它想得太难。json 转 mask 的核心就是把顶点坐标填进一张同尺寸的图逻辑不超过二十行转 COCO 更是几乎平移因为 COCO 本身就支持多边形。真正的门槛不在代码在于你有没有先想清楚“我要解决的是分割还是检测、是语义还是实例”想清楚了格式只是最后一步的体力活。这份数据最大的诚意是把 2616 张图、7687 个多边形、6 个类别老老实实标完并说明白了缺口在哪——缺口不可怕可怕的是不知道缺口在哪。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑