/* Given a parameter vector p made up of the 3D coordinates of n points, 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 returned in the order (B_11, ..., B_1m, ..., B_n1, ..., B_nm), where B_ij=dx_ij/db_i (see HZ).
 * Caller supplies rcidxs and rcsubs which can be used as working memory.
 * Notice that depending on idxij, some of the B_ij might be missing
 *
 */
static void sba_str_Qs_jac(double *p, struct sba_crsm *idxij, int *rcidxs, int *rcsubs, double *jac, void *adata)
{
  register int i, j;
  int pnp, mnp;
  double *pbi, *pBij;
  //int n;
  int m, nnz, Bsz, idx;
  struct wrap_str_data_ *wdata;
  void (*projac)(int j, int i, double *bi, double *Bij, void *projac_adata);
  void *projac_adata;

  
  wdata=(struct wrap_str_data_ *)adata;
  pnp=wdata->pnp; mnp=wdata->mnp;
  projac=wdata->projac;
  projac_adata=wdata->adata;

  //n=idxij->nr;
  m=idxij->nc;
  Bsz=mnp*pnp;

  for(j=0; j<m; ++j){

    nnz=sba_crsm_col_elmidxs(idxij, j, rcidxs, rcsubs); /* find nonzero hx_ij, i=0...n-1 */

    for(i=0; i<nnz; ++i){
      pbi=p + rcsubs[i]*pnp;
      idx=idxij->val[rcidxs[i]];
      pBij=jac + idx*Bsz; // set pBij to point to B_ij

      (*projac)(j, rcsubs[i], pbi, pBij, projac_adata); // evaluate dQ/db in pBij
    }
  }
}
/* Given a parameter vector p made up of the 3D coordinates of n points and the parameters of m cameras, compute in
 * hx the prediction of the measurements, i.e. the projections of 3D points in the m images. The measurements
 * are returned in the order (hx_11^T, .. hx_1m^T, ..., hx_n1^T, .. hx_nm^T)^T, where hx_ij is the predicted
 * projection of the i-th point on the j-th camera.
 * Caller supplies rcidxs and rcsubs which can be used as working memory.
 * Notice that depending on idxij, some of the hx_ij might be missing
 *
 */
static void sba_motstr_Qs(double *p, struct sba_crsm *idxij, int *rcidxs, int *rcsubs, double *hx, void *adata)
{
  register int i, j;
  int cnp, pnp, mnp; 
  double *pa, *pb, *paj, *pbi, *pxij;
  int n, m, nnz;
  struct wrap_motstr_data_ *wdata;
  void (*proj)(int j, int i, double *aj, double *bi, double *xij, void *proj_adata);
  void *proj_adata;

  wdata=(struct wrap_motstr_data_ *)adata;
  cnp=wdata->cnp; pnp=wdata->pnp; mnp=wdata->mnp;
  proj=wdata->proj;
  proj_adata=wdata->adata;

  n=idxij->nr; m=idxij->nc;
  pa=p; pb=p+m*cnp;

  for(j=0; j<m; ++j){
    /* j-th camera parameters */
    paj=pa+j*cnp;

    nnz=sba_crsm_col_elmidxs(idxij, j, rcidxs, rcsubs); /* find nonzero hx_ij, i=0...n-1 */

    for(i=0; i<nnz; ++i){
      pbi=pb + rcsubs[i]*pnp;
      pxij=hx + idxij->val[rcidxs[i]]*mnp; // set pxij to point to hx_ij

      (*proj)(j, rcsubs[i], paj, pbi, pxij, proj_adata); // evaluate Q in pxij
    }
  }
}
/* Given a parameter vector p made up of 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 returned in the order (A_11, ..., A_1m, ..., A_n1, ..., A_nm),
 * where A_ij=dx_ij/db_j (see HZ).
 * Caller supplies rcidxs and rcsubs which can be used as working memory.
 * Notice that depending on idxij, some of the A_ij might be missing
 *
 */
