[Insight-users] Need help with PermuteAxesImageFilter

Luis Ibanez luis.ibanez at kitware.com
Sun Aug 20 17:20:30 EDT 2006


Hi Martin,



Thanks for posting your code.


Please find attached a modified version of your code.


There are many issues with your code.
Here are some comments:



1) Please *never* use the expression

                 "using namespace std"


    This defeats the purpose of namespaces.

    It is unfortunately introduced in some C++ books and encourage
    carelessly laziness in programmers.  Instead of opening the
    std (or any other) namespace, you should use the explicit
    namespace in its objects. For example:   "std::cout"


2) Instead of getting the image out of the series and updating
    the image, you should update the series reader directly:


                readerSeries->Update();
                image = readerSeries->GetOutput();

     instead your current code:

                image = readerSeries->GetOutput();
                image->Update()



3) The std::vector for filenames can be a static variable,
    there is no need for using dynamic memory for this object.



4) You forgot to mention that you were manually setting the
    RequestedImageRegion() in the PermuteAxesImageFilter.

    You should avoid doing this.

    If you actually want to extract a region out of the image
    you should do this with the ExtractImageFilter or the
    RegionOfInterestImageFilter.

    You shouldn't directly manipulate the RequestedRegion
    of the output of a filter. This region is defined during
    the pipeline negotiation, and any region you set will be
    override as soon as you run the filters that are downstream
    in the pipeline.


5) You are setting the MetaDataDictionary *BEFORE* having
    set up the ImageIO object. This is the main source of
    your problem. You *must* set the ImageIO object first
    because it is the recipient of the MetaImageDictionary.


6) There is no need for *reusing* variables such as "image".
    Your program will not run faster, it will not save any
    memory. It only going to be hard to read, buggy , and
    almost impossible to maintain. Please be generous by
    creating variables that are clearly identified by their
    actual role in your problem.


7) There are two major flaws in your code:

    You are passing the MetaImage dictionary unchanged
    despite the fact that you

     a)*permuted* the axis of the image

    and

     b) *cropped* a region out of it.

    The MetaImage dictionary is carrying data in the order
    or the original axis. When you store the data in the
    outgoing image, most of the data is in the wrong order,
    and due to the cropping is also carrying outdated values.


8) After fixing for comments (1-6) the major flaws of (7)
    result in the following very clear error:



itk::ExceptionObject (0x22b85b0)
Location: "void itk::ImageSeriesWriter<TInputImage, 
TOutputImage>::GenerateData() [with TInputImage = main(int, 
char**)::s3ImageType, TOutputImage = main(int, char**)::s2ImageType]"
File: /home/ibanez/src/Insight/Code/IO/itkImageSeriesWriter.txx
Line: 367
Description: itk::ERROR: ImageSeriesWriter(0x22f2090): The slice number: 
23 exceeds the size of the MetaDataDictionaryArray 22.



    Of Course, if you remove the setting of the MetaData
    dictionary in the series writer, then the code will
    run.





To summarize:


      A) Use the RegionOfInterestImageFilter if you want to
         extract a region of interest. DO NOT manipulate the
         regions manually


      B) The MetaData dictionary of the input image is not
         good for the output image because you permuted it
         and changed its size. You *MUST* edit the content
         of the MetaDataDictionary accordingly.




Regards,



    Luis



-----------

