SLProject  4.3.020
A platform independent 3D computer graphics framework for desktop OS, Android, iOS and online in web browsers
SENSCalibration.h
Go to the documentation of this file.
1 /**
2  * \file SENSCalibration.h
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 #ifndef SENSCALIBRATION_H
11 #define SENSCALIBRATION_H
12 
14 
15 using std::string;
16 
17 //-----------------------------------------------------------------------------
19 {
20 public:
21  enum class State
22  {
23  uncalibrated, //!< The camera is not calibrated (no calibration found)
24  calibrated, //!< The camera is calibrated (mainly this means it has distortion coeffs)
25  guessed, //!< The camera intrinsics where estimated from FOV
26  };
27 
28  //!creates a fully defined calibration
29  SENSCalibration(const cv::Mat& cameraMat,
30  const cv::Mat& distortion,
31  cv::Size imageSize,
32  cv::Size boardSize,
33  float boardSquareMM,
34  float reprojectionError,
35  int numCaptured,
36  const string& calibrationTime,
37  int camSizeIndex,
38  bool mirroredH,
39  bool mirroredV,
41  string computerInfos,
42  int calibFlags,
43  bool calcUndistortionMaps);
44 
45  //!creates a guessed calibration using image size and fovV angle
46  SENSCalibration(const cv::Size& imageSize,
47  float fovH,
48  bool mirroredH,
49  bool mirroredV,
50  SENSCameraType type,
51  string computerInfos);
52 
53  //!create a guessed calibration using sensor size, camera focal length and captured image size
54  SENSCalibration(float sensorWMM,
55  float sensorHMM,
56  float focalLengthMM,
57  const cv::Size& imageSize,
58  bool mirroredH,
59  bool mirroredV,
61  string computerInfos);
62 
63  //!create a calibration using a known camera matrix (intrinsics) without distortion parameters
64  SENSCalibration(const cv::Mat& intrinsics,
65  const cv::Size& imageSize,
66  bool mirroredH,
67  bool mirroredV,
69  const string& computerInfos);
70  //! ???
71  SENSCalibration(const string& calibDir,
72  const string& calibFileName,
73  bool calcUndistortionMaps);
74 
75  //!destructor
77  {
78  }
79 
80  //! copy constructor
82  : _cameraMat(other._cameraMat.clone()),
83  _distortion(other._distortion.clone()),
84  _cameraMatOrig(other._cameraMatOrig.clone()),
86  _state(other._state),
90  _calibFlags(other._calibFlags),
94  _boardSize(other._boardSize),
97  _imageSize(other._imageSize),
99  _undistortMapX(other._undistortMapX.clone()),
100  _undistortMapY(other._undistortMapY.clone()),
104  _camType(other._camType)
105  {
106  }
107  //! copy assignment operator implicitly defined
109  {
110  _cameraMat = other._cameraMat.clone();
111  _distortion = other._distortion.clone();
112  _cameraMatOrig = other._cameraMatOrig.clone();
114  _state = other._state;
118  _calibFlags = other._calibFlags;
119  _isMirroredH = other._isMirroredH;
120  _isMirroredV = other._isMirroredV;
121  _numCaptured = other._numCaptured;
122  _boardSize = other._boardSize;
125  _imageSize = other._imageSize;
127  _undistortMapX = other._undistortMapX.clone();
128  _undistortMapY = other._undistortMapY.clone();
132  _camType = other._camType;
133 
134  return *this;
135  }
136 
137  bool save(const string& calibDir,
138  const string& calibFileName);
139 
140  void remap(cv::Mat& inDistorted,
141  cv::Mat& outUndistorted) const;
142 
143  //! Adapts an already calibrated camera to a new resolution (cropping and scaling)
144  void adaptForNewResolution(const cv::Size& newSize, bool calcUndistortionMaps);
145  void buildUndistortionMaps();
146 
147  static void getInnerAndOuterRectangles(const cv::Mat& cameraMatrix,
148  const cv::Mat& distCoeffs,
149  const cv::Mat& R,
150  const cv::Mat& newCameraMatrix,
151  const cv::Size& imgSize,
152  cv::Rect_<float>& inner,
153  cv::Rect_<float>& outer);
154 
155  // Getters
156  cv::Size imageSize() const { return _imageSize; }
157  cv::Size imageSizeOriginal() const { return _imageSizeOrig; }
158 
159  float imageAspectRatio() const { return (float)_imageSize.width / (float)_imageSize.height; }
160  const cv::Mat& cameraMat() const { return _cameraMat; }
161  const cv::Mat& cameraMatUndistorted() const { return _cameraMatUndistorted; }
162  const cv::Mat& distortion() const { return _distortion; }
163  float cameraFovVDeg() const { return _cameraFovVDeg; }
164  float cameraFovHDeg() const { return _cameraFovHDeg; }
165 
166  int calibrationFlags() const { return _calibFlags; }
167  bool calibFixPrincipalPoint() { return _calibFlags & cv::CALIB_FIX_PRINCIPAL_POINT; }
168  bool calibFixAspectRatio() { return _calibFlags & cv::CALIB_FIX_ASPECT_RATIO; }
169  bool calibZeroTangentDist() { return _calibFlags & cv::CALIB_ZERO_TANGENT_DIST; }
170  bool calibRationalModel() { return _calibFlags & cv::CALIB_RATIONAL_MODEL; }
171  bool calibTiltedModel() { return _calibFlags & cv::CALIB_TILTED_MODEL; }
172  bool calibThinPrismModel() { return _calibFlags & cv::CALIB_THIN_PRISM_MODEL; }
173  bool isMirroredH() const { return _isMirroredH; }
174  bool isMirroredV() const { return _isMirroredV; }
175  bool undistortMapsValid() const { return (!_undistortMapX.empty() && !_undistortMapY.empty()); }
176 
177  float fx() const { return _cameraMat.cols == 3 && _cameraMat.rows == 3 ? (float)_cameraMat.at<double>(0, 0) : 0.0f; }
178  float fy() const { return _cameraMat.cols == 3 && _cameraMat.rows == 3 ? (float)_cameraMat.at<double>(1, 1) : 0.0f; }
179  float cx() const { return _cameraMat.cols == 3 && _cameraMat.rows == 3 ? (float)_cameraMat.at<double>(0, 2) : 0.0f; }
180  float cy() const { return _cameraMat.cols == 3 && _cameraMat.rows == 3 ? (float)_cameraMat.at<double>(1, 2) : 0.0f; }
181  float k1() const { return _distortion.rows >= 4 ? (float)_distortion.at<double>(0, 0) : 0.0f; }
182  float k2() const { return _distortion.rows >= 4 ? (float)_distortion.at<double>(1, 0) : 0.0f; }
183  float p1() const { return _distortion.rows >= 4 ? (float)_distortion.at<double>(2, 0) : 0.0f; }
184  float p2() const { return _distortion.rows >= 4 ? (float)_distortion.at<double>(3, 0) : 0.0f; }
185  float k3() const { return _distortion.rows >= 5 ? (float)_distortion.at<double>(4, 0) : 0.0f; }
186  float k4() const { return _distortion.rows >= 6 ? (float)_distortion.at<double>(5, 0) : 0.0f; }
187  float k5() const { return _distortion.rows >= 7 ? (float)_distortion.at<double>(6, 0) : 0.0f; }
188  float k6() const { return _distortion.rows >= 8 ? (float)_distortion.at<double>(7, 0) : 0.0f; }
189  float s1() const { return _distortion.rows >= 9 ? (float)_distortion.at<double>(8, 0) : 0.0f; }
190  float s2() const { return _distortion.rows >= 10 ? (float)_distortion.at<double>(9, 0) : 0.0f; }
191  float s3() const { return _distortion.rows >= 11 ? (float)_distortion.at<double>(10, 0) : 0.0f; }
192  float s4() const { return _distortion.rows >= 12 ? (float)_distortion.at<double>(11, 0) : 0.0f; }
193  float tauX() const { return _distortion.rows >= 13 ? (float)_distortion.at<double>(12, 0) : 0.0f; }
194  float tauY() const { return _distortion.rows >= 14 ? (float)_distortion.at<double>(13, 0) : 0.0f; }
195 
196  SENSCameraType camType() const { return _camType; }
197  State state() const { return _state; }
198  int numCapturedImgs() const { return _numCaptured; }
199  float reprojectionError() const { return _reprojectionError; }
200  cv::Size boardSize() const { return _boardSize; }
201  float boardSquareMM() const { return _boardSquareMM; }
202  float boardSquareM() const { return _boardSquareMM * 0.001f; }
203  string calibrationTime() const { return _calibrationTime; }
204  string calibFileName() const { return _calibFileName; }
205  string computerInfos() const { return _computerInfos; }
206  string stateStr() const
207  {
208  switch (_state)
209  {
210  case State::uncalibrated: return "uncalibrated";
211  case State::calibrated: return "calibrated";
212  case State::guessed: return "guessed";
213  default: return "unknown";
214  }
215  }
216 
219 
220 private:
221  bool load(const string& calibDir,
222  const string& calibFileName,
223  bool calcUndistortionMaps);
224 
225  void createFromGuessedFOV(int imageWidthPX, int imageHeightPX, float fovH);
226 
227  ///////////////////////////////////////////////////////////////////////////////////
228  cv::Mat _cameraMat; //!< 3x3 Matrix for intrinsic camera matrix
229  cv::Mat _distortion; //!< 4x1 Matrix for intrinsic distortion
230  ///////////////////////////////////////////////////////////////////////////////////
231 
232  //original data used for adaption:
233  cv::Mat _cameraMatOrig; //!< 3x3 Matrix for intrinsic camera matrix (original from loading or calibration estimation)
234  cv::Size _imageSizeOrig; //!< original image size (original from loading or calibration estimation)
235 
236  State _state = State::uncalibrated; //!< calibration state enumeration
237  float _cameraFovVDeg = 0.0f; //!< Vertical field of view in degrees
238  float _cameraFovHDeg = 0.0f; //!< Horizontal field of view in degrees
239  string _calibFileName; //!< name for calibration file
240  int _calibFlags = 0; //!< OpenCV calibration flags
241  //todo: not necessary if calibrated before mirroring postprocessing
242  bool _isMirroredH = false; //!< Flag if image must be horizontally mirrored
243  //todo: not necessary if calibrated before mirroring postprocessing
244  bool _isMirroredV = false; //!< Flag if image must be vertically mirrored
245 
246  //todo: maybe we dont need this here..
247  int _numCaptured = 0; //!< NO. of images captured
248  cv::Size _boardSize; //!< NO. of inner chessboard corners.
249  float _boardSquareMM = 20.f; //!< Size of chessboard square in mm
250  float _reprojectionError = -1.0f; //!< Reprojection error after calibration
251  cv::Size _imageSize; //!< Input image size in pixels (after cropping)
252  int _camSizeIndex = -1; //!< The requested camera size index
253 
254  cv::Mat _undistortMapX; //!< Undistortion float map in x-direction
255  cv::Mat _undistortMapY; //!< Undistortion float map in y-direction
256 
257  /* Camera matrix that defines an optimal camera matrix that may be used e.g. as frustum definition in
258  an scene graph. It is optimal in the sense that it is adapted so that the focal point is centered (by cx and cy) and
259  black borders of an undistorted image are removed by scaling fx and fy.
260  If the viewport is different to the camera image size it fits to cx and cy have to be additionally adjusted.
261  The _cameraMatUndistorted may also be used for reprojection of an undistorted image.
262  In this context it is used by this class to build the undistortion maps
263  (in buildUndistortionMaps) and the resulting undistortion maps are used to undistort
264  an image in the remap function). If the distortion coefficients are empty (_distortion)
265  _cameraMatUndistorted is equal to _cameraMat.
266  */
268  string _calibrationTime = "-"; //!< Time stamp string of calibration
271 
272  static const int _CALIBFILEVERSION; //!< Global const file format version
273 };
274 //-----------------------------------------------------------------------------
275 
276 #endif // SENSCALIBRATION_H
string stateStr() const
SENSCalibration(const SENSCalibration &other)
copy constructor
State _state
calibration state enumeration
float boardSquareM() const
int _numCaptured
NO. of images captured.
float k2() const
cv::Mat _undistortMapX
Undistortion float map in x-direction.
float k5() const
SENSCalibration(const cv::Mat &intrinsics, const cv::Size &imageSize, bool mirroredH, bool mirroredV, SENSCameraType camType, const string &computerInfos)
create a calibration using a known camera matrix (intrinsics) without distortion parameters
bool save(const string &calibDir, const string &calibFileName)
Saves the camera calibration parameters to the config file.
float s2() const
float fy() const
cv::Mat _cameraMatOrig
3x3 Matrix for intrinsic camera matrix (original from loading or calibration estimation)
SENSCameraType camType() const
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.
SENSCalibration & operator=(const SENSCalibration &other)
copy assignment operator implicitly defined
bool isMirroredV() const
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
const cv::Mat & distortion() const
int _camSizeIndex
The requested camera size index.
bool undistortMapsValid() const
float cameraFovVDeg() const
float fx() const
SENSCameraType _camType
const cv::Mat & cameraMat() 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.
SENSCalibration(const string &calibDir, const string &calibFileName, bool calcUndistortionMaps)
???
void remap(cv::Mat &inDistorted, cv::Mat &outUndistorted) const
Undistorts the inDistorted image into the outUndistorted.
bool calibFixAspectRatio()
float reprojectionError() const
bool load(const string &calibDir, const string &calibFileName, bool calcUndistortionMaps)
Loads the calibration information from the config file.
bool calibZeroTangentDist()
float k1() const
cv::Size _imageSize
Input image size in pixels (after cropping)
State state() const
string calibrationTime() const
float p2() const
float k4() const
cv::Size imageSizeOriginal() const
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
~SENSCalibration()
destructor
string _calibrationTime
Time stamp string of calibration.
float boardSquareMM() const
cv::Size imageSize() const
static const int _CALIBFILEVERSION
Global const file format version.
bool calibFixPrincipalPoint()
string calibFileName() const
float cameraFovHDeg() const
float s3() const
float _boardSquareMM
Size of chessboard square in mm.
SENSCalibration(float sensorWMM, float sensorHMM, float focalLengthMM, const cv::Size &imageSize, bool mirroredH, bool mirroredV, SENSCameraType camType, string computerInfos)
create a guessed calibration using sensor size, camera focal length and captured image size
float k6() const
cv::Mat _undistortMapY
Undistortion float map in y-direction.
cv::Size _boardSize
NO. of inner chessboard corners.
float imageAspectRatio() const
void calculateUndistortedCameraMat()
Calculate a camera matrix that we use for the scene graph and for the reprojection of the undistored ...
float cy() const
float p1() const
bool isMirroredH() const
int numCapturedImgs() 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.
string computerInfos() const
void calcCameraFovFromUndistortedCameraMat()
Calculates the vertical field of view angle in degrees.
SENSCalibration(const cv::Size &imageSize, float fovH, bool mirroredH, bool mirroredV, SENSCameraType type, string computerInfos)
creates a guessed calibration using image size and fovV angle
cv::Size boardSize() const
bool _isMirroredH
Flag if image must be horizontally mirrored.
int calibrationFlags() const
cv::Mat _cameraMat
3x3 Matrix for intrinsic camera matrix
cv::Mat _distortion
4x1 Matrix for intrinsic distortion
bool calibThinPrismModel()
const cv::Mat & cameraMatUndistorted() const
int _calibFlags
OpenCV calibration flags.
float s4() const
string _calibFileName
name for calibration file
float tauX() const
cv::Size _imageSizeOrig
original image size (original from loading or calibration estimation)
float tauY() const
bool _isMirroredV
Flag if image must be vertically mirrored.
float k3() const