You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
newValue/3part/Cyclops/include/CameraCalibrator.h

549 lines
26 KiB
C

4 years ago
/*!
* \file CameraCalibrator.h
* \date 2018/09/04
*
* \author Lin, Chi
* Contact: lin.chi@hzleaper.com
*
*
* \note
*/
#ifndef __CameraCalibrator_h_
#define __CameraCalibrator_h_
#include "StdUtils.h"
#include "CVUtils.h"
#include "CyclopsEnums.h"
#include "CyclopsModules.h"
#include <memory>
#include <unordered_map>
#include <opencv2/aruco/charuco.hpp>
/*! \brief Calibrate camera, find its intrinsic and extrinsic parameters
*
* By design, we assume the real world is on a flat plane. So the calibration could be a 3D-to-2D model as its common concept,
* or a 2D-to-2D model fixing the world Z value all o 0.
* We support several calibration model in this class, you could either manually set the corresponding image and world positions, using CalibModel::NPoints,
* or use grid calibration board, then we'll detect patterns (corners or circles) and use predefined world positions.
*
* It also support insufficient calibration using only a few points:
* a. (Not implemented yet) only 2 points, with specified assumption, like fix rotation, fix transform.
* b. 4 points, without lens distortion optimization
*
* Example:
* \code{.cpp}
* CameraCalibrator cc;
* double err = cc.calibrate(img, &worldPnts, &imgPnts);
* Mat undistortImg = cc.undistort(img); // get undistorted and transformed image
*
* \\ do you detection on the undistorted image, like find a circle
* Point2f circleCenter;
* Point2f circleCenter_world = cc.mapFromWorld2D(circleCenter, CameraCalibrator::PixelStage::PerspectiveTransform);
*
* \\ if you prefer to do the detection on original image (don't want to introduce much interpolation to pixels)
* Point2f lineMidPointOnOriImg;
* Point2f lineMidPoint_world = cc.mapFromWorld2D(lineMidPointOnOriImg, CameraCalibrator::PixelStage::Original);
* \endcode
*
* \\ an experiment shows the accuracy of charuco is approaching
* ++++++++++++++++++++++++++++++++++++++++++++++
* + method ++ RMS ++ error +++
* + Charuco ++ 0.460 ++ 0.083/100mm +++
* + chess 1 ++ 0.457 ++ 0.0825/100mm +++
* + chess 2 ++ 0.473 ++ 0.015/100mm +++
* ++++++++++++++++++++++++++++++++++++++++++++++
* chess 1 use the same board(13*8*20mm) as charuco, chess 2 use another board(130*80*2mm)
*
* See CameraCalibratorTest for unite test
*
*/
class StereoCalibrator;
class CameraCalibrator : public ICyclopsModuleInstance
{
public:
/*! \fn getIsCalibrated
* Get whether this calibrator is calibrated, call calibrate() if it's not.
*/
DECLARE_PARAMETER_GET(bool, IsCalibrated)
/*! \fn setCalibModel
* Define the calibration model, it could be some built-in model or NPoints
* (then you have to manually setup the world positions), default to CalibModel::NPoints, see also getCalibModel()
* \fn getCalibModel
* Get the calibration model, see also setCalibModel()
*/
DECLARE_PARAMETER2(CalibModel, CalibModel, CalibModel::NPoints, CalibModel::Charuco)
/*! \fn setCameraModel
* Define the camera model, default to CameraModel::Normal, see also getCameraModel()
* \fn getCameraModel
* Get the camera model, see also setCameraModel()
*/
DECLARE_PARAMETER2(CameraModel, CameraModel, CameraModel::Normal, CameraModel::FishEye)
/*! \fn setDistortionModel
* Define the distortion model, default to DistortionModel::Default, see also getDistortionModel()
* \fn getDistortionModel
* Get value of the distortion model, see also setDistortionModel()
*/
DECLARE_PARAMETER2(DistortionModel, DistortionModel, DistortionModel::Default, DistortionModel::All)
/*! \fn setSquareSize
* Define square size(mm) of calibration board, default to 10,
* Only works for CalibModel::Charuco or CalibModel::AsymGrid model
* see also getSquareSize()
* \fn getSquareSize
* Get square size(mm) of calibration board, see also setSquareSize()
*/
DECLARE_PARAMETER2(double, SquareSize, 0, 200)
/*! \fn setMarkerSize
* Define marker size(mm) of calibration board, default to 8,
* Only works for CalibModel::Charuco model
* see also getMarkerSize()
* \fn getMarkerSize
* Get square size(mm) of calibration board, see also setSquareSize()
*/
DECLARE_PARAMETER2(double, MarkerSize, 0, 200)
/*! \fn setGridWidth
* Only works for CalibModel::SymGrid or CalibModel::AsymGrid model
* Define how many square/circle/corners there is horizontally, default to 10, see also getGridWidth()
* \fn getGridWidth
* Get how many square/circle/corners there is horizontally, see also setGridWidth()
*/
DECLARE_PARAMETER(int, GridWidth)
/*! \fn setGridHeight
* Only works for CalibModel::SymGrid or CalibModel::AsymGrid model
* Define how many square/circle/corners there is vertically, default to 7, see also getGridHeight()
* \fn getGridHeight
* Get how many square/circle/corners there is vertically, see also setGridHeight()
*/
DECLARE_PARAMETER(int, GridHeight)
/*! \fn getRMSErr
* Get the overall RMS re-projection error.
*/
DECLARE_PARAMETER_GET(double, RMSErr)
/*! \fn getPerspectiveScale
* Get value of scale when apply undistortion and perspective transform, see also setPerspectiveScaleShift()
*/
DECLARE_PARAMETER_GET(double, PerspectiveScale)
/*! \fn getPerspectiveShift
* Get shift value when apply perspective transform, see also setPerspectiveScaleShift()
*/
DECLARE_PARAMETER_GET(Point2f, PerspectiveShift)
/*! \fn getIs2D
* Get whether this is a 2D calibrated (without z value in world points)
*/
DECLARE_PARAMETER_GET(bool, Is2D)
/*! \fn setPixelStage
* Define the level of undistorted image's pixels, see UndistortPixelStage,
* default to UndistortPixelStage::Origina, see also getPixelStage()
* \fn getPixelStage
* Get value of the level of undistorted image's pixels, see also setPixelStage()
*/
DECLARE_PARAMETER2(UndistortPixelStage, PixelStage, UndistortPixelStage::Original, UndistortPixelStage::PerspectiveTransform)
/*! \fn getOriginPosition
* Get value of world position of origin, it's usually used for align several calibrated camera, defualt to (0, 0), see also setOriginPosition()
*/
DECLARE_PARAMETER_GET(Point3f, OriginPosition)
/*! \fn getOriginAngle
* Get value of angle of world origin (around x, y, z axis), it's usually used for align several calibrated camera, default to 0, see also setOriginAngle()
*/
DECLARE_PARAMETER_GET(Point3f, OriginAngle)
/*! \fn setTermCount
* Define the maximum iteration count to do calibration optimization, default to 30, see also getTermCount()
* \fn getTermCount
* Get value of the maximum iteration count to do calibration optimization, see also setTermCount()
*/
DECLARE_PARAMETER(int, TermCount)
// Following parameters are from camera and len device, or physical metrics from working scenario,
// we should move them to a CalibrationContext class for those extra informations that helps improve calibration optimization.
/*! \fn setBoardThickness
* Define the thickness of calibration board, it will help compensate the calibration error due to mismatch of plane of calibration and detection.
* Works for calibration model except CalibModel::NPoints
* default to 0, see also getBoardThickness()
* \fn getBoardThickness
* Get value of the thickness of calibration board, see also setBoardThickness()
*/
DECLARE_PARAMETER(double, BoardThickness)
/*! \fn setCellSize
* Define cell size of camera sensor(in μm), which is used in setting up initial value for calibration, default to 0.
* It should be available in datasheet of your device, we use same cell size for both x and y axis as in most cases they are same.
* see also getCellSize()
* \fn getCellSize
* Get value of cell size of camera sensor(in μm), which is used as initial value in calibration, see also setCellSize()
*/
DECLARE_PARAMETER(double, CellSize)
/*! \fn setFocusLength
* Define focus length of camera sensor(in mm), which is used in setting up initial value for calibration, default to 0.
* It should be available in datasheet of your device, see also getFocusLength()
* \fn getFocusLength
* Get value of focus length of camera sensor, see also setFocusLength()
*/
DECLARE_PARAMETER(double, FocusLength)
/*! \fn setZ
* Define distance from world plane to image plane(in mm), which is used in setting up initial value for calibration,, default to 0, see also getZ()
* \fn getZ
* Get value of distance from world plane to image plane, see also setZ()
*/
DECLARE_PARAMETER(double, Z)
/*! \fn setUseLFSubPixCorner
* Define line-fitting for sub-pix chessboard corner detection, default to false, see also getUseLFSubPixCorner()
* \fn getUseLFSubPixCorner
* Get value of line-fitting for sub-pix chessboard corner detection, see also setUseLFSubPixCorner()
*/
DECLARE_PARAMETER(bool, UseLFSubPixCorner)
/*! \fn setAutoRemoveBad
* Define whether to remove bad calibration point pair automatically, default to false, see also getAutoRemoveBad()
* \fn getAutoRemoveBad
* Get value of whether to remove bad calibration point pair automatically, see also setAutoRemoveBad()
*/
DECLARE_PARAMETER(bool, AutoRemoveBad)
public:
CameraCalibrator(CalibModel calibModel) :
mCalibModel(calibModel),
mIsCalibrated(false), mCameraModel(CameraModel::Normal), mDistortionModel(DistortionModel::Default),
mSquareSize(10), mMarkerSize(8), mGridWidth(10), mGridHeight(7), mBoardThickness(0),
mRMSErr(-1), mPTransMat(Mat::eye(3, 3, CV_64FC1)), mPerspectiveScale(1.), mPerspectiveShift(0, 0), mIs2D(false), mNoDistort(false),
mPixelStage(UndistortPixelStage::Original),
mOriginPosition(0, 0, 0), mOriginAngle(0), mTermCount(30), mCellSize(0), mFocusLength(0), mZ(0),
mUseLFSubPixCorner(false), mAutoRemoveBad(false)
{}
CameraCalibrator() : CameraCalibrator(CalibModel::NPoints) {}
virtual ~CameraCalibrator() {}
//! Smart pointer to hold an instance of CameraCalibrator
typedef std::shared_ptr<CameraCalibrator> Ptr;
DECL_GET_INSTANCE(CameraCalibrator::Ptr)
enum ErrorCode {
NoError = 1,
// negative values for error
ErrTooFewWorldPoints = -1,
ErrUnequalImageWorldPoints = -2,
ErrFailDetectImagePoints = -3,
ErrFailCalibration = -4,
ErrUnexpect = -5,
};
/*! Set calibration grid size, how many grid there's horizontally and vertically.
* Mean nothing if calibration mode is set to CalibModel::NPoints or CalibModel::Custom.
* @param w width
* @param h height
*/
void setGridSize(unsigned int w, unsigned int h) {
mGridWidth = w; mGridHeight = h;
}
/*! Add one frame for multi-frame calibration.
* Do nothing if calibration mode is set to CalibModel::NPoints or CalibModel::Custom.
* We'll detect and record corner points from provided image with grid and calibration mode setting
* @param img image used for calibration
* @return NoError for succeed, or error code if fail
*/
virtual int addCalibrateFrame(const Mat& img);
int getFrameCount() const {
return mAssistImgPoints.size();
}
virtual bool removeAssistFrame(int idx);
/*! Run calibration with provided image.
* If calibration mode is set to CalibModel::NPoints (Default),
* you need also provide the corresponding points in world and image coordinates;
* If it's in other mode (Grid calibration),
* we'll detect the pattern (either corner or circle) on image, and use predefined world positions
* @param img image used for calibration
* for non-custom calibration, this image will be used as main plane
* @param worldPoints input and output, used as NPoints input world point positions,
* and report the real positions used in algorithm
* @param imgPoints input and output, used as NPoints input image point positions,
* and report the real positions used in algorithm
* @return NoError for succeed, or error code if fail
*/
virtual int calibrate(const Mat& img,
Point3fVec* worldPoints = nullptr,
Point2fVec* imgPoints = nullptr);
/*! Run calibration with provided image. This is a more convenient function if you are calibrating 2D world positions
* @param img image used for calibration
* for non-custom calibration, this image will be used as main plane
* @param worldPoints input and output, used as NPoints input world point positions,
* and report the real positions used in algorithm
* @param imgPoints input and output, used as NPoints input image point positions,
* and report the real positions used in algorithm
* @return NoError for succeed, or error code if fail
*/
virtual int calibrate2D(const Mat& img,
Point2fVec* worldPoints = nullptr,
Point2fVec* imgPoints = nullptr);
/*! Run calibration with provided points, only for NPoints calibration.
* @param imgSize image size
* @param worldPoints input and output, used as NPoints input world point positions
* @param imgPoints input and output, used as NPoints input image point positions
* @return NoError for succeed, or error code if fail
*/
virtual int calibrate2D(const Size& imgSize,
Point2fVec* worldPoints = nullptr,
Point2fVec* imgPoints = nullptr);
/*! Run calibration with provided numeric, only for Custom calibration.
* @param sx scale factor used for scaling numeric over x-axis
* @param sy scale factor used for scaling numeric over y-axis
* @param cx a shift value over x-axis for principal point
* @param cy a shift value over y-axis for principal point
* @param theta an angle value for determining coordinate system
*/
virtual void calibrate2D(double sx, double sy,
double cx, double cy, double theta);
/*! Calibration adaptation for slight camera rotation/translation changes,
it may be caused by temperature changes, vibration, etc.
* @param imgPoints positions of marks in current image
* @param worldPoints known world positions of marks
* @param roi Roi
* @return true if adaptation succeed
*/
virtual bool adapt(const Point2fVec& imgPoints, const Point3fVec& worldPoints, Rect roi = Rect());
/*! Reset adaptation, rotation/translation matrix are reset to original value */
virtual void resetAdapt();
/*! Evaluate the calibration result using grid broads, by comparing the distance of mapping result of image points
detected from the provided image and generated world points
* @param img image of calibration board
* @param err distance mis-matching range(relative error), -1 ~ 1, smaller range means better calibration
* @param skipNear skip evaluation of point nearby in 2 square
* @return NoError for succeed, or error code if fail
*/
virtual int evaluate(const Mat& img, Rangef& err, bool skipNear = true);
/*! Transforms an image to compensate for lens distortion, and also for camera tilt if required
* @param img input image
* @param roi Roi
* @return the transformed image
*/
virtual Mat undistort(const Mat& img, Rect roi = Rect());
/*! Map a point in image coordinates to world coordinates
* @param imgPoint position in image coordinates
* @param roi optional, set it if the image is in some roi, then the input position will be treated as located in that roi
* @param z optional, set it if the returned world points are required to be on z-planar, otherwise it's on the defined thickness-planar
* @param postTrans optional, whether post-transform and origin point transform is applied in this mapping, default to true
* @return 3D position in world coordinates
*/
virtual Point3f mapToWorld(const Point2f& imgPoint, Rect roi = Rect(), double z = DBL_MAX, bool postTrans = true);
virtual Point3fVec mapToWorld(const Point2fVec& imgPoint, Rect roi = Rect(), double z = DBL_MAX, bool postTrans = true);
/*! Mat a point in world coordinates to image coordinates
* @param worldPoint 3D position in world coordinates
* @param roi optional, set it if the image is in some roi, then the returned position will located in that roi
* @param postTrans optional, whether post-transform and origin point transform is applied in this mapping, default to true
* @return position in image coordinates
*/
virtual Point2f mapFromWorld(const Point3f& worldPoint, Rect roi = Rect(), bool postTrans = true);
virtual Point2fVec mapFromWorld(const Point3fVec& worldPoint, Rect roi = Rect(), bool postTrans = true);
/*! Map a point in image coordinates to world coordinates
* @param imgPoint position in image coordinates
* @param fromStage specify where the point is, aka. how the image is generated
* @param roi optional, set it if the image is in some roi, then the input position will be treated as located in that roi
* @param postTrans optional, whether post-transform and origin point transform is applied in this mapping, default to true
* @return 2D position in world coordinates
*/
virtual Point2f mapToWorld2D(const Point2f& imgPoint, Rect roi = Rect(), bool postTrans = true);
virtual Point2fVec mapToWorld2D(const Point2fVec& imgPoint, Rect roi = Rect(), bool postTrans = true);
/*! Map a point in world coordinates to image coordinates
* @param worldPoint 2D position in world coordinates
* @param roi optional, set it if the image is in some roi, then the returned position will located in that roi
* @param postTrans optional, whether post-transform and origin point transform is applied in this mapping, default to true
* @return position in image coordinates
*/
virtual Point2f mapFromWorld2D(const Point2f& worldPoint, Rect roi = Rect(), bool postTrans = true);
virtual Point2fVec mapFromWorld2D(const Point2fVec& worldPoint, Rect roi = Rect(), bool postTrans = true);
/*! Map a length (numeric) value in image coordinates to world coordinates.
* Note this function doesn't give accurate result when there's strong distortion or camera tilt.
* It's recommend to fix them in the very beginning before detection and inspection and transformation, via undistort().
* @param length numeric length in image coordinates
* @param anchorPnt the reference point to do a relatively accurate mapping
* @param roi optional, set it if the image is in some roi, then the input position will be treated as located in that roi
* @param postTrans optional, whether post-transform and origin point transform is applied in this mapping, default to true
* @return length in world coordinates
*/
virtual double mapLengthToWorld(const double& length, const Point2f& anchorPnt, Rect roi = Rect(), bool postTrans = true);
virtual vector<double> mapLengthToWorld(const vector<double>& lengths, const Point2fVec& anchorPnts, Rect roi = Rect(), bool postTrans = true);
/*! Map an area (numeric) value in image coordinates to world coordinates.
* Note this function doesn't give accurate result when there's strong distortion or camera tilt.
* It's recommend to fix them in the very beginning before detection and inspection and transformation, via undistort().
* @param area numeric area in image coordinates
* @param anchorPnt the reference point to do a relatively accurate mapping
* @param roi optional, set it if the image is in some roi, then the input position will be treated as located in that roi
* @param postTrans optional, whether post-transform and origin point transform is applied in this mapping, default to true
* @return area in world coordinates
*/
virtual double mapAreaToWorld(const double& area, const Point2f& anchorPnt, Rect roi = Rect(), bool postTrans = true);
virtual vector<double> mapAreaToWorld(const vector<double>& areas, const Point2fVec& anchorPnts, Rect roi = Rect(), bool postTrans = true);
/*! Map an angle (numeric) value in image coordinates to world coordinates.
* Note this function doesn't give accurate result when there's strong distortion or camera tilt.
* It's recommend to fix them in the very beginning before detection and inspection and transformation, via undistort().
* @param angle numeric angle in image coordinates
* @param anchorPnt the reference point to do a relatively accurate mapping
* @param roi optional, set it if the image is in some roi, then the input position will be treated as located in that roi
* @param postTrans optional, whether post-transform and origin point transform is applied in this mapping, default to true
* @return angle in world coordinates
*/
virtual double mapAngleToWorld(const double& angle, const Point2f& anchorPnt, Rect roi = Rect(), bool postTrans = true);
virtual vector<double> mapAngleToWorld(const vector<double>& angles, const Point2fVec& anchorPnts, Rect roi = Rect(), bool postTrans = true);
/*! \fn serializeToMemory
* Serialize the camera calibrator (including calibration and distortion matrixes) into a in-memory string, see also deserializeFromMemory()
* @param str used to take the output serialization result
* @return true for succeed, false for fail
* \fn serializeToFile
* Serialize the camera calibrator (including calibration and distortion matrixes) into a text file, see also deserializeFromFile()
* @param filename file name (full path) where we will write the data
* @return true for succeed, false for fail
* \fn deserializeFromMemory
* Deserialize the camera calibrator from in-memory string, see also serializeToMemory()
* @param str in-memory string
* @return true for succeed, false for fail
* \fn deserializeFromFile
* Deserialize the camera calibrator from a text file, see also serializeToFile()
* @param filename file name (full path) where we will read the data
* @return true for succeed, false for fail
*/
DECL_SERIALIZE_FUNCS
/*! Clear calibration result */
virtual void clear(bool clearAllFrame = false);
/*! Define scale when apply undistortion and perspective transform, 0 to 10, default to 1 means no scale, see also getPerspectiveScale() */
virtual void setPerspectiveScale(double s);
/*! Define scale and additional shift when apply perspective transform*/
virtual void setPerspectiveScaleShift(double s, Point2f shift);
/*! Get mapping from image to world point in a descriptive string */
virtual void getMappingInStr(std::string& str) const;
/*! Get error message when calibration failed */
virtual std::string getErrorStr(int errorCode) const;
/*! Set world origin pose for 2D calibration */
virtual void setOriginPose2D(const Point2f& position, double angle);
/*! Set world origin pose for 3D calibration
* Note: this and related functions are implemented by not tested, please test (and fix bugs) before use
*/
virtual void setOriginPose3D(const Point3f& position, const Point3f& angle);
/*! Set world customized affine matrix for 2D calibration */
virtual bool setCustomMatrix2D(const Mat& custMat);
/*! Set world customized affine matrix for 3D calibration */
virtual bool setCustomMatrix3D(const Mat& custMat);
/*! Set preceding distortion calibrator */
virtual bool setDistortCalibrator(CameraCalibrator::Ptr ccPtr);
/*! Get preceding distortion calibrator */
CameraCalibrator::Ptr getDistortCalibrator() const {
return mDistortCalibPtr;
}
/*! Get image points used for calibration
* @param idx negative value for get image point on 0-planar, otherwise, for assistant planar
*/
Point2fVec getImgPnts(int idx = -1) const {
if (idx < 0 || idx >= mAssistImgPoints.size()) return mImgPoints;
else return mAssistImgPoints[idx];
}
/*! Get world points used for calibration
* @param idx negative value for get world point on 0-planar, otherwise, for assistant planar
*/
Point3fVec getWorldPnts(int idx = -1) const {
if (idx < 0 || idx >= mAssistWorldPoints.size()) return mWorldPoints;
else return mAssistWorldPoints[idx];
}
/*! Get image size */
Size getImageSize() const { return mImgSize; }
protected:
Mat mCameraMatrix;
Mat mDistCoeffs;
bool mNoDistort;
Mat mTVec, mRVec, mInvTVec;
Mat mTVecBackup, mRVecBackup;
Mat mPTransMat;
Mat mScaledCamearMatrix;
Size mImgSize;
Mat mRMat, mInvRMat;
Mat mTransMat, mInvTransMat;
Mat mCustMat;
Mat mUndistrotMap;
Point2fVec mImgPoints;
Point3fVec mWorldPoints;
std::vector<int> mCharucoIds;
std::vector<Point2fVec> mAssistImgPoints;
std::vector<Point3fVec> mAssistWorldPoints;
std::string mErrorMsg;
friend class StereoCalibrator;
CameraCalibrator::Ptr mDistortCalibPtr;
cv::Ptr<cv::aruco::CharucoBoard> mCharucoBoardPtr;
void genGridBoardCornerPnts(Point3fVec& corners, const Point2fVec& imgPnts);
void ensureCharucoBoard();
void genCharucoCornerPnts(Point3fVec& corners);
bool detectGridBoardImagePnts(const Mat& img, Point2fVec& corners);
bool detectBoardPnts(const Mat& img, Point2fVec& imgPoints, Point3fVec& worldPoints, bool removeBad = false);
bool detectCharucoBoardImagePnts(const Mat& img, Point2fVec& corners, std::vector<int>& cornerIds);
bool updateIEMatrix(
const Mat& camMatrix, const Mat& distCoeffs);
virtual bool serialize(FileStorage& fs);
virtual bool deserialize(const FileNode& fs);
bool updateMatrix(const Mat& cameraMat, const Mat& distCoeff, const Mat& R, const Mat& T);
void customizeCamMatrix(Mat & camMatrix, double cellSize, double focalLength, int &flag);
void genHomoMat(const Mat& custMat, const Mat& originMat, Mat& homoCustMat, Mat& homoOriginMat, bool is2D);
void setCustMat(const Mat& custMat);
void genTransMat();
int getCalibFlagForDistortion(bool fix);
private:
bool doCalibration(const Point3fVec& worldPoints, const Point2fVec& imgPoints, double& rmsErr);
bool doUndistort(const Point2fVec& imgPoints, Point2fVec& undistortImgPoints, const Mat& cameraMatrix);
void project2WorldPlane(const Point2fVec& imgPoints, Point3fVec& worldPoints,
UndistortPixelStage pixStage, double z = DBL_MAX);
bool genPTransMat();
Mat guessCameraMatrix(const Point3fVec& worldPoints, const Point2fVec& imgPoints);
void getIntrisincParam(double* fx, double* fy = nullptr, double* cx = nullptr, double* cy = nullptr);
void prepareMatrix();
void resetFullSizeRoi(Rect& roi);
Rect getUndistortRoi(const Rect& roi);
Mat adjPMatrixForRoi(const Rect& roi, const Rect& undistortRoi);
bool _doCalibration(const vector<Point3fVec>& worldPointsVec, const vector<Point2fVec>& imgPointsVec,
double& rmsErr, Mat& camMatrix, Mat& distCoeffs, Mat& tVec, Mat& rVec, int flag);
void pntsAroundAnchor(double halfLength, const Point2f& pnt, Point2fVec& aroundPnts);
void anglePntsAroundAnchor(double angle, const Point2f& pnt, Point2fVec& aroundPnts);
typedef std::unordered_map<Rect, Mat, RectHasher, RectEqualFunc> Rect2MatMap;
Rect2MatMap mPTransMatMap; // for query and maintain perspective transform matrix map
CyclopsLock mPMapLock;
CyclopsLock mLock;
private:
Mat mImg;
};
#endif // CameraCalibrator_h_