MX wrote:
> Hi Luis,
> 
> thanks for your reply.
> I did put the code in a try catch block as you said,
> but there's no output. I was wrong telling that it's an exception.
> I debugged it with gdb and it says that it's a segmentation fault
> in  itk::MetaDataDictionary::operator= ...  The programm just crashes.
> 
> But it does only when there's the PermuteAxesImageFilter in pipeline and 
> does
> permute the image.
> I really have no idea what it can be. If I comment the line
>    seriesWriter->SetMetaDataDictionaryArray( 
> seriesReader->GetMetaDataDictionaryArray() );
> out there' no problem (except that all header info is lost )
> 
> Thx,
> Martin
> 
> The code it tried:
> 
> #include <itkImageSeriesWriter.h>
> #include <itkImageSeriesReader.h>
> #include <itkGDCMImageIO.h>
> #include <itkGDCMSeriesFileNames.h>
> #include <itkNumericSeriesFileNames.h>
> #include <itkPermuteAxesImageFilter.h>
> 
> #include <string.h>
> 
> 
> using namespace std;
> int main( int argc, char **argv ) {
>      typedef itk::Image< short, 2> s2ImageType;
>    typedef itk::Image< short, 3> s3ImageType;
>       typedef itk::ImageSeriesReader<s3ImageType> SeriesReaderType;      
>    SeriesReaderType::Pointer seriesReader = SeriesReaderType::New();
>          typedef itk::GDCMImageIO DicomIOType;
>    DicomIOType::Pointer dicomIO = DicomIOType::New();
>      vector< string > *fileNames = new vector< string >;
>      for ( int i=1; i<argc-1; i++ ){
>        fileNames->push_back( string( argv[i] ) );
>    }
>          seriesReader->SetFileNames( (*fileNames) );
>    seriesReader->SetImageIO( dicomIO );      s3ImageType::Pointer image 
> = seriesReader->GetOutput();
> 
>    try {
>        cout << "reading...";
>        image->Update();          } catch( itk::ExceptionObject & ex ) {
>        cout << ex << endl;
>        delete fileNames;
>        return 0;
>    }
>      cout << "done" << endl;
>        typedef itk::PermuteAxesImageFilter< s3ImageType > 
> PermuteAxesImageFilterType;        PermuteAxesImageFilterType::Pointer 
> permuteAxesFilter = PermuteAxesImageFilterType::New();
>    permuteAxesFilter->SetInput( image );
>      typedef itk::FixedArray< signed short, 3> FixedArrayType;
>    FixedArrayType dimensionArray;
>    dimensionArray[0] = permuteAxesFilter->GetOrder()[2];
>    dimensionArray[1] = permuteAxesFilter->GetOrder()[0];
>    dimensionArray[2] = permuteAxesFilter->GetOrder()[1];
>    permuteAxesFilter->SetOrder( dimensionArray );
>      image = permuteAxesFilter->GetOutput();
>      try {
>        cout << "permuting...";
>        image->Update();
>    } catch( itk::ExceptionObject & ex ) {
>        cout << ex << endl;
>        delete fileNames;
>        return 0;
>    }
>             s3ImageType::RegionType region = 
> image->GetLargestPossibleRegion();
>    s3ImageType::IndexType start = region.GetIndex();
>    s3ImageType::SizeType size = region.GetSize();
>      image->SetRequestedRegion( region );
>    const unsigned int firstSlice = start[2] +1 ;
>    const unsigned int lastSlice = start[2] + size[2];
>      string format = "D:\\projects\\daten\\output\\TestVolume-%04d.dcm";
>      typedef itk::NumericSeriesFileNames NumericNamesGeneratorType;
>      NumericNamesGeneratorType::Pointer numericNamesGenerator = 
> NumericNamesGeneratorType::New();
>      numericNamesGenerator->SetSeriesFormat( format.c_str() );
>    numericNamesGenerator->SetStartIndex( firstSlice );
>    numericNamesGenerator->SetEndIndex( lastSlice );
>    numericNamesGenerator->SetIncrementIndex( 1 );
>          typedef itk::ImageSeriesWriter < s3ImageType, s2ImageType > 
> SeriesWriterType;
>    SeriesWriterType::Pointer seriesWriter = SeriesWriterType::New();
>      cout << "starting seriesWriter" << endl;
>      try {
>        seriesWriter->SetInput( image );   // commented out so that the 
> programm terminates normal
> //         seriesWriter->SetMetaDataDictionaryArray( 
> seriesReader->GetMetaDataDictionaryArray() );
>        seriesWriter->SetImageIO( dicomIO );            
> seriesWriter->SetStartIndex( firstSlice );
>        seriesWriter->SetIncrementIndex( 1 );
>        seriesWriter->SetFileNames( numericNamesGenerator->GetFileNames() );
>     } catch( itk::ExceptionObject & ex ) {
>         cout << "error at metaData" << endl;
>         cout << ex << endl;
>     }
>      try{
>        cout << "writing...";
>        seriesWriter->Update();
>    } catch( itk::ExceptionObject &ex ){
>        cout << ex << endl;          }
>    cout << "done" << endl;
>      delete fileNames;
>      return 0;
> }
> 
> 
> Luis Ibanez wrote:
> 
>>
>> Hi Martin,
>>
>> If you are getting and Exception you should add a try/catch
>> block around your code and print out the message returned by
>> the exception.
>>
>> You will find many examples on how to do this in the
>> ITK Software Guide
>>
>>
>>       http://www.itk.org/ItkSoftwareGuide.pdf
>>
>>
>> Please let us know what message do you  get from the exception.
>>
>>
>>   Thanks
>>
>>
>>     Luis
>>
>>
>>
>> ------------
>> MX wrote:
>>
>>>
>>> Hello,
>>> i have a problem with the PermuteAxesImageFilter,
>>> when writing DICOM series I used the MetaDataDicitonaryArray
>>> i could get from the ImageSeriesReader:
>>> I couldn't find anything about it in the archives.
>>>
>>> seriesWriter->SetMetaDataDictionaryArray( 
>>> seriesReader->GetMetaDataDicitonaryArray() );
>>> This worked very well.
>>>
>>> But as I put the PermuteAxesImageFilter in the pipeline, it does not 
>>> work so well anymore,
>>> I get an exception at runtime.
>>> Why does it happen?
>>> And what can I do for not loosing the header information?
>>>
>>> Thx,
>>> Martin
>>>
>>>
>>> _______________________________________________
>>> Insight-users mailing list
>>> Insight-users at itk.org
>>> http://www.itk.org/mailman/listinfo/insight-users
>>>
>>>
>>
>>
>>
> 
> 
> 

-------------- next part --------------

 #include <itkImageSeriesWriter.h>
 #include <itkImageSeriesReader.h>
 #include <itkGDCMImageIO.h>
 #include <itkGDCMSeriesFileNames.h>
 #include <itkNumericSeriesFileNames.h>
 #include <itkPermuteAxesImageFilter.h>
 
 #include <string>
 #include <vector>
 
 
int main( int argc, char **argv ) 
{


  typedef itk::Image< short, 2> s2ImageType;
  typedef itk::Image< short, 3> s3ImageType;

  typedef itk::ImageSeriesReader<s3ImageType> SeriesReaderType;      

  SeriesReaderType::Pointer seriesReader = SeriesReaderType::New();

  typedef itk::GDCMImageIO DicomIOType;

  DicomIOType::Pointer dicomIO = DicomIOType::New();

  std::vector< std::string > fileNames;

  for ( int i=1; i<argc-1; i++ )
    {
    fileNames.push_back( std::string( argv[i] ) );
    }

  seriesReader->SetFileNames( fileNames );
  seriesReader->SetImageIO( dicomIO );      

  s3ImageType::ConstPointer inputImage = seriesReader->GetOutput();
 
  try 
    {
    std::cout << "reading...";
    seriesReader->Update();     
    } 
  catch( itk::ExceptionObject & ex ) 
    {
    std::cout << ex << std::endl;
    return 0;
    }


  std::cout << "done" << std::endl;

  typedef itk::PermuteAxesImageFilter< s3ImageType > 

  PermuteAxesImageFilterType;        PermuteAxesImageFilterType::Pointer 

  permuteAxesFilter = PermuteAxesImageFilterType::New();

  permuteAxesFilter->SetInput( inputImage );

  typedef itk::FixedArray< signed short, 3> FixedArrayType;

  FixedArrayType dimensionArray;
  dimensionArray[0] = permuteAxesFilter->GetOrder()[2];
  dimensionArray[1] = permuteAxesFilter->GetOrder()[0];
  dimensionArray[2] = permuteAxesFilter->GetOrder()[1];

  permuteAxesFilter->SetOrder( dimensionArray );


  try 
    {
    std::cout << "permuting...";
    permuteAxesFilter->Update();
    } 
  catch( itk::ExceptionObject & ex ) 
    {
    std::cout << ex << std::endl;
    return 0;
    }

 s3ImageType::Pointer permutedImage = permuteAxesFilter->GetOutput();

 s3ImageType::RegionType region = permutedImage->GetLargestPossibleRegion();

 s3ImageType::IndexType start = region.GetIndex();
 s3ImageType::SizeType size = region.GetSize();

 permutedImage->SetRequestedRegion( region );

 const unsigned int firstSlice = start[2] +1 ;
 const unsigned int lastSlice = start[2] + size[2];

 //std::string format = "D:\\projects\\daten\\output\\TestVolume-%04d.dcm";
 std::string format = "TestVolume-%04d.dcm";

 typedef itk::NumericSeriesFileNames NumericNamesGeneratorType;

 NumericNamesGeneratorType::Pointer numericNamesGenerator = 
                                             NumericNamesGeneratorType::New();

 numericNamesGenerator->SetSeriesFormat( format.c_str() );
 numericNamesGenerator->SetStartIndex( firstSlice );
 numericNamesGenerator->SetEndIndex( lastSlice );
 numericNamesGenerator->SetIncrementIndex( 1 );

 typedef itk::ImageSeriesWriter < s3ImageType, s2ImageType > SeriesWriterType;

 SeriesWriterType::Pointer seriesWriter = SeriesWriterType::New();

 std::cout << "starting seriesWriter" << std::endl;

 try 
   {
   seriesWriter->SetInput( permutedImage );   

   seriesWriter->SetImageIO( dicomIO );            

   // commented out so that the programm terminates normal
   std::cout << "HERE : Segmentation fault ??" << std::endl;
   seriesWriter->SetMetaDataDictionaryArray( 
        seriesReader->GetMetaDataDictionaryArray() );

   seriesWriter->SetStartIndex( firstSlice );
   seriesWriter->SetIncrementIndex( 1 );
   seriesWriter->SetFileNames( numericNamesGenerator->GetFileNames() );
   } 
 catch( itk::ExceptionObject & ex ) 
   {
   std::cout << "error at metaData" << std::endl;
   std::cout << ex << std::endl;
   }


 try
   {
   std::cout << "writing...";
   seriesWriter->Update();
   } 
  catch( itk::ExceptionObject &ex )
   {
   std::cout << ex << std::endl;
   }

 std::cout << "done" << std::endl;

 return 0;

 }



More information about the Insight-users mailing list