void CriminisiInpainting::ExpandMask() { // 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(2); // Just a little bit of expansion //radius.Fill(this->PatchRadius[0]); // This was working, but huge expansion //radius.Fill(2.0* this->PatchRadius[0]); StructuringElementType structuringElement = StructuringElementType::Box(radius); typedef itk::BinaryDilateImageFilter<Mask, Mask, StructuringElementType> BinaryDilateImageFilterType; BinaryDilateImageFilterType::Pointer expandMaskFilter = BinaryDilateImageFilterType::New(); expandMaskFilter->SetInput(this->CurrentMask); expandMaskFilter->SetKernel(structuringElement); expandMaskFilter->Update(); if(this->DebugImages) { Helpers::WriteImage<Mask>(expandMaskFilter->GetOutput(), "Debug/ExpandMask.expandedMask.mha"); } //Helpers::DeepCopy<Mask>(expandMaskFilter->GetOutput(), this->CurrentMask); this->CurrentMask->DeepCopyFrom(expandMaskFilter->GetOutput()); //WriteScaledImage<Mask>(this->Mask, "expandedMask.mhd"); #if defined(INTERACTIVE) emit RefreshSignal(); #endif }
void Mask::ExpandHole(const unsigned int kernelRadius) { UnsignedCharImageType::Pointer binaryHoleImage = UnsignedCharImageType::New(); this->CreateBinaryImage(binaryHoleImage, 255, 0); // std::cout << "binaryHoleImage: " << std::endl; // ITKHelpers::PrintImage(binaryHoleImage.GetPointer()); typedef itk::FlatStructuringElement<2> StructuringElementType; StructuringElementType::RadiusType radius; radius.Fill(kernelRadius); // This is correct that the RadiusType expects the region radius, not the side length. StructuringElementType structuringElement = StructuringElementType::Box(radius); typedef itk::BinaryDilateImageFilter<UnsignedCharImageType, UnsignedCharImageType, StructuringElementType> BinaryDilateImageFilterType; BinaryDilateImageFilterType::Pointer dilateFilter = BinaryDilateImageFilterType::New(); dilateFilter->SetInput(binaryHoleImage); dilateFilter->SetKernel(structuringElement); dilateFilter->Update(); // std::cout << "dilateFilter output: " << std::endl; // ITKHelpers::PrintImage(dilateFilter->GetOutput()); // There will now be more hole pixels than there were previously. Copy them into the mask. this->CreateHolesFromValue(dilateFilter->GetOutput(), 255); }
void Mask::ExpandHole() { // 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(2); // Just a little bit of expansion //radius.Fill(this->PatchRadius[0]); // This was working, but huge expansion //radius.Fill(2.0* this->PatchRadius[0]); StructuringElementType structuringElement = StructuringElementType::Box(radius); typedef itk::BinaryDilateImageFilter<Mask, Mask, StructuringElementType> BinaryDilateImageFilterType; BinaryDilateImageFilterType::Pointer expandMaskFilter = BinaryDilateImageFilterType::New(); expandMaskFilter->SetInput(this); expandMaskFilter->SetKernel(structuringElement); expandMaskFilter->Update(); this->DeepCopyFrom(expandMaskFilter->GetOutput()); }
void myVtkInteractorStyleImage3D::RemoveLeaks(){ boost::mutex::scoped_lock scoped_lock(_canSegment_mutex); if (!_foundLeaks){ cout << "Final segmentation had no leaks!" << endl; vtkSmartPointer<vtkNIFTIImageWriter> niw = vtkSmartPointer<vtkNIFTIImageWriter>::New(); vtkStructuredPoints* saveMat = vtkStructuredPoints::New(); cout << "At filtering." << endl; saveMat->DeepCopy(_selection); vtkUnsignedShortArray* scalars = (vtkUnsignedShortArray*)(saveMat->GetPointData()->GetScalars()); for (int i = 0; i < saveMat->GetNumberOfPoints(); i++){ if (scalars->GetValue(i) == BACKGROUND){ scalars->SetValue(i, NOT_ACTIVE); } } scalars->Modified(); //dilate: cout << "at dilation" << endl; vtkSmartPointer<vtkImageDilateErode3D> dilateErode = vtkSmartPointer<vtkImageDilateErode3D>::New(); dilateErode->SetInputData(saveMat); dilateErode->SetDilateValue(FOREGROUND); dilateErode->SetErodeValue(NOT_ACTIVE); dilateErode->SetKernelSize(DILATION_ST_SIZE, DILATION_ST_SIZE, 1); dilateErode->ReleaseDataFlagOff(); dilateErode->Update(); cout << "finished dilation" << endl; cout << "Saving..." << endl; niw->SetInputData(dilateErode->GetOutput()); niw->SetFileName("correctedImage.nii.gz"); niw->Write(); cout << "Final segmentation was saved successfully!" << endl; return; } cout << "Started fixing mesh!" << endl; typedef double PixelType; typedef unsigned short SegPixelType; const unsigned char dim = 3; typedef itk::Image<PixelType, dim> ImageType; typedef itk::Image<SegPixelType, dim> SegImageType; MeshLeaksCorrector mlc; ImageType::Pointer inputImage = mlc.read3DImage<ImageType>(_inputName.c_str()); cout << "Image reading done." << endl; typedef itk::GradientMagnitudeImageFilter<ImageType, ImageType> GradientFilterType; GradientFilterType::Pointer gradientFilter = GradientFilterType::New(); gradientFilter->SetInput(inputImage); gradientFilter->Update(); ImageType::Pointer gradientInputImage = gradientFilter->GetOutput(); cout << "Produced gradient image" << endl; typedef itk::ImageRegionIterator<ImageType> IteratorType; typedef itk::ImageRegionIterator<SegImageType> SegIteratorType; IteratorType gradIt(gradientFilter->GetOutput(), gradientFilter->GetOutput()->GetLargestPossibleRegion()); cout << "GradIt" << endl; vtkPolyDataMapper* mapper = (vtkPolyDataMapper*)(this->GetDefaultRenderer()->GetActors()->GetLastActor()->GetMapper()); vtkSmartPointer<vtkPolyData> vtkSegImage = vtkSmartPointer<vtkPolyData>::New(); vtkSegImage->DeepCopy(mapper->GetInput()); vtkSegImage->GetPointData()->SetScalars(NULL); cout << "Extracted mesh from actor" << endl; vtkSmartPointer<vtkSmoothPolyDataFilter> smoother = vtkSmoothPolyDataFilter::New(); smoother->SetInputData(vtkSegImage); smoother->SetNumberOfIterations(MESH_SMOOTH_ITERATIONS); smoother->Update(); vtkSmartPointer<vtkPolyData> mesh = smoother->GetOutput(); cout << "Mesh smoothed" << endl; typedef itk::ImageToVTKImageFilter<ImageType> ConverterType; ConverterType::Pointer gradientConverter = ConverterType::New(); gradientConverter->SetInput(inputImage); gradientConverter->Update(); vtkSmartPointer<vtkImageData> vtkGradientImage = gradientConverter->GetOutput(); cout << "Read CT image" << endl; vtkSmartPointer<vtkProbeFilter> probeFilter = vtkProbeFilter::New(); probeFilter->SetSourceData(vtkGradientImage); probeFilter->SetInputData(mesh); probeFilter->Update(); cout << "Probe finished" << endl; vtkSmartPointer<vtkGeometryFilter> geometryFilter = vtkGeometryFilter::New(); geometryFilter->SetInputData(probeFilter->GetOutput()); geometryFilter->Update(); vtkSmartPointer<vtkPolyData> gradientMesh = geometryFilter->GetOutput(); cout << "Geometric filter finished" << endl; vtkSmartPointer<vtkPolyData> minCurvatureMesh = mlc.polyDataToMinCurvature(mapper->GetInput()); cout << "mlc.minCurv finished" << endl; //just temporary - don't forget to delete vtkSmartPointer<vtkPolyData> maxCurvatureMesh = mlc.polyDataToMaxCurvature(mapper->GetInput()); // --- up to here cout << "mlc.maaxCurv finished" << endl; vtkSmartPointer<vtkPolyData> minCutMeshLeaks = mlc.minCut(minCurvatureMesh, mapper->GetInput(), gradientMesh, MIN_CURVATURE_TAG, 1.0f); cout << "minCut finished" << endl; vtkSmartPointer<vtkPolyData> minCutMeshInteriorLeaks = mlc.minCut(maxCurvatureMesh, mapper->GetInput(), gradientMesh, MAX_CURVATURE_TAG, 1.0f); cout << "minCut Interior finished" << endl; vtkSmartPointer<vtkPolyData> minCutMesh = mlc.minCutConjunction(minCutMeshLeaks, minCutMeshInteriorLeaks); cout << "Conjunction finished" << endl; mlc.attributeDilation(minCutMesh, ATTRIBUTE_DILATION_RADIUS); cout << "dilation finished" << endl; vtkSmartPointer<vtkPolyData> correctedMesh1 = mlc.laplaceInterpolation(minCutMesh); cout << "laplace finished" << endl; vtkSmartPointer<vtkPolyDataNormals> normals = vtkPolyDataNormals::New(); normals->SetInputData(correctedMesh1); normals->FlipNormalsOn(); normals->Update(); vtkSmartPointer<vtkPolyData> correctedMesh = normals->GetOutput(); cout << "Finished fixing mesh! Wow...." << endl; cout << "Writing mesh to file! laplaceMesh.vtk" << endl; mlc.writePolyData(correctedMesh, "laplaceMesh.vtk"); vtkSmartPointer<vtkDecimatePro> decimateFilter = vtkDecimatePro::New(); decimateFilter->SetInputData(correctedMesh); decimateFilter->SetTargetReduction(DECIMATION_FACTOR); decimateFilter->PreserveTopologyOn(); decimateFilter->Update(); vtkSmartPointer<vtkPolyData> decimatedMesh = decimateFilter->GetOutput(); cout << "Writing mesh to file! decimatedMesh.vtk" << endl; mlc.writePolyData(decimatedMesh, "decimatedMesh.vtk"); //2.5D NEW code //Seg input image is the selection_structured_points. (upcast to vtkImageData) typedef itk::VTKImageToImageFilter<SegImageType> SegConverterType; SegConverterType::Pointer converter = SegConverterType::New(); cout << "bedug 1" << endl; // selection is not NULL (checked...) cout << "this->_selection->GetScalarType(): " << this->_selection->GetScalarType() << endl; if (this->_selection->GetScalarType() == VTK_INT){ cout << "I have INTs instead of shorts for some reason!" << endl; } converter->SetInput(this->_selection); cout << "deb 5" << endl; converter->Update(); // cout << "bedug 2" << endl; SegImageType::Pointer segInputImage = converter->GetOutput(); cout << "bedug 3" << endl; SegImageType::Pointer outputContourImage = mlc.sampleMeshOnImage<SegImageType>(decimatedMesh, segInputImage); cout << "bedug 4" << endl; vtkSmartPointer<vtkDecimatePro> decimateFilter2 = vtkDecimatePro::New(); decimateFilter2->SetInputData(mapper->GetInput()); decimateFilter2->SetTargetReduction(DECIMATION_FACTOR); decimateFilter2->PreserveTopologyOn(); decimateFilter2->Update(); SegImageType::Pointer seedInputImage = mlc.sampleMeshOnImage<SegImageType>(decimateFilter2->GetOutput(), segInputImage); cout << "bedug 5" << endl; SegImageType::Pointer outputImage = mlc.correctImage<SegImageType>(segInputImage, seedInputImage, outputContourImage, _numTumors); //Here we should dilate: cout << "at dilation" << endl; typedef itk::BinaryBallStructuringElement<SegPixelType,3> StructuringElementType; StructuringElementType structuringElement; structuringElement.SetRadius(DILATION_ST_SIZE); structuringElement.CreateStructuringElement(); typedef itk::BinaryDilateImageFilter<SegImageType, SegImageType, StructuringElementType> BinaryDilateImageFilterType; BinaryDilateImageFilterType::Pointer dilateFilter = BinaryDilateImageFilterType::New(); dilateFilter->SetInput(outputImage); dilateFilter->SetKernel(structuringElement); dilateFilter->Update(); outputImage = dilateFilter->GetOutput(); cout << "finished dilation" << endl; //dilation end. typedef itk::ImageFileWriter<SegImageType> WriterType; WriterType::Pointer writer = WriterType::New(); cout << "bedug 6" << endl; writer->SetInput(outputImage); cout << "Writing mesh to file! correctedImage.nii.gz" << endl; writer->SetFileName("correctedImage.nii.gz"); try{ writer->Update(); } catch (itk::ExceptionObject & excp) { std::cerr << "writing input image exception thrown" << std::endl; std::cerr << excp << std::endl; exit(1); } typedef itk::ImageToVTKImageFilter<SegImageType> SegInvConverterType; SegInvConverterType::Pointer correctionConverter = SegInvConverterType::New(); cout << "bedug 7" << endl; correctionConverter->SetInput(outputImage); correctionConverter->Update(); vtkSmartPointer<vtkImageData> vtkCorrectedImage = correctionConverter->GetOutput(); vtkUnsignedShortArray* scalars = (vtkUnsignedShortArray*)(vtkCorrectedImage->GetPointData()->GetScalars()); vtkUnsignedShortArray* selection_scalars = (vtkUnsignedShortArray*)(_selection->GetPointData()->GetScalars()); for (int i = 0; i < _selection->GetNumberOfPoints(); i++){ if (scalars->GetValue(i) != NOT_ACTIVE){ //cout << scalars->GetValue(i) << endl; selection_scalars->SetValue(i, FOREGROUND); } else{ selection_scalars->SetValue(i, NOT_ACTIVE); } } selection_scalars->Modified(); this->_selection->Modified(); cout << "bedug 8" << endl; vtkSmartPointer<vtkPolyData> outputMesh = mlc.createAndSmoothSurface(vtkCorrectedImage, 50); vtkUnsignedShortArray* meshScalars = vtkUnsignedShortArray::New();// (vtkUnsignedShortArray*)(outputMesh->GetPointData()->GetScalars()); meshScalars->SetNumberOfComponents(1); meshScalars->SetNumberOfTuples(outputMesh->GetNumberOfPoints()); cout <<"outputMesh->GetNumberOfPoints()"<< outputMesh->GetNumberOfPoints() << endl; for (int i = 0; i < outputMesh->GetNumberOfPoints(); i++){ meshScalars->SetValue(i, NOT_ACTIVE); } meshScalars->SetName("mesh_colors"); meshScalars->Modified(); outputMesh->GetPointData()->RemoveArray("mesh_colors"); outputMesh->GetPointData()->SetScalars(meshScalars); outputMesh->GetPointData()->Modified(); cout << "output values: " << meshScalars->GetValue(0) << endl; mapper->GetInput()->DeepCopy(outputMesh); mapper->Modified(); cout << "We won!" << endl; }
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"); }
void LidarSegmentationWidget::GenerateNeighborSinks() { Mask::Pointer sourcesImage = Mask::New(); sourcesImage->SetRegions(this->ImageRegion); ITKHelpers::IndicesToBinaryImage(this->Sources, sourcesImage); ITKHelpers::WriteImage(sourcesImage.GetPointer(), "sourcesImage.png"); // Dilate the mask std::cout << "Dilating mask..." << std::endl; typedef itk::BinaryBallStructuringElement<Mask::PixelType, 2> StructuringElementType; StructuringElementType structuringElement; structuringElement.SetRadius(1); structuringElement.CreateStructuringElement(); typedef itk::BinaryDilateImageFilter<Mask, Mask, StructuringElementType> BinaryDilateImageFilterType; BinaryDilateImageFilterType::Pointer dilateFilter = BinaryDilateImageFilterType::New(); dilateFilter->SetInput(sourcesImage); dilateFilter->SetKernel(structuringElement); dilateFilter->Update(); // Binary XOR the images to get the difference image //std::cout << "XORing masks..." << std::endl; typedef itk::XorImageFilter<Mask> XorImageFilterType; XorImageFilterType::Pointer xorFilter = XorImageFilterType::New(); xorFilter->SetInput1(dilateFilter->GetOutput()); xorFilter->SetInput2(sourcesImage); xorFilter->Update(); ITKHelpers::WriteImage(xorFilter->GetOutput(), "boundaryOfSegmentation.png"); // Iterate over the border pixels. If the closest pixel in the original segmentation has // a depth greater than a threshold, mark it as a new sink. Else, do not. std::cout << "Determining which boundary pixels should be declared background..." << std::endl; //std::cout << "There should be " << Helpers::CountNonZeroPixels(xorFilter->GetOutput()) // << " considered." << std::endl; typedef std::vector<itk::Index<2> > VectorOfPixelsType; VectorOfPixelsType newSinks; typedef itk::VectorIndexSelectionCastImageFilter<ImageType, FloatScalarImageType> IndexSelectionType; IndexSelectionType::Pointer indexSelectionFilter = IndexSelectionType::New(); indexSelectionFilter->SetIndex(3); indexSelectionFilter->SetInput(this->Image); indexSelectionFilter->Update(); FloatScalarImageType::Pointer depthImage = indexSelectionFilter->GetOutput(); //float sameObjectThreshold = 0.1f; VectorOfPixelsType consideredPixels; itk::ImageRegionIterator<Mask> imageIterator(xorFilter->GetOutput(), xorFilter->GetOutput()->GetLargestPossibleRegion()); while(!imageIterator.IsAtEnd()) { if(imageIterator.Get()) // If the current pixel is in question { consideredPixels.push_back(imageIterator.GetIndex()); } ++imageIterator; } std::cout << "There are " << consideredPixels.size() << " potential new sink pixels." << std::endl; for(VectorOfPixelsType::const_iterator iter = consideredPixels.begin(); iter != consideredPixels.end(); ++iter) { //std::cout << "Considering pixel " << consideredCounter << " (index " // << imageIterator.GetIndex() << ")" << std::endl; ImageType::PixelType currentPixel = this->Image->GetPixel(*iter); unsigned int radius = this->txtBackgroundCheckRadius->text().toUInt(); ImageType::RegionType desiredRegion = ITKHelpers::GetRegionInRadiusAroundPixel(*iter, radius); //std::cout << "desiredRegion: " << desiredRegion << std::endl; itk::ImageRegionIterator<Mask> sourcesImageIterator(sourcesImage, desiredRegion); std::vector<float> nonForegroundDepths; std::vector<float> foregroundDepths; while(!sourcesImageIterator.IsAtEnd()) { if(sourcesImageIterator.Get()) { foregroundDepths.push_back(depthImage->GetPixel(sourcesImageIterator.GetIndex())); } else { nonForegroundDepths.push_back(depthImage->GetPixel(sourcesImageIterator.GetIndex())); } ++sourcesImageIterator; } if(nonForegroundDepths.size() < 1) { } float nonForegroundMedian = Helpers::VectorMedian(nonForegroundDepths); float foregroundMedian = Helpers::VectorMedian(foregroundDepths); float difference = fabs(foregroundMedian - nonForegroundMedian); if(difference > this->txtBackgroundThreshold->text().toFloat()) { //std::cout << "Difference was " << difference << " so this is a sink pixel." << std::endl; newSinks.push_back(*iter); } else { //std::cout << "Difference was " << difference << " so this is NOT a sink pixel." << std::endl; } } // end loop over considered pixels unsigned char blue[3] = {0, 0, 255}; // ImageType::PixelType blue(3); // blue[0] = 0; // blue[1] = 0; // blue[2] = 255; ITKVTKHelpers::SetPixels(this->SourceSinkImageData.GetPointer(), consideredPixels, blue); this->SourceSinkImageData->Modified(); this->Refresh(); // Save the new sink pixels for inspection UnsignedCharScalarImageType::Pointer newSinksImage = UnsignedCharScalarImageType::New(); newSinksImage->SetRegions(this->Image->GetLargestPossibleRegion()); newSinksImage->Allocate(); ITKHelpers::IndicesToBinaryImage(newSinks, newSinksImage); ITKHelpers::WriteImage(newSinksImage.GetPointer(), "newSinks.png"); //std::cout << "Out of " << consideredCounter << " pixels considered, " // << backgroundCounter << " were declared background." << std::endl; // Set the new sinks std::cout << "Setting " << newSinks.size() << " new sinks." << std::endl; // Modify the list of sinks so it can be retrieved by the MainWindow after the segmentation is finished this->Sinks.insert(this->Sinks.end(), newSinks.begin(), newSinks.end()); UpdateSelections(); }