[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
>