예제 #1
0
int main (int argc, char *argv[])
{
    if(argc != 4)
    {
        std::cout << "Required arguments: InputFilename(ptx) NewRGB(mhd) OutputFilename(ptx)" << std::endl;
        return EXIT_FAILURE;
    }

    std::string inputFilename = argv[1];
    std::string newDepthImageFilename = argv[2];
    std::string outputFilename = argv[3];

    PTXImage ptxImage = PTXReader::Read(inputFilename);

    typedef itk::ImageFileReader<PTXImage::RGBVectorImageType> ImageReaderType;
    ImageReaderType::Pointer reader = ImageReaderType::New();
    reader->SetFileName(newDepthImageFilename);
    reader->Update();

    if(reader->GetOutput()->GetLargestPossibleRegion().GetSize() != ptxImage.GetSize())
    {
        std::cerr << "RGB image must be the same size as PTX image!" << std::endl;
        exit(-1);
    }

    ptxImage.ReplaceRGB(reader->GetOutput());

    ptxImage.WritePTX(outputFilename);

    return EXIT_SUCCESS;
}
// 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();
}
void QmitkDeformableRegistrationView::ApplyDeformationField()
{

  ImageReaderType::Pointer reader  = ImageReaderType::New();
  reader->SetFileName( m_Controls.m_QmitkBSplineRegistrationViewControls->m_Controls.m_DeformationField->text().toStdString() );
  reader->Update();

  DeformationFieldType::Pointer deformationField = reader->GetOutput();

  mitk::Image * mimage = dynamic_cast<mitk::Image*> (m_MovingNode->GetData());
  mitk::Image * fimage = dynamic_cast<mitk::Image*> (m_FixedNode->GetData());

  typedef itk::Image<float, 3> FloatImageType;

  FloatImageType::Pointer itkMovingImage = FloatImageType::New();
  FloatImageType::Pointer itkFixedImage = FloatImageType::New();
  mitk::CastToItkImage(mimage, itkMovingImage);
  mitk::CastToItkImage(fimage, itkFixedImage);

  typedef itk::WarpImageFilter<
                            FloatImageType,
                            FloatImageType,
                            DeformationFieldType  >     WarperType;

  typedef itk::LinearInterpolateImageFunction<
                                    FloatImageType,
                                    double          >  InterpolatorType;

  WarperType::Pointer warper = WarperType::New();
  InterpolatorType::Pointer interpolator = InterpolatorType::New();

  warper->SetInput( itkMovingImage );
  warper->SetInterpolator( interpolator );
  warper->SetOutputSpacing( itkFixedImage->GetSpacing() );
  warper->SetOutputOrigin( itkFixedImage->GetOrigin() );
  warper->SetOutputDirection (itkFixedImage->GetDirection() );
  warper->SetDisplacementField( deformationField );
  warper->Update();

  FloatImageType::Pointer outputImage = warper->GetOutput();
  mitk::Image::Pointer result = mitk::Image::New();

  mitk::CastToMitkImage(outputImage, result);

  // Create new DataNode
  mitk::DataNode::Pointer newNode = mitk::DataNode::New();
  newNode->SetData( result );
  newNode->SetProperty( "name", mitk::StringProperty::New("warped image") );

  // add the new datatree node to the datatree
  this->GetDefaultDataStorage()->Add(newNode);
  mitk::RenderingManager::GetInstance()->RequestUpdateAll();

  //Image::Pointer outputImage = this->GetOutput();
  //mitk::CastToMitkImage( warper->GetOutput(), outputImage );


}
예제 #4
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 SuperPixelSegmentationGUI::OpenImage(const std::string& imageFileName)
{
  // Load and display image
  typedef itk::ImageFileReader<ImageType> ImageReaderType;
  ImageReaderType::Pointer imageReader = ImageReaderType::New();
  imageReader->SetFileName(imageFileName);
  imageReader->Update();

  Helpers::DeepCopy<ImageType>(imageReader->GetOutput(), this->Image);

  QImage qimageImage = HelpersQt::GetQImageRGBA<ImageType>(this->Image);
  this->ImagePixmapItem = this->Scene->addPixmap(QPixmap::fromImage(qimageImage));
  this->graphicsView->fitInView(this->ImagePixmapItem);
  Refresh();
}
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;
}
void QmitkBSplineRegistrationView::PrintDeformationField()
{               
 
  ImageReaderType::Pointer reader  = ImageReaderType::New();
  reader->SetFileName(  m_Controls.m_DeformationField->text().toStdString()  );
  reader->Update();
      
  DeformationFieldType::Pointer deformationField = reader->GetOutput();
     

  typedef itk::ImageRegionIterator<DeformationFieldType> IteratorType;
  IteratorType deformIter(deformationField, deformationField->GetRequestedRegion());

  for(deformIter.GoToBegin(); !deformIter.IsAtEnd(); ++deformIter)
  {
    std::cout << deformIter.Get() << std::endl;
  }
}
예제 #8
0
BinaryImageType::Pointer readBinaryImage(const std::string& filename) {
    ImageReaderType::Pointer reader = ImageReaderType::New();
    reader->SetFileName(filename.c_str());
    reader->Update();

    // we make sure that the image really has value 0 and 1
    typedef itk::BinaryThresholdImageFilter<BinaryImageType, BinaryImageType> ThresholdFilterType;
    ThresholdFilterType::Pointer thresholdFilter = ThresholdFilterType::New();
    thresholdFilter->SetInsideValue(1);
    thresholdFilter->SetOutsideValue(0);
    thresholdFilter->SetLowerThreshold(1);
    thresholdFilter->SetUpperThreshold(255);
    thresholdFilter->SetInput(reader->GetOutput());
    thresholdFilter->Update();
    BinaryImageType::Pointer img = thresholdFilter->GetOutput();
    img->DisconnectPipeline();
    return img;
}
예제 #9
0
void Mask::ReadFromImage(const std::string& filename,
                         const HolePixelValueWrapper<TPixel>& holeValue,
                         const ValidPixelValueWrapper<TPixel>& validValue)
{
  std::cout << "Reading mask from image: " << filename << std::endl;

  // Ensure the input image can be interpreted as a mask.
  unsigned int numberOfComponents = GetNumberOfComponentsPerPixelInFile( filename );

  if(!(numberOfComponents == 1 || numberOfComponents == 3))
  {
    std::stringstream ss;
    ss << "Number of components for a mask must be 1 or 3! (" << filename
       << " is " << numberOfComponents << ")";
    throw std::runtime_error(ss.str());
  }

  // Read the image
  typedef int ReadPixelType;
  typedef itk::Image<ReadPixelType, 2> ImageType;
  typedef  itk::ImageFileReader<ImageType> ImageReaderType;
  ImageReaderType::Pointer imageReader = ImageReaderType::New();
  imageReader->SetFileName(filename);
  imageReader->Update();

  this->SetRegions(imageReader->GetOutput()->GetLargestPossibleRegion());
  this->Allocate();

  CreateHolesFromValue(imageReader->GetOutput(),
                       static_cast<ReadPixelType>(holeValue.Value));
  CreateValidPixelsFromValue(imageReader->GetOutput(),
                             static_cast<ReadPixelType>(validValue.Value));
}
int main(int argc, char*argv[])
{
  if(argc != 5)
    {
    std::cerr << "Required arguments: image mask kernelRadius output" << std::endl;
    return EXIT_FAILURE;
    }

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

  std::stringstream ssRadius;
  ssRadius << argv[3];
  unsigned int kernelRadius = 0;
  ssRadius >> kernelRadius;

  std::string outputFilename = argv[4];

  std::cout << "Reading image: " << imageFilename << std::endl;
  std::cout << "Reading mask: " << maskFilename << std::endl;
  std::cout << "Kernel radius: " << kernelRadius << std::endl;
  std::cout << "Output: " << outputFilename << std::endl;

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

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

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

  MaskOperations::MedianFilterInHole(imageReader->GetOutput(), mask, kernelRadius);

  OutputHelpers::WriteImage(imageReader->GetOutput(), outputFilename);

  return EXIT_SUCCESS;
}
void ForegroundBackgroundSegmentMask::
ReadFromImage(const std::string& filename,
              const ForegroundPixelValueWrapper<TPixel>& foregroundValue,
              const BackgroundPixelValueWrapper<TPixel>& backgroundValue)
{
  std::cout << "Reading mask from image: " << filename << std::endl;

  // Ensure the input image can be interpreted as a mask.
  unsigned int numberOfComponents =
      ITKHelpers::GetNumberOfComponentsPerPixelInFile(filename);

  if(!(numberOfComponents == 1 || numberOfComponents == 3))
  {
    std::stringstream ss;
    ss << "Number of components for a mask must be 1 or 3! (" << filename
       << " is " << numberOfComponents << ")";
    throw std::runtime_error(ss.str());
  }

  // Read the image
  typedef int ReadPixelType;
  typedef itk::Image<ReadPixelType, 2> ImageType;
  typedef  itk::ImageFileReader<ImageType> ImageReaderType;
  ImageReaderType::Pointer imageReader = ImageReaderType::New();
  imageReader->SetFileName(filename);
  imageReader->Update();

  this->SetRegions(imageReader->GetOutput()->GetLargestPossibleRegion());
  this->Allocate();

  itk::ImageRegionConstIteratorWithIndex<ImageType>
      imageIterator(imageReader->GetOutput(),
                    imageReader->GetOutput()->GetLargestPossibleRegion());
  while(!imageIterator.IsAtEnd())
  {
    if(imageIterator.Get() == foregroundValue.Value)
    {
      this->SetPixel(imageIterator.GetIndex(),
                     ForegroundBackgroundSegmentMaskPixelTypeEnum::FOREGROUND);
    }
    else if(imageIterator.Get() == backgroundValue.Value)
    {
      this->SetPixel(imageIterator.GetIndex(),
                     ForegroundBackgroundSegmentMaskPixelTypeEnum::BACKGROUND);
    }
    else
    {
      std::cerr << "Warning: Pixels with value " << imageIterator.Get()
                << " found and is being ignored." << std::endl;
//      std::cerr << "Warning: Pixels with values other than the specified foreground "
//                   "and background values exist in the image and are being ignored." << std::endl;

    }
    ++imageIterator;
  }

}
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 << "Reading image: " << imageFilename << std::endl;
  std::cout << "Reading mask: " << maskFilename << std::endl;
  std::cout << "Output: " << outputFilename << std::endl;

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

  //typedef itk::Image<itk::CovariantVector<unsigned char, 3>, 2> ImageType;
