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