示例#1
0
bool NewtonCalculator::BuildFunction() {
	vector<double> coords_x, coords_y;
	vector<double> tmp_divert[2];
	vector<double> divert;

	if (coords->size() < 2)
		throw NextException("I have no coefficients.");

	/* Initialize the coeffs' vector to all 0s */
	for (int i = 0; i < coords->size(); i++)
		coeffs->push_back(0.);

	/* Almost useless, makes the debugging easier */
	for (vector<pair<double, double> >::iterator ite = coords->begin(); ite != coords->end(); ++ite) {
		coords_x.push_back(ite->first);
		coords_y.push_back(ite->second);
		tmp_divert[0].push_back(ite->second);
	}

	divert.push_back(tmp_divert[0].data()[0]);

	if (coords_x.size() != coords_y.size())
		throw NextException("What exactly happened, here? o_O");

	/* Calculate the divided differences, using two vectors for the calculations */
	int skip = 1;
	int used_vector = 0;
	while (divert.size() < coords->size()) {

		/* 'skip' holds how many "jumps" we must do in the x vector to find the divisor */
		for (int i = 1; i < tmp_divert[used_vector].size(); i++)
			tmp_divert[1 - used_vector].push_back(
					(tmp_divert[used_vector].data()[i] - tmp_divert[used_vector].data()[i - 1]) /
					(coords_x.data()[(i-1) + skip] - coords_x.data()[i-1])
			);

		/* after that, the divided difference we want, is stored as the first element of the vector */
		divert.push_back(tmp_divert[1-used_vector].data()[0]);

		/* we can now clear the "old" vector, because we'll use it again */
		tmp_divert[used_vector].clear();

		used_vector++;
		if (used_vector == 2)
			used_vector = 0;

		skip++;
	}

#ifdef DEBUG
	for (vector<double>::iterator ite = divert.begin(); ite != divert.end(); ++ite)
		DPRINTF("%.5f ", *ite);
	DPRINTF("\n");
#endif

	try {
		/* Now we're building the polynom */
		vector<double>* polynom = new vector<double>();

		coeffs->data()[coeffs->size()-1] += divert.data()[0] + (divert.data()[1] * (coords_x.data()[0] * -1));
		coeffs->data()[coeffs->size()-2] += divert.data()[1];

		for (int i = 1; i < coords_x.size()-1; i++) {

			/* If the divided difference is 0, is quite useless to do further calculations */
			if (divert.data()[i+1] == 0)
				continue;

			polynom->clear();
			polynom->push_back(1);
			polynom->push_back(coords_x.data()[i] * -1);

			DPRINTF("%.f (x - %.f) ", divert.data()[i+1], coords_x.data()[i]);

			for (int k = i-1; k >= 0; k--) {
				vector<double> m_vec;
				m_vec.push_back(divert.data()[i+1]);
				m_vec.push_back((coords_x.data()[k] * divert.data()[i+1]) * -1);

				polynom = MultiplyVectors(*polynom, m_vec);

				DPRINTF("(x %.f) ", m_vec.data()[1]);
			}

			DPRINTF("=");

			/* Fill the empty polynom positions with 0s */
			while (polynom->size() < coeffs->size())
				polynom->insert(polynom->begin(), 0.);

			/* Insert the Coeffs */
			for (int j = 0; j < polynom->size(); j++) {
				DPRINTF(" %.f", polynom->data()[j]);
				coeffs->data()[j] += polynom->data()[j];
			}

			DPRINTF("\n");
		}

		delete(polynom);
	}
	catch (NextException & e) {
		return false;
	}

#ifdef DEBUG
	DPRINTF("COEFF\n");

	for (vector<double>::iterator ite = coeffs->begin(); ite != coeffs->end(); ++ite)
		DPRINTF("%.f ", *ite);


	DPRINTF("\n");
#endif

	return true;
}
示例#2
0
/*
OPWEIGHTEDL2: Solves weighted L2 regularized inverse problems.
Minimizes the cost function
X* = argmin_X ||A(X)-b_FC||_2^2 + lambda ||W |D(X)| ||_2^2
where     X* = recovered image
          A  = linear measurement operator
          b_FC  = (noisy) measurements
                 %           W  = diagonal weight matrix built from the edge mask
          |D(X)| = gradient magnitude at each pixel

Inputs:  A = function handle representing the forward
              model/measurement operator
         At = function handle representing the backwards model/
              the transpose of the measurment operator.
              (e.g. if A is a downsampling, At is a upsampling)
         b_FC =  a vector of measurements; should match the
              dimensions of A(X)
         lambda = regularization parameter that balances data fidelity
              and smoothness. set lambda high for more smoothing.
         siz = output image size, e.g. siz = [512,512]
         Niter = is the number of iterations; should be ~100-500

Output:  X = high-resolution output image
         cost = array of cost function value vs. iteration
Define AtA fourier mask
PrecisionType lambda, uvec ind_samples, frowvec res, int Niter, double tol, PrecisionType gam, FloatImageType::Pointer& X, frowvec& cost, frowvec& resvec)
 */