//   ImageType::PixelType color;
//   color[0] = 0;
//   color[1] = 255;
//   color[2] = 0;

  typedef itk::VectorImage<float, 2> ImageType;
  
//   ImageType::PixelType color;
//   color.SetRed(0);
//   color.SetGreen(255);
//   color.SetBlue(0);


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

  ImageType::PixelType value(imageReader->GetOutput()->GetNumberOfComponentsPerPixel());
  value.Fill(0);
  
  Mask::Pointer mask = Mask::New();
  mask->Read(maskFilename.c_str());

  mask->ApplyToImage(imageReader->GetOutput(), value);

  OutputHelpers::WriteImage(imageReader->GetOutput(), outputFilename);

  return EXIT_SUCCESS;
}
예제 #13
0
파일: StrokeMask.hpp 프로젝트: Tabshi/Mask
void StrokeMask::
ReadFromImage(const std::string& filename,
              const TPixel& strokeValue)
{
  std::cout << "Reading stroke mask from image: " << filename << std::endl;

  // Ensure the input image can be interpreted as a mask.
  unsigned int numberOfComponents =
      ITKHelpers::GetNumberOfComponentsPerPixelInFile(filename);

  if(!(numberOfComponents == 1 || numberOfComponents == 3))
  {
    std::stringstream ss;
    ss << "Number of components for a mask must be 1 or 3! (" << filename
       << " is " << numberOfComponents << ")";
    throw std::runtime_error(ss.str());
  }

  // Read the image
  typedef int ReadPixelType;
  typedef itk::Image<ReadPixelType, 2> ImageType;
  typedef  itk::ImageFileReader<ImageType> ImageReaderType;
  ImageReaderType::Pointer imageReader = ImageReaderType::New();
  imageReader->SetFileName(filename);
  imageReader->Update();

  this->SetRegions(imageReader->GetOutput()->GetLargestPossibleRegion());
  this->Allocate();

  itk::ImageRegionConstIteratorWithIndex<ImageType>
      imageIterator(imageReader->GetOutput(),
                    imageReader->GetOutput()->GetLargestPossibleRegion());
  while(!imageIterator.IsAtEnd())
  {
    if(imageIterator.Get() == strokeValue)
    {
      this->SetPixel(imageIterator.GetIndex(),
                     StrokeMaskPixelTypeEnum::STROKE);
    }
    else
    {
      this->SetPixel(imageIterator.GetIndex(),
                     StrokeMaskPixelTypeEnum::NOTSTROKE);
    }
    ++imageIterator;
  }

}
예제 #14
0
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;
}
// Run with: Data/trashcan.mha Data/trashcan_mask.mha 15 filled.mha
int main(int argc, char *argv[])
{
  // Verify arguments
  if(argc != 6)
    {
    std::cerr << "Required arguments: image.mha imageMask.mha patchHalfWidth neighborhoodRadius output.mha" << 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;

  // The percent of the image size to use as the neighborhood (0 - 1)
  std::stringstream ssNeighborhoodPercent;
  ssNeighborhoodPercent << argv[4];
  float neighborhoodPercent = 0;
  ssNeighborhoodPercent >> neighborhoodPercent;

  std::string outputFileName = argv[5];

  // 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 << "Neighborhood percent: " << neighborhoodPercent << std::endl;
  std::cout << "Output: " << outputFileName << std::endl;

  typedef itk::Image<itk::CovariantVector<int, 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 << "hole pixels: " << mask->CountHolePixels() << std::endl;
  std::cout << "valid pixels: " << mask->CountValidPixels() << std::endl;

  typedef ImagePatchPixelDescriptor<ImageType> ImagePatchPixelDescriptorType;

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


  //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 PatchInpainter<ImageType> ImageInpainterType;
  std::shared_ptr<ImageInpainterType> imagePatchInpainter(new
      ImageInpainterType(patchHalfWidth, image, mask));

  // Create the priority function
   typedef PriorityRandom PriorityType;
   std::shared_ptr<PriorityType> priorityFunction(new PriorityType);
//  typedef PriorityCriminisi<ImageType> PriorityType;
//  std::shared_ptr<PriorityType> priorityFunction(new PriorityType(image, mask, patchHalfWidth));

  typedef IndirectPriorityQueue<VertexListGraphType> BoundaryNodeQueueType;
  std::shared_ptr<BoundaryNodeQueueType> boundaryNodeQueue(new BoundaryNodeQueueType(*graph));

  // Create the descriptor map. This is where the data for each pixel is stored.
  typedef boost::vector_property_map<ImagePatchPixelDescriptorType, BoundaryNodeQueueType::IndexMapType> ImagePatchDescriptorMapType;
//  ImagePatchDescriptorMapType imagePatchDescriptorMap(num_vertices(graph), indexMap);
  std::shared_ptr<ImagePatchDescriptorMapType> imagePatchDescriptorMap(new
      ImagePatchDescriptorMapType(num_vertices(*graph), *(boundaryNodeQueue->GetIndexMap())));

  // Create the descriptor visitor
  typedef ImagePatchDescriptorVisitor<VertexListGraphType, ImageType, ImagePatchDescriptorMapType>
          ImagePatchDescriptorVisitorType;
//  ImagePatchDescriptorVisitorType imagePatchDescriptorVisitor(image, mask, imagePatchDescriptorMap, patchHalfWidth);
  std::shared_ptr<ImagePatchDescriptorVisitorType> imagePatchDescriptorVisitor(new
      ImagePatchDescriptorVisitorType(image.GetPointer(), mask,
                                      imagePatchDescriptorMap, patchHalfWidth));
/*   ImagePatchDescriptorVisitor(TImage* const in_image, Mask* const in_mask,
  std::shared_ptr<TDescriptorMap> in_descriptorMap,
  const unsigned int in_half_width) : */
  typedef ImagePatchDifference<ImagePatchPixelDescriptorType, SumAbsolutePixelDifference<ImageType::PixelType> >
            ImagePatchDifferenceType;

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

  // Create the descriptor visitor


//  typedef CompositeAcceptanceVisitor<VertexListGraphType> CompositeAcceptanceVisitorType;
//  CompositeAcceptanceVisitorType compositeAcceptanceVisitor;

  typedef DefaultAcceptanceVisitor<VertexListGraphType> AcceptanceVisitorType;
  std::shared_ptr<AcceptanceVisitorType> acceptanceVisitor(new AcceptanceVisitorType);

//  typedef AlwaysAccept<VertexListGraphType> AcceptanceVisitorType;
//  AcceptanceVisitorType acceptanceVisitor;



  // If the hole is less than 15% of the patch, always accept the initial best match
//  HoleSizeAcceptanceVisitor<VertexListGraphType> holeSizeAcceptanceVisitor(mask, patchHalfWidth, .15);
//  compositeAcceptanceVisitor.AddOverrideVisitor(&holeSizeAcceptanceVisitor);

//  AllQuadrantHistogramCompareAcceptanceVisitor<VertexListGraphType, ImageType>
//               allQuadrantHistogramCompareAcceptanceVisitor(image, mask, patchHalfWidth, 8.0f); // Crazy low
//  compositeAcceptanceVisitor.AddRequiredPassVisitor(&allQuadrantHistogramCompareAcceptanceVisitor);

//  template <typename TGraph, typename TBoundaryNodeQueue,
//            typename TDescriptorVisitor, typename TAcceptanceVisitor, typename TPriority>

  typedef InpaintingVisitor<VertexListGraphType, BoundaryNodeQueueType,
                            ImagePatchDescriptorVisitorType, AcceptanceVisitorType, PriorityType>
                            InpaintingVisitorType;
  std::shared_ptr<InpaintingVisitorType> inpaintingVisitor(new InpaintingVisitorType(mask, boundaryNodeQueue,
                                                                                     imagePatchDescriptorVisitor, acceptanceVisitor,
                                                                                     priorityFunction, patchHalfWidth, "InpaintingVisitor"));

//  typedef InpaintingVisitor<VertexListGraphType, BoundaryNodeQueueType,
//                            ImagePatchDescriptorVisitorType, AcceptanceVisitorType, PriorityType>
//                            InpaintingVisitorType;
//  std::shared_ptr<InpaintingVisitorType> inpaintingVisitor(new InpaintingVisitorType(mask, boundaryNodeQueue,
//                                          imagePatchDescriptorVisitor, acceptanceVisitor,
//                                          priorityFunction, patchHalfWidth, "InpaintingVisitor"));

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

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

  InitializePriority(mask, boundaryNodeQueue.get(), priorityFunction.get());
  // Initialize the boundary node queue from the user provided mask image.
  InitializeFromMaskImage<InpaintingVisitorType, VertexDescriptorType>(mask, inpaintingVisitor.get());

  // For debugging we use LinearSearchBestProperty instead of DefaultSearchBest because it can output the difference value.
  typedef LinearSearchBestProperty<ImagePatchDescriptorMapType,
                                   ImagePatchDifferenceType > BestSearchType;
  std::shared_ptr<BestSearchType> linearSearchBest(new BestSearchType(*imagePatchDescriptorMap));

  typedef NeighborhoodSearch<VertexDescriptorType, ImagePatchDescriptorMapType> NeighborhoodSearchType;
  NeighborhoodSearchType neighborhoodSearch(image->GetLargestPossibleRegion(), image->GetLargestPossibleRegion().GetSize()[0] * neighborhoodPercent, *imagePatchDescriptorMap);
  
  InpaintingAlgorithmWithLocalSearch<VertexListGraphType, InpaintingVisitorType,
                      BoundaryNodeQueueType, NeighborhoodSearchType,
                      ImageInpainterType, BestSearchType>(graph, inpaintingVisitor, boundaryNodeQueue,
                      linearSearchBest, imagePatchInpainter, neighborhoodSearch);

  // If the output filename is a png file, then use the RGBImage writer so that it is first
  // casted to unsigned char. Otherwise, write the file directly.
  if(Helpers::GetFileExtension(outputFileName) == "png")
  {
    ITKHelpers::WriteRGBImage(image.GetPointer(), outputFileName);
  }
  else
  {
    ITKHelpers::WriteImage(image.GetPointer(), outputFileName);
  }

  return EXIT_SUCCESS;
}
// 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();
}
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;
}
int main(int argc, char*argv[])
{
  // Parse the input
  if(argc < 6)
  {
    std::cerr << "Required arguments: image sourceMask.mask targetMask.mask patchRadius output" << std::endl;
    return EXIT_FAILURE;
  }

  std::stringstream ss;
  for(int i = 1; i < argc; ++i)
  {
    ss << argv[i] << " ";
  }

  std::string imageFilename;
  std::string sourceMaskFilename;
  std::string targetMaskFilename;
  unsigned int patchRadius;
  std::string outputFilename;

  ss >> imageFilename >> sourceMaskFilename >> targetMaskFilename >> patchRadius >> outputFilename;

  // Output the parsed values
  std::cout << "imageFilename: " << imageFilename << std::endl
            << "sourceMaskFilename: " << sourceMaskFilename << std::endl
            << "targetMaskFilename: " << targetMaskFilename << std::endl
            << "patchRadius: " << patchRadius << std::endl
            << "outputFilename: " << outputFilename << std::endl;

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

  // Read the image and the masks
  typedef itk::ImageFileReader<ImageType> ImageReaderType;
  ImageReaderType::Pointer imageReader = ImageReaderType::New();
  imageReader->SetFileName(imageFilename);
  imageReader->Update();

  ImageType* image = imageReader->GetOutput();

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

  Mask::Pointer targetMask = Mask::New();
  targetMask->Read(targetMaskFilename);

  // Poisson fill the input image in HSV space
  typedef itk::Image<itk::CovariantVector<float, 3>, 2> HSVImageType;
  HSVImageType::Pointer hsvImage = HSVImageType::New();
  ITKVTKHelpers::ConvertRGBtoHSV(image, hsvImage.GetPointer());

  ITKHelpers::WriteImage(image, "HSV.mha");

  typedef PoissonEditing<typename TypeTraits<HSVImageType::PixelType>::ComponentType> PoissonEditingType;

  typename PoissonEditingType::GuidanceFieldType::Pointer zeroGuidanceField =
            PoissonEditingType::GuidanceFieldType::New();
  zeroGuidanceField->SetRegions(hsvImage->GetLargestPossibleRegion());
  zeroGuidanceField->Allocate();
  typename PoissonEditingType::GuidanceFieldType::PixelType zeroPixel;
  zeroPixel.Fill(0);
  ITKHelpers::SetImageToConstant(zeroGuidanceField.GetPointer(), zeroPixel);

  PoissonEditingType::FillImage(hsvImage.GetPointer(), targetMask,
                                zeroGuidanceField.GetPointer(), hsvImage.GetPointer());

  ITKHelpers::WriteImage(image, "PoissonFilled_HSV.mha");

  ITKVTKHelpers::ConvertHSVtoRGB(hsvImage.GetPointer(), image);

  ITKHelpers::WriteRGBImage(image, "PoissonFilled_HSV.png");

  // PatchMatch requires that the target region be specified by valid pixels
  targetMask->InvertData();

  // Here, the source mask and target mask are the same, specifying the classicial
  // "use pixels outside the hole to fill the pixels inside the hole".
  // In an interactive algorith, the user could manually specify a source region,
  // improving the resulting inpainting.
  BDSInpaintingRings<ImageType> bdsInpainting;
  bdsInpainting.SetPatchRadius(patchRadius);
  bdsInpainting.SetImage(image);
  bdsInpainting.SetSourceMask(sourceMask);
  bdsInpainting.SetTargetMask(targetMask);

  bdsInpainting.SetIterations(1);
  //bdsInpainting.SetIterations(4);

  Compositor<ImageType, PixelCompositorAverage> compositor;
  bdsInpainting.Inpaint();

  ITKHelpers::WriteRGBImage(bdsInpainting.GetOutput(), outputFilename);

  return EXIT_SUCCESS;
}
예제 #19
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;
}
// Run with: Data/trashcan.mha Data/trashcan_mask.mha 15 Data/trashcan.vtp Intensity filled.mha
int main(int argc, char *argv[])
{
  // Verify arguments
  if(argc != 6)
    {
    std::cerr << "Required arguments: image.mha imageMask.mha patch_half_width normals.vts output.mha" << 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 patch_half_width = 0;
  ssPatchRadius >> patch_half_width;

  std::string normalsFileName = argv[4];

  std::string outputFilename = argv[5];

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

  vtkSmartPointer<vtkXMLStructuredGridReader> structuredGridReader = vtkSmartPointer<vtkXMLStructuredGridReader>::New();
  structuredGridReader->SetFileName(normalsFileName.c_str());
  structuredGridReader->Update();
  
  typedef FloatVectorImageType 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 << "hole pixels: " << mask->CountHolePixels() << std::endl;
  std::cout << "valid pixels: " << mask->CountValidPixels() << std::endl;

  typedef ImagePatchPixelDescriptor<ImageType> ImagePatchPixelDescriptorType;
  typedef FeatureVectorPixelDescriptor FeatureVectorPixelDescriptorType;

  // Create the graph
  typedef boost::grid_graph<2> VertexListGraphType;
  boost::array<std::size_t, 2> graphSideLengths = { { imageReader->GetOutput()->GetLargestPossibleRegion().GetSize()[0],
                                                      imageReader->GetOutput()->GetLargestPossibleRegion().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 node fill status map. Each pixel is either filled (true) or not filled (false).
  typedef boost::vector_property_map<bool, IndexMapType> FillStatusMapType;
  FillStatusMapType fillStatusMap(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);

  // Create the descriptor map. This is where the data for each pixel is stored.
  typedef boost::vector_property_map<FeatureVectorPixelDescriptorType, IndexMapType> FeatureVectorDescriptorMapType;
  FeatureVectorDescriptorMapType featureVectorDescriptorMap(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 MaskedGridPatchInpainter<FillStatusMapType> InpainterType;
  InpainterType patchInpainter(patch_half_width, fillStatusMap);

  // Create the priority function
  typedef PriorityRandom PriorityType;
  PriorityType priorityFunction;

  // 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
  typedef std::less<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 visitors
  typedef FeatureVectorPrecomputedStructuredGridNormalsDescriptorVisitor<VertexListGraphType, FeatureVectorDescriptorMapType> FeatureVectorPrecomputedStructuredGridNormalsDescriptorVisitorType;
  FeatureVectorPrecomputedStructuredGridNormalsDescriptorVisitorType featureVectorPrecomputedStructuredGridNormalsDescriptorVisitor(featureVectorDescriptorMap, structuredGridReader->GetOutput());

  typedef ImagePatchDescriptorVisitor<VertexListGraphType, ImageType, ImagePatchDescriptorMapType> ImagePatchDescriptorVisitorType;
  ImagePatchDescriptorVisitorType imagePatchDescriptorVisitor(image, mask, imagePatchDescriptorMap, patch_half_width);

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

  // Create the inpainting visitor
  typedef InpaintingVisitor<VertexListGraphType, ImageType, BoundaryNodeQueueType, FillStatusMapType,
                            CompositeDescriptorVisitorType, PriorityType, PriorityMapType, BoundaryStatusMapType> InpaintingVisitorType;
  InpaintingVisitorType inpaintingVisitor(image, mask, boundaryNodeQueue, fillStatusMap,
                                          compositeDescriptorVisitor, priorityMap, &priorityFunction, patch_half_width, boundaryStatusMap);

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

  // Initialize the boundary node queue from the user provided mask image.
  InitializeFromMaskImage(mask, &inpaintingVisitor, graph, fillStatusMap);
  std::cout << "PatchBasedInpaintingNonInteractive: There are " << boundaryNodeQueue.size()
            << " nodes in the boundaryNodeQueue" << std::endl;

  // Create the nearest neighbor finder
//   typedef LinearSearchKNNProperty<FeatureVectorDescriptorMapType, FeatureVectorAngleDifference> KNNSearchType;
//   KNNSearchType linearSearchKNN(featureVectorDescriptorMap);
  typedef LinearSearchCriteriaProperty<FeatureVectorDescriptorMapType, FeatureVectorAngleDifference> ThresholdSearchType;
  //float maximumAngle = 0.34906585; // ~ 20 degrees
  float maximumAngle = 0.15; // ~ 10 degrees
  //float maximumAngle = 0.08; // ~ 5 degrees (this seems to be too strict)
  ThresholdSearchType thresholdSearchType(featureVectorDescriptorMap, maximumAngle);

  typedef LinearSearchBestProperty<ImagePatchDescriptorMapType, ImagePatchDifference<ImagePatchPixelDescriptorType> > BestSearchType;
  BestSearchType linearSearchBest(imagePatchDescriptorMap);

  TwoStepNearestNeighbor<ThresholdSearchType, BestSearchType> twoStepNearestNeighbor(thresholdSearchType, linearSearchBest);

  // Perform the inpainting
  std::cout << "Performing inpainting...: " << std::endl;
  inpainting_loop(graph, inpaintingVisitor, boundaryStatusMap, boundaryNodeQueue, twoStepNearestNeighbor, patchInpainter);

  HelpersOutput::WriteImage<ImageType>(image, outputFilename);

  return EXIT_SUCCESS;
}
예제 #21
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 argc, char* argv[])
{
  // Verify arguments
  if(argc < 5)
    {
    std::cout << "Usage: ImageToFill mask guidanceField outputImage" << std::endl;
    return EXIT_FAILURE;
    }

  // Parse arguments
  std::string targetImageFilename = argv[1];
  std::string maskFilename = argv[2];
  std::string guidanceFieldFilename = argv[3];
  std::string outputFilename = argv[4];

  // Output arguments
  std::cout << "Target image: " << targetImageFilename << std::endl
            << "Mask image: " << maskFilename << std::endl
            << "Guidance field: " << guidanceFieldFilename << std::endl
            << "Output image: " << outputFilename << std::endl;

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

  // Read images
  typedef itk::ImageFileReader<ImageType> ImageReaderType;
  ImageReaderType::Pointer targetImageReader = ImageReaderType::New();
  targetImageReader->SetFileName(targetImageFilename);
  targetImageReader->Update();

  std::cout << "Read target image." << std::endl;

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

  std::cout << "Read mask." << std::endl;

  typedef itk::CovariantVector<float, 2> Vector2Type;
  typedef itk::Image<Vector2Type, 2> Vector2ImageType;
  typedef itk::ImageFileReader<Vector2ImageType> GuidanceFieldReaderType;

  GuidanceFieldReaderType::Pointer guidanceFieldReader = GuidanceFieldReaderType::New();
  guidanceFieldReader->SetFileName(guidanceFieldFilename);
  guidanceFieldReader->Update();

  std::cout << "Read guidance field." << std::endl;

  typedef PoissonEditing<float> PoissonEditingFilterType;
  PoissonEditingFilterType poissonFilter;
  poissonFilter.SetTargetImage(targetImageReader->GetOutput());
  poissonFilter.SetGuidanceField(guidanceFieldReader->GetOutput());
  poissonFilter.SetMask(mask);
  poissonFilter.FillMaskedRegion();

  // Write output
  ITKHelpers::WriteImage(poissonFilter.GetOutput(), outputFilename);
  // Helpers::WriteVectorImageAsPNG(output.GetPointer(), outputFilename);

  return EXIT_SUCCESS;
}
예제 #23
0
int
main(int argc, char* argv[])
{
	boost::filesystem::path inputFile;
	boost::filesystem::path outputFile;

	Algorithm algorithm;
	std::string algorithmName;

	po::options_description desc("Allowed options");
	desc.add_options()
		("help", "produce help message")
		("input,i", po::value<boost::filesystem::path>(&inputFile), "input file")
		("algorithm,a", po::value<std::string>(&algorithmName)->default_value("itk-implementation"), "itk-implementation")
		("output,o", po::value<boost::filesystem::path>(&outputFile), "output mask file")
		;

	po::variables_map vm;
	po::store(po::parse_command_line(argc, argv, desc), vm);
	po::notify(vm);

	algorithm = getAlgorithmFromString(algorithmName);

	if (vm.count("help")) {
		std::cout << desc << "\n";
		return 1;
	}

	if (vm.count("input") == 0) {
		std::cout << "Missing input filename\n" << desc << "\n";
		return 1;
	}

	if (vm.count("output") == 0) {
		std::cout << "Missing output filename\n" << desc << "\n";
		return 1;
	}

	typedef itk::ImageFileReader<ImageType>  ImageReaderType;

	BOOST_LOG_TRIVIAL(info) << "Loading inputs ...";
	ImageReaderType::Pointer imageReader = ImageReaderType::New();
	imageReader->SetFileName(inputFile.string());
	imageReader->Update();

	ImageType::Pointer image = imageReader->GetOutput();

	LabeledImageType::Pointer outputImage;

	switch (algorithm) {
	case Algorithm::ItkImplementation: {
		BOOST_LOG_TRIVIAL(info) << "Running ITK version of watershed transformation ...";
			WatershedFilterType::Pointer filter = WatershedFilterType::New();
			filter->SetInput(image);
			filter->MarkWatershedLineOff();

			boost::timer::cpu_timer computationTimer;
			computationTimer.start();
			filter->Update();
			BOOST_LOG_TRIVIAL(info) << "Computation time: " << computationTimer.format(9, "%w");

			outputImage = filter->GetOutput();
		}
		break;
	default:
		BOOST_LOG_TRIVIAL(info) << "Allocating output ...";
		outputImage = LabeledImageType::New();
		outputImage->SetRegions(image->GetLargestPossibleRegion());
		outputImage->Allocate();
		outputImage->SetSpacing(image->GetSpacing());
		BOOST_LOG_TRIVIAL(info) << "Running CUDA version of watershed transformation (topographical distance)...";
		boost::timer::cpu_timer computationTimer;
		computationTimer.start();
		watershedTransformation2(
			cugip::const_view(*(image.GetPointer())),
			cugip::view(*(outputImage.GetPointer())),
			Options()
			);
		BOOST_LOG_TRIVIAL(info) << "Computation time: " << computationTimer.format(9, "%w");
		//BOOST_LOG_TRIVIAL(error) << "Unknown algorithm";
	}

	BOOST_LOG_TRIVIAL(info) << "Saving output `" << outputFile << "` ...";
	WriterType::Pointer writer = WriterType::New();
	writer->SetFileName(outputFile.string());
	writer->SetInput(outputImage);
	try {
		writer->Update();
	} catch (itk::ExceptionObject & error) {
		std::cerr << "Error: " << error << std::endl;
		return EXIT_FAILURE;
	}

	return 0;
}
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[])
{
  // Verify arguments
  if(argc != 5)
  {
    std::cerr << "Required arguments: image.png imageMask.mask patchHalfWidth targetPatch.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 ssPatchHalfWidth;
  ssPatchHalfWidth << argv[3];
  unsigned int patchHalfWidth = 0;
  ssPatchHalfWidth >> patchHalfWidth;

  std::string targetPatchFileName = 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 << "targetPatchFileName: " << targetPatchFileName << std::endl;

  typedef itk::Image<itk::CovariantVector<int, 3>, 2> OriginalImageType;

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

  OriginalImageType* originalImage = imageReader->GetOutput();

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

  itk::ImageRegion<2> fullRegion = originalImage->GetLargestPossibleRegion();

  // Blur the image
//  typedef TImage BlurredImageType; // Usually the blurred image is the same type as the original image.
//  typename BlurredImageType::Pointer blurredImage = BlurredImageType::New();
//  float blurVariance = 2.0f;
////  float blurVariance = 1.2f;
//  MaskOperations::MaskedBlur(originalImage.GetPointer(), mask, blurVariance, blurredImage.GetPointer());

//  ITKHelpers::WriteRGBImage(blurredImage.GetPointer(), "BlurredImage.png");

  typedef ImagePatchPixelDescriptor<OriginalImageType> ImagePatchPixelDescriptorType;

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

  // Queue
  typedef IndirectPriorityQueue<VertexListGraphType> BoundaryNodeQueueType;
  std::shared_ptr<BoundaryNodeQueueType> boundaryNodeQueue(new BoundaryNodeQueueType(*graph));

  // Create the descriptor map. This is where the data for each pixel is stored.
  typedef boost::vector_property_map<ImagePatchPixelDescriptorType,
      BoundaryNodeQueueType::IndexMapType> ImagePatchDescriptorMapType;
  std::shared_ptr<ImagePatchDescriptorMapType> imagePatchDescriptorMap(new
      ImagePatchDescriptorMapType(num_vertices(*graph), *(boundaryNodeQueue->GetIndexMap())));

  // Create the descriptor visitor
  typedef ImagePatchDescriptorVisitor<VertexListGraphType, OriginalImageType, ImagePatchDescriptorMapType>
      ImagePatchDescriptorVisitorType;
  std::shared_ptr<ImagePatchDescriptorVisitorType> imagePatchDescriptorVisitor(new
      ImagePatchDescriptorVisitorType(originalImage, mask,
//        ImagePatchDescriptorVisitorType(blurredImage.GetPointer(), mask,
                                      imagePatchDescriptorMap, patchHalfWidth));

  // Create the inpainting visitor
//  typedef InpaintingVisitor<VertexListGraphType, BoundaryNodeQueueType,
//                            ImagePatchDescriptorVisitorType, AcceptanceVisitorType, PriorityType>
//                            InpaintingVisitorType;
//  std::shared_ptr<InpaintingVisitorType> inpaintingVisitor(new InpaintingVisitorType(mask, boundaryNodeQueue,
//                                          imagePatchDescriptorVisitor, acceptanceVisitor,
//                                          priorityFunction, patchHalfWidth, "InpaintingVisitor"));
//  inpaintingVisitor->SetAllowNewPatches(false);

//  // Initialize the boundary node queue from the user provided mask image.
//  InitializeFromMaskImage<InpaintingVisitorType, VertexDescriptorType>(mask, inpaintingVisitor.get());

//  // Create the nearest neighbor finder
//  typedef ImagePatchDifference<ImagePatchPixelDescriptorType,
//      SumSquaredPixelDifference<typename TImage::PixelType> > PatchDifferenceType;

//  // Write top patch grid at each iteration. To do this, we need a KNNSearcher
//  // to pass a list of valid patches to the FirstAndWrite class.
//  typedef LinearSearchKNNProperty<ImagePatchDescriptorMapType,
//                                  PatchDifferenceType > KNNSearchType;

//  unsigned int knn = 100;
//  std::shared_ptr<KNNSearchType> knnSearch(new KNNSearchType(imagePatchDescriptorMap, knn));

//  typedef LinearSearchBestFirstAndWrite<ImagePatchDescriptorMapType, TImage,
//                                   PatchDifferenceType> BestSearchType;
//  std::shared_ptr<BestSearchType> linearSearchBest(
//        new BestSearchType(*imagePatchDescriptorMap, originalImage, mask));

////  typedef KNNBestWrapper<KNNSearchType, BestSearchType> KNNWrapperType;
////  std::shared_ptr<KNNWrapperType> knnWrapper(new KNNWrapperType(knnSearch,
////                                                                linearSearchBest));


  return EXIT_SUCCESS;
}
예제 #26
0
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;
}
// Run with: Data/trashcan.png Data/trashcan.mask 15 filled.png
int main(int argc, char *argv[])
{
  // Verify arguments
  if(argc != 5)
  {
    std::cerr << "Required arguments: image.png imageMask.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 ssPatchHalfWidth;
  ssPatchHalfWidth << argv[3];
  unsigned int patchHalfWidth = 0;
  ssPatchHalfWidth >> 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<int, 3>, 2> OriginalImageType;

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

//  OriginalImageType* originalImage = imageReader->GetOutput();

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

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

  ClassicalImageInpaintingDebug(originalImage, mask, patchHalfWidth);

  // If the output filename is a png file, then use the RGBImage writer so that it is first
  // casted to unsigned char. Otherwise, write the file directly.
  if(Helpers::GetFileExtension(outputFileName) == "png")
  {
    ITKHelpers::WriteRGBImage(originalImage.GetPointer(), outputFileName);
  }
  else
  {
    ITKHelpers::WriteImage(originalImage.GetPointer(), outputFileName);
  }

  return EXIT_SUCCESS;
}
int main(int argc, char*argv[])
{
  // Parse the input
  if(argc < 6)
  {
    std::cerr << "Required arguments: image sourceMask.mask targetMask.mask patchRadius output" << std::endl;
    return EXIT_FAILURE;
  }

  std::stringstream ss;
  for(int i = 1; i < argc; ++i)
  {
    ss << argv[i] << " ";
  }

  std::string imageFilename;
  std::string sourceMaskFilename;
  std::string targetMaskFilename;
  unsigned int patchRadius;
  std::string outputFilename;

  ss >> imageFilename >> sourceMaskFilename >> targetMaskFilename >> patchRadius >> outputFilename;

  // Output the parsed values
  std::cout << "imageFilename: " << imageFilename << std::endl
            << "sourceMaskFilename: " << sourceMaskFilename << std::endl
            << "targetMaskFilename: " << targetMaskFilename << std::endl
            << "patchRadius: " << patchRadius << std::endl
            << "outputFilename: " << outputFilename << std::endl;

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

  // Read the image and the masks
  typedef itk::ImageFileReader<ImageType> ImageReaderType;
  ImageReaderType::Pointer imageReader = ImageReaderType::New();
  imageReader->SetFileName(imageFilename);
  imageReader->Update();

  ImageType* image = imageReader->GetOutput();

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

  Mask::Pointer targetMask = Mask::New();
  targetMask->Read(targetMaskFilename);

  //std::cout << "target mask has " << targetMask->CountHolePixels() << " hole pixels." << std::endl;

  // Poisson fill the input image
  typedef PoissonEditing<typename TypeTraits<ImageType::PixelType>::ComponentType> PoissonEditingType;

  typename PoissonEditingType::GuidanceFieldType::Pointer zeroGuidanceField =
            PoissonEditingType::GuidanceFieldType::New();
  zeroGuidanceField->SetRegions(image->GetLargestPossibleRegion());
  zeroGuidanceField->Allocate();
  typename PoissonEditingType::GuidanceFieldType::PixelType zeroPixel;
  zeroPixel.Fill(0);
  ITKHelpers::SetImageToConstant(zeroGuidanceField.GetPointer(), zeroPixel);

  PoissonEditingType::FillImage(image, targetMask,
                                zeroGuidanceField.GetPointer(), image);

  ITKHelpers::WriteRGBImage(image, "PoissonFilled.png");

  // PatchMatch requires that the target region be specified by valid pixels
  targetMask->InvertData();

  // Setup the patch distance functor
  SSD<ImageType> ssdFunctor;
  ssdFunctor.SetImage(image);

  // Setup the PatchMatch functor
  //PatchMatch<ImageType> patchMatchFunctor;
  PatchMatchRings<ImageType> patchMatchFunctor;
  patchMatchFunctor.SetPatchRadius(patchRadius);
  patchMatchFunctor.SetPatchDistanceFunctor(&ssdFunctor);
  patchMatchFunctor.SetIterations(1);

  InitializerRandom<ImageType> initializer;
  initializer.SetImage(image);
  initializer.SetTargetMask(targetMask);
  initializer.SetSourceMask(sourceMask);
  initializer.SetPatchDistanceFunctor(&ssdFunctor);
  initializer.SetPatchRadius(patchRadius);
  patchMatchFunctor.SetInitializer(&initializer);

  // Test the result of PatchMatch here
   patchMatchFunctor.SetRandom(false);

  // Here, the source match and target match are the same, specifying the classicial
  // "use pixels outside the hole to fill the pixels inside the hole".
  // In an interactive algorith, the user could manually specify a source region,
  // improving the resulting inpainting.
  BDSInpaintingMultiRes<ImageType> bdsInpainting;
  bdsInpainting.SetPatchRadius(patchRadius);
  bdsInpainting.SetImage(image);
  bdsInpainting.SetSourceMask(sourceMask);
  bdsInpainting.SetTargetMask(targetMask);

  bdsInpainting.SetIterations(1);
  //bdsInpainting.SetIterations(4);

  Compositor<ImageType> compositor;
  compositor.SetCompositingMethod(Compositor<ImageType>::AVERAGE);
  bdsInpainting.SetCompositor(&compositor);

  bdsInpainting.SetPatchMatchFunctor(&patchMatchFunctor);
  bdsInpainting.Inpaint();

  ITKHelpers::WriteRGBImage(bdsInpainting.GetOutput(), 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();

  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;
}