[solved] Padding without extending image size


(Antoine Letouzey) #1

Hi,

I’m trying to add an uniform (in color and size) margin to a 3D image and the only filter that always comes up in google is itk::ConstantPadImageFilter. https://itk.org/Doxygen/html/classitk_1_1ConstantPadImageFilter.html

Documentation clearly states:

Increase the image size by padding with a constant value.

But I would like the output image to have the same size as the input image, i.e. I would like the padding to go “inward” and overwrite some of the content of my image.
Just for information, here is the code I have that creates nice black margins but increase the size of my image by 10 in all dimensions (5+5).

// add black border to prevent leakage
using ConstantPadImageFilterType = itk::ConstantPadImageFilter <Image3d, Image3d>;
ConstantPadImageFilterType::Pointer padFilter = ConstantPadImageFilterType::New();
Image3d::SizeType v_ExtendRegion;
v_ExtendRegion.Fill(5); // 5 pixels wide
padFilter->SetInput(v_CropedImg);
padFilter->SetPadLowerBound(v_ExtendRegion);
padFilter->SetPadUpperBound(v_ExtendRegion);
padFilter->SetConstant(-3000); // very low value (black)
padFilter->Update();

Any idea on how to proceed from there ?


(Pablo Hernandez-Cerdan) #2

One approach is to first crop the image, see example. And then pad the cropped image.

Following the example, I think the cropSize you want is 10 (this will crop 5 from each side).

Image3d::SizeType cropSize;
cropSize.Fill(10)

And then use your current pad size v_ExtendRegion.Fill(5) with the cropped image.


(Antoine Letouzey) #3

Well, thanks a lot, that did the trick.

I had to set the cropsize to 5 and not 10 though. Otherwise the resulting image is somehow 10 pixels wider. It seems contre-intuitive when I read the comments from the page you linked.
The code bellow works for me.

// add black border to prevent leakage
// first shrink the image
using CropImageFilterType = itk::CropImageFilter <Image3d, Image3d>;
CropImageFilterType::Pointer cropFilter = CropImageFilterType::New();
cropFilter->SetInput(v_CropedImg);
Image3d::SizeType cropSize;
cropSize.Fill(5);
cropFilter->SetBoundaryCropSize(cropSize);

// then expand with black borders
using ConstantPadImageFilterType = itk::ConstantPadImageFilter <Image3d, Image3d>;
ConstantPadImageFilterType::Pointer padFilter = ConstantPadImageFilterType::New();
Image3d::SizeType v_ExtendRegion;
v_ExtendRegion.Fill(5);
padFilter->SetInput(cropFilter->GetOutput());
padFilter->SetPadLowerBound(v_ExtendRegion);
padFilter->SetPadUpperBound(v_ExtendRegion);
padFilter->SetConstant(-3000);
padFilter->Update();
return padFilter->GetOutput();


(Pablo Hernandez-Cerdan) #4

Glad to hear it worked and seems easier if crop and pad share the same size, I was confused by the comment in the example.

By the way, instead of using -3000 as the constant you might find useful to use: itk::NumericTraits< Image3d::PixelType >::min() that will put a black pixel for any kind of image. You would need to #include "itkNumericTraits.h" for it to work.


(Antoine Letouzey) #5

thanks for the tip about the min value I added another filter to compute the min value of the image but this is better and faster :slight_smile:


(Pablo Hernandez-Cerdan) #6

Take into account that itk::NumericTraits::min() is the lowest possible pixel value given the pixel type (double, int, etc), the actual min value found in your image might be other. So your computation of that might be useful :smiley: !. ITK provides a way to compute min,max, mean, etc of an image in: https://itk.org/Doxygen/html/classitk_1_1StatisticsImageFilter.html


(Antoine Letouzey) #7

Yeah that’s the filter I used. I needed a low-enough value not to be mistaken as foreground. itk::NumericTraits::min() always qualifies for it in my application and is easier to compute.