The image is full of zero after using resample filter.

Hi, I am sorry for troubling you so many times.
I am trying to resize my image from (530,530,604) ->(512,512,604), then i use ResampleImageFilter, ScaleTransform and BSplineInterpolateImageFunction to do it. The converted image is full of zeros,why?
code snippet:

ImageTypeFloat::SizeType newshape;
newshape[0] = 512;
newshape[1] = 512;
newshape[2] = 604;

ImageTypeFloat::Pointer img = reader->GetOutput();
ImageTypeFloat::SizeType current_size = img->GetLargestPossibleRegion().GetSize();
typedef itk::ResampleImageFilter<ImageTypeFloat, ImageTypeFloat,double,double> ResampleFilterType;
ResampleFilterType::Pointer resamplefilter = ResampleFilterType::New();

using TransformType = itk::ScaleTransform<double, 3>;
auto transform = TransformType::New();
TransformType::ParametersType scaleTransFormParameters = transform->GetParameters();
itk::Point<float, 3> center;

for (int i = 0; i < 3; i++)
{
	scaleTransFormParameters[i] = newshape[i] / current_size[i];
	center[i] = static_cast<float>(static_cast<float>(current_size[i] / 2));
}

transform->SetParameters(scaleTransFormParameters);
transform->SetCenter(center);

typedef itk::BSplineInterpolateImageFunction <ImageTypeFloat, double> InterpolatorType;
InterpolatorType::Pointer interpolator = InterpolatorType::New();

interpolator->SetSplineOrder(1);
resamplefilter->SetTransform(transform);
resamplefilter->SetInterpolator(interpolator);
resamplefilter->SetOutputParametersFromImage(img);

resamplefilter->Update();
ImageTypeFloat::Pointer out = resamplefilter->GetOutput();

I think this is integer division, which yields 0. Try static_cast<double>(newshape[i]) / current_size[i]

Also, if you input image has non-identity metadata (spacing or direction) the resampling will not work correctly.

1 Like

Hi, @dzenanz
I have changed the integer division into float division, but it has little effect.
I solved this problem by annotating resamplefilter->SetOutputParametersFromImage(img) and everything has to do with spacing ,origin and direction. I do not know the reason why it works.

What does this mean?

That means: //resamplefilter->SetOutputParametersFromImage(img) in c++.
@dzenanz

Aha, you meant commenting out that line.

In your code sample, I don’t see resamplefilter->SetInput(), so I can’t tell what is it that you are resampling. If you used img both as input, and output reference, that would be unexpected. I don’t know why it wouldn’t produce some result, though.

Hi @dzenanz .

the img is the input image. I don`t know what does it mean?

output reference

If you point to resamplefilter->SetOutputParametersFromImage(img);, I set spacing and shape underneath this code. Don`t be worry.

There is still a problem about resample, sometimes this function does not work(I mean the image full of zero ,but shape has changed), no matter scale up or scale dowm.

This is my full code in this function:


ImageTypeFloat::SizeType current_size = img->GetLargestPossibleRegion().GetSize();
typedef itk::ResampleImageFilter<ImageTypeFloat, ImageTypeFloat,double,double> ResampleFilterType;
ResampleFilterType::Pointer resamplefilter = ResampleFilterType::New();
	
using TransformType = itk::ScaleTransform<double, 3>;
auto transform = TransformType::New();
itk::FixedArray<float, 3> scaleTransFormParameters;
itk::Point<float, 3> center;
for (int i = 0; i < 3; i++)
{
	scaleTransFormParameters[i] = float(newshape[i]) / current_size[i];
	center[i] = 0;
	//center[i] = static_cast<float>(static_cast<float>(current_size[i] / 2));
}
transform->SetScale(scaleTransFormParameters);
transform->SetCenter(center);
	
typedef itk::BSplineInterpolateImageFunction <ImageTypeFloat, double> InterpolatorType;
InterpolatorType::Pointer interpolator = InterpolatorType::New();
interpolator->SetSplineOrder(order);

resamplefilter->SetTransform(transform);
resamplefilter->SetInterpolator(interpolator);
resamplefilter->SetOutputParametersFromImage(img);
resamplefilter->SetOutputSpacing(target_spacing);
resamplefilter->SetSize(newshape);
resamplefilter->SetInput(img);
resamplefilter->Update();
ImageTypeFloat::Pointer out = resamplefilter->GetOutput();

return out;

If you just want to change resolution of the image, you don’t need the scale transform - implicit identity transform will do. Your image probably has non-zero origin, which makes the resampling miss the object. Here is what I tried:

#include "itkImageFileWriter.h"
#include "itkImageFileReader.h"

#include "itkResampleImageFilter.h"
#include "itkScaleTransform.h"
#include "itkBSplineInterpolateImageFunction.h"
using ImageTypeFloat = itk::Image<float, 3>;
ImageTypeFloat::Pointer
resample(ImageTypeFloat::Pointer img, ImageTypeFloat::SizeType newshape, ImageTypeFloat::SpacingType target_spacing, unsigned order = 3)
{
  ImageTypeFloat::SizeType current_size = img->GetLargestPossibleRegion().GetSize();
  typedef itk::ResampleImageFilter<ImageTypeFloat, ImageTypeFloat, double, double> ResampleFilterType;
  ResampleFilterType::Pointer resamplefilter = ResampleFilterType::New();

  using TransformType = itk::ScaleTransform<double, 3>;
  auto                      transform = TransformType::New();
  itk::FixedArray<float, 3> scaleTransFormParameters;
  itk::Point<float, 3>      center;
  for (int i = 0; i < 3; i++)
  {
    scaleTransFormParameters[i] = float(newshape[i]) / current_size[i];
    center[i] = 0;
    // center[i] = static_cast<float>(static_cast<float>(current_size[i] / 2));
  }
  transform->SetScale(scaleTransFormParameters);
  transform->SetCenter(center);

  typedef itk::BSplineInterpolateImageFunction<ImageTypeFloat, double> InterpolatorType;
  InterpolatorType::Pointer                                            interpolator = InterpolatorType::New();
  interpolator->SetSplineOrder(order);

  //resamplefilter->SetTransform(transform);
  resamplefilter->SetInterpolator(interpolator);
  resamplefilter->SetOutputParametersFromImage(img);
  resamplefilter->SetOutputSpacing(target_spacing);
  resamplefilter->SetSize(newshape);
  resamplefilter->SetInput(img);
  resamplefilter->Update();
  ImageTypeFloat::Pointer out = resamplefilter->GetOutput();

  return out;
}

int
main()
{
  auto image = itk::ReadImage<ImageTypeFloat>("interp_out.nrrd");
  ImageTypeFloat::SizeType size = image->GetLargestPossibleRegion().GetSize(); // 64x64x8
  size[2] = 64;
  ImageTypeFloat::SpacingType target_spacing = image->GetSpacing();
  target_spacing[2] /= 8.0;
  auto resampled = resample(image, size, target_spacing);
  itk::WriteImage(resampled, "interp_64.nrrd");
}

When scale transform is used, the object gets distorted (in my case, significantly squished). When it is commented out, the resampling works as expected.

With scale transform:

Without scale transform:

Oh Thanks @dzenanz , it helps me a lot.
Why do these happen? I mean does the scale transform can not with B-spline?

Scale transform works with BSpline. But for resampling the image, you don’t need the scale transform. The physical size of the objects in the image remain the same, only the image sampling grid changes (size and spacing).

If you want to change the size of the objects in the image, then you use scaling transform. For example, you want to register a head of a child to a head of an adult - you would need scaling (together with translation and rotation).

1 Like