Пример #1
0
DPH::ImageType::Pointer GetBlurredVectorImage( DPH::ImageType::Pointer vectorImage, double sigma)
{
  typedef itk::DiscreteGaussianImageFilter< itk::Image<DPH::DiffusionPixelType, 3 >, itk::Image<DPH::DiffusionPixelType, 3 > > GaussianFilterType;

  typedef itk::VectorIndexSelectionCastImageFilter< DPH::ImageType, itk::Image<DPH::DiffusionPixelType, 3 > > IndexSelectionType;
  IndexSelectionType::Pointer indexSelectionFilter = IndexSelectionType::New();
  indexSelectionFilter->SetInput( vectorImage );

  typedef itk::ComposeImageFilter< itk::Image<DPH::DiffusionPixelType, 3>, DPH::ImageType > ComposeFilterType;
  ComposeFilterType::Pointer vec_composer = ComposeFilterType::New();

  for( unsigned int i=0; i<vectorImage->GetVectorLength(); ++i)
  {
    GaussianFilterType::Pointer gaussian_filter = GaussianFilterType::New();

    indexSelectionFilter->SetIndex( i );

    gaussian_filter->SetInput( indexSelectionFilter->GetOutput() );
    gaussian_filter->SetVariance( sigma );

    vec_composer->SetInput(i, gaussian_filter->GetOutput() );

    gaussian_filter->Update();
  }

  try
  {
    vec_composer->Update();
  }
  catch(const itk::ExceptionObject &e)
  {
    mitkThrow() << "[VectorImage.GaussianSmoothing] !! Failed with ITK Exception: " << e.what();
  }

  DPH::ImageType::Pointer smoothed_vector = vec_composer->GetOutput();

  /*
  itk::ImageFileWriter< DPH::ImageType >::Pointer writer =
      itk::ImageFileWriter< DPH::ImageType >::New();

  writer->SetInput( smoothed_vector );
  writer->SetFileName( "/tmp/itk_smoothed_vector.nrrd");
  writer->Update();*/

  return smoothed_vector;


}
void Difference::ComputeMinAndMaxInAllChannels()
{
  std::cout << "ComputeMinAndMaxInAllChannels()" << std::endl;
  
  this->MinimumOfChannels.SetSize(this->Image->GetNumberOfComponentsPerPixel());
  this->MaximumOfChannels.SetSize(this->Image->GetNumberOfComponentsPerPixel());
  
  for(unsigned int i = 0; i < this->Image->GetNumberOfComponentsPerPixel(); ++i)
    {
    typedef itk::VectorIndexSelectionCastImageFilter<ImageType, FloatScalarImageType> IndexSelectionType;
    IndexSelectionType::Pointer indexSelectionFilter = IndexSelectionType::New();
    indexSelectionFilter->SetIndex(i);
    indexSelectionFilter->SetInput(this->Image);
    indexSelectionFilter->Update();
  
    typedef itk::MinimumMaximumImageCalculator <FloatScalarImageType> ImageCalculatorFilterType;
    ImageCalculatorFilterType::Pointer imageCalculatorFilter = ImageCalculatorFilterType::New();
    imageCalculatorFilter->SetImage(indexSelectionFilter->GetOutput());
    imageCalculatorFilter->Compute();
    
    this->MinimumOfChannels[i] = imageCalculatorFilter->GetMinimum();
    this->MaximumOfChannels[i] = imageCalculatorFilter->GetMaximum();
    }
}
bool AppITKImage::LoadAndValidate(const std::string& imagePath)
{
	typedef itk::ImageFileReader<AppImageITKType> ReaderType;
	ReaderType::Pointer reader = ReaderType::New();
	reader->SetFileName(imagePath);
	reader->Update();

	if(!m_image)
	{
		m_image = AppImageITKType::New();
	}

	// Deep copy

	m_image->SetRegions(reader->GetOutput()->GetLargestPossibleRegion());
	m_image->SetNumberOfComponentsPerPixel(LfnIc::Image::Pixel::NUM_CHANNELS);
	m_image->Allocate();

	itk::ImageRegionConstIterator<AppImageITKType> inputIterator(reader->GetOutput(), reader->GetOutput()->GetLargestPossibleRegion());
	itk::ImageRegionIterator<AppImageITKType> outputIterator(m_image, m_image->GetLargestPossibleRegion());

	while(!inputIterator.IsAtEnd())
	{
		outputIterator.Set(inputIterator.Get());
		++inputIterator;
		++outputIterator;
	}

#if USE_CHANNEL_WEIGHTING
	// Setup channel weights - Uniform weighting - set the weight of each channel so it has the perceived range of 255
	// If a channel already has the range 255, the weight is set to 1. If a channel has a range smaller
	// than 255, its weight will be > 1. If a channel has a weight larger than 255, its weight will be set to < 1.
	// A weight should never be negative. There is no magic to scaling to 255, it is just that usually there will be some
	// RGB type channels so 255 should make several of the weights close to 1.
	std::cout << "Weights: ";
	for (int c = 0; c < LfnIc::Image::Pixel::NUM_CHANNELS; c++)
	{
		typedef itk::Image<LfnIc::Image::Pixel::ChannelType, 2> ScalarImageType;

		typedef itk::VectorIndexSelectionCastImageFilter<AppImageITKType, ScalarImageType> IndexSelectionType;
		IndexSelectionType::Pointer indexSelectionFilter = IndexSelectionType::New();
		indexSelectionFilter->SetIndex(c);
		indexSelectionFilter->SetInput(m_image);
		indexSelectionFilter->Update();

		typedef itk::MinimumMaximumImageCalculator <ScalarImageType> ImageCalculatorFilterType;
		ImageCalculatorFilterType::Pointer imageCalculatorFilter = ImageCalculatorFilterType::New();
		imageCalculatorFilter->SetImage(indexSelectionFilter->GetOutput());
		imageCalculatorFilter->Compute();

		// If there is no variation in a channel (take an image with only red (255,0,0) and blue (0,0,255) pixels for example),
		// then computing the weight doesn't make sense (and causes a divide by zero).
		if( (imageCalculatorFilter->GetMaximum() - imageCalculatorFilter->GetMinimum()) <= 0)
		{
			m_channelWeights[c] = 1.0f;
		}
		else
		{
			m_channelWeights[c] = 255.0f / (imageCalculatorFilter->GetMaximum() - imageCalculatorFilter->GetMinimum());
		}

		std::cout << m_channelWeights[c] << " ";
	}
	std::cout << std::endl;

	// Now that the weights have been calculated, apply them directly to the image data.
	LfnIc::Image::Pixel* pixelPtr = AppITKImage::GetData();
	for (int i = 0, n = GetWidth() * GetHeight(); i < n; ++i, ++pixelPtr)
	{
		LfnIc::Image::Pixel& pixel = *pixelPtr;
		for (int c = 0; c < LfnIc::Image::Pixel::NUM_CHANNELS; ++c)
		{
			pixel.channel[c] *= m_channelWeights[c];
		}
	}
#endif // USE_CHANNEL_WEIGHTING

	return true;
}
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();
}