Bilateral Filter an Image#

Synopsis#

Bilateral filter an image.

Results#

../../../../_images/bafkreia6f57kj22tmfdijxbost4c47xz3mpixwicor7ix34zvrll3qcbqm

Input image.#

../../../../_images/bafkreiahbujdvlnyawpba75i226a45wjagrtyoqx3uxjzjhtob7ys7v7zy

Output In VTK Window#

Code#

C++#

#include "itkImage.h"
#include "itkImageFileReader.h"
#include "itkBilateralImageFilter.h"
#include "itkSubtractImageFilter.h"

#ifdef ENABLE_QUICKVIEW
#  include "QuickView.h"
#endif

int
main(int argc, char * argv[])
{
  // Verify command line arguments
  if (argc < 2)
  {
    std::cerr << "Usage: " << std::endl;
    std::cerr << argv[0] << " inputImageFile [domainSigma] [rangeSigma]" << std::endl;
    return EXIT_FAILURE;
  }
  double rangeSigma = 2.0;
  double domainSigma = 2.0;
  if (argc > 2)
  {
    domainSigma = std::stod(argv[2]);
  }
  if (argc > 3)
  {
    rangeSigma = std::stod(argv[3]);
  }

  // Parse command line arguments
  std::string inputFileName = argv[1];

  // Setup types
  using ImageType = itk::Image<float, 2>;
  using FilterType = itk::BilateralImageFilter<ImageType, ImageType>;
  using SubtractImageFilterType = itk::SubtractImageFilter<ImageType>;

  const auto input = itk::ReadImage<ImageType>(inputFileName);

  // Create and setup a derivative filter
  auto bilateralFilter = FilterType::New();
  bilateralFilter->SetInput(input);
  bilateralFilter->SetDomainSigma(domainSigma);
  bilateralFilter->SetRangeSigma(rangeSigma);

  auto diff = SubtractImageFilterType::New();
  diff->SetInput1(input);
  diff->SetInput2(bilateralFilter->GetOutput());

#ifdef ENABLE_QUICKVIEW
  QuickView viewer;
  viewer.AddImage(input.GetPointer(), true, itksys::SystemTools::GetFilenameName(argv[1]));

  std::stringstream desc;
  desc << "Bilateral\ndomainSigma = " << domainSigma << " rangeSigma = " << rangeSigma;
  viewer.AddImage(bilateralFilter->GetOutput(), true, desc.str());

  std::stringstream desc2;
  desc2 << "Original - Bilateral";
  viewer.AddImage(diff->GetOutput(), true, desc2.str());

  viewer.Visualize();
#endif
  return EXIT_SUCCESS;
}

Classes demonstrated#

template<typename TInputImage, typename TOutputImage>
class BilateralImageFilter : public itk::ImageToImageFilter<TInputImage, TOutputImage>

Blurs an image while preserving edges.

This filter uses bilateral filtering to blur an image using both domain and range “neighborhoods”. Pixels that are close to a pixel in the image domain and similar to a pixel in the image range are used to calculate the filtered value. Two gaussian kernels (one in the image domain and one in the image range) are used to smooth the image. The result is an image that is smoothed in homogeneous regions yet has edges preserved. The result is similar to anisotropic diffusion but the implementation in non-iterative. Another benefit to bilateral filtering is that any distance metric can be used for kernel smoothing the image range. Hence, color images can be smoothed as vector images, using the CIE distances between intensity values as the similarity metric (the Gaussian kernel for the image domain is evaluated using CIE distances). A separate version of this filter will be designed for color and vector images.

Bilateral filtering is capable of reducing the noise in an image by an order of magnitude while maintaining edges.

The bilateral operator used here was described by Tomasi and Manduchi in [128].

Todo:

Support color images

Support vector images

See also

GaussianOperator

See also

RecursiveGaussianImageFilter

See also

DiscreteGaussianImageFilter

See also

AnisotropicDiffusionImageFilter

See also

Image

See also

Neighborhood

See also

NeighborhoodOperator

ITK Sphinx Examples:

See itk::BilateralImageFilter for additional documentation.