1 #include "vpgl_camera_homographies.h"
2 //:
3 // \file
4 #include "vgl/vgl_vector_3d.h"
5 #include <vgl/algo/vgl_rotation_3d.h>
6 #include <vgl/algo/vgl_h_matrix_3d.h>
7 #include "vnl/vnl_vector_fixed.h"
8 #include "vnl/vnl_matrix_fixed.h"
9 static vgl_h_matrix_3d<double>
plane_trans(vgl_plane_3d<double> const & plane,vgl_point_3d<double> const & ref_pt)10 plane_trans(vgl_plane_3d<double> const & plane, vgl_point_3d<double> const & ref_pt)
11 {
12   // get the translation that moves the plane to intersect with the origin
13   // note that calling plane.normal() pre-normalizes the vector so
14   // scale factor is lost, so form normal directly
15   vgl_vector_3d<double> n(plane.a(), plane.b(), plane.c());
16   double mag = n.length();
17   n /= mag;
18   double trans = plane.d() / mag; // translate the plane to the origin
19   // find the rotation needed to align the normal with the positive z axis
20   vgl_vector_3d<double> z(0, 0, 1.0);
21   vgl_rotation_3d<double> R(n, z);
22   vgl_vector_3d<double> t = R * (trans * n);
23   vgl_h_matrix_3d<double> Tr = R.as_h_matrix_3d();
24   Tr.set_translation(t.x(), t.y(), t.z());
25   // note the composition is [R][t], i.e. first translate then rotate
26   // correct the transformation if the reference point is inverse transformed
27   // to negative z
28   vgl_homg_point_3d<double> hp(ref_pt);
29   vgl_homg_point_3d<double> thp = Tr(hp);
30   vgl_point_3d<double> tp(thp);
31   // This flip is here to standardize the reference point
32   //(typically a camera center)
33   // to be in the positive z half space of the x-y plane
34   if (tp.z() < 0)
35   {
36     vnl_matrix_fixed<double, 3, 3> m(0.0);
37     m[0][0] = -1.0;
38     m[1][1] = 1.0;
39     m[2][2] = -1.0;
40     vgl_h_matrix_3d<double> Trflip; // 180 degree rotation about the y axis
41     Trflip.set_identity();
42     Trflip.set_rotation_matrix(m);
43     Tr = Trflip * Tr;
44   }
45   return Tr;
46 }
47 
48 vgl_h_matrix_2d<double>
homography_to_camera(vpgl_proj_camera<double> const & cam,vgl_plane_3d<double> const & plane)49 vpgl_camera_homographies::homography_to_camera(vpgl_proj_camera<double> const & cam, vgl_plane_3d<double> const & plane)
50 {
51   vgl_homg_point_3d<double> hc = cam.camera_center();
52   vgl_point_3d<double> cp(hc);
53   vgl_h_matrix_3d<double> Tr = plane_trans(plane, cp);
54   vgl_h_matrix_3d<double> Trinv = Tr.get_inverse();
55   // postmultipy the camera by the inverse
56   vpgl_proj_camera<double> tcam = postmultiply(cam, Trinv);
57   // extract the homography (columns 0, 1, and 3)
58   vnl_matrix_fixed<double, 3, 4> p = tcam.get_matrix();
59   vnl_matrix_fixed<double, 3, 3> h;
60   vnl_vector_fixed<double, 3> h0, h1, h2; // columns of h
61   h0 = p.get_column(0);
62   h1 = p.get_column(1);
63   h2 = p.get_column(3);
64   h.set_column(0, h0);
65   h.set_column(1, h1);
66   h.set_column(2, h2);
67   vgl_h_matrix_2d<double> H(h);
68   return H;
69 }
70 
71 //: create a plane projective transformation from the camera image plane to the specified plane
72 vgl_h_matrix_2d<double>
homography_to_camera(vpgl_perspective_camera<double> const & cam,vgl_plane_3d<double> const & plane)73 vpgl_camera_homographies::homography_to_camera(vpgl_perspective_camera<double> const & cam,
74                                                vgl_plane_3d<double> const & plane)
75 {
76   auto const & pcam = static_cast<vpgl_proj_camera<double> const &>(cam);
77   return vpgl_camera_homographies::homography_to_camera(pcam, plane);
78 }
79 
80 //: create a plane projective transformation from the camera image plane to the specified plane
81 vgl_h_matrix_2d<double>
homography_from_camera(vpgl_proj_camera<double> const & cam,vgl_plane_3d<double> const & plane)82 vpgl_camera_homographies::homography_from_camera(vpgl_proj_camera<double> const & cam,
83                                                  vgl_plane_3d<double> const & plane)
84 {
85   vgl_h_matrix_2d<double> H = vpgl_camera_homographies::homography_to_camera(cam, plane);
86   return H.get_inverse();
87 }
88 
89 //: create a plane projective transformation from the camera image plane to the specified plane
90 vgl_h_matrix_2d<double>
homography_from_camera(vpgl_perspective_camera<double> const & cam,vgl_plane_3d<double> const & plane)91 vpgl_camera_homographies::homography_from_camera(vpgl_perspective_camera<double> const & cam,
92                                                  vgl_plane_3d<double> const & plane)
93 {
94   vgl_h_matrix_2d<double> H = vpgl_camera_homographies::homography_to_camera(cam, plane);
95   return H.get_inverse();
96 }
97 
98 vpgl_perspective_camera<double>
transform_camera_to_plane(vpgl_perspective_camera<double> const & cam,vgl_plane_3d<double> const & plane)99 vpgl_camera_homographies::transform_camera_to_plane(vpgl_perspective_camera<double> const & cam,
100                                                     vgl_plane_3d<double> const & plane)
101 {
102   vgl_homg_point_3d<double> hc = cam.camera_center();
103   vgl_point_3d<double> cp(hc);
104   vgl_h_matrix_3d<double> Tr = plane_trans(plane, cp);
105   vgl_h_matrix_3d<double> Trinv = Tr.get_inverse();
106   // postmultipy the camera by the inverse
107   vpgl_perspective_camera<double> tcam = vpgl_perspective_camera<double>::postmultiply(cam, Trinv);
108   return tcam;
109 }
110 
111 vpgl_proj_camera<double>
transform_camera_to_plane(vpgl_proj_camera<double> const & cam,vgl_plane_3d<double> const & plane)112 vpgl_camera_homographies::transform_camera_to_plane(vpgl_proj_camera<double> const & cam,
113                                                     vgl_plane_3d<double> const & plane)
114 {
115   vgl_homg_point_3d<double> hc = cam.camera_center();
116   vgl_point_3d<double> cp(hc);
117   vgl_h_matrix_3d<double> Tr = plane_trans(plane, cp);
118   vgl_h_matrix_3d<double> Trinv = Tr.get_inverse();
119   // postmultipy the camera by the inverse
120   vpgl_proj_camera<double> tcam = postmultiply(cam, Trinv);
121   return tcam;
122 }
123 
124 std::vector<vgl_point_3d<double>>
transform_points_to_plane(vgl_plane_3d<double> const & plane,vgl_point_3d<double> const & ref_point,std::vector<vgl_point_3d<double>> const & pts)125 vpgl_camera_homographies::transform_points_to_plane(vgl_plane_3d<double> const & plane,
126                                                     vgl_point_3d<double> const & ref_point,
127                                                     std::vector<vgl_point_3d<double>> const & pts)
128 {
129   std::vector<vgl_point_3d<double>> tr_pts;
130   vgl_h_matrix_3d<double> Tr = plane_trans(plane, ref_point);
131   for (const auto & pt : pts)
132   {
133     vgl_homg_point_3d<double> hp(pt);
134     vgl_homg_point_3d<double> tr_hp = Tr(hp);
135     vgl_point_3d<double> trp(tr_hp);
136     tr_pts.push_back(trp);
137   }
138   return tr_pts;
139 }
140