source: proiecte/pmake3d/make3d_original/Make3dSingleImageStanford_version0.1/third_party/sba-1.3/sba_chkjac.c @ 37

Last change on this file since 37 was 37, checked in by (none), 14 years ago

Added original make3d

File size: 16.1 KB
Line 
1/////////////////////////////////////////////////////////////////////////////////
2////
3////  Verification routines for the jacobians employed in the expert & simple drivers
4////  for sparse bundle adjustment based on the Levenberg - Marquardt minimization algorithm
5////  Copyright (C) 2005  Manolis Lourakis (lourakis@ics.forth.gr)
6////  Institute of Computer Science, Foundation for Research & Technology - Hellas
7////  Heraklion, Crete, Greece.
8////
9////  This program is free software; you can redistribute it and/or modify
10////  it under the terms of the GNU General Public License as published by
11////  the Free Software Foundation; either version 2 of the License, or
12////  (at your option) any later version.
13////
14////  This program is distributed in the hope that it will be useful,
15////  but WITHOUT ANY WARRANTY; without even the implied warranty of
16////  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17////  GNU General Public License for more details.
18////
19///////////////////////////////////////////////////////////////////////////////////
20
21#include <stdio.h>
22#include <stdlib.h>
23#include <math.h>
24#include <float.h>
25
26#include "sba.h"
27
28#define emalloc(sz)       emalloc_(__FILE__, __LINE__, sz)
29
30#define FABS(x)           (((x)>=0)? (x) : -(x))
31
32
33/* inline */
34#ifdef _MSC_VER
35#define inline __inline //MSVC
36#elif !defined(__GNUC__)
37#define inline //other than MSVC, GCC: define empty
38#endif
39
40/* auxiliary memory allocation routine with error checking */
41inline static void *emalloc_(char *file, int line, size_t sz)
42{
43void *ptr;
44
45  ptr=(void *)malloc(sz);
46  if(ptr==NULL){
47    fprintf(stderr, "memory allocation request for %u bytes failed in file %s, line %d, exiting", sz, file, line);
48    exit(1);
49  }
50
51  return ptr;
52}
53
54/*
55 * Check the jacobian of a projection function in nvars variables
56 * evaluated at a point p, for consistency with the function itself.
57 * Expert version
58 *
59 * Based on fortran77 subroutine CHKDER by
60 * Burton S. Garbow, Kenneth E. Hillstrom, Jorge J. More
61 * Argonne National Laboratory. MINPACK project. March 1980.
62 *
63 *
64 * func points to a function from R^{nvars} --> R^{nobs}: Given a p in R^{nvars}
65 *      it yields hx in R^{nobs}
66 * jacf points to a function implementing the jacobian of func, whose consistency with
67 *     func is to be tested. Given a p in R^{nvars}, jacf computes into the nvis*(Asz+Bsz)
68 *     matrix jac the jacobian of func at p. Note the jacobian is sparse, consisting of
69 *     all A_ij, B_ij and that row i of jac corresponds to the gradient of the i-th
70 *     component of func, evaluated at p.
71 * p is an input array of length nvars containing the point of evaluation.
72 * idxij, rcidxs, rcsubs, mcon, cnp, pnp, mnp are as usual. Note that if cnp=0 or
73 *     pnp=0 a jacobian corresponding resp. to motion or camera parameters
74 *     only is assumed.
75 * func_adata, jac_adata point to possible additional data and are passed
76 *     uninterpreted to func, jacf respectively.
77 * err is an array of length nobs. On output, err contains measures
78 *     of correctness of the respective gradients. if there is
79 *     no severe loss of significance, then if err[i] is 1.0 the
80 *     i-th gradient is correct, while if err[i] is 0.0 the i-th
81 *     gradient is incorrect. For values of err between 0.0 and 1.0,
82 *     the categorization is less certain. In general, a value of
83 *     err[i] greater than 0.5 indicates that the i-th gradient is
84 *     probably correct, while a value of err[i] less than 0.5
85 *     indicates that the i-th gradient is probably incorrect.
86 *
87 * CAUTION: THIS FUNCTION IS NOT 100% FOOLPROOF. The
88 * following excerpt comes from CHKDER's documentation:
89 *
90 *     "The function does not perform reliably if cancellation or
91 *     rounding errors cause a severe loss of significance in the
92 *     evaluation of a function. therefore, none of the components
93 *     of p should be unusually small (in particular, zero) or any
94 *     other value which may cause loss of significance."
95 */
96
97void sba_motstr_chkjac_x(
98    void (*func)(double *p, struct sba_crsm *idxij, int *rcidxs, int *rcsubs, double *hx, void *adata),
99    void (*jacf)(double *p, struct sba_crsm *idxij, int *rcidxs, int *rcsubs, double *jac, void *adata),
100    double *p, struct sba_crsm *idxij, int *rcidxs, int *rcsubs, int mcon, int cnp, int pnp, int mnp, void *func_adata, void *jac_adata)
101{
102const double factor=100.0, one=1.0, zero=0.0;
103double *fvec, *fjac, *pp, *fvecp, *buf, *err;
104
105int nvars, nobs, m, n, Asz, Bsz, nnz;
106register int i, j, ii, jj;
107double eps, epsf, temp, epsmch, epslog;
108register double *ptr1, *ptr2, *pab;
109double *pa, *pb;
110int fvec_sz, pp_sz, fvecp_sz, numerr=0;
111
112  nobs=idxij->nnz*mnp;
113  n=idxij->nr; m=idxij->nc;
114  nvars=m*cnp + n*pnp;
115  epsmch=DBL_EPSILON;
116  eps=sqrt(epsmch);
117
118  Asz=mnp*cnp; Bsz=mnp*pnp;
119  fjac=(double *)emalloc(idxij->nnz*(Asz+Bsz)*sizeof(double));
120
121  fvec_sz=fvecp_sz=nobs;
122  pp_sz=nvars;
123  buf=(double *)emalloc((fvec_sz + pp_sz + fvecp_sz)*sizeof(double));
124  fvec=buf;
125  pp=fvec+fvec_sz;
126  fvecp=pp+pp_sz;
127
128  err=(double *)emalloc(nobs*sizeof(double));
129
130  /* compute fvec=func(p) */
131  (*func)(p, idxij, rcidxs, rcsubs, fvec, func_adata);
132
133  /* compute the jacobian at p */
134  (*jacf)(p, idxij, rcidxs, rcsubs, fjac, jac_adata);
135
136  /* compute pp */
137  for(j=0; j<nvars; ++j){
138    temp=eps*FABS(p[j]);
139    if(temp==zero) temp=eps;
140    pp[j]=p[j]+temp;
141  }
142
143  /* compute fvecp=func(pp) */
144  (*func)(pp, idxij, rcidxs, rcsubs, fvecp, func_adata);
145
146  epsf=factor*epsmch;
147  epslog=log10(eps);
148
149  for(i=0; i<nobs; ++i)
150    err[i]=zero;
151
152  pa=p;
153  pb=p + m*cnp;
154  for(i=0; i<n; ++i){
155    nnz=sba_crsm_row_elmidxs(idxij, i, rcidxs, rcsubs); /* find nonzero A_ij, B_ij, j=0...m-1, actual column numbers in rcsubs */
156    for(j=0; j<nnz; ++j){
157      if(rcsubs[j]<mcon) continue; // A_ij, B_ij are zero
158 
159      ptr2=err + idxij->val[rcidxs[j]]*mnp; // set ptr2 to point into err
160
161      if(cnp){
162        ptr1=fjac + idxij->val[rcidxs[j]]*Asz; // set ptr1 to point to A_ij
163        pab=pa + rcsubs[j]*cnp;
164        for(jj=0; jj<cnp; ++jj){
165          temp=FABS(pab[jj]);
166          if(temp==zero) temp=one;
167
168          for(ii=0; ii<mnp; ++ii)
169            ptr2[ii]+=temp*ptr1[ii*cnp+jj];
170        }
171      }
172
173      if(pnp){
174        ptr1=fjac + idxij->nnz*Asz + idxij->val[rcidxs[j]]*Bsz; // set ptr1 to point to B_ij
175        pab=pb + i*pnp;
176        for(jj=0; jj<pnp; ++jj){
177          temp=FABS(pab[jj]);
178          if(temp==zero) temp=one;
179
180          for(ii=0; ii<mnp; ++ii)
181            ptr2[ii]+=temp*ptr1[ii*pnp+jj];
182        }
183      }
184    }
185  }
186
187  for(i=0; i<nobs; ++i){
188    temp=one;
189    if(fvec[i]!=zero && fvecp[i]!=zero && FABS(fvecp[i]-fvec[i])>=epsf*FABS(fvec[i]))
190        temp=eps*FABS((fvecp[i]-fvec[i])/eps - err[i])/(FABS(fvec[i])+FABS(fvecp[i]));
191    err[i]=one;
192    if(temp>epsmch && temp<eps)
193        err[i]=(log10(temp) - epslog)/epslog;
194    if(temp>=eps) err[i]=zero;
195  }
196
197  free(fjac);
198  free(buf);
199
200  for(i=0; i<n; ++i){
201    nnz=sba_crsm_row_elmidxs(idxij, i, rcidxs, rcsubs); /* find nonzero err_ij, j=0...m-1 */
202    for(j=0; j<nnz; ++j){
203      if(rcsubs[j]<mcon) continue; // corresponding gradients are taken to be zero
204
205      ptr1=err + idxij->val[rcidxs[j]]*mnp; // set ptr1 to point into err
206      for(ii=0; ii<mnp; ++ii)
207        if(ptr1[ii]<=0.5){
208          fprintf(stderr, "Gradient %d (corresponding to element %d of the projection of point %d on camera %d) is %s (err=%g)\n",
209                  idxij->val[rcidxs[j]]*mnp+ii, ii, i, rcsubs[j], (ptr1[ii]==0.0)? "wrong" : "probably wrong", ptr1[ii]);
210          ++numerr;
211        }
212    }
213  }
214  if(numerr) fprintf(stderr, "Found %d suspicious gradients out of %d\n\n", numerr, nobs);
215
216  free(err);
217
218  return;
219}
220
221void sba_mot_chkjac_x(
222    void (*func)(double *p, struct sba_crsm *idxij, int *rcidxs, int *rcsubs, double *hx, void *adata),
223    void (*jacf)(double *p, struct sba_crsm *idxij, int *rcidxs, int *rcsubs, double *jac, void *adata),
224    double *p, struct sba_crsm *idxij, int *rcidxs, int *rcsubs, int mcon, int cnp, int mnp, void *func_adata, void *jac_adata)
225{
226  sba_motstr_chkjac_x(func, jacf, p, idxij, rcidxs, rcsubs, mcon, cnp, 0, mnp, func_adata, jac_adata);
227}
228
229void sba_str_chkjac_x(
230    void (*func)(double *p, struct sba_crsm *idxij, int *rcidxs, int *rcsubs, double *hx, void *adata),
231    void (*jacf)(double *p, struct sba_crsm *idxij, int *rcidxs, int *rcsubs, double *jac, void *adata),
232    double *p, struct sba_crsm *idxij, int *rcidxs, int *rcsubs, int pnp, int mnp, void *func_adata, void *jac_adata)
233{
234  sba_motstr_chkjac_x(func, jacf, p, idxij, rcidxs, rcsubs, 0, 0, pnp, mnp, func_adata, jac_adata);
235}
236
237#if 0
238/* Routines for directly checking the jacobians supplied to the simple drivers.
239 * They shouldn't be necessary since these jacobians can be verified indirectly
240 * through the expert sba_XXX_chkjac_x() routines.
241 */
242
243/*****************************************************************************************/
244// Sample code for using sba_motstr_chkjac():
245
246  for(i=0; i<n; ++i)
247    for(j=mcon; j<m; ++j){
248      if(!vmask[i*m+j]) continue; // point i does not appear in image j
249
250    sba_motstr_chkjac(proj, projac, p+j*cnp, p+m*cnp+i*pnp, j, i, cnp, pnp, mnp, adata, adata);
251  }
252
253
254/*****************************************************************************************/
255
256
257/* union used for passing pointers to the user-supplied functions for the motstr/mot/str simple drivers */
258union proj_projac{
259  struct{
260    void (*proj)(int j, int i, double *aj, double *bi, double *xij, void *adata);
261    void (*projac)(int j, int i, double *aj, double *bi, double *Aij, double *Bij, void *adata);
262  } motstr;
263
264  struct{
265    void (*proj)(int j, int i, double *aj, double *xij, void *adata);
266    void (*projac)(int j, int i, double *aj, double *Aij, void *adata);
267  } mot;
268
269  struct{
270    void (*proj)(int j, int i, double *bi, double *xij, void *adata);
271    void (*projac)(int j, int i, double *bi, double *Bij, void *adata);
272  } str;
273};
274
275
276/*
277 * Check the jacobian of a projection function in cnp+pnp variables
278 * evaluated at a point p, for consistency with the function itself.
279 * Simple version of the above, NOT to be called directly
280 *
281 * Based on fortran77 subroutine CHKDER by
282 * Burton S. Garbow, Kenneth E. Hillstrom, Jorge J. More
283 * Argonne National Laboratory. MINPACK project. March 1980.
284 *
285 *
286 * proj points to a function from R^{cnp+pnp} --> R^{mnp}: Given a p=(aj, bi) in R^{cnp+pnp}
287 *      it yields hx in R^{mnp}
288 * projac points to a function implementing the jacobian of func, whose consistency with proj
289 *     is to be tested. Given a p in R^{cnp+pnp}, jacf computes into the matrix jac=[Aij | Bij]
290 *     jacobian of proj at p. Note that row i of jac corresponds to the gradient of the i-th
291 *     component of proj, evaluated at p.
292 * aj, bi are input arrays of lengths cnp, pnp containing the parameters for the point of
293 *     evaluation, i.e. j-th camera and i-th point
294 * jj, ii specify the point (ii) whose projection jacobian in image (jj) is being checked
295 * cnp, pnp, mnp are as usual. Note that if cnp=0 or
296 *     pnp=0 a jacobian corresponding resp. to motion or camera parameters
297 *     only is assumed.
298 * func_adata, jac_adata point to possible additional data and are passed
299 *     uninterpreted to func, jacf respectively.
300 * err is an array of length mnp. On output, err contains measures
301 *     of correctness of the respective gradients. if there is
302 *     no severe loss of significance, then if err[i] is 1.0 the
303 *     i-th gradient is correct, while if err[i] is 0.0 the i-th
304 *     gradient is incorrect. For values of err between 0.0 and 1.0,
305 *     the categorization is less certain. In general, a value of
306 *     err[i] greater than 0.5 indicates that the i-th gradient is
307 *     probably correct, while a value of err[i] less than 0.5
308 *     indicates that the i-th gradient is probably incorrect.
309 *
310 * CAUTION: THIS FUNCTION IS NOT 100% FOOLPROOF. The
311 * following excerpt comes from CHKDER's documentation:
312 *
313 *     "The function does not perform reliably if cancellation or
314 *     rounding errors cause a severe loss of significance in the
315 *     evaluation of a function. therefore, none of the components
316 *     of p should be unusually small (in particular, zero) or any
317 *     other value which may cause loss of significance."
318 */
319
320static void sba_chkjac(
321    union proj_projac *funcs, double *aj, double *bi, int jj, int ii, int cnp, int pnp, int mnp, void *func_adata, void *jac_adata)
322{
323const double factor=100.0, one=1.0, zero=0.0;
324double *fvec, *fjac, *Aij, *Bij, *ajp, *bip, *fvecp, *buf, *err;
325
326int Asz, Bsz;
327register int i, j;
328double eps, epsf, temp, epsmch, epslog;
329int fvec_sz, ajp_sz, bip_sz, fvecp_sz, err_sz, numerr=0;
330
331  epsmch=DBL_EPSILON;
332  eps=sqrt(epsmch);
333
334  Asz=mnp*cnp; Bsz=mnp*pnp;
335  fjac=(double *)emalloc((Asz+Bsz)*sizeof(double));
336  Aij=fjac;
337  Bij=Aij+Asz;
338
339  fvec_sz=fvecp_sz=mnp;
340  ajp_sz=cnp; bip_sz=pnp;
341  err_sz=mnp;
342  buf=(double *)emalloc((fvec_sz + ajp_sz + bip_sz + fvecp_sz + err_sz)*sizeof(double));
343  fvec=buf;
344  ajp=fvec+fvec_sz;
345  bip=ajp+ajp_sz;
346  fvecp=bip+bip_sz;
347  err=fvecp+fvecp_sz;
348
349  /* compute fvec=proj(p), p=(aj, bi) & the jacobian at p */
350  if(cnp && pnp){
351    (*(funcs->motstr.proj))(jj, ii, aj, bi, fvec, func_adata);
352    (*(funcs->motstr.projac))(jj, ii, aj, bi, Aij, Bij, jac_adata);
353  }
354  else if(cnp){
355    (*(funcs->mot.proj))(jj, ii, aj, fvec, func_adata);
356    (*(funcs->mot.projac))(jj, ii, aj, Aij, jac_adata);
357  }
358  else{
359    (*(funcs->str.proj))(jj, ii, bi, fvec, func_adata);
360    (*(funcs->str.projac))(jj, ii, bi, Bij, jac_adata);
361  }
362
363  /* compute pp, pp=(ajp, bip) */
364  for(j=0; j<cnp; ++j){
365    temp=eps*FABS(aj[j]);
366    if(temp==zero) temp=eps;
367    ajp[j]=aj[j]+temp;
368  }
369  for(j=0; j<pnp; ++j){
370    temp=eps*FABS(bi[j]);
371    if(temp==zero) temp=eps;
372    bip[j]=bi[j]+temp;
373  }
374
375  /* compute fvecp=proj(pp) */
376  if(cnp && pnp)
377    (*(funcs->motstr.proj))(jj, ii, ajp, bip, fvecp, func_adata);
378  else if(cnp)
379    (*(funcs->mot.proj))(jj, ii, ajp, fvecp, func_adata);
380  else
381    (*(funcs->str.proj))(jj, ii, bip, fvecp, func_adata);
382
383  epsf=factor*epsmch;
384  epslog=log10(eps);
385
386  for(i=0; i<mnp; ++i)
387    err[i]=zero;
388
389  for(j=0; j<cnp; ++j){
390    temp=FABS(aj[j]);
391    if(temp==zero) temp=one;
392
393    for(i=0; i<mnp; ++i)
394      err[i]+=temp*Aij[i*cnp+j];
395  }
396  for(j=0; j<pnp; ++j){
397    temp=FABS(bi[j]);
398    if(temp==zero) temp=one;
399
400    for(i=0; i<mnp; ++i)
401      err[i]+=temp*Bij[i*pnp+j];
402  }
403
404  for(i=0; i<mnp; ++i){
405    temp=one;
406    if(fvec[i]!=zero && fvecp[i]!=zero && FABS(fvecp[i]-fvec[i])>=epsf*FABS(fvec[i]))
407        temp=eps*FABS((fvecp[i]-fvec[i])/eps - err[i])/(FABS(fvec[i])+FABS(fvecp[i]));
408    err[i]=one;
409    if(temp>epsmch && temp<eps)
410        err[i]=(log10(temp) - epslog)/epslog;
411    if(temp>=eps) err[i]=zero;
412  }
413
414  for(i=0; i<mnp; ++i)
415    if(err[i]<=0.5){
416      fprintf(stderr, "Gradient %d (corresponding to element %d of the projection of point %d on camera %d) is %s (err=%g)\n",
417                i, i, ii, jj, (err[i]==0.0)? "wrong" : "probably wrong", err[i]);
418      ++numerr;
419  }
420  if(numerr) fprintf(stderr, "Found %d suspicious gradients out of %d\n\n", numerr, mnp);
421
422  free(fjac);
423  free(buf);
424
425  return;
426}
427
428void sba_motstr_chkjac(
429    void (*proj)(int jj, int ii, double *aj, double *bi, double *xij, void *adata),
430    void (*projac)(int jj, int ii, double *aj, double *bi, double *Aij, double *Bij, void *adata),
431    double *aj, double *bi, int jj, int ii, int cnp, int pnp, int mnp, void *func_adata, void *jac_adata)
432{
433union proj_projac funcs;
434
435  funcs.motstr.proj=proj;
436  funcs.motstr.projac=projac;
437
438  sba_chkjac(&funcs, aj, bi, jj, ii, cnp, pnp, mnp, func_adata, jac_adata);
439}
440
441void sba_mot_chkjac(
442    void (*proj)(int jj, int ii, double *aj, double *xij, void *adata),
443    void (*projac)(int jj, int ii, double *aj, double *Aij, void *adata),
444    double *aj, double *bi, int jj, int ii, int cnp, int pnp, int mnp, void *func_adata, void *jac_adata)
445{
446union proj_projac funcs;
447
448  funcs.mot.proj=proj;
449  funcs.mot.projac=projac;
450
451  sba_chkjac(&funcs, aj, NULL, jj, ii, cnp, 0, mnp, func_adata, jac_adata);
452}
453
454void sba_str_chkjac(
455    void (*proj)(int jj, int ii, double *bi, double *xij, void *adata),
456    void (*projac)(int jj, int ii, double *bi, double *Bij, void *adata),
457    double *aj, double *bi, int jj, int ii, int cnp, int pnp, int mnp, void *func_adata, void *jac_adata)
458{
459union proj_projac funcs;
460
461  funcs.str.proj=proj;
462  funcs.str.projac=projac;
463
464  sba_chkjac(&funcs, NULL, bi, jj, ii, 0, pnp, mnp, func_adata, jac_adata);
465}
466#endif /* 0 */
Note: See TracBrowser for help on using the repository browser.