the speed of vtk.vtkMarchingCubes is slow, how to speed it up?

Currently, I want to extract the isosurface from a volume image, and I use vtk.vtkMarchingCubes to implement it. Moreover, I want to change the iso-value by mouse. I have implement the code as following:

import vtk, sys

from vtk.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor

from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *

val = [1000, None]
def setVal(v):
    val[0] = v
    val[1].SetValue(v)

class MyInteractor(vtk.vtkInteractorStyleTrackballCamera):

    def __init__(self):
        self.AddObserver("LeftButtonPressEvent", self.leftButtonPressEvent)
        self.AddObserver("LeftButtonReleaseEvent", self.leftButtonReleaseEvent)
        self.AddObserver("MouseMoveEvent", self.leftButtonMoveEvent)
        self.btnPress = False
        self.lastPoint = [0, 0]

    def leftButtonPressEvent(self, obj, event):
        self.btnPress = True
        pos = self.GetInteractor().GetEventPosition()
        self.lastPoint = [pos[0], pos[1]]

    def leftButtonReleaseEvent(self, obj, event):
        self.btnPress = False

    def leftButtonMoveEvent(self, obj, event):
        if self.btnPress == True:
            curPos = self.GetInteractor().GetEventPosition()
            dx = curPos[0] - self.lastPoint[0]
            dy = curPos[1] - self.lastPoint[1]

            isoValue = val[0]
            if abs(dx) > abs(dy):
                isoValue += dx
            else:
                isoValue += dy
            setVal(isoValue)

            self.lastPoint = [curPos[0], curPos[1]]
        else:
            super().OnMouseMove()

class MainWindow(QMainWindow):

    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent=parent)

        self.frame = QFrame()

        self.vl = QVBoxLayout()
        self.vtkWidget = QVTKRenderWindowInteractor(self.frame)
        self.vl.addWidget(self.vtkWidget)

        self.ren = vtk.vtkRenderer()
        self.vtkWidget.GetRenderWindow().AddRenderer(self.ren)
        self.iren = self.vtkWidget.GetRenderWindow().GetInteractor()

        style = MyInteractor()
        self.iren.SetInteractorStyle(style)
        reader = vtk.vtkDICOMImageReader()
        reader.SetDirectoryName("C:\\Users\\MLoong\\Desktop\\Angiograph Data\\Chang Cheng\\TOF")
        reader.Update()

        surface = vtk.vtkMarchingCubes()
        surface.SetInputConnection(reader.GetOutputPort())
        surface.ComputeNormalsOn()
        surface.SetValue(0, 300)
        surface.Update()
        self.surface = surface

        # Create a mapper
        mapper = vtk.vtkPolyDataMapper()
        mapper.SetInputConnection(surface.GetOutputPort())
        mapper.ScalarVisibilityOff()

        # Create an actor
        actor = vtk.vtkActor()
        actor.SetMapper(mapper)
        actor.GetProperty().SetColor(1, 1, 1)
        actor.GetProperty().ShadingOff()

        self.ren.AddActor(actor)

        self.ren.ResetCamera()

        self.frame.setLayout(self.vl)
        self.setCentralWidget(self.frame)

        self.show()
        self.iren.Initialize()

    def SetValue(self, val):
        print(val)
        self.surface.SetValue(0, val)
        self.surface.Update()
        self.vtkWidget.GetRenderWindow().Render()

if __name__ == "__main__":
    app = QApplication(sys.argv)

    window = MainWindow()
    val[1] = window

    sys.exit(app.exec_())

This code has no bug after provide a correct image in reader.SetDirectoryName(“path”). I can change the iso-value by left mouse press and move. But the problem is that the speed is slow. Does anybody has any suggestion to speed it up?

You can try vtkFlyingEdges3D filter instead. vtkFlyingEdges3D is about a magnitude faster than marching cubes if you build VTK with TBB SMP backend.

Thanks. vtkFlyingEdges3D is much faster than vtkMarchingCube. In addition, can GPU be used to speed up isosurface extraction?

If you just want to render the isosurface then you can use GPU raycasting directly on the image data. You will probably get much higher quality results at very high frame rates (you should be able to get 100+ FPS on a 512^3 volume with recent GPU).

If rendering is not enough but you also need to process the isosurface then extracting it on the GPU will not likely to get you much farther, since you need to transfer data to/from GPU, perform other time consuming operations, etc., which will overall diminish any computation time advantage.