[Insight-users] Image (memory) management question
Iordanescu, Gheorghe (NIH/CC/DRD)
GIordanescu@cc.nih.gov
Mon, 17 Mar 2003 17:17:34 -0500
Hello everybody,
I have a question about image memory management.
It seems the way to use ITK is by cascading different filters, where each
filter generates a new image. I would like to wrap the ITK in simple
objects, i.e. to have an object that has a setInput() method (which should
hide/take care about all the settings), a process(some parameters,...)
method, a getResult() method and so on, an I would like the methods to
affect the same data, not to generate new data. For this I$B!G(Jve built a class
(code is attached below).
I am using as input an array style "cxLattice" structure (parent class
BasicFilter extracts CTWidth, CTHeight, NoOfCTSlices and data pointer
CTPixels from it). As you can see I am using an ImportImageFilter (to import
3D data) and an ExtractImageFilter (to extract 2D slices and be able to save
them on the disk). I am trying to use CastImageFilter as an image holder (as
a pointer to an itk image). I would like to be able to process the 2D slices
in the current 3D data, i.e. modify this data. For example I would like to
apply a morphological filter which should affect the existing 3D data and
not generate new 3D/2D data. In other words I would like my methods to
affect current data, not to generate new one.
As you can see - since I don't know any better, I am using
importFilter->GetOutput() method to retrieve and return a pointer to the 3D
data in the getWholeImageFromCXLattice() wrapping method, hoping it will not
trigger an Update() request through the whole pipe-line. Now I am quite
stuck because I would like to be able to process a certain slice (in 2D) or
portions of the 3D data. A possible solution would be to copy the 2D data
back to the 3D data using either an ImportImageFilter or some code like that
suggested by Dr. Ibanez (:)) - Luis), i.e create a new 3D image and copy in
it (mix) parts of the old 3D data and new 2D data.
new(2Dor3D)Image->SetRegions(old(2Dor3D)Image ->GetLargestPossibleRegion()
);
new(2Dor3D)Image ->Allocate();
new(2Dor3D)Image ->CopyInformation(old(2Dor3D)Image );
Is there a better solution?
Thanks,
George
//header file START --$B"*(J
// BasicFilterITK.h: interface for the BasicFilterITK class.
//
//////////////////////////////////////////////////////////////////////
#if
!defined(AFX_BASICFILTERITK_H__119E5013_4EAB_41A2_A3B2_079BD6CC583E__INCLUDE
D_)
#define
AFX_BASICFILTERITK_H__119E5013_4EAB_41A2_A3B2_079BD6CC583E__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "BasicFilter.h"
#include "itkImportImageFilter.h"
#include "itkExtractImageFilter.h"
#include "itkCastImageFilter.h"
class BasicFilterITK : public BasicFilter
{
public:
typedef BasicFilter Superclass;
typedef Superclass::basicFilterDataType inputPixelType;
typedef inputPixelType slicePixelType;
enum { inputImageDimension = 3 , sliceImageDimension = 2 };
typedef itk::Image< slicePixelType, sliceImageDimension >
outputSliceImageType;
typedef itk::Image< inputPixelType, inputImageDimension >
imageFromCXLatticeType;
imageFromCXLatticeType::Pointer getWholeImageFromCXLattice();
outputSliceImageType::Pointer getSliceImageFromCXLattice(unsigned
int SliceNo);
void saveSliceToFile
(unsigned int SliceNo, char* SliceName=0);
virtual int setInputCxLattice
(cxLattice *lat16BitCTVolume);
//virtual int setInputITKI
mage (imageFromCXLatticeType::Pointer
//
input3DITKImage);
BasicFilterITK();
virtual ~BasicFilterITK();
protected:
typedef itk::ImportImageFilter< inputPixelType, inputImageDimension
> ImportFilterType;
ImportFilterType::Pointer importFilter;
typedef itk::CastImageFilter< imageFromCXLatticeType,
imageFromCXLatticeType > CastFilterType;
CastFilterType::Pointer imageHolderFilter;
typedef itk::ExtractImageFilter< imageFromCXLatticeType,
outputSliceImageType > SliceExtractorFilterType;
SliceExtractorFilterType::Pointer slicer ;
void prepareSlicer ();
//imageFromCXLatticeType::IndexType sliceIndex;
//imageFromCXLatticeType::SizeType sliceSize;
imageFromCXLatticeType::RegionType sliceWantedRegion;
};
#endif //
!defined(AFX_BASICFILTERITK_H__119E5013_4EAB_41A2_A3B2_079BD6CC583E__INCLUDE
D_)
//<- ---header file END
____________________________________________________________
____________________________________________________________
////cpp file START --$B"*(J
// BasicFilterITK.cpp: implementation of the BasicFilterITK class.
//
//////////////////////////////////////////////////////////////////////
#include "BasicFilterITK.h"
//#include "itkImportImageFilter.h"
#include "itkImageFileWriter.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
BasicFilterITK::BasicFilterITK()
{
importFilter = ImportFilterType::New();
slicer = SliceExtractorFilterType::New();
imageHolderFilter = CastFilterType::New();
}
BasicFilterITK::~BasicFilterITK()
{
}
/**/
BasicFilterITK::imageFromCXLatticeType::Pointer
BasicFilterITK::getWholeImageFromCXLattice()
{
return importFilter->GetOutput();
}
BasicFilterITK::outputSliceImageType::Pointer
BasicFilterITK::getSliceImageFromCXLattice(unsigned int SliceNo)
{
imageFromCXLatticeType::Pointer imageFromCXLattice =
getWholeImageFromCXLattice();
sliceWantedRegion.SetIndex(2, SliceNo);
slicer->SetExtractionRegion ( sliceWantedRegion) ;
try{
slicer->Update();
}
catch( itk::ExceptionObject & exp ){
std::cerr << "Exception caught !" << std::endl;
std::cerr << exp << std::endl;
}
return slicer->GetOutput();
}
int BasicFilterITK::setInputCxLattice (cxLattice *latt)
{
int returnedByParentClass = Superclass::setInput(latt);
//CTSlice.setHeight(CTHeight); //
or CTSlice.setHeight(getYsize(latt));
//CTSlice.setWidth(CTWidth); //or CTSlice.setWidth(getXsize(latt));
//if (imageFromCXLattice) imageFromCXLattice->UnRegister();
//import data from the cx lattice
//typedef itk::ImportImageFilter< inputPixelType,
inputImageDimension > ImportFilterType;
//ImportFilterType::Pointer importFilter = ImportFilterType::New();
ImportFilterType::SizeType size;
size[0] = CTWidth; // size along X
size[1] = CTHeight; // size along Y
size[2] = NoOfCTSlices; // size along Z
ImportFilterType::IndexType start;
start.Fill( 0 );
ImportFilterType::RegionType region;
region.SetIndex( start );
region.SetSize( size );
importFilter->SetRegion( region );
double origin[ inputImageDimension ];
origin[0] = 0.0; // X coordinate
origin[1] = 0.0; // Y coordinate
origin[2] = 0.0; // Z coordinate
importFilter->SetOrigin( origin );
double spacing[ inputImageDimension ];
spacing[0] = 1.0; // along X direction
spacing[1] = 1.0; // along Y direction
spacing[2] = 1.0; // along Z direction
importFilter->SetSpacing( spacing );
const bool userPromiseToDeleteTheBuffer = true;
unsigned int numberOfPixels = size[0] * size[1] * size[2];
importFilter->SetImportPointer( CTPixels,
numberOfPixels,
userPromiseToDeleteTheBuffer );
//imageFromCXLattice = importFilter->GetOutput();
try{
importFilter->Update();
}
catch( itk::ExceptionObject & exp ){
std::cerr << "Exception caught !" << std::endl;
std::cerr << exp << std::endl;
}
prepareSlicer ();
return returnedByParentClass;
}
void BasicFilterITK::prepareSlicer (){
imageFromCXLatticeType::Pointer imageFromCXLattice =
getWholeImageFromCXLattice();
imageFromCXLatticeType::IndexType sliceIndex;
sliceIndex[0] = 0; //atoi( 0 );
sliceIndex[1] = 0;//atoi( 0 );
sliceIndex[2] = 0; // this is
the Number of slice to be saved
imageFromCXLatticeType::RegionType regionOfImageFromCxLattice =
imageFromCXLattice->GetLargestPossibleRegion ();
imageFromCXLatticeType::SizeType sizeOfImageFromCxLattice =
regionOfImageFromCxLattice.GetSize ();
imageFromCXLatticeType::SizeType sliceSize;
sliceSize[0] = sizeOfImageFromCxLattice[0];
sliceSize[1] = sizeOfImageFromCxLattice[1];
sliceSize[2] = 0;
//imageFromCXLatticeType::RegionType sliceWantedRegion;
sliceWantedRegion.SetSize( sliceSize );
sliceWantedRegion.SetIndex( sliceIndex );
try
{
slicer->SetExtractionRegion( sliceWantedRegion );
}
catch( itk::ExceptionObject & exp )
{
std::cerr << "Exception caught !" << std::endl;
std::cerr << exp << std::endl;
}
slicer->SetInput( imageFromCXLattice );
}
void BasicFilterITK::saveSliceToFile (unsigned int SliceNo, char* SliceName)
{
//compute the output file name
char fileName[200];
if (SliceName) strcpy(fileName, SliceName);
else strcpy(fileName, "Slice");
char buffer[20];
_itoa( SliceNo, buffer, 10 );
strcat(fileName, buffer);
strcat(fileName, ".png");
//and now write the slice
typedef itk::ImageFileWriter< outputSliceImageType > WriterType;
WriterType::Pointer writer = WriterType::New();
writer->SetFileName( fileName );
writer->SetInput( getSliceImageFromCXLattice(SliceNo) );
try{
writer->Update();
}
catch( itk::ExceptionObject & exp ){
std::cerr << "Exception caught !" << std::endl;
std::cerr << exp << std::endl;
}
}
//<- ---CPP file END