core/vpgl/algo/vpgl_camera_homographies.cxx
Go to the documentation of this file.
00001 #include "vpgl_camera_homographies.h"
00002 //:
00003 // \file
00004 #include <vgl/vgl_vector_3d.h>
00005 #include <vgl/algo/vgl_rotation_3d.h>
00006 #include <vgl/algo/vgl_h_matrix_3d.h>
00007 #include <vnl/vnl_vector_fixed.h>
00008 #include <vnl/vnl_matrix_fixed.h>
00009 static vgl_h_matrix_3d<double> plane_trans(vgl_plane_3d<double> const& plane,
00010                                            vgl_point_3d<double> const& ref_pt)
00011 {
00012   // get the translation that moves the plane to intersect with the origin
00013   // note that calling plane.normal() pre-normalizes the vector so
00014   // scale factor is lost, so form normal directly
00015   vgl_vector_3d<double> n(plane.a(), plane.b(), plane.c());
00016   double mag = n.length();
00017   n/=mag;
00018   double trans = plane.d()/mag;//translate the plane to the origin
00019   // find the rotation needed to align the normal with the positive z axis
00020   vgl_vector_3d<double> z(0, 0, 1.0);
00021   vgl_rotation_3d<double> R(n, z);
00022   vgl_vector_3d<double> t = R*(trans*n);
00023   vgl_h_matrix_3d<double> Tr = R.as_h_matrix_3d();
00024   Tr.set_translation(t.x(), t.y(), t.z());
00025   //note the composition is [R][t], i.e. first translate then rotate
00026   //correct the transformation if the reference point is inverse transformed
00027   //to negative z
00028   vgl_h_matrix_3d<double> Trinv = Tr.get_inverse();
00029   vgl_homg_point_3d<double> hp(ref_pt);
00030   vgl_homg_point_3d<double> thp = Trinv(hp);
00031   vgl_point_3d<double> tp(thp);
00032   //This flip is here to standardize the reference point
00033   //(typically a camera center)
00034   //to be in the positive z half space of the x-y plane
00035   if (tp.z()<0) {
00036     vnl_matrix_fixed<double,3, 3> m(0.0);
00037     m[0][0] = -1.0; m[1][1] = 1.0; m[2][2]=-1.0;
00038     vgl_h_matrix_3d<double> Trflip;//180 degree rotation about the y axis
00039     Trflip.set_identity();
00040     Trflip.set_rotation_matrix(m);
00041     Tr = Trflip*Tr;
00042   }
00043   return Tr;
00044 }
00045 
00046 vgl_h_matrix_2d<double> vpgl_camera_homographies::
00047 homography_to_camera(vpgl_proj_camera<double> const& cam,
00048                      vgl_plane_3d<double> const& plane)
00049 {
00050   vgl_homg_point_3d<double> hc = cam.camera_center();
00051   vgl_point_3d<double> cp(hc);
00052   vgl_h_matrix_3d<double> Tr = plane_trans(plane,cp);
00053   vgl_h_matrix_3d<double> Trinv = Tr.get_inverse();
00054   // postmultipy the camera by the inverse
00055   vpgl_proj_camera<double> tcam = postmultiply(cam, Trinv);
00056   // extract the homography (columns 0, 1, and 3)
00057   vnl_matrix_fixed<double, 3, 4> p = tcam.get_matrix();
00058   vnl_matrix_fixed<double, 3, 3> h;
00059   vnl_vector_fixed<double, 3> h0, h1, h2; //columns of h
00060   h0 = p.get_column(0);  h1 = p.get_column(1); h2 = p.get_column(3);
00061   h.set_column(0, h0);   h.set_column(1, h1); h.set_column(2, h2);
00062   vgl_h_matrix_2d<double> H(h);
00063   return H;
00064 }
00065 
00066 //: create a plane projective transformation from the camera image plane to the specified plane
00067 vgl_h_matrix_2d<double> vpgl_camera_homographies::
00068 homography_to_camera(vpgl_perspective_camera<double> const& cam,
00069                      vgl_plane_3d<double> const& plane)
00070 {
00071   vpgl_proj_camera<double> const& pcam =
00072     static_cast<vpgl_proj_camera<double> const&>(cam);
00073   return vpgl_camera_homographies::homography_to_camera(pcam, plane);
00074 }
00075 
00076 //: create a plane projective transformation from the camera image plane to the specified plane
00077 vgl_h_matrix_2d<double> vpgl_camera_homographies::
00078 homography_from_camera(vpgl_proj_camera<double> const& cam,
00079                        vgl_plane_3d<double> const& plane)
00080 {
00081   vgl_h_matrix_2d<double> H =
00082     vpgl_camera_homographies::homography_to_camera(cam, plane);
00083   return H.get_inverse();
00084 }
00085 
00086 //: create a plane projective transformation from the camera image plane to the specified plane
00087 vgl_h_matrix_2d<double> vpgl_camera_homographies::
00088 homography_from_camera(vpgl_perspective_camera<double> const& cam,
00089                        vgl_plane_3d<double> const& plane)
00090 {
00091   vgl_h_matrix_2d<double> H =
00092     vpgl_camera_homographies::homography_to_camera(cam, plane);
00093   return H.get_inverse();
00094 }
00095 
00096 vpgl_perspective_camera<double> vpgl_camera_homographies::
00097 transform_camera_to_plane(vpgl_perspective_camera<double> const& cam,
00098                           vgl_plane_3d<double> const& plane)
00099 {
00100   vgl_homg_point_3d<double> hc = cam.camera_center();
00101   vgl_point_3d<double> cp(hc);
00102   vgl_h_matrix_3d<double> Tr = plane_trans(plane,cp);
00103   vgl_h_matrix_3d<double> Trinv = Tr.get_inverse();
00104   // postmultipy the camera by the inverse
00105   vpgl_perspective_camera<double> tcam =
00106     vpgl_perspective_camera<double>::postmultiply(cam, Trinv);
00107   return tcam;
00108 }
00109 
00110 vpgl_proj_camera<double> vpgl_camera_homographies::
00111 transform_camera_to_plane(vpgl_proj_camera<double> const& cam,
00112                           vgl_plane_3d<double> const& plane)
00113 {
00114   vgl_homg_point_3d<double> hc = cam.camera_center();
00115   vgl_point_3d<double> cp(hc);
00116   vgl_h_matrix_3d<double> Tr = plane_trans(plane,cp);
00117   vgl_h_matrix_3d<double> Trinv = Tr.get_inverse();
00118   // postmultipy the camera by the inverse
00119   vpgl_proj_camera<double> tcam = postmultiply(cam, Trinv);
00120   return tcam;
00121 }
00122 
00123 vcl_vector<vgl_point_3d<double> > vpgl_camera_homographies::
00124 transform_points_to_plane(vgl_plane_3d<double> const& plane,
00125                           vgl_point_3d<double> const& ref_point,
00126                           vcl_vector<vgl_point_3d<double> > const& pts )
00127 {
00128   vcl_vector<vgl_point_3d<double> > tr_pts;
00129   vgl_h_matrix_3d<double> Tr = plane_trans(plane, ref_point);
00130   for (vcl_vector<vgl_point_3d<double> >::const_iterator pit = pts.begin();
00131        pit != pts.end(); ++pit)
00132   {
00133     vgl_homg_point_3d<double> hp(*pit);
00134     vgl_homg_point_3d<double> tr_hp = Tr(hp);
00135     vgl_point_3d<double> trp(tr_hp);
00136     tr_pts.push_back(trp);
00137   }
00138   return tr_pts;
00139 }