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[]) { // 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; }