尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

OHIF 3.9 分割创建 API 迁移指南:createLabelmapFor* 系列方法与 viewport 中心化重构

OHIF 3.9 分割创建 API 迁移指南:createLabelmapFor* 系列方法与 viewport 中心化重构 OHIF 3.9 分割创建 API 迁移指南createLabelmapFor* 系列方法与 viewport 中心化重构【免费下载链接】ViewersOHIF zero-footprint DICOM viewer and oncology specific Lesion Tracker, plus shared extension packages项目地址: https://gitcode.com/GitHub_Trending/vi/Viewers本文是 OHIF 3.8 → 3.9 迁移指南中「分割系统」章节的核心实操文档聚焦分割创建类 API 的重命名、签名变更与架构转向。通过本文你将掌握createLabelmapForViewport、createLabelmapForDisplaySet、createSegmentationForRTDisplaySet与createSegmentationForSEGDisplaySet四个关键方法的 3.9 新用法、参数结构差异以及背后从 toolGroup 中心化到 viewport 中心化的设计动机可直接据此完成既有扩展代码的升级改造。迁移背景为什么分割创建 API 会大改OHIF 3.9 对分割体系进行了架构级重构核心变化是从 toolGroup 中心化转向 viewport 中心化详见迁移指南架构说明与入口导读3.8 时代分割Segmentation与 toolGroup 绑定一个 toolGroup 内的所有 viewport 共享同一份「全局激活分割」管理粒度较粗。3.9 时代分割直接绑定到具体 viewport每个 viewport 可以拥有独立的激活分割与表示Representation粒度更细、控制更灵活但要求调用方显式传入viewportId。与此同时Cornerstone3D 2.0 明确区分了「分割数据Segmentation」与「分割表示Segmentation Representation」两个概念同一份分割数据可以派生出 Labelmap 表示、Contour 表示等多种可视化形态。OHIF 3.9 新增了Stack Segmentation 支持默认不再生成基于 volume 的 labelmap、也不再默认把 viewport 切换为 volume viewport——默认创建路径改为基于 stack切片序列。这正是createSegmentationForDisplaySet被改名的直接原因既然分割也可以是轮廓Contour旧名字无法表达真实用途因此重命名为更明确的createLabelmapForDisplaySet。createEmptySegmentationForViewport → createLabelmapForViewport变更要点createEmptySegmentationForViewport重命名为createLabelmapForViewport与其他分割创建方法保持命名一致性。3.9 调用方式通过命令管理器执行commandsManager.runCommand(createLabelmapForViewport, { viewportId });在源码中该命令注册于 extensions/cornerstone/src/commandsModule.ts实现委托给createSegmentationForViewport工具函数见 extensions/cornerstone/src/utils/createSegmentationForViewport.tscreateLabelmapForViewport: async ({ viewportId, options {} }) { return createSegmentationForViewport(servicesManager, { viewportId, options, segmentationType: SegmentationRepresentations.Labelmap, }); },对应的底层流程createSegmentationForViewport内部值得关注从viewportGridService.getState()取出目标 viewport并取viewport.displaySetInstanceUIDs[0]作为要分割的 displaySet若传入options.displaySetInstanceUID则优先使用通过displaySetService.getDisplaySetByUID(displaySetInstanceUID)把 UID 解析为 displaySet 对象调用segmentationService.createLabelmapForDisplaySet(displaySet, segmentationCreationOptions)创建分割数据再调用segmentationService.addSegmentationRepresentation(viewportId, { segmentationId, type })把分割表示挂到该 viewport 上。注意createSegmentationForViewport中默认 label 为Segmentation (已存在分割数 1)labelIsGenerated由是否显式传入 label 决定——这正对应下方createLabelmapForDisplaySet的labelIsGenerated选项。命令也提供了对应的 Contour 版本createContourForViewport两者共用同一工具函数仅segmentationType不同。小贴士若 viewport 尚未在 grid 中注册例如「Add segmentation」命令执行时机过早工具函数会优雅返回undefined而非抛错避免未捕获错误覆盖层弹出。createSegmentationForDisplaySet → createLabelmapForDisplaySet这是本次迁移中改动最大、最需要逐行核对的地方。API 差异对照BeforeOHIF 3.8async createSegmentationForDisplaySet( displaySetInstanceUID: string, options?: { segmentationId: string; FrameOfReferenceUID: string; label: string; } ): PromisestringAfterOHIF 3.9// Method 1: Display Set Based async createLabelmapForDisplaySet( displaySet: DisplaySet, options?: { segmentationId?: string; label: string; segments?: { [segmentIndex: number]: PartialSegment }; } ): Promisestring两个关键变化方法重命名createSegmentationForDisplaySet→createLabelmapForDisplaySet明确该方法创建的是 labelmap 形态的分割。源码中它与姊妹方法createContourForDisplaySet共同委托给私有方法_createSegmentationForDisplaySet(displaySet, segmentationType, options)见 extensions/cornerstone/src/services/SegmentationService/SegmentationService.tssegmentationType分别为LABELMAP/CONTOUR。入参从 UID 改为对象不再传displaySetInstanceUID: string而是传完整的displaySet对象。官方说明指出这增强了类型安全与灵活性并为未来displaySetService的演进预留空间。迁移示例// Before - OHIF 3.8 const segmentationId await segmentationService.createSegmentationForDisplaySet( displaySetInstanceUID, { label: My Segmentation } );// After - OHIF 3.9 // Option 1: If you have a display set UID const displaySet displaySetService.getDisplaySetByUID(displaySetInstanceUID); const segmentationId await segmentationService.createLabelmapForDisplaySet( displaySet, { label: My Segmentation } );底层实现细节源码级解读_createSegmentationForDisplaySet内部做了几件值得了解的事SegmentationService.tssegmentationId 生成未传入时使用csUtils.uuidv4()生成。动态 volume 特殊处理当displaySet.isDynamicVolume为 true 时取dynamicVolumeInfo.timePoints的中间时间点作为参考 imageIds保证 labelmap 建立在一个有代表性的时间帧上。派生图像创建调用imageLoader.createAndCacheDerivedLabelmapImages(referenceImageIds)生成 labelmap 派生图像并缓存。默认 labeloptions.label || Segmentation (已有分割数 1)。默认 segments未传options.segments时自动创建Segment 1label 为本地化的Segment 1active: true。labelIsGenerated 标记options.labelIsGenerated ?? !options.label用于标记 label 是否为程序自动生成用户尚未命名。颜色 LUT 管理每个 segmentationId 维护独立的 color LUT index_segmentationIdToColorLUTIndexMap确保该分割在多个 viewport 上的多个表示共享同一 LUT——否则在不同 viewport 上编辑段颜色会出现颜色「回退」的不一致现象。这些行为在 extensions/cornerstone/src/services/SegmentationService/SegmentationService.test.ts 中有对应断言例如验证createAndCacheDerivedLabelmapImages以[imageId]调用、addOrUpdateSegmentation收到的config包含label: Segmentation 2、labelIsGenerated: true、默认Segment 1激活等。关联变化提醒3.9 中分割 ID 与 volume ID 已分离。若旧代码用cache.getVolume(segmentationId)取 labelmap 体积应改用segmentationService.getLabelmapVolume(segmentationId)详见SegmentationService API 变更文档。createSegmentationForRTDisplaySet改为 options 对象传参RT放射治疗结构集分割创建方法的方法名保持不变但签名从「位置参数」迁移为「options 对象」。BeforeOHIF 3.8async createSegmentationForRTDisplaySet( rtDisplaySet, segmentationId?: string, suppressEvents false ): PromisestringAfterOHIF 3.9async createSegmentationForRTDisplaySet( rtDisplaySet, options: { segmentationId?: string; type: SegmentationRepresentations; // not required, defaults to Contour } ): Promisestring源码中默认值定义在 SegmentationService.tsoptions: { segmentationId?: string; type: csToolsEnums.SegmentationRepresentations; } { type: CONTOUR, }当前实现只支持 Contour 表示若传入type ! CONTOUR会抛出Only contour type is supported for RT display sets right now。此外实现要求rtDisplaySet必须已加载structureSet存在否则抛出错误提示先调用rtDisplaySet.load()随后通过mapROIContoursToRTStructData将 ROI 轮廓映射为 RT Struct 数据并按segmentIndex排序最终以geometryIds组装成 Contour 类型的SegmentationPublicInput。迁移示例场景一之前没传 segmentationId 的无需任何改动// Before - OHIF 3.8 const segmentationId await segmentationService.createSegmentationForRTDisplaySet( rtDisplaySet ); // After - OHIF 3.9 const segmentationId await segmentationService.createSegmentationForRTDisplaySet( rtDisplaySet, );场景二之前传了 segmentationId 的必须改为 options 对象// Before - OHIF 3.8 const segmentationId await segmentationService.createSegmentationForRTDisplaySet( rtDisplaySet, custom-id, ); // After - OHIF 3.9 const segmentationId await segmentationService.createSegmentationForRTDisplaySet( rtDisplaySet, { segmentationId: custom-id, type: csToolsEnums.SegmentationRepresentations.Contour } );注意旧签名中的suppressEvents位置参数已移除未传 segmentationId 时实现会回退到rtDisplaySet.displaySetInstanceUID作为 segmentationId。createSegmentationForSEGDisplaySet同样收敛为 options 对象DICOM SEG 分割的创建方法与 RT 版本同步改造方法名不变、签名改为 options 对象。BeforeOHIF 3.8async createSegmentationForSEGDisplaySet( segDisplaySet, segmentationId?: string, suppressEvents false ): PromisestringAfterOHIF 3.9async createSegmentationForSEGDisplaySet( segDisplaySet, options: { segmentationId?: string; type: SegmentationRepresentations; // not required, defaults to Labelmap } ): Promisestring源码默认值SegmentationService.tsoptions: { segmentationId?: string; type: csToolsEnums.SegmentationRepresentations; } { type: LABELMAP, }当前实现只支持 Labelmap 表示传入其他 type 会抛出Only labelmap type is supported for SEG display sets right now。实现细节包括要求labelMapImages非空否则抛SEG reading failed、通过referencedDisplaySetInstanceUID找到被引用的显示集以确定参考 imageIds、对每个派生图像扫描第一个非零体素以确定firstSegmentedSliceImageId、从segDisplaySet.segMetadata.data提取每个段的编号/标签/算法信息与 RGBA 颜色构建 color LUT最终经assembleSegmentationDataForSEG组装分割数据并广播SEGMENTATION_LOADING_COMPLETE事件。迁移示例基础用法更新注意 3.9 建议显式传入type// Before - OHIF 3.8 const segmentationId await segmentationService.createSegmentationForSEGDisplaySet( segDisplaySet ); // After - OHIF 3.9 const segmentationId await segmentationService.createSegmentationForSEGDisplaySet( segDisplaySet, { type: csToolsEnums.SegmentationRepresentations.Labelmap } );自定义配置旧的位置参数segmentationId、suppressEvents均需并入 options// Before - OHIF 3.8 const segmentationId await segmentationService.createSegmentationForSEGDisplaySet( segDisplaySet, custom-id, false ); // After - OHIF 3.9 const segmentationId await segmentationService.createSegmentationForSEGDisplaySet( segDisplaySet, { segmentationId: custom-id, type: csToolsEnums.SegmentationRepresentations.Labelmap } );与 RT 版本一致未传 segmentationId 时回退到segDisplaySet.displaySetInstanceUID。另外SEGMENTATION_UPDATED事件在 3.9 中更名为SEGMENTATION_MODIFIED如你的代码订阅了旧事件名请同步更新见API 变更文档。迁移核对清单完成本文涉及的改造后建议按以下清单逐项自检createEmptySegmentationForViewport→ 改为commandsManager.runCommand(createLabelmapForViewport, { viewportId })createSegmentationForDisplaySet(displaySetInstanceUID, ...)→createLabelmapForDisplaySet(displaySet, ...)先用displaySetService.getDisplaySetByUID()将 UID 解析为对象调用createSegmentationForRTDisplaySet/createSegmentationForSEGDisplaySet时segmentationId 放入 options 对象并显式指定typeRT 默认Contour、SEG 默认Labelmap删除旧的suppressEvents位置参数若依赖cache.getVolume(segmentationId)获取 labelmap 体积改为segmentationService.getLabelmapVolume(segmentationId)订阅事件名SEGMENTATION_UPDATED→SEGMENTATION_MODIFIED涉及激活分割的代码补传viewportId如getActiveSegmentation(viewportId)、setActiveSegmentation(viewportId, segmentationId)这套迁移规则同样收录于 3.8→3.9 版本化文档 中可作为长期维护的参考基线。【免费下载链接】ViewersOHIF zero-footprint DICOM viewer and oncology specific Lesion Tracker, plus shared extension packages项目地址: https://gitcode.com/GitHub_Trending/vi/Viewers创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表