OSVR-Core
CameraParameters.h
Go to the documentation of this file.
1 
11 // Copyright 2015 Sensics, Inc.
12 //
13 // Licensed under the Apache License, Version 2.0 (the "License");
14 // you may not use this file except in compliance with the License.
15 // You may obtain a copy of the License at
16 //
17 // http://www.apache.org/licenses/LICENSE-2.0
18 //
19 // Unless required by applicable law or agreed to in writing, software
20 // distributed under the License is distributed on an "AS IS" BASIS,
21 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 // See the License for the specific language governing permissions and
23 // limitations under the License.
24 
25 #ifndef INCLUDED_CameraParameters_h_GUID_5BBC6151_6C1F_44B1_14FC_34CB6BF601E9
26 #define INCLUDED_CameraParameters_h_GUID_5BBC6151_6C1F_44B1_14FC_34CB6BF601E9
27 
28 // Internal Includes
29 // - none
30 
31 // Library/third-party includes
33 #include <opencv2/core/core.hpp>
34 
35 // Standard includes
36 #include <initializer_list>
37 #include <vector>
38 
39 namespace osvr {
40 namespace vbtracker {
43  CameraParameters(double fx, double fy, cv::Size size,
44  std::initializer_list<double> distortionParams)
45  : cameraMatrix(cv::Matx33d::eye()),
46  distortionParameters(distortionParams), imageSize(size) {
47  cameraMatrix(0, 0) = fx;
48  cameraMatrix(1, 1) = fy;
49  cameraMatrix(0, 2) = size.width / 2.;
50  cameraMatrix(1, 2) = size.height / 2.;
51  normalizeDistortionParameters();
52  }
53 
55  CameraParameters(double focalLength, cv::Size size,
56  std::initializer_list<double> distortionParams)
57  : CameraParameters(focalLength, focalLength, size,
58  distortionParams) {}
59 
61  CameraParameters(double fx, double fy, cv::Size size)
62  : CameraParameters(fx, fy, size, {0., 0., 0., 0., 0.}) {}
63 
65  CameraParameters(double focalLength = 700,
66  cv::Size size = cv::Size(640, 480))
67  : CameraParameters(focalLength, focalLength, size) {}
68 
71  // copy
72  auto ret = *this;
73  // zero the distortion
74  ret.distortionParameters.clear();
75  ret.normalizeDistortionParameters();
76  return ret;
77  }
78 
79  double focalLengthX() const { return cameraMatrix(0, 0); }
80  double focalLengthY() const { return cameraMatrix(1, 1); }
81  double focalLength() const { return focalLengthX(); }
82  double k1() const { return distortionParameters[0]; }
83  double k2() const { return distortionParameters[1]; }
84  double k3() const { return distortionParameters[2]; }
85  cv::Point2d principalPoint() const {
86  return cv::Point2d(cameraMatrix(0, 2), cameraMatrix(1, 2));
87  }
88 
89  Eigen::Vector2d eiPrincipalPoint() const {
90  return Eigen::Vector2d(cameraMatrix(0, 2), cameraMatrix(1, 2));
91  }
92 
93  cv::Matx33d cameraMatrix;
94  std::vector<double> distortionParameters;
95  cv::Size imageSize;
96 
97  private:
98  void normalizeDistortionParameters() {
100  distortionParameters.resize(5, 0.);
101  }
102  };
103 
104  inline CameraParameters getSimulatedHDKCameraParameters() {
105 
106  // The fake tracker uses real LED positions and a
107  // simulated camera, whose parameters we describe here.
108  // Here's where we get 700 for the focal length:
109  // The aspect ratio of the camera in Blender is determined by two
110  // parameters:
111  // the focal length(which defaults to 35mm) and the sensor size (which
112  // is set on the camera control panel, and defaults to 32 in my
113  // version). This is the horizontal size of the image sensor in mm,
114  // according to the pop-up info box. The model in OpenCV only has the
115  // focal length as a parameter. So the question becomes how to set the
116  // sensor size in Blender to match what OpenCV is expecting. The basic
117  // issue is that the camera matrix in OpenCV stores the focal length
118  // in pixel units, not millimeters. For the default image sensor width
119  // of 32mm, and an image resolution of 640x480, we compute the OpenCV
120  // focal length as follows: 35mm * (640 pixels / 32 mm) = 700 pixels.
121  // The resulting camera matrix would be: { {700, 0, 320}, {0, 700, 240},
122  // {0, 0, 1} }
123  return CameraParameters(700, cv::Size(640, 480));
124  }
125 
127  // See http://paulbourke.net/miscellaneous/lens/ for diagram.
128  // The focal length of a lens is the distance from the center of
129  // the lens to the point at which objects and infinity focus. The
130  // horizontal field of view = 2 * atan (0.5 * width / focal length).
131  // hFOV / 2 = atan( 0.5 * W / FL )
132  // tan (hFOV / 2) = 0.5 * W / FL
133  // 2 * tan (hFOV/2) = W / FL
134  // FL = W / ( 2 * tan(hFOV/2) )
135  // We want the focal length in units of pixels. The manufacturer
136  // tells us that the optical FOV is 82.9 degrees; we assume that
137  // this is a diagonal measurement. Since the camera resolution is
138  // 640x480 pixels, the diagonal is sqrt( 640*640 + 480*480 ) = 800.
139  // If we use the equation above, but compute the diagonal focal
140  // length (they are linearly related), we get
141  // FL = 800 / ( 2 * tan(82.9/2) )
142  // FL = 452.9
143  // Testing with the tracked position when the unit was about 10
144  // inches from the camera and nearly centered produced a Z estimate
145  // of 0.255, where 0.254 is expected. This is well within the
146  // ruler-based method of estimating 10 inches, so seems to be
147  // correct.
148 
149  // Distortion correction comes from the following data points:
150  // (first column is distance from center in units of millimeters;
151  // second column is distortion in percent).
152  // 1.19 0.944444444
153  // 1.104 1.152777778
154  // 1.032 1.319444444
155  // 0.89 1.430555556
156  // 0.642 1.833333333
157  // 0.514 2.041666667
158  // 0.368 2.347222222
159  // 0.302 2.347222222
160  // 0.208 1.861111111
161  // 0.082 0.666666667
162  // 0.004 0.027777778
163  // 0 0
164  // Convert these to a function as follows:
165  // -The sensor is 640x480 with 3 micron pixels.
166  // -Center of the sensor is (320, 240)
167  // -So, for instance, if you have a pixel at (500,400), it is (180,
168  // 160) pixels away from the center so sqrt(180x180 + 160x160) =
169  // 240.83 pixels.
170  // This means 240.83 x 3 = 722.49 microns or 0.72249 mm.
171  // Thus, you read 0.722 on the left column and you get the
172  // distortion value in percent by reading from the right column.
173  // -Multiply (@todo or divide, I'm never certain) the distance by
174  // (1 + that factor)
175  // (That's the real radius.)
176  // That conversion followed by multiplying back to pixel units
177  // results in the following camera-pixel to actual-location mapping
178  // (inverting the order, so the center is at the top):
179  // 0.000 0.000
180  // 1.333 1.334
181  // 27.333 27.516
182  // 69.333 70.624
183  // 100.667 103.030
184  // 122.667 125.546
185  // 171.333 174.831
186  // 214.000 217.923
187  // 296.667 300.911
188  // 344.000 348.539
189  // 368.000 372.242
190  // 396.667 400.413
191  // The k1-k3 coefficients we want to solve for are the ones that
192  // solve the equation: rCorrected = r(1 + k1*r^2 + k2*r^4 + k3*r^6)
193  // So, rCorrected/r = 1 + k1*r^2 + k2*r^4 + k3*r^6
194  // So, rCorrected/r - 1 = k1*r^2 + k2*r^4 + k3*r^6
195  // Solving for (rCorrected/r - 1) in the above equations, ignoring
196  // 0, produces the following list of values, where the left column
197  // is r and the right is rCorrected/r - 1:
198  // 1.333 0.000277778
199  // 27.333 0.006666667
200  // 69.333 0.018611111
201  // 100.667 0.023472222
202  // 122.667 0.023472222
203  // 171.333 0.020416667
204  // 214.000 0.018333333
205  // 296.667 0.014305556
206  // 344.000 0.013194444
207  // 368.000 0.011527778
208  // 396.667 0.009444444
209  // (which of course is the second column of the first table /100)
210  // Using the "R" programming environment to solve for the k1, k2, k3
211  // for the equation Y = k1*x^2 + k2*x^4 + x3*x^6, where X = r (left
212  // column) and Y = rCorrected/2-1 (right column):
213  // R code:
214  /*
215  x <- c(1.333, 27.333, 69.333, 100.667, 122.667, 171.333, 214.000,
216  296.667, 344.000, 368.000, 396.667)
217  y <- c(0.000277778, 0.006666667, 0.018611111, 0.023472222,
218  0.023472222, 0.020416667, 0.018333333, 0.014305556, 0.013194444,
219  0.011527778, 0.009444444)
220  model <- lm(y~0+I(x^2)+I(x^4)+I(x^6))
221  coefficients(model)
222  */
223  // Output:
224  // I(x^2) I(x^4) I(x^6)
225  // 1.252916e-06 -1.752020e-11 6.405327e-17
226 
227  // The manufacturer specs distortion < 3% on the module and 1.5% on
228  // the lens, so we ignore the distortion where unknown and put in 0
229  // coefficients.
230  double fx = 452.9; // 700.0; // XXX This needs to be in pixels, not mm
233  double k1 = 1.252916e-06;
234  double k2 = -1.752020e-11;
235  double k3 = 6.405327e-17;
236  double p1 = 0;
237  double p2 = 0;
238 
239  return CameraParameters(fx, cv::Size(640, 480), {k1, k2, p1, p2, k3});
240  }
241 } // End namespace vbtracker
242 } // End namespace osvr
243 #endif // INCLUDED_CameraParameters_h_GUID_5BBC6151_6C1F_44B1_14FC_34CB6BF601E9
CameraParameters createUndistortedVariant() const
Copy-constructs, with zero distortion parameters.
Definition: CameraParameters.h:70
The main namespace for all C++ elements of the framework, internal and external.
Definition: namespace_osvr.dox:3
Definition: CameraParameters.h:41
CameraParameters getHDKCameraParameters()
Definition: CameraParameters.h:126
CameraParameters(double focalLength=700, cv::Size size=cv::Size(640, 480))
The zero-distortion constructor, single focal length.
Definition: CameraParameters.h:65
Header wrapping include of <Eigen/Core> and <Eigen/Geometry> for warning quieting.
detail::size< coerce_list< Ts... >> size
Get the size of a list (number of elements.)
Definition: Size.h:56
CameraParameters(double focalLength, cv::Size size, std::initializer_list< double > distortionParams)
Single focal length, distortion specified.
Definition: CameraParameters.h:55
CameraParameters(double fx, double fy, cv::Size size, std::initializer_list< double > distortionParams)
Separate focal lengths, distortion specified.
Definition: CameraParameters.h:43
CameraParameters(double fx, double fy, cv::Size size)
The zero-distortion constructor, separate focal lengths.
Definition: CameraParameters.h:61