# using VTK to get a 3D .obj file from DICOM files

**URL:** https://discourse.vtk.org/t/using-vtk-to-get-a-3d-obj-file-from-dicom-files/14318
**Category:** Support
**Created:** [July 29, 2024, 4:15pm UTC](https://discourse.vtk.org/t/using-vtk-to-get-a-3d-obj-file-from-dicom-files/14318 "2024-07-29T16:15:08Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![SaneSoup](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/s/53a042/32.png) [@SaneSoup](https://discourse.vtk.org/u/SaneSoup)
#### Post date: [July 29, 2024, 4:15pm UTC](https://discourse.vtk.org/t/using-vtk-to-get-a-3d-obj-file-from-dicom-files/14318/1 "2024-07-29T16:15:08Z")

</div>

Hello everyone,

my goal is it to have a python code that reads DICOM files and then turns them into a 3D .obj file, the problem is that I don’t know how the values of vtkMarchingCubes work because I can’t seem to get all the data but only parts of it. So to say, sometimes I only get the Skull as a model or just the skin, the important thing for me would be the brain tho.

I have tried to render everything in python before, where nothing went missing and at least this part worked well but because of other problems with vtk not liking tk inter I made up my mind to use Godot for the UI stuff. Now using Godot I need the before mentioned .obj file to kind of import it into the 3D environment as a node or something like that.

(I’m a Godot noob so I also have no idea on how to implement the .obj but first I gotta find out how to solve my python problem)

My first full python try looked like this (the # are in german):

```auto
import tkinter as tk
from tkinter import filedialog
import vtk

class DICOMViewer:
    def __init__ (self, root):
        self.root = root
        self.root.title("DICOM Viewer")

        # Initialisieren Sie die VTK-Variable
        self.vtk_window = None

        # Menü erstellen
        menu_bar = tk.Menu(root)
        root.config(menu=menu_bar)

        file_menu = tk.Menu(menu_bar, tearoff=0)
        menu_bar.add_cascade(label="File", menu=file_menu)
        file_menu.add_command(label="Open DICOM", command=self.open_dicom_folder)

    def open_dicom_folder(self):
        folder_path = filedialog.askdirectory(title="Open DICOM Folder")

        if folder_path:
            # Verzögere das Laden der VTK-Operationen im Hauptthread
            self.root.after(0, self.load_dicom_and_render, folder_path)

    def load_dicom_and_render(self, folder_path):
        # Laden aller DICOM-Dateien im ausgewählten Ordner
        dicom_reader = vtk.vtkDICOMImageReader()
        dicom_reader.SetDirectoryName(folder_path)
        dicom_reader.Update()
        dicom_volume = dicom_reader.GetOutput()

        # 3D-Rekonstruktion
        volume_mapper = vtk.vtkGPUVolumeRayCastMapper()
        volume_mapper.SetInputData(dicom_volume)

        volume_property = vtk.vtkVolumeProperty()
        volume_property.ShadeOn()
        volume_property.SetInterpolationTypeToLinear()

        volume_color = vtk.vtkColorTransferFunction()
        volume_color.AddRGBPoint(-1024, 0.0, 0.0, 0.0)
        volume_color.AddRGBPoint(0, 1.0, 0.5, 0.5)
        volume_color.AddRGBPoint(3071, 1.0, 1.0, 1.0)

        volume_scalar_opacity = vtk.vtkPiecewiseFunction()
        volume_scalar_opacity.AddPoint(-1024, 0.0)
        volume_scalar_opacity.AddPoint(0, 0.2)
        volume_scalar_opacity.AddPoint(3071, 0.2)

        volume_property.SetColor(volume_color)
        volume_property.SetScalarOpacity(volume_scalar_opacity)

        volume_actor = vtk.vtkVolume()
        volume_actor.SetMapper(volume_mapper)
        volume_actor.SetProperty(volume_property)

        # Rendering
        renderer = vtk.vtkRenderer()
        renderer.SetBackground(0.0, 0.0, 0.0)

        render_window = vtk.vtkRenderWindow()
        render_window.SetWindowName("DICOM 3D Viewer")
        render_window.SetSize(self.root.winfo_screenwidth() // 2, self.root.winfo_screenheight())
        render_window.AddRenderer(renderer)

        interactor = vtk.vtkRenderWindowInteractor()
        interactor.SetRenderWindow(render_window)

        renderer.AddVolume(volume_actor)
        renderer.ResetCamera()

        # Interaktionsstil erstellen
        interactor_style = vtk.vtkInteractorStyleTrackballCamera()
        interactor.SetInteractorStyle(interactor_style)

        # Ändere die Position des VTK-Fensters
        self.root.update_idletasks()
        render_window.SetPosition(self.root.winfo_width(), 0)

        # Speichern Sie die Referenz auf das VTK-Fenster
        self.vtk_window = render_window

        # Starte die Interaktion
        interactor.Start()

if __name__ == " __main__":
    root = tk.Tk()
    app = DICOMViewer(root)

    # Setze die Tkinter-GUI auf die gesamte linke Seite
    root.geometry("{}x{}+0+0".format(root.winfo_screenwidth() // 2, root.winfo_screenheight()))

    root.mainloop()

```

my current attempt looks more like this:

```auto
import vtk

def load_dicom_series(a):
    reader = vtk.vtkDICOMImageReader()
    reader.SetDirectoryName(a)
    reader.Update()
    return reader

def create_3d_model(b):
    # Apply Marching Cubes to extract the surface
    marching_cubes = vtk.vtkMarchingCubes()
    marching_cubes.SetInputConnection(b.GetOutputPort())
    marching_cubes.SetValue(10, 1500) # Adjust this value to include more/less of the data
    marching_cubes.Update()
    return marching_cubes

def save_obj(c, d):
    # Convert to PolyData
    poly_data = d.GetOutput()

    # Write to OBJ file
    obj_writer = vtk.vtkOBJWriter()
    obj_writer.SetFileName(c)
    obj_writer.SetInputData(poly_data)
    obj_writer.Write()

# Pfad zur DICOM-Serie
dicom_path = 'C:\\Users\\User\\Desktop\\python\\privat\\Germanische\\Scans'
output_path = 'C:\\Users\\User\\Desktop\\model.obj'

# Laden der DICOM-Daten
dicom_reader = load_dicom_series(dicom_path)

# Erzeugung des 3D-Modells
e = create_3d_model(dicom_reader)

# Speichern des 3D-Modells in einer .obj-Datei
save_obj(output_path, e)

```

---

<div class="post-metadata">

### Author: ![rexthor](https://discourse.vtk.org/user_avatar/discourse.vtk.org/rexthor/32/6481_2.png) [@rexthor](https://discourse.vtk.org/u/rexthor)
#### Post date: [July 30, 2024, 6:07pm UTC](https://discourse.vtk.org/t/using-vtk-to-get-a-3d-obj-file-from-dicom-files/14318/2 "2024-07-30T18:07:48Z")

</div>

Have you tried to load your DICOM image into ParaView in order to figure out the filter settings manually? There are probably a few examples here in this site as well, such as [this one](https://discourse.vtk.org/t/extracting-isosurface-from-a-vtkimagedata/10502/9), or [this one](https://examples.vtk.org/site/Python/Visualization/IsosurfaceSampling/) or [this one](https://examples.vtk.org/site/Python/Modelling/MarchingCubes/).

---

<div class="post-metadata">

### Author: ![SaneSoup](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/s/53a042/32.png) [@SaneSoup](https://discourse.vtk.org/u/SaneSoup)
#### Post date: [July 30, 2024, 6:24pm UTC](https://discourse.vtk.org/t/using-vtk-to-get-a-3d-obj-file-from-dicom-files/14318/3 "2024-07-30T18:24:25Z")

</div>

Hey there,

what I’m trying to achieve doesn’t work with doing things manually.  
I tried to further explain my standpoint here [Render 3D DICOM object with marching cube? · Issue #1012 · Kitware/vtk-js · GitHub](https://github.com/Kitware/vtk-js/issues/1012)  
But instead of forming the .obj from the .vti files and then “importing” them into Godot I plan on getting them directly into Unity using this plugin [3dheart\_public / VtkToUnity · GitLab](https://gitlab.com/3dheart_public/vtktounity)  
However I have no clue on how Unity works and will try some things in the following days.  
(I also tried some Voxel plugin/addon for Godot to “import” the .vti files directly but without any luck so far ☹ )
