电脑基础 · 2023年3月1日

Python使用VTK对容积超声图像进行体绘制(三维重建)

目录

    • VTK简介
    • 什么是体绘制?
    • 体绘制效果图
    • 流程
    • 安装VTK
    • Code
    • Q&A
    • Reference

VTK简介

VTK(Visualization Toolkit)是一个用于3D计算机图形学、图像处理和可视化的开源软件包。它包括一组C++类和工具,可以让用户创建和处理复杂的3D图形和数据可视化。VTK提供了多种算法,如体绘制、剪切、切片、等值面、等值线、流线、轮廓线、纹理映射等,可以处理各种类型的数据,包括体数据、网格数据、点云数据等。VTK也提供了Python、Java等多种编程语言的接口,方便用户在不同的环境中使用。
VTK的应用十分广泛,包括医学图像处理、工程和科学可视化、计算流体动力学、地球科学、物理模拟等领域。由于其开源和免费的特点,VTK被广泛应用于学术界和工业界,并得到了许多用户和贡献者的支持和发展。

什么是体绘制?

体绘制(Voxel-Based Volume Rendering),也称为三维重建(区别于投影图像的三维重建),直接利用体数据来生成二维图像的绘制技术。与面绘制(Surface Rendering)不同的是体绘制技术不需要提取体数据内部的等值面,它是一个对三维体数据进行采样和合成的过程。体绘制能够通过设置不透明度值来显示体数据内部的不同成分和细节。常用于人体CT图像通过设置不透明度来显示各种器官与组织。总的来说体绘制是包含体数据,而面绘制则是让整个模型由多种多边形构成模型表面,但内部是空的,想要看到模型各个切面的数据还是需要使用体绘制。

体绘制效果图

超声图像大小尺寸为 208 x 240,切面一共176张,往z轴延伸。
Python使用VTK对容积超声图像进行体绘制(三维重建)

流程

VTK体绘制渲染管线

1. 将多张图像转化为vtkImageData
2. 使用体绘制算法,本文用的是vtkGPUVolumeRayCastMapper
3. vtkVolume
4. vtkRenderer
5. vtkRenderWindow
vtkVolumeProperty设置颜色与不透明度
SetColor
SetScalarOpacity

安装VTK

本文测试时VTK版本为9.2.5。若提示函数不存在的情况请检查本地版本对应函数是否废弃。

pip install vtk

Code

import vtk
# 定义图片读取接口
# 读取PNG图片就换成PNG_Reader = vtk.vtkPNGReader()
Jpg_Reader = vtk.vtkJPEGReader()
Jpg_Reader.SetNumberOfScalarComponents(1)
Jpg_Reader.SetFileDimensionality(3)  # 说明图像是三维的
# 定义3D模型大小,图像大小尺寸为 208 x 240, 一共176张
# 定义范围从0开始
Jpg_Reader.SetDataExtent(0, 207, 0, 239, 0, 175)
# 设置图像的存放位置
Jpg_Reader.SetFilePrefix("./imgs/")
# 迭代文件中所有图像, 图像命名格式为: 000.jpg开始到175.jpg, 03d代表三位字符串, 不够三位则左侧补0
Jpg_Reader.SetFilePattern("%s%03d.jpg")
Jpg_Reader.Update()
# 二进制数据排序按小端(LittleEndian)规则
Jpg_Reader.SetDataByteOrderToLittleEndian()
# 图像处理结束
# 创建一个vtkRenderer对象,用于显示渲染结果
renderer = vtk.vtkRenderer()
# 创建一个vtkRenderWindow对象,用于显示vtkRenderer对象中的内容
render_window = vtk.vtkRenderWindow()
render_window.AddRenderer(renderer)
# 创建一个vtkRenderWindowInteractor对象,用于处理交互事件
interactor = vtk.vtkRenderWindowInteractor()
interactor.SetRenderWindow(render_window)
# 应用体绘制算法,生成三维模型
volume_mapper = vtk.vtkGPUVolumeRayCastMapper()
# Jpg_Reader.GetOutput()的输出为vtkImageData
volume_mapper.SetInputData(Jpg_Reader.GetOutput())
# 定义颜色映射
color_transfer_function = vtk.vtkColorTransferFunction()
# 越接近黑色0越暗, 越接近白色255越亮
color_transfer_function.AddRGBPoint(0, 0.0, 0.0, 0.0)
color_transfer_function.AddRGBPoint(255, 1.0, 1.0, 1.0)
# 设置不透明度函数
opacity_transfer_function = vtk.vtkPiecewiseFunction()
# 把像素值低于15的设置为透明, 去除黑色0, 白色255则不透明
threshold = 15
for i in range(threshold):
    opacity_transfer_function.AddPoint(i, 0.0)
opacity_transfer_function.AddPoint(255, 1.0)
# 设置vtkVolume参数
volume_property = vtk.vtkVolumeProperty()
volume_property.SetColor(color_transfer_function)
volume_property.SetScalarOpacity(opacity_transfer_function)
# 是否开启阴影
# volume_property.ShadeOn()
# 设置线性插值方式
volume_property.SetInterpolationTypeToLinear()
# 将vtkVolumeMapper、vtkVolumeProperty和vtkVolume组合在一起
volume = vtk.vtkVolume()
volume.SetMapper(volume_mapper)
volume.SetProperty(volume_property)
renderer.AddVolume(volume)
# 设置背景为白色
renderer.SetBackground(1.0, 1.0, 1.0)
# 显示渲染结果
render_window.Render()
interactor.Start()

Q&A

  1. Q: 如何过滤VTK模型中的背景/黑色部分/空气部分?
    A: 给vtkVolume的Property通过SetScalarOpacity函数设置opacity_transfer_function,给不需要显示的组织的对应像素设置透明度为0即可过滤对应组织。

体绘制数据使用vtkImageData储存,不过滤黑色像素就会像下图一样显示为一个长方体。
Python使用VTK对容积超声图像进行体绘制(三维重建)

Reference

  1. 《VTK图形图像开发进阶》- 张晓东 罗火灵编著