SLProject  4.3.020
A platform independent 3D computer graphics framework for desktop OS, Android, iOS and online in web browsers
SENSCalibration.cpp
Go to the documentation of this file.
1 /**
2  * \file SENSCalibration.cpp
3  * \authors Michael Goettlicher, Marcus Hudritsch
4  * \date Winter 2016
5  * \remarks Please use clangformat to format the code. See more code style on
6  * https://github.com/cpvrlab/SLProject4/wiki/SLProject-Coding-Style
7  * \copyright http://opensource.org/licenses/GPL-3.0
8  */
9 
10 #include <SENSCalibration.h>
11 #include <Utils.h>
12 #include <HighResTimer.h>
13 #include <opencv2/imgproc.hpp>
14 #include <SENSUtils.h>
15 #include <SENSException.h>
16 //-----------------------------------------------------------------------------
17 //! Increase the _CALIBFILEVERSION each time you change the file format
18 // Version 6, Date: 6.JUL.2019: Added device parameter from Android
20 
21 //-----------------------------------------------------------------------------
22 //creates a fully defined calibration
23 SENSCalibration::SENSCalibration(const cv::Mat& cameraMat,
24  const cv::Mat& distortion,
25  cv::Size imageSize,
26  cv::Size boardSize,
27  float boardSquareMM,
28  float reprojectionError,
29  int numCaptured,
30  const std::string& calibrationTime,
31  int camSizeIndex,
32  bool mirroredH,
33  bool mirroredV,
34  SENSCameraType camType,
35  std::string computerInfos,
36  int calibFlags,
37  bool calcUndistortionMaps)
38  : _cameraMat(cameraMat.clone()),
39  _distortion(distortion.clone()),
40  _imageSize(std::move(imageSize)),
41  _boardSize(std::move(boardSize)),
42  _boardSquareMM(boardSquareMM),
43  _reprojectionError(reprojectionError),
44  _numCaptured(numCaptured),
45  _calibrationTime(calibrationTime),
46  _camSizeIndex(camSizeIndex),
47  _isMirroredH(mirroredH),
48  _isMirroredV(mirroredV),
49  _camType(camType),
50  _computerInfos(std::move(computerInfos)),
51  _calibFlags(calibFlags)
52 {
53  _cameraMatOrig = _cameraMat.clone();
54  _imageSizeOrig = _imageSize;
55 
56  calculateUndistortedCameraMat();
57  calcCameraFovFromUndistortedCameraMat();
58  if (calcUndistortionMaps)
59  buildUndistortionMaps();
60  _state = State::calibrated;
61 }
62 //-----------------------------------------------------------------------------
63 //create a guessed calibration using image size and horizontal fovV angle
64 SENSCalibration::SENSCalibration(const cv::Size& imageSize,
65  float fovH,
66  bool mirroredH,
67  bool mirroredV,
68  SENSCameraType camType,
69  std::string computerInfos)
70  : _isMirroredH(mirroredH),
71  _isMirroredV(mirroredV),
72  _camType(camType),
73  _computerInfos(std::move(computerInfos))
74 {
75  createFromGuessedFOV(imageSize.width, imageSize.height, fovH);
76  _cameraMatUndistorted = _cameraMat.clone();
77  _cameraMatOrig = _cameraMat.clone();
78  _imageSizeOrig = _imageSize;
79  Utils::log("SENSCalibration", "Guessing calibration from fovV: fovH: %f. fovV: %f", _cameraFovHDeg, _cameraFovVDeg);
80 }
81 //-----------------------------------------------------------------------------
82 //create a guessed calibration using sensor size, camera focal length and captured image size
83 SENSCalibration::SENSCalibration(float sensorWMM,
84  float sensorHMM,
85  float focalLengthMM,
86  const cv::Size& imageSize,
87  bool mirroredH,
88  bool mirroredV,
89  SENSCameraType camType,
90  std::string computerInfos)
91  : _isMirroredH(mirroredH),
92  _isMirroredV(mirroredV),
93  _camType(camType),
94  _computerInfos(std::move(computerInfos))
95 {
96  // aspect ratio
97  float devFovH = 2.0f * atan(sensorWMM / (2.0f * focalLengthMM)) * Utils::RAD2DEG;
98  if (devFovH > 60.0f && devFovH < 70.0f)
99  {
100  createFromGuessedFOV(imageSize.width, imageSize.height, devFovH);
101  Utils::log("SENSCalibration", "From physical sensor data: fovH: %f. fovV: %f", _cameraFovHDeg, _cameraFovVDeg);
102  }
103  else
104  {
105  //if not between
106  createFromGuessedFOV(imageSize.width, imageSize.height, 65.0);
107  Utils::log("SENSCalibration", "Guessing calibration from fovV: fovH: %f. fovV: %f", _cameraFovHDeg, _cameraFovVDeg);
108  }
109  _cameraMatUndistorted = _cameraMat.clone();
110  _cameraMatOrig = _cameraMat.clone();
111  _imageSizeOrig = _imageSize;
112 }
113 //-----------------------------------------------------------------------------
114 SENSCalibration::SENSCalibration(const cv::Mat& intrinsics,
115  const cv::Size& imageSize,
116  bool mirroredH,
117  bool mirroredV,
118  SENSCameraType camType,
119  const std::string& computerInfos)
120  : _imageSize(imageSize),
121  _isMirroredH(mirroredH),
122  _isMirroredV(mirroredV),
123  _camType(camType),
124  _computerInfos(computerInfos)
125 {
126  _cameraMatUndistorted = intrinsics.clone();
127  _cameraMatOrig = intrinsics.clone();
128  _cameraMat = intrinsics.clone();
129  _imageSizeOrig = imageSize;
130 
131  _distortion = (cv::Mat_<double>(5, 1) << 0, 0, 0, 0, 0); // No distortion
132  float meanFocalLength = 0.5 * (intrinsics.at<double>(0, 0) + intrinsics.at<double>(1, 1));
133  _cameraFovHDeg = SENS::calcFOVDegFromFocalLengthPix(meanFocalLength, imageSize.width);
134  _cameraFovVDeg = SENS::calcFOVDegFromFocalLengthPix(meanFocalLength, imageSize.height);
135  //_calibrationTime = Utils::getDateTime2String();
136  _state = State::guessed;
137 }
138 //-----------------------------------------------------------------------------
139 SENSCalibration::SENSCalibration(const std::string& calibDir,
140  const std::string& calibFileName,
141  bool calcUndistortionMaps)
142 {
143  if (!load(calibDir, calibFileName, calcUndistortionMaps))
144  throw SENSException(SENSType::CAM, "Could not load calibration file!", __LINE__, __FILE__);
145 }
146 //-----------------------------------------------------------------------------
147 //! Loads the calibration information from the config file
148 /*! Added a flag to disable calculation of undistortion maps because this may take
149  a lot of time for big images on mobile devices
150 */
151 bool SENSCalibration::load(const std::string& calibDir,
152  const std::string& calibFileName,
153  bool calcUndistortionMaps)
154 {
155  //load camera parameter
156  std::string fullPathAndFilename = Utils::unifySlashes(calibDir) + calibFileName;
157 
158  // try to open the local calibration file
159  cv::FileStorage fs(fullPathAndFilename, cv::FileStorage::READ);
160  if (!fs.isOpened())
161  {
162  Utils::log("SLProject", "Calibration : %s", calibFileName.c_str());
163  Utils::log("SLProject", "Calib. created : No. Calib. will be estimated");
164  _numCaptured = 0;
165  _isMirroredH = false;
166  _isMirroredV = false;
167  _reprojectionError = 0;
168  _calibrationTime = "-";
170  _camSizeIndex = -1;
171  return false;
172  }
173 
174  // Reset if new file format version is available
175  int calibFileVersion = 0;
176  fs["CALIBFILEVERSION"] >> calibFileVersion;
177  if (calibFileVersion < _CALIBFILEVERSION)
178  {
179  _numCaptured = 0;
180  _reprojectionError = -1;
181  _calibrationTime = "-";
183  _camSizeIndex = -1;
184  }
185  else
186  {
187  fs["imageSizeWidth"] >> _imageSize.width;
188  fs["imageSizeHeight"] >> _imageSize.height;
189  fs["numCaptured"] >> _numCaptured;
190  fs["isMirroredH"] >> _isMirroredH;
191  fs["isMirroredV"] >> _isMirroredV;
192  fs["cameraMat"] >> _cameraMat;
193  fs["distortion"] >> _distortion;
194  fs["reprojectionError"] >> _reprojectionError;
195  fs["calibrationTime"] >> _calibrationTime;
196  fs["camSizeIndex"] >> _camSizeIndex;
197  fs["boardSizeWidth"] >> _boardSize.width;
198  fs["boardSizeHeight"] >> _boardSize.height;
199  fs["boardSquareMM"] >> _boardSquareMM;
201  }
202 
203  //estimate computer infos
204  if (!fs["computerInfos"].empty())
205  fs["computerInfos"] >> _computerInfos;
206  else
207  {
208  std::vector<std::string> stringParts;
210  if (stringParts.size() >= 3)
211  _computerInfos = stringParts[1];
212  }
213 
214  // close the input file
215  fs.release();
216 
217  //calculate FOV and undistortion maps
218  if (_state == State::calibrated)
219  {
220  //calcCameraFov();
223  if (calcUndistortionMaps)
225  }
226 
227  Utils::log("SLProject", "Calib. loaded : %s", fullPathAndFilename.c_str());
228  Utils::log("SLProject", "Calib. created : %s", _calibrationTime.c_str());
229  Utils::log("SLProject", "Camera FOV H/V : %3.1f/%3.1f", _cameraFovVDeg, _cameraFovHDeg);
230 
231  _cameraMatOrig = _cameraMat.clone();
233 
234  return true;
235 }
236 //-----------------------------------------------------------------------------
237 //! Saves the camera calibration parameters to the config file
238 bool SENSCalibration::save(const std::string& calibDir,
239  const std::string& calibFileName)
240 {
241  std::string fullPathAndFilename = Utils::unifySlashes(calibDir) + calibFileName;
242 
243  cv::FileStorage fs(fullPathAndFilename, cv::FileStorage::WRITE);
244 
245  if (!fs.isOpened())
246  {
247  Utils::log("SLProject", "Failed to write calib. %s", fullPathAndFilename.c_str());
248  return false;
249  }
250 
251  char buf[1024];
252  snprintf(buf, sizeof(buf),
253  "flags:%s%s%s%s%s%s%s",
254  _calibFlags & cv::CALIB_USE_INTRINSIC_GUESS ? " +use_intrinsic_guess" : "",
255  _calibFlags & cv::CALIB_FIX_ASPECT_RATIO ? " +fix_aspectRatio" : "",
256  _calibFlags & cv::CALIB_FIX_PRINCIPAL_POINT ? " +fix_principal_point" : "",
257  _calibFlags & cv::CALIB_ZERO_TANGENT_DIST ? " +zero_tangent_dist" : "",
258  _calibFlags & cv::CALIB_RATIONAL_MODEL ? " +rational_model" : "",
259  _calibFlags & cv::CALIB_THIN_PRISM_MODEL ? " +thin_prism_model" : "",
260  _calibFlags & cv::CALIB_TILTED_MODEL ? " +tilted_model" : "");
261  fs.writeComment(buf, 0);
262 
263  fs << "CALIBFILEVERSION" << _CALIBFILEVERSION;
264  fs << "calibrationTime" << _calibrationTime;
265  fs << "imageSizeWidth" << _imageSize.width;
266  fs << "imageSizeHeight" << _imageSize.height;
267  fs << "boardSizeWidth" << _boardSize.width; // do not reload
268  fs << "boardSizeHeight" << _boardSize.height; // do not reload
269  fs << "boardSquareMM" << _boardSquareMM; // do not reload
270  fs << "numCaptured" << _numCaptured;
271  fs << "calibFlags" << _calibFlags;
272  fs << "isMirroredH" << _isMirroredH;
273  fs << "isMirroredV" << _isMirroredV;
274  fs << "calibFixAspectRatio" << (_calibFlags & cv::CALIB_FIX_ASPECT_RATIO);
275  fs << "calibFixPrincipalPoint" << (_calibFlags & cv::CALIB_FIX_PRINCIPAL_POINT);
276  fs << "calibZeroTangentDist" << (_calibFlags & cv::CALIB_ZERO_TANGENT_DIST);
277  fs << "calibRationalModel" << (_calibFlags & cv::CALIB_RATIONAL_MODEL);
278  fs << "calibTiltedModel" << (_calibFlags & cv::CALIB_TILTED_MODEL);
279  fs << "calibThinPrismModel" << (_calibFlags & cv::CALIB_THIN_PRISM_MODEL);
280  fs << "cameraMat" << _cameraMat;
281  fs << "distortion" << _distortion;
282  fs << "reprojectionError" << _reprojectionError;
283  fs << "cameraFovVDeg" << _cameraFovVDeg;
284  fs << "cameraFovHDeg" << _cameraFovHDeg;
285  fs << "camSizeIndex" << _camSizeIndex;
286  fs << "computerInfos" << _computerInfos;
287 
288  // close file
289  fs.release();
290  Utils::log("SLProject", "Calib. saved : %s", fullPathAndFilename.c_str());
291  return true;
292  //uploadCalibration(fullPathAndFilename);
293 }
294 //-----------------------------------------------------------------------------
295 //! get inscribed and circumscribed rectangle
296 void SENSCalibration::getInnerAndOuterRectangles(const cv::Mat& cameraMatrix,
297  const cv::Mat& distCoeffs,
298  const cv::Mat& R,
299  const cv::Mat& newCameraMatrix,
300  const cv::Size& imgSize,
301  cv::Rect_<float>& inner,
302  cv::Rect_<float>& outer)
303 {
304  const int N = 9;
305  // Fill matrix with N * N sampling points
306  cv::Mat pts(N * N, 2, CV_32F);
307  for (int y = 0, k = 0; y < N; y++)
308  {
309  for (int x = 0; x < N; x++)
310  {
311  pts.at<float>(k, 0) = (float)x * imgSize.width / (N - 1);
312  pts.at<float>(k, 1) = (float)y * imgSize.height / (N - 1);
313  k++;
314  }
315  }
316 
317  pts = pts.reshape(2);
318  cv::undistortPoints(pts, pts, cameraMatrix, distCoeffs, R, newCameraMatrix);
319  pts = pts.reshape(1);
320 
321  float iX0 = -FLT_MAX, iX1 = FLT_MAX, iY0 = -FLT_MAX, iY1 = FLT_MAX;
322  float oX0 = FLT_MAX, oX1 = -FLT_MAX, oY0 = FLT_MAX, oY1 = -FLT_MAX;
323  // find the inscribed rectangle.
324  // the code will likely not work with extreme rotation matrices (R) (>45%)
325  for (int y = 0, k = 0; y < N; y++)
326  for (int x = 0; x < N; x++)
327  {
328  cv::Point2f p = {pts.at<float>(k, 0), pts.at<float>(k, 1)};
329  oX0 = MIN(oX0, p.x);
330  oX1 = MAX(oX1, p.x);
331  oY0 = MIN(oY0, p.y);
332  oY1 = MAX(oY1, p.y);
333 
334  if (x == 0)
335  iX0 = MAX(iX0, p.x);
336  if (x == N - 1)
337  iX1 = MIN(iX1, p.x);
338  if (y == 0)
339  iY0 = MAX(iY0, p.y);
340  if (y == N - 1)
341  iY1 = MIN(iY1, p.y);
342  k++;
343  }
344  inner = cv::Rect_<float>(iX0, iY0, iX1 - iX0, iY1 - iY0);
345  outer = cv::Rect_<float>(oX0, oY0, oX1 - oX0, oY1 - oY0);
346 }
347 
348 //-----------------------------------------------------------------------------
349 //! Builds undistortion maps after calibration or loading
351 {
352  if (_cameraMatUndistorted.rows != 3 || _cameraMatUndistorted.cols != 3)
353  Utils::exitMsg("SLProject",
354  "SENSCalibration::buildUndistortionMaps: No _cameraMatUndistorted available",
355  __LINE__,
356  __FILE__);
357 
358  // Create undistortion maps
359  _undistortMapX.release();
360  _undistortMapY.release();
361 
362  HighResTimer t;
363  cv::initUndistortRectifyMap(_cameraMat,
364  _distortion,
365  cv::Mat(), // Identity matrix R
367  _imageSize,
368  CV_16SC2, //before we had CV_32FC1 but in all tutorials they use CV_16SC2.. is there a reason?
371  Utils::log("SLProject",
372  "initUndistortRectifyMap: %fms",
374 
375  if (_undistortMapX.empty() || _undistortMapY.empty())
376  Utils::exitMsg("SLProject",
377  "SENSCalibration::buildUndistortionMaps failed.",
378  __LINE__,
379  __FILE__);
380 }
381 //-----------------------------------------------------------------------------
382 //! Undistorts the inDistorted image into the outUndistorted
383 void SENSCalibration::remap(cv::Mat& inDistorted,
384  cv::Mat& outUndistorted) const
385 {
386  assert(!inDistorted.empty() &&
387  "Input image is empty!");
388 
389  assert(!_undistortMapX.empty() &&
390  !_undistortMapY.empty() &&
391  "Undistortion Maps are empty!");
392 
393  cv::remap(inDistorted,
394  outUndistorted,
397  cv::INTER_LINEAR);
398 }
399 //-----------------------------------------------------------------------------
400 //! Calculates camera intrinsics from a guessed FOV angle
401 /*! Most laptop-, webcam- or mobile camera have a horizontal view angle or
402  so called field of view (FOV) of around 65 degrees. From this parameter we
403  can calculate the most important intrinsic parameter the focal length. All
404  other parameters are set as if the lens would be perfect: No lens distortion
405  and the view axis goes through the center of the image.
406  If the focal length and sensor size is provided by the device we deduce the
407  the fovV from it.
408  @param imageWidthPX image width in pixels
409  @param imageHeightPX image height in pixels
410  @param fovH average horizontal view angle in degrees
411 */
413  int imageHeightPX,
414  float fovH)
415 {
416  //if (fx == fy) and (cx == imgwidth * 0.5f) and (cy == imgheight * 0.5f)
417  float f = (0.5f * imageWidthPX) / tanf(fovH * 0.5f * Utils::DEG2RAD);
418  float fovV = 2.f * atan(0.5f * imageHeightPX / f) * Utils::RAD2DEG;
419 
420  // Create standard camera matrix
421  // fx, fx, cx, cy are all in pixel values not mm
422  // We asume that we have an ideal image sensor with square pixels
423  // so that the focal length fx and fy are identical
424  // See the OpenCV documentation for more details:
425  // http://docs.opencv.org/3.1.0/dc/dbb/tutorial_py_calibration.html
426 
427  float cx = (float)imageWidthPX * 0.5f;
428  float cy = (float)imageHeightPX * 0.5f;
429  float fx = cx / tanf(fovH * 0.5f * Utils::DEG2RAD);
430  float fy = fx;
431 
432  _imageSize.width = imageWidthPX;
433  _imageSize.height = imageHeightPX;
434  _cameraMat = (cv::Mat_<double>(3, 3) << fx, 0, cx, 0, fy, cy, 0, 0, 1);
435  _distortion = (cv::Mat_<double>(5, 1) << 0, 0, 0, 0, 0); // No distortion
436  _cameraFovHDeg = fovH;
437  _cameraFovVDeg = fovV;
440 }
441 //-----------------------------------------------------------------------------
442 //! Adapts an already calibrated camera to a new resolution (cropping and scaling)
443 void SENSCalibration::adaptForNewResolution(const cv::Size& newSize, bool calcUndistortionMaps)
444 {
446  return;
447 
448  // new center and focal length in pixels not mm
449  float fx, fy, cy, cx;
450 
451  // use original camera matrix for adaptions.
452  // Otherwise we get rounding errors after too many adaptions.
453  float fxOrig = (float)_cameraMatOrig.at<double>(0, 0);
454  float fyOrig = (float)_cameraMatOrig.at<double>(1, 1);
455  float cxOrig = (float)_cameraMatOrig.at<double>(0, 2);
456  float cyOrig = (float)_cameraMatOrig.at<double>(1, 2);
457 
458  if (((float)newSize.width / (float)newSize.height) >
459  ((float)_imageSizeOrig.width / (float)_imageSizeOrig.height))
460  {
461  float scaleFactor = (float)newSize.width / (float)_imageSizeOrig.width;
462 
463  fx = fxOrig * scaleFactor;
464  fy = fyOrig * scaleFactor;
465  float oldHeightScaled = _imageSizeOrig.height * scaleFactor;
466  float heightDiff = (oldHeightScaled - newSize.height) * 0.5f;
467 
468  cx = cxOrig * scaleFactor;
469  cy = cyOrig * scaleFactor - heightDiff;
470  }
471  else
472  {
473  float scaleFactor = (float)newSize.height / (float)_imageSizeOrig.height;
474  fx = fxOrig * scaleFactor;
475  fy = fyOrig * scaleFactor;
476  float oldWidthScaled = _imageSizeOrig.width * scaleFactor;
477  float widthDiff = (oldWidthScaled - newSize.width) * 0.5f;
478 
479  cx = cxOrig * scaleFactor - widthDiff;
480  cy = cyOrig * scaleFactor;
481  }
482 
483  //std::cout << "adaptForNewResolution: _cameraMat before: " << _cameraMat << std::endl;
484  _cameraMat = (cv::Mat_<double>(3, 3) << fx, 0, cx, 0, fy, cy, 0, 0, 1);
485  //std::cout << "adaptForNewResolution: _cameraMat after: " << _cameraMat << std::endl;
486  //_distortion remains unchanged
488 
489  //std::cout << "adaptForNewResolution: _imageSize before: " << _imageSize << std::endl;
490  _imageSize.width = newSize.width;
491  _imageSize.height = newSize.height;
492  //std::cout << "adaptForNewResolution: _imageSize after: " << _imageSize << std::endl;
493 
496  if (calcUndistortionMaps)
498 }
499 //-----------------------------------------------------------------------------
500 //! Calculate a camera matrix that we use for the scene graph and for the reprojection of the undistored image
502 {
503  if (_cameraMat.rows != 3 || _cameraMat.cols != 3)
504  Utils::exitMsg("SLProject", "SENSCalibration::calculateUndistortedCameraMat: No intrinsic parameter available", __LINE__, __FILE__);
505 
506  // An alpha of 0 leads to no black borders
507  // An alpha of 1 leads to black borders
508  // (with alpha equaly zero the augmentation fits best)
509  double alpha = 1.0;
510 
511  bool centerPrinciplePoint = true;
512  if (centerPrinciplePoint)
513  {
514  //Attention: the principle point has to be centered because for the projection matrix we assume that image plane is "symmetrically arranged wrt the focal plane"
515  //(see http://kgeorge.github.io/2014/03/08/calculating-opengl-perspective-matrix-from-opencv-intrinsic-matrix)
516  //_cameraMatUndistorted = cv::getOptimalNewCameraMatrix(_cameraMat, _distortion, _imageSize, alpha, _imageSize, nullptr, centerPrinciplePoint);
517  //! (The following is the algorithm from cv::getOptimalNewCameraMatrix and the code is here for understanding (it does the same))
518 
519  double cx0 = _cameraMat.at<double>(0, 2);
520  double cy0 = _cameraMat.at<double>(1, 2);
521  double cx = (_imageSize.width) * 0.5;
522  double cy = (_imageSize.height) * 0.5;
523 
524  cv::Rect_<float> inner, outer;
526  _distortion,
527  cv::Mat(),
528  _cameraMat,
529  _imageSize,
530  inner,
531  outer);
532 
533  double s0 = std::max(std::max(std::max(cx / (cx0 - inner.x),
534  cy / (cy0 - inner.y)),
535  cx / (inner.x + inner.width - cx0)),
536  cy / (inner.y + inner.height - cy0));
537 
538  double s1 = std::min(std::min(std::min(cx / (cx0 - outer.x),
539  cy / (cy0 - outer.y)),
540  cx / (outer.x + outer.width - cx0)),
541  cy / (outer.y + outer.height - cy0));
542 
543  double s = s0 * (1 - alpha) + s1 * alpha;
544 
546  _cameraMatUndistorted.at<double>(0, 0) *= s;
547  _cameraMatUndistorted.at<double>(1, 1) *= s;
548  _cameraMatUndistorted.at<double>(0, 2) = cx;
549  _cameraMatUndistorted.at<double>(1, 2) = cy;
550  }
551  else
552  {
553  _cameraMatUndistorted = cv::getOptimalNewCameraMatrix(_cameraMat,
554  _distortion,
555  _imageSize,
556  alpha,
557  _imageSize,
558  nullptr,
559  centerPrinciplePoint);
560  }
561 
562  //std::cout << "_cameraMatUndistorted: " << _cameraMatUndistorted << std::endl;
563  //std::cout << "_cameraMat: " << _cameraMat << std::endl;
564 }
565 //-----------------------------------------------------------------------------
566 //! Calculates the vertical field of view angle in degrees
568 {
569  if (_cameraMatUndistorted.rows != 3 || _cameraMatUndistorted.cols != 3)
570  Utils::exitMsg("SLProject", "SENSCalibration::calcCameraFovFromSceneCameraMat: No _cameraMatUndistorted available", __LINE__, __FILE__);
571 
572  //calculate vertical field of view
573  float fx = (float)_cameraMatUndistorted.at<double>(0, 0);
574  float fy = (float)_cameraMatUndistorted.at<double>(1, 1);
575  float cx = (float)_cameraMatUndistorted.at<double>(0, 2);
576  float cy = (float)_cameraMatUndistorted.at<double>(1, 2);
577  _cameraFovHDeg = 2.0f * atan2(cx, fx) * Utils::RAD2DEG;
578  _cameraFovVDeg = 2.0f * atan2(cy, fy) * Utils::RAD2DEG;
579 }
580 //-----------------------------------------------------------------------------
High Resolution Timer class using C++11.
Definition: HighResTimer.h:31
float elapsedTimeInMilliSec()
Definition: HighResTimer.h:38
State _state
calibration state enumeration
int _numCaptured
NO. of images captured.
cv::Mat _undistortMapX
Undistortion float map in x-direction.
bool save(const string &calibDir, const string &calibFileName)
Saves the camera calibration parameters to the config file.
float fy() const
cv::Mat _cameraMatOrig
3x3 Matrix for intrinsic camera matrix (original from loading or calibration estimation)
void buildUndistortionMaps()
Builds undistortion maps after calibration or loading.
void createFromGuessedFOV(int imageWidthPX, int imageHeightPX, float fovH)
Calculates camera intrinsics from a guessed FOV angle.
cv::Mat _cameraMatUndistorted
static void getInnerAndOuterRectangles(const cv::Mat &cameraMatrix, const cv::Mat &distCoeffs, const cv::Mat &R, const cv::Mat &newCameraMatrix, const cv::Size &imgSize, cv::Rect_< float > &inner, cv::Rect_< float > &outer)
get inscribed and circumscribed rectangle
int _camSizeIndex
The requested camera size index.
float fx() const
float _reprojectionError
Reprojection error after calibration.
float _cameraFovHDeg
Horizontal field of view in degrees.
@ uncalibrated
The camera is not calibrated (no calibration found)
@ calibrated
The camera is calibrated (mainly this means it has distortion coeffs)
@ guessed
The camera intrinsics where estimated from FOV.
void remap(cv::Mat &inDistorted, cv::Mat &outUndistorted) const
Undistorts the inDistorted image into the outUndistorted.
bool load(const string &calibDir, const string &calibFileName, bool calcUndistortionMaps)
Loads the calibration information from the config file.
cv::Size _imageSize
Input image size in pixels (after cropping)
float s1() const
SENSCalibration(const cv::Mat &cameraMat, const cv::Mat &distortion, cv::Size imageSize, cv::Size boardSize, float boardSquareMM, float reprojectionError, int numCaptured, const string &calibrationTime, int camSizeIndex, bool mirroredH, bool mirroredV, SENSCameraType camType, string computerInfos, int calibFlags, bool calcUndistortionMaps)
creates a fully defined calibration
string _calibrationTime
Time stamp string of calibration.
static const int _CALIBFILEVERSION
Global const file format version.
string calibFileName() const
float _boardSquareMM
Size of chessboard square in mm.
cv::Mat _undistortMapY
Undistortion float map in y-direction.
cv::Size _boardSize
NO. of inner chessboard corners.
void calculateUndistortedCameraMat()
Calculate a camera matrix that we use for the scene graph and for the reprojection of the undistored ...
float cy() const
float cx() const
void adaptForNewResolution(const cv::Size &newSize, bool calcUndistortionMaps)
Adapts an already calibrated camera to a new resolution (cropping and scaling)
float _cameraFovVDeg
Vertical field of view in degrees.
void calcCameraFovFromUndistortedCameraMat()
Calculates the vertical field of view angle in degrees.
bool _isMirroredH
Flag if image must be horizontally mirrored.
cv::Mat _cameraMat
3x3 Matrix for intrinsic camera matrix
cv::Mat _distortion
4x1 Matrix for intrinsic distortion
int _calibFlags
OpenCV calibration flags.
cv::Size _imageSizeOrig
original image size (original from loading or calibration estimation)
bool _isMirroredV
Flag if image must be vertically mirrored.
The SLScene class represents the top level instance holding the scene structure.
Definition: SLScene.h:47
float calcFOVDegFromFocalLengthPix(const float focalLengthPix, const int imgLength)
Definition: SENSUtils.cpp:192
string getDateTime2String()
Returns local time as string like "20190213-154611".
Definition: Utils.cpp:289
static const float DEG2RAD
Definition: Utils.h:239
string unifySlashes(const string &inputDir, bool withTrailingSlash)
Returns the inputDir string with unified forward slashes, e.g.: "dirA/dirB/".
Definition: Utils.cpp:367
string getFileNameWOExt(const string &pathFilename)
Returns the filename without extension.
Definition: Utils.cpp:615
void splitString(const string &s, char delimiter, vector< string > &splits)
Splits an input string at a delimiter character into a string vector.
Definition: Utils.cpp:152
void exitMsg(const char *tag, const char *msg, const int line, const char *file)
Terminates the application with a message. No leak checking.
Definition: Utils.cpp:1132
static const float RAD2DEG
Definition: Utils.h:238
void log(const char *tag, const char *format,...)
logs a formatted string platform independently
Definition: Utils.cpp:1100