Bug for GPU Demons

I want to use GPU Demons in my application with multi-resolution framework. However, the current multi-resolution framework do not suport GPU Demons, thus I implement it by myself.

The main code is:

using VectorPixelType = itk::Vector< float, Dimension >;
using CPUDisplacementFieldType = itk::Image< VectorPixelType, Dimension >;
CPUDisplacementFieldType::Pointer cpuDisplacementField = CPUDisplacementFieldType::New();

using GPUImageType = itk::GPUImage<PixelType, Dimension>;
using GPUDisplacementFieldType = itk::GPUImage< VectorPixelType, Dimension >;
GPUDisplacementFieldType::Pointer gpuDisplacementField = GPUDisplacementFieldType::New();

using CPUTOGPUImageFilter = itk::CastImageFilter<InternalImageType, GPUImageType>;
CPUTOGPUImageFilter::Pointer movingImageCPUToGPUFilter = CPUTOGPUImageFilter::New();
CPUTOGPUImageFilter::Pointer fixImageCPUToGPUFilter = CPUTOGPUImageFilter::New();

using CPUToGPUDisplacementFieldFilter = itk::CastImageFilter<CPUDisplacementFieldType, GPUDisplacementFieldType>;
using GPUToCPUDisplacementFieldFilter = itk::CastImageFilter<GPUDisplacementFieldType, CPUDisplacementFieldType>;
CPUToGPUDisplacementFieldFilter::Pointer cpuToGpuDisplacementFieldFilter = CPUToGPUDisplacementFieldFilter::New();
GPUToCPUDisplacementFieldFilter::Pointer gpuToCpuDisplacementFieldFilter = GPUToCPUDisplacementFieldFilter::New();

using FieldExpanderType = itk::ResampleImageFilter<CPUDisplacementFieldType, CPUDisplacementFieldType>;
FieldExpanderType::Pointer fieldExpander = FieldExpanderType::New();

using RegistrationFilterType = itk::GPUDemonsRegistrationFilter<
GPUImageType,
GPUImageType,
GPUDisplacementFieldType>;
RegistrationFilterType::Pointer demonsFilter = RegistrationFilterType::New();

using ImagePyramidType = itk::MultiResolutionPyramidImageFilter<InternalImageType, InternalImageType>;
ImagePyramidType::Pointer movingImagePyramid = ImagePyramidType::New();
ImagePyramidType::Pointer fixImagePyramid = ImagePyramidType::New();

unsigned int nIterations[2] = { 2,1 };
int numberOfLevel = 2;
movingImagePyramid->SetNumberOfLevels(numberOfLevel);
fixImagePyramid->SetNumberOfLevels(numberOfLevel);

InternalImageType::Pointer fixImage = targetImageCaster->GetOutput();
InternalImageType::Pointer movingImage = matcher->GetOutput();

movingImagePyramid->SetInput(movingImage);
movingImagePyramid->UpdateLargestPossibleRegion();

fixImagePyramid->SetInput(fixImage);
fixImagePyramid->UpdateLargestPossibleRegion();

bool lastShrinkFactorsAllOnes = false;

for (int i = 0; i < numberOfLevel; i++)
{
demonsFilter->SetInitialDisplacementField(nullptr);
movingImageCPUToGPUFilter->SetInput(movingImagePyramid->GetOutput(i));
movingImageCPUToGPUFilter->Update();
auto size1 = movingImageCPUToGPUFilter->GetOutput()->GetLargestPossibleRegion().GetSize();
demonsFilter->SetMovingImage(movingImageCPUToGPUFilter->GetOutput());

fixImageCPUToGPUFilter->SetInput(fixImagePyramid->GetOutput(i));
fixImageCPUToGPUFilter->Update();
auto size2 = fixImageCPUToGPUFilter->GetOutput()->GetLargestPossibleRegion().GetSize();
demonsFilter->SetFixedImage(fixImageCPUToGPUFilter->GetOutput());

demonsFilter->SetNumberOfIterations(nIterations[i]);

lastShrinkFactorsAllOnes = true;
for (int idim=0; idim<Dimension; idim++)
{
auto a = fixImagePyramid->GetSchedule()[i];
if (fixImagePyramid->GetSchedule()[i][idim] > 1)
{
lastShrinkFactorsAllOnes = false;
break;
}
}
demonsFilter->UpdateLargestPossibleRegion();
gpuDisplacementField = demonsFilter->GetOutput();
gpuDisplacementField->DisconnectPipeline();
gpuToCpuDisplacementFieldFilter->SetInput(gpuDisplacementField);
gpuToCpuDisplacementFieldFilter->Update();
cpuDisplacementField = gpuToCpuDisplacementFieldFilter->GetOutput();

movingImagePyramid->GetOutput(i)->ReleaseData();
fixImagePyramid->GetOutput(i)->ReleaseData();

}

And the bug is happen in demonsFilter->UpdateLargestPossibleRegion();, and the bug information is:

Microsoft C++ exception: itk::ExceptionObject at memory location 0x00000078DA99E650.

And the bug is located in: itkProcessObject.cxx, line 1781: this->GenerateData()

I am pretty sure that the moving and fix image for demons filter is correct. I use movingImageCPUToGPUFilter->GetOutput()->GetLargestPossibleRegion().GetSize() and fixImageCPUToGPUFilter->GetOutput()->GetLargestPossibleRegion().GetSize() to obtain the input image size, and they are correct.

Finally, I don’t know what’s wrong with my code.

1 Like

Try putting your code inside a try block. That way you will get a more informative error message.

2 Likes