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