void CriminisiInpainting::UpdateMask(const itk::Index<2> inputPixel)
{
  try
  {
    // Create a black patch
    Mask::Pointer blackPatch = Mask::New();
    //Helpers::CreateBlankPatch<UnsignedCharScalarImageType>(blackPatch, this->PatchRadius[0]);
    Helpers::CreateConstantPatch<Mask>(blackPatch, this->CurrentMask->GetValidValue(), this->PatchRadius[0]);
    itk::Index<2> pixel;
    pixel[0] = inputPixel[0] - blackPatch->GetLargestPossibleRegion().GetSize()[0]/2;
    pixel[1] = inputPixel[1] - blackPatch->GetLargestPossibleRegion().GetSize()[1]/2;

    // Paste it into the mask
    typedef itk::PasteImageFilter <Mask, Mask> PasteImageFilterType;
    PasteImageFilterType::Pointer pasteFilter = PasteImageFilterType::New();
    //pasteFilter->SetInput(0, this->CurrentMask);
    //pasteFilter->SetInput(1, blackPatch);
    pasteFilter->SetSourceImage(blackPatch);
    pasteFilter->SetDestinationImage(this->CurrentMask);
    pasteFilter->SetSourceRegion(blackPatch->GetLargestPossibleRegion());
    pasteFilter->SetDestinationIndex(pixel);
    pasteFilter->Update();

    // Not sure how Mask::DeepCopyFrom would work on the output of a filter, so do this manually.
    Helpers::DeepCopy<Mask>(pasteFilter->GetOutput(), this->CurrentMask);
    this->CurrentMask->SetHoleValue(this->OriginalMask->GetHoleValue());
    this->CurrentMask->SetValidValue(this->OriginalMask->GetValidValue());
  }
  catch( itk::ExceptionObject & err )
  {
    std::cerr << "ExceptionObject caught in UpdateMask!" << std::endl;
    std::cerr << err << std::endl;
    exit(-1);
  }
}
Ejemplo n.º 2
0
int main(int argc, char*argv[])
{
  if(argc != 3)
    {
    std::cerr << "Required arguments: mask output" << std::endl;
    return EXIT_FAILURE;
    }

  std::string maskFilename = argv[1];
  std::string outputFilename = argv[2];

  std::cout << "Reading mask: " << maskFilename << std::endl;
  std::cout << "Output: " << outputFilename << std::endl;

  Mask::Pointer mask = Mask::New();
  mask->Read(maskFilename.c_str());

  Mask::BoundaryImageType::Pointer boundaryImage = Mask::BoundaryImageType::New();
  boundaryImage->SetRegions(mask->GetLargestPossibleRegion());
  boundaryImage->Allocate();
  
//  mask->CreateBoundaryImage(boundaryImage.GetPointer(), mask->GetValidValue());
  mask->CreateBoundaryImage(boundaryImage.GetPointer(), Mask::VALID);
  
  ITKHelpers::WriteImage(boundaryImage.GetPointer(), outputFilename);

  return EXIT_SUCCESS;
}
static void CreateMask(Mask::Pointer mask)
{
  itk::Size<2> size;
  size.Fill(20);

  itk::Index<2> start;
  start.Fill(0);

  itk::ImageRegion<2> region(start,size);

  mask->SetRegions(region);
  mask->Allocate();
  mask->FillBuffer(mask->GetValidValue());

  itk::ImageRegionIterator<Mask> iterator(mask, mask->GetLargestPossibleRegion());

  while(!iterator.IsAtEnd())
    {
    if(iterator.GetIndex()[0] > 5 && iterator.GetIndex()[0] < 15 &&
       iterator.GetIndex()[1] > 5 && iterator.GetIndex()[1] < 15)
      {
      mask->SetPixel(iterator.GetIndex(), mask->GetHoleValue());
      }

    ++iterator;
    }
}
// Run with: image.png image.mask 15 filled.png
int main(int argc, char *argv[])
{
  // Verify arguments
  if(argc != 5)
  {
    std::cerr << "Required arguments: image.png image.mask patchHalfWidth output.png" << std::endl;
    std::cerr << "Input arguments: ";
    for(int i = 1; i < argc; ++i)
    {
      std::cerr << argv[i] << " ";
    }
    return EXIT_FAILURE;
  }

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

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

  std::string outputFilename = argv[4];

  // Output arguments
  std::cout << "Reading image: " << imageFilename << std::endl;
  std::cout << "Reading mask: " << maskFilename << std::endl;
  std::cout << "Patch half width: " << patchHalfWidth << std::endl;
  std::cout << "Output: " << outputFilename << std::endl;

  typedef itk::Image<itk::CovariantVector<float, 3>, 2> ImageType;

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

  ImageType::Pointer image = ImageType::New();
  ITKHelpers::DeepCopy(imageReader->GetOutput(), image.GetPointer());

  Mask::Pointer mask = Mask::New();
  mask->Read(maskFilename);

  std::cout << "Mask size: " << mask->GetLargestPossibleRegion().GetSize() << std::endl;
  std::cout << "hole pixels: " << mask->CountHolePixels() << std::endl;
  std::cout << "valid pixels: " << mask->CountValidPixels() << std::endl;

  // Setup the GUI system
  QApplication app( argc, argv );
  // Without this, after we close the first dialog
  // (after the first iteration that is not accepted automatically), the event loop quits.
  app.setQuitOnLastWindowClosed(false);

  DummyPatchesDriver(image, mask, patchHalfWidth);

  return app.exec();
}
Ejemplo n.º 5
0
void Mask::FindBoundary(UnsignedCharScalarImageType* boundaryImage) const
{
  // Compute the "outer" boundary of the region to fill. That is, we want the boundary pixels to be in the source region.

  //HelpersOutput::WriteImageConditional<Mask>(this->CurrentMask, "Debug/FindBoundary.CurrentMask.mha", this->DebugImages);
  //HelpersOutput::WriteImageConditional<Mask>(this->CurrentMask, "Debug/FindBoundary.CurrentMask.png", this->DebugImages);

  // Create a binary image (throw away the "dont use" pixels)
  Mask::Pointer holeOnly = Mask::New();
  holeOnly->DeepCopyFrom(this);

  itk::ImageRegionIterator<Mask> maskIterator(holeOnly, holeOnly->GetLargestPossibleRegion());
  // This should result in a white hole on a black background
  while(!maskIterator.IsAtEnd())
    {
    itk::Index<2> currentPixel = maskIterator.GetIndex();
    if(!holeOnly->IsHole(currentPixel))
      {
      holeOnly->SetPixel(currentPixel, holeOnly->GetValidValue());
      }
    ++maskIterator;
    }

  //HelpersOutput::WriteImageConditional<Mask>(holeOnly, "Debug/FindBoundary.HoleOnly.mha", this->DebugImages);
  //HelpersOutput::WriteImageConditional<Mask>(holeOnly, "Debug/FindBoundary.HoleOnly.png", this->DebugImages);

  // Since the hole is white, we want the foreground value of the contour filter to be black. This means that the boundary will
  // be detected in the black pixel region, which is on the outside edge of the hole like we want. However,
  // The BinaryContourImageFilter will change all non-boundary pixels to the background color, so the resulting output will be inverted -
  // the boundary pixels will be black and the non-boundary pixels will be white.

  // Find the boundary
  typedef itk::BinaryContourImageFilter <Mask, Mask> binaryContourImageFilterType;
  binaryContourImageFilterType::Pointer binaryContourFilter = binaryContourImageFilterType::New();
  binaryContourFilter->SetInput(holeOnly);
  binaryContourFilter->SetFullyConnected(true);
  binaryContourFilter->SetForegroundValue(holeOnly->GetValidValue());
  binaryContourFilter->SetBackgroundValue(holeOnly->GetHoleValue());
  binaryContourFilter->Update();

  //HelpersOutput::WriteImageConditional<Mask>(binaryContourFilter->GetOutput(), "Debug/FindBoundary.Boundary.mha", this->DebugImages);
  //HelpersOutput::WriteImageConditional<Mask>(binaryContourFilter->GetOutput(), "Debug/FindBoundary.Boundary.png", this->DebugImages);

  // Since we want to interpret non-zero pixels as boundary pixels, we must invert the image.
  typedef itk::InvertIntensityImageFilter <Mask> InvertIntensityImageFilterType;
  InvertIntensityImageFilterType::Pointer invertIntensityFilter = InvertIntensityImageFilterType::New();
  invertIntensityFilter->SetInput(binaryContourFilter->GetOutput());
  invertIntensityFilter->SetMaximum(255);
  invertIntensityFilter->Update();

  //this->BoundaryImage = binaryContourFilter->GetOutput();
  //this->BoundaryImage->Graft(binaryContourFilter->GetOutput());
  ITKHelpers::DeepCopy<UnsignedCharScalarImageType>(invertIntensityFilter->GetOutput(), boundaryImage);

  //HelpersOutput::WriteImageConditional<UnsignedCharScalarImageType>(this->BoundaryImage, "Debug/FindBoundary.BoundaryImage.mha", this->DebugImages);

}
Ejemplo n.º 6
0
int main(int argc, char*argv[])
{
  if(argc < 4)
  {
    std::cerr << "Required arguments: image mask output" << std::endl;
    return EXIT_FAILURE;
  }

  std::string imageFilename = argv[1];
  std::string maskFilename = argv[2];
  std::string outputFilename = argv[3];

  std::cout << "imageFilename: " << imageFilename << std::endl;
  std::cout << "maskFilename: " << maskFilename << std::endl;
  std::cout << "outputFilename: " << outputFilename << std::endl;

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

  Mask::Pointer sourceMask = Mask::New();
  sourceMask->Read(maskFilename);

  Mask::Pointer targetMask = Mask::New();
  targetMask->SetRegions(sourceMask->GetLargestPossibleRegion());
  targetMask->Allocate();
  ITKHelpers::SetImageToConstant(targetMask.GetPointer(), HoleMaskPixelTypeEnum::VALID);

  typedef SSD<ImageType> DistanceFunctorType;
  DistanceFunctorType* patchDistanceFunctor = new DistanceFunctorType;
  patchDistanceFunctor->SetImage(imageReader->GetOutput());

  typedef Propagator<DistanceFunctorType> PropagatorType;
  PropagatorType* propagationFunctor = new PropagatorType;

  typedef RandomSearch<ImageType, DistanceFunctorType> RandomSearchType;
  RandomSearchType* randomSearchFunctor = new RandomSearchType;

  typedef PatchMatch<ImageType, PropagatorType, RandomSearchType> PatchMatchType;
  PatchMatchType patchMatch;
  patchMatch.SetImage(imageReader->GetOutput());
  patchMatch.SetPatchRadius(3);
  
  patchMatch.SetPropagationFunctor(propagationFunctor);
  patchMatch.SetRandomSearchFunctor(randomSearchFunctor);

  patchMatch.Compute();

  NNFieldType::Pointer output = patchMatch.GetNNField();
  PatchMatchHelpers::WriteNNField(output.GetPointer(), "nnfield.mha");

  return EXIT_SUCCESS;
}
Ejemplo n.º 7
0
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, char*[])
{
//  typedef itk::Image<itk::CovariantVector<int, 3>, 2> ImageType;
  typedef itk::Image<itk::CovariantVector<unsigned char, 3>, 2> ImageType;

  ImageType::PixelType red;
  red.Fill(0);
  red[0] = 255;

  ImageType::PixelType black;
  black.Fill(0);

  ImageType::PixelType white;
  white.Fill(255);

  ImageType::PixelType green; // Note this is not 255 because then the magnitude of red and green would be the same,
  // which makes debugging hard since the gradient of the magnitude image is used internally (in IntroducedEnergy).
  green.Fill(0);
  green[1] = 122;

  ImageType::PixelType blue;
  blue.Fill(0);
  blue[2] = 255;

  ImageType::Pointer image = ImageType::New();
  itk::Index<2> imageCorner = {{0,0}};
  itk::Size<2> imageSize = {{100,100}};

  itk::ImageRegion<2> region(imageCorner,imageSize);
  image->SetRegions(region);
  image->Allocate();

  Mask::Pointer mask = Mask::New();
  mask->SetRegions(region);
  mask->Allocate();

  itk::ImageRegionIteratorWithIndex<Mask> initializeMaskIterator(mask, mask->GetLargestPossibleRegion());

  while(!initializeMaskIterator.IsAtEnd())
  {
    if(initializeMaskIterator.GetIndex()[0] < 55)
    {
      initializeMaskIterator.Set(mask->GetHoleValue());
    }
    else
    {
      initializeMaskIterator.Set(mask->GetValidValue());
    }

    ++initializeMaskIterator;
  }

  ITKHelpers::WriteImage(mask.GetPointer(), "mask.png");

  // Create a red image
  itk::ImageRegionIterator<ImageType> initializeIterator(image, image->GetLargestPossibleRegion());

  while(!initializeIterator.IsAtEnd())
  {
    initializeIterator.Set(red);

    ++initializeIterator;
  }

  // Setup source and target patch
  itk::Size<2> patchSize = {{10,10}};

  itk::Index<2> sourceCorner = {{10,10}};
  itk::ImageRegion<2> sourceRegion(sourceCorner, patchSize);

  itk::Index<2> targetCorner = {{50,50}};
  itk::ImageRegion<2> targetRegion(targetCorner, patchSize);

  itk::Index<2> perfectSourceCorner = {{75,75}};
  itk::ImageRegion<2> perfectSourceRegion(perfectSourceCorner, patchSize);

  // Make the source patch green
  itk::ImageRegionIterator<ImageType> sourceRegionIterator(image, sourceRegion);

  while(!sourceRegionIterator.IsAtEnd())
  {
    sourceRegionIterator.Set(green);

    ++sourceRegionIterator;
  }

  ITKHelpers::WriteImage(image.GetPointer(), "image.png");

  {
    ImageType::Pointer regionHighlightImage = ImageType::New();
    ITKHelpers::DeepCopy(image.GetPointer(), regionHighlightImage.GetPointer());

    ITKHelpers::OutlineRegion(regionHighlightImage.GetPointer(), sourceRegion, white);
    ITKHelpers::OutlineRegion(regionHighlightImage.GetPointer(), targetRegion, black);
    ITKHelpers::OutlineRegion(regionHighlightImage.GetPointer(), perfectSourceRegion, blue);

    ITKHelpers::WriteImage(regionHighlightImage.GetPointer(), "regions.png");
  }

  IntroducedEnergy<ImageType> introducedEnergy;
  introducedEnergy.SetDebugImages(true);

  // Bad match
  {
    std::cout << "Bad match:" << std::endl;

    float patchBoundaryEnergy = introducedEnergy.ComputeIntroducedEnergyPatchBoundary(image, mask, sourceRegion, targetRegion);
    std::cout << "patchBoundaryEnergy: " << patchBoundaryEnergy << std::endl;

    float maskBoundaryEnergy = introducedEnergy.ComputeIntroducedEnergyMaskBoundary(image, mask, sourceRegion, targetRegion);
    std::cout << "maskBoundaryEnergy: " << maskBoundaryEnergy << std::endl;

    float totalEnergy = introducedEnergy.ComputeIntroducedEnergy(image, mask, sourceRegion, targetRegion);
    std::cout << "totalEnergy: " << totalEnergy << std::endl;
  }

  // Perfect match
  {
    std::cout << "Perfect match:" << std::endl;
  //  IntroducedEnergy<ImageType> introducedEnergy;
    typedef IntroducedEnergy<ImageType> IntroducedEnergyType;

    float patchBoundaryEnergy = introducedEnergy.ComputeIntroducedEnergyPatchBoundary(image, mask, perfectSourceRegion, targetRegion);
    std::cout << "patchBoundaryEnergy: " << patchBoundaryEnergy << std::endl;

    float maskBoundaryEnergy = introducedEnergy.ComputeIntroducedEnergyMaskBoundary(image, mask, perfectSourceRegion, targetRegion);
    std::cout << "maskBoundaryEnergy: " << maskBoundaryEnergy << std::endl;

    float totalEnergy = introducedEnergy.ComputeIntroducedEnergy(image, mask, perfectSourceRegion, targetRegion);
    std::cout << "totalEnergy: " << totalEnergy << std::endl;
  }

  return EXIT_SUCCESS;
}
Ejemplo n.º 9
0
int main(int argc, char *argv[])
{
  unsigned int t = time(NULL);
  srand(t);

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

  itk::Index<2> index;
  index.Fill(0);

  itk::ImageRegion<2> region(index, size);
/*
  // Generate a random image (this method doesn't work with VectorImage)
  itk::RandomImageSource<FloatVectorImageType>::Pointer imageSource =
    itk::RandomImageSource<FloatVectorImageType>::New();
  imageSource->SetNumberOfThreads(1); // to produce non-random results
  imageSource->SetSize(size);
  imageSource->SetMin(0);
  imageSource->SetMax(100);
  imageSource->Update();
  FloatVectorImageType::Pointer image = imageSource->GetOutput();
*/
  // Generate a random image
  FloatVectorImageType::Pointer image = FloatVectorImageType::New();
  image->SetRegions(region);
  image->SetNumberOfComponentsPerPixel(3);
  image->Allocate();

  {
  itk::ImageRegionIterator<FloatVectorImageType> imageIterator(image, image->GetLargestPossibleRegion());

  while(!imageIterator.IsAtEnd())
    {
    FloatVectorImageType::PixelType pixel;
    pixel.SetSize(3);
    pixel[0] = drand48();
    pixel[1] = drand48();
    pixel[2] = drand48();
    imageIterator.Set(pixel);
    ++imageIterator;
    }
  }

  // Generate a random membership image
  IntImageType::Pointer membershipImage = IntImageType::New();
  membershipImage->SetRegions(region);
  membershipImage->Allocate();
  membershipImage->FillBuffer(0);

  {
  itk::ImageRegionIterator<IntImageType> membershipImageIterator(membershipImage, membershipImage->GetLargestPossibleRegion());

  while(!membershipImageIterator.IsAtEnd())
    {
    IntImageType::PixelType pixel;
    pixel = rand() / 1000;
    membershipImageIterator.Set(pixel);
    ++membershipImageIterator;
    }
  }

  // Write the image
  itk::ImageFileWriter<FloatVectorImageType>::Pointer imageWriter =
    itk::ImageFileWriter<FloatVectorImageType>::New();
  imageWriter->SetFileName("image.mha");
  imageWriter->SetInput(image);
  imageWriter->Update();

//   // Generate a random mask
//   itk::RandomImageSource<Mask>::Pointer maskSource = itk::RandomImageSource<Mask>::New();
//   maskSource->SetNumberOfThreads(1); // to produce non-random results
//   maskSource->SetSize(size);
//   maskSource->SetMin(0);
//   maskSource->SetMax(255);
//   maskSource->Update();
//
//   // Threshold the mask
//   //typedef itk::ThresholdImageFilter <UnsignedCharImageType> ThresholdImageFilterType;
//   typedef itk::BinaryThresholdImageFilter <Mask, Mask> ThresholdImageFilterType;
//   ThresholdImageFilterType::Pointer thresholdFilter = ThresholdImageFilterType::New();
//   thresholdFilter->SetInput(maskSource->GetOutput());
//   thresholdFilter->SetLowerThreshold(0);
//   thresholdFilter->SetUpperThreshold(122);
//   thresholdFilter->SetOutsideValue(1);
//   thresholdFilter->SetInsideValue(0);
//   thresholdFilter->Update();
//   Mask::Pointer mask = thresholdFilter->GetOutput();

  std::cout << "Creating mask..." << std::endl;
  Mask::Pointer mask = Mask::New();
  mask->SetRegions(region);
  mask->Allocate();

  {
  itk::ImageRegionIterator<Mask> maskIterator(mask, mask->GetLargestPossibleRegion());

  while(!maskIterator.IsAtEnd())
    {
    int randomNumber = rand()%10;
    //std::cout << "randomNumber: " << randomNumber << std::endl;
    if(randomNumber > 5)
      {
      maskIterator.Set(mask->GetHoleValue());
      }
    else
      {
      maskIterator.Set(mask->GetValidValue());
      }
    ++maskIterator;
    }
  }
  std::cout << "Writing mask..." << std::endl;
  // Write the mask
  itk::ImageFileWriter<Mask>::Pointer maskWriter = itk::ImageFileWriter<Mask>::New();
  maskWriter->SetFileName("mask.png");
  maskWriter->SetInput(mask);
  maskWriter->Update();

  std::cout << "Creating source patches..." << std::endl;
  unsigned int patchRadius = 10;
  // Create source patches
  itk::ImageRegionConstIterator<FloatVectorImageType> imageIterator(image, image->GetLargestPossibleRegion());
  std::vector<Patch> sourcePatches;
  while(!imageIterator.IsAtEnd())
    {
    itk::Index<2> currentPixel = imageIterator.GetIndex();
    itk::ImageRegion<2> region = Helpers::GetRegionInRadiusAroundPixel(currentPixel, patchRadius);
    if(image->GetLargestPossibleRegion().IsInside(region))
      {
      sourcePatches.push_back(Patch(region));
      }
    ++imageIterator;
    }
  std::cout << "Source patches: " << sourcePatches.size() << std::endl;
  itk::Size<2> targetSize;
  targetSize.Fill(patchRadius * 2 + 1);

  itk::Index<2> targetIndex;
  targetIndex.Fill(3);

  itk::ImageRegion<2> targetRegion(targetIndex, targetSize);
  Patch targetPatch(targetRegion);

  CandidatePairs pairs(targetPatch);
  pairs.AddPairFromPatch(targetPatch);

  itk::ImageRegion<2> adjacentRegion = targetRegion;
  itk::Index<2> adjacentIndex;
  adjacentIndex[0] = targetIndex[0] + 1;
  adjacentIndex[1] = targetIndex[1] + 1;
  adjacentRegion.SetIndex(adjacentIndex);
  Patch adjacentPatch(adjacentRegion);
  pairs.AddPairFromPatch(adjacentPatch);
  //pairs.AddPairFromPatch(sourcePatches[0]);

  SelfPatchCompare patchCompare;
  patchCompare.SetPairs(&pairs);
  patchCompare.SetImage(image);
  patchCompare.SetMask(mask);
  patchCompare.SetNumberOfComponentsPerPixel(3);
  patchCompare.SetMembershipImage(membershipImage);

  patchCompare.FunctionsToCompute.push_back(boost::bind(&SelfPatchCompare::SetPatchMembershipDifference,&patchCompare,_1));
  patchCompare.ComputeAllSourceDifferences();

  std::cout << "pairs: " << pairs.size() << std::endl;
  for(unsigned int i = 0; i < pairs.size(); ++i)
    {
    std::cout << "MembershipDifference: " << pairs[i].DifferenceMap[PatchPair::MembershipDifference] << std::endl;
    }

  //unsigned int bestMatchSourcePatchId = patchCompare.FindBestPatch();
  //std::cout << "bestMatchSourcePatchId: " << bestMatchSourcePatchId << std::endl;
/*
  unsigned int patchId = 1;
  float slowPatchDifference = patchCompare.SlowDifference(sourcePatches[patchId]);
  std::cout << "slowPatchDifference: " << slowPatchDifference << std::endl;

  float fastPatchDifference = patchCompare.PatchDifference(sourcePatches[patchId]);
  std::cout << "fastPatchDifference: " << fastPatchDifference << std::endl;

  unsigned int iterations = 1e6;

  itk::TimeProbe slowTimer;
  slowTimer.Start();

  for(unsigned int i = 0; i < iterations; ++i)
    {
    float slowPatchDifference = patchCompare.SlowDifference(sourcePatches[patchId]);
    }

  slowTimer.Stop();
  std::cout << "Slow Total: " << slowTimer.GetTotal() << std::endl;

  itk::TimeProbe fastTimer;
  fastTimer.Start();

  for(unsigned int i = 0; i < iterations; ++i)
    {
    float fastPatchDifference = patchCompare.PatchDifference(sourcePatches[patchId]);
    }

  fastTimer.Stop();
  std::cout << "Fast Total: " << fastTimer.GetTotal() << std::endl;*/

  return EXIT_SUCCESS;
}
  bool AcceptMatch(VertexDescriptorType target, VertexDescriptorType source, float& computedEnergy) const
  {
    //std::cout << "DilatedVarianceDifferenceAcceptanceVisitor::AcceptMatch" << std::endl;

    itk::Index<2> targetPixel = ITKHelpers::CreateIndex(target);
    itk::ImageRegion<2> targetRegion = ITKHelpers::GetRegionInRadiusAroundPixel(targetPixel, HalfWidth);

    itk::Index<2> sourcePixel = ITKHelpers::CreateIndex(source);
    itk::ImageRegion<2> sourceRegion = ITKHelpers::GetRegionInRadiusAroundPixel(sourcePixel, HalfWidth);

    // Compute the functor on the pixels in the region just inside the hole in the source patch
    typename TypeTraits<typename TImage::PixelType>::LargerType sourceValue;
    {
    Mask::Pointer originalHole = Mask::New();
    ITKHelpers::ExtractRegion(MaskImage, targetRegion, originalHole.GetPointer());

    Mask::Pointer shrunkHole = Mask::New();
    shrunkHole->DeepCopyFrom(originalHole);
    shrunkHole->ShrinkHole(5);

    typedef itk::Image<bool, 2> BoolImage;
    BoolImage::Pointer holeRindImage = BoolImage::New(); // "rind" like an "orange rind"
    ITKHelpers::XORRegions(originalHole.GetPointer(), originalHole->GetLargestPossibleRegion(),
                           shrunkHole.GetPointer(), shrunkHole->GetLargestPossibleRegion(), holeRindImage.GetPointer());

    std::vector<itk::Index<2> > holeRindPixels = ITKHelpers::GetPixelsWithValue(holeRindImage.GetPointer(), holeRindImage->GetLargestPossibleRegion(), true);

    itk::Index<2> zeroIndex = {{0,0}};
    std::vector<itk::Offset<2> > holeRindOffsets = ITKHelpers::IndicesToOffsets(holeRindPixels, zeroIndex);

    std::vector<itk::Index<2> > sourceRindPixelIndices = ITKHelpers::OffsetsToIndices(holeRindOffsets, sourceRegion.GetIndex());
    std::vector<typename TImage::PixelType> sourceRindPixels = ITKHelpers::GetPixelValues(Image, sourceRindPixelIndices);
    sourceValue = Functor(sourceRindPixels);
    }

    // Compute the functor on the pixels in the region just outside the hole in the target patch
    typename TypeTraits<typename TImage::PixelType>::LargerType targetValue;
    {
    Mask::Pointer originalHole = Mask::New();
    ITKHelpers::ExtractRegion(MaskImage, targetRegion, originalHole.GetPointer());

    Mask::Pointer expandedHole = Mask::New();
    expandedHole->DeepCopyFrom(originalHole);
    expandedHole->ExpandHole(5);

    typedef itk::Image<bool, 2> BoolImage;
    BoolImage::Pointer validRindImage = BoolImage::New(); // "rind" like an "orange rind"
    ITKHelpers::XORRegions(originalHole.GetPointer(), originalHole->GetLargestPossibleRegion(),
                           expandedHole.GetPointer(), expandedHole->GetLargestPossibleRegion(), validRindImage.GetPointer());

    std::vector<itk::Index<2> > validRindPixels = ITKHelpers::GetPixelsWithValue(validRindImage.GetPointer(), validRindImage->GetLargestPossibleRegion(), true);

    itk::Index<2> zeroIndex = {{0,0}};
    std::vector<itk::Offset<2> > validRindOffsets = ITKHelpers::IndicesToOffsets(validRindPixels, zeroIndex);

    std::vector<itk::Index<2> > targetRindPixelIndices = ITKHelpers::OffsetsToIndices(validRindOffsets, targetRegion.GetIndex());
    std::vector<typename TImage::PixelType> targetRindPixels = ITKHelpers::GetPixelValues(Image, targetRindPixelIndices);
    targetValue = Functor(targetRindPixels);
    }

    // Compute the difference
    computedEnergy = (targetValue - sourceValue).GetNorm();
    //std::cout << this->VisitorName << " Energy: " << computedEnergy << std::endl;

    if(computedEnergy < DifferenceThreshold)
      {
      std::cout << this->VisitorName << ": Match accepted (" << computedEnergy << " is less than " << DifferenceThreshold << ")" << std::endl << std::endl;
      return true;
      }
    else
      {
      std::cout << this->VisitorName << ": Match rejected (" << computedEnergy << " is greater than " << DifferenceThreshold << ")" << std::endl << std::endl;
      return false;
      }
  };