[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