hellow, everyone.
i want to creat a segment from a numpy array. and i found the python code in script repository as following.
volumeNode = getNode('MRHead')
segmentationNode = getNode('Segmentation')
segmentId = segmentationNode.GetSegmentation().GetSegmentIdBySegmentName('Segment_1')
# Get segment as numpy array
segmentArray = slicer.util.arrayFromSegmentBinaryLabelmap(segmentationNode, segmentId, volumeNode)
# Modify the segmentation
segmentArray[:] = 0 # clear the segmentation
segmentArray[ slicer.util.arrayFromVolume(volumeNode) > 80 ] = 1 # create segment by simple thresholding of an image
segmentArray[20:80, 40:90, 30:70] = 1 # fill a rectangular region using numpy indexing
slicer.util.updateSegmentBinaryLabelmapFromArray(segmentArray, segmentationNode, segmentId, volumeNode)
in my own extension, the code line “volumeNode = getNode(‘MRHead’)” was be replaced by a qMRMLNodeCombobox in the nodetypes called “vtkMRMLScalarVolumeNode“.
the code line “segmentationNode = getNode(‘Segmentation’)“ was be replaced by a qMRMLNodeCombobox in the nodetypes called “vtkMRMLSegmentationNode“.
and i convert the “inputSelector“ and “inputsegmentation“ into def process as following.
def onApplyButton(self) -> None: """Run processing when user clicks "Apply" button.""" with slicer.util.tryWithErrorDisplay(\_("Failed to compute results."), waitCursor=True): \# Compute output self.logic.process(self.ui.inputSelector.currentNode(), self.ui.imageThresholdSliderWidget.value, self.ui.inputlowerpoint.currentNode(), self.ui.inputmidpoint.currentNode(), self.ui.inputupperpoint.currentNode(), self.ui.inputsegmentation.currentNode())
class cutcalciLogic(ScriptedLoadableModuleLogic):
"""This class should implement all the actual computation done by your module. The interface should be such that other python code can import this class and make use of the functionality without requiring an instance of the Widget. Uses ScriptedLoadableModuleLogic base class, available at: https://github.com/Slicer/Slicer/blob/main/Base/Python/slicer/ScriptedLoadableModule.py """ def \__init_\_(self) -> None: """Called when the logic class is instantiated. Can be used for initializing member variables.""" ScriptedLoadableModuleLogic.\__init_\_(self) def getParameterNode(self): return cutcalciParameterNode(super().getParameterNode()) def getFiducialKJI(self, inputpoint, volume): def get_vascular_up2low(self, image, upperpoint, lowerpoint, CT_value): def get_vascular_low2up(self, image, lowerpoint, upperpoint, CT_value): def check_vascular(self, vascular_array, lowerpoint): def get_vascular(self, image, upperpoint, midpoint, lowerpoint): vascular_array= self.get_vascular_up2low(image, upperpoint, lowerpoint, CT_value= 130) while self.check_vascular(vascular_array, lowerpoint)==0: vascular_array_1= self.get_vascular_low2up(image, midpoint, upperpoint) vascular_array_2= self.get_vascular_up2low(image, midpoint, lowerpoint) vascular_array= vascular_array+ vascular_array_1+ vascular_array_2 return vascular_array def process(self, inputVolume: vtkMRMLScalarVolumeNode, imageThreshold: float, inputlowerpoint, inputmidpoint, inputupperpoint, inputsegmentation, showResult: bool = True) -> None: if not inputVolume: raise ValueError("Input volume is invalid") lowerpoint= self.getFiducialKJI(inputlowerpoint, inputVolume) midpoint= self.getFiducialKJI(inputmidpoint, inputVolume) upperpoint= self.getFiducialKJI(inputupperpoint, inputVolume) image_array= slicer.util.arrayFromVolume(inputVolume) #vascular_array= self.get_vascular(image_array,upperpoint, midpoint, lowerpoint) segmentId = inputsegmentation.GetSegmentation().GetSegmentIdBySegmentName('Segment_1') print(lowerpoint) \# Get segment as numpy array segmentArray = slicer.util.arrayFromSegmentBinaryLabelmap(inputsegmentation, segmentId, inputVolume) **#there is an error in this code line** \# Modify the segmentation #segmentArray\[:\] = 0 # clear the segmentation #segmentArray\[ slicer.util.arrayFromVolume(inputVolume) > 80 \] = 1 # create segment by simple thresholding of an image #segmentArray\[20:80, 40:90, 30:70\] = 1 # fill a rectangular region using numpy indexing #slicer.util.updateSegmentBinaryLabelmapFromArray(segmentArray, inputsegmentation, segmentId, inputVolume)
and when i reload and apply this extension.
3D slicer tell me there is an error.
Traceback (most recent call last):
File “D:\program_file\Slicer 5.6.2\bin\Python\slicer\util.py”, line 3255, in tryWithErrorDisplay
yield
File “D:/program_file/Slicer 5.6.2/cutcalci/cutcalci/cutcalci.py”, line 245, in onApplyButton
self.logic.process(self.ui.inputSelector.currentNode(), self.ui.imageThresholdSliderWidget.value,
File “D:/program_file/Slicer 5.6.2/cutcalci/cutcalci/cutcalci.py”, line 423, in processGet segment as numpy array
File “D:\program_file\Slicer 5.6.2\bin\Python\slicer\util.py”, line 2138, in arrayFromSegmentBinaryLabelmap
narray = slicer.util.arrayFromVolume(labelmapVolumeNode)
File “D:\program_file\Slicer 5.6.2\bin\Python\slicer\util.py”, line 1742, in arrayFromVolume
narray = vtk.util.numpy_support.vtk_to_numpy(vimage.GetPointData().GetScalars()).reshape(nshape)
File “D:\program_file\Slicer 5.6.2\bin\Lib\site-packages\vtkmodules\util\numpy_support.py”, line 215, in vtk_to_numpy
typ = vtk_array.GetDataType()
AttributeError: ‘NoneType’ object has no attribute ‘GetDataType’
i’m sure that it is the code line “segmentArray = slicer.util.arrayFromSegmentBinaryLabelmap(inputsegmentation, segmentId, inputVolume) “ which causes this error. because there the KJI coordinate of lowerpoint can be printed in python console.
so, my problem is how to create a segment from numpy array successfully?




