
简介这份数据集名为CardiacUS-Septum专注心脏超声室间隔分割包含3,092张已脱敏的高质量超声切面图像及LabelMe JSON标注面向算法工程师和医学影像研究人员可直接用于训练与评估分割模型。资源包共2000个文件其中1999个JSON标注文件逐张对应图像另有1个文本说明压缩后约48.73MB结构清晰便于检索。目前已有142人学习下载。数据来自多中心采集仅标注室间隔单一类别标签名IVS兼容主流分割工具省去手动标注环节既可用于监督学习也能在预处理后接入U-Net、Transformer等网络进行精度对比与消融实验为超声辅助诊断研究提供标准化数据基础兼顾入门实操与科研扩展是开展医学图像分割、超声影像分析及AI辅助诊断相关课题的实用基础数据。 搞医学影像分割的朋友应该都体会过那种“公开数据集一大把但真正贴合自己任务的没几个”的窘境。尤其是心脏超声本来图像质量就差噪声多、边界模糊想找一个现成的、标注规范的室间隔分割数据集更是难上加难。所以当我拿到“CardiacUS-Septum”这套标注为LabelMe格式的心脏超声室间隔分割数据集时第一反应是这玩意儿太实用了。它解决的核心问题很简单——给做超声图像分割、心血管功能评估、以及深度学习模型训练的人提供一份可以直接落地的、带逐像素标注的室间隔数据。这篇文章我想从一个实际使用的角度把这套数据集的格式细节、处理流程、训练要点和踩坑经验完整梳理一遍。不管你是刚入门图像分割的新手还是已经在用UNet、nnUNet跑医学影像的老手只要你打算用这份数据训练模型或者想参考它的标注方式来构建自己的数据集这篇文章都能给你省下不少摸索的时间。1. 一个“小而专”的数据集为什么要单独做室间隔分割1.1 室间隔分割的临床价值与难点室间隔Interventricular Septum是左右心室之间的那层心肌壁它的厚度、运动幅度是评估心脏功能的重要指标。临床上医生通过超声测量室间隔厚度来判断左心室肥厚、高血压心脏病、肥厚型心肌病等病变。但问题是超声图像本身存在大量斑点噪声、声影衰减室间隔边界在心内膜和心外膜处往往并不清晰自动分割的难度比CT、MRI高一个量级。这也是为什么很多通用分割模型在自然图像上表现很好一到超声数据上就“翻车”。如果有一套高质量标注数据训练出来的模型就能辅助医生自动测量室间隔厚度、追踪室壁运动甚至进一步计算射血分数等心功能参数。CardiacUS-Septum这套数据集的定位就在这它不是一个大而全的多器官数据集而是专注“室间隔”这一个目标把一件事做细做透。这种小而专的数据集在实际科研和临床落地中往往比那些标注粗糙的大数据集更有价值。1.2 LabelMe格式为什么是“默认选项”LabelMe是MIT开源的一个图像标注工具它输出的JSON格式非常直观每个文件对应一张图片标注信息存储在shapes数组里每个形状可以是多边形、矩形、圆等。它不像COCO那样需要理解复杂的category_id映射也不像VOC那样需要生成多个XML和PNG文件一个JSON就搞定了所有标注。对于医学影像这种“一图一标注”的场景LabelMe格式的轻量和灵活确实是很大的优势。不过轻量也意味着你需要自己处理后续的格式转换。深度学习框架尤其是nnUNet、UNet这类分割框架通常不直接吃LabelMe的JSON而是需要你把它转成PNG mask或者NIfTI格式。所以拿到这份数据集后第一件事不是直接丢进模型训练而是先把JSON搞清楚。2. 先把标注格式吃透LabelMe JSON到底长什么样2.1 JSON结构与坐标体系我拿到这份数据后随手打开一个标注文件看了一下结构非常典型。简单来说核心信息就几块version标注工具版本号这个不影响后续处理。imagePath对应的原始图像文件名。imageDataBase64编码的原始图像数据有的数据集为了省空间会把它置为空字符串CardiacUS-Septum大概率也是依赖外置图片不内嵌图像数据。shapes核心数组每个元素包含label类别名、points多边形顶点坐标列表、shape_type一般是polygon、group_id等。这里最关键的就是points。LabelMe标出来的坐标是像素坐标坐标系原点在图像左上角x轴向右、y轴向下。这个坐标系和绝大多数图像处理库是一致的所以转mask时不需要做坐标翻转直接用就行。但要注意如果标注时图片被缩放或者裁剪过坐标是对应缩放后图像的必须和原图尺寸对齐。{ version: 5.2.1, flag: {}, shapes: [ { label: septum, points: [[122, 156], [135, 162], [158, 179], [172, 201]], group_id: null, shape_type: polygon, flags: {} } ], imagePath: patient001_frame025.png, imageData: null }你可以把LabelMe的多边形理解成“用一串点围出来的封闭区域”。点越密边界拟合得越精细但标注工作量也越大。对于室间隔这种细长型结构标注时通常会沿心内膜和心外膜边界各打一串点形成一个闭合的环状区域中间围出来的就是室间隔壁。2.2 从JSON到mask的转换流程实际训练时我们需要的是和原图同尺寸的单通道mask背景像素为0目标区域像素为255或者类别序号。从JSON转mask的核心就是调用shapely或cv2.fillPoly把多边形“填充”成掩码。用cv2.fillPoly是最直接的方式效率高、代码少。思路就是遍历shapes数组拿到每个多边形的顶点然后在全零的mask上填充。如果一份数据里同时标注了室间隔和左心室腔等多个结构就需要给不同label分配不同的像素值避免类别重叠。import json import numpy as np import cv2 from PIL import Image def labelme_json_to_mask(json_path, img_shape): with open(json_path, r, encodingutf-8) as f: data json.load(f) mask np.zeros((img_shape[0], img_shape[1]), dtypenp.uint8) for shape in data[shapes]: label shape[label] points np.array(shape[points], dtypenp.int32) # 假设室间隔的label名是 septum if label septum: cv2.fillPoly(mask, [points], color255) # 如果有其他结构可以继续用不同像素值比如 128, 64... return mask mask labelme_json_to_mask(annotations/patient001_frame025.json, (600, 800)) cv2.imwrite(masks/patient001_frame025.png, mask)这里有一个容易忽略的细节cv2.fillPoly要求顶点坐标是整数而且坐标不能超出图像边界。如果标注时手滑把点打到图外了填充时会报错。稳妥的做法是在转换前做一次坐标裁剪把超出边界的点强制拉回图像范围内。3. 数据集落地的第一关加载、校验和预处理3.1 读取与可视化标注拿到数据集后我建议的流程是先把图像和对应的JSON配对做一个“标注预览”逐张检查有没有标错、漏标、边界明显不合理的情况。用matplotlib叠加显示原图和标注轮廓是最直观的。你可以把每个多边形的点用plt.plot连起来画在原图上这样能快速发现“这个室间隔边界怎么飘到心腔里去了”这类问题。数据集发布方一般做过一轮质检但数据到了自己手里最好还是再过一遍毕竟训练数据质量直接决定模型上限。import matplotlib.pyplot as plt import json from PIL import Image img Image.open(images/patient001_frame025.png) with open(annotations/patient001_frame025.json) as f: data json.load(f) plt.imshow(img, cmapgray) for shape in data[shapes]: pts shape[points] xs [p[0] for p in pts] [pts[0][0]] ys [p[1] for p in pts] [pts[0][1]] plt.plot(xs, ys, linewidth2) plt.axis(off) plt.show()这个可视化步骤不是走形式。我见过有人在数据集上直接跑训练跑了三个epoch后loss不降排查半天才发现是label名称不一致导致mask全黑。所以训练前花几分钟做可视化校验能省下后续调参的好几个小时。3.2 多类别与灰度图的处理细节心脏超声图像通常是单通道灰度图但有些设备保存出来的可能是三通道的伪彩图或RGB图。训练模型前要统一图像格式。CardiacUS-Septum这类数据集图像一般以灰度PNG居多但保险起见加载时还是做一次灰度化处理避免某些框架在读图时把单通道当成三通道处理。如果数据集里除了室间隔还标了其他结构比如左心室内膜、右心室壁那mask就不是二值的了而是多类别标签。这种情况下需要维护一个类别到像素值的映射表比如背景0、septum1、LV腔2。这种映射在训练时要保证每次读取都一致不能今天用1表示室间隔明天用2不然模型会学得一头雾水。3.3 关键校验点命名、尺寸、标注完整性数据量不大时校验可以用脚本自动化。我总结了几个必检项图像与JSON是否一一对应有没有只图不标、只标不图的情况。所有图像的尺寸是否一致如果不一致是resize到统一大小还是做padding。每个JSON里的shapes是否为空空标注的文件训练时要么剔除要么当成全背景样本。多边形顶点是否都在图像尺寸范围内。类别名称是否统一比如不要出现Septum和septum并存的情况。这些检查写成一个Python脚本跑一遍就可以没必要手工翻。数据质量过关后再进入模型训练环节心里才踏实。4. 拿它训练分割模型时我建议这样安排4.1 数据划分与增强方案室间隔分割属于典型的小目标细长结构分割数据量往往不大。我按经验建议按7:2:1或者8:1:1划分训练集、验证集和测试集。划分时要注意同一个病人的不同帧尽量分到同一组避免数据泄漏带来虚高的评估指标。数据增强方面超声图像适合用的增强包括随机旋转角度控制在±15°以内别转太狠、水平翻转、随机亮度和对比度调整、高斯噪声添加。对这些增强都要谨慎的是弹性形变和随机裁剪。弹性形变适合分割任务是没错但如果形变幅度太大会把室间隔这种长条状结构扭曲得不合解剖常理随机裁剪则要保证裁剪框覆盖到室间隔区域否则训练时大量样本里根本没有目标模型容易偏向预测背景。import albumentations as A train_transform A.Compose([ A.RandomRotate90(p0.5), A.HorizontalFlip(p0.5), A.RandomBrightnessContrast(brightness_limit0.1, contrast_limit0.1, p0.5), A.GaussNoise(var_limit(10.0, 30.0), p0.3), ])4.2 损失函数与评估指标选择分割任务最常用的损失是Dice Loss和交叉熵损失的组合。对于室间隔这种前景占比很小的结构单独用交叉熵容易让模型倾向于预测背景Dice Loss能把前景和背景的不平衡问题缓解不少。我一般用Dice Loss BCE的加权组合权重可以设成0.5和0.5也可以根据验证集表现去调。评估指标除了Dice系数建议同时看IoU、Precision、Recall。Dice和IoU相关性高但Dice对小的预测偏移更敏感。室间隔厚度只有那么几毫米几个像素的边界误差对Dice的影响都不小所以不要只看一个指标下结论。如果做的是临床测量任务还可以补充“室间隔厚度预测误差”这种和临床更相关的指标毕竟医生关心的是测出来的厚度准不准而不仅仅是重叠率。4.3 从UNet到nnUNet模型怎么选如果是第一次用这份数据跑模型我建议先用UNet打底。UNet在医学图像分割里依然是效果稳定的基线特别是数据量不大的情况下复杂模型容易过拟合。把UNet跑通、指标记下来再考虑上nnUNet。说到nnUNet它最大的特点是自动化了预处理、训练策略和推理流程你只需要把数据按指定目录结构放好它会自己算归一化、resample和最优网络结构。但nnUNet默认面向NIfTI格式的3D数据而CardiacUS-Septum是2D超声图像。使用时要把它当成2D数据集处理把每张超声图像当成一个单独的样本或按“2D_plan”模式配置。想省事也可以用nnUNetv2自带的2D配置只是需要把数据转成PNG序列或NIfTI格式这又回到最开始的格式转换步骤了。5. 常见问题与排查技巧实录训练过程中遇到的问题有时候比模型本身更能让人长经验。我把用这类LabelMe格式超声分割数据集时最容易遇到的坑列一个速查表问题现象可能原因解决方案训练时loss不下降mask全黑JSON没读到shapes或label不对可视化检查mask是否覆盖目标区域推理结果全是背景图像和mask尺寸不一致resize时坐标没同步缩放统一在数据加载函数里做resize不要改原始标注模型把无关区域也分割出来某个JSON里标了其他结构类别混淆仔细检查所有shapes的label名称报“Coordinate out of bounds”标注点超出图像边界转换mask前做坐标裁剪验证Dice很高但临床效果差评价指标只看Dice忽略了边界精度增加边界距离指标如HD95或厚度误差还有一个容易被忽略的问题是图像方向的统一。超声图像的心尖朝向在不同case里可能不同有的设备成像后左右是翻转的。如果训练集和测试集方向分布不一致模型学到的“位置先验”就是错的测试时性能会明显下降。建议在预处理阶段检查所有图像的解剖方向必要时做水平翻转统一。数据增强里还有一个坑不要对mask做插值类的resize操作时用默认的线性插值。mask是离散标签resize时要用最近邻插值否则会引入很多灰度中间值导致标签不干净。用cv2.resize(mask, (H, W), interpolationcv2.INTER_NEAREST)就对了。6. 这份数据集的更多可能扩展与迁移6.1 转成开源框架所需的格式如果你想用MMDetection、MMSegmentation或者YOLOv8来跑需要把LabelMe格式转成对应框架要求的格式。以YOLOv8为例它做分割任务用的是自己的TXT格式每行一个类别id加一组归一化坐标。转换逻辑并不复杂读JSON取出多边形点坐标按图像宽高归一化写到TXT文件里。目录结构按images/train、images/val、labels/train、labels/val组织就行。# 伪代码示意LabelMe多边形 - YOLO分割txt x_norm x / img_width y_norm y / img_height line f0 .join(f{x_norm:.6f} {y_norm:.6f} for x_norm, y_norm in zip(xs_norm, ys_norm))MMSegmentation则支持自定义Dataset类你可以写一个继承BaseDataset的数据类直接在__getitem__里读JSON和原图在线生成mask。这样做的好处是不需要离线存一份PNG mask节省磁盘空间坏处是每次训练都要解析JSON会拖慢数据加载速度。数据量大时我还是建议离线把mask全部生成好训练时直接从PNG读。6.2 预训练、半监督与多任务扩展的方向这份数据集的规模如果不算大通常很难从头训练一个大模型。比较务实的路线是用ImageNet预训练权重做初始化或者用自监督预训练比如MAE先在大量无标注超声图像上预训练再用这份数据做微调。超声图像和自然图像差异大但ImageNet权重在浅层特征上依然有不错的迁移效果实测下来收敛速度会比从头训练快不少。更进阶一点的玩法是借助这份数据做半监督。把训练好的模型拿去对无标注的超声图像做伪标注筛选高置信度的样本加入训练集迭代几轮往往能明显提升泛化能力。这个方法在医学影像上尤其吃香因为标注成本高但未标注的超声影像在临床上随处可见。配合LabelMe格式的灵活性伪标注结果可以直接存成同一个格式形成“标注—训练—再标注”的闭环。我个人的体会是像CardiacUS-Septum这种细小结构数据集真正的难点从来不是模型的网络结构有多花哨而是数据处理的每个环节是否足够细致。把格式转换、坐标对齐、标签校验这些脏活累活做扎实好模型水到渠成。最后再分享一个我自己的小习惯每次转换完格式我会随机抽10张图把原图和叠加了真值轮廓的图打印出来贴到墙上对比看一遍。这个习惯帮我在很多项目里提前发现了标注错位、标签名不统一之类的问题。数据干净了训练结果自然不会差。本文还有配套的精品资源点击获取