Commit 3e717c63 authored by David Gobbi's avatar David Gobbi

ENH: Add an example of how to use vtkImageReslice to display a 3D image

parent 28c17f83
......@@ -140,6 +140,7 @@ ELSE(VTK_BINARY_DIR)
MultiBlock/Cxx
GUI/Motif
DataManipulation/Cxx
ImageProcessing/Cxx
Medical/Cxx
Modelling/Cxx
Rendering/Cxx
......
PROJECT(ImageProcessing)
FIND_PACKAGE(VTK REQUIRED)
IF(NOT VTK_USE_RENDERING)
MESSAGE(FATAL_ERROR "Example ${PROJECT_NAME} requires VTK_USE_RENDERING.")
ENDIF(NOT VTK_USE_RENDERING)
INCLUDE(${VTK_USE_FILE})
ADD_EXECUTABLE(ImageSlicing ImageSlicing.cxx)
TARGET_LINK_LIBRARIES(ImageSlicing vtkRendering vtkImaging vtkIO)
/*=========================================================================
Program: Visualization Toolkit
Module: ImageSlicing.cxx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
//
// This example shows how to load a 3D image into VTK and then reformat
// that image into a different orientation for viewing. It uses
// vtkImageReslice for reformatting the image, and uses vtkImageActor
// and vtkInteractorStyleImage to display the image. This InteractorStyle
// forces the camera to stay perpendicular to the XY plane.
//
// Thanks to David Gobbi of Atamai Inc. for contributing this example.
//
#include "vtkImageReader2.h"
#include "vtkMatrix4x4.h"
#include "vtkImageReslice.h"
#include "vtkLookupTable.h"
#include "vtkImageMapToColors.h"
#include "vtkImageActor.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkInteractorStyleImage.h"
#include "vtkCommand.h"
#include "vtkImageData.h"
// The mouse motion callback, to turn "Slicing" on and off
class vtkImageInteractionCallback : public vtkCommand
{
public:
static vtkImageInteractionCallback *New() {
return new vtkImageInteractionCallback; };
vtkImageInteractionCallback() {
this->Slicing = 0;
this->ImageReslice = 0;
this->Interactor = 0; };
void SetImageReslice(vtkImageReslice *reslice) {
this->ImageReslice = reslice; };
vtkImageReslice *GetImageReslice() {
return this->ImageReslice; };
void SetInteractor(vtkRenderWindowInteractor *interactor) {
this->Interactor = interactor; };
vtkRenderWindowInteractor *GetInteractor() {
return this->Interactor; };
virtual void Execute(vtkObject *, unsigned long event, void *)
{
vtkRenderWindowInteractor *interactor = this->GetInteractor();
int lastPos[2];
interactor->GetLastEventPosition(lastPos);
int currPos[2];
interactor->GetEventPosition(currPos);
if (event == vtkCommand::LeftButtonPressEvent)
{
this->Slicing = 1;
}
else if (event == vtkCommand::LeftButtonReleaseEvent)
{
this->Slicing = 0;
}
else if (event == vtkCommand::MouseMoveEvent)
{
if (this->Slicing)
{
vtkImageReslice *reslice = this->ImageReslice;
// Increment slice position by deltaY of mouse
int deltaY = lastPos[1] - currPos[1];
reslice->GetOutput()->UpdateInformation();
double sliceSpacing = reslice->GetOutput()->GetSpacing()[2];
vtkMatrix4x4 *matrix = reslice->GetResliceAxes();
// move the center point that we are slicing through
double point[4];
double center[4];
point[0] = 0.0;
point[1] = 0.0;
point[2] = sliceSpacing * deltaY;
point[3] = 1.0;
matrix->MultiplyPoint(point, center);
matrix->SetElement(0, 3, center[0]);
matrix->SetElement(1, 3, center[1]);
matrix->SetElement(2, 3, center[2]);
interactor->Render();
}
else
{
vtkInteractorStyle *style = vtkInteractorStyle::SafeDownCast(
interactor->GetInteractorStyle());
if (style)
{
style->OnMouseMove();
}
}
}
};
private:
// Actions (slicing only, for now)
int Slicing;
// Pointer to vtkImageReslice
vtkImageReslice *ImageReslice;
// Pointer to the interactor
vtkRenderWindowInteractor *Interactor;
};
// The program entry point
int main (int argc, char **argv)
{
if (argc < 2)
{
cout << "Usage: " << argv[0] << " DATADIR/headsq/quarter" << endl;
return 1;
}
// Start by loading some data.
vtkImageReader2 *reader = vtkImageReader2::New();
reader->SetFilePrefix(argv[1]);
reader->SetDataExtent(0, 63, 0, 63, 1, 93);
reader->SetDataSpacing(3.2, 3.2, 1.5);
reader->SetDataOrigin(0.0, 0.0, 0.0);
reader->SetDataScalarTypeToUnsignedShort();
reader->UpdateWholeExtent();
// Calculate the center of the volume
reader->GetOutput()->UpdateInformation();
int extent[6];
double spacing[3];
double origin[3];
reader->GetOutput()->GetWholeExtent(extent);
reader->GetOutput()->GetSpacing(spacing);
reader->GetOutput()->GetOrigin(origin);
double center[3];
center[0] = origin[0] + spacing[0] * 0.5 * (extent[0] + extent[1]);
center[1] = origin[1] + spacing[1] * 0.5 * (extent[2] + extent[3]);
center[2] = origin[2] + spacing[2] * 0.5 * (extent[4] + extent[5]);
// Matrices for axial, coronal, sagittal, oblique view orientations
static double axialElements[16] = {
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1 };
static double coronalElements[16] = {
1, 0, 0, 0,
0, 0, 1, 0,
0,-1, 0, 0,
0, 0, 0, 1 };
static double sagittalElements[16] = {
0, 0,-1, 0,
1, 0, 0, 0,
0,-1, 0, 0,
0, 0, 0, 1 };
static double obliqueElements[16] = {
1, 0, 0, 0,
0, 0.866025, -0.5, 0,
0, 0.5, 0.866025, 0,
0, 0, 0, 1 };
// Set the slice orientation
vtkMatrix4x4 *resliceAxes = vtkMatrix4x4::New();
resliceAxes->DeepCopy(sagittalElements);
// Set the point through which to slice
resliceAxes->SetElement(0, 3, center[0]);
resliceAxes->SetElement(1, 3, center[1]);
resliceAxes->SetElement(2, 3, center[2]);
// Extract a slice in the desired orientation
vtkImageReslice *reslice = vtkImageReslice::New();
reslice->SetInputConnection(reader->GetOutputPort());
reslice->SetOutputDimensionality(2);
reslice->SetResliceAxes(resliceAxes);
reslice->SetInterpolationModeToLinear();
// Create a greyscale lookup table
vtkLookupTable *table = vtkLookupTable::New();
table->SetRange(0, 2000); // image intensity range
table->SetValueRange(0.0, 1.0); // from black to white
table->SetSaturationRange(0.0, 0.0); // no color saturation
table->SetRampToLinear();
table->Build();
// Map the image through the lookup table
vtkImageMapToColors *color = vtkImageMapToColors::New();
color->SetLookupTable(table);
color->SetInputConnection(reslice->GetOutputPort());
// Display the image
vtkImageActor *actor = vtkImageActor::New();
actor->SetInput(color->GetOutput());
vtkRenderer *renderer = vtkRenderer::New();
renderer->AddActor(actor);
vtkRenderWindow *window = vtkRenderWindow::New();
window->AddRenderer(renderer);
// Set up the interaction
vtkInteractorStyleImage *imageStyle = vtkInteractorStyleImage::New();
vtkRenderWindowInteractor *interactor = vtkRenderWindowInteractor::New();
interactor->SetInteractorStyle(imageStyle);
window->SetInteractor(interactor);
window->Render();
vtkImageInteractionCallback *callback = vtkImageInteractionCallback::New();
callback->SetImageReslice(reslice);
callback->SetInteractor(interactor);
imageStyle->AddObserver(vtkCommand::MouseMoveEvent, callback);
imageStyle->AddObserver(vtkCommand::LeftButtonPressEvent, callback);
imageStyle->AddObserver(vtkCommand::LeftButtonReleaseEvent, callback);
// Start interaction
// The Start() method doesn't return until the window is closed by the user
interactor->Start();
// Clean up
callback->Delete();
interactor->Delete();
imageStyle->Delete();
window->Delete();
renderer->Delete();
actor->Delete();
reslice->Delete();
resliceAxes->Delete();
color->Delete();
table->Delete();
reader->Delete();
}
#!/usr/bin/env python
# This example shows how to load a 3D image into VTK and then reformat
# that image into a different orientation for viewing. It uses
# vtkImageReslice for reformatting the image, and uses vtkImageActor
# and vtkInteractorStyleImage to display the image. This InteractorStyle
# forces the camera to stay perpendicular to the XY plane.
import vtk
from vtk.util.misc import vtkGetDataRoot
VTK_DATA_ROOT = vtkGetDataRoot()
# Start by loading some data.
reader = vtk.vtkImageReader2()
reader.SetFilePrefix(VTK_DATA_ROOT + "/Data/headsq/quarter")
reader.SetDataExtent(0, 63, 0, 63, 1, 93)
reader.SetDataSpacing(3.2, 3.2, 1.5)
reader.SetDataOrigin(0.0, 0.0, 0.0)
reader.SetDataScalarTypeToUnsignedShort()
reader.UpdateWholeExtent()
# Calculate the center of the volume
reader.GetOutput().UpdateInformation()
(xMin, xMax, yMin, yMax, zMin, zMax) = reader.GetOutput().GetWholeExtent()
(xSpacing, ySpacing, zSpacing) = reader.GetOutput().GetSpacing()
(x0, y0, z0) = reader.GetOutput().GetOrigin()
center = [x0 + xSpacing * 0.5 * (xMin + xMax),
y0 + ySpacing * 0.5 * (yMin + yMax),
z0 + zSpacing * 0.5 * (zMin + zMax)]
# Matrices for axial, coronal, sagittal, oblique view orientations
axial = vtk.vtkMatrix4x4()
axial.DeepCopy((1, 0, 0, center[0],
0, 1, 0, center[1],
0, 0, 1, center[2],
0, 0, 0, 1))
coronal = vtk.vtkMatrix4x4()
coronal.DeepCopy((1, 0, 0, center[0],
0, 0, 1, center[1],
0,-1, 0, center[2],
0, 0, 0, 1))
sagittal = vtk.vtkMatrix4x4()
sagittal.DeepCopy((0, 0,-1, center[0],
1, 0, 0, center[1],
0,-1, 0, center[2],
0, 0, 0, 1))
oblique = vtk.vtkMatrix4x4()
oblique.DeepCopy((1, 0, 0, center[0],
0, 0.866025, -0.5, center[1],
0, 0.5, 0.866025, center[2],
0, 0, 0, 1))
# Extract a slice in the desired orientation
reslice = vtk.vtkImageReslice()
reslice.SetInputConnection(reader.GetOutputPort())
reslice.SetOutputDimensionality(2)
reslice.SetResliceAxes(sagittal)
reslice.SetInterpolationModeToLinear()
# Create a greyscale lookup table
table = vtk.vtkLookupTable()
table.SetRange(0, 2000) # image intensity range
table.SetValueRange(0.0, 1.0) # from black to white
table.SetSaturationRange(0.0, 0.0) # no color saturation
table.SetRampToLinear()
table.Build()
# Map the image through the lookup table
color = vtk.vtkImageMapToColors()
color.SetLookupTable(table)
color.SetInputConnection(reslice.GetOutputPort())
# Display the image
actor = vtk.vtkImageActor()
actor.SetInput(color.GetOutput())
renderer = vtk.vtkRenderer()
renderer.AddActor(actor)
window = vtk.vtkRenderWindow()
window.AddRenderer(renderer)
# Set up the interaction
interactorStyle = vtk.vtkInteractorStyleImage()
interactor = vtk.vtkRenderWindowInteractor()
interactor.SetInteractorStyle(interactorStyle)
window.SetInteractor(interactor)
window.Render()
# Create callbacks for slicing the image
actions = {}
actions["Slicing"] = 0
def ButtonCallback(obj, event):
if event == "LeftButtonPressEvent":
actions["Slicing"] = 1
else:
actions["Slicing"] = 0
def MouseMoveCallback(obj, event):
(lastX, lastY) = interactor.GetLastEventPosition()
(mouseX, mouseY) = interactor.GetEventPosition()
if actions["Slicing"] == 1:
deltaY = mouseY - lastY
reslice.GetOutput().UpdateInformation()
sliceSpacing = reslice.GetOutput().GetSpacing()[2]
matrix = reslice.GetResliceAxes()
# move the center point that we are slicing through
center = matrix.MultiplyPoint((0, 0, sliceSpacing*deltaY, 1))
matrix.SetElement(0, 3, center[0])
matrix.SetElement(1, 3, center[1])
matrix.SetElement(2, 3, center[2])
window.Render()
else:
interactorStyle.OnMouseMove()
interactorStyle.AddObserver("MouseMoveEvent", MouseMoveCallback)
interactorStyle.AddObserver("LeftButtonPressEvent", ButtonCallback)
interactorStyle.AddObserver("LeftButtonReleaseEvent", ButtonCallback)
# Start interaction
interactor.Start()
package require vtk
package require vtkinteraction
# This example shows how to load a 3D image into VTK and then reformat
# that image into a different orientation for viewing. It uses
# vtkImageReslice for reformatting the image, and uses vtkImageActor
# and vtkInteractorStyleImage to display the image. This InteractorStyle
# forces the camera to stay perpendicular to the XY plane.
# Start by loading some data.
vtkImageReader2 reader
reader SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter"
reader SetDataExtent 0 63 0 63 1 93
reader SetDataSpacing 3.2 3.2 1.5
reader SetDataOrigin 0.0 0.0 0.0
reader SetDataScalarTypeToUnsignedShort
reader UpdateWholeExtent
# Calculate the center of the volume
[reader GetOutput] UpdateInformation
set extent [[reader GetOutput] GetWholeExtent]
set spacing [[reader GetOutput] GetSpacing]
set origin [[reader GetOutput] GetOrigin]
set xMin [lindex $extent 0]
set xMax [lindex $extent 1]
set yMin [lindex $extent 2]
set yMax [lindex $extent 3]
set zMin [lindex $extent 4]
set zMax [lindex $extent 5]
set xSpacing [lindex $spacing 0]
set ySpacing [lindex $spacing 1]
set zSpacing [lindex $spacing 2]
set x0 [lindex $origin 0]
set y0 [lindex $origin 1]
set z0 [lindex $origin 2]
set xCenter [expr $x0 + $xSpacing * 0.5 * ($xMin + $xMax)]
set yCenter [expr $y0 + $ySpacing * 0.5 * ($yMin + $yMax)]
set zCenter [expr $z0 + $zSpacing * 0.5 * ($zMin + $zMax)]
# Matrices for axial, coronal, sagittal, oblique view orientations
vtkMatrix4x4 axial
set elements { 1 0 0 $xCenter
0 1 0 $yCenter
0 0 1 $zCenter
0 0 0 1}
for {set i 0} {$i < 16} {incr i} {
axial SetElement [expr $i / 4] [expr $i % 4] [expr [lindex $elements $i]]
}
vtkMatrix4x4 coronal
set elements { 1 0 0 $xCenter
0 0 1 $yCenter
0 -1 0 $zCenter
0 0 0 1}
for {set i 0} {$i < 16} {incr i} {
coronal SetElement [expr $i / 4] [expr $i % 4] [expr [lindex $elements $i]]
}
vtkMatrix4x4 sagittal
set elements { 0 0 -1 $xCenter
1 0 0 $yCenter
0 -1 0 $zCenter
0 0 0 1}
for {set i 0} {$i < 16} {incr i} {
sagittal SetElement [expr $i / 4] [expr $i % 4] [expr [lindex $elements $i]]
}
vtkMatrix4x4 oblique
set elements { 1 0 0 $xCenter
0 0.866025 -0.5 $yCenter
0 0.5 0.866025 $zCenter
0 0 0 1 }
for {set i 0} {$i < 16} {incr i} {
oblique SetElement [expr $i / 4] [expr $i % 4] [expr [lindex $elements $i]]
}
# Extract a slice in the desired orientation
vtkImageReslice reslice
reslice SetInputConnection [reader GetOutputPort]
reslice SetOutputDimensionality 2
reslice SetResliceAxes sagittal
reslice SetInterpolationModeToLinear
# Create a greyscale lookup table
vtkLookupTable table
table SetTableRange 0 2000
table SetValueRange 0.0 1.0
table SetSaturationRange 0.0 0.0
table SetRampToLinear
table Build
# Map the image through the lookup table
vtkImageMapToColors color
color SetLookupTable table
color SetInputConnection [reslice GetOutputPort]
# Display the image
vtkImageActor actor
actor SetInput [color GetOutput]
vtkRenderer renderer
renderer AddActor actor
vtkRenderWindow window
window AddRenderer renderer
# Set up the interaction
vtkInteractorStyleImage imageStyle
vtkRenderWindowInteractor interactor
interactor SetInteractorStyle imageStyle
window SetInteractor interactor
window Render
# Create callbacks for slicing the image
global action
set action ""
proc ButtonPressCallback {} {
global action
set action "Slicing"
}
proc ButtonReleaseCallback {} {
global action
set action ""
}
proc MouseMoveCallback {} {
set lastPos [interactor GetLastEventPosition]
set currPos [interactor GetEventPosition]
global action
if {$action == "Slicing"} {
set deltaY [expr [lindex $currPos 1] - [lindex $lastPos 1]]
[reslice GetOutput] UpdateInformation
set spacing [[reslice GetOutput] GetSpacing]
set sliceSpacing [lindex $spacing 2]
set matrix [reslice GetResliceAxes]
# move the center point that we are slicing through
set center [$matrix MultiplyPoint 0 0 [expr $sliceSpacing * $deltaY] 1]
$matrix SetElement 0 3 [lindex $center 0]
$matrix SetElement 1 3 [lindex $center 1]
$matrix SetElement 2 3 [lindex $center 2]
window Render
} else {
imageStyle OnMouseMove
}
}
imageStyle AddObserver MouseMoveEvent MouseMoveCallback
imageStyle AddObserver LeftButtonPressEvent ButtonPressCallback
imageStyle AddObserver LeftButtonReleaseEvent ButtonReleaseCallback
interactor AddObserver UserEvent {wm deiconify .vtkInteract}
interactor AddObserver ExitEvent {exit}
interactor Initialize
#
# Hide the default . widget
#
wm withdraw .
#
# You only need this line if you run this script from a Tcl shell
# (tclsh) instead of a Tk shell (wish)
#
tkwait window .
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment