int main()
{
  typedef itk::Image<itk::CovariantVector<float, 3>, 2> ImageType;
//  typedef FloatVectorImageType ImageType;
  ImageType::Pointer image = ImageType::New();
  Testing::GetBlankImage(image.GetPointer(), 4);

  Mask::Pointer mask = Mask::New();
  Testing::GetFullyValidMask(mask.GetPointer());

  unsigned int patchRadius = 5;
  PriorityCriminisi<ImageType> priority(image.GetPointer(), mask.GetPointer(),
                                                   patchRadius);

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

  itk::Index<2> targetPixel;
  targetPixel.Fill(1);

  priority.Update(sourcePixel, targetPixel);

  itk::Index<2> queryPixel = {{0,0}};
  priority.ComputePriority(queryPixel);

  return EXIT_SUCCESS;
}
int main()
{
  FloatVectorImageType::Pointer image = FloatVectorImageType::New();
  Testing::GetBlankImage(image.GetPointer(), 4);

  Mask::Pointer mask = Mask::New();
  Testing::GetFullyValidMask(mask.GetPointer());

  UnsignedCharScalarImageType::Pointer manualPriorityImage = UnsignedCharScalarImageType::New();
  Testing::GetBlankImage(manualPriorityImage.GetPointer());

  unsigned int patchRadius = 5;
  typedef PriorityConfidence ConfidencePriorityType;
  ConfidencePriorityType priorityConfidence(mask, patchRadius);
  
  PriorityManual<itk::Index<2>, UnsignedCharScalarImageType, ConfidencePriorityType>
      priority(manualPriorityImage, &priorityConfidence);

  itk::Index<2> filledPixel = {{0,0}};
  priority.Update(filledPixel);
  priority.SetManualPriorityImage(manualPriorityImage);

  itk::Index<2> queryPixel = {{0,0}};
  priority.ComputePriority(queryPixel);

  return EXIT_SUCCESS;
}
int main(int argc, char*argv[])
{
  Mask::Pointer mask = Mask::New();
  CreateMask(mask);

  OutputHelpers::WriteImage(mask.GetPointer(), "mask.png");
  
  UnsignedCharScalarImageType::Pointer image = UnsignedCharScalarImageType::New();
  CreateImage(image);
  OutputHelpers::WriteImage(image.GetPointer(), "image.png");
  
  FloatScalarImageType::Pointer output = FloatScalarImageType::New();
  MaskOperations::MaskedLaplacian(image.GetPointer(), mask.GetPointer(), output.GetPointer());

  OutputHelpers::WriteImage(output.GetPointer(), "laplacian.mha");

  return EXIT_SUCCESS;
}
예제 #4
0
void Mask::CreateBoundaryImageInRegion(const itk::ImageRegion<2>& region, BoundaryImageType* const boundaryImage,
                                       const HoleMaskPixelTypeEnum& whichSideOfBoundary) const
{
  // Create a binary image of the mask
  unsigned char holeColor = 255;
  unsigned char validColor = 0;
  UnsignedCharImageType::Pointer fullBinaryImage = UnsignedCharImageType::New();
  CreateBinaryImageInRegion(region, fullBinaryImage, holeColor, validColor);

  // Extract the relevant region from the binary image
  UnsignedCharImageType::Pointer binaryImage = UnsignedCharImageType::New();
  binaryImage->SetRegions(region);
  binaryImage->Allocate();
  CopyRegion(fullBinaryImage.GetPointer(), binaryImage.GetPointer(), region, region);

  // Extract the relevant region from the mask
  Mask::Pointer extractedRegionMask = Mask::New();
  extractedRegionMask->SetRegions(region);
  extractedRegionMask->Allocate();
  CopyRegion(this, extractedRegionMask.GetPointer(), region, region);

  // Since the hole is white (we have specified this at the beginning of this function),
  // 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<UnsignedCharImageType, UnsignedCharImageType> binaryContourImageFilterType;
  binaryContourImageFilterType::Pointer binaryContourFilter = binaryContourImageFilterType::New();
  binaryContourFilter->SetInput(binaryImage);
  binaryContourFilter->SetFullyConnected(true);

  if(whichSideOfBoundary == HoleMaskPixelTypeEnum::VALID)
  {
    // we want the boundary pixels to be in the valid region.
      binaryContourFilter->SetForegroundValue(validColor);
      binaryContourFilter->SetBackgroundValue(holeColor);
  }
  else if(whichSideOfBoundary == HoleMaskPixelTypeEnum::HOLE)
  {
    // we want the boundary pixels to be in the hole region.
      binaryContourFilter->SetForegroundValue(holeColor);
      binaryContourFilter->SetBackgroundValue(validColor);
  }
  else
  {
    throw std::runtime_error("An invalid side of the boundary was requested.");
  }

  binaryContourFilter->Update();

  DeepCopy(binaryContourFilter->GetOutput(), boundaryImage);
}
예제 #5
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;
}
void Vector()
{
  typedef itk::Image<unsigned char, 2 >  ChannelType;
  const unsigned int NumberOfChannels = 3;
  typedef itk::Image<itk::CovariantVector<unsigned char, NumberOfChannels>, 2 >  ImageType;

  ImageType::Pointer image = ImageType::New();
  itk::Index<2> corner = {{0,0}};
  itk::Size<2> imageSize = {{500,500}};
  itk::ImageRegion<2> fullRegion(corner, imageSize);
  image->SetRegions(fullRegion);
  image->Allocate();

  for(unsigned int i = 0; i < NumberOfChannels; ++i)
  {
    itk::RandomImageSource<ChannelType>::Pointer randomImageSource =
      itk::RandomImageSource<ChannelType>::New();
    randomImageSource->SetNumberOfThreads(1); // to produce non-random results
    randomImageSource->SetSize(imageSize);
    randomImageSource->Update();

    ITKHelpers::SetChannel(image.GetPointer(), i, randomImageSource->GetOutput());
  }

  itk::Size<2> patchSize = {{21,21}};

  // There is nothing magic about these particular patches
  itk::Index<2> targetCorner = {{319, 302}};
  itk::ImageRegion<2> targetRegion(targetCorner, patchSize);

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

  Mask::Pointer mask = Mask::New();
  mask->SetRegions(fullRegion);
  mask->Allocate();
  ITKHelpers::SetImageToConstant(mask.GetPointer(), mask->GetValidValue());

  typedef SumSquaredPixelDifference<ImageType::PixelType> PixelDifferenceType;

  typedef ImagePatchPixelDescriptor<ImageType> PatchType;

  ImagePatchDifference<PatchType, PixelDifferenceType> imagePatchDifference;

  PatchType targetPatch(image, mask, targetRegion);
  PatchType sourcePatch(image, mask, sourceRegion);

  float difference = imagePatchDifference(targetPatch, sourcePatch);

  std::cout << "GMHDifference: " << difference << std::endl;

}
예제 #7
0
int main()
{
  FloatVectorImageType::Pointer image = FloatVectorImageType::New();
  Testing::GetBlankImage(image.GetPointer(), 4);

  Mask::Pointer mask = Mask::New();
  Testing::GetFullyValidMask(mask.GetPointer());

  unsigned int patchRadius = 5;
  PriorityDepth<FloatVectorImageType> priority(image, mask, patchRadius);

  itk::Index<2> filledPixel = {{0,0}};
  priority.Update(filledPixel);

  itk::Index<2> queryPixel = {{0,0}};
  priority.ComputePriority(queryPixel);

  return EXIT_SUCCESS;
}
void Scalar()
{
  typedef itk::Image< unsigned char, 2 >  ImageType;

  itk::Size<2> imageSize = {{500,500}};

  itk::RandomImageSource<ImageType>::Pointer randomImageSource =
    itk::RandomImageSource<ImageType>::New();
  randomImageSource->SetNumberOfThreads(1); // to produce non-random results
  randomImageSource->SetSize(imageSize);
  randomImageSource->Update();

  ImageType* image = randomImageSource->GetOutput();

  itk::Size<2> patchSize = {{21,21}};

  // There is nothing magic about these particular patches
  itk::Index<2> targetCorner = {{319, 302}};
  itk::ImageRegion<2> targetRegion(targetCorner, patchSize);

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

  Mask::Pointer mask = Mask::New();
  mask->SetRegions(randomImageSource->GetOutput()->GetLargestPossibleRegion());
  mask->Allocate();
  ITKHelpers::SetImageToConstant(mask.GetPointer(), mask->GetValidValue());

  typedef SumSquaredPixelDifference<ImageType::PixelType> PixelDifferenceType;

  typedef ImagePatchPixelDescriptor<ImageType> PatchType;

  ImagePatchDifference<PatchType, PixelDifferenceType> imagePatchDifference;

  PatchType targetPatch(image, mask, targetRegion);
  PatchType sourcePatch(image, mask, sourceRegion);

  float difference = imagePatchDifference(targetPatch, sourcePatch);

  std::cout << "Difference: " << difference << std::endl;

}
int main()
{
  typedef itk::Image<itk::CovariantVector<float, 3>, 2> ImageType;

  ImageType::Pointer image = ImageType::New();
  Testing::GetBlankImage(image.GetPointer(), 4);

  Mask::Pointer mask = Mask::New();
  Testing::GetFullyValidMask(mask.GetPointer());

  vtkSmartPointer<vtkStructuredGrid> structuredGrid = vtkSmartPointer<vtkStructuredGrid>::New();

  unsigned int patchRadius = 5;
  PriorityCurvature<itk::Index<2> > priority(structuredGrid, patchRadius);

  itk::Index<2> filledPixel = {{0,0}};
  itk::Index<2> sourcePixel = {{0,0}};
  priority.Update(sourcePixel, filledPixel);

  itk::Index<2> queryPixel = {{0,0}};
  priority.ComputePriority(queryPixel);

  return EXIT_SUCCESS;
}
예제 #10
0
void TestComputeMaskedImage1DHistogram()
{
//  // Single channel
//  {
//  typedef itk::Image<unsigned char, 2> ImageType;
//  ImageType::Pointer image = ImageType::New();
//  ImageType::IndexType corner = {{0,0}};

//  ImageType::SizeType size = {{100,100}};

//  ImageType::RegionType region(corner, size);

//  image->SetRegions(region);
//  image->Allocate();

//  itk::ImageRegionIterator<ImageType> imageIterator(image,region);

//  while(!imageIterator.IsAtEnd())
//    {
//    if(imageIterator.GetIndex()[0] < 70)
//      {
//      imageIterator.Set(255);
//      }
//    else
//      {
//      imageIterator.Set(0);
//      }

//    ++imageIterator;
//    }

//  ImageType::PixelType rangeMin = 0;
//  ImageType::PixelType rangeMax = 255;

//  unsigned int numberOfBins = 10;
//  typedef int BinValueType;
//  typedef Histogram<BinValueType>::HistogramType HistogramType;

//  HistogramType histogram = Histogram<BinValueType>::ComputeImageHistogram1D(image.GetPointer(),
//                                                         image->GetLargestPossibleRegion(),
//                                                         numberOfBins, rangeMin, rangeMax);

//  Histogram<BinValueType>::OutputHistogram(histogram);
//  std::cout << std::endl;
//  }

   // Multi channel VectorImage
   {
   typedef itk::VectorImage<unsigned char, 2> ImageType;
   ImageType::Pointer image = ImageType::New();
   ImageType::IndexType corner = {{0,0}};

   ImageType::SizeType size = {{100,100}};

   ImageType::RegionType region(corner, size);

   image->SetRegions(region);
   image->SetNumberOfComponentsPerPixel(3);
   image->Allocate();

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

   itk::ImageRegionIterator<ImageType> imageIterator(image,region);

   while(!imageIterator.IsAtEnd())
   {
     ImageType::PixelType pixel(image->GetNumberOfComponentsPerPixel());
     if(imageIterator.GetIndex()[0] < 70)
     {
       for(unsigned int i = 0; i < pixel.GetSize(); ++i)
       {
         pixel[i] = 255;
       }
     }
     else
     {
       for(unsigned int i = 0; i < pixel.GetSize(); ++i)
       {
         pixel[i] = 0;
       }
     }
     imageIterator.Set(pixel);
     ++imageIterator;
   }

//   TypeTraits<ImageType::PixelType>::ComponentType rangeMin = 0;
//   TypeTraits<ImageType::PixelType>::ComponentType rangeMax = 255;

   ImageType::PixelType rangeMins;
   rangeMins.SetSize(image->GetNumberOfComponentsPerPixel());
   rangeMins.Fill(0);

   ImageType::PixelType rangeMaxs;
   rangeMaxs.SetSize(image->GetNumberOfComponentsPerPixel());
   rangeMaxs.Fill(255);

   unsigned int numberOfBinsPerComponent = 10;
   typedef int BinValueType;

   itk::ImageRegion<2> imageRegion = image->GetLargestPossibleRegion();
   itk::ImageRegion<2> maskRegion = image->GetLargestPossibleRegion();

   typedef MaskedHistogramGenerator<BinValueType> HistogramGeneratorType;
   typedef HistogramGeneratorType::HistogramType HistogramType;

   bool allowOutside = false;

   HistogramType histogram =
       HistogramGeneratorType::ComputeMaskedImage1DHistogram(image.GetPointer(), imageRegion,
                                                      mask.GetPointer(), maskRegion,
                                                      numberOfBinsPerComponent, rangeMins, rangeMaxs,
                                                      allowOutside, HoleMaskPixelTypeEnum::VALID);

   histogram.Print();
   std::cout << std::endl;
   }

//  // Multi channel Image<CovariantVector>
//  {
//  typedef itk::Image<itk::CovariantVector<unsigned char, 3>, 2> ImageType;
//  ImageType::Pointer image = ImageType::New();
//  ImageType::IndexType corner = {{0,0}};

//  ImageType::SizeType size = {{100,100}};

//  ImageType::RegionType region(corner, size);

//  image->SetRegions(region);
//  image->Allocate();

//  itk::ImageRegionIterator<ImageType> imageIterator(image,region);

//  while(!imageIterator.IsAtEnd())
//    {
//    ImageType::PixelType pixel(image->GetNumberOfComponentsPerPixel());
//    if(imageIterator.GetIndex()[0] < 70)
//      {
//      for(unsigned int i = 0; i < pixel.GetNumberOfComponents(); ++i)
//        {
//        pixel[i] = 255;
//        }
//      }
//    else
//      {
//      for(unsigned int i = 0; i < pixel.GetNumberOfComponents(); ++i)
//        {
//        pixel[i] = 0;
//        }
//      }
//    imageIterator.Set(pixel);
//    ++imageIterator;
//    }

//  TypeTraits<ImageType::PixelType>::ComponentType rangeMin = 0;
//  TypeTraits<ImageType::PixelType>::ComponentType rangeMax = 255;

//  unsigned int numberOfBinsPerComponent = 10;
//  typedef int BinValueType;
//  Histogram<BinValueType>::HistogramType histogram = Histogram<BinValueType>::ComputeImageHistogram1D(image.GetPointer(),
//                                                         image->GetLargestPossibleRegion(),
//                                                         numberOfBinsPerComponent, rangeMin, rangeMax);

//  Histogram<BinValueType>::OutputHistogram(histogram);
//  std::cout << std::endl;
//  }
}
예제 #11
0
int main(int argc, char* argv[])
{
  // Verify arguments
  if(argc < 5)
  {
    std::cout << "Usage: PatchImage repeatX repeatY outputImage" << std::endl;
    return EXIT_FAILURE;
  }

  // Parse arguments
  std::string patchImageFilename = argv[1];

  std::stringstream ssRepeatX;
  ssRepeatX << argv[2];
  unsigned int repeatX = 0;
  ssRepeatX >> repeatX;

  std::stringstream ssRepeatY;
  ssRepeatY << argv[3];
  unsigned int repeatY = 0;
  ssRepeatY >> repeatY;

  std::string outputFilename = argv[4];

  // Output arguments
  std::cout << "Patch image: " << patchImageFilename << std::endl
            << "Repeat X: " << repeatX << std::endl
            << "Repeat Y: " << repeatY << std::endl
            << "Output image: " << outputFilename << std::endl;

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

  // Read patch image
  typedef itk::ImageFileReader<ImageType> ImageReaderType;
  ImageReaderType::Pointer patchImageReader = ImageReaderType::New();
  patchImageReader->SetFileName(patchImageFilename);
  patchImageReader->Update();

  Mask::Pointer mask = Mask::New();
  itk::ImageRegion<2> patchRegion = patchImageReader->GetOutput()->GetLargestPossibleRegion();
  mask->SetRegions(patchRegion);
  mask->Allocate();

  itk::Index<2> holeCorner = {{1,1}};
  itk::Size<2> holeSize = patchRegion.GetSize();
  holeSize[0] -= 2; // Missing one row on the top, and one row on the bottom
  holeSize[1] -= 2; // Missing one column on the left, and one column on the right
  itk::ImageRegion<2> holeRegion(holeCorner, holeSize);
  mask->SetValid(patchRegion);
  mask->SetHole(holeRegion);


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

  // Enforce periodic boundary conditions
  // Top and bottom
  for(int i = 0; i < static_cast<int>(patchRegion.GetSize()[1]); ++i)
  {
      itk::Index<2> topPixelIndex = {{0, i}};
      itk::Index<2> bottomPixelIndex = {{static_cast<int>(patchRegion.GetSize()[0])-1, i}};
      ImageType::PixelType topPixelValue = seamlessPatch->GetPixel(topPixelIndex);
      ImageType::PixelType bottomPixelValue = seamlessPatch->GetPixel(bottomPixelIndex);
      ImageType::PixelType averageValue = (topPixelValue + bottomPixelValue)/2.0f;
      seamlessPatch->SetPixel(topPixelIndex, averageValue);
      seamlessPatch->SetPixel(bottomPixelIndex, averageValue);
  }

  // Left and right
  for(int i = 0; i < static_cast<int>(patchRegion.GetSize()[0]); ++i)
  {
      itk::Index<2> leftPixelIndex = {{i, 0}};
      itk::Index<2> rightPixelIndex = {{i, static_cast<int>(patchRegion.GetSize()[1])-1}};
      ImageType::PixelType leftPixelValue = seamlessPatch->GetPixel(leftPixelIndex);
      ImageType::PixelType rightPixelValue = seamlessPatch->GetPixel(rightPixelIndex);
      ImageType::PixelType averageValue = (leftPixelValue + rightPixelValue)/2.0f;
      seamlessPatch->SetPixel(leftPixelIndex, averageValue);
      seamlessPatch->SetPixel(rightPixelIndex, averageValue);
  }

  typedef PoissonEditingParent::GuidanceFieldType GuidanceFieldType;

  std::vector<GuidanceFieldType::Pointer> guidanceFields = PoissonEditingParent::ComputeGuidanceField(patchImageReader->GetOutput());

  ImageType::Pointer output = ImageType::New();

  FillImage(seamlessPatch.GetPointer(), mask.GetPointer(),
            guidanceFields, output.GetPointer(),
            patchRegion, seamlessPatch.GetPointer());


  // Write output
  ITKHelpers::WriteRGBImage(output.GetPointer(), outputFilename);

  // Original tiled
  ImageType::Pointer originalTiled = ImageType::New();
  TilePatch(patchImageReader->GetOutput(), repeatX, repeatY, originalTiled.GetPointer());
  ITKHelpers::WriteRGBImage(originalTiled.GetPointer(), "original_tiled.png");

  // Seamless tiled
  ImageType::Pointer seamlessTiled = ImageType::New();
  TilePatch(output.GetPointer(), repeatX, repeatY, seamlessTiled.GetPointer());
  ITKHelpers::WriteRGBImage(seamlessTiled.GetPointer(), "seamless_tiled.png");

  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;
}
int main(int argc, char*argv[])
{
  if(argc != 6)
    {
    std::cerr << "Required arguments: image output R G B" << std::endl;
    return EXIT_FAILURE;
    }

  std::vector<int> values(3,0);
  std::stringstream ss;
  unsigned int counter = 0;
  for(int i = 3; i < argc; ++i)
  {
    ss << argv[i] << " ";
    counter++;
  }

  for(int i = 0; i < 3; ++i)
  {
    ss >> values[i];
  }

//   itk::RGBPixel<unsigned char> color;
//   color.SetRed(values[0]);
//   color.SetGreen(values[1]);
//   color.SetBlue(values[2]);
  Color color;
  color.r = values[0];
  color.g = values[1];
  color.b = values[2];

  std::string imageFilename = argv[1];
  std::string outputMaskFilename = argv[2];

  std::cout << "Reading image: " << imageFilename << std::endl;
  std::cout << "outputMaskFilename: " << outputMaskFilename << std::endl;

  std::cout << "Color: " << static_cast<int>(values[0]) << " " << static_cast<int>(values[1]) << " " << static_cast<int>(values[2]) << std::endl;

  //typedef itk::Image<float, 2> ImageType;

  typedef itk::Image<itk::CovariantVector<unsigned char, 3>, 2> ImageType;
  ImageType::PixelType pixelColor;
  pixelColor[0] = color.r;
  pixelColor[1] = color.g;
  pixelColor[2] = color.b;


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

  Mask::Pointer mask = Mask::New();
  mask->SetRegions(imageReader->GetOutput()->GetLargestPossibleRegion());
  mask->Allocate();
  mask->CreateFromImage(imageReader->GetOutput(), pixelColor);

  OutputHelpers::WriteImage(mask.GetPointer(), outputMaskFilename);

  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;
      }
  };
