当前位置: 首页 > news >正文

SimpleITK——创建nrrd体素模型

在介绍如何生成nrrd前,了解一下为什么医学影像上一般使用nrrd的体素模型?

为什么医学影像上一般使用nrrd的体素模型?

在医学影像领域,‌NRRD(Nearly Raw Raster Data)格式‌被广泛用于存储体素模型(如CT、MRI数据),主要基于以下技术优势:


‌1. 灵活的数据存储方式‌

  • ‌支持原始数据无损存储‌
    NRRD可直接存储未经压缩的体素数据(如16位整型、32位浮点),避免DICOM等格式的二次编码损失,适合科研和精准医疗。
  • ‌多维数据兼容性‌
    可处理3D体素(CT/MRI)、4D时序数据(如fMRI、心脏动态扫描)甚至更高维数据(如DTI纤维追踪)。

‌2. 强大的元数据支持‌

  • ‌关键医学参数嵌入‌
    通过文本头文件(Header)记录:
    • 体素间距(spacings:如 0.5mm×0.5mm×1.0mm
    • 空间方向矩阵(space directions,用于对齐DICOM坐标系)
    • 患者体位标识(如LPS/RAS坐标系)
  • ‌可扩展性‌
    支持自定义字段(如扫描协议、厂商参数),比DICOM更轻量但足够专业。

‌3. 跨平台与开源生态‌

  • ‌无专利限制‌
    相比DICOM(需授权),NRRD为开源格式,兼容ITK、VTK、3D Slicer等主流医学软件。
  • ‌简化预处理流程‌
    直接存储已重建的体素矩阵,省去DICOM多层文件合并的步骤,加速AI模型训练(如nnUNet直接读取NRRD)。

‌4. 与其他格式的对比‌

特性NRRDDICOMNIfTI
‌数据维度‌支持任意维度单层2D为主3D/4D
‌元数据灵活性‌高(自定义字段)高(但结构复杂)中(固定字段)
‌坐标系支持‌明确空间方向需计算固定(RAS/LPS)
‌适用场景‌科研/算法开发临床归档神经影像(fMRI)

‌典型应用场景‌

  • ‌放射治疗规划‌:NRRD存储的CT体素数据可直接用于剂量计算(如RayStation)。
  • ‌深度学习‌:MONAI等框架默认支持NRRD,便于加载标注数据(如image.nrrd+label.nrrd)。
  • ‌三维重建‌:通过VTK将NRRD转换为STL模型用于3D打印。

‌注意事项‌

    • ‌临床兼容性‌:医院PACS系统通常仍以DICOM为主,NRRD多用于科研后端。
    • ‌压缩选项‌:NRRD支持GZIP压缩(如*.nhdr+*.raw.gz),但会牺牲部分读写速度。

以上是愚通过ds了解到的一些情况,仅供参考。

代码实现

以下为调用SimpleITK实现将Dicom文件转化为Nrrd体素模型的示例:

 public class DicomToNRRDHelper{/// <summary>/// DICOM序列转化为NRRD文件/// </summary>/// <param name="dicomDirectory">dicom文件路径</param>/// <param name="outPutFilename">包含路径和后缀名,且后缀名必须为.NRRD(因为需要以体素渲染)</param>/// <returns>失败为false;成功为true</returns>[MethodImpl(MethodImplOptions.Synchronized)]public static bool DicomToNRRD(string dicomDirectory, string outPutFilename){// 输入验证if (!Directory.Exists(dicomDirectory)){NlogHelper.Logger.Error($"Directory not found: {dicomDirectory}");return false;}if (!outPutFilename.EndsWith(".nrrd", StringComparison.OrdinalIgnoreCase)){NlogHelper.Logger.Error("Output file must have .nrrd extension");return false;}Image image3D = null;try{var seriesIDs = ImageSeriesReader.GetGDCMSeriesIDs(dicomDirectory);if (seriesIDs == null || seriesIDs.Length == 0){NlogHelper.Logger.Error($"No DICOM series found in: {dicomDirectory}");return false;}var seriesFileNames = ImageSeriesReader.GetGDCMSeriesFileNames(dicomDirectory, seriesIDs[0]);NlogHelper.Logger.Debug($"Processing {seriesFileNames.Count} DICOM files");if (seriesFileNames.Count > 1){using var reader = new ImageSeriesReader();reader.SetFileNames(seriesFileNames);image3D = reader.Execute();}else if (seriesFileNames.Count == 1){using var reader = new ImageFileReader();reader.SetFileName(seriesFileNames[0]);image3D = reader.Execute();}else{return false;}// 保留原始像素类型using var filter = new CastImageFilter();// 保留原始像素类型选项filter.SetOutputPixelType(image3D.GetPixelID());using var convertedImage = filter.Execute(image3D);using (var writer = new ImageFileWriter()){writer.SetFileName(outPutFilename);writer.Execute(convertedImage);}NlogHelper.Logger.Info($"Successfully created: {outPutFilename}");return true;}catch (Exception ex){NlogHelper.Logger.Error(ex, $"Failed to convert DICOM to NRRD");return false;}finally{image3D?.Dispose();}}}

注意事项

  1. SimpleITK中涉及到image、reader、writer最好都显示释放一下或 使用using语句,以达到使用完及时回收这些非托管资源。尽量不要依赖于它们在终结器中通过调用dispose的相关方法来实现资源回收,这个在实际项目中有过惨痛教训(资源不能及时回收,导致非托管对象无限增长,最终导致程序崩溃)。
  2. 对于非托管对象的释放,特别是在try catch语句中,若异常时容易忽略,尽量在finally中处理一下。
  3. 日志要尽量完善,如文件的长度检测;文件路径的检测;文件名的规范性检测等待

以上需要在实际开发中引起注意。

http://www.lqws.cn/news/472771.html

相关文章:

  • 三种语言写 MCP
  • C++ 的设计模式
  • [Python学习日记-93] 并发编程之多线程 —— 互斥锁与 Python GIL(Global Interpreter Lock)
  • 微处理器原理与应用篇---计算机系统的性能测试
  • 人工智能学习51-ResNet训练
  • 旧物回收小程序开发:开启绿色生活新方式
  • [TPAMI 2022]HGNN: General Hypergraph Neural Networks+
  • GO语言---数组
  • ffmpeg(七):直播相关命令
  • AI大模型学习之基础数学:高斯分布-AI大模型概率统计的基石
  • 4.1 FFmpeg编译选项配置
  • Wire--编译时依赖注入工具
  • Python元组常用操作方法
  • C++模板基础
  • 并查集(Disjoint-Set Union)详解
  • 【分布式理论】读确认数与写确认数:分布式一致性的核心概念
  • AI大模型学习之基础数学:微积分-AI大模型的数学引擎
  • 【Linux 平台总线驱动开发实战】
  • 湖北理元理律师事务所企业债务纾困路径:司法重整中的再生之道
  • Spring中IoC的理解
  • AI大模型提示词工程研究报告:长度与效果的辩证分析
  • TensorFlow 安装与 GPU 驱动兼容(h800)
  • 【软考高级系统架构论文】论模型驱动架构设计方法及其应用
  • 【知识图谱提取】【阶段总结】【LLM4KGC】LLM4KGC项目提取知识图谱推理部分
  • 网站并发访问量达到1万以上需要注意哪些事项
  • Qt 连接信号使用lambda表达式和槽函数的区别
  • nginx服务器配置时遇到的一些问题
  • 【软考高级系统架构论文】论软件系统架构风格
  • 【Node】最佳Node.js后端开发模板推荐
  • 从0开始学linux韦东山教程Linux驱动入门实验班(1)