首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >VTK: 3D矩阵的体积尺寸错误

VTK: 3D矩阵的体积尺寸错误
EN

Stack Overflow用户
提问于 2017-08-18 18:32:22
回答 1查看 397关注 0票数 1

我想将一个3-D矩阵( X*Y分辨率的Z切片)可视化为经典的3-d体素。我在MATLAB中生成矩阵,然后将其导入Python。然后,按照代码herehere,我提出了这个解决方案。在这个演示中,我使用了一个矩阵,它应该生成一个包含4个2*3体素的切片的3D图像。

在MATLAB中

代码语言:javascript
运行
复制
C(:,:,1) =

   5   5   5
   5   5   5


C(:,:,2) =

   15   15   15
   15   15   15


C(:,:,3) =

   25   25   25
   25   25   25


C(:,:,4) =

   35   35   35
   35   35   35

在python中:

代码语言:javascript
运行
复制
Cmat = spio.loadmat('CMAT.mat')['C']
>>>print Cmat.shape
(2, 3, 4)

Cmat = np.ascontiguousarray(Cmat.T)
>>>print Cmat
[[[ 5  5]
  [ 5  5]
  [ 5  5]]

 [[15 15]
  [15 15]
  [15 15]]


 [[25 25]
  [25 25]
  [25 25]]

 [[35 35]
  [35 35]
  [35 35]]]

下面的代码会生成这个图像(为了方便,我对它进行了旋转):

得到的形状不是2*3*4,切片的大小也不一样,我做错了什么?我试着调整

代码语言:javascript
运行
复制
dataImporter.SetDataExtent
dataImporter.SetWholeExtent
dataImporter.SetDataSpacing

如果我改变dataImporter.SetDataExtent(0,1,0,1,1)dataImporter.SetWholeExtent(0,1,0,1,1)

我如期获得了一个2x2x2的立方体,但如果我调用

代码语言:javascript
运行
复制
dataImporter.SetDataExtent(0, 1, 0, 2, 0, 1)
dataImporter.SetWholeExtent(0, 1, 0, 2, 0, 1)

我得到了一个2x4x2的实心(而不是2x3x2)

如果我打电话给

代码语言:javascript
运行
复制
dataImporter.SetDataExtent(0, 1, 0, 10, 0, 2)
dataImporter.SetWholeExtent(0, 1, 0, 10, 0, 2)

我得到了一个2x20x4的实心

这似乎与setDataExtent和SetWholeExtent的文档相矛盾:

*数据的维度必须等于(extent1-extent+1) * (extent4-extent3+1) * (extent5-DataExtent4+1).例如,对于2D图像,使用(0,width-1,0,height-1,0,0).*

有什么想法吗?

MATLAB下的完整代码:

代码语言:javascript
运行
复制
C = zeros(2,3,4)
C(:,:,1) = 5;
C(:,:,2) = 15;
C(:,:,3) = 25;
C(:,:,4) = 35;

save Cmat C

Python:

代码语言:javascript
运行
复制
import vtk
from numpy import *
import numpy as np
import scipy.io as spio

data_matrix = zeros([2, 3, 4], dtype=uint8)

Cmat = spio.loadmat('CMAT.mat')['C']
Cmat = np.ascontiguousarray(Cmat.T)
print Cmat
data_matrix = Cmat
# For VTK to be able to use the data, it must be stored as a VTK-image. This can be done by the vtkImageImport-class which
# imports raw data and stores it.
dataImporter = vtk.vtkImageImport()
# The previously created array is converted to a string of chars and imported.
data_string = data_matrix.tostring()
dataImporter.CopyImportVoidPointer(data_string, len(data_string))
# The type of the newly imported data is set to unsigned char (uint8)
dataImporter.SetDataScalarTypeToUnsignedChar()
# Because the data that is imported only contains an intensity value (it isn't RGB-coded or something similar), the importer
# must be told this is the case.
dataImporter.SetNumberOfScalarComponents(1)
# The following two functions describe how the data is stored and the dimensions of the array it is stored in.
dataImporter.SetDataExtent(0, 1, 0, 2, 0, 3)
dataImporter.SetWholeExtent(0, 1, 0, 2, 0, 3)

# This class stores color data and can create color tables from a few color points. For this demo, we want the three cubes
# to be of the colors red green and blue.
colorFunc = vtk.vtkColorTransferFunction()
colorFunc.AddRGBPoint(5, 1, 0.0, 0.0)  # Red
colorFunc.AddRGBPoint(15, 0.0, 1, 0.0) # Green
colorFunc.AddRGBPoint(25, 0.0, 0.0, 1) # Blue
colorFunc.AddRGBPoint(35, 0.0, 0, 0.0) # Black

# The previous two classes stored properties. Because we want to apply these properties to the volume we want to render,
# we have to store them in a class that stores volume properties.
volumeProperty = vtk.vtkVolumeProperty()
volumeProperty.SetColor(colorFunc)

volumeMapper = vtk.vtkOpenGLGPUVolumeRayCastMapper()
volumeMapper.SetInputConnection(dataImporter.GetOutputPort())

# The class vtkVolume is used to pair the previously declared volume as well as the properties to be used when rendering that volume.
volume = vtk.vtkVolume()
volume.SetMapper(volumeMapper)
volume.SetProperty(volumeProperty)

# With almost everything else ready, its time to initialize the renderer and window, as well as creating a method for exiting the application
renderer = vtk.vtkRenderer()
renderWin = vtk.vtkRenderWindow()
renderWin.AddRenderer(renderer)
renderInteractor = vtk.vtkRenderWindowInteractor()
renderInteractor.SetRenderWindow(renderWin)

# We add the volume to the renderer ...
renderer.AddVolume(volume)
# ... set background color to white ...
renderer.SetBackground(1, 1, 1)
# ... and set window size.
renderWin.SetSize(400, 400)


# A simple function to be called when the user decides to quit the application.
def exitCheck(obj, event):
    if obj.GetEventPending() != 0:
        obj.SetAbortRender(1)


# Tell the application to use the function as an exit check.
renderWin.AddObserver("AbortCheckEvent", exitCheck)

renderInteractor.Initialize()
# Because nothing will be rendered without any input, we order the first render manually before control is handed over to the main-loop.
renderWin.Render()
renderInteractor.Start()

我唯一的假设是,这些体素不是立方体,但它们的一个维度是其他维度的两倍。但仍然不能解释为什么4个切片中只有2个受此影响。

更新:似乎只有第一个和最后一个切片的大小是其他切片的一半。对于20x30x40矩阵,可以看出第一个和最后一个切片比其他切片更薄。

EN

回答 1

Stack Overflow用户

发布于 2020-05-13 17:16:25

这是一个古老的问题,也许你已经找到了答案。

我的第一个猜测是,数据的存储方式和预期的读取方式之间存在某种不一致。可能,MATLAB将3D矩阵存储为以列为主的数据结构,而VTK正在将此类数据恢复为以行为主的数据。另一种可能是,当读取文件并获得2x20x4实体时,尺寸将被交换。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45754524

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档