一:主要的知识点
1、说明
本文只是教程内容的一小段,因博客字数限制,故进行拆分。主教程链接:vtk教程------逐行解析官网所有Python示例-CSDN博客
2、知识点纪要
本段代码主要涉及的有①三维图形转换为3D体素数据
二:代码及注释
python
import math
import vtkmodules.vtkRenderingOpenGL2
import vtkmodules.vtkInteractionStyle
from vtkmodules.vtkFiltersSources import vtkSphereSource
from vtkmodules.vtkFiltersCore import vtkCutter, vtkStripper
from vtkmodules.vtkCommonDataModel import vtkImageData, vtkPlane
from vtkmodules.vtkIOXML import vtkXMLPolyDataWriter
from vtkmodules.vtkCommonCore import VTK_UNSIGNED_CHAR
from vtkmodules.vtkFiltersModeling import vtkLinearExtrusionFilter
from vtkmodules.vtkImagingStencil import vtkImageStencil, vtkPolyDataToImageStencil
from vtkmodules.vtkIOImage import vtkMetaImageWriter, vtkPNGWriter
def main():
# 创建一个3D图形
sphereSource = vtkSphereSource()
sphereSource.SetPhiResolution(30)
sphereSource.SetThetaResolution(30)
sphereSource.SetCenter(40, 40, 40)
sphereSource.SetRadius(20)
# 切割数据集的"刀"
# 首先先定义这个刀是什么,需要使用隐函数定义
cutPlane = vtkPlane()
cutPlane.SetOrigin(sphereSource.GetCenter())
cutPlane.SetNormal(0, 0, 1)
circleCutter = vtkCutter()
circleCutter.SetInputConnection(sphereSource.GetOutputPort())
circleCutter.SetCutFunction(cutPlane)
stripper = vtkStripper()
stripper.SetInputConnection(circleCutter.GetOutputPort())
stripper.Update()
circle = stripper.GetOutput()
# 写入vtp文件
polyDataWriter = vtkXMLPolyDataWriter()
polyDataWriter.SetInputData(circle)
polyDataWriter.SetFileName("circle.vtp")
polyDataWriter.SetCompressorTypeToNone() # 不适用任何压缩
polyDataWriter.SetDataModeToAscii() # 设置输出文件中的数据以ASCII(文本)格式存储
polyDataWriter.Write()
# 准备一个体素数据
whiteImage = vtkImageData()
bounds = [0] * 6
circle.GetBounds(bounds)
spacing = [0.5, 0.5, 0.5]
whiteImage.SetSpacing(spacing)
# 计算这个体素数据的维度
dim = [0] * 3
for i in range(3):
dim[i] = int(math.ceil((bounds[i * 2 + 1] - bounds[i * 2]) / spacing[i])) + 1
if dim[i] < 1:
dim[i] = 1
whiteImage.SetDimensions(dim) # 算是设置了图像体素的数量
# SetExtent 设置了图像的索引范围 确保了生成的 3D 图像的体素网格是最小且精确的,既不浪费内存,又能完整地覆盖输入的几何体
whiteImage.SetExtent(0, dim[0] - 1, 0, dim[1] - 1, 0, dim[2] - 1)
origin_shift = 5 * 0.5
origin = [0] * 3
origin[0] = bounds[0] - origin_shift
origin[1] = bounds[2] - origin_shift
origin[2] = bounds[4] - origin_shift
# 上述添加origin_shift是为了vtkImageData能够完全包裹住mesh
whiteImage.SetOrigin(origin)
# AllocateScalars # 为图像的体素数据分配内存。VTK_UNSIGNED_CHAR(无符号字符,范围 0-255),1 表示每个体素有一个分量(即灰度值)
whiteImage.AllocateScalars(VTK_UNSIGNED_CHAR, 1)
# 将 整个 3D 图像(体素网格)预先填充为前景值(即白色)
# inval = 255
outval = 0
# count = whiteImage.GetNumberOfPoints()
# for i in range(count):
# whiteImage.GetPointData().GetScalars().SetTuple1(i, inval)
# 上述for循环的简便替代方法
whiteImage.GetPointData().GetScalars().Fill(255)
extrude = vtkLinearExtrusionFilter()
extrude.SetInputData(circle)
extrude.SetScaleFactor(1.0) # 设置挤压的比例因子
extrude.SetExtrusionTypeToVectorExtrusion() # 设置为向量挤压,而非几何体表面的法线定义
extrude.SetVector(0, 0, 1) # 设置挤压的向量
extrude.Update()
pol2stenc = vtkPolyDataToImageStencil()
pol2stenc.SetInputConnection(extrude.GetOutputPort())
pol2stenc.SetTolerance(0) # 帮助过滤垂直面
pol2stenc.SetOutputOrigin(origin)
pol2stenc.SetOutputSpacing(spacing)
pol2stenc.SetOutputWholeExtent(whiteImage.GetExtent())
pol2stenc.Update()
imgstenc = vtkImageStencil()
"""
tkImageStencil 是另一个关键过滤器,它接收一个图像作为输入,并根据一个模板(Stencil)修改该图像的像素值。
"""
imgstenc.SetInputData(whiteImage)
imgstenc.SetStencilConnection(pol2stenc.GetOutputPort())
imgstenc.ReverseStencilOff()
imgstenc.SetBackgroundValue(outval)
imgstenc.Update()
imageWriter = vtkMetaImageWriter()
imageWriter.SetFileName('labelImage.mhd')
imageWriter.SetInputConnection(imgstenc.GetOutputPort())
imageWriter.Write()
imageWriter = vtkPNGWriter()
imageWriter.SetFileName('labelImage.png')
imageWriter.SetInputConnection(imgstenc.GetOutputPort())
imageWriter.Write()
if __name__ == '__main__':
main()