Exemplo n.º 1
0
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);
}
Exemplo n.º 2
0
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 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 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();
}