static void sba_mot_Qs_jac(double *p, struct sba_crsm *idxij, int *rcidxs, int *rcsubs, double *jac, void *adata)
{
  register int i, j;
  int cnp, mnp;
  double *paj, *pAij;
  //int n;
  int m, nnz, Asz, idx;
  struct wrap_mot_data_ *wdata;
  void (*projac)(int j, int i, double *aj, double *Aij, void *projac_adata);
  void *projac_adata;

  wdata=(struct wrap_mot_data_ *)adata;
  cnp=wdata->cnp; mnp=wdata->mnp;
  projac=wdata->projac;
  projac_adata=wdata->adata;

  //n=idxij->nr;
  m=idxij->nc;
  Asz=mnp*cnp;

  for(j=0; j<m; ++j){
    /* j-th camera parameters */
    paj=p+j*cnp;

    nnz=sba_crsm_col_elmidxs(idxij, j, rcidxs, rcsubs); /* find nonzero hx_ij, i=0...n-1 */

    for(i=0; i<nnz; ++i){
      idx=idxij->val[rcidxs[i]];
      pAij=jac + idx*Asz; // set pAij to point to A_ij

      (*projac)(j, rcsubs[i], paj, pAij, projac_adata); // evaluate dQ/da in pAij
    }
  }
}
/* Given a parameter vector p made up of the 3D coordinates of n points, compute in
 * hx the prediction of the measurements, i.e. the projections of 3D points in the m images. The measurements
 * are returned in the order (hx_11^T, .. hx_1m^T, ..., hx_n1^T, .. hx_nm^T)^T, where hx_ij is the predicted
 * projection of the i-th point on the j-th camera.
 * Caller supplies rcidxs and rcsubs which can be used as working memory.
 * Notice that depending on idxij, some of the hx_ij might be missing
 *
 */
static void sba_str_Qs(double *p, struct sba_crsm *idxij, int *rcidxs, int *rcsubs, double *hx, void *adata)
{
  register int i, j;
  int pnp, mnp; 
  double *pbi, *pxij;
  //int n;
  int m, nnz;
  struct wrap_str_data_ *wdata;
  void (*proj)(int j, int i, double *bi, double *xij, void *proj_adata);
  void *proj_adata;

  wdata=(struct wrap_str_data_ *)adata;
  pnp=wdata->pnp; mnp=wdata->mnp;
  proj=wdata->proj;
  proj_adata=wdata->adata;

  //n=idxij->nr;
  m=idxij->nc;

  for(j=0; j<m; ++j){
    nnz=sba_crsm_col_elmidxs(idxij, j, rcidxs, rcsubs); /* find nonzero hx_ij, i=0...n-1 */

    for(i=0; i<nnz; ++i){
      pbi=p + rcsubs[i]*pnp;
      pxij=hx + idxij->val[rcidxs[i]]*mnp; // set pxij to point to hx_ij

      (*proj)(j, rcsubs[i], pbi, pxij, proj_adata); // evaluate Q in pxij
    }
  }
}
Beispiel #5
0
void sba_pinhole_model(double *p, struct sba_crsm *idxij, int *rcidxs, int *rcsubs, double *hx, void *adata) {
	const sba_model_data_t<double> *sba_data = static_cast< sba_model_data_t<double>* >(adata);
	if(!sba_data) return;

	const cv::Mat &camera_matrix = sba_data->camera_matrix;
	
	const int num_cols = idxij->nc;
	double *p_pose = p;
	double *p_points = p+num_cols*num_params_per_cam;

	double rotation_quat[quaternion_size];
	double total_rot_quat[quaternion_size];

	for(int j=0; j<num_cols; ++j) {
		// get j-th camera parameters
		double *p_quat = p_pose + j*num_params_per_cam;
		double *p_transl = p_quat + 3;	// rotation vector part has 3 elements
		// get rotation estimation
		vec2quat(p_quat, rotation_quat);
		const double *p_rotation_guess = &(sba_data->initial_rotations[j*quaternion_size]);
		multiply_quaternion(rotation_quat, p_rotation_guess, total_rot_quat);

		// find number of nonzero hx_ij, i=0...n-1 
		int num_nonzero = sba_crsm_col_elmidxs(idxij, j, rcidxs, rcsubs); 
		for(int i=0; i<num_nonzero; ++i) {
			double *p_point = p_points + rcsubs[i]*num_params_per_point;
			double *p_measurement = hx + idxij->val[rcidxs[i]]*num_params_per_measuremnt; // p_measurement = hx_ij
			
			quaternion_pinhole_model<double>(p_point, total_rot_quat, p_transl, camera_matrix, p_measurement);
		}
	}
}
Beispiel #6
0
main()
{
	int mat[7][6]= {
		{	10, 0, 0, 0, -2, 0},
		{	3, 9, 0, 0, 0, 3},
		{	0, 7, 8, 7, 0, 0},
		{	3, 0, 8, 7, 5, 0},
		{	0, 8, 0, 9, 9, 13},
		{	0, 4, 0, 0, 2, -1},
		{	3, 7, 0, 9, 2, 0}
	};

	struct sba_crsm sm;
	int idx1, idx2, k, pyramidLevel;
	int vidxs[7], /* max(6, 7) */
	jidxs[6], iidxs[7];

	sba_crsm_build(&sm, mat[0], 7, 6);
	sba_crsm_print(&sm, stdout);

	for(idx1=0; idx1<7; ++idx1) {
		for(idx2=0; idx2<6; ++idx2)
		printf("%3d ", ((k=sba_crsm_elmidx(&sm, idx1, idx2))!=-1)? sm.val[k] : 0);
		printf("\n");
	}

	for(idx1=0; idx1<7; ++idx1) {
		k=sba_crsm_row_elmidxs(&sm, idx1, vidxs, jidxs);
		printf("row %d\n", idx1);
		for(pyramidLevel=0; pyramidLevel<k; ++pyramidLevel) {
			idx2=jidxs[pyramidLevel];
			printf("%d %d  ", idx2, sm.val[vidxs[pyramidLevel]]);
		}
		printf("\n");
	}

	for(idx2=0; idx2<6; ++idx2) {
		k=sba_crsm_col_elmidxs(&sm, idx2, vidxs, iidxs);
		printf("col %d\n", idx2);
		for(pyramidLevel=0; pyramidLevel<k; ++pyramidLevel) {
			idx1=iidxs[pyramidLevel];
			printf("%d %d  ", idx1, sm.val[vidxs[pyramidLevel]]);
		}
		printf("\n");
	}

	sba_crsm_free(&sm);
}
Beispiel #7
0
void sba_pinhole_model_jac(double *p, struct sba_crsm *idxij, int *rcidxs, int *rcsubs, double *jac, void *adata) {
	const sba_model_data_t<double> *sba_data = static_cast< sba_model_data_t<double>* >(adata);
	if(!sba_data) return;

	const cv::Mat &camera_matrix = sba_data->camera_matrix;

	const int num_cols = idxij->nc;
	double *p_pose = p;
	double *p_points = p+num_cols*num_params_per_cam;

	static const int size_A = num_params_per_measuremnt*num_params_per_cam;
	static const int size_B = num_params_per_measuremnt*num_params_per_point;
	static const int size_AB = size_A+size_B;
	
	for(int j=0; j<num_cols; ++j) {
		// get j-th camera parameters
		double *p_quat = p_pose + j*num_params_per_cam;
		double *p_transl = p_quat + 3;	// rotation vector part has 3 elements
		const double *p_rotation_guess = &(sba_data->initial_rotations[j*quaternion_size]);

		// find number of nonzero hx_ij, i=0...n-1 
		int num_nonzero = sba_crsm_col_elmidxs(idxij, j, rcidxs, rcsubs); 
		for(int i=0; i<num_nonzero; ++i) {
			double *p_point = p_points + rcsubs[i]*num_params_per_point;
			double *p_Aij = jac + idxij->val[rcidxs[i]]*size_AB;
			double *p_Bij = p_Aij + size_A;

			quaternion_pinhole_model_jac<double>(p_point,
				p_quat,
				p_transl,
				camera_matrix,
				p_rotation_guess,
				(double (*)[6])p_Aij,
				(double (*)[3])p_Bij);
		}
	}
}
/* 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 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/db_j and B_ij=dx_ij/db_i (see HZ).
 * Caller supplies rcidxs and rcsubs which can be used as working memory.
 * Notice that depending on idxij, some of the A_ij, B_ij might be missing
 *
 */
static void sba_motstr_Qs_jac(double *p, struct sba_crsm *idxij, int *rcidxs, int *rcsubs, double *jac, void *adata)
{
  register int i, j;
  int cnp, pnp, mnp;
  double *pa, *pb, *paj, *pbi, *pAij, *pBij;
  int n, m, nnz, Asz, Bsz, ABsz, idx;
  struct wrap_motstr_data_ *wdata;
  void (*projac)(int j, int i, double *aj, double *bi, double *Aij, double *Bij, void *projac_adata);
  void *projac_adata;

  
  wdata=(struct wrap_motstr_data_ *)adata;
  cnp=wdata->cnp; pnp=wdata->pnp; mnp=wdata->mnp;
  projac=wdata->projac;
  projac_adata=wdata->adata;

  n=idxij->nr; m=idxij->nc;
  pa=p; pb=p+m*cnp;
  Asz=mnp*cnp; Bsz=mnp*pnp; ABsz=Asz+Bsz;

  for(j=0; j<m; ++j){
    /* j-th camera parameters */
    paj=pa+j*cnp;

    nnz=sba_crsm_col_elmidxs(idxij, j, rcidxs, rcsubs); /* find nonzero hx_ij, i=0...n-1 */

    for(i=0; i<nnz; ++i){
      pbi=pb + rcsubs[i]*pnp;
      idx=idxij->val[rcidxs[i]];
      pAij=jac  + idx*ABsz; // set pAij to point to A_ij
      pBij=pAij + Asz; // set pBij to point to B_ij

      (*projac)(j, rcsubs[i], paj, pbi, pAij, pBij, projac_adata); // evaluate dQ/da, dQ/db in pAij, pBij
    }
  }
}
/* Given a parameter vector p made up of 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, ..., A_1m, ..., A_n1, ..., A_nm), where A_ij=dx_ij/da_j (see HZ).
 * Notice that depending on idxij, some of the A_ij might be missing
 *
 * Problem-specific information is assumed to be stored in a structure pointed to by "dat".
 *
 * NOTE: This function is provided mainly for illustration purposes; in case that execution time is a concern,
 * the jacobian should be computed analytically
 */
static void sba_mot_Qs_fdjac(
    double *p,                /* I: current parameter estimate, (m*cnp)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 "wrap_mot_data_" structure */
{
  register int i, j, ii, jj;
  double *paj;
  register double *pA;
  //int n; 
  int m, nnz, Asz;

  double tmp;
  register double d, d1;

  struct wrap_mot_data_ *fdjd;
  void (*proj)(int j, int i, double *aj, double *xij, void *adata);
  double *hxij, *hxxij;
  int cnp, mnp;
  void *adata;

  /* retrieve problem-specific information passed in *dat */
  fdjd=(struct wrap_mot_data_ *)dat;
  proj=fdjd->proj;
  cnp=fdjd->cnp; mnp=fdjd->mnp;
  adata=fdjd->adata;

  //n=idxij->nr;
  m=idxij->nc;
  Asz=mnp*cnp;

  /* allocate memory for hxij, hxxij */
  if((hxij=malloc(2*mnp*sizeof(double)))==NULL){
    fprintf(stderr, "memory allocation request failed in sba_mot_Qs_fdjac()!\n");
    exit(1);
  }
  hxxij=hxij+mnp;

  /* compute A_ij */
  for(j=0; j<m; ++j){
    paj=p+j*cnp; // j-th camera parameters

    nnz=sba_crsm_col_elmidxs(idxij, j, rcidxs, rcsubs); /* find nonzero A_ij, i=0...n-1 */
    for(jj=0; jj<cnp; ++jj){
      /* determine d=max(SBA_DELTA_SCALE*|paj[jj]|, SBA_MIN_DELTA), see HZ */
      d=(double)(SBA_DELTA_SCALE)*paj[jj]; // force evaluation
      d=FABS(d);
      if(d<SBA_MIN_DELTA) d=SBA_MIN_DELTA;
      d1=1.0/d; /* invert so that divisions can be carried out faster as multiplications */

      for(i=0; i<nnz; ++i){
        (*proj)(j, rcsubs[i], paj, hxij, adata); // evaluate supplied function on current solution

        tmp=paj[jj];
        paj[jj]+=d;
        (*proj)(j, rcsubs[i], paj, hxxij, adata);
        paj[jj]=tmp; /* restore */

        pA=jac + idxij->val[rcidxs[i]]*Asz; // set pA to point to A_ij
        for(ii=0; ii<mnp; ++ii)
          pA[ii*cnp+jj]=(hxxij[ii]-hxij[ii])*d1;
      }
    }
  }

  free(hxij);
}