1. 数据集选型逻辑:三个腹腔镜公开数据集各自的定位
手术视频分析这几年在医学影像AI里算是非常活跃的方向了,但真正能拉到台面上用的公开数据集并不多。做腹腔镜胆囊切除术相关的算法研究,绕不开的就是Cholec80、CholecSeg8k2020、Endoscapes2024这三个名字。它们在任务覆盖上刚好形成互补关系:一个管阶段识别,一个管语义分割,一个管更细粒度的器械与场景理解。如果刚接触这个方向,或者正在搭建自己的手术视频分析流程,把这三个数据集的定位和区别搞清楚,能省下大量试错成本。
1.1 Cholec80:手术阶段识别的事实标准
Cholec80是目前引用量最高的腹腔镜手术视频数据集之一,来自80台胆囊切除术的完整视频记录,分辨率为1920x1080,帧率25fps,总时长大概7小时左右。它的核心标注是手术阶段(Phase)和手术工具存在性(Tool Presence)。Stage标注共7类:Preparation of Calot's triangle、Calot's triangle dissection、Clipping and cutting、Gallbladder dissection、Gallbladder packaging、Cleaning and coagulation、Gallbladder retraction。工具标注共7类:Grasper、Bipolar、Hook、Scissors、Clipper、Irrigator、Specimen bag。
我见过很多初学者拿到Cholec80后,第一反应是把它当图像分类任务去跑。这个理解其实不太对。Cholec80真正有价值的点在于它提供了完整的时序上下文——每一帧都有phase_id和时间戳。这意味着你不仅能做单帧的阶段识别,还能做基于视频时序的模型,比如常见的LSTM、Transformer、时序卷积。做手术阶段识别的论文,如果方法不是在Cholec80上报的结果,审稿人大概率会质疑工作的可比性,这个数据集的江湖地位就是这么稳。
使用Cholec80时有一个隐藏细节需要特别注意:原始标注是按帧给出的,视频长度不一,帧数差异很大。很多早期论文在评测时并没有统一帧率采样策略,导致不同方法之间的数值对比存在明显偏差。如果你要做公平对比,建议固定采样策略,比如统一每1秒抽1帧,或者统一用官方提供的帧索引,而不是直接用不同倍速抽帧后去对比精度。
1.2 CholecSeg8k2020:像素级分割和器械精准定位的关键资源
CholecSeg8k2020是从Cholec80基础上延伸出来的语义分割数据集。它选取了80个视频中的一部分关键帧,总共标注约8000帧左右,每一帧都做了像素级的语义标签。这个数据集的设计初衷很明确:阶段识别只能说明“手术进行到哪一步了”,但临床和算法层面更关心的是“手术器械的轮廓和器官边界在哪”。如果要做辅助手术系统,单纯判断位置标签远远不够,必须输出像素级别的分割图。
CholecSeg8k2020的标注类别一共13类,包括背景、腹壁、肝脏、胃肠组织、脂肪、各类手术器械等。这个类别设计在实际训练时是比较让人头疼的,因为组织类别的像素分布极其不均衡。常见的不只是背景占比过高,更麻烦的是肝脏和脂肪这类区域颜色纹理很接近,靠颜色分割几乎必翻车。很多公开实现中,直接套用通用分割模型的效果并不理想,原因就在这里。
CholecSeg8k2020和Cholec80的关联很紧密,但两者不能混用。CholecSeg8k2020的标注帧是从Cholec80里的部分视频中抽取的,所以如果你想做“阶段识别+分割”的多任务联合训练,理论上是可以把数据集组合起来玩的。但要特别注意帧对齐问题,因为两个数据集的标注文件格式和帧索引并不完全一致,拼接前一定要做逐帧校验,否则喂给模型的就是错误监督信号,训练出来的模型指标再好看也是空中楼阁。
1.3 Endoscapes2024:偏向前沿场景理解的新基准
Endoscapes2024是近几年开始流行的一个较新的腹腔镜数据集,研究方向偏向前沿的细粒度场景理解。与Cholec80偏阶段分类、CholecSeg8k2020偏分割不同,Endoscapes2024在工具检测、语义分割、阶段识别这三个维度上都有覆盖,标注的精细度比前两个更高,尤其是对工具的刃口、钳嘴、组织接触区域做了更细的划分。
这个数据集的诞生背景其实很直接——手术AI不能只停留在“知道现在是什么阶段”的层面。真实手术场景里,医生需要的是器械位置提示、器械与组织的交互状态提示,甚至是操作风险预警。而实现这些,传统只标一个框或者只给一个全局标签的数据集远远不够。Endoscapes2024的价值就在于提供了一个更贴近真实临床理解需求的基准。
不过这个数据集也有自己的门槛。一是申请审核比Cholec80严格,数据使用协议条款比较多;二是类别体系与Cholec80/CholecSeg8k2020并不完全一致,做跨数据集迁移时需要考虑类别映射问题。如果你同时使用多个数据集训练统一模型,建议先花点时间把类别体系梳理清楚,比如把不同数据集中的“钳子”“电钩”“吸引器”归一到统一标签体系,否则数据之间互相打架,模型性能反而会下降。
1.4 三个数据集横向对比速查表
| 对比维度 | Cholec80 | CholecSeg8k2020 | Endoscapes2024 |
|---|---|---|---|
| 视频来源 | 80台胆囊切除手术,完整视频 | 从Cholec80中抽帧的子集 | 较新采集的腹腔镜手术视频 |
| 主要标注类型 | 阶段标签、工具存在标签 | 逐像素语义分割标签 | 工具检测、语义分割、阶段标签 |
| 标注类别数 | 阶段7类、工具7类 | 语义类别13类 | 比前两者更细粒度 |
| 主要用途 | 手术阶段识别、工具使用识别 | 器械与组织图像分割 | 多任务场景理解、基础模型预训练 |
| 难度特点 | 时序建模是关键,单帧识别简单 | 像素不均衡严重,边界分割是难点 | 标注更细,跨域迁移需要额外适配 |
看完这张表应该能明白,这三个数据集不是重复造轮子,而是同一个大方向下的不同层次。Cholec80解决的是“视频级时序理解”,CholecSeg8k2020解决的是“图像级精确分割”,Endoscapes2024则在往“综合场景理解”方向走。如果预算和精力有限,我建议先从一个数据集入手吃透,再逐步扩展到另外两个,不要一开始就全量上多任务训练。
2. 数据获取与工程化处理:别在原始文件上栽跟头
数据集搞定后,很多人会卡在数据预处理这一关。腹腔镜视频数据与普通图像数据集最大的不同是:它既不是以“一堆图片+一个label.txt”的简单形式存在,又没有统一的标准目录结构。不同数据集之间的标注文件、视频编码、帧率标记都存在差异。这里把处理流程拆开讲清楚,能帮你少走不少弯路。
2.1 申请、下载与使用协议注意事项
Cholec80和CholecSeg8k2020的申请流程基本一致,通常是通过数据集发布方提供的在线表单提交申请,写明单位、邮箱和用途。审核周期从几天到几周不等,官方审核通过后才会提供下载链接。Endoscapes2024的申请流程类似,但审核更严格,有些机构还要求签署额外的数据使用协议。
这里有一个很多人不注意的细节:很多数据集只允许非商业用途,也就是说你在公司商业项目里使用这些数据集做内部测试是可以讨论的,但发布商业产品或接入商业系统就会涉及授权问题。如果后续有产品化打算,最好先把数据使用条款看清楚,咨询法务,避免后期被告知不能商用。
下载完成后的第一件事不是直接开始训练,而是验证文件完整性。腹腔镜视频普遍较大,传输过程中很容易出现文件缺失或损坏。我遇到过不止一次——训练到一半损失值突然变成NAN,检查很久才发现是某个视频文件解压后只有开头几秒可用。建议下载后立即记录文件大小、帧数和md5值,与官方提供的清单逐一比对。
2.2 视频解码:从原始视频到模型可读的帧序列
Cholec80的原始文件是视频格式,训练时通常需要先抽帧。很多人直接写个for循环用OpenCV逐帧读取,这种方式可以跑,但效率偏低。如果项目周期紧张,推荐用ffmpeg做批量抽帧,命令大概是这样的:
ffmpeg -i VIDEO01.mp4 -vf fps=25 -qmin 1 -q:v 2 frame_%04d.png上面这个命令的意思是把输入视频按25fps抽帧,输出为PNG格式。-qmin 1 -q:v 2这两个参数是控制压缩质量的,如果抽出来的帧要用于分割任务,建议尽量无损或高质量,否则标注边界细节会因为压缩而损失。注意这里写的是frame_%04d.png,实际项目中最好把文件名设计成video01_frame_0001.png这种带视频编号的格式,方便后续把阶段标签和帧序列对齐。
抽帧时最容易出的问题是音画不同步导致的抽帧错位。视觉类任务对音频无感,但如果原视频有音轨且抽帧时没有做音视频同步控制,偶尔会碰到抽出来的帧序号和标注文件对应不上。稳妥做法是抽帧时禁用音频流:加一个-an参数:
ffmpeg -i VIDEO01.mp4 -an -vf fps=25 -qmin 1 -q:v 2 frame_%04d.png这样能杜绝音频流带来的读取问题。
对于Cholec80,官方标注是按视频时间戳给出的,具体是VIDEO01.json这类文件中包含time_stamp和phase_id两个键。解析时要注意:时间戳是秒级别,而抽帧是按帧速率生成的。如果你按25fps抽帧,时间戳t对应的帧索引就是t乘以fps再向下取整。这个换算关系很容易搞反,推荐写一个公共工具函数统一处理,不要在每个实验脚本里重复实现。
import json def load_cholec80_annotation(json_path, fps=25): with open(json_path, 'r') as f: ann = json.load(f) frame_phase = {} for item in ann: phase_id = item['phase_id'] start_frame = int(item['time_stamp'] * fps) end_frame = int(item.get('next_timestamp', item['time_stamp']) * fps) # 这里简化了,实际需要根据时间戳区间设置标签 for f_idx in range(start_frame, end_frame): frame_phase[f_idx] = phase_id return frame_phase上面只是示意代码,实际使用时要根据官方标注文件的结构做调整。Cholec80的标注文件格式在不同版本可能略有变化,加载后先打印两行看看结构,不要直接跑管道。
2.3 CholecSeg8k2020和Endoscapes2024的掩码文件处理
CholecSeg8k2020的分割标注通常以彩色PNG掩码或灰度索引图形式给出。彩色PNG看起来直观,但训练时不能直接用RGB当作类别标签,需要做一次颜色到类别的映射。常见做法是维护一个调色板字典:
# color_to_class 需要根据数据集提供的 color map 建立 color_map = { (0, 0, 0): 0, # background (255, 0, 0): 1, # 示例:某个工具类别 # ... 根据数据集文档补全 } def rgb_mask_to_label(mask): h, w, _ = mask.shape label = np.zeros((h, w), dtype=np.int64) for color, cls_id in color_map.items(): label[np.all(mask == color, axis=-1)] = cls_id return label这个处理看似简单,实际坑很多。比如图像压缩导致的边缘伪影,会让某个像素值既不是纯背景色也不是纯目标色,映射后出现大量噪声标签。解决方法是参考数据集的原始标注格式,如果官方提供的是灰度索引图,那就直接用,不要再去做不必要的RGB转换。
Endoscapes2024的标注文件格式更复杂一些,涉及实例级别的分割标记,也就是同一类别的多个不同实例要分别标记。如果只做语义分割,可以把实例掩码合并成类别掩码;但如果是做实例分割或者追踪,就得保留实例编号。这一点在写数据加载器时就要决定好,否则后期改标签格式会非常痛苦。
3. 基于这三个数据集的主流任务与模型实现路线
数据集处理干净了,接下来就是模型训练。这里按三个任务的典型路线展开:手术阶段识别、手术场景语义分割、工具检测与多任务场景理解。每个任务我都会给出数据组织方式、模型选择逻辑和训练技巧。
3.1 手术阶段识别:从单帧CNN到时序模型
手术阶段识别是Cholec80上最经典的任务。最简单的方法是逐帧用CNN预测阶段标签,再把所有帧的预测结果做时间平滑。常见做法是先用ImageNet预训练的ResNet50提取帧特征,再接一个时序模型。下面是一个典型的pipeline:
第一步,逐帧提取特征。把每一帧缩放到224x224或256x256,过ResNet50的pool5层,得到2048维特征向量。把所有帧的特征保存成npy文件,后续训练时序模型时就无需重复跑CNN,能节省大量时间。
第二步,时序建模。经典做法是把连续帧的特征序列输入LSTM或GRU,也有用Transformer的。关键超参数是序列长度。我试过,序列长度32和64在Cholec80上差异不大,但计算量差一倍,建议从32开始。
第三步,训练时要注意类别及其出现的顺序。Cholec80的7个阶段不是均匀分布的,比如“Clipping and cutting”阶段持续时间明显短于“Gallbladder dissection”,如果直接用交叉熵损失,模型会倾向预测那些时长占比大的阶段。解决办法是做类别加权,或者使用Focal Loss来缓解类别不平衡。
下面是一段简单的PyTorch时序模型伪代码,供参考:
class PhaseClassifier(nn.Module): def __init__(self, input_dim=2048, hidden_dim=512, num_classes=7): super().__init__() self.lstm = nn.LSTM(input_dim, hidden_dim, batch_first=True, num_layers=2) self.fc = nn.Linear(hidden_dim, num_classes) def forward(self, x): # x: (batch, seq_len, 2048) out, _ = self.lstm(x) # 取最后一个时间步输出,也可以用池化 out = out[:, -1, :] return self.fc(out)阶段识别任务的评估指标通常有准确率(Accuracy)、精确率/召回率/F1、以及视频级别的一致性。官方评测一般看帧级别准确率,但很多应用场景更关注“过渡点检测”的准确度,也就是阶段切换的时间点预测准不准。如果你的应用场景是术中提示,建议把阶段切换的误差距离也纳入评价,这项指标通常能让模型能力高下立判。
3.2 手术场景语义分割:处理好类别不均衡是关键
CholecSeg8k2020的语义分割任务是经典的分割任务,但比自然图像的Cityscapes、ADE20K难度更大。难点在于:组织器官颜色高度相似、器械边缘细长、类别像素占比极不均衡。直接套U-Net效果并不好,关键原因不是模型能力,而是数据组织方式。
训练前,一定要分析类别的像素占比分布。CholecSeg8k2020的标注里,背景像素往往占绝对多数,而像“剪刀”“吸引器”这类细长器械类别占比可能不足1%。如果直接用Softmax交叉熵,模型几乎不会输出这些稀有类别。解决方案有两个方向:一是使用加权交叉熵,根据像素占比的反比设置权重;二是用Dice Loss或Tversky Loss,这类损失函数天然适合类别不平衡场景。
实际经验来看,两者组合使用效果更好。加权交叉熵能保证训练稳定,Dice Loss能拉高子类别的IoU。训练时可以先单独用加权交叉熵跑几个epoch,再用联合损失微调,比一开始就用联合损失收敛更快。
模型选择上,如果追求速度推荐使用轻量化的实时分割网络,因为腹腔镜视频模型最终要跑在手术室里,延迟要求非常高。但如果只是做学术实验,用DeepLabV3+或者U-Net++这类标准结构就够了。
另一个容易忽略的细节是输入分辨率。CholecSeg8k2020原始标注帧是1280x1024或者1920x1080左右,如果为了省显存直接缩放到512x512,小器械的像素几乎就没了。建议至少用768x768,显存不够就减少batch size,不要过度压缩分辨率。
3.3 工具检测与多任务场景理解
Endoscapes2024支持的工具检测任务,可以按目标检测的方式处理,也可以用“多标签分类+分割”的联合任务方式。如果想走检测路线,常见选择是Faster R-CNN或YOLO系列。相比分割任务,检测任务在腹腔镜场景下最大的挑战是:器械密集、互相遮挡、且器械运动速度快导致运动模糊。
我用Endoscapes2024做检测时的体会是,数据增强的影响远大于模型结构选择的影响。简单使用随机翻转和颜色抖动完全不够,建议加入随机裁剪、随机缩放以及针对视频帧的运动模糊模拟。这类增强能显著提升模型对器械快速运动场景的鲁棒性。
多任务场景理解则更复杂,需要同时输出阶段标签、工具检测框和分割掩码。现阶段主流做法是设计一个共享编码器的多分支网络,编码器提取通用特征,三个分支分别处理不同任务。这种方式的好处是节省计算量,坏处是任务之间如果不平衡,优化过程会比较难收敛。建议给每个任务设置动态权重,根据验证集表现实时调整。
4. 训练环境搭建与评测体系:站在前人的肩膀上起跑
数据集和模型路线都明确了,但训练效果好不好,还取决于环境配置和评测方式。这里把常见环境问题和评测指标理一下,尽量让首次接触的人能少踩坑。
4.1 硬件与软件环境的基本配置
腹腔镜视频模型训练对显存的需求不算特别夸张。一个ResNet50特征提取+时序模型,在GTX 3090或RTX 4090上完全可以跑起来。分割任务的显存压力更大,建议至少24GB显存,并且配合混合精度训练(AMP)使用。如果只有单卡16GB显存,可以考虑把输入分辨率降到512,或者使用梯度累积来模拟更大batch size。
软件环境方面,PyTorch依然是主流选择。有一个环境坑值得提醒:不同版本的CUDA和cuDNN对视频解码相关库的影响很大。如果你用PyTorch Video或OpenCV做帧读取,在某些CUDA版本下会报莫名其妙的解码错误,建议先固定一个经过验证的镜像或conda环境,不要频繁升级。
数据加载建议把所有帧文件放到SSD上,并使用num_workers>0做多进程加载。如果磁盘IO跟不上,训练速度会被严重拖慢。另一种做法是预先将所有帧打包成LMDB格式或TFRecord,但工程量较大,数据规模不大的情况下没必要。
4.2 评估指标详解:准确率之外还要看什么
对于阶段识别任务,最常用的指标是准确率,但这个指标在大类别极度不均衡的情况下的参考价值有限。比如某个阶段占整个手术时长的40%,无脑预测该阶段的准确率就有40%。这时候需要看类别平均F1或者Cohen's Kappa系数,它们能更好地反映模型是否真正学会了识别不同阶段。
语义分割任务的评价标准是IoU(Intersection over Union)和mIoU。对每个类别单独看IoU非常关键,因为mIoU高可能只是背景类别占了大头。在CholecSeg8k2020上,至少要单独报告每个器械类别的IoU,特别是那些小目标器械的IoU。
工具检测任务要看mAP(mean Average Precision),和自然图像检测一样。但这里有一个额外维度:时间一致性。一个质量很好的检测器如果频繁在相邻帧之间跳变,在手术辅助场景中也无法使用。所以建议额外计算检测结果在时序上的一致性指标,比如相邻帧检测框的交并比平均值。
4.3 常用的预训练模型与公开代码库
现在做这些任务已经不需要从头训练了。阶段识别方面,很多公开的TeCNO、Trans-SVNet、SURGIC等模型实现可以直接在Cholec80上复现,建议先跑通一个复现版,再在此基础上做改进。分割方面,常见的是用ImageNet预训练的编码器初始化,或者使用在医学图像上预训练过的骨干网络。把公开代码仓库的逻辑读一遍,比自己从零搭更容易快速进入状态。
但复现代码时一定要擦亮眼睛:不同实现在数据划分、采样率、预处理上可能略有不同,直接叉开跑会得到不一致的结果。做对比实验时,尽量保持数据处理完全一致,只改变要验证的变量,否则你报告出来的差异可能根本不是你想表达的原因。
5. 常见问题与排查技巧实录
在实际跑这三个数据集的过程中,我遇到过不少奇怪的问题。挑几个高频的写下来,希望能帮大家省点调试时间。
视频和标注对不齐的问题,是最容易被忽视但又最致命的坑。我有一次训练阶段识别模型,验证指标一直上不去,后来逐帧检查才发现,标注数据里的时间戳基准和抽帧起始位置差了大概几秒钟。常见原因是原视频开头有片头或静帧,解码器自动跳过了某些帧。排查方法是把标注阶段变化的时间点和视频实际内容做一次可视化对照,抽取几个关键时间点的画面看看是否真的处于对应阶段。
类别标签错位是另一个高发问题。Cholec80的工具标签是7类,CholecSeg8k2020的分割类别是13类,Endoscapes2024又有更细的类别体系。当你想同时使用两个数据集做联合训练时,类别映射写错几乎不可避免。建议先建一个跨数据集的类别映射表,把语义相同但编号不同的类别统一,并在训练前做一次可视化确认。
分割模型的输出边界粗、有小碎块也是常见现象。这种情况常见原因有两个:一是标签本身就存在噪声,比如标注时把电钩的尖端颜色和脂肪组织混在一起了;二是模型的分辨率不够或者感受野不足。解决办法是增大输入分辨率、添加CRF后处理,或者加入边界感知损失函数去强化边界约束。
还有一个容易被忽略的点:很多公开数据集在采集时,器械的状态(比如钳子张开的程度、电钩是否在电凝)会影响标签的可信度。同一个器械在不同视频中的外观差异很大,比如有些视频中钳子表面沾了血迹,颜色接近组织,模型就会混淆。我的经验是在训练时加入大量颜色增强和模拟污染增强,可以让模型对这种跨域差异更加鲁棒。
另外,建议养成每次实验固定随机种子并记录数据划分版本的习惯。医学影像数据集的标注偶尔会有修订,比如某些帧原本标注错了后来更新了。如果你不记录用的是哪个版本,过段时间想复现实验会非常痛苦。
6. 多数据集融合与扩展方向
聊完单数据集的实操,再聊聊更进阶的玩法:把这三个数据集融合起来做联合训练,或者用它们做预训练然后迁移到其他手术场景。
6.1 跨数据集联合训练的必要性与可行性
手术视频AI的一个现实问题就是数据量不够。Cholec80只有80个视频,CholecSeg8k2020只有约8000帧标注,Endoscapes2024虽然标注更细,但整体规模也不算大。单数据集训出的模型泛化能力有限,尤其是不同医院的腹腔镜设备、镜头参数、光照条件差别很大,模型在新场景上容易掉点。
一个合理的路线是:用Cholec80做阶段识别的骨干数据,用CholecSeg8k2020做分割能力的注入,用Endoscapes2024做细粒度场景理解的增强。三者的标注维度不同,不能直接拼在一起训练,但可以先在各自任务上训练教师模型,再用知识蒸馏或伪标签的方式把知识迁移到统一模型中。
这种做法的工程复杂度比较高,但效果通常很显著。尤其是在工具分割上,如果能同时利用CholecSeg8k2020和Endoscapes2024的标注,分割的鲁棒性会有可见提升。不过要注意的是,不同数据集的图像风格差异也很大,直接混合训练有时会导致模型出现过拟合。建议在数据加载时增加域随机化操作,或者使用域自适应技术来缩小域差距。
6.2 从学术基准到临床应用:还有多远的路要走
这三个数据集在学术圈被用来验证算法创新,但距离真正的临床应用还有一段不短的距离。真实手术室的挑战包括:患者体型差异导致组织形态变化、术中出血和烟雾干扰、摄像头切换和镜头抖动、不同医生的操作习惯差异等。这些都是公开数据集中覆盖不足的。
如果想往产品方向走,我的建议是先用这三个数据集把算法能力做到极致,然后找合作医院收集小规模私有数据进行微调。公开数据集的价值在于让你拥有一条完整且可复现的技术基线,私有数据则决定最终落地的性能上限。两者配合,才是务实路线。
6.3 后续可以扩展的玩法
如果时间和资源允许,可以在数据集基础之上做不少扩展工作。比如用这三个数据集训练一个自监督预训练模型,再用少量标注数据做微调,这种范式在手术视频领域还很新,值得探索。也可以尝试把阶段识别和分割模型输出结合起来做手术风险预警系统,比如当检测到电钩靠近肝脏且电凝开启时提示风险,这已经不是纯算法任务,而是系统集成任务。
我个人的经验是,算法指标提升到一定程度后,边际收益会迅速降低,真正的价值在于把算法输出转化成临床可理解、可操作的信息。这也是做手术AI最有成就感的地方。
回到我自己的实操体会上,最想说的一点是:不要贪多求快,一个数据集一个小任务先跑透,比三个数据集囫囵吞枣强得多。Cholec80帮我理解了时序建模在手术视频中的作用,CholecSeg8k2020加深了我对类别不平衡和像素级标注的认识,Endoscapes2024则提醒我手术AI的终极目标不是刷榜,而是在真实手术中帮上忙。先把手上这一个数据集用透,把代码、预处理、评测流程打磨成顺手可用的工具链,再去碰下一个数据集,你会发现一切都顺了。