shot.h
Go to the documentation of this file.
00001 /****************************************************************************
00002 * VCGLib                                                            o o     *
00003 * Visual and Computer Graphics Library                            o     o   *
00004 *                                                                _   O  _   *
00005 * Copyright(C) 2004                                                \/)\/    *
00006 * Visual Computing Lab                                            /\/|      *
00007 * ISTI - Italian National Research Council                           |      *
00008 *                                                                    \      *
00009 * All rights reserved.                                                      *
00010 *                                                                           *
00011 * This program is free software; you can redistribute it and/or modify      *
00012 * it under the terms of the GNU General Public License as published by      *
00013 * the Free Software Foundation; either version 2 of the License, or         *
00014 * (at your option) any later version.                                       *
00015 *                                                                           *
00016 * This program is distributed in the hope that it will be useful,           *
00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
00019 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
00020 * for more details.                                                         *
00021 *                                                                           *
00022 ****************************************************************************/
00023 
00024 
00056 #ifndef __VCGLIB_SHOT
00057 #define __VCGLIB_SHOT
00058 
00059 #include <vcg/space/point2.h>
00060 #include <vcg/space/point3.h>
00061 #include <vcg/math/similarity.h>
00062 #include <vcg/math/camera.h>
00063 
00064 namespace vcg{
00065 
00066 template <class S, class RotationType = Matrix44<S> >
00067 class Shot {
00068 public:
00069   typedef Camera<S> CameraType;
00070   typedef S ScalarType;
00071 
00072   template <class ScalarType, class RotoType >
00073   class ReferenceFrame {
00074     friend class Shot<ScalarType, RotoType>;
00075       RotoType rot;      // rotation
00076       Point3<S> tra; // viewpoint
00077   public:
00078       ReferenceFrame(){}
00079 
00080       void SetIdentity(){ rot.SetIdentity(); tra = Point3<S>(0.0,0.0,0.0);}
00081       void SetTra(const Point3<S> & tr) {tra = tr;}
00082       void SetRot(const  RotoType & rt) {rot = rt;}
00083       Point3<ScalarType>   Tra() const  { return tra;}
00084       RotoType Rot() const  { return rot;}
00085   };
00086 
00087   Camera<S>                            Intrinsics;              // the camera that made the shot
00088   ReferenceFrame<S,RotationType>   Extrinsics;          // the position and orientation of the camera
00089   Shot(const Camera<S> &i, const ReferenceFrame<S,RotationType> &e)
00090   {
00091     Intrinsics = i;
00092     Extrinsics = e;
00093   }
00094 
00095   Shot(const Camera<S> &c)
00096   {
00097     Intrinsics = c;
00098     Extrinsics.SetIdentity();
00099   }
00100 
00101   Shot()
00102   {
00103     Extrinsics.SetIdentity();
00104   }
00105 
00106    template <class Q>
00107    static inline Shot Construct( const Shot<Q> & b )
00108    {
00109      ReferenceFrame<S,RotationType> r;
00110      r.SetRot(Matrix44<S>::Construct(b.Extrinsics.Rot()));
00111      r.SetTra(Point3<S>::Construct(b.Extrinsics.Tra()));
00112      return Shot(Camera<S>::Construct(b.Intrinsics), r);
00113    }
00114 
00115 
00117   vcg::Point3<S> Axis(const int & i)const;
00118 
00120   const vcg::Point3<S> GetViewDir()const;
00122   const vcg::Point3<S> GetViewPoint()const;
00124   void SetViewPoint(const vcg::Point3<S> & viewpoint);
00125 
00127   float GetFovFromFocal();
00128 
00130   void LookAt(const vcg::Point3<S> & point,const vcg::Point3<S> & up);
00131 
00133   void LookAt(const S & eye_x,const S & eye_y,const S & eye_z,
00134         const S & at_x,const S & at_y,const S & at_z,
00135         const S & up_x,const S & up_y,const S & up_z);
00136 
00138   void LookTowards(const vcg::Point3<S> & z_dir,const vcg::Point3<S> & up);
00139 
00140     /* Sometimes the focal is given in pixels. In this case, this function can be used to convert it in millimiters
00141      * given the CCD width (in mm). This method should be moved in vcg::Camera().
00142      * Equivalent focal length is obtained by setting the ccd width to 35 mm.
00143    */
00144   void ConvertFocalToMM(S ccdwidth);
00145 
00146     /* Sometimes the 3D World coordinates are known up to a scale factor. This method adjust the camera/shot parameters
00147      * to account for the re-scaling of the World. If the intrisic parameters are just reasonable values
00148      * the cameras need only a re-positioning.
00149      */
00150   void RescalingWorld(S scalefactor, bool adjustIntrinsics);
00151 
00153   void ApplyRigidTransformation(const Matrix44<S> & M);
00154 
00156   void ApplySimilarity(  Matrix44<S>   M);
00157 
00159   void ApplySimilarity(const Similarity<S> & Sim);
00160 
00162   vcg::Point3<S> ConvertWorldToCameraCoordinates(const vcg::Point3<S> & p) const;
00163 
00165   vcg::Point3<S> ConvertCameraToWorldCoordinates(const vcg::Point3<S> & p) const;
00166 
00167   /* convert a 3d point from camera (do not confuse with the Shot reference frame) to world coordinates
00168    * it uses inverse instead of transpose for non-exactly-rigid rotation matrices (such as calculated by tsai and garcia)
00169    */
00170   vcg::Point3<S> ConvertCameraToWorldCoordinates_Substitute(const vcg::Point3<S> & p) const;
00171 
00173   vcg::Point2<S> Project(const vcg::Point3<S> & p) const;
00174 
00176   vcg::Point3<S> UnProject(const vcg::Point2<S> & p, const S & d) const;
00177 
00178   /* inverse projection from 2d camera viewport (in pixels) to 3d world coordinates (it requires the original depth of the projected point)
00179    * uses inverse instead of trranspose for non-exactly-rigid rotation matrices (such as calculated by tsai and garcia)
00180    */
00181   vcg::Point3<S> UnProject_Substitute(const vcg::Point2<S> & p, const S & d) const;
00182 
00184   S Depth(const vcg::Point3<S> & p)const;
00185 
00186 
00187 // accessors
00188 public:
00189 
00191     Matrix44<S> GetExtrinsicsToWorldMatrix() const
00192     {
00193         Matrix44<S> rotM;
00194         Extrinsics.rot.ToMatrix(rotM);
00195         return Matrix44<S>().SetTranslate(Extrinsics.tra) * rotM.transpose();
00196     }
00197 
00199     Matrix44<S> GetWorldToExtrinsicsMatrix() const
00200     {
00201         Matrix44<S> rotM;
00202         Extrinsics.rot.ToMatrix(rotM);
00203         return rotM * Matrix44<S>().SetTranslate(-Extrinsics.tra) ;
00204     }
00205 
00206   /*  multiply the current reference frame for the matrix passed
00207    note: it is up to the caller to check the the matrix passed is a pure rototraslation
00208    */
00209   void MultMatrix(    vcg::Matrix44<S>    m44)
00210   {
00211     Extrinsics.tra = m44 * Extrinsics.tra;
00212     m44[0][3] = m44[1][3] = m44[2][3] =  0.0; //set no translation
00213     const S k = m44.GetRow3(0).Norm(); //compute scaling (assumed uniform)
00214     Extrinsics.rot = Extrinsics.rot * m44.transpose() * (1/k);
00215   }
00216 
00217   /*  multiply the current reference frame for the similarity passed
00218    note: it is up to the caller to check the the matrix passed is a pure rototraslation
00219    */
00220   void MultSimilarity( const Similarity<S> & s){ MultMatrix(s.Matrix());}
00221 
00222   bool IsValid() const
00223   {
00224     return Intrinsics.PixelSizeMm[0]>0 && Intrinsics.PixelSizeMm[1]>0;
00225   }
00226 
00227 }; // end class definition
00228 
00229 
00230 
00231 template <class S, class RotationType>
00232 const vcg::Point3<S> Shot<S,RotationType>::GetViewDir() const
00233 {
00234   return  Extrinsics.Rot().GetRow3(2);
00235 }
00236 
00237 
00238 
00239 //---
00241 template <class S, class RotationType>
00242 const vcg::Point3<S> Shot<S,RotationType>::GetViewPoint() const
00243 {
00244   return  Extrinsics.tra;
00245 }
00247 template <class S, class RotationType>
00248 void Shot<S,RotationType>::SetViewPoint(const vcg::Point3<S> & viewpoint)
00249 {
00250   Extrinsics.SetTra( viewpoint );
00251 }
00252 //---
00253 
00255 template <class S, class RotationType>
00256 float Shot<S,RotationType>::GetFovFromFocal()
00257 {
00258   double viewportYMm= Intrinsics.PixelSizeMm[1]* Intrinsics.ViewportPx[1];
00259   return 2*(vcg::math::ToDeg(atanf(viewportYMm/(2*Intrinsics.FocalMm))));
00260 }
00261 
00262 //---
00263 
00265 template <class S, class RotationType>
00266 vcg::Point3<S>  Shot<S,RotationType>::Axis(const int & i) const
00267 {
00268   vcg::Matrix44<S> m;
00269   Extrinsics.rot.ToMatrix(m);
00270   vcg::Point3<S> aa = m.GetRow3(i);
00271   return aa;
00272 }
00273 
00275 template <class S, class RotationType>
00276 void Shot<S,RotationType>::LookAt(const vcg::Point3<S> & z_dir,const vcg::Point3<S> & up)
00277 {
00278     LookTowards(z_dir-GetViewPoint(),up);
00279 }
00280 
00282 template <class S, class RotationType>
00283 void Shot<S,RotationType>::LookAt(const S & eye_x, const S & eye_y, const S & eye_z,
00284            const S & at_x, const S & at_y, const S & at_z,
00285            const S & up_x,const S & up_y,const S & up_z)
00286 {
00287   SetViewPoint(Point3<S>(eye_x,eye_y,eye_z));
00288   LookAt(Point3<S>(at_x,at_y,at_z),Point3<S>(up_x,up_y,up_z));
00289 }
00290 
00292 template <class S, class RotationType>
00293 void Shot<S,RotationType>::LookTowards(const vcg::Point3<S> & z_dir,const vcg::Point3<S> & up)
00294 {
00295   vcg::Point3<S> x_dir = up ^-z_dir;
00296   vcg::Point3<S> y_dir = -z_dir ^x_dir;
00297 
00298   Matrix44<S> m;
00299   m.SetIdentity();
00300   *(vcg::Point3<S> *)&m[0][0] =  x_dir/x_dir.Norm();
00301   *(vcg::Point3<S> *)&m[1][0] =  y_dir/y_dir.Norm();
00302   *(vcg::Point3<S> *)&m[2][0] = -z_dir/z_dir.Norm();
00303 
00304   Extrinsics.rot.FromMatrix(m);
00305 }
00306 
00307 //--- Space transformation methods
00308 
00310 template <class S, class RotationType>
00311 vcg::Point3<S> Shot<S,RotationType>::ConvertWorldToCameraCoordinates(const vcg::Point3<S> & p) const
00312 {
00313   Matrix44<S> rotM;
00314   Extrinsics.rot.ToMatrix(rotM);
00315   vcg::Point3<S> cp = rotM * (p - GetViewPoint() );
00316   cp[2]=-cp[2];
00317   return cp;
00318   }
00319 
00321 template <class S, class RotationType>
00322 vcg::Point3<S> Shot<S,RotationType>::ConvertCameraToWorldCoordinates(const vcg::Point3<S> & p) const
00323 {
00324   Matrix44<S> rotM;
00325   vcg::Point3<S> cp = p;
00326   cp[2]=-cp[2];
00327   Extrinsics.rot.ToMatrix(rotM);
00328   cp = rotM.transpose() * cp + GetViewPoint();
00329   return cp;
00330 }
00331 
00333 template <class S, class RotationType>
00334 vcg::Point3<S> Shot<S,RotationType>::ConvertCameraToWorldCoordinates_Substitute(const vcg::Point3<S> & p) const
00335 {
00336   Matrix44<S> rotM;
00337   vcg::Point3<S> cp = p;
00338   cp[2]=-cp[2];
00339   Extrinsics.rot.ToMatrix(rotM);
00340   cp = Inverse(rotM) * cp + GetViewPoint();
00341   return cp;
00342 }
00343 
00345 template <class S, class RotationType>
00346 vcg::Point2<S> Shot<S,RotationType>::Project(const vcg::Point3<S> & p) const
00347 {
00348   Point3<S> cp = ConvertWorldToCameraCoordinates(p);
00349   Point2<S> pp = Intrinsics.Project(cp);
00350   Point2<S> vp = Intrinsics.LocalToViewportPx(pp);
00351   return vp;
00352 }
00353 
00355 template <class S, class RotationType>
00356 vcg::Point3<S> Shot<S,RotationType>::UnProject(const vcg::Point2<S> & p, const S & d) const
00357 {
00358   Point2<S> lp = Intrinsics.ViewportPxToLocal(p);
00359   Point3<S> cp = Intrinsics.UnProject(lp,d);
00360   Point3<S> wp = ConvertCameraToWorldCoordinates(cp);
00361   return wp;
00362 }
00363 
00364 /* inverse projection from 2d camera viewport (in pixels) to 3d world coordinates (it requires the original depth of the projected point)
00365  * uses inverse instead of trranspose for non-exactly-rigid rotation matrices (such as calculated by tsai and garcia)
00366  */
00367 template <class S, class RotationType>
00368 vcg::Point3<S> Shot<S,RotationType>::UnProject_Substitute(const vcg::Point2<S> & p, const S & d) const
00369 {
00370   Point2<S> lp = Intrinsics.ViewportPxToLocal(p);
00371   Point3<S> cp = Intrinsics.UnProject(lp,d);
00372   Point3<S> wp = ConvertCameraToWorldCoordinates_Substitute(cp);
00373   return wp;
00374 }
00375 
00377 template <class S, class RotationType>
00378 S Shot<S,RotationType>::Depth(const vcg::Point3<S> & p)const
00379 {
00380   return ConvertWorldToCameraCoordinates(p).Z();
00381 }
00382 
00383 /* Sometimes the focal is given in pixels. In this case, this function can be used to convert it in millimiters
00384  * given the CCD width (in mm). This method should be moved in vcg::Camera().
00385  * Equivalent focal length is obtained by setting the ccd width to 35 mm.
00386  */
00387 template <class S, class RotationType>
00388 void Shot<S, RotationType>::ConvertFocalToMM(S ccdwidth)
00389 {
00390   double ccd_width = ccdwidth; // ccd is assumed conventionally to be 35mm
00391   double ccd_height = (ccd_width * Intrinsics.ViewportPx[1]) / Intrinsics.ViewportPx[0];
00392   Intrinsics.PixelSizeMm[0] = (ccd_width / Intrinsics.ViewportPx[0]);
00393   Intrinsics.PixelSizeMm[1] = (ccd_height / Intrinsics.ViewportPx[1]);
00394   Intrinsics.FocalMm = (ccd_width * Intrinsics.FocalMm) / Intrinsics.ViewportPx[0];  // NOW FOCAL IS IN MM
00395 }
00396 
00397 /* Sometimes the 3D World coordinates are known up to a scale factor. This method adjust the camera/shot parameters
00398  * to account for the re-scaling of the World. If the intrisic parameters are just reasonable values
00399  * the cameras need only a re-positioning.
00400  */
00401 template <class S, class RotationType>
00402 void Shot<S, RotationType>::RescalingWorld(S scalefactor, bool adjustIntrinsics)
00403 {
00404     // adjust INTRINSICS (if required)
00405 
00406         if (adjustIntrinsics)
00407         {
00408             Intrinsics.FocalMm = Intrinsics.FocalMm * scalefactor;
00409             double ccdwidth = static_cast<double>(Intrinsics.ViewportPx[0] * Intrinsics.PixelSizeMm[0]);
00410             double ccdheight = static_cast<double>(Intrinsics.ViewportPx[1] * Intrinsics.PixelSizeMm[1]);
00411 
00412             Intrinsics.PixelSizeMm[0] = (ccdwidth * scalefactor) / Intrinsics.ViewportPx[0];
00413             Intrinsics.PixelSizeMm[1] = (ccdheight * scalefactor) / Intrinsics.ViewportPx[1];
00414         }
00415 
00416     // adjust EXTRINSICS
00417 
00418     // rotation remains the same (!)
00419     // nothing to do..
00420 
00421     // the viewpoint should be modified according to the scale factor
00422     Extrinsics.tra *= scalefactor;
00423 }
00424 
00426 template <class S, class RotationType>
00427 void Shot<S, RotationType>::ApplyRigidTransformation(const Matrix44<S> & M)
00428 {
00429   Matrix44<S> rotM;
00430   Extrinsics.rot.ToMatrix(rotM);
00431   // roto-translate the viewpoint
00432   Extrinsics.tra = M * Extrinsics.tra;
00433   Matrix44<S> newRot = rotM * M.transpose();
00434   newRot[3][0] =  newRot[3][1] =  newRot[3][2] = 0.0;
00435 
00436   Extrinsics.SetRot(newRot);
00437 }
00438 
00440 template <class S, class RotationType>
00441 void Shot<S, RotationType>::ApplySimilarity( Matrix44<S>   M)
00442 {
00443   Matrix44<S> rotM;
00444   Extrinsics.rot.ToMatrix(rotM);
00445 
00446   // normalize
00447   M = M * (1/M.ElementAt(3,3));
00448   M[3][3] = 1; // just for numeric precision
00449 
00450   // compute scale factor
00451   ScalarType scalefactor = 1.0 / pow(ScalarType(M.Determinant()),1/ScalarType(3.0));
00452 
00453   // roto-translate the viewpoint
00454   Extrinsics.tra = M * Extrinsics.tra;
00455 
00456   vcg::Matrix44<S> M2 = M;
00457 
00458   M2 = M2 * scalefactor;                                // remove the scaling
00459   M2[3][3] = 1.0;
00460   M2[0][3] = M2[1][3] = M2[2][3] = 0;   // remove the translation
00461 
00462   rotM = rotM * M2.transpose();
00463   Extrinsics.SetRot(rotM);
00464 }
00465 
00467 template <class S, class RotationType>
00468 void Shot<S, RotationType>::ApplySimilarity(const Similarity<S> & Sm)
00469 {
00470   Matrix44<S> rotM;
00471   Extrinsics.rot.ToMatrix(rotM);
00472 
00473   // similarity decomposition
00474   vcg::Matrix44<S> R;
00475   Sm.rot.ToMatrix(R);
00476   vcg::Matrix44<S> T;
00477   T.SetIdentity();
00478   T.ElementAt(0,3) = Sm.tra[0];
00479   T.ElementAt(1,3) = Sm.tra[1];
00480   T.ElementAt(2,3) = Sm.tra[2];
00481   vcg::Matrix44d S44;
00482   S44.SetIdentity();
00483   S44 *= Sm.sca;
00484   S44.ElementAt(3,3) = 1.0;
00485 
00486   vcg::Matrix44<S> M = T * R * S44;
00487 
00488   // roto-translate the viewpoint
00489   Extrinsics.tra = M * Extrinsics.tra;
00490 
00491   vcg::Matrix44<S> M2 = M;
00492 
00493   M2 = M2 * (1.0 / Sm.sca);
00494 
00495   Extrinsics.rot = rotM * M2.transpose();
00496 
00497   Extrinsics.rot.ElementAt(3,0) = 0;
00498   Extrinsics.rot.ElementAt(3,1) = 0;
00499   Extrinsics.rot.ElementAt(3,2) = 0;
00500   Extrinsics.rot.ElementAt(3,3) = 1;
00501 
00502 }
00503 
00504 
00505 //--------------------------------
00506 
00507 
00508 //--- utility definitions
00509 typedef  Shot<float> Shotf;
00510 typedef  Shot<double> Shotd;
00511 //-----------------------
00512 
00513 } // end name space
00514 
00515 #endif
00516 
00517 
00518 
00519 


shape_reconstruction
Author(s): Roberto Martín-Martín
autogenerated on Sat Jun 8 2019 18:35:22