Example #1
0
bool BundlerApp::EstimateRelativePose2(int i1, int i2, 
                                       camera_params_t &camera1, 
                                       camera_params_t &camera2)
{
    // int num_images = GetNumImages();
    MatchIndex list_idx;

    if (i1 < i2)
        list_idx = GetMatchIndex(i1, i2); // i1 * num_images + i2;
    else
        list_idx = GetMatchIndex(i2, i1); // i2 * num_images + i1;

    std::vector<KeypointMatch> &matches = m_matches.GetMatchList(list_idx);
    // int num_matches = (int) m_match_lists[list_idx].size();
    int num_matches = (int) matches.size();

    // double f1 = m_image_data[i1].m_init_focal;
    // double f2 = m_image_data[i2].m_init_focal;
    double K1[9], K2[9];
    GetIntrinsics(camera1, K1);
    GetIntrinsics(camera2, K2);

    double R0[9], t0[3];
    int num_inliers = 0;

    if (!m_optimize_for_fisheye) {
        num_inliers = 
            EstimatePose5Point(m_image_data[i1].m_keys, 
                               m_image_data[i2].m_keys, 
                               matches,
                               512, /* m_fmatrix_rounds, 8 * m_fmatrix_rounds */
                               0.25 * m_fmatrix_threshold, // 0.003, // 0.004 /*0.001,*/ // /*0.5 **/ m_fmatrix_threshold, 
                               K1, K2, R0, t0);
    } else {
        std::vector<Keypoint> k1 = m_image_data[i1].UndistortKeysCopy();
        std::vector<Keypoint> k2 = m_image_data[i2].UndistortKeysCopy();

        num_inliers = 
            EstimatePose5Point(k1, k2, matches,
                               1024, /*512*/ /* m_fmatrix_rounds, 8 * m_fmatrix_rounds */
                               0.25 * m_fmatrix_threshold, // 0.004, /*0.001,*/ // /*0.5 **/ m_fmatrix_threshold, 
                               K1, K2, R0, t0);
    }
    
    if (num_inliers == 0)
        return false;

    printf("  Found %d / %d inliers (%0.3f%%)\n", num_inliers, num_matches,
           100.0 * num_inliers / num_matches);

    bool initialized = false;
    if (!initialized) {
        memcpy(camera2.R, R0, sizeof(double) * 9);

        matrix_transpose_product(3, 3, 3, 1, R0, t0, camera2.t);
        matrix_scale(3, 1, camera2.t, -1.0, camera2.t);
    }

    return true;
}
Example #2
0
void PlaneData::Transform(const double *M)
{
    double p[4] = { m_normal[0], m_normal[1], m_normal[2], m_dist };

    double Minv[16];
    matrix_invert(4, (double *)M, Minv);
    
    double pNew[4];
    matrix_transpose_product(4, 4, 4, 1, Minv, p, pNew);

    double len = matrix_norm(3, 1, pNew);
    
    m_normal[0] = pNew[0] / len;
    m_normal[1] = pNew[1] / len;
    m_normal[2] = pNew[2] / len;
    m_dist = pNew[3] / len;

#if 0
    double origin[4] = { m_origin[0], m_origin[1], m_origin[2], 1.0 };
    double Morigin[4];
    matrix_product(4, 4, 4, 1, (double *) M, origin, Morigin);

    double dot0, dot1;
    matrix_product(1, 4, 4, 1, p, origin, &dot0);
    matrix_product(1, 4, 4, 1, pNew, Morigin, &dot1);

    printf("dot0 = %0.3f\n", dot0);
    printf("dot1 = %0.3f\n", dot1);
#endif
}
Example #3
0
v3_t BundlerApp::GeneratePointAtInfinity(const ImageKeyVector &views, 
                                         int *added_order, 
                                         camera_params_t *cameras,
                                         double &error, 
                                         bool explicit_camera_centers)
{
    camera_params_t *cam = NULL;

    int camera_idx = views[0].first;
    int image_idx = added_order[camera_idx];
    int key_idx = views[0].second;
    Keypoint &key = GetKey(image_idx, key_idx);

    cam = cameras + camera_idx;

    double p3[3] = { key.m_x, key.m_y, 1.0 };

    if (m_optimize_for_fisheye) {
        /* Undistort the point */
        double x = p3[0], y = p3[1];
        m_image_data[image_idx].UndistortPoint(x, y, p3[0], p3[1]);
    }

    double K[9], Kinv[9];
    GetIntrinsics(cameras[camera_idx], K);
    matrix_invert(3, K, Kinv);

    double ray[3];
    matrix_product(3, 3, 3, 1, Kinv, p3, ray);

    /* We now have a ray, put it at infinity */
    double ray_world[3];
    matrix_transpose_product(3, 3, 3, 1, cam->R, ray, ray_world);

    double pos[3] = { 0.0, 0.0, 0.0 };
    double pt_inf[3] = { 0.0, 0.0, 0.0 };

    if (!explicit_camera_centers) {
        
    } else {
        memcpy(pos, cam->t, 3 * sizeof(double));
        double ray_extend[3];
        matrix_scale(3, 1, ray, 100.0, ray_extend);
        matrix_sum(3, 1, 3, 1, pos, ray, pt_inf);
    }

    return v3_new(pt_inf[0], pt_inf[1], pt_inf[2]);
}
Example #4
0
/* Decompose a square matrix into an orthogonal matrix and a symmetric
 * positive semidefinite matrix */
