void Cell::ComputeMaskedImage() { typedef itk::MaskNegatedImageFilter< ImageType, MaskImageType, ImageType > MaskFilterType; MaskFilterType::Pointer maskFilter = MaskFilterType::New(); maskFilter->SetMaskImage(this->mask); maskFilter->SetInput(this->image); try { //ftk::TimeStampOverflowSafeUpdate( maskFilter.GetPointer() ); maskFilter->Update(); } catch (itk::ExceptionObject &err) { std::cerr << "maskFilter Exception: " << err << std::endl; } this->masked_image = maskFilter->GetOutput(); this->masked_image->DisconnectPipeline(); //Disconnect pipeline so we don't propagate... //Make the file name of the masked cell image std::stringstream masked_cell_filename_stream; masked_cell_filename_stream << cell_x << "_" << cell_y << "_" << cell_z << "_masked.TIF"; //X_Y_Z_masked.TIF //Write the masked cell image //WriteImage(masked_cell_filename_stream.str(), this->masked_image); }
void CriminisiInpainting::ComputeBoundaryNormals() { try { // Blur the mask, compute the gradient, then keep the normals only at the original mask boundary if(this->DebugImages) { Helpers::WriteImage<UnsignedCharScalarImageType>(this->BoundaryImage, "Debug/ComputeBoundaryNormals.BoundaryImage.mha"); Helpers::WriteImage<Mask>(this->CurrentMask, "Debug/ComputeBoundaryNormals.CurrentMask.mha"); } // Blur the mask typedef itk::DiscreteGaussianImageFilter< Mask, FloatScalarImageType > BlurFilterType; BlurFilterType::Pointer gaussianFilter = BlurFilterType::New(); gaussianFilter->SetInput(this->CurrentMask); gaussianFilter->SetVariance(2); gaussianFilter->Update(); if(this->DebugImages) { Helpers::WriteImage<FloatScalarImageType>(gaussianFilter->GetOutput(), "Debug/ComputeBoundaryNormals.BlurredMask.mha"); } // Compute the gradient of the blurred mask typedef itk::GradientImageFilter< FloatScalarImageType, float, float> GradientFilterType; GradientFilterType::Pointer gradientFilter = GradientFilterType::New(); gradientFilter->SetInput(gaussianFilter->GetOutput()); gradientFilter->Update(); if(this->DebugImages) { Helpers::WriteImage<FloatVector2ImageType>(gradientFilter->GetOutput(), "Debug/ComputeBoundaryNormals.BlurredMaskGradient.mha"); } // Only keep the normals at the boundary typedef itk::MaskImageFilter< FloatVector2ImageType, UnsignedCharScalarImageType, FloatVector2ImageType > MaskFilterType; MaskFilterType::Pointer maskFilter = MaskFilterType::New(); //maskFilter->SetInput1(gradientFilter->GetOutput()); //maskFilter->SetInput2(this->BoundaryImage); maskFilter->SetInput(gradientFilter->GetOutput()); maskFilter->SetMaskImage(this->BoundaryImage); maskFilter->Update(); if(this->DebugImages) { Helpers::WriteImage<FloatVector2ImageType>(maskFilter->GetOutput(), "Debug/ComputeBoundaryNormals.BoundaryNormalsUnnormalized.mha"); } //this->BoundaryNormals = maskFilter->GetOutput(); //this->BoundaryNormals->Graft(maskFilter->GetOutput()); Helpers::DeepCopy<FloatVector2ImageType>(maskFilter->GetOutput(), this->BoundaryNormals); // Normalize the vectors because we just care about their direction (the Data term computation calls for the normalized boundary normal) itk::ImageRegionIterator<FloatVector2ImageType> boundaryNormalsIterator(this->BoundaryNormals, this->BoundaryNormals->GetLargestPossibleRegion()); itk::ImageRegionConstIterator<UnsignedCharScalarImageType> boundaryIterator(this->BoundaryImage, this->BoundaryImage->GetLargestPossibleRegion()); while(!boundaryNormalsIterator.IsAtEnd()) { if(boundaryIterator.Get()) // The pixel is on the boundary { FloatVector2ImageType::PixelType p = boundaryNormalsIterator.Get(); p.Normalize(); boundaryNormalsIterator.Set(p); } ++boundaryNormalsIterator; ++boundaryIterator; } if(this->DebugImages) { Helpers::WriteImage<FloatVector2ImageType>(this->BoundaryNormals, "Debug/ComputeBoundaryNormals.BoundaryNormals.mha"); } } catch( itk::ExceptionObject & err ) { std::cerr << "ExceptionObject caught in ComputeBoundaryNormals!" << std::endl; std::cerr << err << std::endl; exit(-1); } }
void CriminisiInpainting::ComputeIsophotes() { try { Helpers::DebugWriteImageConditional<FloatVectorImageType>(this->CurrentImage, "Debug/ComputeIsophotes.input.mha", this->DebugImages); /* // This only works when the image is RGB typedef itk::VectorMagnitudeImageFilter<FloatVectorImageType, UnsignedCharScalarImageType> VectorMagnitudeFilterType; VectorMagnitudeFilterType::Pointer magnitudeFilter = VectorMagnitudeFilterType::New(); magnitudeFilter->SetInput(this->OriginalImage); // We use the original image here because the image that has been painted green inside the hole has a strong gradient around the hole. magnitudeFilter->Update(); */ RGBImageType::Pointer rgbImage = RGBImageType::New(); Helpers::VectorImageToRGBImage(this->OriginalImage, rgbImage); Helpers::DebugWriteImageConditional<RGBImageType>(rgbImage, "Debug/ComputeIsophotes.rgb.mha", this->DebugImages); typedef itk::RGBToLuminanceImageFilter< RGBImageType, FloatScalarImageType > LuminanceFilterType; LuminanceFilterType::Pointer luminanceFilter = LuminanceFilterType::New(); luminanceFilter->SetInput(rgbImage); luminanceFilter->Update(); Helpers::DebugWriteImageConditional<FloatScalarImageType>(luminanceFilter->GetOutput(), "Debug/ComputeIsophotes.luminance.mha", this->DebugImages); // Blur the image to compute better gradient estimates typedef itk::DiscreteGaussianImageFilter<FloatScalarImageType, FloatScalarImageType > BlurFilterType; BlurFilterType::Pointer blurFilter = BlurFilterType::New(); blurFilter->SetInput(luminanceFilter->GetOutput()); blurFilter->SetVariance(2); blurFilter->Update(); Helpers::DebugWriteImageConditional<FloatScalarImageType>(blurFilter->GetOutput(), "Debug/ComputeIsophotes.blurred.mha", true); // Compute the gradient // Template parameters are <TInputImage, TOperatorValueType, TOutputValueType> typedef itk::GradientImageFilter<FloatScalarImageType, float, float> GradientFilterType; GradientFilterType::Pointer gradientFilter = GradientFilterType::New(); gradientFilter->SetInput(blurFilter->GetOutput()); gradientFilter->Update(); Helpers::DebugWriteImageConditional<FloatVector2ImageType>(gradientFilter->GetOutput(), "Debug/ComputeIsophotes.gradient.mha", this->DebugImages); // Rotate the gradient 90 degrees to obtain isophotes from gradient typedef itk::UnaryFunctorImageFilter<FloatVector2ImageType, FloatVector2ImageType, RotateVectors< FloatVector2ImageType::PixelType, FloatVector2ImageType::PixelType> > FilterType; FilterType::Pointer rotateFilter = FilterType::New(); rotateFilter->SetInput(gradientFilter->GetOutput()); rotateFilter->Update(); Helpers::DebugWriteImageConditional<FloatVector2ImageType>(rotateFilter->GetOutput(), "Debug/ComputeIsophotes.rotatedGradient.mha", this->DebugImages); // Mask the isophote image with the expanded version of the inpainting mask. // That is, keep only the values outside of the expanded mask. To do this, we have to first invert the mask. // Invert the mask typedef itk::InvertIntensityImageFilter <Mask> InvertIntensityImageFilterType; InvertIntensityImageFilterType::Pointer invertMaskFilter = InvertIntensityImageFilterType::New(); invertMaskFilter->SetInput(this->CurrentMask); invertMaskFilter->Update(); if(this->DebugImages) { Helpers::WriteImage<Mask>(invertMaskFilter->GetOutput(), "Debug/ComputeIsophotes.invertedMask.mha"); } //std::cout << "rotateFilter: " << rotateFilter->GetOutput()->GetLargestPossibleRegion() << std::endl; //std::cout << "invertMaskFilter: " << invertMaskFilter->GetOutput()->GetLargestPossibleRegion() << std::endl; // Keep only values outside the masked region typedef itk::MaskImageFilter< FloatVector2ImageType, Mask, FloatVector2ImageType > MaskFilterType; MaskFilterType::Pointer maskFilter = MaskFilterType::New(); maskFilter->SetInput1(rotateFilter->GetOutput()); maskFilter->SetInput2(invertMaskFilter->GetOutput()); maskFilter->Update(); if(this->DebugImages) { Helpers::WriteImage<FloatVector2ImageType>(maskFilter->GetOutput(), "Debug/ComputeIsophotes.maskedIsophotes.mha"); } Helpers::DeepCopy<FloatVector2ImageType>(maskFilter->GetOutput(), this->IsophoteImage); } catch( itk::ExceptionObject & err ) { std::cerr << "ExceptionObject caught in ComputeIsophotes!" << std::endl; std::cerr << err << std::endl; exit(-1); } }
int exampleProcessImageFilter::update() { typedef unsigned short PixelType; const unsigned int Dimension = 3; typedef itk::Image< PixelType, Dimension > ImageType; qDebug() << d->inputA->identifier(); if (d->option == optionA) { if (d->inputA->identifier()=="itkDataImageUShort3" && d->inputB->identifier()=="itkDataImageUShort3") { typedef itk::MaskImageFilter< ImageType,ImageType,ImageType > MaskFilterType; MaskFilterType::Pointer maskFilter = MaskFilterType::New(); //convert from dtkImages to ItkImages and set as intputs for the itk::MaskImageFilter maskFilter->SetInput1(dynamic_cast<ImageType*>((itk::Object*)(d->inputA->output()))); maskFilter->SetInput2(dynamic_cast<ImageType*>((itk::Object*)(d->inputB->output()))); //Create an image where the output of the filter is going to be displayed d->output =dynamic_cast<medAbstractDataImage *>(dtkAbstractDataFactory::instance()->create ("itkDataImageUShort3")); maskFilter->Update(); //Set the data for the output d->output->setData(maskFilter->GetOutput()); } else if(d->inputA->identifier()=="itkDataImageDouble4" && d->inputB->identifier()=="itkDataImageDouble4") { typedef double PixelType4; const unsigned int Dimension4 = 4; typedef itk::Image< PixelType4, Dimension4 > ImageType4; typedef itk::MaskImageFilter< ImageType4,ImageType4,ImageType4 > MaskFilterType4; MaskFilterType4::Pointer maskFilter4 = MaskFilterType4::New(); //convert from dtkImages to ItkImages and set as intputs for the itk::MaskImageFilter maskFilter4->SetInput1(dynamic_cast<ImageType4*>((itk::Object*)(d->inputA->output()))); maskFilter4->SetInput2(dynamic_cast<ImageType4*>((itk::Object*)(d->inputB->output()))); maskFilter4->Update(); //Create an image where the output of the filter is going to be displayed d->output =dynamic_cast<medAbstractDataImage *> (dtkAbstractDataFactory::instance()->create ("itkDataImageDouble4")); //Set the data for the output d->output->setData(maskFilter4->GetOutput()); typedef itk::ImageFileWriter< ImageType4 > WriterType; WriterType::Pointer writer = WriterType::New(); writer->SetFileName("/user/jgarciag/home/AnalyzeStuff/headerModify/ResulHalfMask4D.mha"); writer->SetInput(/*dynamic_cast<ImageType4*>((itk::Object*)(d->output->output()))*/maskFilter4->GetOutput()); writer->Update(); } else qDebug("Not the right itkDataImageUShort3 type of images"); } else if (d->option == optionB) { if (d->inputA->identifier()=="itkDataImageUShort3" && d->inputB->identifier()=="itkDataImageUShort3") { typedef itk::AddImageFilter< ImageType,ImageType,ImageType > AddFilterType; AddFilterType::Pointer AddFilter = AddFilterType::New(); AddFilter->SetInput1(dynamic_cast<ImageType*>((itk::Object*)(d->inputA->output()))); AddFilter->SetInput2(dynamic_cast<ImageType*>((itk::Object*)(d->inputB->output()))); d->output =dynamic_cast<medAbstractDataImage *> (dtkAbstractDataFactory::instance()->create ("itkDataImageUShort3")); AddFilter->Update(); d->output->setData(AddFilter->GetOutput()); } else qDebug("Not the right itkDataImageUShort3 type of images"); } else if (d->option == optionC) { if (d->inputA->identifier()=="itkDataImageUShort3" && d->inputB->identifier()=="itkDataImageUShort3") { typedef itk::ConnectedThresholdImageFilter< ImageType, ImageType > ConnectedFilterType; ConnectedFilterType::Pointer connectedThreshold = ConnectedFilterType::New(); connectedThreshold->SetInput( dynamic_cast<ImageType*>((itk::Object*)(d->inputA->output())) ); connectedThreshold->SetLower((d->lowerThreshold)); connectedThreshold->SetUpper((d->lowerThreshold)+150); ImageType::IndexType index; index[0] = d->x; index[1] = d->y; index[2] = d->z; connectedThreshold->SetSeed( index ); connectedThreshold->Update(); d->output =dynamic_cast<medAbstractDataImage *> (dtkAbstractDataFactory::instance()->create ("itkDataImageUShort3")); d->output->setData(connectedThreshold->GetOutput()); } else qDebug("Not the right itkDataImageUShort3 type of image"); } // emit progressed (100); qDebug("Adios"); return 0; }
int main(int argc, char *argv[]) { if(argc != 3) { std::cerr << "Required arguments: image mask" << std::endl; return EXIT_FAILURE; } std::string imageFilename = argv[1]; std::string maskFilename = argv[2]; std::cout << "Reading image: " << imageFilename << std::endl; std::cout << "Reading mask: " << maskFilename << std::endl; typedef itk::ImageFileReader<FloatVectorImageType> ImageReaderType; ImageReaderType::Pointer imageReader = ImageReaderType::New(); imageReader->SetFileName(imageFilename.c_str()); imageReader->Update(); std::cout << "Read image " << imageReader->GetOutput()->GetLargestPossibleRegion() << std::endl; typedef itk::ImageFileReader<Mask> MaskReaderType; MaskReaderType::Pointer maskReader = MaskReaderType::New(); maskReader->SetFileName(maskFilename.c_str()); maskReader->Update(); std::cout << "Read mask " << maskReader->GetOutput()->GetLargestPossibleRegion() << std::endl; // Prepare image RGBImageType::Pointer rgbImage = RGBImageType::New(); // 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; }
void MaskNewGradientWithOriginalMask(std::string imageFilename, std::string maskFilename) { // Read image and convert it to grayscale ColorImageReaderType::Pointer imageReader = ColorImageReaderType::New(); imageReader->SetFileName(imageFilename); imageReader->Update(); UnsignedCharImageType::Pointer image = UnsignedCharImageType::New(); ColorToGrayscale<ColorImageType>(imageReader->GetOutput(), image); // Read mask image UnsignedCharImageReaderType::Pointer maskReader = UnsignedCharImageReaderType::New(); maskReader->SetFileName(maskFilename.c_str()); maskReader->Update(); // Blur the image to compute better gradient estimates typedef itk::DiscreteGaussianImageFilter< UnsignedCharImageType, FloatImageType > filterType; // Create and setup a Gaussian filter filterType::Pointer gaussianFilter = filterType::New(); gaussianFilter->SetInput(image); gaussianFilter->SetVariance(2); gaussianFilter->Update(); //WriteImage<FloatImageType>(gaussianFilter->GetOutput(), "gaussianBlur.mhd"); // this cannot be png because they are floats /* // Compute the gradient typedef itk::GradientImageFilter< FloatImageType, float, float> GradientFilterType; GradientFilterType::Pointer gradientFilter = GradientFilterType::New(); gradientFilter->SetInput(gaussianFilter->GetOutput()); gradientFilter->Update(); WriteImage<VectorImageType>(gradientFilter->GetOutput(), "gradient.mhd"); // this cannot be png because they are floats */ // Compute the gradient magnitude typedef itk::GradientMagnitudeImageFilter< FloatImageType, UnsignedCharImageType> GradientMagnitudeFilterType; GradientMagnitudeFilterType::Pointer gradientMagnitudeFilter = GradientMagnitudeFilterType::New(); gradientMagnitudeFilter->SetInput(gaussianFilter->GetOutput()); gradientMagnitudeFilter->Update(); WriteImage<UnsignedCharImageType>(gradientMagnitudeFilter->GetOutput(), "gradient.png"); // Expand the mask - this is necessary to prevent the isophotes from being undefined in the target region typedef itk::FlatStructuringElement<2> StructuringElementType; StructuringElementType::RadiusType radius; radius.Fill(5); StructuringElementType structuringElement = StructuringElementType::Box(radius); typedef itk::BinaryDilateImageFilter<UnsignedCharImageType, UnsignedCharImageType, StructuringElementType> BinaryDilateImageFilterType; BinaryDilateImageFilterType::Pointer expandMaskFilter = BinaryDilateImageFilterType::New(); expandMaskFilter->SetInput(maskReader->GetOutput()); expandMaskFilter->SetKernel(structuringElement); expandMaskFilter->Update(); UnsignedCharImageType::Pointer expandedMask = UnsignedCharImageType::New(); expandedMask->Graft(expandMaskFilter->GetOutput()); WriteScaledImage<UnsignedCharImageType>(expandedMask, "ExpandedMasked.png"); // Invert the mask typedef itk::InvertIntensityImageFilter <UnsignedCharImageType> InvertIntensityImageFilterType; InvertIntensityImageFilterType::Pointer invertMaskFilter = InvertIntensityImageFilterType::New(); invertMaskFilter->SetInput(expandedMask); invertMaskFilter->Update(); //WriteScaledImage<UnsignedCharImageType>(invertMaskFilter->GetOutput(), "invertedExpandedMask.mhd"); // Keep only values outside the masked region typedef itk::MaskImageFilter< UnsignedCharImageType, UnsignedCharImageType, UnsignedCharImageType > MaskFilterType; MaskFilterType::Pointer maskFilter = MaskFilterType::New(); maskFilter->SetInput(gradientMagnitudeFilter->GetOutput()); maskFilter->SetMaskImage(invertMaskFilter->GetOutput()); maskFilter->Update(); WriteScaledImage<UnsignedCharImageType>(maskFilter->GetOutput(), "MaskedGradientMagnitude.png"); }
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; }