简体   繁体   中英

Pointer as function argument in ITK/C++ - can't get it working

I'm new to both ITK and C++, and am currently in the process of setting up a testing program for an image registration algorithm. In my message I will tell the specifics of what I'm doing in using ITK-terminology. However, I expect that any experienced C++-programmer should be able to tell what's wrong with my code without understanding the specifics of ITK, since I think I'm just doing something wrong in my referencing/dereferencing. The thing to keep track of here (explained in more detail below) is the MetaDataContainer-type variable, called metaData in all functions. If any of the ITK-specifics confuse you, please ask for more details, but I didn't want to make this original message too long. Anyway, here goes:

I will have to read and write dicom-images quite a few times within the program execution, so instead of doing all the steps of the read/write processes every time, I decided to write separate functions for them. Since I have to use some data from the reading process, such as the MetaDataDictionaryArray in the output as well, the readDicom-function (as well as another function, preregistrationOperations) returns a tuple:

typedef std::tuple< ImageType::Pointer, MetaDataContainer, FileNamesContainer > ImageMetaOutputTuple;

The other important typedef to be aware of is the MetaDataContainer, which is itself a pointer to a DictionaryRawPointer-vector. From ItkImageSeriesReader.h:

typedef MetaDataDictionary                  DictionaryType;
typedef MetaDataDictionary *                DictionaryRawPointer;
typedef std::vector< DictionaryRawPointer > DictionaryArrayType;
typedef const DictionaryArrayType *         DictionaryArrayRawPointer;

In my own header-file, feir.h:

typedef itk::ImageSeriesWriter< ImageType, Image2DType >::DictionaryArrayRawPointer  MetaDataContainer;

The other types are the same as in the ITK-examples for Dicom-handling. The rough layout of my program is seen below.

This program crashes in the writeDicom-function however, with the error “…vector subscript out of range”. I have narrowed the error down to having to do with the MetaDataDictionaryArray. Its size when the dicoms are first read in reaDicom is eg 64 (the number of files in the series), but when it is returned to the preRegistrationOperations, its size is suddenly 0, and it is this zero-sized container that is then passed to writeDicom which crashes.

EDIT: the crash itself happens on the seriesWriter->Update() -line.

I have tried to get around this problem by using MetaDataContainer-pointers instead, but the problem persists. I might add that I'm quite new to C++ too (more of a physicist than a programmer). Can anybody help me in this? It should be simple enough to return a MetaDataContainer within a tuple from readDicom, unpack it in preRegistrationOperations, and pass it to writeDicom, but no matter how I try I can't get it to work.

Best regards, Mikael

ImageMetaOutputTuple preRegistrationOperations( std::string inputDir,  std::string outputDir, std::string seriesNumber, bool preparationsDone = false, bool verbose = true )
{ 
   // No output verbose if operations have already been done
   if (preparationsDone) verbose = false;

   // Read input-Dicoms
   ImageType::Pointer image;
   MetaDataContainer metaData;
   FileNamesContainer outputFilenames; 
   ImageMetaOutputTuple returnTuple = readDicom( inputDir, outputDir, seriesNumber, verbose );
   std::tie (image, metaData, outputFilenames) = returnTuple;    

   // Pass image and directory and filename information to writeDicom and write into outputDir
   if (!preparationsDone) {                
          try {
                 int resultCode = writeDicom( image, outputDir, outputFilenames, metaData );
          }
          catch (itk::ExceptionObject &ex) {
                 std::cout << "Exception caught in writeDICOM:" << std::endl;
                 std::cout << ex << std::endl;            
          }      
   }      
   return returnTuple;
}

-

int writeDicom ( ImageType::Pointer image, std::string inputDir, FileNamesContainer filenames, MetaDataContainer metaData )
{ 
            …
            seriesWriter->SetMetaDataDictionaryArray( metaData );  
            try {       
                 seriesWriter->Update();        
                 return 0;
               }
            catch {
                   ...
                  }
   …
}

-

ImageMetaOutputTuple readDicom ( std::string inputDir, std::string outputDir = "", std::string seriesNumber = "", bool verbose = true)
{      
   …
   image = reader->GetOutput();
   files = nameGenerator->GetOutputFileNames();
   MetaDataContainer metaData = reader->GetMetaDataDictionaryArray();
          …
ImageMetaOutputTuple returnTuple (image, metaData, files);
return returnTuple;
}

-

int main( int argc, char* argv[] )
{
   …
   ImageType::Pointer moving; 
   ImageType::Pointer target;
   std::tie(moving, std::ignore, std::ignore) = preRegistrationOperations( inputDir, movingDir, movingSeriesNumber, preparationsDone, verbose );       
   std::tie(target, std::ignore, std::ignore) = preRegistrationOperations( inputDir, targetDir, targetSeriesNumber, preparationsDone, verbose );       
   …
}

It could be that GetMetaDataDictionaryArray just returns the raw pointer of a member of the series reader, but when you exit from readDicom the reader goes out scope. I would expect more that you had a segfault in this case, but maybe it's a direction to look into. Instead of returning a tuple, you could add 4 extra arguments in your function where to store the result (for an easier debugging).

Touching the dictionary it's always nasty, here is an example http://www.itk.org/Wiki/ITK/Examples/DICOM/ResampleDICOM (but here they read the dictionary slice by slice). Are you sure that you need to update it? Some fields will be automatically updated by the dicom writer (for example orientation), you can not force them anyway.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM