📄 sba_levmar.c
字号:
for(i=0, dL=0.0; i<nvars; ++i) dL+=dp[i]*(mu*dp[i]+eab[i]); dF=p_eL2-pdp_eL2; if(verbose>1) printf("\ndamping term %8g, gain ratio %8g, errors %8g / %8g = %g\n", mu, dL!=0.0? dF/dL : dF/DBL_EPSILON, p_eL2/nvis, pdp_eL2/nvis, p_eL2/pdp_eL2); if(dL>0.0 && dF>0.0){ /* reduction in error, increment is accepted */ tmp=(2.0*dF/dL-1.0); tmp=1.0-tmp*tmp*tmp; mu=mu*( (tmp>=SBA_ONE_THIRD)? tmp : SBA_ONE_THIRD ); nu=2; /* the test below is equivalent to the relative reduction of the RMS reprojection error: sqrt(p_eL2)-sqrt(pdp_eL2)<eps4*sqrt(p_eL2) */ if(pdp_eL2-2.0*sqrt(p_eL2*pdp_eL2)<(eps4_sq-1.0)*p_eL2) stop=4; for(i=0; i<nvars; ++i) /* update p's estimate */ p[i]=pdp[i]; for(i=0; i<nobs; ++i) /* update e and ||e||_2 */ e[i]=hx[i]; p_eL2=pdp_eL2; break; } } /* issolved */moredamping: /* if this point is reached (also via an explicit goto!), either the linear system could * not be solved or the error did not reduce; in any case, the increment must be rejected */ mu*=nu; nu2=nu<<1; // 2*nu; if(nu2<=nu){ /* nu has wrapped around (overflown) */ fprintf(stderr, "SBA: too many failed attempts to increase the damping factor in sba_motstr_levmar_x()! Singular Hessian matrix?\n"); //exit(1); stop=6; break; } nu=nu2; /* restore U, V diagonal entries */ for(j=mcon; j<m; ++j){ ptr1=U + j*Usz; // set ptr1 to point to U_j ptr2=diagU + j*cnp; // set ptr2 to point to diagU_j for(i=0; i<cnp; ++i) ptr1[i*cnp+i]=ptr2[i]; } for(i=0; i<n; ++i){ ptr1=V + i*Vsz; // set ptr1 to point to V_i ptr2=diagV + i*pnp; // set ptr2 to point to diagV_i for(j=0; j<pnp; ++j) ptr1[j*pnp+j]=ptr2[j]; } } /* inner while loop */ if(p_eL2<=eps3_sq) stop=5; // error is small, force termination of outer loop } if(itno>=itmax) stop=3; /* restore U, V diagonal entries */ for(j=mcon; j<m; ++j){ ptr1=U + j*Usz; // set ptr1 to point to U_j ptr2=diagU + j*cnp; // set ptr2 to point to diagU_j for(i=0; i<cnp; ++i) ptr1[i*cnp+i]=ptr2[i]; } for(i=0; i<n; ++i){ ptr1=V + i*Vsz; // set ptr1 to point to V_i ptr2=diagV + i*pnp; // set ptr2 to point to diagV_i for(j=0; j<pnp; ++j) ptr1[j*pnp+j]=ptr2[j]; } if(info){ info[0]=init_p_eL2; info[1]=p_eL2; info[2]=eab_inf; info[3]=dp_L2; for(j=mcon, tmp=DBL_MIN; j<m; ++j){ ptr1=U + j*Usz; // set ptr1 to point to U_j for(i=0; i<cnp; ++i) if(tmp<ptr1[i*cnp+i]) tmp=ptr1[i*cnp+i]; } for(i=0; i<n; ++i){ ptr1=V + i*Vsz; // set ptr1 to point to V_i for(j=0; j<pnp; ++j) if(tmp<ptr1[j*pnp+j]) tmp=ptr1[j*pnp+j]; } info[4]=mu/tmp; info[5]=itno; info[6]=stop; info[7]=nfev; info[8]=njev; info[9]=nlss; } //sba_print_sol(n, m, p, cnp, pnp, x, mnp, &idxij, rcidxs, rcsubs); retval=(stop!=7)? itno : SBA_ERROR;freemem_and_return: /* NOTE: this point is also reached via a goto! */ /* free whatever was allocated */ free(W); free(U); free(V); free(e); free(eab); free(E); free(Yj); free(YWt); free(S); free(dp); free(Wtda); free(rcidxs); free(rcsubs);#ifndef SBA_DESTROY_COVS if(wght) free(wght);#else /* nothing to do */#endif /* SBA_DESTROY_COVS */ free(hx); free(diagUV); free(pdp); if(fdj_data.hxx){ // cleanup free(fdj_data.hxx); free(fdj_data.func_rcidxs); } sba_crsm_free(&idxij); /* free the memory allocated by the matrix inversion & linear solver routines */ if(matinv) (*matinv)(NULL, 0); if(linsolver) (*linsolver)(NULL, NULL, NULL, 0, 0); return retval;}/* Bundle adjustment on camera parameters only * using the sparse Levenberg-Marquardt as described in HZ p. 568 * * Returns the number of iterations (>=0) if successfull, SBA_ERROR if failed */int sba_mot_levmar_x( const int n, /* number of points */ const int m, /* number of images */ const int mcon,/* number of images (starting from the 1st) whose parameters should not be modified. * All A_ij (see below) with j<mcon are assumed to be zero */ char *vmask, /* visibility mask: vmask[i, j]=1 if point i visible in image j, 0 otherwise. nxm */ double *p, /* initial parameter vector p0: (a1, ..., am). * aj are the image j parameters, size m*cnp */ const int cnp,/* number of parameters for ONE camera; e.g. 6 for Euclidean cameras */ double *x, /* measurements vector: (x_11^T, .. x_1m^T, ..., x_n1^T, .. x_nm^T)^T where * x_ij is the projection of the i-th point on the j-th image. * NOTE: some of the x_ij might be missing, if point i is not visible in image j; * see vmask[i, j], max. size n*m*mnp */ double *covx, /* measurements covariance matrices: (Sigma_x_11, .. Sigma_x_1m, ..., Sigma_x_n1, .. Sigma_x_nm), * where Sigma_x_ij is the mnp x mnp covariance of x_ij stored row-by-row. Set to NULL if no * covariance estimates are available (identity matrices are implicitly used in this case). * NOTE: a certain Sigma_x_ij is missing if the corresponding x_ij is also missing; * see vmask[i, j], max. size n*m*mnp*mnp */ const int mnp,/* number of parameters for EACH measurement; usually 2 */ void (*func)(double *p, struct sba_crsm *idxij, int *rcidxs, int *rcsubs, double *hx, void *adata), /* functional relation describing measurements. Given a parameter vector p, * computes a prediction of the measurements \hat{x}. p is (m*cnp)x1, * \hat{x} is (n*m*mnp)x1, maximum * rcidxs, rcsubs are max(m, n) x 1, allocated by the caller and can be used * as working memory */ void (*fjac)(double *p, struct sba_crsm *idxij, int *rcidxs, int *rcsubs, double *jac, void *adata), /* function to evaluate the sparse jacobian dX/dp. * The Jacobian is returned in jac as * (dx_11/da_1, ..., dx_1m/da_m, ..., dx_n1/da_1, ..., dx_nm/da_m), or (using HZ's notation), * jac=(A_11, ..., A_1m, ..., A_n1, ..., A_nm) * Notice that depending on idxij, some of the A_ij might be missing. * Note also that the A_ij are mnp x cnp matrices and they * should be stored in jac in row-major order. * rcidxs, rcsubs are max(m, n) x 1, allocated by the caller and can be used * as working memory * * If NULL, the jacobian is approximated by repetitive func calls and finite * differences. This is computationally inefficient and thus NOT recommended. */ void *adata, /* pointer to possibly additional data, passed uninterpreted to func, fjac */ const int itmax, /* I: maximum number of iterations. itmax==0 signals jacobian verification followed by immediate return */ const int verbose, /* I: verbosity */ const double opts[SBA_OPTSSZ], /* I: minim. options [\mu, \epsilon1, \epsilon2, \epsilon3, \epsilon4]. Respectively the scale factor for initial \mu, * stopping thresholds for ||J^T e||_inf, ||dp||_2, ||e||_2 and (||e||_2-||e_new||_2)/||e||_2 */ double info[SBA_INFOSZ] /* O: information regarding the minimization. Set to NULL if don't care * info[0]=||e||_2 at initial p. * info[1-4]=[ ||e||_2, ||J^T e||_inf, ||dp||_2, mu/max[J^T J]_ii ], all computed at estimated p. * info[5]= # iterations, * info[6]=reason for terminating: 1 - stopped by small gradient J^T e * 2 - stopped by small dp * 3 - stopped by itmax * 4 - stopped by small relative reduction in ||e||_2 * 5 - stopped by small ||e||_2 * 6 - too many attempts to increase damping. Restart with increased mu * 7 - stopped by invalid (i.e. NaN or Inf) "func" values. This is a user error * info[7]= # function evaluations * info[8]= # jacobian evaluations * info[9]= # number of linear systems solved, i.e. number of attempts for reducing error */){register int i, j, ii, jj, k;int nvis, nnz, retval;/* The following are work arrays that are dynamically allocated by sba_mot_levmar_x() */double *jac; /* work array for storing the jacobian, max. size n*m*mnp*cnp */double *U; /* work array for storing the U_j in the order U_1, ..., U_m, size m*cnp*cnp */double *e; /* work array for storing the e_ij in the order e_11, ..., e_1m, ..., e_n1, ..., e_nm, max. size n*m*mnp */double *ea; /* work array for storing the ea_j in the order ea_1, .. ea_m, size m*cnp */double *dp; /* work array for storing the parameter vector updates da_1, ..., da_m, size m*cnp */double *wght= /* work array for storing the weights computed from the covariance inverses, max. size n*m*mnp*mnp */ NULL;/* Of the above arrays, jac, e, wght are sparse and * U, ea, dp are dense. Sparse arrays are indexed through * idxij (see below), that is with the same mechanism as the input * measurements vector x *//* submatrices sizes */int Asz, Usz, esz, easz, covsz;register double *ptr1, *ptr2, *ptr3, *ptr4, sum;struct sba_crsm idxij; /* sparse matrix containing the location of x_ij in x. This is also the location of A_ij * in jac, e_ij in e, etc. * This matrix can be thought as a map from a sparse set of pairs (i, j) to a continuous * index k and it is used to efficiently lookup the memory locations where the non-zero * blocks of a sparse matrix/vector are stored */int maxCPvis, /* max. of projections across cameras & projections across points */ *rcidxs, /* work array for the indexes corresponding to the nonzero elements of a single row or column in a sparse matrix, size max(n, m) */ *rcsubs; /* work array for the subscripts of nonzero elements in a single row or column of a sparse matrix, size max(n, m) *//* The following variables are needed by the LM algorithm */register int itno; /* iteration counter */int nsolved;/* temporary work arrays that are dynamically allocated */double *hx, /* \hat{x}_i, max. size m*n*mnp */ *diagU, /* diagonals of U_j, size m*cnp */ *pdp; /* p + dp, size m*cnp */register double mu, /* damping constant */ tmp; /* mainly used in matrix & vector multiplications */double p_eL2, ea_inf, pdp_eL2; /* ||e(p)||_2, ||J^T e||_inf, ||e(p+dp)||_2 */double p_L2, dp_L2=DBL_MAX, dF, dL;double tau=FABS(opts[0]), eps1=FABS(opts[1]), eps2=FABS(opts[2]), eps2_sq=opts[2]*opts[2], eps3_sq=opts[3]*opts[3], eps4_sq=opts[4]*opts[4];double init_p_eL2;int nu=2, nu2, stop=0, nfev, njev=0, nlss=0;int nobs, nvars;PLS linsolver=NULL;struct fdj_data_x_ fdj_data;void *jac_adata;/* Initialization */ mu=ea_inf=0.0; /* -Wall */ /* block sizes */ Asz=mnp * cnp; Usz=cnp * cnp; esz=mnp; easz=cnp; covsz=mnp * mnp; /* count total number of visible image points */ for(i=nvis=0, jj=n*m; i<jj; ++i) nvis+=(vmask[i]!=0); nobs=nvis*mnp; nvars=m*cnp; if(nobs<nvars){ fprintf(stderr, "SBA: sba_mot_levmar_x() cannot solve a problem with fewer measurements [%d] than unknowns [%d]\n", nobs, nvars); return SBA_ERROR; } /* allocate & fill up the idxij structure */ sba_crsm_alloc(&idxij, n, m, nvis); for(i=k=0; i<n; ++i){ idxij.rowptr[i]=k; ii=i*m; for(j=0; j<m; ++j) if(vmask[ii+j]){ idxij.val[k]=k; idxij.colidx[k++]=j; } } idxij.rowptr[n]=nvis; /* find the maximum number of visible image points in any single camera or coming from a single 3D point */ /* cameras */ for(i=maxCPvis=0; i<n; ++i) if((k=idxij.rowptr[i+1]-idxij.rowptr[i])>maxCPvis) maxCPvis=k; /* points, note that maxCPvis is not reinitialized! */ for(j=0; j<m; ++j){ for(i=ii=0; i<n; ++i) if(vmask[i*m+j]) ++ii; if(ii>maxCPvis) maxCPvis=ii; } /* allocate work arrays */ jac=(double *)emalloc(nvis*Asz*sizeof(double)); U=(double *)emalloc(m*Usz*sizeof(double)); e=(double *)emalloc(nobs*sizeof(double)); ea=(double *)emalloc(nvars*sizeof(double)); dp=(double *)emalloc(nvars*sizeof(double)); rcidxs=(int *)emalloc
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -