# Filter Image In Fourier Domain¶

## Synopsis¶

Filter an Image in the Fourier Domain One of the most common image processing operations performed in the Fourier Domain is the masking of the spectrum in order to modulate a range of spatial frequencies from the input image. This operation is typically performed by taking the input image, computing its Fourier transform using a FFT filter, masking the resulting image in the Fourier domain with a mask, and finally taking the result of the masking and computing its inverse Fourier transform.

Input image

Output image

## Code¶

### C++¶

```#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkForwardFFTImageFilter.h"
#include "itkGaussianImageSource.h"
#include "itkFFTShiftImageFilter.h"
#include "itkMultiplyImageFilter.h"
#include "itkInverseFFTImageFilter.h"

int
main(int argc, char * argv[])
{
if (argc < 3)
{
std::cerr << "Usage: " << std::endl;
std::cerr << argv[0];
std::cerr << " <InputFileName> <OutputFileName>";
std::cerr << " [Sigma]";
std::cerr << std::endl;
return EXIT_FAILURE;
}

const char * inputFileName = argv[1];
const char * outputFileName = argv[2];
double       sigmaValue = 0.5;
if (argc > 3)
{
sigmaValue = std::stod(argv[3]);
}

constexpr unsigned int Dimension = 3;

using PixelType = float;
using RealImageType = itk::Image<PixelType, Dimension>;

// Some FFT filter implementations, like VNL's, need the image size to be a
// multiple of small prime numbers.
// Input size is [48, 62, 42].  Pad to [48, 64, 48].

using ForwardFFTFilterType = itk::ForwardFFTImageFilter<RealImageType>;
using ComplexImageType = ForwardFFTFilterType::OutputImageType;
ForwardFFTFilterType::Pointer forwardFFTFilter = ForwardFFTFilterType::New();

try
{
forwardFFTFilter->UpdateOutputInformation();
}
catch (itk::ExceptionObject & error)
{
std::cerr << "Error: " << error << std::endl;
return EXIT_FAILURE;
}

// A Gaussian is used here to create a low-pass filter.
using GaussianSourceType = itk::GaussianImageSource<RealImageType>;
GaussianSourceType::Pointer gaussianSource = GaussianSourceType::New();
gaussianSource->SetNormalized(true);
ComplexImageType::ConstPointer        transformedInput = forwardFFTFilter->GetOutput();
const ComplexImageType::RegionType    inputRegion(transformedInput->GetLargestPossibleRegion());
const ComplexImageType::SizeType      inputSize = inputRegion.GetSize();
const ComplexImageType::SpacingType   inputSpacing = transformedInput->GetSpacing();
const ComplexImageType::PointType     inputOrigin = transformedInput->GetOrigin();
const ComplexImageType::DirectionType inputDirection = transformedInput->GetDirection();
gaussianSource->SetSize(inputSize);
gaussianSource->SetSpacing(inputSpacing);
gaussianSource->SetOrigin(inputOrigin);
gaussianSource->SetDirection(inputDirection);
GaussianSourceType::ArrayType sigma;
GaussianSourceType::PointType mean;
sigma.Fill(sigmaValue);
for (unsigned int ii = 0; ii < Dimension; ++ii)
{
const double halfLength = inputSize[ii] * inputSpacing[ii] / 2.0;
sigma[ii] *= halfLength;
mean[ii] = inputOrigin[ii] + halfLength;
}
mean = inputDirection * mean;
gaussianSource->SetSigma(sigma);
gaussianSource->SetMean(mean);

using FFTShiftFilterType = itk::FFTShiftImageFilter<RealImageType, RealImageType>;
FFTShiftFilterType::Pointer fftShiftFilter = FFTShiftFilterType::New();
fftShiftFilter->SetInput(gaussianSource->GetOutput());

using MultiplyFilterType = itk::MultiplyImageFilter<ComplexImageType, RealImageType, ComplexImageType>;
MultiplyFilterType::Pointer multiplyFilter = MultiplyFilterType::New();
multiplyFilter->SetInput1(forwardFFTFilter->GetOutput());
multiplyFilter->SetInput2(fftShiftFilter->GetOutput());

using InverseFilterType = itk::InverseFFTImageFilter<ComplexImageType, RealImageType>;
InverseFilterType::Pointer inverseFFTFilter = InverseFilterType::New();
inverseFFTFilter->SetInput(multiplyFilter->GetOutput());

using WriterType = itk::ImageFileWriter<RealImageType>;
WriterType::Pointer writer = WriterType::New();
writer->SetFileName(outputFileName);
writer->SetInput(inverseFFTFilter->GetOutput());
try
{
writer->Update();
}
catch (itk::ExceptionObject & error)
{
std::cerr << "Error: " << error << std::endl;
return EXIT_FAILURE;
}

return EXIT_SUCCESS;
}
```