[Insight-users] why vtkImagePlaneWidget run extremely slow after
itk::BinaryThresholdImageFilter excuted several times
kdsfinger at gmail.com
kdsfinger at gmail.com
Mon Aug 21 15:48:58 EDT 2006
hi, all
I found the myITKgui runs extremely slow after
itk::BinaryThresholdImageFilter excuted several times. The myITKgui is
a little demo of itk-fltk and here is the link:
http://www.eecs.berkeley.edu/~eklund/teaching/cs294/software/Software/myITKgui-cs294v1.0.zip
Here is major part of the code.
/*=========================================================================
Program: My ITK GUI - A Foundation for Pipeline Visualization in ITK
Module: $RCSfile: migAppBase.h,v $
Language: C++
Date: $Date: 2006/02/06 06:35:36 $
Version: $Revision: 1.1 $
Copyright (c) 2003-5 Damion Shelton
All rights reserved.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef _migAppBase_h
#define _migAppBase_h
#include <stdio.h>
#include <itkSize.h>
#include <itkIndex.h>
#include <itkImage.h>
#include <itkBinaryThresholdImageFilter.h>
#include <itkImageFileReader.h>
#include <itkVTKImageExport.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkImageImport.h>
#include <vtkImagePlaneWidget.h>
#include "vtkFlRenderWindowInteractor.h"
class migAppBase
{
public:
/** Typedefs used in myITKgui */
typedef itk::Image<unsigned char, 3> InputImageType;
typedef itk::ImageFileReader<InputImageType> ImageFileReaderType;
typedef itk::Image<unsigned char, 3> OutputImageType;
typedef itk::VTKImageExport<InputImageType> itkVTKImageExportType;
typedef itkVTKImageExportType::Pointer itkVTKImageExportPointerType;
/** The type of filter the demo uses... YOU WILL NEED TO CHANGE THIS
FILTER IN YOUR HOMEWORK */
typedef itk::BinaryThresholdImageFilter<InputImageType,
InputImageType> ThresholdType;
/** Read a META format image from disk */
void ReadImage();
/** Hook together an ITK pipeline, EDIT THIS FUNCTION TO CHANGE ITK
BEHAVIOR! */
void CreateITKPipeline();
/** Callback for making the ITK pipeline do something */
void UpdatePipelineCallback();
/** Window creation */
void CreateInputImageWindow();
void CreateOutputImageWindow();
/** Create a FLTK window with a VTK interator */
void CreateWindowWithRWI(vtkFlRenderWindowInteractor *&flrwi,
Fl_Window *&flw, char *title);
/** Create input and output pipelines */
void CreateInputImageVTKPipeline(vtkFlRenderWindowInteractor *flrwi);
void CreateOutputImageVTKPipeline(vtkFlRenderWindowInteractor *flrwi);
/** Reset the image planes to the center of the image */
void ResetInputImagePlaneWidgets();
void ResetOutputImagePlaneWidgets();
/** Constructor - not much to see */
migAppBase();
/** Destructor - not much to see */
virtual ~migAppBase();
protected:
/** Input image file name */
char* m_InputImageFilename;
/** The image reader */
ImageFileReaderType::Pointer m_ImageReader;
/** The image we loaded from the file */
InputImageType::Pointer m_InputImage;
/** The image that results from running the pipeline */
OutputImageType::Pointer m_OutputImage;
/** Tracks whether this is the first time we've pressed "update" */
bool m_IsFirstUpdate;
/** The _EXAMPLE_ filter used here... YOU SHOULD CHANGE THIS */
ThresholdType::Pointer m_ThresholdFilter;
/** Example filter parameters... should also be changed in your code */
double m_LowerThreshold;
double m_UpperThreshold;
double m_InsideThresholdValue;
double m_OutsideThresholdValue;
/** Input window FLTK stuff */
vtkFlRenderWindowInteractor* m_InputInteractor;
Fl_Window* m_InputWindow;
/** Converter from ITK to VTK for input image */
itk::VTKImageExport<InputImageType>::Pointer m_InputImageITKtoVTKexporter;
vtkImageImport* m_InputImageVTKimporter;
/** VTK rendering architecture for input image */
vtkRenderWindow * m_InputRenderWindow;
vtkRenderer * m_InputRenderer;
/** Slices through the input image */
vtkImagePlaneWidget* m_InputImagePlaneX;
vtkImagePlaneWidget* m_InputImagePlaneY;
vtkImagePlaneWidget* m_InputImagePlaneZ;
/** Output window FLTK stuff */
vtkFlRenderWindowInteractor* m_OutputInteractor;
Fl_Window* m_OutputWindow;
/** VTK rendering architecture for output image */
vtkRenderWindow * m_OutputRenderWindow;
vtkRenderer * m_OutputRenderer;
/** Converter from ITK to VTK for output image */
itk::VTKImageExport<OutputImageType>::Pointer m_OutputImageITKtoVTKexporter;
vtkImageImport* m_OutputImageVTKimporter;
/** Slices through the output image */
vtkImagePlaneWidget* m_OutputImagePlaneX;
vtkImagePlaneWidget* m_OutputImagePlaneY;
vtkImagePlaneWidget* m_OutputImagePlaneZ;
};
#endif
/*=========================================================================
Program: My ITK GUI - A Foundation for Pipeline Visualization in ITK
Module: $RCSfile: migAppBase.cxx,v $
Language: C++
Date: $Date: 2006/02/06 06:35:36 $
Version: $Revision: 1.1 $
Copyright (c) 2003-5 Damion Shelton
...with thanks to Charl Botha who the FlRenderWindowInteractor example
code on which part of this class is based
All rights reserved.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "migAppBase.h"
#include <FL/Fl.H>
#include <FL/Fl_File_Chooser.H>
#include <itkMetaImageIOFactory.h>
/**
* This function will connect the given itk::VTKImageExport filter to
* the given vtkImageImport filter.
*/
template <typename ITK_Exporter, typename VTK_Importer>
void ConnectPipelines(ITK_Exporter exporter, VTK_Importer* importer)
{
importer->SetUpdateInformationCallback(exporter->GetUpdateInformationCallback());
importer->SetPipelineModifiedCallback(exporter->GetPipelineModifiedCallback());
importer->SetWholeExtentCallback(exporter->GetWholeExtentCallback());
// importer->SetSpacingCallback(exporter->GetSpacingCallback());
// importer->SetOriginCallback(exporter->GetOriginCallback());
importer->SetScalarTypeCallback(exporter->GetScalarTypeCallback());
importer->SetNumberOfComponentsCallback(exporter->GetNumberOfComponentsCallback());
importer->SetPropagateUpdateExtentCallback(exporter->GetPropagateUpdateExtentCallback());
importer->SetUpdateDataCallback(exporter->GetUpdateDataCallback());
importer->SetDataExtentCallback(exporter->GetDataExtentCallback());
importer->SetBufferPointerCallback(exporter->GetBufferPointerCallback());
importer->SetCallbackUserData(exporter->GetCallbackUserData());
}
migAppBase
::migAppBase()
{
// The file name of the image we're reading
m_InputImageFilename = new char[256];
// The first time update is called we need to do some extra stuff
m_IsFirstUpdate = true;
m_InputImage = 0;
m_OutputImage = 0;
m_ThresholdFilter = 0;
m_LowerThreshold = 25;
m_UpperThreshold = 100;
m_InsideThresholdValue = 0;
m_OutsideThresholdValue = 255;
m_InputInteractor = 0;
m_InputWindow = 0;
m_InputImageITKtoVTKexporter = 0;
m_InputImageVTKimporter = 0;
m_InputRenderWindow = 0;
m_InputRenderer = 0;
m_InputImagePlaneX = 0;
m_InputImagePlaneY = 0;
m_InputImagePlaneZ = 0;
m_OutputInteractor = 0;
m_OutputWindow = 0;
m_OutputImageITKtoVTKexporter = 0;
m_OutputImageVTKimporter = 0;
m_OutputRenderWindow = 0;
m_OutputRenderer = 0;
m_OutputImagePlaneX = 0;
m_OutputImagePlaneY = 0;
m_OutputImagePlaneZ = 0;
}
migAppBase
::~migAppBase()
{
if( m_InputImageFilename )
delete[] m_InputImageFilename;
}
void
migAppBase
::ReadImage()
{
// Can only read an image once
#if 0 //FIXME
if(m_InputImage != 0)
return;
#endif
// Show a dialog box to let the user pick a file
char* chooserName = fl_file_chooser("Pick a .mha file to load",
"*.mha", 0, 0);
// Store the filename
strcpy( m_InputImageFilename, chooserName );
cout << "Opening file with name: " << m_InputImageFilename << endl;
// Now we can read the file
m_ImageReader = ImageFileReaderType::New();
itk::MetaImageIOFactory::RegisterOneFactory();
m_ImageReader->SetFileName( m_InputImageFilename );
m_InputImage = m_ImageReader->GetOutput();
m_InputImage->SetRequestedRegionToLargestPossibleRegion();
m_ImageReader->Update();
// Create the ITK pipeline (NB: pipeline not yet executed)
this->CreateITKPipeline();
// Create the input image VTK pipeline
this->CreateInputImageWindow();
}
/**
*
*
* EDIT THE FOLLOWING FUNCTION TO CHANGE THE BEHAVIOR OF THE FILTERS
*
*
**/
void
migAppBase
::CreateITKPipeline()
{
// Set up our example filter
m_ThresholdFilter = ThresholdType::New();
m_ThresholdFilter->SetInput(m_InputImage);
m_ThresholdFilter->SetOutsideValue( m_OutsideThresholdValue );
m_ThresholdFilter->SetInsideValue( m_InsideThresholdValue );
m_ThresholdFilter->SetLowerThreshold( m_LowerThreshold );
m_ThresholdFilter->SetUpperThreshold( m_UpperThreshold );
// Get the final pipeline output... be sure to do this in your revisions!
m_OutputImage = m_ThresholdFilter->GetOutput();
}
void
migAppBase
::UpdatePipelineCallback()
{
// Transfer the most recent filter parameters to the filter
m_ThresholdFilter->SetOutsideValue( m_OutsideThresholdValue );
m_ThresholdFilter->SetInsideValue( m_InsideThresholdValue );
m_ThresholdFilter->SetLowerThreshold( m_LowerThreshold );
m_ThresholdFilter->SetUpperThreshold( m_UpperThreshold );
// Update the pipeline
m_ThresholdFilter->Update();
// If this is the first time we've hit update there's other stuff
// that needs to happen
if(m_IsFirstUpdate)
{
// Display the output image
this->CreateOutputImageWindow();
// No longer the first update
m_IsFirstUpdate = false;
}
else
{
// Refresh the output window if not the first update
// NB: doing this on the first update on Windows causes a new
// renderwindow to spawn (not sure why)
m_OutputRenderWindow->Render();
}
}
void
migAppBase
::CreateInputImageWindow()
{
CreateWindowWithRWI(m_InputInteractor, m_InputWindow, "Input Image");
// these two steps are VERY IMPORTANT, you have to show() the fltk window
// containing the vtkFlRenderWindowInteractor, and then the
// vtkFlRenderWindowInteractor itself
m_InputWindow->show();
m_InputInteractor->show();
// now we get to setup our VTK rendering pipeline
CreateInputImageVTKPipeline(m_InputInteractor);
}
void
migAppBase
::CreateOutputImageWindow()
{
CreateWindowWithRWI(m_OutputInteractor, m_OutputWindow, "Output Image");
// these two steps are VERY IMPORTANT, you have to show() the fltk window
// containing the vtkFlRenderWindowInteractor, and then the
// vtkFlRenderWindowInteractor itself
m_OutputWindow->show();
m_OutputInteractor->show();
// now we get to setup our VTK rendering pipeline
this->CreateOutputImageVTKPipeline(m_OutputInteractor);
}
void
migAppBase
::CreateWindowWithRWI(vtkFlRenderWindowInteractor *&flrwi, Fl_Window
*&flw, char *title)
{
// set up main FLTK window
flw = new Fl_Window(300,330,title);
// and instantiate vtkFlRenderWindowInteractor (here it acts like a
// FLTK window, i.e. you could also instantiate it as child of a
// Fl_Group in a window)
flrwi = new vtkFlRenderWindowInteractor(5,5,290,260,NULL);
// this will result in a little message under the rendering
Fl_Box* box = new Fl_Box(5,261,290,34,
"3 = stereo, j = joystick, t = trackball, "
"w = wireframe, s = surface, p = pick; "
"you can also resize the window");
box->labelsize(10);
box->align(FL_ALIGN_WRAP);
// we're done populating the flw
flw->end();
// if the main window gets resized, the vtk window should resize with it
flw->resizable(flrwi);
}
void
migAppBase
::CreateInputImageVTKPipeline(vtkFlRenderWindowInteractor *flrwi)
{
// Abort if the user is being stupid
#if 0 //FIXME
if(m_InputImage==0)
return;
#endif
// create a rendering window and renderer
m_InputRenderer = vtkRenderer::New();
m_InputRenderer->SetBackground(0.0, 0.0, 0.0);
m_InputRenderWindow = vtkRenderWindow::New();
m_InputRenderWindow->AddRenderer(m_InputRenderer);
// NB: here we treat the vtkFlRenderWindowInteractor just like any other
// old vtkRenderWindowInteractor
flrwi->SetRenderWindow(m_InputRenderWindow);
// Hook the VTK pipeline up to the ITK pipeline
m_InputImageITKtoVTKexporter = itk::VTKImageExport<InputImageType>::New();
m_InputImageVTKimporter = vtkImageImport::New();
m_InputImageITKtoVTKexporter->SetInput( m_InputImage );
ConnectPipelines(m_InputImageITKtoVTKexporter, m_InputImageVTKimporter);
// Need to update prior to creating the cutting planes
m_InputImageITKtoVTKexporter->Update();
m_InputImageVTKimporter->Update();
// Create the image cutting planes
m_InputImagePlaneX = vtkImagePlaneWidget::New();
m_InputImagePlaneX->RestrictPlaneToVolumeOn();
m_InputImagePlaneX->SetResliceInterpolateToCubic();
m_InputImagePlaneX->SetInput( (vtkDataSet*)
m_InputImageVTKimporter->GetOutput() );
m_InputImagePlaneX->SetPlaneOrientationToXAxes();
m_InputImagePlaneX->SetSliceIndex( 0 );
m_InputImagePlaneY = vtkImagePlaneWidget::New();
m_InputImagePlaneY->RestrictPlaneToVolumeOn();
m_InputImagePlaneY->SetResliceInterpolateToCubic();
m_InputImagePlaneY->SetInput( (vtkDataSet*)
m_InputImageVTKimporter->GetOutput() );
m_InputImagePlaneY->SetPlaneOrientationToYAxes();
m_InputImagePlaneY->SetSliceIndex( 0 );
m_InputImagePlaneZ = vtkImagePlaneWidget::New();
m_InputImagePlaneZ->RestrictPlaneToVolumeOn();
m_InputImagePlaneZ->SetResliceInterpolateToCubic();
m_InputImagePlaneZ->SetInput( (vtkDataSet*)
m_InputImageVTKimporter->GetOutput() );
m_InputImagePlaneZ->SetPlaneOrientationToZAxes();
m_InputImagePlaneZ->SetSliceIndex( 0 );
// Set the position of the image planes to the center of the volume
this->ResetInputImagePlaneWidgets();
// Link the image planes to the interactor
m_InputImagePlaneX->SetInteractor( flrwi );
m_InputImagePlaneY->SetInteractor( flrwi );
m_InputImagePlaneZ->SetInteractor( flrwi );
// Turn on the image plane so they display
m_InputImagePlaneX->On();
m_InputImagePlaneY->On();
m_InputImagePlaneZ->On();
// just like with any other vtkRenderWindowInteractor(), you HAVE to call
// Initialize() before the interactor will function. See the docs in
// vtkRenderWindowInteractor.h
// This must occur AFTER the image planes have been added to the interactor
flrwi->Initialize();
// Clean up memory allocation (NB: not actually deleted until program returns)
m_InputRenderer->Delete();
m_InputRenderWindow->Delete();
}
void
migAppBase
::CreateOutputImageVTKPipeline(vtkFlRenderWindowInteractor *flrwi)
{
// Abort if the user is being stupid
#if 0 //FIXME
if(m_OutputImage==0)
return;
#endif
// create a rendering window and renderer
m_OutputRenderer = vtkRenderer::New();
m_OutputRenderer->SetBackground(0.0, 0.0, 0.0);
m_OutputRenderWindow = vtkRenderWindow::New();
m_OutputRenderWindow->AddRenderer(m_OutputRenderer);
// NB: here we treat the vtkFlRenderWindowInteractor just like any other
// old vtkRenderWindowInteractor
flrwi->SetRenderWindow(m_OutputRenderWindow);
// Hook the VTK pipeline up to the ITK pipeline
m_OutputImageITKtoVTKexporter = itk::VTKImageExport<OutputImageType>::New();
m_OutputImageVTKimporter = vtkImageImport::New();
m_OutputImageITKtoVTKexporter->SetInput( m_OutputImage );
ConnectPipelines(m_OutputImageITKtoVTKexporter, m_OutputImageVTKimporter);
// Need to update prior to creating the cutting planes
m_OutputImageITKtoVTKexporter->Update();
m_OutputImageVTKimporter->Update();
// Create the image cutting planes
m_OutputImagePlaneX = vtkImagePlaneWidget::New();
m_OutputImagePlaneX->RestrictPlaneToVolumeOn();
m_OutputImagePlaneX->SetResliceInterpolateToCubic();
m_OutputImagePlaneX->SetInput( (vtkDataSet*)
m_OutputImageVTKimporter->GetOutput() );
m_OutputImagePlaneX->SetPlaneOrientationToXAxes();
m_OutputImagePlaneX->SetSliceIndex( 0 );
m_OutputImagePlaneY = vtkImagePlaneWidget::New();
m_OutputImagePlaneY->RestrictPlaneToVolumeOn();
m_OutputImagePlaneY->SetResliceInterpolateToCubic();
m_OutputImagePlaneY->SetInput( (vtkDataSet*)
m_OutputImageVTKimporter->GetOutput() );
m_OutputImagePlaneY->SetPlaneOrientationToYAxes();
m_OutputImagePlaneY->SetSliceIndex( 0 );
m_OutputImagePlaneZ = vtkImagePlaneWidget::New();
m_OutputImagePlaneZ->RestrictPlaneToVolumeOn();
m_OutputImagePlaneZ->SetResliceInterpolateToCubic();
m_OutputImagePlaneZ->SetInput( (vtkDataSet*)
m_OutputImageVTKimporter->GetOutput() );
m_OutputImagePlaneZ->SetPlaneOrientationToZAxes();
m_OutputImagePlaneZ->SetSliceIndex( 0 );
// Set the position of the image planes to the center of the volume
this->ResetOutputImagePlaneWidgets();
// Link the image planes to the interactor
m_OutputImagePlaneX->SetInteractor( flrwi );
m_OutputImagePlaneY->SetInteractor( flrwi );
m_OutputImagePlaneZ->SetInteractor( flrwi );
// Turn on the image plane so they display
m_OutputImagePlaneX->On();
m_OutputImagePlaneY->On();
m_OutputImagePlaneZ->On();
// just like with any other vtkRenderWindowInteractor(), you HAVE to call
// Initialize() before the interactor will function. See the docs in
// vtkRenderWindowInteractor.h
// This must occur AFTER the image planes have been added to the interactor
flrwi->Initialize();
// Clean up memory allocation (NB: not actually deleted until program returns)
m_OutputRenderer->Delete();
m_OutputRenderWindow->Delete();
}
void
migAppBase
::ResetInputImagePlaneWidgets()
{
// Sanity check
if(m_InputInteractor == 0)
return;
// Reset plane orientations
m_InputImagePlaneZ->SetPlaneOrientationToZAxes();
m_InputImagePlaneY->SetPlaneOrientationToYAxes();
m_InputImagePlaneX->SetPlaneOrientationToXAxes();
// Figure out how big the image is
itk::Size<3> imageSize = m_InputImage->GetLargestPossibleRegion().GetSize();
int xmax = imageSize[0];
int ymax = imageSize[1];
int zmax = imageSize[2];
// Set the image planes to the center of the image
m_InputImagePlaneX->SetSlicePosition( xmax/2 );
m_InputImagePlaneY->SetSlicePosition( ymax/2 );
m_InputImagePlaneZ->SetSlicePosition( zmax/2 );
}
void
migAppBase
::ResetOutputImagePlaneWidgets()
{
// Sanity check
if(m_OutputInteractor == 0)
return;
// Reset plane orientations
m_OutputImagePlaneZ->SetPlaneOrientationToZAxes();
m_OutputImagePlaneY->SetPlaneOrientationToYAxes();
m_OutputImagePlaneX->SetPlaneOrientationToXAxes();
// Figure out how big the image is
itk::Size<3> imageSize = m_OutputImage->GetLargestPossibleRegion().GetSize();
int xmax = imageSize[0];
int ymax = imageSize[1];
int zmax = imageSize[2];
// Set the image planes to the center of the image
m_OutputImagePlaneX->SetSlicePosition( xmax/2 );
m_OutputImagePlaneY->SetSlicePosition( ymax/2 );
m_OutputImagePlaneZ->SetSlicePosition( zmax/2 );
}
Thanks for comments.
zl2k
More information about the Insight-users
mailing list