腹盆腔三维可视化系统的设计与实现

宁国玺. 腹盆腔三维可视化系统的设计与实现[D].山西大学,2020.

介绍:

本文基于使用 Opencv、VTK、ITK 和 Qt 工具包,完成了从二维医学图像序列到三维立体器官模型这一过程,并对系统各组成部分的设计与实现进行了详细的介绍。文章中首先介绍了课题研究的背景与意义以及国内外研究现状。接着介绍了三维可视化进程的流程顺序即:读取医学图像序列数据;对读取到的数据进行预处理步骤;对感兴趣的目标器官或组织进行分割;基于分割后的图像数据生成三维立体模型。论文基于每一步的流程详细地介绍了完成这些步骤的相关技术与算法,比如使用区域生长算法分割器官组织以及使用体绘制算法完成三维建模的工作。在介绍完理论技术与算法之后,介绍本系统使用的工具与编写工作环境。比如使用 ITK 工具包完成医学图像读取与图像分割的工作,使用 VTK 工具包完成三维模型的渲染,使用 Qt 完成对整个系统界面的设计以及用户交互事件响应机制的设计,并对系统架构的设计进行了详细介绍。最后通过进行系统测试将本文中提到过的所有算法与技术以截图的形式进行展示。

第二章 医学图像预处理

第五章 医学图像三维可视化系统搭建

5.3 图像数据控制部分

5.3.1 医学图像输入输出

ITK工具包里的ImageIOBase类里封装了所有医学图像数据的读写方法,系统对于医学图像的访问就依赖于这个类。在应用过程中系统通常需要读取的是一个图像序列,比如上文提到的DICOM格式的文件,这时利用ITK提供的itkSeriesReader来进行读取。

5.3.2 系统图像格式

将医学图像文件读入内存之后,为了方便系统对图像数据进行操作,需要将这些格式统一转换为系统内部的图像格式。比如在本系统中定义了两种图像的抽象类SImage和SPolygonal,分别用来构造图像类别(DICOM 文件格式)和多边形类别(vtk文件格式)。 其中 SImage 类里包含图像数据灰度值矩阵 S_data,图像名称 S_name,图像路径 S_path,图像原点 S_origin,图像读写锁 S_RWlock 等。而 SPolygonal 相对较为简单一些有图像名称P_name,图像路径 P_path,P_PolyData 此成员是 vtkPolyData 类型的。

5.3.3 图像数据item的树形结构

为了实现图像可视化的需求,上文中写到的图像数据结构需要加入一些新的属性(图像绘制器种类、绘制参数等等)进行封装形成一个数据节点用 dataNode 表示。之后需要建立一个树形结构 dataTree 来存储和管理所有的数据节点。在 dataTree 内定义了数据节点的增删改获取等接口,每个数据节点包含了图像数据(灰度值矩阵)和图像属性两部分构成。系统中不能直接对图像数据进行访问需要通过树结构 dataTree,这大大增加了数据的安全性。

5.3.4 用户图形界面UI设计

关于用户界面的设计需要用到的工具是 Qt,首先新建一个 QImageDataView 类来完成数据面板界面的设计。图像数据 item 需要在界面中以树形结构来显示,因此需要 Qt 里的 QTreeView和 QAbstractItemModel 类来设计界面。一个图像数据 item 模型的树形结构展示需要通过 QTreeView 来实现。QAbstractItemModel 是一个虚基类即必须定义一个子类继承他才能创建图像数据 item 模型,我们将子类定义为 dataTreeItemModel。QTreeView 通过 set Model()函数进行配置。

最后需要在 QTreeView 中添加不同的事件和功能,比如保存功能可视化功能等。通常一般软件中图形界面中点击右键会弹出菜单来。在本系统中也需要将部分功能添加到右键弹出的菜单中。它的实现方法是利用 Qt 中的 QMenu,在 QMenu 中添加响应信号来实现功能。使用 QT 中信号和槽机制将右键点击事件与功能函数绑定起来就完成了一次事件响应。比如:

表示的就是 showAction 的 triggered 信号发生后,调用 ShowNoedes()函数。右键菜单主要功能有保存节点(SaveNodes()),删除节点(Delete Nodes()),重新初始化节点(ReinitNodes())用以初始化节点的参数。

5.4 图像模型显示部分

显示模块是用来把图像信息显示给用户的模块,本系统中用户界面上有 4 个基础视图,分别是医学图像的 3 个轴位面横断面、冠状面、矢状面视图,还有一个是模型视图用来显示三维模型。

5.4.1 可视化流程

根据上文中对 VTK 对象的描述,我们需要把视图中 vtkRenderWindow、vtkRender、vtkActor等要素加入到系统中。

首先先介绍一下 QVTKWidget 类,它是 VTK 为了适应 Qt 而设计的一个类,它是 Qt 与 VTK联系的桥梁, 类 里 定 义 了 一 个 vtkRenderWindow 对 象 用 来 显 示 图 像 或 者 是 模 型 。vtkRenderWindow 类需要新建一个 QVTKWidget 类里的 QRenderWindow 来定义。除此之外还需要定义 vtkRenderer(渲染场景)对象。
在本系统中,不同图像数据在进行渲染之前的设置方法有所不同。举个例子,对于医学图像序列来说如果要显示在二维的视图上,需要从三维数据中提取出对应的一张二维图像设置对应参数,如果要显示在三维视图中就需要设置三维可视化渲染器。我们通过为每种数据类型设计一个渲染类 Renderer,设置所有图像数据的绘制属性。同时我们还需要建立一个类用来管理渲染的流程,它的对象设置为全局属性使整个系统都可以调用里面函数来设置渲染属性,我们将它命名为 renderManager 将所有 VTK 渲染的对象参数的设置都组合起来封装成一个完整的过程。

5.4.2 渲染器

如上文所述系统内不同种类的图像数据的渲染方法也是不同的,由不同的渲染器(Renderer类)控制。Renderer 的类型总结如下:
ImageRenderer2D 用来渲染二维图像格式,ImageRenderer3D 用来渲染三维图像格式,MeshRenderer2D 用来渲染二维多边形图像格式,Mesh Renderer3D 用来渲染三维多边形图像格式。以下是对以上 4 种渲染器的详细设计。
ImageRenderer2D 的主要功能是从三维图像数据中提取出对应的二维图像切片,并显示在二维视图上。其配置流程如下图(图 6-1)所示:

其中,vtkImageReslice 用于从三维体数据中提取出对应的二维切片,vtkTexture 用途是将 vtkImageData 图像转化为纹理数据,vtkPlane 是指 vtk 平面,VtkPolyDataMapper 用于渲染VtkPolyData 类型图像。

ImageRenderer3D 的主要功能是通过将三维医学图像序列数据进行体绘制并且显示在三维视图上。体绘制采用的是 VTK 中的体绘制类:vtkFixedPointVolumeRayCastMapper 类(流程图中简化称为 vtkFPVRCM)。如图类名这个类就是通过光线投射算法来实现体数据。其配置流程如下图(6-2)所示

光线投射算法已在上文中详细介绍过了,图中 vtkImageResample 用途是对图像进行重采样,渲染流程中除了要对图像序列进行处理外需要创建一个 VtkVolumeProperty 实例,然后在设置好各个属性(颜色透明度属性,rgb 颜色映射等),最后将渲染器和实例传递给最后的成品vtkVolume 实例展示到视图上。

MeshRenderer2D 类主要功能是将三维多边形 SPolygonal 数据绘制到二维视图上。其配置流程如下图(图 6-3)所示:

其中,VtkCutter 的作用是从 vtkPolyData 获取 vtkPlane 对应的图像数据。

MeshRenderer3D 的操作比较流程与 Mesh Renderer2D 类似,流程没有其他分支,用途是将三维多边形数据 SPolygonal 绘制到三维视图上。流程图如下图(图 6-4)所示:

5.4.3 图像交互

在系统运行过程中,用户需要对四个视图的交互操作来控制图片显示效果,比如切片视图中图像序列中切片的选取,图片移动,图片缩放,亮度对比度调整等等。用户还需要在三维模型视图中交互操作控制模型的旋转,控制摄像机的位置。以及在分割模块中在切片视图中手动选取种子点才能完成相应的分割操作等等。

系统中 4 个视图均是 QVTKWidget 类的对象 vtk RenderWindow。在四个视图中需要能够响应Qt 中的鼠标操作事件,和部分键盘快捷键的点击事件。这些用户操作对应的是 Qt 事件响应函数,以下是系统中用到的响应函数,在使用时需要对这些函数进行重载即可按照用户需要来进行相关处理。

比如:MousePressEvent()对应的是鼠标按下事件,MouseMoveEvent()对应的是鼠标在视图上移动就会触发的事件,MouseClicked()是鼠标点击事件,MouseReleaseEvent()是鼠标按键松开事件,keyPressEvent()键盘按键按下事件等等。下文会对部分图像的操作效果进行说明:

1. 二维图像序列中切片的切换

要实现这个效果需要把鼠标指针放在该视图中的情况下,滑动滚轮进行当前切片的前后层切换。修改 SlicerController 类中的当前切片参数(currentSlicer),然后更新渲染即可。VTK 工具包里的 vtkImageReslice 就会从三维数据中提取出对应的二维图像数据渲染在视图上。

2.图像缩放

图像缩放的效果是要实现二维视图中切片图像放大缩小功能,具体的操作方法是按住Ctrl 键的同时鼠标指针放在该视图的情况下滑动鼠标滑轮可以放大或是缩小图片。实现方法就是检测两种键盘鼠标事件的时候,计算鼠标滑轮滚动的尺度来控制图片缩放因子factor,然后将 factor 传递给渲染流程中 camera 类的成员函数 zoom()来实现缩放效果。

3.视图同步切换

视图同步切换的效果是鼠标停留在 3 个方向切片的二维视图中之一的情况下,鼠标指针停留在该视图的某一坐标之下,按住 shift 键其他两个方向的视图会自动切换到鼠标指针点停留坐标点所在的那张切片。方法就是提取鼠标指针点所在的坐标参数,然后修改其他二维视图的当前切片层数值即修改slicerController对象的当前切片层数(currentSlice),再修改 SlicerController 类中的当前切片参数,然后进行更新视图操作利用 VTK 从三维数据中提取出相应的二维图像将此切片图像绘制出来。

4.图像信息显示

图像信息显示用来显示二维图像切片的一些必要信息,比如切片层数,像素点信息,灰度分布等等,操作方式很简单用鼠标指针放在该视图的情况下点击右键选择菜单栏里的“图像信息显示”即可查看。方法就是绑定事件调用 showImageMessage()函数。

5.视图绘图工具

对二维切片视图进行绘图标记的目的是为图像分割模块中区域生长算法做准备,执行区域生长算法需要建立在二维视图标记有种子点的情况下。绘图工具包括画笔,橡皮,剪刀工具等等,使用方法类似于 windows 系统中自带的画图程序,每一种颜色区域表示不同的器官组织,具体方法定义一个 Segment 类每一个颜色就是该类的一个对象,画笔工具和橡皮工具分别对应调用该类中的 seedPointAdd(),seedPointDelete()成员函数来实现对种子点的增删功能,笔刷大小尺寸越大标记时就会把鼠标指针点击的像素点临近更大范围的像素点包括进来。所有Segment 对象对应的种子点标记完成之后,将种子点的物理坐标(PhysicalGrid)转为索引坐标 IndexGrid,再提取出原始数据灰度矩阵 imageData,根据图像窗宽计算出初始的区域生长阈值 threshold,获取图像 extent,将这四项数据数据参数传入 itk::ConnectedThresholdImageFilter 类内 set()函数,然后运行类内生长算法进行运算,区域生长的结果是二值的上下限是 0 和 1,分割后的图像需要经过 vtkLookupTable进行颜色映射转化为 vtkImageData 才可进行显示。

第六章 系统测试案例

6.1 测试用例

6.2 系统测试结果

6.2.1 导入DICOM序列文件

如上图(图 7-1)所示,在读取 DICOM 文件后系统主界面上三个方向的切片视图中会生成对应 CT 序列。右上角为模型视图,图中视图的位置结构均可手动调节。

6.2.2 图像鼠标操作测试

本系统通过鼠标键盘响应事件,来实现图像缩放功能如图(图 6-3)以及图像亮度对比度的调整(如图 6-4)。具体做法是:鼠标停留在切片视图时,按住 ctrl 鼠标上下滑动实现图像缩放。鼠标停留在切片视图时,按住鼠标按住左键上下/左右滑动来实现亮度/对比度调整。

6.2.3 图像描绘与区域生长

如下图首先在图 7-5 左图中选择相应的描绘工具然后在切片视图中选取不同器官组织先标记为不同的颜色,之后就是选择相应的颜色后在图中标记种子点,为了分割出完整器官模型,需要选择一个颜色标记为对照区域(图中黄色部分),最后进行区域生长后产生效果如图(7-6)。如果出现了过生长或空洞的效果,则在分割基础上再选取一些种子点即可。

6.2.4 阈值分割效果

如下图 7-7 中,在控制区域可以选择上文中提到的阈值分割中三种阈值选择算法。图中蓝色滑动条对应的是手动选择阈值法,而在自动设置阈值一栏中可以选择剩下两种选择算法分别是大津法(Otsu)和最大熵阈值分割算法。阈值分割效果如图 7-8 所示。

6.2.5 体绘制测试

如上图(图 7-9)所示,首先截取患者腹部区域,然后选择体绘制模块,在本系统模型视图(右图)中显示了使用光线投影算法进行体绘制运算后产生的效果。

6.2.6 面绘制渲染效果

如图(图 7-6)基于经过分割算法分割出来的器官组织区域(案例中使用了肝脏肾脏和部分主动脉分割效果),使用面绘制移动立方体算法进行面绘制效果如下:

