# Segmentation of Mitral valve

**URL:** <https://discourse.slicer.org/t/segmentation-of-mitral-valve/14598>\
**Category:** Feature requests\
**Tags:** segmentation, cine-mri\
**Created:** [November 14, 2020, 1:34pm UTC](https://discourse.slicer.org/t/segmentation-of-mitral-valve/14598 "2020-11-14T13:34:52Z")\
**Posts on this page:** 1\
**Showing post:** 10

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [November 26, 2020, 9:26pm UTC](https://discourse.slicer.org/t/segmentation-of-mitral-valve/14598/10 "2020-11-26T21:26:04Z")

</div>

You can reconstruct volume from these 2D ultrasound rotational sweep very similarly to the cine MRI above.

Result:

[![](https://img.youtube.com/vi/hIxr9OKBvQ8/maxresdefault.jpg "Reconstruct 3D or 4D cardiac volumes from sparse 2D frame set") ](https://www.youtube.com/watch?v=hIxr9OKBvQ8)

Script that reorganizes the volume into a sequence of frames, adds position&orientation information to each frame, and reconstructs a volume:

```python
# Input 3D volume that contains each frame as a slice
inputFrameVolumeNode = slicer.mrmlScene.GetFirstNodeByClass('vtkMRMLVolumeNode')
imageSpacingMm = 0.2 # this needs to be replaced with the actual spacing
outputSpacingMm = imageSpacingMm * 1.0 # Make the reconstructed volume spacing larger to reduce memory usage and make computations faster

# Get volume size
inputFrameVolume = inputFrameVolumeNode.GetImageData()
extent = inputFrameVolume.GetExtent()
numberOfFrames = extent[5]-extent[4]+1

# Set up frame geometry and rotation
centerOfRotationIJK = [(extent[0]+extent[1])/2.0, extent[2], 0]
rotationAxis = [0, 1, 0]
rotationDegreesPerFrame = 180.0/numberOfFrames

# Convert RGB/RGBA volume to grayscale volume
if inputFrameVolume.GetNumberOfScalarComponents() > 1:
    componentToExtract = 0
    print(f"Using scalar component {componentToExtract} of the image")
    extract = vtk.vtkImageExtractComponents()
    extract.SetInputData(inputFrameVolume)
    extract.SetComponents(componentToExtract)
    extract.Update()
    inputFrameVolume = extract.GetOutput()

# Create an image sequence that contains the frames as a time sequence
# and also contains position/orientation for each frame.
outputSequenceNode = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLSequenceNode", inputFrameVolumeNode.GetName()+"_frames")
outputSequenceNode.SetIndexName("frame")
outputSequenceNode.SetIndexUnit("")

# This temporary node will be used to add frames to the image sequence
tempFrameVolumeNode = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLScalarVolumeNode")

for frameIndex in range(numberOfFrames):
    # set current image from multiframe
    crop = vtk.vtkImageClip()
    crop.SetInputData(inputFrameVolume)
    crop.SetOutputWholeExtent(extent[0], extent[1], extent[2], extent[3], extent[4] + frameIndex, extent[4] + frameIndex)
    crop.ClipDataOn()
    crop.Update()
    croppedOutput = crop.GetOutput()
    croppedOutput.SetExtent(extent[0], extent[1], extent[2], extent[3], 0, 0)
    croppedOutput.SetOrigin(0.0, 0.0, 0.0)
    tempFrameVolumeNode.SetAndObserveImageData(croppedOutput)
    # set current transform
    ijkToRasTransform = vtk.vtkTransform()
    ijkToRasTransform.Scale(imageSpacingMm, imageSpacingMm, imageSpacingMm)
    ijkToRasTransform.RotateWXYZ(frameIndex * rotationDegreesPerFrame, *rotationAxis)
    ijkToRasTransform.Translate(-centerOfRotationIJK[0], -centerOfRotationIJK[1], -centerOfRotationIJK[2])
    tempFrameVolumeNode.SetIJKToRASMatrix(ijkToRasTransform.GetMatrix())
    # add to sequence
    added = outputSequenceNode.SetDataNodeAtValue(tempFrameVolumeNode, str(frameIndex))

slicer.mrmlScene.RemoveNode(tempFrameVolumeNode)

# Create a sequence browser node for the reconstructed volume sequence
outputSequenceBrowserNode = slicer.mrmlScene.AddNewNodeByClass(
    'vtkMRMLSequenceBrowserNode', outputSequenceNode.GetName() + '_browser')
outputSequenceBrowserNode.AddSynchronizedSequenceNode(outputSequenceNode)
slicer.modules.sequences.logic().UpdateAllProxyNodes() # ensure that proxy node is created
outputSequenceProxyNode = outputSequenceBrowserNode.GetProxyNode(outputSequenceNode)
slicer.util.setSliceViewerLayers(background=outputSequenceProxyNode)
slicer.modules.sequences.showSequenceBrowser(outputSequenceBrowserNode)

# Make slice view move with the image (just for visualization)
driver = slicer.modules.volumereslicedriver.logic()
redSliceNode = slicer.util.getFirstNodeByClassByName("vtkMRMLSliceNode", "Red")
driver.SetModeForSlice(driver.MODE_TRANSVERSE, redSliceNode)
driver.SetDriverForSlice(outputSequenceProxyNode.GetID(), redSliceNode)

# Reconstruct
volumeReconstructionNode = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLVolumeReconstructionNode")
volumeReconstructionNode.SetAndObserveInputSequenceBrowserNode(outputSequenceBrowserNode)
volumeReconstructionNode.SetAndObserveInputVolumeNode(outputSequenceProxyNode)
volumeReconstructionNode.SetOutputSpacing(outputSpacingMm, outputSpacingMm, outputSpacingMm)
volumeReconstructionNode.SetFillHoles(True)
slicer.modules.volumereconstruction.logic().ReconstructVolumeFromSequence(volumeReconstructionNode)
reconstructedVolume = volumeReconstructionNode.GetOutputVolumeNode()
reconstructedVolume.SetName(outputSequenceProxyNode.GetName()+"_recon")
roiNode = volumeReconstructionNode.GetInputROINode()
# Cleanup
slicer.mrmlScene.RemoveNode(volumeReconstructionNode)
# Show reconstruction result
roiNode.SetDisplayVisibility(False)
slicer.util.setSliceViewerLayers(background=reconstructedVolume,fit=True)

```

---

_[View the full topic](https://discourse.slicer.org/t/segmentation-of-mitral-valve/14598)._