void matrix_polar_decomposition(int n, double *A, double *Q, double *S) 
{
    double *U, *diag, *VT;
    double *diag_full, *tmp;
    int i;

    U = (double *) malloc(sizeof(double) * n * n);
    diag = (double *) malloc(sizeof(double) * n);
    VT = (double *) malloc(sizeof(double) * n * n);

    /* Compute SVD */
    dgesvd_driver(n, n, A, U, diag, VT);
 
    /* Compute Q */
    matrix_product(n, n, n, n, U, VT, Q);
    
    /* Compute S */
    diag_full = (double *) malloc(sizeof(double) * n * n);

    for (i = 0; i < n * n; i++) {
	diag_full[i] = 0.0;
    }
    
    for (i = 0; i < n; i++) {
	diag_full[i * n + i] = diag[i];
    }

    tmp = (double *) malloc(sizeof(double) * n * n);
    matrix_transpose_product(n, n, n, n, VT, diag_full, tmp);
    matrix_product(n, n, n, n, tmp, VT, S);

    free(U);
    free(diag);
    free(VT);
    free(diag_full);
    free(tmp);
}
void ThresholdTwists(int num_images, ModelMap &models, 
                     std::vector<ImageData> &image_data, bool panos_only) 
{
    int *num_large_twists = new int[num_images];
    int *degree = new int[num_images];

    for (int i = 0; i < num_images; i++) {
        num_large_twists[i] = 0;
        degree[i] = 0;
    }

    for (int i = 0; i < num_images; i++) {
        ModelTable::iterator iter;
        for (iter = models.Begin(i); iter != models.End(i); iter++) {
            unsigned int j = iter->first; // iter->m_index;
            
            if (i >= j)
                continue;
            
            MatchIndex idx = GetMatchIndex(i, j);
            if (models.Contains(idx)) {
                TwoFrameModel &m = models.GetModel(idx);
                
                /* Compute the twist */
                double Rp_i[9], Rp_j[9];
                matrix_transpose(3, 3, m.m_camera0.R, Rp_i);
                matrix_transpose(3, 3, m.m_camera1.R, Rp_j);
                
                double Rp_ij[9];
                matrix_transpose_product(3, 3, 3, 3, Rp_i, Rp_j, Rp_ij);
                
                double twist_angle = GetTwist(Rp_ij);
                
                if (fabs(RAD2DEG(twist_angle)) >= 12.0) { 
                    num_large_twists[i]++;
                    num_large_twists[j]++;
                }
                
                degree[i]++;
                degree[j]++;
            }
        }
    }
    
    for (int i = 0; i < num_images; i++) {
        if (degree[i] == 0)
            continue;

        double perc_large_twists = (double) num_large_twists[i] / degree[i];
        
        int w = image_data[i].GetWidth();
        int h = image_data[i].GetHeight();
        
        double ratio = (double) w / h;

        if ((panos_only || perc_large_twists < 0.4) && 
             ratio > 0.4 && ratio < 2.5) {
            continue;
        }

        printf("[ThresholdTwists] Removing image %d with score %0.3f, %0.3f\n",
               i, perc_large_twists, ratio);

        std::list<unsigned int> nbrs = models.GetNeighbors(i);
        std::list<unsigned int>::iterator iter;
        for (iter = nbrs.begin(); iter != nbrs.end(); iter++) {
            unsigned int j = *iter; // iter->m_index;
            
            if (i < j) {            
                MatchIndex idx = GetMatchIndex(i, j);
                if (models.Contains(idx)) {
                    models.RemoveModel(idx);
                }
            } else {
                MatchIndex idx = GetMatchIndex(j, i);
                if (models.Contains(idx)) {
                    models.RemoveModel(idx);
                }
            }
        }
    }
}
Example #6
0
bool BundlerApp::EstimateRelativePose(int i1, int i2, 
                                      camera_params_t &camera1, 
                                      camera_params_t &camera2)
{
    MatchIndex list_idx;

    if (i1 < i2)
        list_idx = GetMatchIndex(i1, i2);
    else
        list_idx = GetMatchIndex(i2, i1);

    std::vector<KeypointMatch> &matches = m_matches.GetMatchList(list_idx);
    int num_matches = (int) matches.size();

    double f1 = m_image_data[i1].m_init_focal;
    double f2 = m_image_data[i2].m_init_focal;

    double E[9], F[9];
    std::vector<int> inliers;

    if (!m_optimize_for_fisheye) {
        inliers = 
            EstimateEMatrix(m_image_data[i1].m_keys, m_image_data[i2].m_keys, 
                            matches,
                            4 * m_fmatrix_rounds, // 8 * m_fmatrix_rounds,
                            m_fmatrix_threshold * m_fmatrix_threshold, 
                            f1, f2, E, F);
    } else {
        /* FIXME */
        inliers = 
            EstimateEMatrix(m_image_data[i1].m_keys, m_image_data[i2].m_keys, 
                            matches,
                            4 * m_fmatrix_rounds, // 8 * m_fmatrix_rounds,
                            m_fmatrix_threshold * m_fmatrix_threshold, 
                            f1, f2, E, F);        
    }

    if ((int) inliers.size() == 0)
        return false;

    int num_inliers = (int) inliers.size();
    printf("  Found %d / %d inliers (%0.3f%%)\n", num_inliers, num_matches,
           100.0 * num_inliers / num_matches);


    /* Estimate a homography with the inliers */
    std::vector<KeypointMatch> match_inliers;
    for (int i = 0; i < num_inliers; i++) {
        match_inliers.push_back(matches[inliers[i]]);
    }

    int num_match_inliers = (int) match_inliers.size();

    double H[9];
    std::vector<int> Hinliers = 
        EstimateTransform(m_image_data[i1].m_keys, m_image_data[i2].m_keys,
                          match_inliers, MotionHomography,
                          128 /*m_homography_rounds*/, 
                          6.0 /*m_homography_threshold*/, H);

    printf("  Found %d / %d homography inliers (%0.3f%%)\n",
           (int) Hinliers.size(), num_inliers, 
           100.0 * Hinliers.size() / num_inliers);

    bool initialized = false;
    if ((int) Hinliers.size() > 0) {
        matrix_print(3, 3, H);
        printf("\n");
    
        if ((double) Hinliers.size() / num_inliers >= 0.75 /*0.85*/) {
            KeypointMatch &match0 = matches[Hinliers[0]];
            v2_t p10 = v2_new(m_image_data[i1].m_keys[match0.m_idx1].m_x,
                              m_image_data[i1].m_keys[match0.m_idx1].m_y);
            v2_t p20 = v2_new(m_image_data[i2].m_keys[match0.m_idx2].m_x,
                              m_image_data[i2].m_keys[match0.m_idx2].m_y);

            double R1[9], t1[3], R2[9], t2[3];
            bool success = 
                DecomposeHomography(H, f1, f2, R1, t1, R2, t2, p10, p20);
        
            if (success) {
                printf("[BundleTwoFrame] Using homography "
                       "for initialization\n");

                /* Decide which solution to use */
                double F1h[9], F2h[9];
                ComputeFundamentalMatrix(f1, f2, R1, t1, F1h);
                ComputeFundamentalMatrix(f1, f2, R2, t2, F2h);
                
                double F1hT[9], F2hT[9];
                matrix_transpose(3, 3, F1h, F1hT);
                matrix_transpose(3, 3, F2h, F2hT);

                int num_inliers1 = 0, num_inliers2 = 0;

                for (int i = 0; i < num_match_inliers; i++) {
                    const KeypointMatch &match = match_inliers[i];
                    const Keypoint &k1 = m_image_data[i1].m_keys[match.m_idx1];
                    const Keypoint &k2 = m_image_data[i2].m_keys[match.m_idx2];

                    v3_t rt = v3_new(k1.m_x, k1.m_y, 1.0);
                    v3_t lft = v3_new(k2.m_x, k2.m_y, 1.0);
                    double r1a = fmatrix_compute_residual(F1h, lft, rt);
                    double r1b = fmatrix_compute_residual(F1hT, rt, lft);

                    double r2a = fmatrix_compute_residual(F2h, lft, rt);
                    double r2b = fmatrix_compute_residual(F2hT, rt, lft);

                    if (r1a < m_fmatrix_threshold && r1b < m_fmatrix_threshold)
                        num_inliers1++;

                    if (r2a < m_fmatrix_threshold && r2b < m_fmatrix_threshold)
                        num_inliers2++;
                }

                initialized = true;

                double *R, *t;
                printf("  H1: %d inliers, H2: %d inliers\n", 
                       num_inliers1, num_inliers2);
                if (num_inliers1 > num_inliers2) {
                    R = R1;
                    t = t1;
                } else {
                    R = R2;
                    t = t2;
                }

                memcpy(camera2.R, R, sizeof(double) * 9);
                matrix_transpose_product(3, 3, 3, 1, R, t, camera2.t);
                matrix_scale(3, 1, camera2.t, -1.0, camera2.t);
            }
        }
    }

    if (!initialized) {
        KeypointMatch &match = matches[inliers[0]];
        v2_t p1 = v2_new(m_image_data[i1].m_keys[match.m_idx1].m_x / f1,
                         m_image_data[i1].m_keys[match.m_idx1].m_y / f1);
        v2_t p2 = v2_new(m_image_data[i2].m_keys[match.m_idx2].m_x / f2,
                         m_image_data[i2].m_keys[match.m_idx2].m_y / f2);
    
        double R[9], t[3];
        int success = find_extrinsics_essential(E, p1, p2, R, t);
    
        if (!success) {
            return false;
        }

        memcpy(camera2.R, R, sizeof(double) * 9);

        matrix_transpose_product(3, 3, 3, 1, R, t, camera2.t);
        matrix_scale(3, 1, camera2.t, -1.0, camera2.t);
    }

    return true;
}
Example #7
0
void lmdif_driver3(void *fcn, int m, int n, double *xvec, double tol,
                   int maxfev, double *H) {
    int info;
    double *fvec;
    double gtol = 0, epsfcn = 0;
    // int maxfev = 200 * (n + 1);
    double *diag;
    int mode = 1;
    double factor = 100;
    int nprint = 1;
    int nfev;
    double *fjac;
    int ldfjac = m;
    int *ipvt;
    double *qtf;
    double *wa1, *wa2, *wa3, *wa4;

    if (maxfev == -1)
        maxfev = 200 * (n + 1);

    if (n > m) {
        printf("Error: lmdif called with n > m\n");
        return;
    }

    fvec = (double *)malloc(sizeof(double) * m);
    diag = (double *)malloc(sizeof(double) * n);
    fjac = (double *)malloc(sizeof(double) * m * n);
    ipvt = (int *)malloc(sizeof(int) * n);
    qtf = (double *)malloc(sizeof(double) * n);
    wa1 = (double *)malloc(sizeof(double) * n);
    wa2 = (double *)malloc(sizeof(double) * n);
    wa3 = (double *)malloc(sizeof(double) * n);
    wa4 = (double *)malloc(sizeof(double) * m);

//#ifdef WIN32
//    LMDIF(fcn, &m, &n, xvec, fvec, &tol, &tol, &gtol, &maxfev, 
//           &epsfcn, diag, &mode, &factor, &nprint, &info, &nfev, 
//           fjac, &ldfjac, ipvt, qtf, wa1, wa2, wa3, wa4);
//#else
    lmdif_(fcn, &m, &n, xvec, fvec, &tol, &tol, &gtol, &maxfev, 
           &epsfcn, diag, &mode, &factor, &nprint, &info, &nfev, 
           fjac, &ldfjac, ipvt, qtf, wa1, wa2, wa3, wa4);
//#endif

#if 1
    switch (info) {
        case 0:
            printf("Improper input parameters\n");
            break;
        case 1:
            printf("Sum of squares tolerance reached\n");
            break;
        case 2:
            printf("x is within tolerance\n");
            break;
        case 3:
            printf("Sum of squares and x are within tolerance\n");
            break;
        case 4:
            printf("fvec orthogonal\n");
            break;
        case 5:
            printf("max function calls made\n");
            break;
        case 6:
            printf("tolerance is too small (squares)\n");
            break;
        case 7:
            printf("tolerance is too small (x)\n");
            break;
    default:
	printf("???\n");
    }
#endif


    /* Copy the Hessian in fjac to H */
    if (H != NULL) {
        int i, j;
        double *P, *tmp;
        double *R;
        clock_t start, end;
        
        R = malloc(sizeof(double) * n * n);

        for (i = 0; i < n; i++) {
            for (j = 0; j < n; j++) {
                if (j < i) {
                    R[i * n + j] = 0.0;
                } else {
                    int idx0 = j * m + i;
                    int idx1 = i * n + j;
                
                    R[idx1] = fjac[idx0];
                }
            }
        }

        start = clock();

        matrix_transpose_product(n, n, n, n, R, R, H);
        // cblas_dgemm_driver_transpose(n, n, n, R, R, H);

        /* Unpermute the entries of H */
        P = malloc(sizeof(double) * n * n);
        
        for (i = 0; i < n; i++) {
            int p = ipvt[i] - 1;
            if (p < 0)
                printf("[lmdif_driver3] Error: p < 0\n");

            for (j = 0; j < n; j++) {
                if (p == j) 
                    P[i * n + j] = 1.0;
                else
                    P[i * n + j] = 0.0;
            }
        }


        tmp = malloc(sizeof(double) * n * n);

        matrix_transpose_product(n, n, n, n, P, H, tmp);
        matrix_product(n, n, n, n, tmp, P, H);
        // cblas_dgemm_driver_transpose(n, n, n, P, H, tmp);
        // cblas_dgemm_driver(n, n, n, tmp, P, H);

        end = clock();

        printf("[lmdif_driver3] post-process took %0.3fs\n",
               (double) (end - start) / CLOCKS_PER_SEC);

        free(P);
        free(tmp);
    }

    /* Clean up */
    free(fvec);
    free(diag);
    free(fjac);
    free(ipvt);
    free(qtf);
    free(wa1);
    free(wa2);
    free(wa3);
    free(wa4);
}