Esempio n. 1
0
static int
CalculateGlSZMatrix(itk::Image<TPixel, VImageDimension>* itkImage,
                    itk::Image<unsigned short, VImageDimension>* mask,
                    std::vector<itk::Offset<VImageDimension> > offsets,
                    bool estimateLargestRegion,
                    mitk::GreyLevelSizeZoneMatrixHolder &holder)
{
  typedef itk::Image<TPixel, VImageDimension> ImageType;
  typedef itk::Image<unsigned short, VImageDimension> MaskImageType;
  typedef typename ImageType::IndexType IndexType;

  typedef itk::ImageRegionIteratorWithIndex<ImageType> ConstIterType;
  typedef itk::ImageRegionIteratorWithIndex<MaskImageType> ConstMaskIterType;

  auto region = mask->GetLargestPossibleRegion();
  typename MaskImageType::RegionType newRegion;
  newRegion.SetSize(region.GetSize());
  newRegion.SetIndex(region.GetIndex());

  ConstIterType imageIter(itkImage, itkImage->GetLargestPossibleRegion());
  ConstMaskIterType maskIter(mask, mask->GetLargestPossibleRegion());

  typename MaskImageType::Pointer visitedImage = MaskImageType::New();
  visitedImage->SetRegions(newRegion);
  visitedImage->Allocate();
  visitedImage->FillBuffer(0);

  int largestRegion = 0;

  while (!maskIter.IsAtEnd())
  {
    if (maskIter.Value() > 0 )
    {
      auto startIntensityIndex = holder.IntensityToIndex(imageIter.Value());
      std::vector<IndexType> indices;
      indices.push_back(maskIter.GetIndex());
      unsigned int steps = 0;

      while (indices.size() > 0)
      {
        auto currentIndex = indices.back();
        indices.pop_back();

        if (!region.IsInside(currentIndex))
        {
          continue;
        }

        auto wasVisited = visitedImage->GetPixel(currentIndex);
        auto newIntensityIndex = holder.IntensityToIndex(itkImage->GetPixel(currentIndex));
        auto isInMask = mask->GetPixel(currentIndex);

        if ((isInMask > 0) &&
            (newIntensityIndex == startIntensityIndex) &&
            (wasVisited < 1))
        {
          ++steps;
          visitedImage->SetPixel(currentIndex, 1);
          for (auto offset : offsets)
          {
            auto newIndex = currentIndex + offset;
            indices.push_back(newIndex);
            newIndex = currentIndex - offset;
            indices.push_back(newIndex);
          }

        }
      }
      if (steps > 0)
      {
        largestRegion = std::max<int>(steps, largestRegion);
        steps = std::min<unsigned int>(steps, holder.m_MaximumSize);
        if (!estimateLargestRegion)
        {
          holder.m_Matrix(startIntensityIndex, steps - 1) += 1;
        }
      }
    }
    ++imageIter;
    ++maskIter;
  }
  return largestRegion;
}
SEXP invariantSimilarityHelper(
  typename itk::Image< float , ImageDimension >::Pointer image1,
  typename itk::Image< float , ImageDimension >::Pointer image2,
  SEXP r_thetas, SEXP r_lsits, SEXP r_WM, SEXP r_scale,
  SEXP r_doreflection, SEXP r_txfn  )
{
  unsigned int mibins = 20;
  unsigned int localSearchIterations =
    Rcpp::as< unsigned int >( r_lsits ) ;
  std::string whichMetric = Rcpp::as< std::string >( r_WM );
  std::string txfn = Rcpp::as< std::string >( r_txfn );
  bool useprincaxis = true;
  typedef typename itk::ImageMaskSpatialObject<ImageDimension>::ImageType
    maskimagetype;
  typename maskimagetype::Pointer mask = ITK_NULLPTR;
  Rcpp::NumericVector thetas( r_thetas );
  Rcpp::NumericVector vector_r( r_thetas ) ;
  Rcpp::IntegerVector dims( 1 );
  Rcpp::IntegerVector doReflection( r_doreflection );
  unsigned int vecsize = thetas.size();
  dims[0]=0;
  typedef float  PixelType;
  typedef double RealType;
  RealType bestscale = Rcpp::as< RealType >( r_scale ) ;
  typedef itk::Image< PixelType , ImageDimension > ImageType;
  if( image1.IsNotNull() & image2.IsNotNull() )
    {
    typedef typename itk::ImageMomentsCalculator<ImageType> ImageCalculatorType;
    typedef itk::AffineTransform<RealType, ImageDimension> AffineType0;
    typedef itk::AffineTransform<RealType, ImageDimension> AffineType;
    typedef typename ImageCalculatorType::MatrixType       MatrixType;
    typedef itk::Vector<float, ImageDimension>  VectorType;
    VectorType ccg1;
    VectorType cpm1;
    MatrixType cpa1;
    VectorType ccg2;
    VectorType cpm2;
    MatrixType cpa2;
    typename ImageCalculatorType::Pointer calculator1 =
      ImageCalculatorType::New();
    typename ImageCalculatorType::Pointer calculator2 =
      ImageCalculatorType::New();
    calculator1->SetImage(  image1 );
    calculator2->SetImage(  image2 );
    typename ImageCalculatorType::VectorType fixed_center;
    fixed_center.Fill(0);
    typename ImageCalculatorType::VectorType moving_center;
    moving_center.Fill(0);
    try
      {
      calculator1->Compute();
      fixed_center = calculator1->GetCenterOfGravity();
      ccg1 = calculator1->GetCenterOfGravity();
      cpm1 = calculator1->GetPrincipalMoments();
      cpa1 = calculator1->GetPrincipalAxes();
      try
        {
        calculator2->Compute();
        moving_center = calculator2->GetCenterOfGravity();
        ccg2 = calculator2->GetCenterOfGravity();
        cpm2 = calculator2->GetPrincipalMoments();
        cpa2 = calculator2->GetPrincipalAxes();
        }
      catch( ... )
        {
        fixed_center.Fill(0);
        }
      }
    catch( ... )
      {
      // Rcpp::Rcerr << " zero image1 error ";
      }
    if ( vnl_math_abs( bestscale - 1.0 ) < 1.e-6 )
      {
      RealType volelt1 = 1;
      RealType volelt2 = 1;
      for ( unsigned int d=0; d<ImageDimension; d++)
        {
        volelt1 *= image1->GetSpacing()[d];
        volelt2 *= image2->GetSpacing()[d];
        }
      bestscale =
        ( calculator2->GetTotalMass() * volelt2 )/
        ( calculator1->GetTotalMass() * volelt1 );
      RealType powlev = 1.0 / static_cast<RealType>(ImageDimension);
      bestscale = vcl_pow( bestscale , powlev );
    }
    unsigned int eigind1 = 1;
    unsigned int eigind2 = 1;
    if( ImageDimension == 3 )
      {
      eigind1 = 2;
      }
    typedef vnl_vector<RealType> EVectorType;
    typedef vnl_matrix<RealType> EMatrixType;
    EVectorType evec1_2ndary = cpa1.GetVnlMatrix().get_row( eigind2 );
    EVectorType evec1_primary = cpa1.GetVnlMatrix().get_row( eigind1 );
    EVectorType evec2_2ndary  = cpa2.GetVnlMatrix().get_row( eigind2 );
    EVectorType evec2_primary = cpa2.GetVnlMatrix().get_row( eigind1 );
    /** Solve Wahba's problem http://en.wikipedia.org/wiki/Wahba%27s_problem */
    EMatrixType B = outer_product( evec2_primary, evec1_primary );
    if( ImageDimension == 3 )
      {
      B = outer_product( evec2_2ndary, evec1_2ndary )
        + outer_product( evec2_primary, evec1_primary );
      }
    vnl_svd<RealType>    wahba( B );
    vnl_matrix<RealType> A_solution = wahba.V() * wahba.U().transpose();
    A_solution = vnl_inverse( A_solution );
    RealType det = vnl_determinant( A_solution  );
    if( ( det < 0 ) )
      {
      vnl_matrix<RealType> id( A_solution );
      id.set_identity();
      for( unsigned int i = 0; i < ImageDimension; i++ )
        {
        if( A_solution( i, i ) < 0 )
          {
          id( i, i ) = -1.0;
          }
        }
      A_solution =  A_solution * id.transpose();
      }
    if ( doReflection[0] == 1 ||  doReflection[0] == 3 )
      {
        vnl_matrix<RealType> id( A_solution );
        id.set_identity();
        id = id - 2.0 * outer_product( evec2_primary , evec2_primary  );
        A_solution = A_solution * id;
      }
    if ( doReflection[0] > 1 )
      {
        vnl_matrix<RealType> id( A_solution );
        id.set_identity();
        id = id - 2.0 * outer_product( evec1_primary , evec1_primary  );
        A_solution = A_solution * id;
      }
    typename AffineType::Pointer affine1 = AffineType::New();
    typename AffineType::OffsetType trans = affine1->GetOffset();
    itk::Point<RealType, ImageDimension> trans2;
    for( unsigned int i = 0; i < ImageDimension; i++ )
      {
      trans[i] = moving_center[i] - fixed_center[i];
      trans2[i] =  fixed_center[i] * ( 1 );
      }
    affine1->SetIdentity();
    affine1->SetOffset( trans );
    if( useprincaxis )
      {
      affine1->SetMatrix( A_solution );
      }
    affine1->SetCenter( trans2 );
    if( ImageDimension > 3  )
      {
      return EXIT_SUCCESS;
      }
    vnl_vector<RealType> evec_tert;
    if( ImageDimension == 3 )
      { // try to rotate around tertiary and secondary axis
      evec_tert = vnl_cross_3d( evec1_primary, evec1_2ndary );
      }
    if( ImageDimension == 2 )
      { // try to rotate around tertiary and secondary axis
      evec_tert = evec1_2ndary;
      evec1_2ndary = evec1_primary;
      }
    itk::Vector<RealType, ImageDimension> axis2;
    itk::Vector<RealType, ImageDimension> axis1;
    for( unsigned int d = 0; d < ImageDimension; d++ )
      {
      axis1[d] = evec_tert[d];
      axis2[d] = evec1_2ndary[d];
      }
    typename AffineType::Pointer simmer = AffineType::New();
    simmer->SetIdentity();
    simmer->SetCenter( trans2 );
    simmer->SetOffset( trans );
    typename AffineType0::Pointer affinesearch = AffineType0::New();
    affinesearch->SetIdentity();
    affinesearch->SetCenter( trans2 );
    typedef  itk::MultiStartOptimizerv4         OptimizerType;
    typename OptimizerType::MetricValuesListType metricvalues;
    typename OptimizerType::Pointer  mstartOptimizer = OptimizerType::New();
    typedef itk::CorrelationImageToImageMetricv4
      <ImageType, ImageType, ImageType> GCMetricType;
    typedef itk::MattesMutualInformationImageToImageMetricv4
      <ImageType, ImageType, ImageType> MetricType;
    typename MetricType::ParametersType newparams(  affine1->GetParameters() );
    typename GCMetricType::Pointer gcmetric = GCMetricType::New();
    gcmetric->SetFixedImage( image1 );
    gcmetric->SetVirtualDomainFromImage( image1 );
    gcmetric->SetMovingImage( image2 );
    gcmetric->SetMovingTransform( simmer );
    gcmetric->SetParameters( newparams );
    typename MetricType::Pointer mimetric = MetricType::New();
    mimetric->SetNumberOfHistogramBins( mibins );
    mimetric->SetFixedImage( image1 );
    mimetric->SetMovingImage( image2 );
    mimetric->SetMovingTransform( simmer );
    mimetric->SetParameters( newparams );
    if( mask.IsNotNull() )
      {
      typename itk::ImageMaskSpatialObject<ImageDimension>::Pointer so =
        itk::ImageMaskSpatialObject<ImageDimension>::New();
      so->SetImage( const_cast<maskimagetype *>( mask.GetPointer() ) );
      mimetric->SetFixedImageMask( so );
      gcmetric->SetFixedImageMask( so );
      }
    typedef  itk::ConjugateGradientLineSearchOptimizerv4 LocalOptimizerType;
    typename LocalOptimizerType::Pointer  localoptimizer =
      LocalOptimizerType::New();
    RealType     localoptimizerlearningrate = 0.1;
    localoptimizer->SetLearningRate( localoptimizerlearningrate );
    localoptimizer->SetMaximumStepSizeInPhysicalUnits(
      localoptimizerlearningrate );
    localoptimizer->SetNumberOfIterations( localSearchIterations );
    localoptimizer->SetLowerLimit( 0 );
    localoptimizer->SetUpperLimit( 2 );
    localoptimizer->SetEpsilon( 0.1 );
    localoptimizer->SetMaximumLineSearchIterations( 50 );
    localoptimizer->SetDoEstimateLearningRateOnce( true );
    localoptimizer->SetMinimumConvergenceValue( 1.e-6 );
    localoptimizer->SetConvergenceWindowSize( 5 );
    if( true )
      {
      typedef typename MetricType::FixedSampledPointSetType PointSetType;
      typedef typename PointSetType::PointType              PointType;
      typename PointSetType::Pointer      pset(PointSetType::New());
      unsigned int ind=0;
      unsigned int ct=0;
      itk::ImageRegionIteratorWithIndex<ImageType> It(image1,
        image1->GetLargestPossibleRegion() );
      for( It.GoToBegin(); !It.IsAtEnd(); ++It )
        {
        // take every N^th point
        if ( ct % 10 == 0  )
          {
          PointType pt;
          image1->TransformIndexToPhysicalPoint( It.GetIndex(), pt);
          pset->SetPoint(ind, pt);
          ind++;
          }
          ct++;
        }
      mimetric->SetFixedSampledPointSet( pset );
      mimetric->SetUseFixedSampledPointSet( true );
      gcmetric->SetFixedSampledPointSet( pset );
      gcmetric->SetUseFixedSampledPointSet( true );
    }
    if ( whichMetric.compare("MI") == 0  ) {
      mimetric->Initialize();
      typedef itk::RegistrationParameterScalesFromPhysicalShift<MetricType>
      RegistrationParameterScalesFromPhysicalShiftType;
      typename RegistrationParameterScalesFromPhysicalShiftType::Pointer
      shiftScaleEstimator =
      RegistrationParameterScalesFromPhysicalShiftType::New();
      shiftScaleEstimator->SetMetric( mimetric );
      shiftScaleEstimator->SetTransformForward( true );
      typename RegistrationParameterScalesFromPhysicalShiftType::ScalesType
      movingScales( simmer->GetNumberOfParameters() );
      shiftScaleEstimator->EstimateScales( movingScales );
      mstartOptimizer->SetScales( movingScales );
      mstartOptimizer->SetMetric( mimetric );
      localoptimizer->SetMetric( mimetric );
      localoptimizer->SetScales( movingScales );
    }
    if ( whichMetric.compare("MI") != 0  ) {
      gcmetric->Initialize();
      typedef itk::RegistrationParameterScalesFromPhysicalShift<GCMetricType>
        RegistrationParameterScalesFromPhysicalShiftType;
      typename RegistrationParameterScalesFromPhysicalShiftType::Pointer
        shiftScaleEstimator =
        RegistrationParameterScalesFromPhysicalShiftType::New();
      shiftScaleEstimator->SetMetric( gcmetric );
      shiftScaleEstimator->SetTransformForward( true );
      typename RegistrationParameterScalesFromPhysicalShiftType::ScalesType
      movingScales( simmer->GetNumberOfParameters() );
      shiftScaleEstimator->EstimateScales( movingScales );
      mstartOptimizer->SetScales( movingScales );
      mstartOptimizer->SetMetric( gcmetric );
      localoptimizer->SetMetric( gcmetric );
      localoptimizer->SetScales( movingScales );
    }
    typename OptimizerType::ParametersListType parametersList =
      mstartOptimizer->GetParametersList();
    affinesearch->SetIdentity();
    affinesearch->SetCenter( trans2 );
    affinesearch->SetOffset( trans );
    for ( unsigned int i = 0; i < vecsize; i++ )
      {
      RealType ang1 = thetas[i];
      RealType ang2 = 0; // FIXME should be psi
      vector_r[ i ]=0;
      if( ImageDimension == 3 )
        {
        for ( unsigned int jj = 0; jj < vecsize; jj++ )
        {
        ang2=thetas[jj];
        affinesearch->SetIdentity();
        affinesearch->SetCenter( trans2 );
        affinesearch->SetOffset( trans );
        if( useprincaxis )
          {
          affinesearch->SetMatrix( A_solution );
          }
        affinesearch->Rotate3D(axis1, ang1, 1);
        affinesearch->Rotate3D(axis2, ang2, 1);
        affinesearch->Scale( bestscale );
        simmer->SetMatrix(  affinesearch->GetMatrix() );
        parametersList.push_back( simmer->GetParameters() );
        }
        }
      if( ImageDimension == 2 )
        {
        affinesearch->SetIdentity();
        affinesearch->SetCenter( trans2 );
        affinesearch->SetOffset( trans );
        if( useprincaxis )
          {
          affinesearch->SetMatrix( A_solution );
          }
        affinesearch->Rotate2D( ang1, 1);
        affinesearch->Scale( bestscale );
        simmer->SetMatrix(  affinesearch->GetMatrix() );
        typename AffineType::ParametersType pp =
          simmer->GetParameters();
        //pp[1]=ang1;
        //pp[0]=bestscale;
        parametersList.push_back( simmer->GetParameters() );
        }
      }
    mstartOptimizer->SetParametersList( parametersList );
    if( localSearchIterations > 0 )
      {
      mstartOptimizer->SetLocalOptimizer( localoptimizer );
      }
    mstartOptimizer->StartOptimization();
    typename AffineType::Pointer bestaffine = AffineType::New();
    bestaffine->SetCenter( trans2 );
    bestaffine->SetParameters( mstartOptimizer->GetBestParameters() );
    if ( txfn.length() > 3 )
      {
      typename AffineType::Pointer bestaffine = AffineType::New();
      bestaffine->SetCenter( trans2 );
      bestaffine->SetParameters( mstartOptimizer->GetBestParameters() );
      typedef itk::TransformFileWriter TransformWriterType;
      typename TransformWriterType::Pointer transformWriter =
        TransformWriterType::New();
      transformWriter->SetInput( bestaffine );
      transformWriter->SetFileName( txfn.c_str() );
      transformWriter->Update();
      }
    metricvalues = mstartOptimizer->GetMetricValuesList();
    for ( unsigned int k = 0; k < metricvalues.size(); k++ )
      {
      vector_r[k] = metricvalues[k];
      }
    dims[0] = vecsize;
    vector_r.attr( "dim" ) = vecsize;
    return Rcpp::wrap( vector_r );
    }
  else
    {
    return Rcpp::wrap( vector_r );
    }
}
void udgPerfusionEstimator<TPerfuImage,TMaskImage, TTransform>::ComputeEstimation()
{

  if(m_perfuImage.IsNull()){
    std::cout<<"Not Perfusion Image defined"<<std::endl;
    return;
    }


  if(m_ventricleMask.IsNull()){
    std::cout<<"Not Ventricle Mask Image defined"<<std::endl;
    return;
    }

  if(m_strokeMask.IsNull()){
    std::cout<<"Not Stroke Mask Image defined"<<std::endl;
    return;
    }

  if(m_Transform.IsNull()){
    std::cout<<"Not Transform defined"<<std::endl;
    return;
    }

  m_estimatedImage = PerfuImageType::New();
  m_estimatedImage->SetRegions( m_perfuImage->GetLargestPossibleRegion() );
  m_estimatedImage->SetSpacing( m_perfuImage->GetSpacing() );
  m_estimatedImage->SetOrigin( m_perfuImage->GetOrigin() );
  m_estimatedImage->Allocate();

  //Definim la regi�molt probablement infartada
  typename MaskImageType::Pointer m_strokeInfluence = MaskImageType::New();
  m_strokeInfluence->SetRegions( m_strokeMask->GetLargestPossibleRegion() );
  m_strokeInfluence->SetSpacing( m_strokeMask->GetSpacing() );
  m_strokeInfluence->SetOrigin( m_strokeMask->GetOrigin() );
  m_strokeInfluence->Allocate();

  typename DilateFilterType::Pointer binaryDilate = DilateFilterType::New();
  binaryDilate->SetDilateValue( 255 );	//suposem que el valor alt ser�255
  StructuringElementType structuringElementDilate;
  structuringElementDilate.SetRadius( 2 ); // 3x3 structuring element
  structuringElementDilate.CreateStructuringElement();

  binaryDilate->SetKernel( structuringElementDilate );

  binaryDilate->SetInput( m_strokeMask );
  binaryDilate->Update();
  m_strokeInfluence = binaryDilate->GetOutput();

  //Fi regi�molt probablement infartada




      typename ResampleFilterType::Pointer resample = ResampleFilterType::New();

      typename TransformType::Pointer inverse = TransformType::New();
      if (!m_Transform->GetInverse( inverse ))
      {
          std::cout<<"ERROR! udgPerfusionEstimator<TPerfuImage,TMaskImage, TTransform>::ComputeEstimation() No hi ha inversa!"<<std::endl;
      }

      resample->SetTransform( inverse );
      resample->SetInput( m_ventricleMask);
      resample->SetSize( m_perfuImage->GetLargestPossibleRegion().GetSize() );
      resample->SetOutputOrigin(  m_perfuImage->GetOrigin() );
      resample->SetOutputSpacing( m_perfuImage->GetSpacing() );
      resample->SetDefaultPixelValue( 0 );
      resample->SetInterpolator( m_InterpolatorVentricle );

      resample->Update();

      Ventricles = resample->GetOutput();


      typename ResampleFilterType::Pointer resample2 = ResampleFilterType::New();

      resample2->SetTransform( inverse );
      resample2->SetInput( m_strokeInfluence);
      resample2->SetSize( m_perfuImage->GetLargestPossibleRegion().GetSize() );
      resample2->SetOutputOrigin(  m_perfuImage->GetOrigin() );
      resample2->SetOutputSpacing( m_perfuImage->GetSpacing() );
      resample2->SetDefaultPixelValue( 0 );
      resample2->SetInterpolator( m_InterpolatorStroke );

      resample2->Update();

      //Creem les finestres mostrant les imatges registrades

      Stroke = resample2->GetOutput();



  PerfuIteratorType estimatedIt(m_estimatedImage, m_estimatedImage->GetBufferedRegion());

  PerfuIteratorType perfuIt(m_perfuImage, m_perfuImage->GetBufferedRegion());
  PerfuIteratorType VentIt(Ventricles, Ventricles->GetBufferedRegion());
  PerfuIteratorType StkIt(Stroke, Stroke->GetBufferedRegion());

  RadiusNeighborType radius;
  radius.Fill(2);

  m_InterpolatorVentricle->SetInputImage( m_ventricleMask );
  m_InterpolatorStroke->SetInputImage( m_strokeInfluence );

  PerfuPointType inputPoint;
  PerfuPixelType perfuValue;
  PerfuPixelType VentValue;
  PerfuPixelType StkValue;
  typename PerfuImageType::IndexType index;

  MaskPointType transformedPoint;

  perfuIt.GoToBegin();
  VentIt.GoToBegin();
  StkIt.GoToBegin();
  estimatedIt.GoToBegin();
  ++perfuIt;
  ++VentIt;
  ++StkIt;
  ++estimatedIt;
    while (!perfuIt.IsAtEnd())
    {
        perfuValue = perfuIt.Value();

//         if(perfuValue == 0) // ((maskValue == m_insideValue)&&(perfuValue == 0))
        if ( perfuValue < 32 ) // ((maskValue == m_insideValue)&&(perfuValue == 0))
        {   //és a dir, és un punt negre
            index = perfuIt.GetIndex();
            m_perfuImage->TransformIndexToPhysicalPoint(index, inputPoint);

            transformedPoint = m_Transform->TransformPoint(inputPoint); //transformed point és el punt corresponent en difusió
            if (m_InterpolatorVentricle->IsInsideBuffer(transformedPoint))
            {
//                m_Interpolator->SetInputImage( m_ventricleMask );
                //const RealType VentriclemaskValue = m_InterpolatorVentricle->Evaluate(transformedPoint);
                VentValue = VentIt.Value();

//                if(VentriclemaskValue!=0)
                if(VentValue!=0)
                {
                    estimatedIt.Set(0);//estimatedIt.Set(1);
                }
                else
                {
                    /*
                    const RealType strokemaskValue = m_InterpolatorStroke->Evaluate(transformedPoint);
                    if(strokemaskValue!=0){
                        estimatedIt.Set(1);//estimatedIt.Set(255);
                    }
                    */
                    StkValue = StkIt.Value();
                    if(StkValue != 0)
                    {
                        estimatedIt.Set(255);
                    }
                    else
                    {
                        estimatedIt.Set(0);
                    }
                }
            }
        }
        else
        {
            estimatedIt.Set( perfuValue );  //estimatedIt.Set( perfuValue );
        }
        ++perfuIt;
        ++VentIt;
        ++StkIt;
        ++estimatedIt;
    }

    //Aqu�determinem els punts que no s� ni infart ni ventricle, fent una mitjana dels valors veins
    //La imatge s'actualitza sobre ella mateixa, per�no sembla que aix�hagi de portar problemes
 /*
  double med, cont;
  PerfuNeighborIteratorType perfuNeighborIt(radius, m_estimatedImage,  m_estimatedImage->GetBufferedRegion());

  perfuNeighborIt.GoToBegin();
  perfuIt.GoToBegin();
  estimatedIt.GoToBegin();
  ++perfuNeighborIt;
  ++estimatedIt;
  while (!estimatedIt.IsAtEnd())
  {
	  perfuValue = estimatedIt.Get();

    if (perfuValue == 0)    //� a dir, � un punt negre
	  {
      med=0;
		  cont=0;

		  for (unsigned int i = 0; i < perfuNeighborIt.Size(); i++)
		  {
		    if ( perfuNeighborIt.GetPixel(i) != 0 && perfuNeighborIt.GetPixel(i)<1000 )
		    {
		      med += perfuNeighborIt.GetPixel(i);
		      cont ++;
			  }
		  }
		  estimatedIt.Set(static_cast<PerfuPixelType> (med/cont));
	  }
	  ++perfuNeighborIt;
    ++estimatedIt;
  }
  */
  //Suavitzem la sortida --> S'hauria de fer per�d�a errors
/*
  typename SmoothingFilterType::Pointer smoothFilter = SmoothingFilterType::New();
//  smoothFilter->SetInput(m_estimatedImage);
  smoothFilter->SetInput(m_perfuImage);


//  smoothFilter->SetNumberOfIterations(5);
//  smoothFilter->SetTimeStep(0.0625);
//  smoothFilter->SetConductanceParameter(1);

//std::cout<<"hola 1"<<std::endl;

  smoothFilter->SetVariance(1);
  smoothFilter->SetMaximumKernelWidth(6);


  //smoothFilter->Update();

  RescaleFilterType::Pointer rescaler = RescaleFilterType::New();

  rescaler->SetOutputMinimum(   0 );
  rescaler->SetOutputMaximum( 255 );
//std::cout<<"hola 2"<<std::endl;

  rescaler->SetInput(smoothFilter->GetOutput());
  rescaler->Update();
//std::cout<<"hola 3"<<std::endl;

  m_estimatedImage = rescaler->GetOutput();
  */
}
      void PartialVolumeAnalysisClusteringCalculator::InternalQuantify(
          const itk::Image< TPixel, VImageDimension > *image,
          mitk::Image::Pointer clusteredImage, double* retval, mitk::Image::Pointer mask ) const
  {
    typedef itk::Image< TPixel, VImageDimension > ImageType;
    typedef itk::Image< float, VImageDimension > ProbImageType;
    typedef itk::Image< unsigned char, VImageDimension > MaskImageType;

    typedef mitk::ImageToItk<ProbImageType> CastFilterType;
    typename CastFilterType::Pointer castFilter = CastFilterType::New();
    castFilter->SetInput( clusteredImage );
    castFilter->Update();
    typename ProbImageType::Pointer clusterImage = castFilter->GetOutput();

    typename MaskImageType::Pointer itkmask = 0;
    if(mask.IsNotNull())
    {
      typedef mitk::ImageToItk<MaskImageType> CastFilterType2;
      typename CastFilterType2::Pointer castFilter2 = CastFilterType2::New();
      castFilter2->SetInput( mask );
      castFilter2->Update();
      itkmask = castFilter2->GetOutput();
    }
    else
    {
      itkmask = MaskImageType::New();
      itkmask->SetSpacing( clusterImage->GetSpacing() );   // Set the image spacing
      itkmask->SetOrigin( clusterImage->GetOrigin() );     // Set the image origin
      itkmask->SetDirection( clusterImage->GetDirection() );  // Set the image direction
      itkmask->SetRegions( clusterImage->GetLargestPossibleRegion() );
      itkmask->Allocate();
      itkmask->FillBuffer(1);
    }

    itk::ImageRegionConstIterator<ImageType>
        itimage(image, image->GetLargestPossibleRegion());

    itk::ImageRegionConstIterator<ProbImageType>
        itprob(clusterImage, clusterImage->GetLargestPossibleRegion());

    itk::ImageRegionConstIterator<MaskImageType>
        itmask(itkmask, itkmask->GetLargestPossibleRegion());

    itimage.GoToBegin();
    itprob.GoToBegin();
    itmask.GoToBegin();

    double totalProb = 0;
    double measurement = 0;
    double error = 0;

    while( !itimage.IsAtEnd() && !itprob.IsAtEnd() && !itmask.IsAtEnd() )
    {
      double valImag = itimage.Get();
      double valProb = itprob.Get();
      double valMask = itmask.Get();

      typename ProbImageType::PixelType prop = valProb * valMask;

      totalProb   += prop;
      measurement += valImag * prop;
      error       += valImag * valImag * prop;

      ++itimage;
      ++itprob;
      ++itmask;
    }

    measurement = measurement / totalProb;
    error       = error       / totalProb;
    retval[0]   = measurement;
    retval[1]   = sqrt( error - measurement*measurement );

  }