《腹盆腔三维可视化系统的设计与实现》阅读相关推荐

  1. 阅读《SentiLARE: Sentiment-Aware Language Representation Learning with Linguistic Knowledge》

    SentiLARE: Sentiment-Aware Language Representation Learning with Linguistic Knowledge Abstract 现有的预训 ...

  2. Align before Fuse: Vision and Language Representation Learning with Momentum Distillation

    ALBEF:Align before Fuse: Vision and Language Representation Learning with Momentum Distillation 论文链接 ...

  3. # 互信息最大化[视角统一]:Align before Fuse: Vision Language Representation Learning with Momentum Distillation

    互信息最大化[视角统一]:Align before Fuse: Vision and Language Representation Learning with Momentum Distillati ...

  4. 【论文模型讲解】VideoBERT: A Joint Model for Video and Language Representation Learning

    文章目录 前言 0 摘要 1 Introduction 2 相关工作 3 模型 3.1 BERT 3.2 VideoBERT 4 实验与分析 4.1 数据集 4.2 视频和语言预处理 4.3 模型预训 ...

  5. [论文学习]TDN: An Integrated Representation Learning Model of Knowledge Graphs

    [论文学习以及翻译]TDN: An Integrated Representation Learning Model of Knowledge Graphs 文章主要内容 摘要 前言 相关工作 基于T ...

  6. Kaiming He论文阅读笔记三——Simple Siamese Representation Learning

    Kaiming He大神在2021年发表的Exploring Simple Siamese Representation Learning,截至目前已经有963的引用,今天我们就一起来阅读一下这篇自监 ...

  7. [论文阅读] iCaRL: Incremental Classifier and Representation Learning

    论文地址:https://openaccess.thecvf.com/content_cvpr_2017/html/Rebuffi_iCaRL_Incremental_Classifier_CVPR_ ...

  8. 自然语言处理学习——论文分享——A Mutual Information Maximization Perspective of Language Representation Learning

    资料放在前面:https://blog.csdn.net/Arnetminer/article/details/105840669 文章的贡献如下: (1)提出了一个基于最大化MI的理论框架来理解词表 ...

  9. CVPR 2020 《12-in-1: Multi-Task Vision and Language Representation Learning》论文笔记

    目录 简介 动机 贡献 方法 实验 简介 本文是在NIPS 2019 ViLBERT上的拓展. 论文链接 动机 本文修改了ViLBERT的预训练过程,有两个小修改:1. 对regions进行mask时 ...

  10. 论文阅读Unsupervised Corpus Aware Language Model Pre-training for Dense Passage Retrieval

    密集文本检索的无监督语料库感知语言模型预训练 ACL2022 论文链接 摘要 最近的研究证明了使用微调语言模型(LM)进行密集检索的有效性.然而,密集检索器很难训练,通常需要经过精心设计的微调管道才能 ...

最新文章

  1. C# Windows CE使用小技巧实例
  2. 对javascript闭包的理解
  3. 当git上只做文件大小写重命名的修改时,如何躲坑...
  4. 正则表达式 匹配中文,英文字母和数字及_的写法!同时控制长度
  5. js tostring 16 java_js中toString()和String()区别详解
  6. Open3d之裁剪点云
  7. jQuery MVC 科室异步联动
  8. 接口没获取到就被使用_使用CompletableFuture时,那些令人头疼的问题
  9. EXCEL的去重去除某个字段后全部操作
  10. Directory traversal in Spring framework漏洞修复
  11. java中speak方法的意思_Java中的關鍵字
  12. Appium----基于Ubuntu系统安装个人版免费的Android模拟器Genymotion模拟器
  13. pycharm 将本地文件添加到library root
  14. linux系统怎么远程进服务器
  15. web程序设计(3)——使用CSS设计新闻网页
  16. 软件测试工程师和WGT,三坐标和齿轮测量中心测齿轮的区别
  17. Office 2016系列下载地址
  18. alias 自定义参数——实现一个删除备份的指令
  19. 【数学建模】多目标规划
  20. Python3爬虫查看微信撤回消息

热门文章

  1. python绘制对数坐标图描点,python坐标轴对数显示
  2. 传奇程序员Larry Wall:Perl的乐趣
  3. JAVA计算机毕业设计网上化妆品商城设计(附源码、数据库)
  4. 别让民间资本总盯着房地产
  5. 基于node和npm的命令行工具——tive-cli
  6. python编程绘制楼梯_Python走楼梯问题解决方法示例
  7. [高通MSM8909][Android7.1]移除电池显示选项
  8. OPENCV核心类Mat的基本知识介绍及其使用(一)
  9. 中专计算机应用专业建设思路,以信息化教学资源建设促进中职计算机专业建设的研究...
  10. android dns 苹果,手机怎么设置百度公共dns(ios/Android系统)?