// Run with: Data/trashcan.mha Data/trashcan_mask.mha 15 filled.mha
int main(int argc, char *argv[])
{
  // Verify arguments
  if(argc != 5)
    {
    std::cerr << "Required arguments: image.mha imageMask.mha patchHalfWidth output.mha" << std::endl;
    std::cerr << "Input arguments: ";
    for(int i = 1; i < argc; ++i)
      {
      std::cerr << argv[i] << " ";
      }
    return EXIT_FAILURE;
    }

  // Setup the GUI system
  QApplication app( argc, argv );

  // 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 FloatVectorImageType ImageType;

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

  ImageType* image = imageReader->GetOutput();
  itk::ImageRegion<2> fullRegion = imageReader->GetOutput()->GetLargestPossibleRegion();

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

  std::cout << "hole pixels: " << mask->CountHolePixels() << std::endl;
  std::cout << "valid pixels: " << mask->CountValidPixels() << std::endl;

  std::cout << "image has " << image->GetNumberOfComponentsPerPixel() << " components." << std::endl;

  typedef ImagePatchPixelDescriptor<ImageType> ImagePatchPixelDescriptorType;

  // Create the graph
  typedef boost::grid_graph<2> VertexListGraphType;
  boost::array<std::size_t, 2> graphSideLengths = { { fullRegion.GetSize()[0],
                                                      fullRegion.GetSize()[1] } };
  VertexListGraphType graph(graphSideLengths);
  typedef boost::graph_traits<VertexListGraphType>::vertex_descriptor VertexDescriptorType;

  // Get the index map
  typedef boost::property_map<VertexListGraphType, boost::vertex_index_t>::const_type IndexMapType;
  IndexMapType indexMap(get(boost::vertex_index, graph));

  // Create the priority map
  typedef boost::vector_property_map<float, IndexMapType> PriorityMapType;
  PriorityMapType priorityMap(num_vertices(graph), indexMap);

  // Create the boundary status map. A node is on the current boundary if this property is true.
  // This property helps the boundaryNodeQueue because we can mark here if a node has become no longer
  // part of the boundary, so when the queue is popped we can check this property to see if it should
  // actually be processed.
  typedef boost::vector_property_map<bool, IndexMapType> BoundaryStatusMapType;
  BoundaryStatusMapType boundaryStatusMap(num_vertices(graph), indexMap);

  // Create the descriptor map. This is where the data for each pixel is stored.
  typedef boost::vector_property_map<ImagePatchPixelDescriptorType, IndexMapType> ImagePatchDescriptorMapType;
  ImagePatchDescriptorMapType imagePatchDescriptorMap(num_vertices(graph), indexMap);

  //ImagePatchDescriptorMapType smallImagePatchDescriptorMap(num_vertices(graph), indexMap);

  // Create the patch inpainter. The inpainter needs to know the status of each
  // pixel to determine if they should be inpainted.
  typedef MaskImagePatchInpainter InpainterType;
  MaskImagePatchInpainter patchInpainter(patchHalfWidth, mask);

  // Create the priority function
//   typedef PriorityRandom PriorityType;
//   PriorityType priorityFunction;
  typedef PriorityOnionPeel PriorityType;
  PriorityType priorityFunction(mask, patchHalfWidth);

  // Create the boundary node queue. The priority of each node is used to order the queue.
  typedef boost::vector_property_map<std::size_t, IndexMapType> IndexInHeapMap;
  IndexInHeapMap index_in_heap(indexMap);

  // Create the priority compare functor (we want the highest priority nodes to be first in the queue)
  typedef std::greater<float> PriorityCompareType;
  PriorityCompareType lessThanFunctor;

  typedef boost::d_ary_heap_indirect<VertexDescriptorType, 4, IndexInHeapMap, PriorityMapType, PriorityCompareType>
                                    BoundaryNodeQueueType;
  BoundaryNodeQueueType boundaryNodeQueue(priorityMap, index_in_heap, lessThanFunctor);

  // Create the descriptor visitor
  typedef ImagePatchDescriptorVisitor<VertexListGraphType, ImageType, ImagePatchDescriptorMapType>
          ImagePatchDescriptorVisitorType;
  ImagePatchDescriptorVisitorType imagePatchDescriptorVisitor(image, mask, imagePatchDescriptorMap, patchHalfWidth);
  //ImagePatchDescriptorVisitorType imagePatchDescriptorVisitor(cielabImage,
  //                                                            mask, imagePatchDescriptorMap, patchHalfWidth);

  typedef ImagePatchDifference<ImagePatchPixelDescriptorType, SumAbsolutePixelDifference<ImageType::PixelType> >
            ImagePatchDifferenceType;
  ImagePatchDifferenceType imagePatchDifferenceFunction;

//   typedef WeightedSumAbsolutePixelDifference<ImageType::PixelType> PixelDifferenceFunctorType;
//   PixelDifferenceFunctorType pixelDifferenceFunctor;
//   std::vector<float> weights;
//   weights.push_back(1.0f);
//   weights.push_back(1.0f);
//   weights.push_back(1.0f);
//   float gradientWeight = 500.0f;
//   weights.push_back(gradientWeight);
//   weights.push_back(gradientWeight);
//   pixelDifferenceFunctor.Weights = weights;
//   std::cout << "Weights: ";
//   OutputHelpers::OutputVector(pixelDifferenceFunctor.Weights);

//   typedef ImagePatchDifference<ImagePatchPixelDescriptorType, PixelDifferenceFunctorType >
//           ImagePatchDifferenceType;
// 
//   ImagePatchDifferenceType imagePatchDifferenceFunction(pixelDifferenceFunctor);

  typedef CompositeDescriptorVisitor<VertexListGraphType> CompositeDescriptorVisitorType;
  CompositeDescriptorVisitorType compositeDescriptorVisitor;
  compositeDescriptorVisitor.AddVisitor(&imagePatchDescriptorVisitor);

  typedef CompositeAcceptanceVisitor<VertexListGraphType> CompositeAcceptanceVisitorType;
  CompositeAcceptanceVisitorType compositeAcceptanceVisitor;

  typedef InpaintingVisitor<VertexListGraphType, ImageType, BoundaryNodeQueueType,
                            CompositeDescriptorVisitorType, CompositeAcceptanceVisitorType, PriorityType,
                            PriorityMapType, BoundaryStatusMapType>
                            InpaintingVisitorType;
  InpaintingVisitorType inpaintingVisitor(image, mask, boundaryNodeQueue,
                                          compositeDescriptorVisitor, compositeAcceptanceVisitor, priorityMap,
                                          &priorityFunction, patchHalfWidth,
                                          boundaryStatusMap, outputFilename);

  typedef DisplayVisitor<VertexListGraphType, ImageType> DisplayVisitorType;
  DisplayVisitorType displayVisitor(image, mask, patchHalfWidth);

  typedef DebugVisitor<VertexListGraphType, ImageType, BoundaryStatusMapType, BoundaryNodeQueueType>
          DebugVisitorType;
  DebugVisitorType debugVisitor(image, mask, patchHalfWidth, boundaryStatusMap, boundaryNodeQueue);

  LoggerVisitor<VertexListGraphType> loggerVisitor("log.txt");

  PaintPatchVisitor<VertexListGraphType, ImageType> inpaintRGBVisitor(image,
                                                                      mask.GetPointer(), patchHalfWidth);

  typedef CompositeInpaintingVisitor<VertexListGraphType> CompositeInpaintingVisitorType;
  CompositeInpaintingVisitorType compositeInpaintingVisitor;
  compositeInpaintingVisitor.AddVisitor(&inpaintingVisitor);
  //compositeInpaintingVisitor.AddVisitor(&inpaintRGBVisitor);
  compositeInpaintingVisitor.AddVisitor(&displayVisitor);
  compositeInpaintingVisitor.AddVisitor(&debugVisitor);
  //compositeInpaintingVisitor.AddVisitor(&loggerVisitor);

  InitializePriority(mask, boundaryNodeQueue, priorityMap, &priorityFunction, boundaryStatusMap);

  // Initialize the boundary node queue from the user provided mask image.
  InitializeFromMaskImage<CompositeInpaintingVisitorType, VertexDescriptorType>(mask, &compositeInpaintingVisitor);

  // Create the nearest neighbor finders
  typedef LinearSearchKNNProperty<ImagePatchDescriptorMapType,
                                  ImagePatchDifferenceType > KNNSearchType;
  KNNSearchType knnSearch(imagePatchDescriptorMap, 50000, 1, imagePatchDifferenceFunction);

  // For debugging we use LinearSearchBestProperty instead of DefaultSearchBest
  // because it can output the difference value.
  typedef LinearSearchBestProperty<ImagePatchDescriptorMapType,
                                   ImagePatchDifferenceType > BestSearchType;
  BestSearchType bestSearch(imagePatchDescriptorMap, imagePatchDifferenceFunction);

  BasicViewerWidget<ImageType> basicViewerWidget(image, mask);
  basicViewerWidget.show();
  
  // These connections are Qt::BlockingQueuedConnection because the algorithm quickly
  // goes on to fill the hole, and since we are sharing the image memory, we want to make sure these things are
  // refreshed at the right time, not after the hole has already been filled
  // (this actually happens, it is not just a theoretical thing).
  QObject::connect(&displayVisitor, SIGNAL(signal_RefreshImage()), &basicViewerWidget, SLOT(slot_UpdateImage()),
                   Qt::BlockingQueuedConnection);
  QObject::connect(&displayVisitor, SIGNAL(signal_RefreshSource(const itk::ImageRegion<2>&,
                                                                const itk::ImageRegion<2>&)),
                   &basicViewerWidget, SLOT(slot_UpdateSource(const itk::ImageRegion<2>&,
                                                              const itk::ImageRegion<2>&)),
                   Qt::BlockingQueuedConnection);
  QObject::connect(&displayVisitor, SIGNAL(signal_RefreshTarget(const itk::ImageRegion<2>&)),
                   &basicViewerWidget, SLOT(slot_UpdateTarget(const itk::ImageRegion<2>&)),
                   Qt::BlockingQueuedConnection);
  QObject::connect(&displayVisitor, SIGNAL(signal_RefreshResult(const itk::ImageRegion<2>&,
                                                                const itk::ImageRegion<2>&)),
                   &basicViewerWidget, SLOT(slot_UpdateResult(const itk::ImageRegion<2>&,
                                                              const itk::ImageRegion<2>&)),
                   Qt::BlockingQueuedConnection);

//   TopPatchesDialog<ImageType> topPatchesDialog(image, mask, patchHalfWidth, &basicViewerWidget);
//   typedef VisualSelectionBest<ImageType> ManualSearchType;
//   ManualSearchType manualSearchBest(image, mask, patchHalfWidth, &topPatchesDialog);

  typedef DefaultSearchBest ManualSearchType;
  DefaultSearchBest manualSearchBest;
  
  // By specifying the radius as the image size/8, we are searching up to 1/4 of the image each time
  typedef NeighborhoodSearch<VertexDescriptorType> NeighborhoodSearchType;
  NeighborhoodSearchType neighborhoodSearch(fullRegion, fullRegion.GetSize()[0]/8);

  // Run the remaining inpainting
  QtConcurrent::run(boost::bind(InpaintingAlgorithmWithLocalSearch<
                                VertexListGraphType, CompositeInpaintingVisitorType, BoundaryStatusMapType,
                                BoundaryNodeQueueType, NeighborhoodSearchType, KNNSearchType, BestSearchType,
                                ManualSearchType, InpainterType>,
                                graph, compositeInpaintingVisitor, &boundaryStatusMap, &boundaryNodeQueue,
                                neighborhoodSearch, knnSearch, bestSearch, boost::ref(manualSearchBest),
                                patchInpainter));

  return app.exec();
}
void LidarSegmentationWidget::GenerateNeighborSinks()
{
  Mask::Pointer sourcesImage = Mask::New();
  sourcesImage->SetRegions(this->ImageRegion);
  ITKHelpers::IndicesToBinaryImage(this->Sources, sourcesImage);
  ITKHelpers::WriteImage(sourcesImage.GetPointer(), "sourcesImage.png");
  
  // Dilate the mask
  std::cout << "Dilating mask..." << std::endl;
  typedef itk::BinaryBallStructuringElement<Mask::PixelType, 2> StructuringElementType;
  StructuringElementType structuringElement;
  structuringElement.SetRadius(1);
  structuringElement.CreateStructuringElement();

  typedef itk::BinaryDilateImageFilter<Mask, Mask, StructuringElementType> BinaryDilateImageFilterType;

  BinaryDilateImageFilterType::Pointer dilateFilter = BinaryDilateImageFilterType::New();
  dilateFilter->SetInput(sourcesImage);
  dilateFilter->SetKernel(structuringElement);
  dilateFilter->Update();

  // Binary XOR the images to get the difference image
  //std::cout << "XORing masks..." << std::endl;
  typedef itk::XorImageFilter<Mask> XorImageFilterType;

  XorImageFilterType::Pointer xorFilter = XorImageFilterType::New();
  xorFilter->SetInput1(dilateFilter->GetOutput());
  xorFilter->SetInput2(sourcesImage);
  xorFilter->Update();

  ITKHelpers::WriteImage(xorFilter->GetOutput(), "boundaryOfSegmentation.png");
  
  // Iterate over the border pixels. If the closest pixel in the original segmentation has
  // a depth greater than a threshold, mark it as a new sink. Else, do not.
  std::cout << "Determining which boundary pixels should be declared background..." << std::endl;
  //std::cout << "There should be " << Helpers::CountNonZeroPixels(xorFilter->GetOutput())
  //          << " considered." << std::endl;
  typedef std::vector<itk::Index<2> > VectorOfPixelsType;
  VectorOfPixelsType newSinks;

  typedef itk::VectorIndexSelectionCastImageFilter<ImageType, FloatScalarImageType> IndexSelectionType;
  IndexSelectionType::Pointer indexSelectionFilter = IndexSelectionType::New();
  indexSelectionFilter->SetIndex(3);
  indexSelectionFilter->SetInput(this->Image);
  indexSelectionFilter->Update();
  
  FloatScalarImageType::Pointer depthImage = indexSelectionFilter->GetOutput();

  //float sameObjectThreshold = 0.1f;

  VectorOfPixelsType consideredPixels;

  itk::ImageRegionIterator<Mask> imageIterator(xorFilter->GetOutput(),
                                               xorFilter->GetOutput()->GetLargestPossibleRegion());
  while(!imageIterator.IsAtEnd())
    {
    if(imageIterator.Get()) // If the current pixel is in question
      {
      consideredPixels.push_back(imageIterator.GetIndex());
      }
    ++imageIterator;
    }

  std::cout << "There are " << consideredPixels.size() << " potential new sink pixels." << std::endl;
  
  for(VectorOfPixelsType::const_iterator iter = consideredPixels.begin(); iter != consideredPixels.end(); ++iter)
    {
    //std::cout << "Considering pixel " << consideredCounter << " (index "
    //          << imageIterator.GetIndex() << ")" << std::endl;
    ImageType::PixelType currentPixel = this->Image->GetPixel(*iter);

    unsigned int radius = this->txtBackgroundCheckRadius->text().toUInt();
    ImageType::RegionType desiredRegion = ITKHelpers::GetRegionInRadiusAroundPixel(*iter, radius);
    //std::cout << "desiredRegion: " << desiredRegion << std::endl;
    
    itk::ImageRegionIterator<Mask> sourcesImageIterator(sourcesImage, desiredRegion);
    
    std::vector<float> nonForegroundDepths;
    std::vector<float> foregroundDepths;
    while(!sourcesImageIterator.IsAtEnd())
      {
      if(sourcesImageIterator.Get())
        {
        foregroundDepths.push_back(depthImage->GetPixel(sourcesImageIterator.GetIndex()));
        }
      else
        {
        nonForegroundDepths.push_back(depthImage->GetPixel(sourcesImageIterator.GetIndex()));
        }
      ++sourcesImageIterator;
      }

    if(nonForegroundDepths.size() < 1)
    {
    }
    
    float nonForegroundMedian = Helpers::VectorMedian(nonForegroundDepths);
    float foregroundMedian = Helpers::VectorMedian(foregroundDepths);

    float difference = fabs(foregroundMedian - nonForegroundMedian);

    if(difference > this->txtBackgroundThreshold->text().toFloat())
      {
      //std::cout << "Difference was " << difference << " so this is a sink pixel." << std::endl;
      newSinks.push_back(*iter);
      }
    else
      {
      //std::cout << "Difference was " << difference << " so this is NOT a sink pixel." << std::endl;
      }
    } // end loop over considered pixels
  
  unsigned char blue[3] = {0, 0, 255};
//   ImageType::PixelType blue(3);
//   blue[0] = 0;
//   blue[1] = 0;
//   blue[2] = 255;
  
  ITKVTKHelpers::SetPixels(this->SourceSinkImageData.GetPointer(), consideredPixels, blue);
  this->SourceSinkImageData->Modified();
  this->Refresh();
  
  // Save the new sink pixels for inspection
  UnsignedCharScalarImageType::Pointer newSinksImage = UnsignedCharScalarImageType::New();
  newSinksImage->SetRegions(this->Image->GetLargestPossibleRegion());
  newSinksImage->Allocate();

  ITKHelpers::IndicesToBinaryImage(newSinks, newSinksImage);
  ITKHelpers::WriteImage(newSinksImage.GetPointer(), "newSinks.png");

  //std::cout << "Out of " << consideredCounter << " pixels considered, "
  //          << backgroundCounter << " were declared background." << std::endl;
  // Set the new sinks
  std::cout << "Setting " << newSinks.size() << " new sinks." << std::endl;

  // Modify the list of sinks so it can be retrieved by the MainWindow after the segmentation is finished
  this->Sinks.insert(this->Sinks.end(), newSinks.begin(), newSinks.end());

  UpdateSelections();
}