FloatImageType::Pointer OpWeightedL2(FloatImageType::Pointer norm01_lowres, FloatImageType::Pointer edgemask)
{
  const PrecisionType lambda = 1e-3F ;
  constexpr int Niter = 100;
  const PrecisionType tol = 1e-8F ;

  const PrecisionType gam = 1.0F ;

  //typedef itk::VectorMagnitudeImageFilter<CVImageType, FloatImageType> GMType;

  //The optimal filter for modeling the measurement operator is low pass filter in this case
  // NOTE: That the A operator is a projection operator, so A^{T}A = A, That is to say that applying
  //       the A^{T} to A results in A.
  FloatImageType::Pointer p_image = GetDiracDeltaImage(edgemask);
  // Precompute

  //Make high-res coefficients
  const HalfHermetianImageType::Pointer b_FC = GetAFP_of_b(norm01_lowres, edgemask);
  //TODO: too many copies of Atb here.
  FloatImageType::Pointer Atb = At_fhp(b_FC,
                                       edgemask->GetLargestPossibleRegion().GetSize()[0]%2 == 1,
                                       edgemask.GetPointer());
  FloatImageType::Pointer TwoAtb = MakeTwoAtb(Atb);
  FloatImageType::Pointer X = DeepImageCopy<FloatImageType>(Atb);
  Atb = nullptr; //Save memory here

  CVImageType::Pointer DX = GetGradient(X);
  CVImageType::Pointer L = CreateEmptyImage<CVImageType>(DX);
  CVImageType::Pointer Y = CreateEmptyImage<CVImageType>(DX);
  //CVImageType::Pointer WDX = CreateEmptyImage<CVImageType>(DX);
  CVImageType::Pointer residue = CreateEmptyImage<CVImageType>(DX);
  CVImageType::Pointer YminusL = CreateEmptyImage<CVImageType>(DX);
  FloatImageType::Pointer tempValue=CreateEmptyImage<FloatImageType>(DX);

  std::vector<PrecisionType> resvec(Niter,0);
  std::vector<PrecisionType> cost(Niter,0);

#ifdef USE_WRITE_DEGUBBING
  itk::ComplexToModulusImageFilter<HalfHermetianImageType,FloatImageType>::Pointer cpx2abs =
  itk::ComplexToModulusImageFilter<HalfHermetianImageType,FloatImageType>::New();
#endif

  CVImageType::Pointer gradIm = GetGradient(p_image);
  FloatImageType::Pointer divIm = GetDivergence(gradIm);
  HalfHermetianImageType::Pointer DtDhat = GetForwardFFT(divIm);
  // TODO:  ALL SAME TO HERE!
  typedef HalfHermetianImageType::PixelType FCType;
  HalfHermetianImageType::Pointer TwoTimesAtAhatPlusLamGamDtDhat = CreateEmptyImage<HalfHermetianImageType>(DtDhat);
  {
    HalfHermetianImageType::Pointer TwoTimesAtAhat = GetLowpassOperator(norm01_lowres,p_image, 2.0F);
    TwoTimesAtAhatPlusLamGamDtDhat = opIC(TwoTimesAtAhatPlusLamGamDtDhat,FCType(lambda*gam),'*',DtDhat);
    //TODO:  Make This an inverse!
    TwoTimesAtAhatPlusLamGamDtDhat = opII(TwoTimesAtAhatPlusLamGamDtDhat,TwoTimesAtAhat,'+',TwoTimesAtAhatPlusLamGamDtDhat);
  }
  p_image = nullptr; //Save memory

  const bool edgemask_ActualXDimensionIsOdd = edgemask->GetLargestPossibleRegion().GetSize()[0] % 2 == 1;

  CVImageType::Pointer InvTwoMuPlusGamma = ComputeInvTwoMuPlusGamma(edgemask,gam);
  //FloatImageType::Pointer SqrtMu = ComputeSqrtMu(edgemask);

#define USE_BLAS_WRAPPERS
#ifdef USE_BLAS_WRAPPERS
#else
  typedef itk::AddImageFilter<CVImageType,CVImageType> CVImageAdder;
  CVImageAdder::Pointer dxPlusL = CVImageAdder::New();
#endif

  itk::TimeProbe tp;
  tp.Start();

  HalfHermetianImageType::Pointer tempRatioFC = CreateEmptyImage<HalfHermetianImageType>(DtDhat);

  for (size_t i=0; i < Niter; ++i)
  {
    std::cout << "Iteration : " << i << std::endl;

#ifdef USE_BLAS_WRAPPERS
    //Z = 1.0*L+DX
    AddAllElements(DX,1.0F,L,DX,gam);//DX destroyed
    CVImageType::Pointer & Z = DX;
#else
    //Z = opII(Z,DX,'+',L);
    dxPlusL->SetInput1(DX);
    dxPlusL->SetInput2(L);
    dxPlusL->SetInPlace(true);
    dxPlusL->Update();
    CVImageType::Pointer Z=dxPlusL->GetOutput();
    MultiplyCVByScalar(Z,gam);
#endif
#ifdef USE_BLAS_WRAPPERS
    //Y=InvTwoMuPlusGamm.*Z
    MultiplyVectors(Y,InvTwoMuPlusGamma,Z);
#else
    Y = opII(Y,Z,'*',InvTwoMuPlusGamma);
#endif

    // X Subprob
    // Numerator = 2*Atb+lambda*gam*SRdiv(Y-L))
#ifdef USE_BLAS_WRAPPERS
    //YminusL = 1.0F* SRdiv( -1.0F*L + Y)
    Duplicate(Y,YminusL);
    AddAllElements(YminusL,-1.0F,L,YminusL,1.0F);
#else
    YminusL=opII(YminusL,Y,'-',L);
#endif
    FloatImageType::Pointer tempNumerator=GetDivergence(YminusL);
#ifdef USE_BLAS_WRAPPERS
    //lambd*gam*tempNumerator+TwoAtb
    Duplicate(TwoAtb,tempValue);
    AddAllElements(tempValue,lambda*gam,tempNumerator,tempValue,1.0F);
    HalfHermetianImageType::Pointer tempNumeratorFC = GetForwardFFT(tempValue);
#else
    tempNumerator=opIC(tempNumerator,lambda*gam,'*',tempNumerator);
    tempNumerator=opII(tempNumerator,TwoAtb,'+',tempNumerator);
    HalfHermetianImageType::Pointer tempNumeratorFC = GetForwardFFT(tempNumerator);
#endif

    //KEEP
    tempRatioFC = opII_scalar(tempRatioFC,tempNumeratorFC,'/',TwoTimesAtAhatPlusLamGamDtDhat);

    X = GetInverseFFT(tempRatioFC,edgemask_ActualXDimensionIsOdd,1.0); //TODO: Determine scale factor here. X

    // should be on same dynamic range as b
    DX = GetGradient(X);
    residue = opII(residue, DX, '-', Y); //TODO:  Implement math graph output here
    L = opII(L,L,'+',residue);

    //
    resvec[i] = 0; //TODO: Figure out the math for here
    if ( i > 900000 )
    {
      tp.Stop();
      std::cout << " Only iterations " << tp.GetTotal() << tp.GetUnit() << std::endl;
      return X;
    }
    if( i > 99 ) //HACK: Cutting this function short
    {
      return X;
    }
    //WDX = opII_CVmult(WDX,SqrtMu,'*',DX);
    //diff = opII(diff,A_fhp(X,norm01_lowres.GetPointer()),'-',b_FC);
    //
    //cost[i] = 0; //TODO: Need to figure out math for here
  }
  return X;
}