[Insight-users] Image (memory) management question

Luis Ibanez luis.ibanez@kitware.com
Mon, 17 Mar 2003 23:06:00 -0500


Hi Gheorghe,

You may find interesting to take a look at the plug-ins
that we have been writing for integrating ITK into Volview.

They are basically following the approach that you just
described

1) Importing a C-like data buffer with the ImportImageFilter.
2) Using the CastImageFilter to convert types.
3) Hiding most of the filter parameters, and exposing a few ones.
4) Taking the output data and writing it on an external
   C-like array.

Until very recently ITK didn't offer much support for processing
data "in-place".  The pipelin architecture is always assuming that
input data is passed to a filter and that from it, independently
stored output data will be generated.

Jim Miller recently added the "itkInPlaceImageFilter" into the
Code/Common directory. This is still work in progress and has
so far affected a reduced number of filters. The population of
in-place filter is expected to grow steadily.

Probably Jim could provide a better advice about how to write
portions of the output data into the input data. He knows the
internals of the pipeline better that anyone of us.



  Regards


     Luis


---------------------------------------------
Iordanescu, Gheorghe (NIH/CC/DRD) wrote:
> 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(Bve 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"*(B
> 
> // 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"*(B
> // 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
> 
> 
> _______________________________________________
> Insight-users mailing list
> Insight-users@public.kitware.com
> http://public.kitware.com/mailman/listinfo/insight-users
>