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; }
/* 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; }