SLAMflex SE  0.1.0
SLAMflex provides detection and tracking of dominant planes for smartphone devices. This plane can then be used to show AR content relative to the plane orientation. The detection of plane is performed in the field of view of the smartphone camera. In subsequent frames it is tracked. The interface returns the plane position and orientation.
ATANCamera.cpp
Go to the documentation of this file.
1 // Copyright 2008 Isis Innovation Limited
2 #include "ATANCamera.h"
3 #include "helpers.h"
4 #include "vector_image_ref.h"
5 #include <iostream>
6 
7 using namespace std;
8 using namespace CVD;
9 
11 {
12  msName = sName;
13 // mgvvCameraParams=CameraParameters;
14 //TooN::makeVector(0.92295, 1.28292, 0.497764, 0.490052, 0); -> best vector or calib s far
15  mgvvCameraParams= TooN::makeVector(0.92295, 1.28292, 0.497764, 0.490052, 0);
16  mvImageSize[0] = 640;
17  mvImageSize[1] = 480;
18  RefreshParams();
19 }
20 
22 {
23  mvImageSize = vImageSize;
24  RefreshParams();
25 };
26 
28 {
29  // This updates internal member variables according to the current camera parameters,
30  // and the currently selected target image size.
31  //
32 
33  // First: Focal length and image center in pixel coordinates
34  mvFocal[0] = mvImageSize[0] * mgvvCameraParams[0];
35  mvFocal[1] = mvImageSize[1] * (mgvvCameraParams)[1];
36  mvCenter[0] = mvImageSize[0] * (mgvvCameraParams)[2] - 0.5;
37  mvCenter[1] = mvImageSize[1] * (mgvvCameraParams)[3] - 0.5;
38 
39  // One over focal length
40  mvInvFocal[0] = 1.0 / mvFocal[0];
41  mvInvFocal[1] = 1.0 / mvFocal[1];
42 
43  // Some radial distortion parameters..
44  mdW = (mgvvCameraParams)[4];
45  if(mdW != 0.0)
46  {
47  md2Tan = 2.0 * tan(mdW / 2.0);
48  mdOneOver2Tan = 1.0 / md2Tan;
49  mdWinv = 1.0 / mdW;
50  mdDistortionEnabled = 1.0;
51  }
52  else
53  {
54  mdWinv = 0.0;
55  md2Tan = 0.0;
56  mdDistortionEnabled = 0.0;
57  }
58 
59  // work out biggest radius in image
60  Vector<2> v2;
61  v2[0]= max((mgvvCameraParams)[2], 1.0 - (mgvvCameraParams)[2]) / (mgvvCameraParams)[0];
62  v2[1]= max((mgvvCameraParams)[3], 1.0 - (mgvvCameraParams)[3]) / (mgvvCameraParams)[1];
63  mdLargestRadius = invrtrans(sqrt(v2*v2));
64 
65  // At what stage does the model become invalid?
66  mdMaxR = 1.5 * mdLargestRadius; // (pretty arbitrary)
67 
68  // work out world radius of one pixel
69  // (This only really makes sense for square-ish pixels)
70  {
71  Vector<2> v2Center = UnProject(mvImageSize / 2);
72  Vector<2> v2RootTwoAway = UnProject(mvImageSize / 2 + vec(ImageRef(1,1)));
73  Vector<2> v2Diff = v2Center - v2RootTwoAway;
74  mdOnePixelDist = sqrt(v2Diff * v2Diff) / sqrt(2.0);
75  }
76 
77  // Work out the linear projection values for the UFB
78  {
79  // First: Find out how big the linear bounding rectangle must be
80  vector<Vector<2> > vv2Verts;
81  vv2Verts.push_back(UnProject(makeVector( -0.5, -0.5)));
82  vv2Verts.push_back(UnProject(makeVector( mvImageSize[0]-0.5, -0.5)));
83  vv2Verts.push_back(UnProject(makeVector( mvImageSize[0]-0.5, mvImageSize[1]-0.5)));
84  vv2Verts.push_back(UnProject(makeVector( -0.5, mvImageSize[1]-0.5)));
85  Vector<2> v2Min = vv2Verts[0];
86  Vector<2> v2Max = vv2Verts[0];
87  for(int i=0; i<4; i++)
88  for(int j=0; j<2; j++)
89  {
90  if(vv2Verts[i][j] < v2Min[j]) v2Min[j] = vv2Verts[i][j];
91  if(vv2Verts[i][j] > v2Max[j]) v2Max[j] = vv2Verts[i][j];
92  }
93  mvImplaneTL = v2Min;
94  mvImplaneBR = v2Max;
95 
96  // Store projection parameters to fill this bounding box
97  Vector<2> v2Range = v2Max - v2Min;
98  mvUFBLinearInvFocal = v2Range;
99  mvUFBLinearFocal[0] = 1.0 / mvUFBLinearInvFocal[0];
100  mvUFBLinearFocal[1] = 1.0 / mvUFBLinearInvFocal[1];
101  mvUFBLinearCenter[0] = -1.0 * v2Min[0] * mvUFBLinearFocal[0];
102  mvUFBLinearCenter[1] = -1.0 * v2Min[1] * mvUFBLinearFocal[1];
103  }
104 
105 }
106 
107 // Project from the camera z=1 plane to image pixels,
108 // while storing intermediate calculation results in member variables
110  mvLastCam = vCam;
111  mdLastR = sqrt(vCam * vCam);
112  mbInvalid = (mdLastR > mdMaxR);
113  mdLastFactor = rtrans_factor(mdLastR);
114  mdLastDistR = mdLastFactor * mdLastR;
115  mvLastDistCam = mdLastFactor * mvLastCam;
116 
117  mvLastIm[0] = mvCenter[0] + mvFocal[0] * mvLastDistCam[0];
118  mvLastIm[1] = mvCenter[1] + mvFocal[1] * mvLastDistCam[1];
119 
120  return mvLastIm;
121 }
122 
123 // Un-project from image pixel coords to the camera z=1 plane
124 // while storing intermediate calculation results in member variables
126 {
127  mvLastIm = v2Im;
128  mvLastDistCam[0] = (mvLastIm[0] - mvCenter[0]) * mvInvFocal[0];
129  mvLastDistCam[1] = (mvLastIm[1] - mvCenter[1]) * mvInvFocal[1];
130  mdLastDistR = sqrt(mvLastDistCam * mvLastDistCam);
131  mdLastR = invrtrans(mdLastDistR);
132  double dFactor;
133  if(mdLastDistR > 0.01)
134  dFactor = mdLastR / mdLastDistR;
135  else
136  dFactor = 1.0;
137  mdLastFactor = 1.0 / dFactor;
138  mvLastCam = dFactor * mvLastDistCam;
139  return mvLastCam;
140 }
141 
142 // Utility function for easy drawing with OpenGL
143 // C.f. comment in top of ATANCamera.h
145 {
146  Matrix<4> m4 = Zeros;
147 
148 
149  double left = mvImplaneTL[0] * near;
150  double right = mvImplaneBR[0] * near;
151  double top = mvImplaneTL[1] * near;
152  double bottom = mvImplaneBR[1] * near;
153 
154  // The openGhelL frustum manpage is A PACK OF LIES!!
155  // Two of the elements are NOT what the manpage says they should be.
156  // Anyway, below code makes a frustum projection matrix
157  // Which projects a RHS-coord frame with +z in front of the camera
158  // Which is what I usually want, instead of glFrustum's LHS, -z idea.
159  m4[0][0] = (2 * near) / (right - left);
160  m4[1][1] = (2 * near) / (top - bottom);
161 
162  m4[0][2] = (right + left) / (left - right);
163  m4[1][2] = (top + bottom) / (bottom - top);
164  m4[2][2] = (far + near) / (far - near);
165  m4[3][2] = 1;
166 
167  m4[2][3] = 2*near*far / (near - far);
168 
169  return m4;
170 };
171 
173 {
174  // get the derivative of image frame wrt camera z=1 frame at the last computed projection
175  // in the form (d im1/d cam1, d im1/d cam2)
176  // (d im2/d cam1, d im2/d cam2)
177 
178  double dFracBydx;
179  double dFracBydy;
180 
181  double &k = md2Tan;
182  double &x = mvLastCam[0];
183  double &y = mvLastCam[1];
184  double r = mdLastR * mdDistortionEnabled;
185 
186  if(r < 0.01)
187  {
188  dFracBydx = 0.0;
189  dFracBydy = 0.0;
190  }
191  else
192  {
193  dFracBydx =
194  mdWinv * (k * x) / (r*r*(1 + k*k*r*r)) - x * mdLastFactor / (r*r);
195  dFracBydy =
196  mdWinv * (k * y) / (r*r*(1 + k*k*r*r)) - y * mdLastFactor / (r*r);
197  }
198 
199  Matrix<2> m2Derivs;
200 
201  m2Derivs[0][0] = mvFocal[0] * (dFracBydx * x + mdLastFactor);
202  m2Derivs[1][0] = mvFocal[1] * (dFracBydx * y);
203  m2Derivs[0][1] = mvFocal[0] * (dFracBydy * x);
204  m2Derivs[1][1] = mvFocal[1] * (dFracBydy * y + mdLastFactor);
205  return m2Derivs;
206 }
207 
209 {
210  // Differentials wrt to the camera parameters
211  // Use these to calibrate the camera
212  // No need for this to be quick, so do them numerically
213 
215  Vector<NUMTRACKERCAMPARAMETERS> vNNormal = mgvvCameraParams;
216  Vector<2> v2Cam = mvLastCam;
217  Vector<2> v2Out = Project(v2Cam);
218  for(int i=0; i<NUMTRACKERCAMPARAMETERS; i++)
219  {
220  if(i == NUMTRACKERCAMPARAMETERS-1 && mdW == 0.0)
221  continue;
223  vNUpdate = Zeros;
224  vNUpdate[i] += 0.001;
225  UpdateParams(vNUpdate);
226  Vector<2> v2Out_B = Project(v2Cam);
227  m2NNumDerivs.T()[i] = (v2Out_B - v2Out) / 0.001;
228  mgvvCameraParams = vNNormal;
229  RefreshParams();
230  }
231  if(mdW == 0.0)
232  m2NNumDerivs.T()[NUMTRACKERCAMPARAMETERS-1] = Zeros;
233  return m2NNumDerivs;
234 }
235 
237 {
238  // Update the camera parameters; use this as part of camera calibration.
239  (mgvvCameraParams) = (mgvvCameraParams) + vUpdate;
240  RefreshParams();
241 }
242 
244 {
245  // Set the radial distortion parameter to zero
246  // This disables radial distortion and also disables its differentials
247  mgvvCameraParams[NUMTRACKERCAMPARAMETERS-1] = 0.0;
248  RefreshParams();
249 }
250 
252 {
253  // Project from camera z=1 plane to UFB, storing intermediate calc results.
254  mvLastCam = vCam;
255  mdLastR = sqrt(vCam * vCam);
256  mbInvalid = (mdLastR > mdMaxR);
257  mdLastFactor = rtrans_factor(mdLastR);
258  mdLastDistR = mdLastFactor * mdLastR;
259  mvLastDistCam = mdLastFactor * mvLastCam;
260 
261  mvLastIm[0] = (mgvvCameraParams)[2] + (mgvvCameraParams)[0] * mvLastDistCam[0];
262  mvLastIm[1] = (mgvvCameraParams)[3] + (mgvvCameraParams)[1] * mvLastDistCam[1];
263  return mvLastIm;
264 }
265 
267 {
268  mvLastIm = v2Im;
269  mvLastDistCam[0] = (mvLastIm[0] - (mgvvCameraParams)[2]) / (mgvvCameraParams)[0];
270  mvLastDistCam[1] = (mvLastIm[1] - (mgvvCameraParams)[3]) / (mgvvCameraParams)[1];
271  mdLastDistR = sqrt(mvLastDistCam * mvLastDistCam);
272  mdLastR = invrtrans(mdLastDistR);
273  double dFactor;
274  if(mdLastDistR > 0.01)
275  dFactor = mdLastR / mdLastDistR;
276  else
277  dFactor = 1.0;
278  mdLastFactor = 1.0 / dFactor;
279  mvLastCam = dFactor * mvLastDistCam;
280  return mvLastCam;
281 }
282 
284 
void DisableRadialDistortion()
Definition: ATANCamera.cpp:243
Vector< 2 > Project(const Vector< 2 > &camframe)
Definition: ATANCamera.cpp:109
TooN::Vector< 2 > vec(const ImageRef &ir)
Definition: abs.h:24
Vector< 2 > UnProject(const Vector< 2 > &imframe)
Definition: ATANCamera.cpp:125
Vector< 2 > UFBUnProject(const Vector< 2 > &camframe)
Definition: ATANCamera.cpp:266
Matrix< 4 > MakeUFBLinearFrustumMatrix(double near, double far)
Definition: ATANCamera.cpp:144
static const Vector< NUMTRACKERCAMPARAMETERS > mvDefaultParams
Definition: ATANCamera.h:105
Vector< 1 > makeVector(double x1)
Definition: make_vector.hh:4
Vector< 2 > UFBProject(const Vector< 2 > &camframe)
Definition: ATANCamera.cpp:251
void SetImageSize(Vector< 2 > v2ImageSize)
Definition: ATANCamera.cpp:21
Matrix< 2, NUMTRACKERCAMPARAMETERS > GetCameraParameterDerivs()
Definition: ATANCamera.cpp:208
ATANCamera(std::string sName)
Definition: ATANCamera.cpp:10
#define NUMTRACKERCAMPARAMETERS
Definition: globals.h:12
void UpdateParams(Vector< NUMTRACKERCAMPARAMETERS > vUpdate)
Definition: ATANCamera.cpp:236
Matrix< 2, 2 > GetProjectionDerivs()
Definition: ATANCamera.cpp:172
static Operator< Internal::Zero > Zeros
Definition: objects.h:727
void RefreshParams()
Definition: ATANCamera.cpp:27