ATANCamera.cc
Go to the documentation of this file.
00001 // Copyright 2008 Isis Innovation Limited
00002 #include "ATANCamera.h"
00003 #include <TooN/helpers.h>
00004 #include <cvd/vector_image_ref.h>
00005 #include <iostream>
00006 #include <gvars3/instances.h>
00007 using namespace std;
00008 using namespace CVD;
00009 using namespace GVars3;
00010 
00011 ATANCamera::ATANCamera(TooN::Vector<5> params)
00012 {
00013   // The camera name is used to find the camera's parameters in a GVar.
00014   msName = "Camera";
00015   //mgvvCameraParams = params;
00016   GV2.Register(mgvvCameraParams, "Camera.Parameters",params,HIDDEN | SILENT);
00017   //GV2.Register(mgvvCameraParams, sName+".Parameters", mvDefaultParams, HIDDEN | FATAL_IF_NOT_DEFINED);
00018   mvImageSize[0] = 640.0;
00019   mvImageSize[1] = 480.0;
00020   RefreshParams();
00021 }
00022 
00023 void ATANCamera::SetImageSize(Vector<2> vImageSize)
00024 {
00025   mvImageSize = vImageSize;
00026   RefreshParams();
00027 };
00028 
00029 void ATANCamera::RefreshParams() 
00030 {
00031   // This updates internal member variables according to the current camera parameters,
00032   // and the currently selected target image size.
00033   //
00034   
00035   // First: Focal length and image center in pixel coordinates
00036   mvFocal[0] = mvImageSize[0] * (*mgvvCameraParams)[0];
00037   mvFocal[1] = mvImageSize[1] * (*mgvvCameraParams)[1];
00038   mvCenter[0] = mvImageSize[0] * (*mgvvCameraParams)[2] - 0.5;
00039   mvCenter[1] = mvImageSize[1] * (*mgvvCameraParams)[3] - 0.5;
00040   
00041   // One over focal length
00042   mvInvFocal[0] = 1.0 / mvFocal[0];
00043   mvInvFocal[1] = 1.0 / mvFocal[1];
00044 
00045   // Some radial distortion parameters..
00046   mdW =  (*mgvvCameraParams)[4];
00047   if(mdW != 0.0)
00048     {
00049       md2Tan = 2.0 * tan(mdW / 2.0);
00050       mdOneOver2Tan = 1.0 / md2Tan;
00051       mdWinv = 1.0 / mdW;
00052       mdDistortionEnabled = 1.0;
00053     }
00054   else
00055     {
00056       mdWinv = 0.0;
00057       md2Tan = 0.0;
00058       mdDistortionEnabled = 0.0;
00059     }
00060   
00061   // work out biggest radius in image
00062   Vector<2> v2;
00063   v2[0]= max((*mgvvCameraParams)[2], 1.0 - (*mgvvCameraParams)[2]) / (*mgvvCameraParams)[0];
00064   v2[1]= max((*mgvvCameraParams)[3], 1.0 - (*mgvvCameraParams)[3]) / (*mgvvCameraParams)[1];
00065   mdLargestRadius = invrtrans(sqrt((double)(v2*v2)));
00066   
00067   // At what stage does the model become invalid?
00068   mdMaxR = 1.5 * mdLargestRadius; // (pretty arbitrary)
00069 
00070   // work out world radius of one pixel
00071   // (This only really makes sense for square-ish pixels)
00072   {
00073     Vector<2> v2Center = UnProject(mvImageSize / 2);
00074     Vector<2> v2RootTwoAway = UnProject(mvImageSize / 2 + vec(ImageRef(1,1)));
00075     Vector<2> v2Diff = v2Center - v2RootTwoAway;
00076     mdOnePixelDist = sqrt((double)(v2Diff * v2Diff)) / sqrt(2.0);
00077   }
00078   
00079   // Work out the linear projection values for the UFB
00080   {
00081     // First: Find out how big the linear bounding rectangle must be
00082     vector<Vector<2> > vv2Verts;
00083     vv2Verts.push_back(UnProject(makeVector( -0.5, -0.5)));
00084     vv2Verts.push_back(UnProject(makeVector( mvImageSize[0]-0.5, -0.5)));
00085     vv2Verts.push_back(UnProject(makeVector( mvImageSize[0]-0.5, mvImageSize[1]-0.5)));
00086     vv2Verts.push_back(UnProject(makeVector( -0.5, mvImageSize[1]-0.5)));
00087     Vector<2> v2Min = vv2Verts[0];
00088     Vector<2> v2Max = vv2Verts[0];
00089     for(int i=0; i<4; i++)
00090       for(int j=0; j<2; j++)
00091         {
00092           if(vv2Verts[i][j] < v2Min[j]) v2Min[j] = vv2Verts[i][j];
00093           if(vv2Verts[i][j] > v2Max[j]) v2Max[j] = vv2Verts[i][j];
00094         }
00095     mvImplaneTL = v2Min;
00096     mvImplaneBR = v2Max;
00097     
00098     // Store projection parameters to fill this bounding box
00099     Vector<2> v2Range = v2Max - v2Min;
00100     mvUFBLinearInvFocal = v2Range;
00101     mvUFBLinearFocal[0] = 1.0 / mvUFBLinearInvFocal[0];
00102     mvUFBLinearFocal[1] = 1.0 / mvUFBLinearInvFocal[1];
00103     mvUFBLinearCenter[0] = -1.0 * v2Min[0] * mvUFBLinearFocal[0];
00104     mvUFBLinearCenter[1] = -1.0 * v2Min[1] * mvUFBLinearFocal[1];
00105   }
00106   
00107 }
00108 
00109 // Project from the camera z=1 plane to image pixels,
00110 // while storing intermediate calculation results in member variables
00111 Vector<2> ATANCamera::Project(const Vector<2>& vCam){
00112   mvLastCam = vCam;
00113   mdLastR = sqrt((double)(vCam * vCam));
00114   mbInvalid = (mdLastR > mdMaxR);
00115   mdLastFactor = rtrans_factor(mdLastR);
00116   mdLastDistR = mdLastFactor * mdLastR;
00117   mvLastDistCam = mdLastFactor * mvLastCam;
00118   
00119   mvLastIm[0] = mvCenter[0] + mvFocal[0] * mvLastDistCam[0];
00120   mvLastIm[1] = mvCenter[1] + mvFocal[1] * mvLastDistCam[1];
00121   
00122   return mvLastIm;
00123 }
00124 
00125 // Un-project from image pixel coords to the camera z=1 plane
00126 // while storing intermediate calculation results in member variables
00127 Vector<2> ATANCamera::UnProject(const Vector<2>& v2Im)
00128 {
00129   mvLastIm = v2Im;
00130   mvLastDistCam[0] = (mvLastIm[0] - mvCenter[0]) * mvInvFocal[0];
00131   mvLastDistCam[1] = (mvLastIm[1] - mvCenter[1]) * mvInvFocal[1];
00132   mdLastDistR = sqrt((double)(mvLastDistCam * mvLastDistCam));
00133 
00134   mdLastR = invrtrans(mdLastDistR);
00135   double dFactor;
00136   if(mdLastDistR > 0.01)
00137     dFactor =  mdLastR / mdLastDistR;
00138   else
00139     dFactor = 1.0;
00140   mdLastFactor = 1.0 / dFactor;
00141   mvLastCam = dFactor * mvLastDistCam;
00142   return mvLastCam;
00143 }
00144 
00145 // Utility function for easy drawing with OpenGL
00146 // C.f. comment in top of ATANCamera.h
00147 Matrix<4> ATANCamera::MakeUFBLinearFrustumMatrix(double near, double far)
00148 {
00149   Matrix<4> m4 = Zeros;
00150   
00151 
00152   double left = mvImplaneTL[0] * near;
00153   double right = mvImplaneBR[0] * near;
00154   double top = mvImplaneTL[1] * near;
00155   double bottom = mvImplaneBR[1] * near;
00156   
00157   // The openGhelL frustum manpage is A PACK OF LIES!!
00158   // Two of the elements are NOT what the manpage says they should be.
00159   // Anyway, below code makes a frustum projection matrix
00160   // Which projects a RHS-coord frame with +z in front of the camera
00161   // Which is what I usually want, instead of glFrustum's LHS, -z idea.
00162   m4[0][0] = (2 * near) / (right - left);
00163   m4[1][1] = (2 * near) / (top - bottom);
00164   
00165   m4[0][2] = (right + left) / (left - right);
00166   m4[1][2] = (top + bottom) / (bottom - top);
00167   m4[2][2] = (far + near) / (far - near);
00168   m4[3][2] = 1;
00169   
00170   m4[2][3] = 2*near*far / (near - far);
00171 
00172   return m4;
00173 };
00174 
00175 Matrix<2,2> ATANCamera::GetProjectionDerivs()
00176 {
00177   // get the derivative of image frame wrt camera z=1 frame at the last computed projection
00178   // in the form (d im1/d cam1, d im1/d cam2)
00179   //             (d im2/d cam1, d im2/d cam2)
00180   
00181   double dFracBydx;
00182   double dFracBydy;
00183   
00184   double &k = md2Tan;
00185   double &x = mvLastCam[0];
00186   double &y = mvLastCam[1];
00187   double r = mdLastR * mdDistortionEnabled;
00188   
00189   if(r < 0.01)
00190     {
00191       dFracBydx = 0.0;
00192       dFracBydy = 0.0;
00193     }
00194   else
00195     {
00196       dFracBydx = 
00197         mdWinv * (k * x) / (r*r*(1 + k*k*r*r)) - x * mdLastFactor / (r*r); 
00198       dFracBydy = 
00199         mdWinv * (k * y) / (r*r*(1 + k*k*r*r)) - y * mdLastFactor / (r*r); 
00200     }
00201   
00202   Matrix<2> m2Derivs;
00203   
00204   m2Derivs[0][0] = mvFocal[0] * (dFracBydx * x + mdLastFactor);  
00205   m2Derivs[1][0] = mvFocal[1] * (dFracBydx * y);  
00206   m2Derivs[0][1] = mvFocal[0] * (dFracBydy * x);  
00207   m2Derivs[1][1] = mvFocal[1] * (dFracBydy * y + mdLastFactor);  
00208   return m2Derivs;
00209 }
00210 
00211 Matrix<2,NUMTRACKERCAMPARAMETERS> ATANCamera::GetCameraParameterDerivs()
00212 {
00213   // Differentials wrt to the camera parameters
00214   // Use these to calibrate the camera
00215   // No need for this to be quick, so do them numerically
00216   
00217   Matrix<2, NUMTRACKERCAMPARAMETERS> m2NNumDerivs;
00218   Vector<NUMTRACKERCAMPARAMETERS> vNNormal = *mgvvCameraParams;
00219   Vector<2> v2Cam = mvLastCam;
00220   Vector<2> v2Out = Project(v2Cam);
00221   for(int i=0; i<NUMTRACKERCAMPARAMETERS; i++)
00222     {
00223       if(i == NUMTRACKERCAMPARAMETERS-1 && mdW == 0.0)
00224         continue;
00225       Vector<NUMTRACKERCAMPARAMETERS> vNUpdate;
00226       vNUpdate = Zeros;
00227       vNUpdate[i] += 0.001;
00228       UpdateParams(vNUpdate); 
00229       Vector<2> v2Out_B = Project(v2Cam);
00230       m2NNumDerivs.T()[i] = (v2Out_B - v2Out) / 0.001;
00231       *mgvvCameraParams = vNNormal;
00232       RefreshParams();
00233     }
00234   if(mdW == 0.0)
00235     m2NNumDerivs.T()[NUMTRACKERCAMPARAMETERS-1] = Zeros;
00236   return m2NNumDerivs;
00237 }
00238 
00239 void ATANCamera::UpdateParams(Vector<5> vUpdate)
00240 {
00241   // Update the camera parameters; use this as part of camera calibration.
00242   (*mgvvCameraParams) = (*mgvvCameraParams) + vUpdate;
00243   RefreshParams();
00244 }
00245 
00246 void ATANCamera::DisableRadialDistortion()
00247 {
00248   // Set the radial distortion parameter to zero
00249   // This disables radial distortion and also disables its differentials
00250   (*mgvvCameraParams)[NUMTRACKERCAMPARAMETERS-1] = 0.0;
00251   RefreshParams();
00252 }
00253 
00254 Vector<2> ATANCamera::UFBProject(const Vector<2>& vCam)
00255 {
00256   // Project from camera z=1 plane to UFB, storing intermediate calc results.
00257   mvLastCam = vCam;
00258   mdLastR = sqrt((double)(vCam * vCam));
00259   mbInvalid = (mdLastR > mdMaxR);
00260   mdLastFactor = rtrans_factor(mdLastR);
00261   mdLastDistR = mdLastFactor * mdLastR;
00262   mvLastDistCam = mdLastFactor * mvLastCam;
00263   
00264   mvLastIm[0] = (*mgvvCameraParams)[2]  + (*mgvvCameraParams)[0] * mvLastDistCam[0];
00265   mvLastIm[1] = (*mgvvCameraParams)[3]  + (*mgvvCameraParams)[1] * mvLastDistCam[1];
00266   return mvLastIm;
00267 }
00268 
00269 Vector<2> ATANCamera::UFBUnProject(const Vector<2>& v2Im)
00270 {
00271   mvLastIm = v2Im;
00272   mvLastDistCam[0] = (mvLastIm[0] - (*mgvvCameraParams)[2]) / (*mgvvCameraParams)[0];
00273   mvLastDistCam[1] = (mvLastIm[1] - (*mgvvCameraParams)[3]) / (*mgvvCameraParams)[1];
00274   mdLastDistR = sqrt((double)(mvLastDistCam * mvLastDistCam));
00275   mdLastR = invrtrans(mdLastDistR);
00276   double dFactor;
00277   if(mdLastDistR > 0.01)
00278     dFactor =  mdLastR / mdLastDistR;
00279   else
00280     dFactor = 1.0;
00281   mdLastFactor = 1.0 / dFactor;
00282   mvLastCam = dFactor * mvLastDistCam;
00283   return mvLastCam;
00284 }
00285 
00286 const Vector<NUMTRACKERCAMPARAMETERS> ATANCamera::mvDefaultParams = makeVector(0.5, 0.75, 0.5, 0.5, 0.1);
00287 


tum_ardrone
Author(s):
autogenerated on Sat Jun 8 2019 20:27:22