Указатель как аргумент функции в ITK / C ++ - не может заставить его работать

0

Я новичок как для ITK, так и для C++, и в настоящее время я нахожусь в процессе создания тестовой программы для алгоритма регистрации изображений. В своем сообщении я расскажу о специфике того, что я делаю, используя терминологию ITK. Тем не менее, я ожидаю, что любой опытный C++ -программист должен быть в состоянии сказать, что не так с моим кодом, не понимая специфику ITK, так как я думаю, что просто делаю что-то неправильно в своих ссылках/разыменовании. Вещь, которую нужно отслеживать здесь (поясняется более подробно ниже), это переменная типа MetaDataContainer, называемая метаданные во всех функциях. Если какая-либо из особенностей ITK вас смущает, просьба указать более подробную информацию, но я не хочу слишком долго писать это оригинальное сообщение. Во всяком случае, здесь идет:

Мне нужно будет читать и писать dicom-изображения всего несколько раз в рамках выполнения программы, поэтому каждый раз, когда я выполняю все шаги процессов чтения/записи, я решил написать для них отдельные функции. Так как я должен использовать некоторые данные из процесса чтения, такие как MetaDataDictionaryArray в выходном файле, функция readDicom (а также другая функция, preregistrationOperations) возвращает кортеж:

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

Другим важным типедепом, о котором следует знать, является MetaDataContainer, который сам по себе является указателем на словарь DictionaryRawPointer. От ItkImageSeriesReader.h:

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

В моем собственном заголовочном файле feir.h:

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

Другие типы те же, что и в ITK-примерах для обработки Dicom. Грубая схема моей программы показана ниже.

Однако эта программа вылетает в функции writeDicom с ошибкой "... векторный индекс вне диапазона". Я сузил ошибку до привязки к MetaDataDictionaryArray. Его размер, когда dicoms сначала считываются в reaDicom, например, 64 (количество файлов в серии), но когда он возвращается в preRegistrationOperations, его размер внезапно равен 0, и тогда этот контейнер с нулевым размером передается to writeDicom, который падает.

EDIT: сам авария происходит на seriesWriter->Update() -line.

Я попытался обойти эту проблему, используя вместо этого указатели MetaDataContainer, но проблема сохраняется. Я мог бы добавить, что Im совершенно новый для C++ тоже (более физик, чем программист). Может ли кто-нибудь помочь мне в этом? Он должен быть достаточно простым, чтобы вернуть MetaDataContainer в кортеж из readDicom, распаковать его в preRegistrationOperations и передать его writeDicom, но как бы я ни старался, я не могу заставить его работать.

С уважением, Микаэль

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 );       
   …
}
  • 0
    Вы говорите, что программа аварийно завершает работу в функции writeDicom с сообщением «… векторный индекс вне диапазона» , но показанная строка writeDicom только передает указатель на другую функцию. Вы уверены, что программа вылетает на этой линии?
  • 0
    @ user2079303, он падает в блоке try-catch сразу после показанной строки, содержащей команду seriesWriter->Update(); Когда я печатаю metaData-Zsize () на стандартный вывод внутри readDicom, это 64, что правильно, поскольку у меня 64 DICOM-изображения, но когда я печатаю его размер в других функциях, его 0, поэтому что-то идет не так, когда я возвращаю его от readDicom.
Показать ещё 5 комментариев
Теги:
pointers
itk

1 ответ

0

Может быть, GetMetaDataDictionaryArray просто возвращает необработанный указатель члена читателя серии, но когда вы выходите из readDicom, читатель выходит из сферы действия. Я ожидал бы большего, что у вас был segfault в этом случае, но, возможно, это направление для изучения. Вместо того, чтобы возвращать кортеж, вы можете добавить 4 дополнительных аргумента в свою функцию, где для хранения результата (для более легкой отладки).

Прикосновение к словарю это всегда неприятно, вот пример http://www.itk.org/Wiki/ITK/Examples/DICOM/ResampleDICOM (но здесь они читают ломтик словаря по срезу). Вы уверены, что вам нужно его обновить? Некоторые поля будут автоматически обновляться автором dicom (например, ориентацией), вы никоим образом не можете их принудить.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню