Blank result with non-default variance for the Gaussian smoothing filter GPU implementation

Hi experts,

We have implemented the GPU-supported Gaussian smoothing filter. It works ok for the default variance and kernelWidth. However, when changing the variance parameter to a user-specified value, the GPU version of this filter will yield blank results, but the CPU version of this filter will yield correct results.

imageType::Pointer              imageSptr   = *reinterpret_cast<imageType::Pointer*>(itki);
            // NOTE: the following CPU filter is not used, but for some reason, if we do not create this CPU filter,
            //       the GPU filter will exit with an uncaught exception, exiting the action
            gaussianFilterType::Pointer     gaussian    = gaussianFilterType::New();

            // Do it with GPU
            gpuGaussianFilterType::Pointer     gpuGaussian    = gpuGaussianFilterType::New();
            cpu2gpuCastFilterType::Pointer cpu2gpu = cpu2gpuCastFilterType::New();
            gpu2cpuCastFilterType::Pointer gpu2cpu = gpu2cpuCastFilterType::New();
            cpu2gpu->SetInput(imageSptr);
            gpuGaussian->SetInput(cpu2gpu->GetOutput());
            gpuGaussian->SetVariance(parms->variance);
            gpuGaussian->SetMaximumKernelWidth(parms->kernelWidth);
            gpu2cpu->SetInput(gpuGaussian->GetOutput());
            gpu2cpu->Update();

            // Create image, fill it, and return
            imageType::Pointer          outImageSptr        = imageType::New();
            imageType::Pointer         *outImageSptrPtr     = new imageType::Pointer;
            outImageSptr->Graft(gpu2cpu->GetOutput());
            *outImageSptrPtr = outImageSptr;
            return reinterpret_cast<ITK_Image>(outImageSptrPtr);,

Any idea as to what is happening here? Am I missing a step in setting up the GPU filters? (like missed parameters or something else?)

@Tom_Birdsong might have some advice or questions for you.

Hi @Mumumia, welcome to the ITK community! Would you please provide a few more details regarding the issue you are seeing?

We have implemented the GPU-supported Gaussian smoothing filter.

Great! Do you mean that you have written your own GPU-supported filter, or are you using an existing implementation such as itkGPUDiscreteGaussianImageFilter?

If you are using itkGPUDiscreteGaussianImageFilter, you might take a look at itkGPUDiscreteGaussianImageFilterTest for an example of how to set up and run the filter. In particular note that there is a step for synchronizing the CPU and GPU buffers that is not present in the example above.

If that does not address the problem, please add type definitions to your code snippet so that it is clear what filters are being used in the example. For instance:

using imageType = itk::Image<float,2>;
using gpuGaussianFilterType = ???
using cpu2gpuCastFilterType = ???
1 Like

Hi @Tom_Birdsong, Happy New Year and thank you for your response. We are using itkGPUDiscreteGaussianImageFilter. Thank you for suggesting the example of how to set up and run the filter. I will try to synchronize the CPU and GPU buffers following the example you shared. I will let you know if the problem persists. Thank you!

Hi @Tom_Birdsong, I have tried to update the CPU and GPU buffers as you suggested in the example above. However, it is still yielding blank results.
I have included the type definitions as suggested.

#include "itkDiscreteGaussianImageFilter.h"
#include "itkGradientAnisotropicDiffusionImageFilter.h"
#include "itkGPUImage.h"
#include "itkGPUGradientAnisotropicDiffusionImageFilter.h"
#include "itkGPUDiscreteGaussianImageFilter.h"
#include "itkGaussianOperator.h"
#include "itkGPUImageToImageFilter.h"
#include "itkGPUNeighborhoodOperatorImageFilter.h"

typedef itk::Image<type, dim>                                           imageType;                                                  \
typedef itk::GPUImage<type, dim>                                        gpuImageType;                                             
typedef itk::DiscreteGaussianImageFilter<imageType, imageType>          gaussianFilterType;                                         \
typedef itk::GPUDiscreteGaussianImageFilter<gpuImageType, gpuImageType> gpuGaussianFilterType;                                      \
typedef itk::GradientAnisotropicDiffusionImageFilter<imageType, imageDOUBLEType> gradientDiffusionFilterType;                       \
typedef itk::GPUGradientAnisotropicDiffusionImageFilter<gpuImageType, gpuImageDOUBLEType> gpuGradientDiffusionFilterType;           \

typedef itk::CastImageFilter<imageType, gpuImageType>                   cpu2gpuCastFilterType;                                      \
typedef itk::CastImageFilter<gpuImageType, imageType>                   gpu2cpuCastFilterType;                                      \
imageType::Pointer              imageSptr   = *reinterpret_cast<imageType::Pointer*>(itki);
            gaussianFilterType::Pointer     gaussian    = gaussianFilterType::New();

            // Do it with GPU
            gpuGaussianFilterType::Pointer     gpuGaussian    = gpuGaussianFilterType::New();
            cpu2gpuCastFilterType::Pointer cpu2gpu = cpu2gpuCastFilterType::New();
            gpu2cpuCastFilterType::Pointer gpu2cpu = gpu2cpuCastFilterType::New();
            cpu2gpu->SetInput(imageSptr);
            gpuGaussian->SetInput(cpu2gpu->GetOutput());
            gpuGaussian->SetVariance(parms->variance);
            gpuGaussian->SetMaximumKernelWidth(parms->kernelWidth);
            gpuGaussian->GetOutput()->UpdateBuffers(); 
            gpu2cpu->SetInput(gpuGaussian->GetOutput());
            gpu2cpu->Update();

            // Create image, fill it, and return
            imageType::Pointer          outImageSptr        = imageType::New();
            imageType::Pointer         *outImageSptrPtr     = new imageType::Pointer;
            outImageSptr->Graft(gpu2cpu->GetOutput());
            *outImageSptrPtr = outImageSptr;
            return reinterpret_cast<ITK_Image>(outImageSptrPtr);,

The GradientAnisotropicDiffusionImageFilter works fine, but the Gaussian smoothing filter is yielding blank results. If I don’t specify the variance parameter, it will yield an output, but it is the same image as the input image, not smoothing was done at all.

Do you know what is causing this? Thank you so much for your help!