本文总结的是2024.9.11-2024.9.23的学习内容,公司每周二居家办公,所以计划每周二更新。
上次我们已经了解了dicom读取和MPR渲染的一些基础知识和工具,这次开始coding实现MPR。
首先要解决的问题是如何使用PySide6渲染vtk的renderWindow。
vtk提供了QVTKRenderWindowInteractor帮助我们集成到PySide6, 官方提供了简单的demo解释如何集成,但结合vtkResliceImageViewer使用的时候还是遇到了一些问题。主要是QVTKRenderWindowInteractor和vtkResliceImageViewer都含有renderer和renderwindow,如何统一二者没有太多文档。最后也不记得在哪里找的解决方案成功了,具体代码如下:
class QtMPRViewer(QVTKRenderWindowInteractor):
def __init__(self, orientation):
self.imageViewer = vtkResliceImageViewer()
self.imageViewer.SetRenderWindow(self.GetRenderWindow())
self.imageViewer.SetInputConnection(reader.GetOutputPort())
接下来要解决的问题是代码组织和UI结构。
代码组织这部分参考了开源项目:github.com/MohdFarag/M… ,这个项目也是使用python+vtk+qt的解决方案,但数据接入的是mhd格式。除了代码组织,实现细节也一直在借鉴,毕竟相对于3D slicer这种大而全,小而美的项目很适合初学者学习。
UI结构这部分参考3D slicer的实现,目前只实现了右侧的MPR和slicer切换,目标是将常用的功能都集成到这个项目中。
在解决完上述问题后,面临的主要问题就集中在MPR的渲染上了。
对比3D slicer的渲染效果,直接使用vtkDICOMImageReader+vtkResliceImageViewer渲染,slice顺序,windowlevel,zoom等渲染属性,交互方式都不同。
先从简单的windowlevel解决,vtkResliceImageViewer有得到windowLevel的接口,麻烦的要设定什么样的值,阅读3D slicer的源码里面有个auto set windowlevel的功能,但知道如何实现这个算法的优先级不高,所以就先通过3D slicer的UI知道了windowlevel的值,硬编码到了自己的项目上,得到的渲染效果基本和3D slicer相差无多。windowlevel的问题基本算是解决了。
接下来解决的问题是slice渲染顺序和方向的问题,这个问题主要还是由于vtkDICOMImageReader导致的,其读取的数据所处坐标系既不是RAS也不是LPS,目前也没有找到一个合适的库可以解决这个问题,这部分打算自己手动实现下。在研究这个问题时候发现自己对医疗领域的坐标系还是有很多不清楚的地方,希望后续解决这个问题的时候可以有更深的认识。
以上就是本文的全部内容了,下一步就是将slice问题解决,还计划开发一个类似3D slicer的data probe功能。