⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sba_levmar.c

📁 sparse bundle ajustment的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
 *       to compute the corresponding columns of *all* A_ij through finite differences. A similar *       strategy allows the computation of the B_ij. Overall, only cnp+pnp+1 objective function *       evaluations are needed to compute the jacobian, much fewer compared to the m*cnp+n*pnp+1 *       that would be required by the naive strategy of computing one column of the jacobian *       per function evaluation. See Nocedal-Wright, ch. 7, pp. 169. Although this approach is *       much faster compared to the naive strategy, it is not preferable to analytic jacobians, *       since the latter are considerably faster to compute and result in fewer LM iterations. */static void sba_fdjac_x(    double *p,                /* I: current parameter estimate, (m*cnp+n*pnp)x1 */    struct sba_crsm *idxij,   /* I: sparse matrix containing the location of x_ij in hx */    int    *rcidxs,           /* work array for the indexes of nonzero elements of a single sparse matrix row/column */    int    *rcsubs,           /* work array for the subscripts of nonzero elements in a single sparse matrix row/column */    double *jac,              /* O: array for storing the approximated jacobian */    void   *dat)              /* I: points to a "fdj_data_x_" structure */{  register int i, j, ii, jj;  double *pa, *pb, *pqr, *ppt;  register double *pAB, *phx, *phxx;  int n, m, nm, nnz, Asz, Bsz, ABsz, idx;  double *tmpd;  register double d;  struct fdj_data_x_ *fdjd;  void (*func)(double *p, struct sba_crsm *idxij, int *rcidxs, int *rcsubs, double *hx, void *adata);  double *hx, *hxx;  int cnp, pnp, mnp;  void *adata;  /* retrieve problem-specific information passed in *dat */  fdjd=(struct fdj_data_x_ *)dat;  func=fdjd->func;  cnp=fdjd->cnp; pnp=fdjd->pnp; mnp=fdjd->mnp;  hx=fdjd->hx;  hxx=fdjd->hxx;  adata=fdjd->adata;  n=idxij->nr; m=idxij->nc;  pa=p; pb=p+m*cnp;  Asz=mnp*cnp; Bsz=mnp*pnp; ABsz=Asz+Bsz;  nm=(n>=m)? n : m; // max(n, m);  tmpd=(double *)emalloc(nm*sizeof(double));  (*func)(p, idxij, fdjd->func_rcidxs, fdjd->func_rcsubs, hx, adata); // evaluate supplied function on current solution  if(cnp){ // is motion varying?    /* compute A_ij */    for(jj=0; jj<cnp; ++jj){      for(j=0; j<m; ++j){        pqr=pa+j*cnp; // j-th camera parameters        /* determine d=max(SBA_DELTA_SCALE*|pqr[jj]|, SBA_MIN_DELTA), see HZ */        d=(double)(SBA_DELTA_SCALE)*pqr[jj]; // force evaluation        d=FABS(d);        if(d<SBA_MIN_DELTA) d=SBA_MIN_DELTA;        tmpd[j]=d;        pqr[jj]+=d;      }      (*func)(p, idxij, fdjd->func_rcidxs, fdjd->func_rcsubs, hxx, adata);      for(j=0; j<m; ++j){        pqr=pa+j*cnp; // j-th camera parameters        pqr[jj]-=tmpd[j]; /* restore */        d=1.0/tmpd[j]; /* invert so that divisions can be carried out faster as multiplications */        nnz=sba_crsm_col_elmidxs(idxij, j, rcidxs, rcsubs); /* find nonzero A_ij, i=0...n-1 */        for(i=0; i<nnz; ++i){          idx=idxij->val[rcidxs[i]];          phx=hx + idx*mnp; // set phx to point to hx_ij          phxx=hxx + idx*mnp; // set phxx to point to hxx_ij          pAB=jac + idx*ABsz; // set pAB to point to A_ij          for(ii=0; ii<mnp; ++ii)            pAB[ii*cnp+jj]=(phxx[ii]-phx[ii])*d;        }      }    }  }  if(pnp){ // is structure varying?    /* compute B_ij */    for(jj=0; jj<pnp; ++jj){      for(i=0; i<n; ++i){        ppt=pb+i*pnp; // i-th point parameters        /* determine d=max(SBA_DELTA_SCALE*|ppt[jj]|, SBA_MIN_DELTA), see HZ */        d=(double)(SBA_DELTA_SCALE)*ppt[jj]; // force evaluation        d=FABS(d);        if(d<SBA_MIN_DELTA) d=SBA_MIN_DELTA;        tmpd[i]=d;        ppt[jj]+=d;      }      (*func)(p, idxij, fdjd->func_rcidxs, fdjd->func_rcsubs, hxx, adata);      for(i=0; i<n; ++i){        ppt=pb+i*pnp; // i-th point parameters        ppt[jj]-=tmpd[i]; /* restore */        d=1.0/tmpd[i]; /* invert so that divisions can be carried out faster as multiplications */        nnz=sba_crsm_row_elmidxs(idxij, i, rcidxs, rcsubs); /* find nonzero B_ij, j=0...m-1 */        for(j=0; j<nnz; ++j){          idx=idxij->val[rcidxs[j]];          phx=hx + idx*mnp; // set phx to point to hx_ij          phxx=hxx + idx*mnp; // set phxx to point to hxx_ij          pAB=jac + idx*ABsz + Asz; // set pAB to point to B_ij          for(ii=0; ii<mnp; ++ii)            pAB[ii*pnp+jj]=(phxx[ii]-phx[ii])*d;        }      }    }  }  free(tmpd);}typedef int (*PLS)(double *A, double *B, double *x, int m, int iscolmaj);/* Bundle adjustment on camera and structure parameters  * 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_motstr_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, b1, ..., bn).                   * aj are the image j parameters, bi are the i-th point parameters,                   * size m*cnp + n*pnp                   */    const int cnp,/* number of parameters for ONE camera; e.g. 6 for Euclidean cameras */    const int pnp,/* number of parameters for ONE point; e.g. 3 for Euclidean points */    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 + n*pnp)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,                                               *  dx_11/db_1, ..., dx_1m/db_1, ..., dx_n1/db_n, ..., dx_nm/db_n), or (using HZ's notation),                                               * jac=(A_11, B_11, ..., A_1m, B_1m, ..., A_n1, B_n1, ..., A_nm, B_nm)                                               * Notice that depending on idxij, some of the A_ij and B_ij might be missing.                                               * Note also that A_ij and B_ij are mnp x cnp and mnp x pnp matrices resp. 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, l;int nvis, nnz, retval;/* The following are work arrays that are dynamically allocated by sba_motstr_levmar_x() */double *jac;  /* work array for storing the jacobian, max. size n*m*(mnp*cnp + mnp*pnp) */double *U;    /* work array for storing the U_j in the order U_1, ..., U_m, size m*cnp*cnp */double *V;    /* work array for storing the *strictly upper triangles* of V_i in the order V_1, ..., V_n, size n*pnp*pnp.               * V also stores the lower triangles of (V*_i)^-1 in the order (V*_1)^-1, ..., (V*_n)^-1.               * Note that diagonal elements of V_1 are saved in diagUV               */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 *eab;  /* work array for storing the ea_j & eb_i in the order ea_1, .. ea_m eb_1, .. eb_n size m*cnp + n*pnp */double *E;   /* work array for storing the e_j in the order e_1, .. e_m, size m*cnp *//* Notice that the blocks W_ij, Y_ij are zero iff A_ij (equivalently B_ij) is zero. This means * that the matrix consisting of blocks W_ij is itself sparse, similarly to the * block matrix made up of the A_ij and B_ij (i.e. jac) */double *W;    /* work array for storing the W_ij in the order W_11, ..., W_1m, ..., W_n1, ..., W_nm,                 max. size n*m*cnp*pnp */double *Yj;   /* work array for storing the Y_ij for a *fixed* j in the order Y_1j, Y_nj,                 max. size n*cnp*pnp */double *YWt;  /* work array for storing \sum_i Y_ij W_ik^T, size cnp*cnp */double *S;    /* work array for storing the block array S_jk, size m*m*cnp*cnp */double *dp;   /* work array for storing the parameter vector updates da_1, ..., da_m, db_1, ..., db_n, size m*cnp + n*pnp */double *Wtda; /* work array for storing \sum_j W_ij^T da_j, size pnp */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, W, Yj, wght are sparse and * U, V, eab, E, S, dp are dense. Sparse arrays (except Yj) are indexed * through idxij (see below), that is with the same mechanism as the input  * measurements vector x */double *pa, *pb, *ea, *eb, *dpa, *dpb; /* pointers into p, jac, eab and dp respectively *//* submatrices sizes */int Asz, Bsz, ABsz, Usz, Vsz,    Wsz, Ysz, esz, easz, ebsz,    YWtsz, Wtdasz, Sblsz, covsz;int Sdim; /* S matrix actual dimension */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, B_ij in jac, 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 maxCvis, /* max. of projections of a single point  across cameras, <=m */    maxPvis, /* max. of projections in a single camera across points,  <=n */    maxCPvis, /* max. of the above */    *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 issolved;/* temporary work arrays that are dynamically allocated */double *hx,         /* \hat{x}_i, max. size m*n*mnp */       *diagUV,     /* diagonals of U_j, V_i, size m*cnp + n*pnp */       *pdp;        /* p + dp, size m*cnp + n*pnp */double *diagU, *diagV; /* pointers into diagUV */register double mu,  /* damping constant */                tmp; /* mainly used in matrix & vector multiplications */double p_eL2, eab_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;const int mmcon=m-mcon;PLS linsolver=NULL;int (*matinv)(double *A, int m)=NULL;struct fdj_data_x_ fdj_data;void *jac_adata;/* Initialization */  mu=eab_inf=0.0; /* -Wall */  /* block sizes */  Asz=mnp * cnp; Bsz=mnp * pnp; ABsz=Asz + Bsz;  Usz=cnp * cnp; Vsz=pnp * pnp;  Wsz=cnp * pnp; Ysz=cnp * pnp;  esz=mnp;  easz=cnp; ebsz=pnp;  YWtsz=cnp * cnp;  Wtdasz=pnp;  Sblsz=cnp * cnp;  Sdim=mmcon * 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 + n*pnp;  if(nobs<nvars){    fprintf(stderr, "SBA: sba_motstr_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){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -