1 // This is core/vpgl/vpgl_perspective_camera.h
2 #ifndef vpgl_perspective_camera_h_
3 #define vpgl_perspective_camera_h_
4 //:
5 // \file
6 // \brief A class for the perspective camera model.
7 // \author Thomas Pollard
8 // \date Jan 28, 2005
9 // \author Joseph Mundy, Matt Leotta, Vishal Jain
10 //
11 // \verbatim
12 //  Modifications
13 //   May 08, 2005  Ricardo Fabbri   Added binary I/O support
14 //   May 08, 2005  Ricardo Fabbri   Added == operator
15 //   Feb  8, 2007  Thomas Pollard   Added finite backproject method.
16 //   Mar 16, 2007  Matt Leotta      Replaced vgl_h_matrix_3d with vgl_rotation_3d for rotation
17 //   May 31, 2011  Peter Vanroose   Added homg-coord. "backproject()" method
18 // \endverbatim
19 
20 #include <iosfwd>
21 #include <vnl/vnl_fwd.h>
22 #include <vgl/vgl_fwd.h>
23 #include <vgl/vgl_point_3d.h>
24 #include <vgl/vgl_homg_point_3d.h>
25 #include <vgl/algo/vgl_rotation_3d.h>
26 #include <vgl/vgl_ray_3d.h>
27 #include <vgl/vgl_frustum_3d.h>
28 #ifdef _MSC_VER
29 #  include <vcl_msvc_warnings.h>
30 #endif
31 
32 #include "vpgl_proj_camera.h"
33 #include "vpgl_calibration_matrix.h"
34 
35 
36 //: This class implements the perspective camera class as described in Hartley & Zisserman as a finite camera.
37 //  This is the camera model based on three objects:
38 //  the camera calibration matrix (see "vpgl_calibration_matrix.h"), the camera center,
39 //  and the rotation of the camera from its canonical orientation staring down the
40 //  positive z axis.
41 //
42 //  All rotation matrices entered will be checked that they are indeed rotations, i.e.
43 //  that R.transpose()*R = Identity and in the form:
44 //  \verbatim
45 //   [ R 0 ]
46 //   [ 0 1 ]
47 //  \endverbatim
48 //
49 // \verbatim
50 //  Modifications
51 //   Feb 12, 2007  Thomas Pollard   Added finite backprojection method.
52 // \endverbatim
53 //
54 //  For adding to this class:
55 //
56 //  Be sure to call recompute_matrix in your member functions any time you change any of the
57 //  camera parameters.
58 template <class T>
59 class vpgl_perspective_camera : public vpgl_proj_camera<T>
60 {
61  public:
62   //: Default constructor
63   // Makes a camera at the origin with no rotation and default calibration matrix.
64   vpgl_perspective_camera();
65 
66   //: Main constructor takes all of the camera parameters.
67   vpgl_perspective_camera( const vpgl_calibration_matrix<T>& K,
68                            const vgl_point_3d<T>& camera_center,
69                            vgl_rotation_3d<T>  R );
70 
71   //: Main constructor based on K[R|t]
72   vpgl_perspective_camera( const vpgl_calibration_matrix<T>& K,
73                            vgl_rotation_3d<T>  R,
74                            const vgl_vector_3d<T>& t);
75 
76 
77   //: Copy constructor
78   vpgl_perspective_camera( const vpgl_perspective_camera& cam );
79 
80   //: Destructor
81   ~vpgl_perspective_camera() override = default;
82 
type_name()83   std::string type_name() const override { return "vpgl_perspective_camera"; }
84 
85   //: Clone `this': creation of a new object and initialization
86   // legal C++ because the return type is covariant with vpgl_camera<T>*
87   vpgl_perspective_camera<T> *clone() const override;
88 
89   //: Finite backprojection.
90   // This is a virtual function from the parent class vpgl_proj_camera<T>
91   vgl_homg_line_3d_2_points<T> backproject(const vgl_homg_point_2d<T>& image_point ) const override;
92   //: Finite backprojection.
93   vgl_line_3d_2_points<T> backproject( const vgl_point_2d<T>& image_point ) const;
94   //: Finite backprojection.
backproject(T u,T v)95   vgl_line_3d_2_points<T> backproject(T u, T v) const
96     {return backproject(vgl_point_2d<T>(u, v));}
97 
98   /* suppress
99    * warning: 'vpgl_perspective_camera<double>::backproject_ray' hides overloaded virtual function [-Woverloaded-virtual]
100    * by explicitly acknowledging the parent class virtual function of the same name with different parameters.
101    * that is not overrriden here
102    */
103   using vpgl_proj_camera<T>::backproject_ray;
104 
105   //: Finite ray backprojection.
106   vgl_ray_3d<T> backproject_ray( const vgl_point_2d<T>& image_point ) const ;
107 
108   //: Finite ray backprojection at u v.
backproject_ray(T u,T v)109   vgl_ray_3d<T> backproject_ray(T u, T v) const
110     {return backproject_ray(vgl_point_2d<T>(u, v));}
111 
112   //: Compute the principal axis.
113   // i.e. the vector perpendicular to the image plane pointing towards the front of the camera.
114   vgl_vector_3d<T> principal_axis() const;
115 
116   //: Determine whether the given point lies in front of the principal plane.
117   bool is_behind_camera( const vgl_homg_point_3d<T>& world_point ) const;
118 
119   //: Setters and getters.
120   void set_calibration( const vpgl_calibration_matrix<T>& K );
121   void set_camera_center( const vgl_point_3d<T>& camera_center );
122   void set_translation(const vgl_vector_3d<T>& t);
123   void set_rotation( const vgl_rotation_3d<T>& R );
get_calibration()124   const vpgl_calibration_matrix<T>& get_calibration() const{ return K_; }
get_camera_center()125   const vgl_point_3d<T>& get_camera_center() const { return camera_center_; }
126   vgl_vector_3d<T> get_translation() const;
get_rotation()127   const vgl_rotation_3d<T>& get_rotation() const{ return R_; }
128 
129   //: Rotate the camera about its center such that it looks at the given point
130   //  The camera should also be rotated about its principal axis such that
131   //  the vertical image direction is closest to \p up in the world
132   void look_at(const vgl_homg_point_3d<T>& point,
133                const vgl_vector_3d<T>& up = vgl_vector_3d<T>(0,0,1));
134 
135   // Redefined virtual functions -------------------------------------------
136 
137   //: Return the known camera center instead of computing it in the base class
camera_center()138   vgl_homg_point_3d<T> camera_center() const override
139   { return vgl_homg_point_3d<T>(camera_center_); }
140 
141   // static public functions -----------------------------------------------
142 
143   //: Post-multiply this perspective camera with a 3-d Euclidean transformation
144   // \todo decide whether this needs to be either a static method or a stand-alone function.
145   // (Now both are present.)
146   static  vpgl_perspective_camera<T>
147     postmultiply( const vpgl_perspective_camera<T>& in_cam,
148                   const vgl_h_matrix_3d<T>& euclid_trans);
149   //: Apply a 3-d Euclidean transformation (transform external cam parameters)
150   static vpgl_perspective_camera<T>
151     postmultiply(const vpgl_perspective_camera<T>& camera,
152                  const vgl_rotation_3d<T>& rot, const vgl_vector_3d<T>& trans);
153 
154   //: Equality test
155   inline bool operator==(vpgl_perspective_camera<T> const &that) const
156   { return this == &that ||
157     (K_ == that.K_ && this->get_matrix()== that.get_matrix() &&
158      camera_center_ == that.camera_center_ && this->R_.as_matrix() == that.R_.as_matrix()); }
159 
160   // -------------------- I/O :---------------------
161 
162   //: Save in ascii format
163   void save(std::string cam_path) override;
164 
165 
166   //: Return `this' if `this' is a vpgl_perspective_camera, 0 otherwise
167   // This is used by e.g. the storage class
168   // \todo code for affine camera and other children
cast_to_perspective_camera()169   virtual vpgl_perspective_camera<T> *cast_to_perspective_camera() {return this;}
cast_to_perspective_camera()170   virtual const vpgl_perspective_camera<T> *cast_to_perspective_camera() const {return this;}
171 
172  protected:
173   //: Recalculate the 3x4 camera matrix from the parameters.
174   void recompute_matrix();
175 
176   vpgl_calibration_matrix<T> K_;
177   vgl_point_3d<T> camera_center_;
178   vgl_rotation_3d<T> R_;
179 };
180 
181 // External Functions:-------------------------------------------------------------
182 
183 //: Write vpgl_perspective_camera to stream
184 template <class Type>
185 std::ostream&  operator<<(std::ostream& s, vpgl_perspective_camera<Type> const& p);
186 
187 //: Read vpgl_perspective_camera  from stream
188 template <class Type>
189 std::istream&  operator>>(std::istream& s, vpgl_perspective_camera<Type>& p);
190 
191 //: Write vpgl_perspective_camera to a vrml file, does not write a vrml header, only the camera, the camera center sphere has radius rad
192 template <class Type>
193 void vrml_write(std::ostream& s, vpgl_perspective_camera<Type> const& p, double rad);
194 
195 //: Decompose camera into parameter blocks.
196 // Attempts to decompose a 3x4 camera matrix into the parameter blocks that describe
197 // a perspective camera, but will only work if the supplied matrix has a left 3x3
198 // submatrix with rank 3.
199 template <class T>
200 bool vpgl_perspective_decomposition( const vnl_matrix_fixed<T,3,4>& camera_matrix,
201                                      vpgl_perspective_camera<T>& p_camera );
202 
203 //: Changes the coordinate system of camera p1 such that the same change would transform p0 to K[I|0].
204 template <class T>
205 vpgl_perspective_camera<T> vpgl_align_down( const vpgl_perspective_camera<T>& p0,
206                                             const vpgl_perspective_camera<T>& p1 );
207 
208 //: Changes the coordinate system of camera p1 such that the same change would transform K[I|0] to p0.
209 template <class T>
210 vpgl_perspective_camera<T> vpgl_align_up( const vpgl_perspective_camera<T>& p0,
211                                           const vpgl_perspective_camera<T>& p1 );
212 
213 template <class T>
214 double vpgl_persp_cam_distance( const vpgl_perspective_camera<T>& cam1, const vpgl_perspective_camera<T>& cam2);
215 
216 template <class T>
217 vpgl_perspective_camera<T>
postmultiply(const vpgl_perspective_camera<T> & in_cam,const vgl_h_matrix_3d<T> & euclid_trans)218 postmultiply( const vpgl_perspective_camera<T>& in_cam,
219               const vgl_h_matrix_3d<T>& euclid_trans)
220 {
221   return vpgl_perspective_camera<T>::postmultiply(in_cam, euclid_trans);
222 }
223 
224 //: Return a list of camera's, loaded from the (name sorted) files from the given directory
225 template <class T>
226 std::vector<vpgl_perspective_camera<T> > cameras_from_directory(std::string dir, T);
227 
228 //: compute the frustrum of the camera view cone. The near plane
229 //  the far plane distances are user defined.
230 template <class T>
231 vgl_frustum_3d<T> frustum(vpgl_perspective_camera<T> const& cam,
232                           T d_near, T d_far);
233 
234 template <class T>
235 vgl_vector_3d<T> vpgl_persp_cam_base_line_vector( const vpgl_perspective_camera<T>& cam1, const vpgl_perspective_camera<T>& cam2);
236 
237 //: compute rotation such that principal_vector1 = R*principal_vector2
238 template <class T>
239 vgl_rotation_3d<T> vpgl_persp_cam_relative_orientation( const vpgl_perspective_camera<T>& cam1, const vpgl_perspective_camera<T>& cam2);
240 
241 #endif // vpgl_perspective_camera_h_
242