VTK更改“GetImage”和“Update”

时间:2017-12-12 15:28:36

标签: python vtk dicom

我正在尝试使用Python进入3DSlicer中的扩展编程。 网上有a tutorial。不幸的是第三个示例脚本“HelloSharpen”存在问题。我做了完全相同的事情,但我得到了这个错误:

Traceback (most recent call last):
  File "C:/Users/johan/Desktop/HelloPythonSlicer4/helloPython/code/HelloSharpen.py", line 105, in onApply
    laplacian.SetInput(inputVolume.GetImageData())
AttributeError: 'vtkImagingGeneralPython.vtkImageLaplacian' object has no attribute 'SetInput'

我通过将laplacian.SetInput(inputVolume.GetImageData())更改为laplacian.SetInputData(inputVolume.GetImageData())来解决此问题,因为我读到他们在较新版本的VTK中更改了此内容。

但是,当我尝试运行时,会出现一个新错误:

Traceback (most recent call last):
  File "C:/Users/johan/Desktop/HelloPythonSlicer4/helloPython/code/HelloSharpen.py", line 107, in onApply
    laplacian.GetOutput().Update()
AttributeError: 'vtkCommonDataModelPython.vtkImageData' object has no attribute 'Update'

似乎laplacian.GetOutput().Update()导致了问题 我试图在互联网上找到一些东西,如果他们也在较新版本的VTK中改变了这一点,但我找不到任何东西。我试图将其更改为“UpdateData”,但这不起作用。 你知道他们是否也改变了这个,如果是的话,你知道我应该用这个替换它吗?

以下是“HelloSharpen”的完整代码:

from __main__ import vtk, qt, ctk, slicer

#
# HelloSharpen
#

class HelloSharpen:
  def __init__(self, parent):
    parent.title = "Hello Python Part D - Sharpen"
    parent.categories = ["Examples"]
    parent.dependencies = []
    parent.contributors = ["Jean-Christophe Fillion-Robin (Kitware)",
                           "Steve Pieper (Isomics)",
                           "Sonia Pujol (BWH)"] # replace with "Firstname Lastname (Org)"
    parent.helpText = """
    Example of scripted loadable extension for the HelloSharpen tutorial.
    """
    parent.acknowledgementText = """
    This file was originally developed by Jean-Christophe Fillion-Robin, Kitware Inc.,
Steve Pieper, Isomics, Inc., and Sonia Pujol, Brigham and Women's Hospital and was 
partially funded by NIH grant 3P41RR013218-12S1 (NAC) and is part of the National Alliance 
for Medical Image Computing (NA-MIC), funded by the National Institutes of Health through the 
NIH Roadmap for Medical Research, Grant U54 EB005149.""" # replace with organization, grant and thanks.
    self.parent = parent

#
# qHelloPythonWidget
#

