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

📄 sba_levmar.c

📁 sba, a C/C++ package for generic sparse bundle adjustment is almost invariably used as the last step
💻 C
📖 第 1 页 / 共 5 页
字号:
    }/*if(!(itno%100)){  printf("Current estimate: ");  for(i=0; i<nvars; ++i)    printf("%.9g ", p[i]);  printf("-- errors %.9g %0.9g\n", eab_inf, p_eL2);}*/    /* check for convergence */    if((eab_inf <= eps1)){      dp_L2=0.0; /* no increment for p in this case */      stop=1;      break;    }   /* compute initial damping factor */    if(itno==0){      for(i=mcon*cnp, tmp=DBL_MIN; i<nvars; ++i)        if(diagUV[i]>tmp) tmp=diagUV[i]; /* find max diagonal element */      mu=tau*tmp;    }    /* determine increment using adaptive damping */    while(1){      /* augment U, V */      for(j=mcon; j<m; ++j){        ptr1=U + j*Usz; // set ptr1 to point to U_j        for(i=0; i<cnp; ++i)          ptr1[i*cnp+i]+=mu;      }      for(i=0; i<n; ++i){        ptr1=V + i*Vsz; // set ptr1 to point to V_i        for(j=0; j<pnp; ++j)          ptr1[j*pnp+j]+=mu;		    /* compute V*_i^-1.         * Recall that only the upper triangle of the symmetric pnp x pnp matrix V*_i         * is stored in ptr1; its (also symmetric) inverse is saved in the lower triangle of ptr1         */        /* inverting V*_i with LDLT seems to result in faster overall execution compared to when using LU or Cholesky */        //j=sba_symat_invert_LU(ptr1, pnp); matinv=sba_symat_invert_LU;        //j=sba_symat_invert_Chol(ptr1, pnp); matinv=sba_symat_invert_Chol;        j=sba_symat_invert_BK(ptr1, pnp); matinv=sba_symat_invert_BK;		    if(!j){			    fprintf(stderr, "SBA: singular matrix V*_i (i=%d) in sba_motstr_levmar_x(), increasing damping\n", i);          goto moredamping; // increasing damping will eventually make V*_i diagonally dominant, thus nonsingular          //retval=SBA_ERROR;          //goto freemem_and_return;		    }      }      _dblzero(E, m*easz); /* clear all e_j */      /* compute the mmcon x mmcon block matrix S and e_j */      /* Note that S is symmetric, therefore its computation can be       * sped up by computing only the upper part and then reusing       * it for the lower one.		   */      for(j=mcon; j<m; ++j){        int mmconxUsz=mmcon*Usz;		    nnz=sba_crsm_col_elmidxs(&idxij, j, rcidxs, rcsubs); /* find nonzero Y_ij, i=0...n-1 */        /* compute all Y_ij = W_ij (V*_i)^-1 for a *fixed* j.         * To save memory, the block matrix consisting of the Y_ij         * is not stored. Instead, only a block column of this matrix         * is computed & used at each time: For each j, all nonzero         * Y_ij are computed in Yj and then used in the calculations         * involving S_jk and e_j.         * Recall that W_ij is cnp x pnp and (V*_i) is pnp x pnp         */        for(i=0; i<nnz; ++i){          /* set ptr3 to point to (V*_i)^-1, actual row number in rcsubs[i] */          ptr3=V + rcsubs[i]*Vsz;          /* set ptr1 to point to Y_ij, actual row number in rcsubs[i] */          ptr1=Yj + i*Ysz;          /* set ptr2 to point to W_ij resp. */          ptr2=W + idxij.val[rcidxs[i]]*Wsz;          /* compute W_ij (V*_i)^-1 and store it in Y_ij.           * Recall that only the lower triangle of (V*_i)^-1 is stored           */          for(ii=0; ii<cnp; ++ii){            ptr4=ptr2+ii*pnp;            for(jj=0; jj<pnp; ++jj){              for(k=0, sum=0.0; k<=jj; ++k)                sum+=ptr4[k]*ptr3[jj*pnp+k]; //ptr2[ii*pnp+k]*ptr3[jj*pnp+k];              for( ; k<pnp; ++k)                sum+=ptr4[k]*ptr3[k*pnp+jj]; //ptr2[ii*pnp+k]*ptr3[k*pnp+jj];              ptr1[ii*pnp+jj]=sum;            }          }        }        /* compute the UPPER TRIANGULAR PART of S */        for(k=j; k<m; ++k){ // j>=mcon          /* compute \sum_i Y_ij W_ik^T in YWt. Note that for an off-diagonal block defined by j, k           * YWt (and thus S_jk) is nonzero only if there exists a point that is visible in both the           * j-th and k-th images           */                    /* Recall that Y_ij is cnp x pnp and W_ik is cnp x pnp */           _dblzero(YWt, YWtsz); /* clear YWt */          for(i=0; i<nnz; ++i){            register double *pYWt;            /* find the min and max column indices of the elements in row i (actually rcsubs[i])             * and make sure that k falls within them. This test handles W_ik's which are             * certain to be zero without bothering to call sba_crsm_elmidx()             */            ii=idxij.colidx[idxij.rowptr[rcsubs[i]]];            jj=idxij.colidx[idxij.rowptr[rcsubs[i]+1]-1];            if(k<ii || k>jj) continue; /* W_ik == 0 */            /* set ptr2 to point to W_ik */            l=sba_crsm_elmidxp(&idxij, rcsubs[i], k, j, rcidxs[i]);            //l=sba_crsm_elmidx(&idxij, rcsubs[i], k);            if(l==-1) continue; /* W_ik == 0 */            ptr2=W + idxij.val[l]*Wsz;            /* set ptr1 to point to Y_ij, actual row number in rcsubs[i] */            ptr1=Yj + i*Ysz;            for(ii=0; ii<cnp; ++ii){              ptr3=ptr1+ii*pnp;              pYWt=YWt+ii*cnp;              for(jj=0; jj<cnp; ++jj){                ptr4=ptr2+jj*pnp;                for(l=0, sum=0.0; l<pnp; ++l)                  sum+=ptr3[l]*ptr4[l]; //ptr1[ii*pnp+l]*ptr2[jj*pnp+l];                pYWt[jj]+=sum; //YWt[ii*cnp+jj]+=sum;              }            }          }		  		      /* since the linear system involving S is solved with lapack,		       * it is preferable to store S in column major (i.e. fortran)		       * order, so as to avoid unecessary transposing/copying.           */#if MAT_STORAGE==COLUMN_MAJOR          ptr2=S + (k-mcon)*mmconxUsz + (j-mcon)*cnp; // set ptr2 to point to the beginning of block j,k in S#else          ptr2=S + (j-mcon)*mmconxUsz + (k-mcon)*cnp; // set ptr2 to point to the beginning of block j,k in S#endif		            if(j!=k){ /* Kronecker */            for(ii=0; ii<cnp; ++ii, ptr2+=Sdim)              for(jj=0; jj<cnp; ++jj)                ptr2[jj]=#if MAT_STORAGE==COLUMN_MAJOR				                -YWt[jj*cnp+ii];#else				                -YWt[ii*cnp+jj];#endif          }          else{            ptr1=U + j*Usz; // set ptr1 to point to U_j            for(ii=0; ii<cnp; ++ii, ptr2+=Sdim)              for(jj=0; jj<cnp; ++jj)                ptr2[jj]=#if MAT_STORAGE==COLUMN_MAJOR				                ptr1[jj*cnp+ii] - YWt[jj*cnp+ii];#else				                ptr1[ii*cnp+jj] - YWt[ii*cnp+jj];#endif          }        }        /* copy the LOWER TRIANGULAR PART of S from the upper one */        for(k=mcon; k<j; ++k){#if MAT_STORAGE==COLUMN_MAJOR          ptr1=S + (k-mcon)*mmconxUsz + (j-mcon)*cnp; // set ptr1 to point to the beginning of block j,k in S          ptr2=S + (j-mcon)*mmconxUsz + (k-mcon)*cnp; // set ptr2 to point to the beginning of block k,j in S#else          ptr1=S + (j-mcon)*mmconxUsz + (k-mcon)*cnp; // set ptr1 to point to the beginning of block j,k in S          ptr2=S + (k-mcon)*mmconxUsz + (j-mcon)*cnp; // set ptr2 to point to the beginning of block k,j in S#endif          for(ii=0; ii<cnp; ++ii, ptr1+=Sdim)            for(jj=0, ptr3=ptr2+ii; jj<cnp; ++jj, ptr3+=Sdim)              ptr1[jj]=*ptr3;        }        /* compute e_j=ea_j - \sum_i Y_ij eb_i */        /* Recall that Y_ij is cnp x pnp and eb_i is pnp x 1 */        ptr1=E + j*easz; // set ptr1 to point to e_j        for(i=0; i<nnz; ++i){          /* set ptr2 to point to Y_ij, actual row number in rcsubs[i] */          ptr2=Yj + i*Ysz;          /* set ptr3 to point to eb_i */          ptr3=eb + rcsubs[i]*ebsz;          for(ii=0; ii<cnp; ++ii){            ptr4=ptr2+ii*pnp;            for(jj=0, sum=0.0; jj<pnp; ++jj)              sum+=ptr4[jj]*ptr3[jj]; //ptr2[ii*pnp+jj]*ptr3[jj];            ptr1[ii]+=sum;          }        }        ptr2=ea + j*easz; // set ptr2 to point to ea_j        for(i=0; i<easz; ++i)          ptr1[i]=ptr2[i] - ptr1[i];      }#if 0      if(verbose>1){ /* count the nonzeros in S */        for(i=ii=0; i<Sdim*Sdim; ++i)          if(S[i]!=0.0) ++ii;        printf("\nS density: %.5g\n", ((double)ii)/(Sdim*Sdim)); fflush(stdout);      }#endif      /* solve the linear system S dpa = E to compute the da_j.       *       * Note that if MAT_STORAGE==1 S is modified in the following call;       * this is OK since S is recomputed for each iteration       */	    //issolved=sba_Axb_LU(S, E+mcon*cnp, dpa+mcon*cnp, Sdim, MAT_STORAGE); linsolver=sba_Axb_LU;      issolved=sba_Axb_Chol(S, E+mcon*cnp, dpa+mcon*cnp, Sdim, MAT_STORAGE); linsolver=sba_Axb_Chol;      //issolved=sba_Axb_BK(S, E+mcon*cnp, dpa+mcon*cnp, Sdim, MAT_STORAGE); linsolver=sba_Axb_BK;      //issolved=sba_Axb_QRnoQ(S, E+mcon*cnp, dpa+mcon*cnp, Sdim, MAT_STORAGE); linsolver=sba_Axb_QRnoQ;      //issolved=sba_Axb_QR(S, E+mcon*cnp, dpa+mcon*cnp, Sdim, MAT_STORAGE); linsolver=sba_Axb_QR;	    //issolved=sba_Axb_SVD(S, E+mcon*cnp, dpa+mcon*cnp, Sdim, MAT_STORAGE); linsolver=sba_Axb_SVD;	    //issolved=sba_Axb_CG(S, E+mcon*cnp, dpa+mcon*cnp, Sdim, (3*Sdim)/2, 1E-10, SBA_CG_JACOBI, MAT_STORAGE); linsolver=(PLS)sba_Axb_CG;      ++nlss;	    _dblzero(dpa, mcon*cnp); /* no change for the first mcon camera params */      if(issolved){        /* compute the db_i */        for(i=0; i<n; ++i){          ptr1=dpb + i*ebsz; // set ptr1 to point to db_i          /* compute \sum_j W_ij^T da_j */          /* Recall that W_ij is cnp x pnp and da_j is cnp x 1 */          _dblzero(Wtda, Wtdasz); /* clear Wtda */          nnz=sba_crsm_row_elmidxs(&idxij, i, rcidxs, rcsubs); /* find nonzero W_ij, j=0...m-1 */          for(j=0; j<nnz; ++j){            /* set ptr2 to point to W_ij, actual column number in rcsubs[j] */			      if(rcsubs[j]<mcon) continue; /* W_ij is zero */            ptr2=W + idxij.val[rcidxs[j]]*Wsz;            /* set ptr3 to point to da_j */            ptr3=dpa + rcsubs[j]*cnp;            for(ii=0; ii<pnp; ++ii){              ptr4=ptr2+ii;              for(jj=0, sum=0.0; jj<cnp; ++jj)                sum+=ptr4[jj*pnp]*ptr3[jj]; //ptr2[jj*pnp+ii]*ptr3[jj];              Wtda[ii]+=sum;            }          }          /* compute eb_i - \sum_j W_ij^T da_j = eb_i - Wtda in Wtda */          ptr2=eb + i*ebsz; // set ptr2 to point to eb_i          for(ii=0; ii<pnp; ++ii)            Wtda[ii]=ptr2[ii] - Wtda[ii];          /* compute the product (V*_i)^-1 Wtda = (V*_i)^-1 (eb_i - \sum_j W_ij^T da_j).           * Recall that only the lower triangle of (V*_i)^-1 is stored           */          ptr2=V + i*Vsz; // set ptr2 to point to (V*_i)^-1          for(ii=0; ii<pnp; ++ii){            for(jj=0, sum=0.0; jj<=ii; ++jj)              sum+=ptr2[ii*pnp+jj]*Wtda[jj];            for( ; jj<pnp; ++jj)              sum+=ptr2[jj*pnp+ii]*Wtda[jj];            ptr1[ii]=sum;          }        }        /* parameter vector updates are now in dpa, dpb */        /* compute p's new estimate and ||dp||^2 */        for(i=0, dp_L2=0.0; i<nvars; ++i){          pdp[i]=p[i] + (tmp=dp[i]);          dp_L2+=tmp*tmp;        }        //dp_L2=sqrt(dp_L2);        if(dp_L2<=eps2_sq*p_L2){ /* relative change in p is small, stop */        //if(dp_L2<=eps2*(p_L2 + eps2)){ /* relative change in p is small, stop */          stop=2;          break;        }        if(dp_L2>=(p_L2+eps2)/SBA_EPSILON_SQ){ /* almost singular */        //if(dp_L2>=(p_L2+eps2)/SBA_EPSILON){ /* almost singular */          fprintf(stderr, "SBA: the matrix of the augmented normal equations is almost singular in sba_motstr_levmar_x(),\n"                          "     minimization should be restarted from the current solution with an increased damping term\n");          retval=SBA_ERROR;          goto freemem_and_return;       }        (*func)(pdp, &idxij, rcidxs, rcsubs, hx, adata); ++nfev; /* evaluate function at p + dp */        if(verbose>1)          printf("mean reprojection error %g\n", sba_mean_repr_error(n, mnp, x, hx, &idxij, rcidxs, rcsubs));        /* ### compute ||e(pdp)||_2 */        if(covx==NULL)          pdp_eL2=nrmL2xmy(hx, x, hx, nobs); /* hx=x-hx, pdp_eL2=||hx|| */        else          pdp_eL2=nrmCxmy(hx, x, hx, wght, mnp, nvis); /* hx=wght*(x-hx), pdp_eL2=||hx|| */        if(!SBA_FINITE(pdp_eL2)){          if(verbose) /* identify the offending point projection */            sba_print_inf(hx, m, mnp, &idxij, rcidxs, rcsubs);          stop=7;          break;        }

⌨️ 快捷键说明

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