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

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

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

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

Другой важный typedef, о котором нужно знать, это 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. Его размер, когда впервые читаются в reaDicom, например, 64 (количество файлов в серии), но когда он возвращается в preRegistrationOperations, его размер внезапно становится равным 0, и именно этот контейнер нулевого размера затем передается в writeDicom, который завершается сбоем.

РЕДАКТИРОВАТЬ: сам сбой происходит на seriesWriter->Update()-линия.

Я пытался обойти эту проблему, используя вместо этого MetaDataContainer-указатели, но проблема сохраняется. Могу добавить, что я тоже новичок в 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

Решение

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

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

0

Другие решения


По вопросам рекламы [email protected]