int main(int argc, char *argv[])
{
  if(argc != 3)
    {
    std::cerr << "Only gave " << argc << " arguments!" << std::endl;
    std::cerr << "Required arguments: image mask" << std::endl;
    return EXIT_FAILURE;
    }
  std::string imageFilename = argv[1];
  std::string maskFilename = argv[2];
  std::cout << "Reading image: " << imageFilename << std::endl;
  std::cout << "Reading mask: " << maskFilename << std::endl;

  typedef itk::ImageFileReader<FloatVectorImageType> VectorImageReaderType;
  VectorImageReaderType::Pointer imageReader = VectorImageReaderType::New();
  imageReader->SetFileName(imageFilename.c_str());
  imageReader->Update();

  typedef itk::ImageFileReader<Mask> MaskReaderType;
  MaskReaderType::Pointer maskReader = MaskReaderType::New();
  maskReader->SetFileName(maskFilename.c_str());
  maskReader->Update();

  itk::Size<2> size;
  size.Fill(21);

  itk::Index<2> sourceCorner;
  sourceCorner[0] = 319;
  sourceCorner[1] = 292;
  itk::ImageRegion<2> sourceRegion(sourceCorner, size);

  itk::Index<2> targetCorner;
  targetCorner[0] = 193;
  targetCorner[1] = 218;
  itk::ImageRegion<2> targetRegion(targetCorner, size);

  SelfPatchCompare patchCompare(imageReader->GetOutput()->GetNumberOfComponentsPerPixel());
  patchCompare.SetTargetRegion(targetRegion);
  patchCompare.SetImage(imageReader->GetOutput());
  patchCompare.SetMask(maskReader->GetOutput());

  float totalAbsoluteDifference = patchCompare.SlowTotalAbsoluteDifference(sourceRegion);
  float totalSquaredDifference = patchCompare.SlowTotalSquaredDifference(sourceRegion);

  std::cerr << "Total Absolute Difference: " << totalAbsoluteDifference << std::endl;
  std::cerr << "Total Squared Difference: " << totalSquaredDifference << std::endl;

  return EXIT_SUCCESS;
}
int main(int argc, char *argv[])
{
  // Verify arguments
  if(argc != 5)
    {
    std::cerr << "Required arguments: image imageMask patchRadius output" << std::endl;
    return EXIT_FAILURE;
    }

  // Parse arguments
  std::string imageFilename = argv[1];
  std::string maskFilename = argv[2];

  std::stringstream ssPatchRadius;
  ssPatchRadius << argv[3];
  int patchRadius = 0;
  ssPatchRadius >> patchRadius;

  std::string outputFilename = argv[4];
  
  // Output arguments
  std::cout << "Reading image: " << imageFilename << std::endl;
  std::cout << "Reading mask: " << maskFilename << std::endl;
  std::cout << "Patch radius: " << patchRadius << std::endl;
  std::cout << "Output: " << outputFilename << std::endl;

  typedef  itk::ImageFileReader< FloatVectorImageType > ImageReaderType;
  ImageReaderType::Pointer imageReader = ImageReaderType::New();
  imageReader->SetFileName(imageFilename.c_str());
  imageReader->Update();

  typedef  itk::ImageFileReader< Mask  > MaskReaderType;
  MaskReaderType::Pointer maskReader = MaskReaderType::New();
  maskReader->SetFileName(maskFilename.c_str());
  maskReader->Update();

  CriminisiInpainting Inpainting;
  Inpainting.SetPatchRadius(patchRadius);
  Inpainting.SetDebug(false);
  Inpainting.SetImage(imageReader->GetOutput());
  Inpainting.SetMask(maskReader->GetOutput());
  Inpainting.Inpaint();

  Helpers::WriteImage<FloatVectorImageType>(Inpainting.GetResult(), outputFilename);

  return EXIT_SUCCESS;
}
int main(int argc, char *argv[])
{
  if(argc != 3)
    {
    std::cerr << "Required arguments: image mask" << std::endl;
    return EXIT_FAILURE;
    }
  std::string imageFilename = argv[1];
  std::string maskFilename = argv[2];
  std::cout << "Reading image: " << imageFilename << std::endl;
  std::cout << "Reading mask: " << maskFilename << std::endl;

  typedef itk::ImageFileReader<FloatVectorImageType> ImageReaderType;
  ImageReaderType::Pointer imageReader = ImageReaderType::New();
  imageReader->SetFileName(imageFilename.c_str());
  imageReader->Update();

  typedef itk::ImageFileReader<Mask> MaskReaderType;
  MaskReaderType::Pointer maskReader = MaskReaderType::New();
  maskReader->SetFileName(maskFilename.c_str());
  maskReader->Update();

  std::shared_ptr<SelfPatchCompare> patchCompare(new SelfPatchCompare);
  patchCompare->SetNumberOfComponentsPerPixel(imageReader->GetOutput()->GetNumberOfComponentsPerPixel());
  //patchCompare->FunctionsToCompute.push_back(boost::bind(&SelfPatchCompare::SetPatchAverageAbsoluteSourceDifference,patchCompare,_1));
  //patchCompare->FunctionsToCompute.push_back(boost::bind(&SelfPatchCompare::SetPatchColorDifference,patchCompare,_1));
  patchCompare->FunctionsToCompute.push_back(boost::bind(&SelfPatchCompare::SetPatchDepthDifference,patchCompare.get(),_1));
  //patchCompare->SetImage(imageReader->GetOutput());
  //patchCompare->SetMask(maskReader->GetOutput());

  PatchBasedInpainting inpainting;
  inpainting.SetMask(maskReader->GetOutput());
  inpainting.SetImage(imageReader->GetOutput());
  //inpainting.PatchSortFunction = &SortByDepthDifference;
  //inpainting.SetPatchCompare(patchCompare);
  inpainting.Initialize();
  inpainting.Iterate();

  CandidatePairs candidatePairs = inpainting.GetPotentialCandidatePairs()[0];
  //patchCompare->SetPairs(&candidatePairs);
  //patchCompare->ComputeAllSourceDifferences();
  WriteImageOfScores(candidatePairs, imageReader->GetOutput()->GetLargestPossibleRegion(), "ScoreImage_TargetPatch.mha");

  return EXIT_SUCCESS;
}
void buildImageIntensityModelOnROI(const char* referenceFilename, const char* maskFilename, const char* dir, const char* outputImageFilename) {


	typedef itk::PCAModelBuilder<RepresenterType> ModelBuilderType;
	typedef itk::StatisticalModel<RepresenterType> StatisticalModelType;
    typedef std::vector<std::string> StringVectorType;
    typedef itk::DataManager<RepresenterType> DataManagerType;

    RepresenterType::Pointer representer = RepresenterType::New();

	typedef itk::ImageFileReader< ImageType > MaskReaderType;
	MaskReaderType::Pointer maskReader = MaskReaderType::New();
	maskReader->SetFileName( maskFilename );
    maskReader->Update();

	representer->SetReference( ReadImageFromFile(referenceFilename), maskReader->GetOutput() );

    StringVectorType filenames;
    getdir(dir, filenames, ".vtk");

    DataManagerType::Pointer dataManager = DataManagerType::New();
	dataManager->SetRepresenter(representer);

    for (StringVectorType::const_iterator it = filenames.begin(); it != filenames.end(); it++) {
        std::string fullpath = (std::string(dir) + "/") + *it;

        dataManager->AddDataset( ReadImageFromFile(fullpath), fullpath.c_str());
    }

	ModelBuilderType::Pointer pcaModelBuilder = ModelBuilderType::New();
    StatisticalModelType::Pointer model = pcaModelBuilder->BuildNewModel(dataManager->GetSampleDataStructure(), 0);

    std::cout<<"dimensionality of the data: "<<model->GetDomain().GetNumberOfPoints()<<", dimension of the images: "<<(*dataManager->GetSampleDataStructure().begin())->GetSample()->GetLargestPossibleRegion().GetNumberOfPixels()<<std::endl;

    std::cout<<"writing the mean sample to a png file..."<<std::endl;
    
	typedef itk::ImageFileWriter< ImageType > ImageWriterType;
	ImageWriterType::Pointer writer = ImageWriterType::New();
	writer->SetFileName( outputImageFilename );
	writer->SetInput(model->DrawSample());
    writer->Update();

}
int main(int argc, char *argv[])
{
  // Verify arguments
  if(argc != 5)
    {
    std::cerr << "Required arguments: image imageMask patchRadius outputPrefix" << std::endl;
    return EXIT_FAILURE;
    }

  // Parse arguments
  std::string imageFilename = argv[1];
  std::string maskFilename = argv[2];

  std::stringstream ssPatchRadius;
  ssPatchRadius << argv[3];
  int patchRadius = 0;
  ssPatchRadius >> patchRadius;

  std::string outputPrefix = argv[4];

  // Output arguments
  std::cout << "Reading image: " << imageFilename << std::endl;
  std::cout << "Reading mask: " << maskFilename << std::endl;
  std::cout << "Patch radius: " << patchRadius << std::endl;
  //std::cout << "Output: " << outputFilename << std::endl;

  typedef  itk::ImageFileReader< FloatVectorImageType > ImageReaderType;
  ImageReaderType::Pointer imageReader = ImageReaderType::New();
  imageReader->SetFileName(imageFilename.c_str());
  imageReader->Update();

  FloatVectorImageType::Pointer scaledImage = FloatVectorImageType::New();
  // Initialize
  Helpers::DeepCopy<FloatVectorImageType>(imageReader->GetOutput(), scaledImage);

  std::vector<float> maxValues = Helpers::MaxValuesVectorImage<float>(imageReader->GetOutput());

  // Scale all channels the same
//   for(unsigned int channel = 0; channel < imageReader->GetOutput()->GetNumberOfComponentsPerPixel(); ++channel)
//     {
//     Helpers::ScaleChannel<float>(imageReader->GetOutput(), channel, 1.0f, scaledImage);
//     }

  // Scale color channels
  for(unsigned int channel = 0; channel < 3; ++channel)
    {
    Helpers::ScaleChannel<float>(scaledImage, channel, 0.33f, scaledImage);
    }

  // Scale depth channel
  Helpers::ScaleChannel<float>(scaledImage, 3, 1.0f, scaledImage);

  Helpers::WriteImage<FloatVectorImageType>(scaledImage, "scaled.mha");

  typedef  itk::ImageFileReader< Mask > MaskReaderType;
  MaskReaderType::Pointer maskReader = MaskReaderType::New();
  maskReader->SetFileName(maskFilename.c_str());
  maskReader->Update();

  Mask::Pointer finalMask = Mask::New();
  ModifyMask(maskReader->GetOutput(), patchRadius, finalMask);

  cout.setf(ios::showpoint);

  std::vector<float> lambdas;
  for(unsigned int i = 0; i <= 10; ++i)
    {
    lambdas.push_back(0.1f * static_cast<float>(i));
    std::cout << "Using lambda " << lambdas[i] << std::endl;
    }

  std::shared_ptr<SelfPatchCompare> patchCompare(new SelfPatchCompare);
  patchCompare->SetNumberOfComponentsPerPixel(imageReader->GetOutput()->GetNumberOfComponentsPerPixel());
  //patchCompare->FunctionsToCompute.push_back(boost::bind(&SelfPatchCompare::SetPatchAverageAbsoluteSourceDifference,patchCompare,_1));
  patchCompare->FunctionsToCompute.push_back(boost::bind(&SelfPatchCompare::SetPatchColorDifference,patchCompare,_1));
  patchCompare->FunctionsToCompute.push_back(boost::bind(&SelfPatchCompare::SetPatchDepthDifference,patchCompare,_1));

  std::ofstream fout("scores.txt");

  fout.setf(ios::showpoint);
  for(unsigned int lambdaId = 0; lambdaId < lambdas.size(); ++lambdaId)
    {
    // Inpaint
    std::cout << "Inpainting with lambda = " << lambdas[lambdaId] << std::endl;

    PatchPair::DepthColorLambda = lambdas[lambdaId];

    CriminisiInpainting inpainting;
    //inpainting.SetDebugFunctionEnterLeave(true);
    inpainting.SetPatchRadius(patchRadius);
    inpainting.SetImage(scaledImage);
    inpainting.SetMask(finalMask);
    inpainting.SetMaxForwardLookPatches(3);
    inpainting.SetPatchCompare(patchCompare);

    inpainting.PatchSortFunction = &SortByDepthAndColor;
    //inpainting.PatchSortFunction = &SortByAverageAbsoluteDifference;

    //DepthAndColorDifference = ColorDifference * Lambda + (1.0 - Lambda) * DepthDifference;
    // When lambda = 0, only the depth is used
    // When lambda = 1, only the color is used

    inpainting.Initialize();
    inpainting.Inpaint();

    // Compute error
    itk::ImageRegionIterator<Mask> iterator(finalMask, finalMask->GetLargestPossibleRegion());
    float depthError = 0.0f;
    float colorError = 0.0f;

    while(!iterator.IsAtEnd())
      {
      if(finalMask->IsHole(iterator.GetIndex()))
	{
	colorError += ColorPixelDifference::Difference(scaledImage->GetPixel(iterator.GetIndex()), inpainting.GetCurrentOutputImage()->GetPixel(iterator.GetIndex()));
	depthError += DepthPixelDifference::Difference(scaledImage->GetPixel(iterator.GetIndex()), inpainting.GetCurrentOutputImage()->GetPixel(iterator.GetIndex()));
	}
      ++iterator;
      }
    std::cout << "colorError: " << colorError << std::endl;
    std::cout << "depthError: " << depthError << std::endl;

    fout << colorError << " " << depthError << std::endl;

    // Unscale all channels
    for(unsigned int channel = 0; channel < imageReader->GetOutput()->GetNumberOfComponentsPerPixel(); ++channel)
      {
      Helpers::ScaleChannel<float>(inpainting.GetCurrentOutputImage(), channel, maxValues[channel], inpainting.GetCurrentOutputImage());
      }

    std::stringstream ssFloat;
    ssFloat.setf(ios::showpoint);
    ssFloat << outputPrefix << "_float_lambda_" << lambdas[lambdaId] << ".mha";
    Helpers::WriteImage<FloatVectorImageType>(inpainting.GetCurrentOutputImage(), ssFloat.str());

    std::stringstream ssRGB;
    ssRGB.setf(ios::showpoint);
    ssRGB << outputPrefix << "_RGB_lambda_" << lambdas[lambdaId] << ".mha";
    Helpers::WriteVectorImageAsRGB(inpainting.GetCurrentOutputImage(), ssRGB.str());
    //Helpers::WriteVectorImageAsRGB(inpainting.GetCurrentOutputImage(), Helpers::ReplaceFileExtension(ss.str(), "png"));
    }

  fout.close();

  return EXIT_SUCCESS;
}
int main(int argc, char *argv[])
{
  if(argc != 3)
    {
    std::cerr << "Required arguments: image mask" << std::endl;
    return EXIT_FAILURE;
    }
  std::string imageFilename = argv[1];
  std::string maskFilename = argv[2];
  std::cout << "Reading image: " << imageFilename << std::endl;
  std::cout << "Reading mask: " << maskFilename << std::endl;

  typedef itk::ImageFileReader<FloatVectorImageType> ImageReaderType;
  ImageReaderType::Pointer imageReader = ImageReaderType::New();
  imageReader->SetFileName(imageFilename.c_str());
  imageReader->Update();

  std::cout << "Read image " << imageReader->GetOutput()->GetLargestPossibleRegion() << std::endl;

  typedef itk::ImageFileReader<Mask> MaskReaderType;
  MaskReaderType::Pointer maskReader = MaskReaderType::New();
  maskReader->SetFileName(maskFilename.c_str());
  maskReader->Update();

  std::cout << "Read mask " << maskReader->GetOutput()->GetLargestPossibleRegion() << std::endl;

  // Prepare image
  RGBImageType::Pointer rgbImage = RGBImageType::New();
  // TODO: update this to the new API
  //Helpers::VectorImageToRGBImage(imageReader->GetOutput(), rgbImage);

  OutputHelpers::WriteImage(rgbImage.GetPointer(), "Test/TestIsophotes.rgb.mha");

  typedef itk::RGBToLuminanceImageFilter< RGBImageType, FloatScalarImageType > LuminanceFilterType;
  LuminanceFilterType::Pointer luminanceFilter = LuminanceFilterType::New();
  luminanceFilter->SetInput(rgbImage);
  luminanceFilter->Update();

  FloatScalarImageType::Pointer blurredLuminance = FloatScalarImageType::New();
  // Blur with a Gaussian kernel
  unsigned int kernelRadius = 5;
  MaskOperations::MaskedBlur<FloatScalarImageType>(luminanceFilter->GetOutput(), maskReader->GetOutput(), kernelRadius,
                                            blurredLuminance);

  OutputHelpers::WriteImage<FloatScalarImageType>(blurredLuminance, "Test/TestIsophotes.blurred.mha");

  //inpainting.ComputeMaskedIsophotes(blurredLuminance, maskReader->GetOutput());

  //Helpers::WriteImage<FloatVector2ImageType>(inpainting.GetIsophoteImage(), );
  //HelpersOutput::Write2DVectorImage(inpainting.GetIsophoteImage(), "Test/TestIsophotes.isophotes.mha");

  itk::Size<2> size;
  size.Fill(21);

  // Target
  itk::Index<2> targetIndex;
  targetIndex[0] = 187;
  targetIndex[1] = 118;
  itk::ImageRegion<2> targetRegion(targetIndex, size);

  // Source
  itk::Index<2> sourceIndex;
  sourceIndex[0] = 176;
  sourceIndex[1] = 118;
  itk::ImageRegion<2> sourceRegion(sourceIndex, size);

  //PatchPair patchPair(Patch(sourceRegion), Patch(targetRegion));
  //PatchPair patchPair;
//   Patch sourcePatch(sourceRegion);
//   Patch targetPatch(targetRegion);
//   PatchPair patchPair(sourcePatch, targetPatch);

  //inpainting.FindBoundary();

//   std::vector<itk::Index<2> > borderPixels =
//     ITKHelpers::GetNonZeroPixels(inpainting.GetBoundaryImage(), targetRegion);

  itk::RGBPixel<unsigned char> black;
  black.SetRed(0);
  black.SetGreen(0);
  black.SetBlue(0);

  itk::RGBPixel<unsigned char> red;
  red.SetRed(255);
  red.SetGreen(0);
  red.SetBlue(0);

  itk::RGBPixel<unsigned char> darkRed;
  darkRed.SetRed(100);
  darkRed.SetGreen(0);
  darkRed.SetBlue(0);

  itk::RGBPixel<unsigned char> yellow;
  yellow.SetRed(255);
  yellow.SetGreen(255);
  yellow.SetBlue(0);

  itk::RGBPixel<unsigned char> green;
  green.SetRed(0);
  green.SetGreen(255);
  green.SetBlue(0);

  itk::RGBPixel<unsigned char> darkGreen;
  darkGreen.SetRed(0);
  darkGreen.SetGreen(100);
  darkGreen.SetBlue(0);

  itk::RGBPixel<unsigned char> blue;
  blue.SetRed(0);
  blue.SetGreen(0);
  blue.SetBlue(255);

  RGBImageType::Pointer output = RGBImageType::New();
  output->SetRegions(imageReader->GetOutput()->GetLargestPossibleRegion());
  output->Allocate();
  output->FillBuffer(black);

  ITKHelpers::BlankAndOutlineRegion(output.GetPointer(), targetRegion, black, red);
  ITKHelpers::BlankAndOutlineRegion(output.GetPointer(), sourceRegion, black, green);

  RGBImageType::Pointer target = RGBImageType::New();
  target->SetRegions(imageReader->GetOutput()->GetLargestPossibleRegion());
  target->Allocate();
  ITKHelpers::BlankAndOutlineRegion(target.GetPointer(), targetRegion, black, red);

  RGBImageType::Pointer source = RGBImageType::New();
  source->SetRegions(imageReader->GetOutput()->GetLargestPossibleRegion());
  source->Allocate();
  ITKHelpers::BlankAndOutlineRegion(source.GetPointer(), sourceRegion, black, green);

  // itk::Offset<2> offset = targetIndex - sourceIndex;
  /*
  for(unsigned int pixelId = 0; pixelId < borderPixels.size(); ++pixelId)
    {
    itk::Index<2> targetPatchSourceSideBoundaryPixel = borderPixels[pixelId];
    itk::Index<2> sourcePatchTargetSideBoundaryPixel;
    //bool valid = GetAdjacentBoundaryPixel(currentPixel, candidatePairs[sourcePatchId], adjacentBoundaryPixel);
    bool valid = inpainting.GetAdjacentBoundaryPixel(targetPatchSourceSideBoundaryPixel, patchPair, sourcePatchTargetSideBoundaryPixel);

    target->SetPixel(targetPatchSourceSideBoundaryPixel, darkRed);
    source->SetPixel(sourcePatchTargetSideBoundaryPixel, darkGreen);

    if(!valid)
      {
      continue;
      }

    // Bring the adjacent pixel back to the target region.
    itk::Index<2> targetPatchTargetSideBoundaryPixel = sourcePatchTargetSideBoundaryPixel + offset;

    output->SetPixel(targetPatchSourceSideBoundaryPixel, darkRed);

    output->SetPixel(targetPatchTargetSideBoundaryPixel, blue);
    output->SetPixel(sourcePatchTargetSideBoundaryPixel, darkGreen);
    }
  */

//   OutputHelpers::WriteImage(output.GetPointer(), "Test/FollowIsophotes.Output.mha");
//   OutputHelpers::WriteImage(target.GetPointer(), "Test/FollowIsophotes.Target.mha");
//   OutputHelpers::WriteImage(source.GetPointer(), "Test/FollowIsophotes.Source.mha");

  return EXIT_SUCCESS;
}
int main(int argc, char *argv[])
{
  if(argc != 3)
    {
    std::cerr << "Required arguments: image mask" << std::endl;
    return EXIT_FAILURE;
    }
  std::string imageFilename = argv[1];
  std::string maskFilename = argv[2];
  std::cout << "Reading image: " << imageFilename << std::endl;
  std::cout << "Reading mask: " << maskFilename << std::endl;

  typedef itk::ImageFileReader<FloatVectorImageType> ImageReaderType;
  ImageReaderType::Pointer imageReader = ImageReaderType::New();
  imageReader->SetFileName(imageFilename.c_str());
  imageReader->Update();

  std::cout << "Read image " << imageReader->GetOutput()->GetLargestPossibleRegion() << std::endl;

  typedef itk::ImageFileReader<Mask> MaskReaderType;
  MaskReaderType::Pointer maskReader = MaskReaderType::New();
  maskReader->SetFileName(maskFilename.c_str());
  maskReader->Update();

  std::cout << "Read mask " << maskReader->GetOutput()->GetLargestPossibleRegion() << std::endl;

  // Prepare image
  RGBImageType::Pointer rgbImage = RGBImageType::New();
  // Helpers::VectorImageToRGBImage(imageReader->GetOutput(), rgbImage);
  // TODO: Update this call to new API
  //maskReader->GetOutput()->ApplyToImage(rgbImage.GetPointer(), Qt::black);
  OutputHelpers::WriteImage<RGBImageType>(rgbImage, "Test/TestIsophotes.rgb.mha");

  typedef itk::RGBToLuminanceImageFilter< RGBImageType, FloatScalarImageType > LuminanceFilterType;
  LuminanceFilterType::Pointer luminanceFilter = LuminanceFilterType::New();
  luminanceFilter->SetInput(rgbImage);
  luminanceFilter->Update();

  OutputHelpers::WriteImage<FloatScalarImageType>(luminanceFilter->GetOutput(), "Test/Luminance.mha");

//   PatchBasedInpainting inpainting;
//   inpainting.SetDebugImages(true);
//   inpainting.SetMask(maskReader->GetOutput());
//   inpainting.SetImage(imageReader->GetOutput());
  //Helpers::Write2DVectorImage(inpainting.GetIsophoteImage(), "Test/TestIsophotes.isophotes.mha");
  //inpainting.FindBoundary();

  // After blurVariance == 4, you cannot tell the difference in the output.
  for(unsigned int blurVariance = 0; blurVariance < 5; ++blurVariance)
    {
    std::string fileNumber = Helpers::ZeroPad(blurVariance, 2);

    FloatScalarImageType::Pointer blurredLuminance = FloatScalarImageType::New();

    // Blur with a Gaussian kernel
    MaskOperations::MaskedBlur(luminanceFilter->GetOutput(), maskReader->GetOutput(),
                               blurVariance, blurredLuminance.GetPointer());
    std::stringstream ssBlurredLuminance;
    ssBlurredLuminance << "Test/BlurredLuminance_" << fileNumber << ".mha";
    OutputHelpers::WriteImage(blurredLuminance.GetPointer(), ssBlurredLuminance.str());

    //Helpers::WriteImage<FloatScalarImageType>(blurredLuminance, "Test/TestIsophotes.blurred.mha");
    FloatVector2ImageType::Pointer gradient = FloatVector2ImageType::New();
    Derivatives::MaskedGradient(blurredLuminance.GetPointer(), maskReader->GetOutput(), gradient.GetPointer());

    // Boundary gradient
    typedef itk::MaskImageFilter< FloatVector2ImageType, UnsignedCharScalarImageType, FloatVector2ImageType > MaskFilterType;
    MaskFilterType::Pointer maskFilter = MaskFilterType::New();
    maskFilter->SetInput(gradient);
    //maskFilter->SetMaskImage(inpainting.GetBoundaryImage());
    maskFilter->Update();

    vtkSmartPointer<vtkPolyData> boundaryGradient = vtkSmartPointer<vtkPolyData>::New();
    // TODO: Convert this call to new API
    //Helpers::ConvertNonZeroPixelsToVectors(maskFilter->GetOutput(), boundaryGradient);
    std::stringstream ssPolyData;
    ssPolyData << "Test/BoundaryGradient_" << fileNumber << ".vtp";
    OutputHelpers::WritePolyData(boundaryGradient, ssPolyData.str());
    }

  return EXIT_SUCCESS;
}
int main(int argc, char *argv[])
{
  if(argc != 3)
    {
    std::cerr << "Required arguments: image mask" << std::endl;
    return EXIT_FAILURE;
    }
  std::string imageFilename = argv[1];
  std::string maskFilename = argv[2];
  std::cout << "Reading image: " << imageFilename << std::endl;
  std::cout << "Reading mask: " << maskFilename << std::endl;

  typedef itk::ImageFileReader<FloatVectorImageType> ImageReaderType;
  ImageReaderType::Pointer imageReader = ImageReaderType::New();
  imageReader->SetFileName(imageFilename.c_str());
  imageReader->Update();

  std::cout << "Read image " << imageReader->GetOutput()->GetLargestPossibleRegion() << std::endl;

  typedef itk::ImageFileReader<Mask> MaskReaderType;
  MaskReaderType::Pointer maskReader = MaskReaderType::New();
  maskReader->SetFileName(maskFilename.c_str());
  maskReader->Update();

  std::cout << "Read mask " << maskReader->GetOutput()->GetLargestPossibleRegion() << std::endl;

  // Prepare image
  RGBImageType::Pointer rgbImage = RGBImageType::New();
  Helpers::VectorImageToRGBImage(imageReader->GetOutput(), rgbImage);

  HelpersOutput::WriteImage<RGBImageType>(rgbImage, "Test/TestIsophotes.rgb.mha");

  typedef itk::RGBToLuminanceImageFilter< RGBImageType, FloatScalarImageType > LuminanceFilterType;
  LuminanceFilterType::Pointer luminanceFilter = LuminanceFilterType::New();
  luminanceFilter->SetInput(rgbImage);
  luminanceFilter->Update();

  FloatScalarImageType::Pointer blurredLuminance = FloatScalarImageType::New();
  // Blur with a Gaussian kernel
  unsigned int kernelRadius = 5;
  Helpers::MaskedBlur<FloatScalarImageType>(luminanceFilter->GetOutput(), maskReader->GetOutput(), kernelRadius, blurredLuminance);

  HelpersOutput::WriteImage<FloatScalarImageType>(blurredLuminance, "Test/TestIsophotes.blurred.mha");


  PatchBasedInpainting inpainting(NULL, maskReader->GetOutput());
  //inpainting.SetMask(maskReader->GetOutput());
  //inpainting.SetImage(imageReader->GetOutput());

  //inpainting.FindBoundary();

  for(unsigned int blurVariance = 0; blurVariance < 10; ++blurVariance)
    {
    //inpainting.ComputeBoundaryNormals(blurVariance);

    std::stringstream ss;
    ss << "Test/BoundaryNormals_" << blurVariance << ".mha";
    //HelpersOutput::Write2DVectorImage(inpainting.GetBoundaryNormalsImage(), ss.str());

    typedef itk::MaskImageFilter< FloatVector2ImageType, UnsignedCharScalarImageType, FloatVector2ImageType > MaskFilterType;
    MaskFilterType::Pointer maskFilter = MaskFilterType::New();
    //maskFilter->SetInput(inpainting.GetBoundaryNormalsImage());
    //maskFilter->SetMaskImage(inpainting.GetBoundaryImage());
    maskFilter->Update();

    vtkSmartPointer<vtkPolyData> boundaryNormals = vtkSmartPointer<vtkPolyData>::New();
    Helpers::ConvertNonZeroPixelsToVectors(maskFilter->GetOutput(), boundaryNormals);
    std::stringstream ssPolyData;
    ssPolyData << "Test/BoundaryNormals_" << blurVariance << ".vtp";
    HelpersOutput::WritePolyData(boundaryNormals, ssPolyData.str());
    }

  return EXIT_SUCCESS;
}