class HelloSharpenWidget:
  def __init__(self, parent = None):
    if not parent:
      self.parent = slicer.qMRMLWidget()
      self.parent.setLayout(qt.QVBoxLayout())
      self.parent.setMRMLScene(slicer.mrmlScene)
    else:
      self.parent = parent
    self.layout = self.parent.layout()
    if not parent:
      self.setup()
      self.parent.show()

  def setup(self):
    # Collapsible button
    self.laplaceCollapsibleButton = ctk.ctkCollapsibleButton()
    self.laplaceCollapsibleButton.text = "Sharpen Operator"
    self.layout.addWidget(self.laplaceCollapsibleButton)

    # Layout within the laplace collapsible button
    self.laplaceFormLayout = qt.QFormLayout(self.laplaceCollapsibleButton)

    #
    # the volume selectors
    #
    self.inputFrame = qt.QFrame(self.laplaceCollapsibleButton)
    self.inputFrame.setLayout(qt.QHBoxLayout())
    self.laplaceFormLayout.addWidget(self.inputFrame)
    self.inputSelector = qt.QLabel("Input Volume: ", self.inputFrame)
    self.inputFrame.layout().addWidget(self.inputSelector)
    self.inputSelector = slicer.qMRMLNodeComboBox(self.inputFrame)
    self.inputSelector.nodeTypes = ( ("vtkMRMLScalarVolumeNode"), "" )
    self.inputSelector.addEnabled = False
    self.inputSelector.removeEnabled = False
    self.inputSelector.setMRMLScene( slicer.mrmlScene )
    self.inputFrame.layout().addWidget(self.inputSelector)

    self.outputFrame = qt.QFrame(self.laplaceCollapsibleButton)
    self.outputFrame.setLayout(qt.QHBoxLayout())
    self.laplaceFormLayout.addWidget(self.outputFrame)
    self.outputSelector = qt.QLabel("Output Volume: ", self.outputFrame)
    self.outputFrame.layout().addWidget(self.outputSelector)
    self.outputSelector = slicer.qMRMLNodeComboBox(self.outputFrame)
    self.outputSelector.nodeTypes = ( ("vtkMRMLScalarVolumeNode"), "" )
    self.outputSelector.setMRMLScene( slicer.mrmlScene )
    self.outputFrame.layout().addWidget(self.outputSelector)

    self.sharpen = qt.QCheckBox("Sharpen", self.laplaceCollapsibleButton)
    self.sharpen.toolTip = "When checked, subtract laplacian from input volume"
    self.sharpen.checked = True
    self.laplaceFormLayout.addWidget(self.sharpen) 


    # Apply button
    laplaceButton = qt.QPushButton("Apply")
    laplaceButton.toolTip = "Run the Laplace or Sharpen Operator."
    self.laplaceFormLayout.addWidget(laplaceButton)
    laplaceButton.connect('clicked(bool)', self.onApply)

    # Add vertical spacer
    self.layout.addStretch(1)

    # Set local var as instance attribute
    self.laplaceButton = laplaceButton

  def onApply(self):
    inputVolume = self.inputSelector.currentNode()
    outputVolume = self.outputSelector.currentNode()
    if not (inputVolume and outputVolume):
      qt.QMessageBox.critical(
          slicer.util.mainWindow(),
          'Sharpen', 'Input and output volumes are required for Laplacian')
      return
    # run the filter
    laplacian = vtk.vtkImageLaplacian()
    laplacian.SetInputData(inputVolume.GetImageData())
    laplacian.SetDimensionality(3)
    laplacian.GetOutput().Update()
    ijkToRAS = vtk.vtkMatrix4x4()
    inputVolume.GetIJKToRASMatrix(ijkToRAS)
    outputVolume.SetIJKToRASMatrix(ijkToRAS)
    outputVolume.SetAndObserveImageData(laplacian.GetOutput())

    # optionally subtract laplacian from original image
    if self.sharpen.checked:
      parameters = {}
      parameters['inputVolume1'] = inputVolume.GetID()
      parameters['inputVolume2'] = outputVolume.GetID()
      parameters['outputVolume'] = outputVolume.GetID()
      slicer.cli.run( slicer.modules.subtractscalarvolumes, None, parameters, wait_for_completion=True ) 

    selectionNode = slicer.app.applicationLogic().GetSelectionNode()
    selectionNode.SetReferenceActiveVolumeID(outputVolume.GetID())
    slicer.app.applicationLogic().PropagateVolumeSelection(0)

1 个答案:

答案 0 :(得分:2)

TL; DR laplacian.GetOutput().Update()更改为laplacian.Update()

<强>说明: 根据{{​​3}}链接,VTK 6中引入了一个重大变化。总之,较新版本的VTK将算法和数据分成两个不同的类层次结构。在较新版本的VTK中,Update()函数只能在从vtkAlgorithm类派生的对象上调用。您可以查看vtkImageLaplacian this的继承图,它确实来自vtkAlgorithm类。所以laplacian.Update()会奏效。

顾名思义vtkImageData是一个数据对象。 laplacian.GetOutput()会返回vtkImageData个对象,这就是为什么您无法调用Update()函数的原因,因此您会收到错误。