zoukankan      html  css  js  c++  java
  • 视图重建

    如果空间点在两个或多个视图中出现,如何恢复景物的具体外观呢?

    两视图重建

    假定某物理点出现在两个视角的图片中,基于图像匹配的算法,我们确定了这对点集:<x,x^{'}>

    三维重建的任务是确定摄像机矩阵 P,P^' 以及三维坐标点X。如果我们已经得到了P和P’,计算方法下一篇会做详细的阐述。

    根据摄像机模型:

    left{egin{array}{ll}
x=P*X\
x^{'}=P^{'}*X
end{array}
ight.

    通过叉积构建齐次线性方程组 clip_image002 , 展开:

    PX=[P^{1T}X,P^{2T}X,P^{3T}X]

    叉乘得到

    egin{bmatrix}
i&&j&&k\
x&&y&&1\
P^{1T}X&&P^{2T}X&&P^{3T}X
end{bmatrix}

    所以:

    left{egin{array}{ll}
y(P^{3T}X)-(P^{2T}X)=0\
x(P^{3T}X)-(P^{1T}X)=0\
x(P^{2T}X)-y(P^{1T}X)=0\
end{array}

ight.

    考虑两个对应点(视图),得到:

    A=egin{bmatrix}
xP^{3T}-P^{1T}\
yP^{3T}-P^{2T}\
x^{'}P^{'3T}-P^{'1T}\
y^{'}P^{'3T}-P^{'2T}
end{bmatrix}

    AX=0

    这里是从每个视图中取两个方程,得到4个方程,这是一个冗余方程组,可采用最小二乘法求解即可。

    多点反投影(重建)

    相机的RT参数:

    struct camera_params_t
    {
        double R[9];     /* Rotation */
        double T[3];     /* Translation */
        double t[3];     /*-RT*/
    };

    反投影函数:

    v3_t triangulate_Pre( vector<v2_t> &p, vector<camera_params_t>& params, double &error_out)

    其中 p=K^{-1}*x ,有:

    C*p=C*egin{bmatrix}p.x\p.y\1end{bmatrix}=[R|t]*X=R*X+t

    所以:

    left{egin{array}{ll}
p.x=frac{R^{1T}*X+t[0]}{R^{3T}*X+t[2]}\
p.y=frac{R^{2T}*X+t[1]}{R^{3T}*X+t[2]}
end{array}

ight.

    程序实现:

    v3_t triangulate_Pre( vector<v2_t> &p, vector<camera_params_t>& params, double &error_out) 
    {//T
        int num_points = p.size();
        int num_eqs = 2 * num_points;
        int num_vars = 3;
    
        double *A = (double *) malloc(sizeof(double) * num_eqs * num_vars);
        double *b = (double *) malloc(sizeof(double) * num_eqs);
        double *x = (double *) malloc(sizeof(double) * num_vars);
    
        int i;
        double error;
        v3_t r;
    
        for (i = 0; i < num_points; i++) {
            int row = 6 * i;
            int brow = 2 * i;
    
            A[row + 0] = params[i].R[0] - Vx(p[i]) * params[i].R[6];  
            A[row + 1] = params[i].R[1] - Vx(p[i]) * params[i].R[7];  
            A[row + 2] = params[i].R[2] - Vx(p[i]) * params[i].R[8];
    
            A[row + 3] = params[i].R[3] - Vy(p[i]) * params[i].R[6];  
            A[row + 4] = params[i].R[4] - Vy(p[i]) * params[i].R[7];  
            A[row + 5] = params[i].R[5] - Vy(p[i]) * params[i].R[8];
    
            b[brow + 0] = params[i].T[2] * Vx(p[i]) - params[i].T[0];
            b[brow + 1] = params[i].T[2] * Vy(p[i]) - params[i].T[1];
        }
        
        /* Find the least squares result */
        dgelsy_driver(A, b, x, num_eqs, num_vars, 1);
        error = 0.0;
        for (i = 0; i < num_points; i++) {
            double dx, dy;
            double pp[3];
    
            /* Compute projection error */
            matrix_product331(params[i].R , x, pp);
            pp[0] += params[i].T[0];
            pp[1] += params[i].T[1];
            pp[2] += params[i].T[2];
    
            dx = pp[0] / pp[2] - Vx(p[i]);
            dy = pp[1] / pp[2] - Vy(p[i]);
    
            error += dx * dx + dy * dy;
        }
        error = sqrt(error / num_points);
        printf("1:triangulate error is %f 
    ", error);
        /* Run a non-linear optimization to refine the result */
        global_num_points = num_points;
        global_p = p;
        global_params = params;
        lmdif_driver(triangulate_n_residual, num_eqs, num_vars, x, 1.0e-5);
    
        error = 0.0;
        for (i = 0; i < num_points; i++) {
            double dx, dy;
            double pp[3];
    
            /* Compute projection error */
            matrix_product331(params[i].R , x, pp);
            pp[0] += params[i].T[0];
            pp[1] += params[i].T[1];
            pp[2] += params[i].T[2];
    
            dx = pp[0] / pp[2] - Vx(p[i]);
            dy = pp[1] / pp[2] - Vy(p[i]);
    
            error += dx * dx + dy * dy;
        }
        error = sqrt(error / num_points);
        printf("2:triangulate error is %f 
    ", error);
    
        if (error_out != NULL) {
            error_out = error;
        }
        r = v3_new(x[0], x[1], x[2]);
        free(A);
        free(b);
        free(x);
        return r;
    }

    求优函数参考:https://github.com/TheFrenchLeaf/Bundler/blob/master/lib/matrix/matrix.h

    dgelsy_driver函数: Driver for the lapack function dgelss, which finds x to minimize norm(b - A * x)

    lmdif_driver函数:Driver for the minpack function lmdif, which uses Levenberg-Marquardt for non-linear least squares minimization (可参见:https://www.math.utah.edu/software/minpack/minpack/lmdif.html)

    具体函数的不同见下一篇:最小二乘法

    void triangulate_n_residual(const int *m, const int *n, 
        double *x, double *fvec, double *iflag) {
        int i;
        for (i = 0; i < global_num_points; i++) {
            /* Project the point into the view */
            v2_t p = project(i, x);
            fvec[2 * i + 0] = Vx(global_p[i]) - Vx(p);
            fvec[2 * i + 1] = Vy(global_p[i]) - Vy(p);
        }
    }
    //
    v2_t project(int index, double *P) {
        /* Rigid transform */
        double tmp[3], tmp2[3];
        matrix_product331(global_params[index].R, P, tmp);
        matrix_sum(3, 1, 3, 1, tmp, global_params[index].T, tmp2);
    
        /* Perspective division */
        v2_t result;
        Vx(result) = tmp2[0] / tmp2[2];
        Vy(result) = tmp2[1] / tmp2[2];
    
        return result;
    }
  • 相关阅读:
    《移动Web前端高效开发实战》笔记4--打造单页应用SPA
    《移动Web前端高效开发实战》笔记3--代码检查任务
    《移动Web前端高效开发实战》笔记2——使用Gulp构建一个ECMAScript 6和Sass应用
    《移动Web前端高效开发实战》笔记1——静态布局在移动端上的自适应
    Node.js 历史
    《超实用的Node.js代码段》连载三:Node.js深受欢迎的六大原因
    《超实用的Node.js代码段》连载二:正确拼接Buffer
    《超实用的Node.js代码段》连载一:获取Buffer对象字节长度
    换个地方写博客
    【转一篇出处不明的文章】 Windows多线程通信方式
  • 原文地址:https://www.cnblogs.com/houkai/p/6368235.html
Copyright © 2011-2022 走看看