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

📄 sba_levmar.c

📁 sparse bundle ajustment的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
///////////////////////////////////////////////////////////////////////////////////// ////  Expert drivers for sparse bundle adjustment based on the////  Levenberg - Marquardt minimization algorithm////  Copyright (C) 2004-2008 Manolis Lourakis (lourakis at ics forth gr)////  Institute of Computer Science, Foundation for Research & Technology - Hellas////  Heraklion, Crete, Greece.////////  This program is free software; you can redistribute it and/or modify////  it under the terms of the GNU General Public License as published by////  the Free Software Foundation; either version 2 of the License, or////  (at your option) any later version.////////  This program is distributed in the hope that it will be useful,////  but WITHOUT ANY WARRANTY; without even the implied warranty of////  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the////  GNU General Public License for more details.///////////////////////////////////////////////////////////////////////////////////////#include <stdio.h>#include <stdlib.h>#include <string.h>#include <math.h>#include <float.h>#include "compiler.h"#include "sba.h"#include "sba_chkjac.h"#define SBA_EPSILON       1E-12#define SBA_EPSILON_SQ    ( (SBA_EPSILON)*(SBA_EPSILON) )#define SBA_ONE_THIRD     0.3333333334 /* 1.0/3.0 */#define emalloc(sz)       emalloc_(__FILE__, __LINE__, sz)#define FABS(x)           (((x)>=0)? (x) : -(x))#define ROW_MAJOR         0#define COLUMN_MAJOR      1#define MAT_STORAGE       COLUMN_MAJOR/* contains information necessary for computing a finite difference approximation to a jacobian, * e.g. function to differentiate, problem dimensions and pointers to working memory buffers */struct fdj_data_x_ {  void (*func)(double *p, struct sba_crsm *idxij, int *rcidxs, int *rcsubs, double *hx, void *adata); /* function to differentiate */  int cnp, pnp, mnp;  /* parameter numbers */  int *func_rcidxs,      *func_rcsubs;   /* working memory for func invocations.                       * Notice that this has to be different                       * than the working memory used for                       * evaluating the jacobian!                       */  double *hx, *hxx;   /* memory to save results in */  void *adata;};/* auxiliary memory allocation routine with error checking */inline static void *emalloc_(char *file, int line, size_t sz){void *ptr;  ptr=(void *)malloc(sz);  if(ptr==NULL){    fprintf(stderr, "SBA: memory allocation request for %u bytes failed in file %s, line %d, exiting", sz, file, line);    exit(1);  }  return ptr;}/* auxiliary routine for clearing an array of doubles */inline static void _dblzero(register double *arr, register int count){  while(--count>=0)    *arr++=0.0;}/* auxiliary routine for computing the mean reprojection error; used for debugging */static double sba_mean_repr_error(int n, int mnp, double *x, double *hx, struct sba_crsm *idxij, int *rcidxs, int *rcsubs){register int i, j;int nnz, nprojs;double *ptr1, *ptr2;double err;  for(i=nprojs=0, err=0.0; i<n; ++i){    nnz=sba_crsm_row_elmidxs(idxij, i, rcidxs, rcsubs); /* find nonzero x_ij, j=0...m-1 */    nprojs+=nnz;    for(j=0; j<nnz; ++j){ /* point i projecting on camera rcsubs[j] */      ptr1=x + idxij->val[rcidxs[j]]*mnp;      ptr2=hx + idxij->val[rcidxs[j]]*mnp;      err+=sqrt((ptr1[0]-ptr2[0])*(ptr1[0]-ptr2[0]) + (ptr1[1]-ptr2[1])*(ptr1[1]-ptr2[1]));    }  }  return err/((double)(nprojs));}/* print the solution in p using sba's text format. If cnp/pnp==0 only points/cameras are printed */static void sba_print_sol(int n, int m, double *p, int cnp, int pnp, double *x, int mnp, struct sba_crsm *idxij, int *rcidxs, int *rcsubs){register int i, j, ii;int nnz;double *ptr;  if(cnp){    /* print camera parameters */    for(j=0; j<m; ++j){      ptr=p+cnp*j;      for(ii=0; ii<cnp; ++ii)        printf("%g ", ptr[ii]);      printf("\n");    }  }  if(pnp){    /* 3D & 2D point parameters */    printf("\n\n\n# X Y Z  nframes  frame0 x0 y0  frame1 x1 y1 ...\n");    for(i=0; i<n; ++i){      ptr=p+cnp*m+i*pnp;      for(ii=0; ii<pnp; ++ii) // print 3D coordinates        printf("%g ", ptr[ii]);      nnz=sba_crsm_row_elmidxs(idxij, i, rcidxs, rcsubs); /* find nonzero x_ij, j=0...m-1 */      printf("%d ", nnz);      for(j=0; j<nnz; ++j){ /* point i projecting on camera rcsubs[j] */        ptr=x + idxij->val[rcidxs[j]]*mnp;        printf("%d ", rcsubs[j]);        for(ii=0; ii<mnp; ++ii) // print 2D coordinates          printf("%g ", ptr[ii]);      }      printf("\n");    }  }}/* Compute e=x-y for two n-vectors x and y and return the squared L2 norm of e. * e can coincide with either x or y.  * Uses loop unrolling and blocking to reduce bookkeeping overhead & pipeline * stalls and increase instruction-level parallelism; see http://www.abarnett.demon.co.uk/tutorial.html */static double nrmL2xmy(double *const e, const double *const x, const double *const y, const int n){const int blocksize=8, bpwr=3; /* 8=2^3 */register int i;int j1, j2, j3, j4, j5, j6, j7;int blockn;register double sum0=0.0, sum1=0.0, sum2=0.0, sum3=0.0;  /* n may not be divisible by blocksize,    * go as near as we can first, then tidy up.   */  blockn = (n>>bpwr)<<bpwr; /* (n / blocksize) * blocksize; */  /* unroll the loop in blocks of `blocksize'; looping downwards gains some more speed */  for(i=blockn-1; i>0; i-=blocksize){            e[i ]=x[i ]-y[i ]; sum0+=e[i ]*e[i ];    j1=i-1; e[j1]=x[j1]-y[j1]; sum1+=e[j1]*e[j1];    j2=i-2; e[j2]=x[j2]-y[j2]; sum2+=e[j2]*e[j2];    j3=i-3; e[j3]=x[j3]-y[j3]; sum3+=e[j3]*e[j3];    j4=i-4; e[j4]=x[j4]-y[j4]; sum0+=e[j4]*e[j4];    j5=i-5; e[j5]=x[j5]-y[j5]; sum1+=e[j5]*e[j5];    j6=i-6; e[j6]=x[j6]-y[j6]; sum2+=e[j6]*e[j6];    j7=i-7; e[j7]=x[j7]-y[j7]; sum3+=e[j7]*e[j7];  }  /*   * There may be some left to do.   * This could be done as a simple for() loop,    * but a switch is faster (and more interesting)    */  i=blockn;  if(i<n){   /* Jump into the case at the place that will allow   * us to finish off the appropriate number of items.    */    switch(n - i){       case 7 : e[i]=x[i]-y[i]; sum0+=e[i]*e[i]; ++i;      case 6 : e[i]=x[i]-y[i]; sum0+=e[i]*e[i]; ++i;      case 5 : e[i]=x[i]-y[i]; sum0+=e[i]*e[i]; ++i;      case 4 : e[i]=x[i]-y[i]; sum0+=e[i]*e[i]; ++i;      case 3 : e[i]=x[i]-y[i]; sum0+=e[i]*e[i]; ++i;      case 2 : e[i]=x[i]-y[i]; sum0+=e[i]*e[i]; ++i;      case 1 : e[i]=x[i]-y[i]; sum0+=e[i]*e[i]; ++i;    }  }  return sum0+sum1+sum2+sum3;}/* Compute e=W*(x-y) for two n-vectors x and y and return the squared L2 norm of e. * This norm equals the squared C norm of x-y with C=W^T*W, W being block diagonal * matrix with nvis mnp*mnp blocks: e^T*e=(x-y)^T*W^T*W*(x-y)=||x-y||_C. * Note that n=nvis*mnp; e can coincide with either x or y. * * Similarly to nrmL2xmy() above, uses loop unrolling and blocking */static double nrmCxmy(double *const e, const double *const x, const double *const y,                      const double *const W, const int mnp, const int nvis){const int n=nvis*mnp;const int blocksize=8, bpwr=3; /* 8=2^3 */register int i, ii, k;int j1, j2, j3, j4, j5, j6, j7;int blockn, mnpsq;register double norm, sum;register const double *Wptr, *auxptr;register double *eptr;  /* n may not be divisible by blocksize,    * go as near as we can first, then tidy up.   */  blockn = (n>>bpwr)<<bpwr; /* (n / blocksize) * blocksize; */  /* unroll the loop in blocks of `blocksize'; looping downwards gains some more speed */  for(i=blockn-1; i>0; i-=blocksize){            e[i ]=x[i ]-y[i ];    j1=i-1; e[j1]=x[j1]-y[j1];    j2=i-2; e[j2]=x[j2]-y[j2];    j3=i-3; e[j3]=x[j3]-y[j3];    j4=i-4; e[j4]=x[j4]-y[j4];    j5=i-5; e[j5]=x[j5]-y[j5];    j6=i-6; e[j6]=x[j6]-y[j6];    j7=i-7; e[j7]=x[j7]-y[j7];  }  /*   * There may be some left to do.   * This could be done as a simple for() loop,    * but a switch is faster (and more interesting)    */  i=blockn;  if(i<n){   /* Jump into the case at the place that will allow   * us to finish off the appropriate number of items.    */    switch(n - i){       case 7 : e[i]=x[i]-y[i]; ++i;      case 6 : e[i]=x[i]-y[i]; ++i;      case 5 : e[i]=x[i]-y[i]; ++i;      case 4 : e[i]=x[i]-y[i]; ++i;      case 3 : e[i]=x[i]-y[i]; ++i;      case 2 : e[i]=x[i]-y[i]; ++i;      case 1 : e[i]=x[i]-y[i]; ++i;    }  }  /* compute w_x_ij e_ij in e and its L2 norm.   * Since w_x_ij is upper triangular, the products can be safely saved   * directly in e_ij, without the need for intermediate storage   */  mnpsq=mnp*mnp;  /* Wptr, eptr point to w_x_ij, e_ij below */  for(i=0, Wptr=W, eptr=e, norm=0.0; i<nvis; ++i, Wptr+=mnpsq, eptr+=mnp){    for(ii=0, auxptr=Wptr; ii<mnp; ++ii, auxptr+=mnp){ /* auxptr=Wptr+ii*mnp */      for(k=ii, sum=0.0; k<mnp; ++k) // k>=ii since w_x_ij is upper triangular        sum+=auxptr[k]*eptr[k]; //Wptr[ii*mnp+k]*eptr[k];      eptr[ii]=sum;      norm+=sum*sum;    }  }  return norm;}/* search for & print image projection components that are infinite; useful for identifying errors */static void sba_print_inf(double *hx, int nimgs, int mnp, struct sba_crsm *idxij, int *rcidxs, int *rcsubs){register int i, j, k;int nnz;double *phxij;  for(j=0; j<nimgs; ++j){    nnz=sba_crsm_col_elmidxs(idxij, j, rcidxs, rcsubs); /* find nonzero hx_ij, i=0...n-1 */    for(i=0; i<nnz; ++i){      phxij=hx + idxij->val[rcidxs[i]]*mnp;      for(k=0; k<mnp; ++k)        if(!SBA_FINITE(phxij[k]))          printf("SBA: component %d of the estimated projection of point %d on camera %d is invalid!\n", k, rcsubs[i], j);    }  }}/* Given a parameter vector p made up of the 3D coordinates of n points and the parameters of m cameras, compute in * jac the jacobian of the predicted measurements, i.e. the jacobian of the projections of 3D points in the m images. * The jacobian is approximated with the aid of finite differences and is returned in the order * (A_11, B_11, ..., A_1m, B_1m, ..., A_n1, B_n1, ..., A_nm, B_nm), * where A_ij=dx_ij/da_j and B_ij=dx_ij/db_i (see HZ). * Notice that depending on idxij, some of the A_ij, B_ij might be missing * * Problem-specific information is assumed to be stored in a structure pointed to by "dat". * * NOTE: The jacobian (for n=4, m=3) in matrix form has the following structure: *       A_11  0     0     B_11 0    0    0 *       0     A_12  0     B_12 0    0    0 *       0     0     A_13  B_13 0    0    0 *       A_21  0     0     0    B_21 0    0 *       0     A_22  0     0    B_22 0    0 *       0     0     A_23  0    B_23 0    0 *       A_31  0     0     0    0    B_31 0 *       0     A_32  0     0    0    B_32 0 *       0     0     A_33  0    0    B_33 0 *       A_41  0     0     0    0    0    B_41 *       0     A_42  0     0    0    0    B_42 *       0     0     A_43  0    0    0    B_43 *       To reduce the total number of objective function evaluations, this structure can be *       exploited as follows: A certain d is added to the j-th parameters of all cameras and *       the objective function is evaluated at the resulting point. This evaluation suffices

⌨️ 快捷键说明

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