core/vpgl/algo/vpgl_triangulate_points.cxx
Go to the documentation of this file.
00001 // This is core/vpgl/algo/vpgl_triangulate_points.cxx
00002 #include "vpgl_triangulate_points.h"
00003 //:
00004 // \file
00005 
00006 #include <vcl_cmath.h>
00007 #include <vcl_cstdlib.h>
00008 #include <vcl_cassert.h>
00009 
00010 #include <vgl/vgl_vector_3d.h>
00011 
00012 #include <vnl/vnl_matrix_fixed.h>
00013 #include <vnl/vnl_matrix.h>
00014 #include <vnl/vnl_vector.h>
00015 #include <vnl/vnl_double_3.h>
00016 #include <vnl/vnl_double_3x3.h>
00017 #include <vnl/algo/vnl_svd.h>
00018 
00019 
00020 double vpgl_triangulate_points::triangulate(
00021         const vcl_vector<vgl_point_2d<double> > &points,
00022         const vcl_vector<vpgl_perspective_camera<double> > &cameras,
00023         vgl_point_3d<double> &point_3d)
00024 {
00025     const int num_vars = 3;// One var for x, y, z of output 3d point
00026     const int num_eqs = 2 * points.size();
00027 
00028     // Set up the least-squares solution.
00029     vnl_matrix<double> A(num_eqs, num_vars, 0.0);
00030     vnl_vector<double> b(num_eqs, 0.0);
00031 
00032     for (unsigned int i = 0; i < points.size(); ++i) {
00033         const vgl_vector_3d<double> &trans =
00034             cameras[i].get_translation();
00035 
00036         const vnl_double_3x3 &rot =
00037             cameras[i].get_rotation().as_matrix();
00038 
00039         const vgl_point_2d<double> pt =
00040             cameras[i].get_calibration().map_to_focal_plane(points[i]);
00041 
00042         // Set the row for x for this point
00043         A.put(2 * i, 0, rot.get(0, 0) - pt.x() * rot.get(2, 0) );
00044         A.put(2 * i, 1, rot.get(0, 1) - pt.x() * rot.get(2, 1) );
00045         A.put(2 * i, 2, rot.get(0, 2) - pt.x() * rot.get(2, 2) );
00046 
00047         // Set the row for y for this point
00048         A.put(2*i+1, 0, rot.get(1, 0) - pt.y() * rot.get(2, 0) );
00049         A.put(2*i+1, 1, rot.get(1, 1) - pt.y() * rot.get(2, 1) );
00050         A.put(2*i+1, 2, rot.get(1, 2) - pt.y() * rot.get(2, 2) );
00051 
00052         // Set the RHS row.
00053         b[2*i + 0] = trans.z() * pt.x() - trans.x();
00054         b[2*i + 1] = trans.z() * pt.y() - trans.y();
00055     }
00056 
00057     // Find the least squares result
00058     vnl_svd<double> svd(A);
00059     vnl_double_3 x = svd.solve(b);
00060 
00061     point_3d.set(x.begin());
00062 
00063     // Find the error
00064     double error = 0.0;
00065     for (unsigned int i = 0; i < points.size(); ++i) {
00066         // Compute projection error
00067         vnl_double_3 pp = cameras[i].get_rotation().as_matrix() * x;
00068 
00069         pp[0] += cameras[i].get_translation().x();
00070         pp[1] += cameras[i].get_translation().y();
00071         pp[2] += cameras[i].get_translation().z();
00072 
00073         double dx = pp[0] / pp[2] - points[i].x();
00074         double dy = pp[1] / pp[2] - points[i].y();
00075         error += dx * dx + dy * dy;
00076     }
00077 
00078     return vcl_sqrt(error / points.size());
00079 }