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.