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; }
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)); }
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 << "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; }
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; }
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; } }
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 ); }
// 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(); }
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; }
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 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; }
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; }
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; } }
int main(int argc, char *argv[]) { if(argc != 3) { std::cerr << "Required arguments: image mask" << std::endl; return EXIT_FAILURE; } std::string imageFilename = argv[1]; std::string maskFilename = argv[2]; std::cout << "Reading image: " << imageFilename << std::endl; std::cout << "Reading mask: " << maskFilename << std::endl; typedef itk::ImageFileReader<FloatVectorImageType> ImageReaderType; ImageReaderType::Pointer imageReader = ImageReaderType::New(); imageReader->SetFileName(imageFilename.c_str()); imageReader->Update(); std::cout << "Read image " << imageReader->GetOutput()->GetLargestPossibleRegion() << std::endl; typedef itk::ImageFileReader<Mask> MaskReaderType; MaskReaderType::Pointer maskReader = MaskReaderType::New(); maskReader->SetFileName(maskFilename.c_str()); maskReader->Update(); std::cout << "Read mask " << maskReader->GetOutput()->GetLargestPossibleRegion() << std::endl; // Prepare image RGBImageType::Pointer rgbImage = RGBImageType::New(); // Helpers::VectorImageToRGBImage(imageReader->GetOutput(), rgbImage); // TODO: Update this call to new API //maskReader->GetOutput()->ApplyToImage(rgbImage.GetPointer(), Qt::black); OutputHelpers::WriteImage<RGBImageType>(rgbImage, "Test/TestIsophotes.rgb.mha"); typedef itk::RGBToLuminanceImageFilter< RGBImageType, FloatScalarImageType > LuminanceFilterType; LuminanceFilterType::Pointer luminanceFilter = LuminanceFilterType::New(); luminanceFilter->SetInput(rgbImage); luminanceFilter->Update(); OutputHelpers::WriteImage<FloatScalarImageType>(luminanceFilter->GetOutput(), "Test/Luminance.mha"); // PatchBasedInpainting inpainting; // inpainting.SetDebugImages(true); // inpainting.SetMask(maskReader->GetOutput()); // inpainting.SetImage(imageReader->GetOutput()); //Helpers::Write2DVectorImage(inpainting.GetIsophoteImage(), "Test/TestIsophotes.isophotes.mha"); //inpainting.FindBoundary(); // After blurVariance == 4, you cannot tell the difference in the output. for(unsigned int blurVariance = 0; blurVariance < 5; ++blurVariance) { std::string fileNumber = Helpers::ZeroPad(blurVariance, 2); FloatScalarImageType::Pointer blurredLuminance = FloatScalarImageType::New(); // Blur with a Gaussian kernel MaskOperations::MaskedBlur(luminanceFilter->GetOutput(), maskReader->GetOutput(), blurVariance, blurredLuminance.GetPointer()); std::stringstream ssBlurredLuminance; ssBlurredLuminance << "Test/BlurredLuminance_" << fileNumber << ".mha"; OutputHelpers::WriteImage(blurredLuminance.GetPointer(), ssBlurredLuminance.str()); //Helpers::WriteImage<FloatScalarImageType>(blurredLuminance, "Test/TestIsophotes.blurred.mha"); FloatVector2ImageType::Pointer gradient = FloatVector2ImageType::New(); Derivatives::MaskedGradient(blurredLuminance.GetPointer(), maskReader->GetOutput(), gradient.GetPointer()); // Boundary gradient typedef itk::MaskImageFilter< FloatVector2ImageType, UnsignedCharScalarImageType, FloatVector2ImageType > MaskFilterType; MaskFilterType::Pointer maskFilter = MaskFilterType::New(); maskFilter->SetInput(gradient); //maskFilter->SetMaskImage(inpainting.GetBoundaryImage()); maskFilter->Update(); vtkSmartPointer<vtkPolyData> boundaryGradient = vtkSmartPointer<vtkPolyData>::New(); // TODO: Convert this call to new API //Helpers::ConvertNonZeroPixelsToVectors(maskFilter->GetOutput(), boundaryGradient); std::stringstream ssPolyData; ssPolyData << "Test/BoundaryGradient_" << fileNumber << ".vtp"; OutputHelpers::WritePolyData(boundaryGradient, ssPolyData.str()); } return EXIT_SUCCESS; }
int main(int argc, char*argv[]) { // 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; }
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; }
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; }
// 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[]) { // 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; }
// 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; }
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[]) { 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[]) { 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[]) { // 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 != 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; }