int main() { FloatVectorImageType::Pointer image = FloatVectorImageType::New(); Testing::GetBlankImage(image.GetPointer(), 4); Mask::Pointer mask = Mask::New(); Testing::GetFullyValidMask(mask.GetPointer()); UnsignedCharScalarImageType::Pointer manualPriorityImage = UnsignedCharScalarImageType::New(); Testing::GetBlankImage(manualPriorityImage.GetPointer()); unsigned int patchRadius = 5; typedef PriorityConfidence ConfidencePriorityType; ConfidencePriorityType priorityConfidence(mask, patchRadius); PriorityManual<itk::Index<2>, UnsignedCharScalarImageType, ConfidencePriorityType> priority(manualPriorityImage, &priorityConfidence); itk::Index<2> filledPixel = {{0,0}}; priority.Update(filledPixel); priority.SetManualPriorityImage(manualPriorityImage); itk::Index<2> queryPixel = {{0,0}}; priority.ComputePriority(queryPixel); return EXIT_SUCCESS; }
int main(int argc, char *argv[]) { 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]; Mask::Pointer mask = Mask::New(); mask->Read(maskFilename); typedef itk::Image<unsigned char, 2> ImageType; ImageType::Pointer image = ImageType::New(); ITKHelpers::ReadImage(imageFilename, image.GetPointer()); FastDigitalInpainting fastDigitalInpainting; fastDigitalInpainting.SetImage(image); fastDigitalInpainting.SetMask(mask); fastDigitalInpainting.SetNumberOfIterations(100); fastDigitalInpainting.Inpaint(); ITKHelpers::WriteImage(fastDigitalInpainting.GetOutput(), outputFilename); return EXIT_SUCCESS; }
void CriminisiInpainting::InitializeConfidence() { // Clone the mask - we need to invert the mask to actually perform the masking, but we don't want to disturb the original mask Mask::Pointer maskClone = Mask::New(); //Helpers::DeepCopy<Mask>(this->CurrentMask, maskClone); maskClone->DeepCopyFrom(this->CurrentMask); // Invert the mask typedef itk::InvertIntensityImageFilter <Mask> InvertIntensityImageFilterType; InvertIntensityImageFilterType::Pointer invertIntensityFilter = InvertIntensityImageFilterType::New(); invertIntensityFilter->SetInput(maskClone); //invertIntensityFilter->InPlaceOn(); invertIntensityFilter->Update(); // Convert the inverted mask to floats and scale them to between 0 and 1 // to serve as the initial confidence image typedef itk::RescaleIntensityImageFilter< Mask, FloatScalarImageType > RescaleFilterType; RescaleFilterType::Pointer rescaleFilter = RescaleFilterType::New(); rescaleFilter->SetInput(invertIntensityFilter->GetOutput()); rescaleFilter->SetOutputMinimum(0); rescaleFilter->SetOutputMaximum(1); rescaleFilter->Update(); Helpers::DeepCopy<FloatScalarImageType>(rescaleFilter->GetOutput(), this->ConfidenceImage); //WriteImage<FloatImageType>(this->ConfidenceImage, "InitialConfidence.mhd"); }
void CriminisiInpainting::UpdateMask(const itk::Index<2> inputPixel) { try { // Create a black patch Mask::Pointer blackPatch = Mask::New(); //Helpers::CreateBlankPatch<UnsignedCharScalarImageType>(blackPatch, this->PatchRadius[0]); Helpers::CreateConstantPatch<Mask>(blackPatch, this->CurrentMask->GetValidValue(), this->PatchRadius[0]); itk::Index<2> pixel; pixel[0] = inputPixel[0] - blackPatch->GetLargestPossibleRegion().GetSize()[0]/2; pixel[1] = inputPixel[1] - blackPatch->GetLargestPossibleRegion().GetSize()[1]/2; // Paste it into the mask typedef itk::PasteImageFilter <Mask, Mask> PasteImageFilterType; PasteImageFilterType::Pointer pasteFilter = PasteImageFilterType::New(); //pasteFilter->SetInput(0, this->CurrentMask); //pasteFilter->SetInput(1, blackPatch); pasteFilter->SetSourceImage(blackPatch); pasteFilter->SetDestinationImage(this->CurrentMask); pasteFilter->SetSourceRegion(blackPatch->GetLargestPossibleRegion()); pasteFilter->SetDestinationIndex(pixel); pasteFilter->Update(); // Not sure how Mask::DeepCopyFrom would work on the output of a filter, so do this manually. Helpers::DeepCopy<Mask>(pasteFilter->GetOutput(), this->CurrentMask); this->CurrentMask->SetHoleValue(this->OriginalMask->GetHoleValue()); this->CurrentMask->SetValidValue(this->OriginalMask->GetValidValue()); } catch( itk::ExceptionObject & err ) { std::cerr << "ExceptionObject caught in UpdateMask!" << std::endl; std::cerr << err << std::endl; exit(-1); } }
int main(int argc, char*argv[]) { if(argc != 3) { std::cerr << "Required arguments: mask output" << std::endl; return EXIT_FAILURE; } std::string maskFilename = argv[1]; std::string outputFilename = argv[2]; std::cout << "Reading mask: " << maskFilename << std::endl; std::cout << "Output: " << outputFilename << std::endl; Mask::Pointer mask = Mask::New(); mask->Read(maskFilename.c_str()); Mask::BoundaryImageType::Pointer boundaryImage = Mask::BoundaryImageType::New(); boundaryImage->SetRegions(mask->GetLargestPossibleRegion()); boundaryImage->Allocate(); // mask->CreateBoundaryImage(boundaryImage.GetPointer(), mask->GetValidValue()); mask->CreateBoundaryImage(boundaryImage.GetPointer(), Mask::VALID); ITKHelpers::WriteImage(boundaryImage.GetPointer(), outputFilename); return EXIT_SUCCESS; }
int main() { typedef itk::Image<itk::CovariantVector<float, 3>, 2> ImageType; // typedef FloatVectorImageType ImageType; ImageType::Pointer image = ImageType::New(); Testing::GetBlankImage(image.GetPointer(), 4); Mask::Pointer mask = Mask::New(); Testing::GetFullyValidMask(mask.GetPointer()); unsigned int patchRadius = 5; PriorityCriminisi<ImageType> priority(image.GetPointer(), mask.GetPointer(), patchRadius); itk::Index<2> sourcePixel; sourcePixel.Fill(0); itk::Index<2> targetPixel; targetPixel.Fill(1); priority.Update(sourcePixel, targetPixel); itk::Index<2> queryPixel = {{0,0}}; priority.ComputePriority(queryPixel); return EXIT_SUCCESS; }
// Run with: image.png image.mask 15 filled.png int main(int argc, char *argv[]) { // Verify arguments if(argc != 5) { std::cerr << "Required arguments: image.png image.mask patchHalfWidth output.png" << std::endl; std::cerr << "Input arguments: "; for(int i = 1; i < argc; ++i) { std::cerr << argv[i] << " "; } return EXIT_FAILURE; } // Parse arguments std::string imageFilename = argv[1]; std::string maskFilename = argv[2]; std::stringstream ssPatchRadius; ssPatchRadius << argv[3]; unsigned int patchHalfWidth = 0; ssPatchRadius >> patchHalfWidth; std::string outputFilename = argv[4]; // Output arguments std::cout << "Reading image: " << imageFilename << std::endl; std::cout << "Reading mask: " << maskFilename << std::endl; std::cout << "Patch half width: " << patchHalfWidth << std::endl; std::cout << "Output: " << outputFilename << std::endl; typedef itk::Image<itk::CovariantVector<float, 3>, 2> ImageType; typedef itk::ImageFileReader<ImageType> ImageReaderType; ImageReaderType::Pointer imageReader = ImageReaderType::New(); imageReader->SetFileName(imageFilename); imageReader->Update(); ImageType::Pointer image = ImageType::New(); ITKHelpers::DeepCopy(imageReader->GetOutput(), image.GetPointer()); Mask::Pointer mask = Mask::New(); mask->Read(maskFilename); std::cout << "Mask size: " << mask->GetLargestPossibleRegion().GetSize() << std::endl; std::cout << "hole pixels: " << mask->CountHolePixels() << std::endl; std::cout << "valid pixels: " << mask->CountValidPixels() << std::endl; // Setup the GUI system QApplication app( argc, argv ); // Without this, after we close the first dialog // (after the first iteration that is not accepted automatically), the event loop quits. app.setQuitOnLastWindowClosed(false); DummyPatchesDriver(image, mask, patchHalfWidth); return app.exec(); }
void Mask::CreateBoundaryImageInRegion(const itk::ImageRegion<2>& region, BoundaryImageType* const boundaryImage, const HoleMaskPixelTypeEnum& whichSideOfBoundary) const { // Create a binary image of the mask unsigned char holeColor = 255; unsigned char validColor = 0; UnsignedCharImageType::Pointer fullBinaryImage = UnsignedCharImageType::New(); CreateBinaryImageInRegion(region, fullBinaryImage, holeColor, validColor); // Extract the relevant region from the binary image UnsignedCharImageType::Pointer binaryImage = UnsignedCharImageType::New(); binaryImage->SetRegions(region); binaryImage->Allocate(); CopyRegion(fullBinaryImage.GetPointer(), binaryImage.GetPointer(), region, region); // Extract the relevant region from the mask Mask::Pointer extractedRegionMask = Mask::New(); extractedRegionMask->SetRegions(region); extractedRegionMask->Allocate(); CopyRegion(this, extractedRegionMask.GetPointer(), region, region); // Since the hole is white (we have specified this at the beginning of this function), // we want the foreground value of the contour filter to be black. // This means that the boundary will be detected in the black pixel region, // which is on the outside edge of the hole like we want. However, // The BinaryContourImageFilter will change all non-boundary pixels to the background color, // so the resulting output will be inverted - the boundary pixels will be black and the // non-boundary pixels will be white. // Find the boundary typedef itk::BinaryContourImageFilter<UnsignedCharImageType, UnsignedCharImageType> binaryContourImageFilterType; binaryContourImageFilterType::Pointer binaryContourFilter = binaryContourImageFilterType::New(); binaryContourFilter->SetInput(binaryImage); binaryContourFilter->SetFullyConnected(true); if(whichSideOfBoundary == HoleMaskPixelTypeEnum::VALID) { // we want the boundary pixels to be in the valid region. binaryContourFilter->SetForegroundValue(validColor); binaryContourFilter->SetBackgroundValue(holeColor); } else if(whichSideOfBoundary == HoleMaskPixelTypeEnum::HOLE) { // we want the boundary pixels to be in the hole region. binaryContourFilter->SetForegroundValue(holeColor); binaryContourFilter->SetBackgroundValue(validColor); } else { throw std::runtime_error("An invalid side of the boundary was requested."); } binaryContourFilter->Update(); DeepCopy(binaryContourFilter->GetOutput(), boundaryImage); }
void Vector() { typedef itk::Image<unsigned char, 2 > ChannelType; const unsigned int NumberOfChannels = 3; typedef itk::Image<itk::CovariantVector<unsigned char, NumberOfChannels>, 2 > ImageType; ImageType::Pointer image = ImageType::New(); itk::Index<2> corner = {{0,0}}; itk::Size<2> imageSize = {{500,500}}; itk::ImageRegion<2> fullRegion(corner, imageSize); image->SetRegions(fullRegion); image->Allocate(); for(unsigned int i = 0; i < NumberOfChannels; ++i) { itk::RandomImageSource<ChannelType>::Pointer randomImageSource = itk::RandomImageSource<ChannelType>::New(); randomImageSource->SetNumberOfThreads(1); // to produce non-random results randomImageSource->SetSize(imageSize); randomImageSource->Update(); ITKHelpers::SetChannel(image.GetPointer(), i, randomImageSource->GetOutput()); } itk::Size<2> patchSize = {{21,21}}; // There is nothing magic about these particular patches itk::Index<2> targetCorner = {{319, 302}}; itk::ImageRegion<2> targetRegion(targetCorner, patchSize); itk::Index<2> sourceCorner = {{341, 300}}; itk::ImageRegion<2> sourceRegion(sourceCorner, patchSize); Mask::Pointer mask = Mask::New(); mask->SetRegions(fullRegion); mask->Allocate(); ITKHelpers::SetImageToConstant(mask.GetPointer(), mask->GetValidValue()); typedef SumSquaredPixelDifference<ImageType::PixelType> PixelDifferenceType; typedef ImagePatchPixelDescriptor<ImageType> PatchType; ImagePatchDifference<PatchType, PixelDifferenceType> imagePatchDifference; PatchType targetPatch(image, mask, targetRegion); PatchType sourcePatch(image, mask, sourceRegion); float difference = imagePatchDifference(targetPatch, sourcePatch); std::cout << "GMHDifference: " << difference << std::endl; }
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 Mask::FindBoundary(UnsignedCharScalarImageType* boundaryImage) const { // Compute the "outer" boundary of the region to fill. That is, we want the boundary pixels to be in the source region. //HelpersOutput::WriteImageConditional<Mask>(this->CurrentMask, "Debug/FindBoundary.CurrentMask.mha", this->DebugImages); //HelpersOutput::WriteImageConditional<Mask>(this->CurrentMask, "Debug/FindBoundary.CurrentMask.png", this->DebugImages); // Create a binary image (throw away the "dont use" pixels) Mask::Pointer holeOnly = Mask::New(); holeOnly->DeepCopyFrom(this); itk::ImageRegionIterator<Mask> maskIterator(holeOnly, holeOnly->GetLargestPossibleRegion()); // This should result in a white hole on a black background while(!maskIterator.IsAtEnd()) { itk::Index<2> currentPixel = maskIterator.GetIndex(); if(!holeOnly->IsHole(currentPixel)) { holeOnly->SetPixel(currentPixel, holeOnly->GetValidValue()); } ++maskIterator; } //HelpersOutput::WriteImageConditional<Mask>(holeOnly, "Debug/FindBoundary.HoleOnly.mha", this->DebugImages); //HelpersOutput::WriteImageConditional<Mask>(holeOnly, "Debug/FindBoundary.HoleOnly.png", this->DebugImages); // Since the hole is white, we want the foreground value of the contour filter to be black. This means that the boundary will // be detected in the black pixel region, which is on the outside edge of the hole like we want. However, // The BinaryContourImageFilter will change all non-boundary pixels to the background color, so the resulting output will be inverted - // the boundary pixels will be black and the non-boundary pixels will be white. // Find the boundary typedef itk::BinaryContourImageFilter <Mask, Mask> binaryContourImageFilterType; binaryContourImageFilterType::Pointer binaryContourFilter = binaryContourImageFilterType::New(); binaryContourFilter->SetInput(holeOnly); binaryContourFilter->SetFullyConnected(true); binaryContourFilter->SetForegroundValue(holeOnly->GetValidValue()); binaryContourFilter->SetBackgroundValue(holeOnly->GetHoleValue()); binaryContourFilter->Update(); //HelpersOutput::WriteImageConditional<Mask>(binaryContourFilter->GetOutput(), "Debug/FindBoundary.Boundary.mha", this->DebugImages); //HelpersOutput::WriteImageConditional<Mask>(binaryContourFilter->GetOutput(), "Debug/FindBoundary.Boundary.png", this->DebugImages); // Since we want to interpret non-zero pixels as boundary pixels, we must invert the image. typedef itk::InvertIntensityImageFilter <Mask> InvertIntensityImageFilterType; InvertIntensityImageFilterType::Pointer invertIntensityFilter = InvertIntensityImageFilterType::New(); invertIntensityFilter->SetInput(binaryContourFilter->GetOutput()); invertIntensityFilter->SetMaximum(255); invertIntensityFilter->Update(); //this->BoundaryImage = binaryContourFilter->GetOutput(); //this->BoundaryImage->Graft(binaryContourFilter->GetOutput()); ITKHelpers::DeepCopy<UnsignedCharScalarImageType>(invertIntensityFilter->GetOutput(), boundaryImage); //HelpersOutput::WriteImageConditional<UnsignedCharScalarImageType>(this->BoundaryImage, "Debug/FindBoundary.BoundaryImage.mha", this->DebugImages); }
static void CreateMask(Mask::Pointer mask) { itk::Size<2> size; size.Fill(20); itk::Index<2> start; start.Fill(0); itk::ImageRegion<2> region(start,size); mask->SetRegions(region); mask->Allocate(); mask->FillBuffer(mask->GetValidValue()); itk::ImageRegionIterator<Mask> iterator(mask, mask->GetLargestPossibleRegion()); while(!iterator.IsAtEnd()) { if(iterator.GetIndex()[0] > 5 && iterator.GetIndex()[0] < 15 && iterator.GetIndex()[1] > 5 && iterator.GetIndex()[1] < 15) { mask->SetPixel(iterator.GetIndex(), mask->GetHoleValue()); } ++iterator; } }
int main(int argc, char*argv[]) { Mask::Pointer mask = Mask::New(); CreateMask(mask); OutputHelpers::WriteImage(mask.GetPointer(), "mask.png"); UnsignedCharScalarImageType::Pointer image = UnsignedCharScalarImageType::New(); CreateImage(image); OutputHelpers::WriteImage(image.GetPointer(), "image.png"); FloatScalarImageType::Pointer output = FloatScalarImageType::New(); MaskOperations::MaskedLaplacian(image.GetPointer(), mask.GetPointer(), output.GetPointer()); OutputHelpers::WriteImage(output.GetPointer(), "laplacian.mha"); return EXIT_SUCCESS; }
int main() { FloatVectorImageType::Pointer image = FloatVectorImageType::New(); Testing::GetBlankImage(image.GetPointer(), 4); Mask::Pointer mask = Mask::New(); Testing::GetFullyValidMask(mask.GetPointer()); unsigned int patchRadius = 5; PriorityDepth<FloatVectorImageType> priority(image, mask, patchRadius); itk::Index<2> filledPixel = {{0,0}}; priority.Update(filledPixel); itk::Index<2> queryPixel = {{0,0}}; priority.ComputePriority(queryPixel); return EXIT_SUCCESS; }
int main(int argc, char*argv[]) { if(argc != 2) { std::cerr << "Required arguments: mask" << std::endl; return EXIT_FAILURE; } std::string maskFilename = argv[1]; std::cout << "Reading mask: " << maskFilename << std::endl; Mask::Pointer mask = Mask::New(); mask->Read(maskFilename.c_str()); std::cout << "There are " << mask->CountBoundaryPixels() << " boundary pixels." << std::endl; return EXIT_SUCCESS; }
void Scalar() { typedef itk::Image< unsigned char, 2 > ImageType; itk::Size<2> imageSize = {{500,500}}; itk::RandomImageSource<ImageType>::Pointer randomImageSource = itk::RandomImageSource<ImageType>::New(); randomImageSource->SetNumberOfThreads(1); // to produce non-random results randomImageSource->SetSize(imageSize); randomImageSource->Update(); ImageType* image = randomImageSource->GetOutput(); itk::Size<2> patchSize = {{21,21}}; // There is nothing magic about these particular patches itk::Index<2> targetCorner = {{319, 302}}; itk::ImageRegion<2> targetRegion(targetCorner, patchSize); itk::Index<2> sourceCorner = {{341, 300}}; itk::ImageRegion<2> sourceRegion(sourceCorner, patchSize); Mask::Pointer mask = Mask::New(); mask->SetRegions(randomImageSource->GetOutput()->GetLargestPossibleRegion()); mask->Allocate(); ITKHelpers::SetImageToConstant(mask.GetPointer(), mask->GetValidValue()); typedef SumSquaredPixelDifference<ImageType::PixelType> PixelDifferenceType; typedef ImagePatchPixelDescriptor<ImageType> PatchType; ImagePatchDifference<PatchType, PixelDifferenceType> imagePatchDifference; PatchType targetPatch(image, mask, targetRegion); PatchType sourcePatch(image, mask, sourceRegion); float difference = imagePatchDifference(targetPatch, sourcePatch); std::cout << "Difference: " << difference << std::endl; }
int main(int argc, char *argv[]) { Mask::Pointer mask = Mask::New(); CreateMask(mask); itk::Index<2> queryPixel; queryPixel[0] = 5; queryPixel[1] = 5; FloatVector2Type direction; direction[0] = 1; direction[1] = 1; direction.Normalize(); itk::Index<2> pixelAcross = mask->FindPixelAcrossHole(queryPixel, direction); std::cout << "Pixel across: " << pixelAcross << std::endl; //HelpersOutput::WriteImage<Mask>(blurredLuminance, "Test/TestIsophotes.blurred.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 << "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 != 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 LidarSegmentationWidget::on_btnErodeSources_clicked() { Mask::Pointer sourcesImage = Mask::New(); sourcesImage->SetRegions(this->ImageRegion); ITKHelpers::IndicesToBinaryImage(this->Sources, sourcesImage); typedef itk::BinaryBallStructuringElement<Mask::PixelType,2> StructuringElementType; StructuringElementType structuringElementBig; structuringElementBig.SetRadius(3); structuringElementBig.CreateStructuringElement(); typedef itk::BinaryErodeImageFilter<Mask, Mask, StructuringElementType> BinaryErodeImageFilterType; BinaryErodeImageFilterType::Pointer erodeFilter = BinaryErodeImageFilterType::New(); erodeFilter->SetInput(sourcesImage); erodeFilter->SetKernel(structuringElementBig); erodeFilter->Update(); //this->Sources.clear(); this->Sources = ITKHelpers::GetNonZeroPixels(erodeFilter->GetOutput()); UpdateSelections(); }
int main() { typedef itk::Image<itk::CovariantVector<float, 3>, 2> ImageType; ImageType::Pointer image = ImageType::New(); Testing::GetBlankImage(image.GetPointer(), 4); Mask::Pointer mask = Mask::New(); Testing::GetFullyValidMask(mask.GetPointer()); vtkSmartPointer<vtkStructuredGrid> structuredGrid = vtkSmartPointer<vtkStructuredGrid>::New(); unsigned int patchRadius = 5; PriorityCurvature<itk::Index<2> > priority(structuredGrid, patchRadius); itk::Index<2> filledPixel = {{0,0}}; itk::Index<2> sourcePixel = {{0,0}}; priority.Update(sourcePixel, filledPixel); itk::Index<2> queryPixel = {{0,0}}; priority.ComputePriority(queryPixel); return EXIT_SUCCESS; }
//BasicViewerWidget<TImage>::BasicViewerWidget(TImage* const image, Mask* const mask) : BasicViewerWidget<TImage>::BasicViewerWidget(typename TImage::Pointer image, Mask::Pointer mask) : Image(image), MaskImage(mask) { qRegisterMetaType<itk::ImageRegion<2> >("itkImageRegion"); this->setupUi(this); int dims[3]; this->ImageLayer.ImageData->GetDimensions(dims); typename TImage::Pointer tempImage = TImage::New(); ITKHelpers::DeepCopy(image.GetPointer(), tempImage.GetPointer()); typename TImage::PixelType zeroPixel(tempImage->GetNumberOfComponentsPerPixel()); zeroPixel = itk::NumericTraits<typename TImage::PixelType>::ZeroValue(zeroPixel); mask->ApplyToImage(tempImage.GetPointer(), zeroPixel); ITKVTKHelpers::ITKVectorImageToVTKImageFromDimension(tempImage.GetPointer(), this->ImageLayer.ImageData); // if(chkScaleImage->isChecked()) // { // VTKHelpers::ScaleImage(this->ImageLayer.ImageData); // } this->ImageDimension[0] = dims[0]; this->ImageDimension[1] = dims[1]; this->ImageDimension[2] = dims[2]; SetupScenes(); // this->InteractorStyle = vtkSmartPointer<InteractorStyleImageWithDrag>::New(); this->InteractorStyle = vtkSmartPointer<vtkInteractorStyleImage>::New(); this->Renderer = vtkSmartPointer<vtkRenderer>::New(); this->qvtkWidget->GetRenderWindow()->AddRenderer(this->Renderer); this->Renderer->AddViewProp(ImageLayer.ImageSlice); this->InteractorStyle->SetCurrentRenderer(this->Renderer); this->qvtkWidget->GetRenderWindow()->GetInteractor()->SetInteractorStyle(this->InteractorStyle); // this->InteractorStyle->Init(); // this->Camera = new ImageCamera(this->Renderer); this->ItkVtkCamera = new ITKVTKCamera(this->InteractorStyle, this->Renderer, this->qvtkWidget->GetRenderWindow()); this->ItkVtkCamera->SetCameraPositionPNG(); }
int main(int argc, char* argv[]) { // Verify arguments if(argc < 5) { std::cout << "Usage: PatchImage repeatX repeatY outputImage" << std::endl; return EXIT_FAILURE; } // Parse arguments std::string patchImageFilename = argv[1]; std::stringstream ssRepeatX; ssRepeatX << argv[2]; unsigned int repeatX = 0; ssRepeatX >> repeatX; std::stringstream ssRepeatY; ssRepeatY << argv[3]; unsigned int repeatY = 0; ssRepeatY >> repeatY; std::string outputFilename = argv[4]; // Output arguments std::cout << "Patch image: " << patchImageFilename << std::endl << "Repeat X: " << repeatX << std::endl << "Repeat Y: " << repeatY << std::endl << "Output image: " << outputFilename << std::endl; //typedef itk::VectorImage<float, 2> ImageType; typedef itk::Image<itk::CovariantVector<float, 3>, 2> ImageType; // Read patch image typedef itk::ImageFileReader<ImageType> ImageReaderType; ImageReaderType::Pointer patchImageReader = ImageReaderType::New(); patchImageReader->SetFileName(patchImageFilename); patchImageReader->Update(); Mask::Pointer mask = Mask::New(); itk::ImageRegion<2> patchRegion = patchImageReader->GetOutput()->GetLargestPossibleRegion(); mask->SetRegions(patchRegion); mask->Allocate(); itk::Index<2> holeCorner = {{1,1}}; itk::Size<2> holeSize = patchRegion.GetSize(); holeSize[0] -= 2; // Missing one row on the top, and one row on the bottom holeSize[1] -= 2; // Missing one column on the left, and one column on the right itk::ImageRegion<2> holeRegion(holeCorner, holeSize); mask->SetValid(patchRegion); mask->SetHole(holeRegion); ImageType::Pointer seamlessPatch = ImageType::New(); ITKHelpers::DeepCopy(patchImageReader->GetOutput(), seamlessPatch.GetPointer()); // Enforce periodic boundary conditions // Top and bottom for(int i = 0; i < static_cast<int>(patchRegion.GetSize()[1]); ++i) { itk::Index<2> topPixelIndex = {{0, i}}; itk::Index<2> bottomPixelIndex = {{static_cast<int>(patchRegion.GetSize()[0])-1, i}}; ImageType::PixelType topPixelValue = seamlessPatch->GetPixel(topPixelIndex); ImageType::PixelType bottomPixelValue = seamlessPatch->GetPixel(bottomPixelIndex); ImageType::PixelType averageValue = (topPixelValue + bottomPixelValue)/2.0f; seamlessPatch->SetPixel(topPixelIndex, averageValue); seamlessPatch->SetPixel(bottomPixelIndex, averageValue); } // Left and right for(int i = 0; i < static_cast<int>(patchRegion.GetSize()[0]); ++i) { itk::Index<2> leftPixelIndex = {{i, 0}}; itk::Index<2> rightPixelIndex = {{i, static_cast<int>(patchRegion.GetSize()[1])-1}}; ImageType::PixelType leftPixelValue = seamlessPatch->GetPixel(leftPixelIndex); ImageType::PixelType rightPixelValue = seamlessPatch->GetPixel(rightPixelIndex); ImageType::PixelType averageValue = (leftPixelValue + rightPixelValue)/2.0f; seamlessPatch->SetPixel(leftPixelIndex, averageValue); seamlessPatch->SetPixel(rightPixelIndex, averageValue); } typedef PoissonEditingParent::GuidanceFieldType GuidanceFieldType; std::vector<GuidanceFieldType::Pointer> guidanceFields = PoissonEditingParent::ComputeGuidanceField(patchImageReader->GetOutput()); ImageType::Pointer output = ImageType::New(); FillImage(seamlessPatch.GetPointer(), mask.GetPointer(), guidanceFields, output.GetPointer(), patchRegion, seamlessPatch.GetPointer()); // Write output ITKHelpers::WriteRGBImage(output.GetPointer(), outputFilename); // Original tiled ImageType::Pointer originalTiled = ImageType::New(); TilePatch(patchImageReader->GetOutput(), repeatX, repeatY, originalTiled.GetPointer()); ITKHelpers::WriteRGBImage(originalTiled.GetPointer(), "original_tiled.png"); // Seamless tiled ImageType::Pointer seamlessTiled = ImageType::New(); TilePatch(output.GetPointer(), repeatX, repeatY, seamlessTiled.GetPointer()); ITKHelpers::WriteRGBImage(seamlessTiled.GetPointer(), "seamless_tiled.png"); return EXIT_SUCCESS; }
int main(int 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.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; }
// 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[]) { // 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; }
void TestComputeMaskedImage1DHistogram() { // // Single channel // { // typedef itk::Image<unsigned char, 2> ImageType; // ImageType::Pointer image = ImageType::New(); // ImageType::IndexType corner = {{0,0}}; // ImageType::SizeType size = {{100,100}}; // ImageType::RegionType region(corner, size); // image->SetRegions(region); // image->Allocate(); // itk::ImageRegionIterator<ImageType> imageIterator(image,region); // while(!imageIterator.IsAtEnd()) // { // if(imageIterator.GetIndex()[0] < 70) // { // imageIterator.Set(255); // } // else // { // imageIterator.Set(0); // } // ++imageIterator; // } // ImageType::PixelType rangeMin = 0; // ImageType::PixelType rangeMax = 255; // unsigned int numberOfBins = 10; // typedef int BinValueType; // typedef Histogram<BinValueType>::HistogramType HistogramType; // HistogramType histogram = Histogram<BinValueType>::ComputeImageHistogram1D(image.GetPointer(), // image->GetLargestPossibleRegion(), // numberOfBins, rangeMin, rangeMax); // Histogram<BinValueType>::OutputHistogram(histogram); // std::cout << std::endl; // } // Multi channel VectorImage { typedef itk::VectorImage<unsigned char, 2> ImageType; ImageType::Pointer image = ImageType::New(); ImageType::IndexType corner = {{0,0}}; ImageType::SizeType size = {{100,100}}; ImageType::RegionType region(corner, size); image->SetRegions(region); image->SetNumberOfComponentsPerPixel(3); image->Allocate(); Mask::Pointer mask = Mask::New(); mask->SetRegions(region); mask->Allocate(); itk::ImageRegionIterator<ImageType> imageIterator(image,region); while(!imageIterator.IsAtEnd()) { ImageType::PixelType pixel(image->GetNumberOfComponentsPerPixel()); if(imageIterator.GetIndex()[0] < 70) { for(unsigned int i = 0; i < pixel.GetSize(); ++i) { pixel[i] = 255; } } else { for(unsigned int i = 0; i < pixel.GetSize(); ++i) { pixel[i] = 0; } } imageIterator.Set(pixel); ++imageIterator; } // TypeTraits<ImageType::PixelType>::ComponentType rangeMin = 0; // TypeTraits<ImageType::PixelType>::ComponentType rangeMax = 255; ImageType::PixelType rangeMins; rangeMins.SetSize(image->GetNumberOfComponentsPerPixel()); rangeMins.Fill(0); ImageType::PixelType rangeMaxs; rangeMaxs.SetSize(image->GetNumberOfComponentsPerPixel()); rangeMaxs.Fill(255); unsigned int numberOfBinsPerComponent = 10; typedef int BinValueType; itk::ImageRegion<2> imageRegion = image->GetLargestPossibleRegion(); itk::ImageRegion<2> maskRegion = image->GetLargestPossibleRegion(); typedef MaskedHistogramGenerator<BinValueType> HistogramGeneratorType; typedef HistogramGeneratorType::HistogramType HistogramType; bool allowOutside = false; HistogramType histogram = HistogramGeneratorType::ComputeMaskedImage1DHistogram(image.GetPointer(), imageRegion, mask.GetPointer(), maskRegion, numberOfBinsPerComponent, rangeMins, rangeMaxs, allowOutside, HoleMaskPixelTypeEnum::VALID); histogram.Print(); std::cout << std::endl; } // // Multi channel Image<CovariantVector> // { // typedef itk::Image<itk::CovariantVector<unsigned char, 3>, 2> ImageType; // ImageType::Pointer image = ImageType::New(); // ImageType::IndexType corner = {{0,0}}; // ImageType::SizeType size = {{100,100}}; // ImageType::RegionType region(corner, size); // image->SetRegions(region); // image->Allocate(); // itk::ImageRegionIterator<ImageType> imageIterator(image,region); // while(!imageIterator.IsAtEnd()) // { // ImageType::PixelType pixel(image->GetNumberOfComponentsPerPixel()); // if(imageIterator.GetIndex()[0] < 70) // { // for(unsigned int i = 0; i < pixel.GetNumberOfComponents(); ++i) // { // pixel[i] = 255; // } // } // else // { // for(unsigned int i = 0; i < pixel.GetNumberOfComponents(); ++i) // { // pixel[i] = 0; // } // } // imageIterator.Set(pixel); // ++imageIterator; // } // TypeTraits<ImageType::PixelType>::ComponentType rangeMin = 0; // TypeTraits<ImageType::PixelType>::ComponentType rangeMax = 255; // unsigned int numberOfBinsPerComponent = 10; // typedef int BinValueType; // Histogram<BinValueType>::HistogramType histogram = Histogram<BinValueType>::ComputeImageHistogram1D(image.GetPointer(), // image->GetLargestPossibleRegion(), // numberOfBinsPerComponent, rangeMin, rangeMax); // Histogram<BinValueType>::OutputHistogram(histogram); // std::cout << std::endl; // } }
// 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; }