This example illustrates the class otb::KullbackLeiblerProfileImageFilter for detecting changes between pairs of images, according to a range of window size. This example is very similar, in its principle, to all of the change detection examples, especially the distance between distributions one which uses a fixed window size.

The main differences are:

  • a set of window range instead of a fixed size of window
  • an output of type otb::VectorImage

Then, the program begins with the otb::VectorImage and the otb::KullbackLeiblerProfileImageFilter header files in addition to those already detailed in the otb::MeanRatioImageFilter example.


Result of the Kullback-Leibler profile change detector, colored composition including the first, 12th and 24th channel of the generated output.

Example usage:

./KullbackLeiblerProfileChDet Input/GomaAvant.png Input/GomaApres.png Output/KLProfileChDet.png 5 51 1 12 24

Example source code (KullbackLeiblerProfileChDet.cxx):

#include "otbImage.h"
#include "otbMultiChannelExtractROI.h"
#include "otbVectorRescaleIntensityImageFilter.h"
#include "otbKullbackLeiblerProfileImageFilter.h"
#include "otbImageFileReader.h"
#include "otbImageFileWriter.h"

int main(int argc, char* argv[])
  if (argc != 9)
    std::cerr << "Change detection based on Kullback-Leibler distance between local pdf through an Edgeworth approximation\n";
    std::cerr << argv[0] << " imgAv imgAp imgResu winSizeMin winSizeMax outRedIndex outGreenIndex outBlueIndex\n";
    return EXIT_FAILURE;

  char*        fileName1   = argv[1];
  char*        fileName2   = argv[2];
  char*        fileNameOut = argv[3];
  int          winSizeMin  = atoi(argv[4]);
  int          winSizeMax  = atoi(argv[5]);
  unsigned int ri          = atoi(argv[6]);
  unsigned int gi          = atoi(argv[7]);
  unsigned int bi          = atoi(argv[8]);

  const unsigned int Dimension = 2;
  using PixelType              = double;
  using OutPixelType           = unsigned char;

  // The KullbackLeiblerProfileImageFilter is templated over
  // the types of the two input images and the type of the generated change
  // image (which is now of multi-components), in a similar way as the
  // KullbackLeiblerDistanceImageFilter.
  using ImageType           = otb::Image<PixelType, Dimension>;
  using VectorImageType     = otb::VectorImage<PixelType, Dimension>;
  using FilterType          = otb::KullbackLeiblerProfileImageFilter<ImageType, ImageType, VectorImageType>;
  using OutVectorImageType  = otb::VectorImage<OutPixelType, Dimension>;
  using ReaderType          = otb::ImageFileReader<ImageType>;
  using WriterType          = otb::ImageFileWriter<OutVectorImageType>;
  using ChannelSelecterType = otb::MultiChannelExtractROI<PixelType, PixelType>;
  using RescalerType        = otb::VectorRescaleIntensityImageFilter<VectorImageType, OutVectorImageType>;

  // The different elements of the pipeline can now be instantiated in the
  // same way as the ratio of means change detector example.
  ReaderType::Pointer reader1 = ReaderType::New();

  ReaderType::Pointer reader2 = ReaderType::New();

  // Two parameters are now required to give the minimum and the maximum size
  // of the analysis window. The program will begin by performing change
  // detection through the smaller window size and then applying moments update
  // by incrementing the radius of the analysis window (i.e. add a ring of
  // width 1 pixel around the current neightborhood shape). The process is
  // applied until the larger window size is reached.
  FilterType::Pointer filter = FilterType::New();
  filter->SetRadius((winSizeMin - 1) / 2, (winSizeMax - 1) / 2);

  ChannelSelecterType::Pointer channelSelecter = ChannelSelecterType::New();

  RescalerType::Pointer rescaler = RescalerType::New();
  OutVectorImageType::PixelType min, max;

  WriterType::Pointer writer = WriterType::New();