将VTK UnstructuredGrid转换为StructuredGrid

时间:2018-07-26 20:41:04

标签: python vtk paraview simpleitk

问题的背景是我将3D结构保存在需要处理的.vtk文件中(膨胀,腐蚀等)。以下代码段旨在按顺序运行,即,如果您一个接一个地运行它们,则应该没有问题(除了我提到的那些问题!)。

我是VTK的新手,对于任何非常基本的错误,我们深表歉意!

问题

我的问题源于SimpleITK的问题,其中无法读取UnstructuredGrid或PolyData:

In [1]: import SimpleITK as sitk
In [2]: img_vtk = sitk.ReadImage(file_vtk)
Traceback (most recent call last):

  File "<ipython-input-52-435ce999db50>", line 1, in <module>
    img_vtk = sitk.ReadImage(file_vtk)

  File "/usr/local/lib/python3.5/dist-packages/SimpleITK/SimpleITK.py", line 8614, in ReadImage
    return _SimpleITK.ReadImage(*args)

RuntimeError: Exception thrown in SimpleITK ReadImage: /tmp/SimpleITK/Code/IO/src/sitkImageReaderBase.cxx:97:
sitk::ERROR: Unable to determine ImageIO reader for "/data/ROMPA_MRIandSeg/09S/Analysis/1_model/clip_dilate.vtk"

但是,SimpleITK可以读取StructuredGrid,因此我尝试通过使用VTK进行读取和转换来解决此问题。

import vtk
reader = vtk.vtkGenericDataObjectReader() # Using generic to allow it to match either Unstructured or PolyData
reader.SetFileName(file_vtk)
reader.Update()
output = reader.GetOutput()

但是,从那时起,我尝试过的每种方法似乎都失败了。

建议的解决方案

转换为numpy,然后转换为sitk图片

我试图将其转换为一个numpy数组(),然后插入一个虚拟变量为1的常规网格以指定结构上的值。

from vtk.utils import numpy_support
import scipy.interpolate
import numpy as np

nparray = numpy_support.vtk_to_numpy(output.GetPointData().GetArray(0))

output_bounds = output.GetBounds()
x_grid = range(math.floor(output_bounds[0]),math.ceil(output_bounds[1]),1)
y_grid = range(math.floor(output_bounds[2]),math.ceil(output_bounds[3]),1)
z_grid = range(math.floor(output_bounds[4]),math.ceil(output_bounds[5]),1)
grid = list()
for x in x_grid:
   for y in y_grid:
      for z in z_grid:
         grid.append((x,y,z))
dummy = np.array([1 for i in range(nparray.shape[0])])
npgrid = scipy.interpolate.griddata(nparray,dummy,grid,fill_value=0)

npgrid.reshape(len(x_grid),len(y_grid),len(z_grid))
img = sitk.GetImageFromArray(npgrid)
sitk.WriteImage(img,file_out)

但是,当我将其加载到ParaView中时,将显示输出的边界框,但是输出的轮廓为空。

使用ShepardMethod

在将UnstructuredGrid转换为PolyData之后,我尝试使用内置的ShepardMethod进行插值(就像我通常看到的ShepardMethod应用于PolyData一样)

bounds = output.GetBounds()
spacings = [1.0,1.0,1.0] # arbitrary spacing
dimensions = [0,0,0]
for i,spacing in enumerate(spacings):
    dimensions[i] = int(math.ceil((bounds[i*2 + 1]-bounds[i*2])/spacing))

vtkPoints = vtk.vtkPoints()
for i in range(0,nparray.shape[0]):
   x=nparray[i,0]
   y=nparray[i,1]
   z=nparray[i,2]
   p=[x,y,z]
   vtkPoints.InsertNextPoint(p)
poly = vtk.vtkPolyData()
poly.SetPoints(vtkPoints)    

shepard = vtk.vtkShepardMethod()
shepard.SetInputData(poly)
shepard.SetSampleDimensions(dimensions)
shepard.SetModelBounds(output.GetBounds())
shepard.Update()
shepard_data = shepard.GetOutput().GetPointData().GetArray(0)

shepard_numpy = numpy_support.vtk_to_numpy(shepard_data)
shepard_numpy = shepard_numpy.reshape(dimensions[0],dimensions[1],dimensions[2])
shepard_img = sitk.GetImageFromArray(shepard_numpy)
sitk.WriteImage(shepard_img,file_out)

与上面的numpy一样,它在ParaView中提供了一个边界框。应用轮廓提供了两个三角形的结构,即几乎没有成功书写。另外,我尝试直接使用VTK编写输出。

shepard_data = shepard.GetOutput()
shepard_grid = vtk.vtkImageToStructuredGrid()
shepard_grid.SetInputData(shepard_data)
shepard_grid.Update()

writer = vtk.vtkStructuredGridWriter()
writer.SetFileName(file_out)
writer.SetInputData(shepard_grid.GetOutput())
writer.Write()

这产生了与以前相同的输出。

使用ProbeFilter

我尝试使用ProbeFilter(同时转换为numpy并直接编写)来进行上述操作。不幸的是,输出结果与上面相同。

mesh = vtk.vtkStructuredGrid()
mesh.SetDimensions(dimensions)

probe = vtk.vtkProbeFilter()
probe.SetInputData(mesh)
probe.SetSourceData(output)
probe.Update()
probe_out = probe.GetOutput()

writer = vtk.vtkStructuredGridWriter()
writer.SetFileName(file_out)
writer.SetInputData(probe.GetOutput())
writer.Write()

probe_data = probe.GetOutput().GetPointData().GetArray(0)
probe_numpy = numpy_support.vtk_to_numpy(probe_data)
probe_numpy = probe_numpy.reshape(dimensions[0],dimensions[1],dimensions[2])
probe_img = sitk.GetImageFromArray(probe_numpy)

sitk.WriteImage(probe_img,file_out)

但是,这似乎无法产生任何可行的输出(vtkStructuredGridWriter产生了一个空文件,而probe_numpy却没有了)。

更改ParaView输出

我的原始数据来自结构化的.vtk文件,该文件是使用ParaView打开的,然后进行裁剪以删除网格中不需要的结构。保存输出会保存一个unstructuredGrid,并且我一直无法弄清楚是否可以更改它,并且首先避免了这种混乱!

1 个答案:

答案 0 :(得分:0)

只需在ParaView中使用“使用数据集重新采样”过滤器即可。

  • 打开ParaView
  • 用您想要的几何图形打开一个StructuredGrid文件文件
  • 打开您的UnstructuredGrid文件
  • 添加“使用数据集重新采样”过滤器
  • 选择结构化数据作为源输入
  • 应用