Merge pull request #2726 from Ilya-Krylov:2.4
This commit is contained in:
commit
2b2ce3f6e9
@ -1493,6 +1493,364 @@ The function reconstructs 3-dimensional points (in homogeneous coordinates) by u
|
||||
|
||||
:ocv:func:`reprojectImageTo3D`
|
||||
|
||||
fisheye
|
||||
----------
|
||||
|
||||
The methods in this namespace use a so-called fisheye camera model. ::
|
||||
|
||||
namespace fisheye
|
||||
{
|
||||
//! projects 3D points using fisheye model
|
||||
void projectPoints(InputArray objectPoints, OutputArray imagePoints, const Affine3d& affine,
|
||||
InputArray K, InputArray D, double alpha = 0, OutputArray jacobian = noArray());
|
||||
|
||||
//! projects points using fisheye model
|
||||
void projectPoints(InputArray objectPoints, OutputArray imagePoints, InputArray rvec, InputArray tvec,
|
||||
InputArray K, InputArray D, double alpha = 0, OutputArray jacobian = noArray());
|
||||
|
||||
//! distorts 2D points using fisheye model
|
||||
void distortPoints(InputArray undistorted, OutputArray distorted, InputArray K, InputArray D, double alpha = 0);
|
||||
|
||||
//! undistorts 2D points using fisheye model
|
||||
void undistortPoints(InputArray distorted, OutputArray undistorted,
|
||||
InputArray K, InputArray D, InputArray R = noArray(), InputArray P = noArray());
|
||||
|
||||
//! computing undistortion and rectification maps for image transform by cv::remap()
|
||||
//! If D is empty zero distortion is used, if R or P is empty identity matrixes are used
|
||||
void initUndistortRectifyMap(InputArray K, InputArray D, InputArray R, InputArray P,
|
||||
const cv::Size& size, int m1type, OutputArray map1, OutputArray map2);
|
||||
|
||||
//! undistorts image, optionally changes resolution and camera matrix.
|
||||
void undistortImage(InputArray distorted, OutputArray undistorted,
|
||||
InputArray K, InputArray D, InputArray Knew = cv::noArray(), const Size& new_size = Size());
|
||||
|
||||
//! estimates new camera matrix for undistortion or rectification
|
||||
void estimateNewCameraMatrixForUndistortRectify(InputArray K, InputArray D, const Size &image_size, InputArray R,
|
||||
OutputArray P, double balance = 0.0, const Size& new_size = Size(), double fov_scale = 1.0);
|
||||
|
||||
//! performs camera calibaration
|
||||
double calibrate(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints, const Size& image_size,
|
||||
InputOutputArray K, InputOutputArray D, OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs, int flags = 0,
|
||||
TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 100, DBL_EPSILON));
|
||||
|
||||
//! stereo rectification estimation
|
||||
void stereoRectify(InputArray K1, InputArray D1, InputArray K2, InputArray D2, const Size &imageSize, InputArray R, InputArray tvec,
|
||||
OutputArray R1, OutputArray R2, OutputArray P1, OutputArray P2, OutputArray Q, int flags, const Size &newImageSize = Size(),
|
||||
double balance = 0.0, double fov_scale = 1.0);
|
||||
|
||||
//! performs stereo calibration
|
||||
double stereoCalibrate(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints1, InputArrayOfArrays imagePoints2,
|
||||
InputOutputArray K1, InputOutputArray D1, InputOutputArray K2, InputOutputArray D2, Size imageSize,
|
||||
OutputArray R, OutputArray T, int flags = CALIB_FIX_INTRINSIC,
|
||||
TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 100, DBL_EPSILON));
|
||||
};
|
||||
|
||||
|
||||
Definitions:
|
||||
Let P be a point in 3D of coordinates X in the world reference frame (stored in the matrix X)
|
||||
The coordinate vector of P in the camera reference frame is:
|
||||
|
||||
.. class:: center
|
||||
.. math::
|
||||
|
||||
Xc = R X + T
|
||||
|
||||
where R is the rotation matrix corresponding to the rotation vector om: R = rodrigues(om);
|
||||
call x, y and z the 3 coordinates of Xc:
|
||||
|
||||
.. class:: center
|
||||
.. math::
|
||||
x = Xc_1 \\
|
||||
y = Xc_2 \\
|
||||
z = Xc_3
|
||||
|
||||
The pinehole projection coordinates of P is [a; b] where
|
||||
|
||||
.. class:: center
|
||||
.. math::
|
||||
|
||||
a = x / z \ and \ b = y / z \\
|
||||
r^2 = a^2 + b^2 \\
|
||||
\theta = atan(r)
|
||||
|
||||
Fisheye distortion:
|
||||
|
||||
.. class:: center
|
||||
.. math::
|
||||
|
||||
\theta_d = \theta (1 + k_1 \theta^2 + k_2 \theta^4 + k_3 \theta^6 + k_4 \theta^8)
|
||||
|
||||
The distorted point coordinates are [x'; y'] where
|
||||
|
||||
..class:: center
|
||||
.. math::
|
||||
|
||||
x' = (\theta_d / r) x \\
|
||||
y' = (\theta_d / r) y
|
||||
|
||||
Finally, convertion into pixel coordinates: The final pixel coordinates vector [u; v] where:
|
||||
|
||||
.. class:: center
|
||||
.. math::
|
||||
|
||||
u = f_x (x' + \alpha y') + c_x \\
|
||||
v = f_y yy + c_y
|
||||
|
||||
fisheye::projectPoints
|
||||
---------------------------
|
||||
Projects points using fisheye model
|
||||
|
||||
.. ocv:function:: void fisheye::projectPoints(InputArray objectPoints, OutputArray imagePoints, const Affine3d& affine, InputArray K, InputArray D, double alpha = 0, OutputArray jacobian = noArray())
|
||||
|
||||
.. ocv:function:: void fisheye::projectPoints(InputArray objectPoints, OutputArray imagePoints, InputArray rvec, InputArray tvec, InputArray K, InputArray D, double alpha = 0, OutputArray jacobian = noArray())
|
||||
|
||||
:param objectPoints: Array of object points, 1xN/Nx1 3-channel (or ``vector<Point3f>`` ), where N is the number of points in the view.
|
||||
|
||||
:param rvec: Rotation vector. See :ocv:func:`Rodrigues` for details.
|
||||
|
||||
:param tvec: Translation vector.
|
||||
|
||||
:param K: Camera matrix :math:`K = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{_1}`.
|
||||
|
||||
:param D: Input vector of distortion coefficients :math:`(k_1, k_2, k_3, k_4)`.
|
||||
|
||||
:param alpha: The skew coefficient.
|
||||
|
||||
:param imagePoints: Output array of image points, 2xN/Nx2 1-channel or 1xN/Nx1 2-channel, or ``vector<Point2f>``.
|
||||
|
||||
:param jacobian: Optional output 2Nx15 jacobian matrix of derivatives of image points with respect to components of the focal lengths, coordinates of the principal point, distortion coefficients, rotation vector, translation vector, and the skew. In the old interface different components of the jacobian are returned via different output parameters.
|
||||
|
||||
The function computes projections of 3D points to the image plane given intrinsic and extrinsic camera parameters. Optionally, the function computes Jacobians - matrices of partial derivatives of image points coordinates (as functions of all the input parameters) with respect to the particular parameters, intrinsic and/or extrinsic.
|
||||
|
||||
fisheye::distortPoints
|
||||
-------------------------
|
||||
Distorts 2D points using fisheye model.
|
||||
|
||||
.. ocv:function:: void fisheye::distortPoints(InputArray undistorted, OutputArray distorted, InputArray K, InputArray D, double alpha = 0)
|
||||
|
||||
:param undistorted: Array of object points, 1xN/Nx1 2-channel (or ``vector<Point2f>`` ), where N is the number of points in the view.
|
||||
|
||||
:param K: Camera matrix :math:`K = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{_1}`.
|
||||
|
||||
:param D: Input vector of distortion coefficients :math:`(k_1, k_2, k_3, k_4)`.
|
||||
|
||||
:param alpha: The skew coefficient.
|
||||
|
||||
:param distorted: Output array of image points, 1xN/Nx1 2-channel, or ``vector<Point2f>`` .
|
||||
|
||||
fisheye::undistortPoints
|
||||
-----------------------------
|
||||
Undistorts 2D points using fisheye model
|
||||
|
||||
.. ocv:function:: void fisheye::undistortPoints(InputArray distorted, OutputArray undistorted, InputArray K, InputArray D, InputArray R = noArray(), InputArray P = noArray())
|
||||
|
||||
:param distorted: Array of object points, 1xN/Nx1 2-channel (or ``vector<Point2f>`` ), where N is the number of points in the view.
|
||||
|
||||
:param K: Camera matrix :math:`K = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{_1}`.
|
||||
|
||||
:param D: Input vector of distortion coefficients :math:`(k_1, k_2, k_3, k_4)`.
|
||||
|
||||
:param R: Rectification transformation in the object space: 3x3 1-channel, or vector: 3x1/1x3 1-channel or 1x1 3-channel
|
||||
|
||||
:param P: New camera matrix (3x3) or new projection matrix (3x4)
|
||||
|
||||
:param undistorted: Output array of image points, 1xN/Nx1 2-channel, or ``vector<Point2f>`` .
|
||||
|
||||
|
||||
fisheye::initUndistortRectifyMap
|
||||
-------------------------------------
|
||||
Computes undistortion and rectification maps for image transform by cv::remap(). If D is empty zero distortion is used, if R or P is empty identity matrixes are used.
|
||||
|
||||
.. ocv:function:: void fisheye::initUndistortRectifyMap(InputArray K, InputArray D, InputArray R, InputArray P, const cv::Size& size, int m1type, OutputArray map1, OutputArray map2)
|
||||
|
||||
:param K: Camera matrix :math:`K = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{_1}`.
|
||||
|
||||
:param D: Input vector of distortion coefficients :math:`(k_1, k_2, k_3, k_4)`.
|
||||
|
||||
:param R: Rectification transformation in the object space: 3x3 1-channel, or vector: 3x1/1x3 1-channel or 1x1 3-channel
|
||||
|
||||
:param P: New camera matrix (3x3) or new projection matrix (3x4)
|
||||
|
||||
:param size: Undistorted image size.
|
||||
|
||||
:param m1type: Type of the first output map that can be CV_32FC1 or CV_16SC2 . See convertMaps() for details.
|
||||
|
||||
:param map1: The first output map.
|
||||
|
||||
:param map2: The second output map.
|
||||
|
||||
fisheye::undistortImage
|
||||
-----------------------
|
||||
Transforms an image to compensate for fisheye lens distortion.
|
||||
|
||||
.. ocv:function:: void fisheye::undistortImage(InputArray distorted, OutputArray undistorted, InputArray K, InputArray D, InputArray Knew = cv::noArray(), const Size& new_size = Size())
|
||||
|
||||
:param distorted: image with fisheye lens distortion.
|
||||
|
||||
:param K: Camera matrix :math:`K = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{_1}`.
|
||||
|
||||
:param D: Input vector of distortion coefficients :math:`(k_1, k_2, k_3, k_4)`.
|
||||
|
||||
:param Knew: Camera matrix of the distorted image. By default, it is the identity matrix but you may additionally scale and shift the result by using a different matrix.
|
||||
|
||||
:param undistorted: Output image with compensated fisheye lens distortion.
|
||||
|
||||
The function transforms an image to compensate radial and tangential lens distortion.
|
||||
|
||||
The function is simply a combination of
|
||||
:ocv:func:`fisheye::initUndistortRectifyMap` (with unity ``R`` ) and
|
||||
:ocv:func:`remap` (with bilinear interpolation). See the former function for details of the transformation being performed.
|
||||
|
||||
See below the results of undistortImage.
|
||||
* a\) result of :ocv:func:`undistort` of perspective camera model (all possible coefficients (k_1, k_2, k_3, k_4, k_5, k_6) of distortion were optimized under calibration)
|
||||
* b\) result of :ocv:func:`fisheye::undistortImage` of fisheye camera model (all possible coefficients (k_1, k_2, k_3, k_4) of fisheye distortion were optimized under calibration)
|
||||
* c\) original image was captured with fisheye lens
|
||||
|
||||
Pictures a) and b) almost the same. But if we consider points of image located far from the center of image, we can notice that on image a) these points are distorted.
|
||||
|
||||
.. image:: pics/fisheye_undistorted.jpg
|
||||
|
||||
|
||||
fisheye::estimateNewCameraMatrixForUndistortRectify
|
||||
----------------------------------------------------------
|
||||
Estimates new camera matrix for undistortion or rectification.
|
||||
|
||||
.. ocv:function:: void fisheye::estimateNewCameraMatrixForUndistortRectify(InputArray K, InputArray D, const Size &image_size, InputArray R, OutputArray P, double balance = 0.0, const Size& new_size = Size(), double fov_scale = 1.0)
|
||||
|
||||
:param K: Camera matrix :math:`K = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{_1}`.
|
||||
|
||||
:param D: Input vector of distortion coefficients :math:`(k_1, k_2, k_3, k_4)`.
|
||||
|
||||
:param R: Rectification transformation in the object space: 3x3 1-channel, or vector: 3x1/1x3 1-channel or 1x1 3-channel
|
||||
|
||||
:param P: New camera matrix (3x3) or new projection matrix (3x4)
|
||||
|
||||
:param balance: Sets the new focal length in range between the min focal length and the max focal length. Balance is in range of [0, 1].
|
||||
|
||||
:param fov_scale: Divisor for new focal length.
|
||||
|
||||
fisheye::stereoRectify
|
||||
------------------------------
|
||||
Stereo rectification for fisheye camera model
|
||||
|
||||
.. ocv:function:: void fisheye::stereoRectify(InputArray K1, InputArray D1, InputArray K2, InputArray D2, const Size &imageSize, InputArray R, InputArray tvec, OutputArray R1, OutputArray R2, OutputArray P1, OutputArray P2, OutputArray Q, int flags, const Size &newImageSize = Size(), double balance = 0.0, double fov_scale = 1.0)
|
||||
|
||||
:param K1: First camera matrix.
|
||||
|
||||
:param K2: Second camera matrix.
|
||||
|
||||
:param D1: First camera distortion parameters.
|
||||
|
||||
:param D2: Second camera distortion parameters.
|
||||
|
||||
:param imageSize: Size of the image used for stereo calibration.
|
||||
|
||||
:param rotation: Rotation matrix between the coordinate systems of the first and the second cameras.
|
||||
|
||||
:param tvec: Translation vector between coordinate systems of the cameras.
|
||||
|
||||
:param R1: Output 3x3 rectification transform (rotation matrix) for the first camera.
|
||||
|
||||
:param R2: Output 3x3 rectification transform (rotation matrix) for the second camera.
|
||||
|
||||
:param P1: Output 3x4 projection matrix in the new (rectified) coordinate systems for the first camera.
|
||||
|
||||
:param P2: Output 3x4 projection matrix in the new (rectified) coordinate systems for the second camera.
|
||||
|
||||
:param Q: Output :math:`4 \times 4` disparity-to-depth mapping matrix (see :ocv:func:`reprojectImageTo3D` ).
|
||||
|
||||
:param flags: Operation flags that may be zero or ``CV_CALIB_ZERO_DISPARITY`` . If the flag is set, the function makes the principal points of each camera have the same pixel coordinates in the rectified views. And if the flag is not set, the function may still shift the images in the horizontal or vertical direction (depending on the orientation of epipolar lines) to maximize the useful image area.
|
||||
|
||||
:param alpha: Free scaling parameter. If it is -1 or absent, the function performs the default scaling. Otherwise, the parameter should be between 0 and 1. ``alpha=0`` means that the rectified images are zoomed and shifted so that only valid pixels are visible (no black areas after rectification). ``alpha=1`` means that the rectified image is decimated and shifted so that all the pixels from the original images from the cameras are retained in the rectified images (no source image pixels are lost). Obviously, any intermediate value yields an intermediate result between those two extreme cases.
|
||||
|
||||
:param newImageSize: New image resolution after rectification. The same size should be passed to :ocv:func:`initUndistortRectifyMap` (see the ``stereo_calib.cpp`` sample in OpenCV samples directory). When (0,0) is passed (default), it is set to the original ``imageSize`` . Setting it to larger value can help you preserve details in the original image, especially when there is a big radial distortion.
|
||||
|
||||
:param roi1: Optional output rectangles inside the rectified images where all the pixels are valid. If ``alpha=0`` , the ROIs cover the whole images. Otherwise, they are likely to be smaller (see the picture below).
|
||||
|
||||
:param roi2: Optional output rectangles inside the rectified images where all the pixels are valid. If ``alpha=0`` , the ROIs cover the whole images. Otherwise, they are likely to be smaller (see the picture below).
|
||||
|
||||
:param balance: Sets the new focal length in range between the min focal length and the max focal length. Balance is in range of [0, 1].
|
||||
|
||||
:param fov_scale: Divisor for new focal length.
|
||||
|
||||
|
||||
|
||||
fisheye::calibrate
|
||||
----------------------------
|
||||
Performs camera calibaration
|
||||
|
||||
.. ocv:function:: double fisheye::calibrate(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints, const Size& image_size, InputOutputArray K, InputOutputArray D, OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs, int flags = 0, TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 100, DBL_EPSILON))
|
||||
|
||||
:param objectPoints: vector of vectors of calibration pattern points in the calibration pattern coordinate space.
|
||||
|
||||
:param imagePoints: vector of vectors of the projections of calibration pattern points. ``imagePoints.size()`` and ``objectPoints.size()`` and ``imagePoints[i].size()`` must be equal to ``objectPoints[i].size()`` for each ``i``.
|
||||
|
||||
:param image_size: Size of the image used only to initialize the intrinsic camera matrix.
|
||||
|
||||
:param K: Output 3x3 floating-point camera matrix :math:`A = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1}` . If ``fisheye::CALIB_USE_INTRINSIC_GUESS``/ is specified, some or all of ``fx, fy, cx, cy`` must be initialized before calling the function.
|
||||
|
||||
:param D: Output vector of distortion coefficients :math:`(k_1, k_2, k_3, k_4)`.
|
||||
|
||||
:param rvecs: Output vector of rotation vectors (see :ocv:func:`Rodrigues` ) estimated for each pattern view. That is, each k-th rotation vector together with the corresponding k-th translation vector (see the next output parameter description) brings the calibration pattern from the model coordinate space (in which object points are specified) to the world coordinate space, that is, a real position of the calibration pattern in the k-th pattern view (k=0.. *M* -1).
|
||||
|
||||
:param tvecs: Output vector of translation vectors estimated for each pattern view.
|
||||
|
||||
:param flags: Different flags that may be zero or a combination of the following values:
|
||||
|
||||
* **fisheye::CALIB_USE_INTRINSIC_GUESS** ``cameraMatrix`` contains valid initial values of ``fx, fy, cx, cy`` that are optimized further. Otherwise, ``(cx, cy)`` is initially set to the image center ( ``imageSize`` is used), and focal distances are computed in a least-squares fashion.
|
||||
|
||||
* **fisheye::CALIB_RECOMPUTE_EXTRINSIC** Extrinsic will be recomputed after each iteration of intrinsic optimization.
|
||||
|
||||
* **fisheye::CALIB_CHECK_COND** The functions will check validity of condition number.
|
||||
|
||||
* **fisheye::CALIB_FIX_SKEW** Skew coefficient (alpha) is set to zero and stay zero.
|
||||
|
||||
* **fisheye::CALIB_FIX_K1..4** Selected distortion coefficients are set to zeros and stay zero.
|
||||
|
||||
:param criteria: Termination criteria for the iterative optimization algorithm.
|
||||
|
||||
|
||||
fisheye::stereoCalibrate
|
||||
----------------------------
|
||||
Performs stereo calibration
|
||||
|
||||
.. ocv:function:: double fisheye::stereoCalibrate(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints1, InputArrayOfArrays imagePoints2, InputOutputArray K1, InputOutputArray D1, InputOutputArray K2, InputOutputArray D2, Size imageSize, OutputArray R, OutputArray T, int flags = CALIB_FIX_INTRINSIC, TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 100, DBL_EPSILON))
|
||||
|
||||
:param objectPoints: Vector of vectors of the calibration pattern points.
|
||||
|
||||
:param imagePoints1: Vector of vectors of the projections of the calibration pattern points, observed by the first camera.
|
||||
|
||||
:param imagePoints2: Vector of vectors of the projections of the calibration pattern points, observed by the second camera.
|
||||
|
||||
:param K1: Input/output first camera matrix: :math:`\vecthreethree{f_x^{(j)}}{0}{c_x^{(j)}}{0}{f_y^{(j)}}{c_y^{(j)}}{0}{0}{1}` , :math:`j = 0,\, 1` . If any of ``fisheye::CALIB_USE_INTRINSIC_GUESS`` , ``fisheye::CV_CALIB_FIX_INTRINSIC`` are specified, some or all of the matrix components must be initialized.
|
||||
|
||||
:param D1: Input/output vector of distortion coefficients :math:`(k_1, k_2, k_3, k_4)` of 4 elements.
|
||||
|
||||
:param K2: Input/output second camera matrix. The parameter is similar to ``K1`` .
|
||||
|
||||
:param D2: Input/output lens distortion coefficients for the second camera. The parameter is similar to ``D1`` .
|
||||
|
||||
:param imageSize: Size of the image used only to initialize intrinsic camera matrix.
|
||||
|
||||
:param R: Output rotation matrix between the 1st and the 2nd camera coordinate systems.
|
||||
|
||||
:param T: Output translation vector between the coordinate systems of the cameras.
|
||||
|
||||
:param flags: Different flags that may be zero or a combination of the following values:
|
||||
|
||||
* **fisheye::CV_CALIB_FIX_INTRINSIC** Fix ``K1, K2?`` and ``D1, D2?`` so that only ``R, T`` matrices are estimated.
|
||||
|
||||
* **fisheye::CALIB_USE_INTRINSIC_GUESS** ``K1, K2`` contains valid initial values of ``fx, fy, cx, cy`` that are optimized further. Otherwise, ``(cx, cy)`` is initially set to the image center (``imageSize`` is used), and focal distances are computed in a least-squares fashion.
|
||||
|
||||
* **fisheye::CALIB_RECOMPUTE_EXTRINSIC** Extrinsic will be recomputed after each iteration of intrinsic optimization.
|
||||
|
||||
* **fisheye::CALIB_CHECK_COND** The functions will check validity of condition number.
|
||||
|
||||
* **fisheye::CALIB_FIX_SKEW** Skew coefficient (alpha) is set to zero and stay zero.
|
||||
|
||||
* **fisheye::CALIB_FIX_K1..4** Selected distortion coefficients are set to zeros and stay zero.
|
||||
|
||||
:param criteria: Termination criteria for the iterative optimization algorithm.
|
||||
|
||||
.. [BT98] Birchfield, S. and Tomasi, C. A pixel dissimilarity measure that is insensitive to image sampling. IEEE Transactions on Pattern Analysis and Machine Intelligence. 1998.
|
||||
|
||||
|
BIN
modules/calib3d/doc/pics/fisheye_undistorted.jpg
Normal file
BIN
modules/calib3d/doc/pics/fisheye_undistorted.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 84 KiB |
@ -45,6 +45,7 @@
|
||||
|
||||
#include "opencv2/core/core.hpp"
|
||||
#include "opencv2/features2d/features2d.hpp"
|
||||
#include "opencv2/core/affine.hpp"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -744,8 +745,67 @@ CV_EXPORTS_W int estimateAffine3D(InputArray src, InputArray dst,
|
||||
OutputArray out, OutputArray inliers,
|
||||
double ransacThreshold=3, double confidence=0.99);
|
||||
|
||||
namespace fisheye
|
||||
{
|
||||
enum{
|
||||
CALIB_USE_INTRINSIC_GUESS = 1,
|
||||
CALIB_RECOMPUTE_EXTRINSIC = 2,
|
||||
CALIB_CHECK_COND = 4,
|
||||
CALIB_FIX_SKEW = 8,
|
||||
CALIB_FIX_K1 = 16,
|
||||
CALIB_FIX_K2 = 32,
|
||||
CALIB_FIX_K3 = 64,
|
||||
CALIB_FIX_K4 = 128,
|
||||
CALIB_FIX_INTRINSIC = 256
|
||||
};
|
||||
|
||||
//! projects 3D points using fisheye model
|
||||
CV_EXPORTS void projectPoints(InputArray objectPoints, OutputArray imagePoints, const Affine3d& affine,
|
||||
InputArray K, InputArray D, double alpha = 0, OutputArray jacobian = noArray());
|
||||
|
||||
//! projects points using fisheye model
|
||||
CV_EXPORTS void projectPoints(InputArray objectPoints, OutputArray imagePoints, InputArray rvec, InputArray tvec,
|
||||
InputArray K, InputArray D, double alpha = 0, OutputArray jacobian = noArray());
|
||||
|
||||
//! distorts 2D points using fisheye model
|
||||
CV_EXPORTS void distortPoints(InputArray undistorted, OutputArray distorted, InputArray K, InputArray D, double alpha = 0);
|
||||
|
||||
//! undistorts 2D points using fisheye model
|
||||
CV_EXPORTS void undistortPoints(InputArray distorted, OutputArray undistorted,
|
||||
InputArray K, InputArray D, InputArray R = noArray(), InputArray P = noArray());
|
||||
|
||||
//! computing undistortion and rectification maps for image transform by cv::remap()
|
||||
//! If D is empty zero distortion is used, if R or P is empty identity matrixes are used
|
||||
CV_EXPORTS void initUndistortRectifyMap(InputArray K, InputArray D, InputArray R, InputArray P,
|
||||
const cv::Size& size, int m1type, OutputArray map1, OutputArray map2);
|
||||
|
||||
//! undistorts image, optionally changes resolution and camera matrix. If Knew zero identity matrix is used
|
||||
CV_EXPORTS void undistortImage(InputArray distorted, OutputArray undistorted,
|
||||
InputArray K, InputArray D, InputArray Knew = cv::noArray(), const Size& new_size = Size());
|
||||
|
||||
//! estimates new camera matrix for undistortion or rectification
|
||||
CV_EXPORTS void estimateNewCameraMatrixForUndistortRectify(InputArray K, InputArray D, const Size &image_size, InputArray R,
|
||||
OutputArray P, double balance = 0.0, const Size& new_size = Size(), double fov_scale = 1.0);
|
||||
|
||||
//! performs camera calibaration
|
||||
CV_EXPORTS double calibrate(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints, const Size& image_size,
|
||||
InputOutputArray K, InputOutputArray D, OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs, int flags = 0,
|
||||
TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 100, DBL_EPSILON));
|
||||
|
||||
//! stereo rectification estimation
|
||||
CV_EXPORTS void stereoRectify(InputArray K1, InputArray D1, InputArray K2, InputArray D2, const Size &imageSize, InputArray R, InputArray tvec,
|
||||
OutputArray R1, OutputArray R2, OutputArray P1, OutputArray P2, OutputArray Q, int flags, const Size &newImageSize = Size(),
|
||||
double balance = 0.0, double fov_scale = 1.0);
|
||||
|
||||
//! performs stereo calibaration
|
||||
CV_EXPORTS double stereoCalibrate(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints1, InputArrayOfArrays imagePoints2,
|
||||
InputOutputArray K1, InputOutputArray D1, InputOutputArray K2, InputOutputArray D2, Size imageSize,
|
||||
OutputArray R, OutputArray T, int flags = CALIB_FIX_INTRINSIC,
|
||||
TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 100, DBL_EPSILON));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
1612
modules/calib3d/src/fisheye.cpp
Normal file
1612
modules/calib3d/src/fisheye.cpp
Normal file
File diff suppressed because it is too large
Load Diff
61
modules/calib3d/src/fisheye.hpp
Normal file
61
modules/calib3d/src/fisheye.hpp
Normal file
@ -0,0 +1,61 @@
|
||||
#ifndef FISHEYE_INTERNAL_H
|
||||
#define FISHEYE_INTERNAL_H
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv { namespace internal {
|
||||
|
||||
struct CV_EXPORTS IntrinsicParams
|
||||
{
|
||||
Vec2d f;
|
||||
Vec2d c;
|
||||
Vec4d k;
|
||||
double alpha;
|
||||
std::vector<int> isEstimate;
|
||||
|
||||
IntrinsicParams();
|
||||
IntrinsicParams(Vec2d f, Vec2d c, Vec4d k, double alpha = 0);
|
||||
IntrinsicParams operator+(const Mat& a);
|
||||
IntrinsicParams& operator =(const Mat& a);
|
||||
void Init(const cv::Vec2d& f, const cv::Vec2d& c, const cv::Vec4d& k = Vec4d(0,0,0,0), const double& alpha = 0);
|
||||
};
|
||||
|
||||
void projectPoints(cv::InputArray objectPoints, cv::OutputArray imagePoints,
|
||||
cv::InputArray _rvec,cv::InputArray _tvec,
|
||||
const IntrinsicParams& param, cv::OutputArray jacobian);
|
||||
|
||||
void ComputeExtrinsicRefine(const Mat& imagePoints, const Mat& objectPoints, Mat& rvec,
|
||||
Mat& tvec, Mat& J, const int MaxIter,
|
||||
const IntrinsicParams& param, const double thresh_cond);
|
||||
CV_EXPORTS Mat ComputeHomography(Mat m, Mat M);
|
||||
|
||||
CV_EXPORTS Mat NormalizePixels(const Mat& imagePoints, const IntrinsicParams& param);
|
||||
|
||||
void InitExtrinsics(const Mat& _imagePoints, const Mat& _objectPoints, const IntrinsicParams& param, Mat& omckk, Mat& Tckk);
|
||||
|
||||
void CalibrateExtrinsics(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints,
|
||||
const IntrinsicParams& param, const int check_cond,
|
||||
const double thresh_cond, InputOutputArray omc, InputOutputArray Tc);
|
||||
|
||||
void ComputeJacobians(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints,
|
||||
const IntrinsicParams& param, InputArray omc, InputArray Tc,
|
||||
const int& check_cond, const double& thresh_cond, Mat& JJ2_inv, Mat& ex3);
|
||||
|
||||
CV_EXPORTS void EstimateUncertainties(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints,
|
||||
const IntrinsicParams& params, InputArray omc, InputArray Tc,
|
||||
IntrinsicParams& errors, Vec2d& std_err, double thresh_cond, int check_cond, double& rms);
|
||||
|
||||
void dAB(cv::InputArray A, InputArray B, OutputArray dABdA, OutputArray dABdB);
|
||||
|
||||
void JRodriguesMatlab(const Mat& src, Mat& dst);
|
||||
|
||||
void compose_motion(InputArray _om1, InputArray _T1, InputArray _om2, InputArray _T2,
|
||||
Mat& om3, Mat& T3, Mat& dom3dom1, Mat& dom3dT1, Mat& dom3dom2,
|
||||
Mat& dom3dT2, Mat& dT3dom1, Mat& dT3dT1, Mat& dT3dom2, Mat& dT3dT2);
|
||||
|
||||
double median(const Mat& row);
|
||||
|
||||
Vec3d median3d(InputArray m);
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
626
modules/calib3d/test/test_fisheye.cpp
Normal file
626
modules/calib3d/test/test_fisheye.cpp
Normal file
@ -0,0 +1,626 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
#include <opencv2/ts/gpu_test.hpp>
|
||||
#include "../src/fisheye.hpp"
|
||||
|
||||
class fisheyeTest : public ::testing::Test {
|
||||
|
||||
protected:
|
||||
const static cv::Size imageSize;
|
||||
const static cv::Matx33d K;
|
||||
const static cv::Vec4d D;
|
||||
const static cv::Matx33d R;
|
||||
const static cv::Vec3d T;
|
||||
std::string datasets_repository_path;
|
||||
|
||||
virtual void SetUp() {
|
||||
datasets_repository_path = combine(cvtest::TS::ptr()->get_data_path(), "cameracalibration/fisheye");
|
||||
}
|
||||
|
||||
protected:
|
||||
std::string combine(const std::string& _item1, const std::string& _item2);
|
||||
std::string combine_format(const std::string& item1, const std::string& item2, ...);
|
||||
|
||||
cv::Mat mergeRectification(const cv::Mat& l, const cv::Mat& r);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// TESTS::
|
||||
|
||||
TEST_F(fisheyeTest, projectPoints)
|
||||
{
|
||||
double cols = this->imageSize.width,
|
||||
rows = this->imageSize.height;
|
||||
|
||||
const int N = 20;
|
||||
cv::Mat distorted0(1, N*N, CV_64FC2), undist1, undist2, distorted1, distorted2;
|
||||
undist2.create(distorted0.size(), CV_MAKETYPE(distorted0.depth(), 3));
|
||||
cv::Vec2d* pts = distorted0.ptr<cv::Vec2d>();
|
||||
|
||||
cv::Vec2d c(this->K(0, 2), this->K(1, 2));
|
||||
for(int y = 0, k = 0; y < N; ++y)
|
||||
for(int x = 0; x < N; ++x)
|
||||
{
|
||||
cv::Vec2d point(x*cols/(N-1.f), y*rows/(N-1.f));
|
||||
pts[k++] = (point - c) * 0.85 + c;
|
||||
}
|
||||
|
||||
cv::fisheye::undistortPoints(distorted0, undist1, this->K, this->D);
|
||||
|
||||
cv::Vec2d* u1 = undist1.ptr<cv::Vec2d>();
|
||||
cv::Vec3d* u2 = undist2.ptr<cv::Vec3d>();
|
||||
for(int i = 0; i < (int)distorted0.total(); ++i)
|
||||
u2[i] = cv::Vec3d(u1[i][0], u1[i][1], 1.0);
|
||||
|
||||
cv::fisheye::distortPoints(undist1, distorted1, this->K, this->D);
|
||||
cv::fisheye::projectPoints(undist2, distorted2, cv::Vec3d::all(0), cv::Vec3d::all(0), this->K, this->D);
|
||||
|
||||
EXPECT_MAT_NEAR(distorted0, distorted1, 1e-10);
|
||||
EXPECT_MAT_NEAR(distorted0, distorted2, 1e-10);
|
||||
}
|
||||
|
||||
TEST_F(fisheyeTest, undistortImage)
|
||||
{
|
||||
cv::Matx33d K = this->K;
|
||||
cv::Mat D = cv::Mat(this->D);
|
||||
std::string file = combine(datasets_repository_path, "/calib-3_stereo_from_JY/left/stereo_pair_014.jpg");
|
||||
cv::Matx33d newK = K;
|
||||
cv::Mat distorted = cv::imread(file), undistorted;
|
||||
{
|
||||
newK(0, 0) = 100;
|
||||
newK(1, 1) = 100;
|
||||
cv::fisheye::undistortImage(distorted, undistorted, K, D, newK);
|
||||
cv::Mat correct = cv::imread(combine(datasets_repository_path, "new_f_100.png"));
|
||||
if (correct.empty())
|
||||
CV_Assert(cv::imwrite(combine(datasets_repository_path, "new_f_100.png"), undistorted));
|
||||
else
|
||||
EXPECT_MAT_NEAR(correct, undistorted, 1e-10);
|
||||
}
|
||||
{
|
||||
double balance = 1.0;
|
||||
cv::fisheye::estimateNewCameraMatrixForUndistortRectify(K, D, distorted.size(), cv::noArray(), newK, balance);
|
||||
cv::fisheye::undistortImage(distorted, undistorted, K, D, newK);
|
||||
cv::Mat correct = cv::imread(combine(datasets_repository_path, "balance_1.0.png"));
|
||||
if (correct.empty())
|
||||
CV_Assert(cv::imwrite(combine(datasets_repository_path, "balance_1.0.png"), undistorted));
|
||||
else
|
||||
EXPECT_MAT_NEAR(correct, undistorted, 1e-10);
|
||||
}
|
||||
|
||||
{
|
||||
double balance = 0.0;
|
||||
cv::fisheye::estimateNewCameraMatrixForUndistortRectify(K, D, distorted.size(), cv::noArray(), newK, balance);
|
||||
cv::fisheye::undistortImage(distorted, undistorted, K, D, newK);
|
||||
cv::Mat correct = cv::imread(combine(datasets_repository_path, "balance_0.0.png"));
|
||||
if (correct.empty())
|
||||
CV_Assert(cv::imwrite(combine(datasets_repository_path, "balance_0.0.png"), undistorted));
|
||||
else
|
||||
EXPECT_MAT_NEAR(correct, undistorted, 1e-10);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(fisheyeTest, jacobians)
|
||||
{
|
||||
int n = 10;
|
||||
cv::Mat X(1, n, CV_64FC3);
|
||||
cv::Mat om(3, 1, CV_64F), T(3, 1, CV_64F);
|
||||
cv::Mat f(2, 1, CV_64F), c(2, 1, CV_64F);
|
||||
cv::Mat k(4, 1, CV_64F);
|
||||
double alpha;
|
||||
|
||||
cv::RNG& r = cv::theRNG();
|
||||
|
||||
r.fill(X, cv::RNG::NORMAL, 2, 1);
|
||||
X = cv::abs(X) * 10;
|
||||
|
||||
r.fill(om, cv::RNG::NORMAL, 0, 1);
|
||||
om = cv::abs(om);
|
||||
|
||||
r.fill(T, cv::RNG::NORMAL, 0, 1);
|
||||
T = cv::abs(T); T.at<double>(2) = 4; T *= 10;
|
||||
|
||||
r.fill(f, cv::RNG::NORMAL, 0, 1);
|
||||
f = cv::abs(f) * 1000;
|
||||
|
||||
r.fill(c, cv::RNG::NORMAL, 0, 1);
|
||||
c = cv::abs(c) * 1000;
|
||||
|
||||
r.fill(k, cv::RNG::NORMAL, 0, 1);
|
||||
k*= 0.5;
|
||||
|
||||
alpha = 0.01*r.gaussian(1);
|
||||
|
||||
cv::Mat x1, x2, xpred;
|
||||
cv::Matx33d K(f.at<double>(0), alpha * f.at<double>(0), c.at<double>(0),
|
||||
0, f.at<double>(1), c.at<double>(1),
|
||||
0, 0, 1);
|
||||
|
||||
cv::Mat jacobians;
|
||||
cv::fisheye::projectPoints(X, x1, om, T, K, k, alpha, jacobians);
|
||||
|
||||
//test on T:
|
||||
cv::Mat dT(3, 1, CV_64FC1);
|
||||
r.fill(dT, cv::RNG::NORMAL, 0, 1);
|
||||
dT *= 1e-9*cv::norm(T);
|
||||
cv::Mat T2 = T + dT;
|
||||
cv::fisheye::projectPoints(X, x2, om, T2, K, k, alpha, cv::noArray());
|
||||
xpred = x1 + cv::Mat(jacobians.colRange(11,14) * dT).reshape(2, 1);
|
||||
CV_Assert (cv::norm(x2 - xpred) < 1e-10);
|
||||
|
||||
//test on om:
|
||||
cv::Mat dom(3, 1, CV_64FC1);
|
||||
r.fill(dom, cv::RNG::NORMAL, 0, 1);
|
||||
dom *= 1e-9*cv::norm(om);
|
||||
cv::Mat om2 = om + dom;
|
||||
cv::fisheye::projectPoints(X, x2, om2, T, K, k, alpha, cv::noArray());
|
||||
xpred = x1 + cv::Mat(jacobians.colRange(8,11) * dom).reshape(2, 1);
|
||||
CV_Assert (cv::norm(x2 - xpred) < 1e-10);
|
||||
|
||||
//test on f:
|
||||
cv::Mat df(2, 1, CV_64FC1);
|
||||
r.fill(df, cv::RNG::NORMAL, 0, 1);
|
||||
df *= 1e-9*cv::norm(f);
|
||||
cv::Matx33d K2 = K + cv::Matx33d(df.at<double>(0), df.at<double>(0) * alpha, 0, 0, df.at<double>(1), 0, 0, 0, 0);
|
||||
cv::fisheye::projectPoints(X, x2, om, T, K2, k, alpha, cv::noArray());
|
||||
xpred = x1 + cv::Mat(jacobians.colRange(0,2) * df).reshape(2, 1);
|
||||
CV_Assert (cv::norm(x2 - xpred) < 1e-10);
|
||||
|
||||
//test on c:
|
||||
cv::Mat dc(2, 1, CV_64FC1);
|
||||
r.fill(dc, cv::RNG::NORMAL, 0, 1);
|
||||
dc *= 1e-9*cv::norm(c);
|
||||
K2 = K + cv::Matx33d(0, 0, dc.at<double>(0), 0, 0, dc.at<double>(1), 0, 0, 0);
|
||||
cv::fisheye::projectPoints(X, x2, om, T, K2, k, alpha, cv::noArray());
|
||||
xpred = x1 + cv::Mat(jacobians.colRange(2,4) * dc).reshape(2, 1);
|
||||
CV_Assert (cv::norm(x2 - xpred) < 1e-10);
|
||||
|
||||
//test on k:
|
||||
cv::Mat dk(4, 1, CV_64FC1);
|
||||
r.fill(dk, cv::RNG::NORMAL, 0, 1);
|
||||
dk *= 1e-9*cv::norm(k);
|
||||
cv::Mat k2 = k + dk;
|
||||
cv::fisheye::projectPoints(X, x2, om, T, K, k2, alpha, cv::noArray());
|
||||
xpred = x1 + cv::Mat(jacobians.colRange(4,8) * dk).reshape(2, 1);
|
||||
CV_Assert (cv::norm(x2 - xpred) < 1e-10);
|
||||
|
||||
//test on alpha:
|
||||
cv::Mat dalpha(1, 1, CV_64FC1);
|
||||
r.fill(dalpha, cv::RNG::NORMAL, 0, 1);
|
||||
dalpha *= 1e-9*cv::norm(f);
|
||||
double alpha2 = alpha + dalpha.at<double>(0);
|
||||
K2 = K + cv::Matx33d(0, f.at<double>(0) * dalpha.at<double>(0), 0, 0, 0, 0, 0, 0, 0);
|
||||
cv::fisheye::projectPoints(X, x2, om, T, K, k, alpha2, cv::noArray());
|
||||
xpred = x1 + cv::Mat(jacobians.col(14) * dalpha).reshape(2, 1);
|
||||
CV_Assert (cv::norm(x2 - xpred) < 1e-10);
|
||||
}
|
||||
|
||||
TEST_F(fisheyeTest, Calibration)
|
||||
{
|
||||
const int n_images = 34;
|
||||
|
||||
std::vector<std::vector<cv::Point2d> > imagePoints(n_images);
|
||||
std::vector<std::vector<cv::Point3d> > objectPoints(n_images);
|
||||
|
||||
const std::string folder =combine(datasets_repository_path, "calib-3_stereo_from_JY");
|
||||
cv::FileStorage fs_left(combine(folder, "left.xml"), cv::FileStorage::READ);
|
||||
CV_Assert(fs_left.isOpened());
|
||||
for(int i = 0; i < n_images; ++i)
|
||||
fs_left[cv::format("image_%d", i )] >> imagePoints[i];
|
||||
fs_left.release();
|
||||
|
||||
cv::FileStorage fs_object(combine(folder, "object.xml"), cv::FileStorage::READ);
|
||||
CV_Assert(fs_object.isOpened());
|
||||
for(int i = 0; i < n_images; ++i)
|
||||
fs_object[cv::format("image_%d", i )] >> objectPoints[i];
|
||||
fs_object.release();
|
||||
|
||||
int flag = 0;
|
||||
flag |= cv::fisheye::CALIB_RECOMPUTE_EXTRINSIC;
|
||||
flag |= cv::fisheye::CALIB_CHECK_COND;
|
||||
flag |= cv::fisheye::CALIB_FIX_SKEW;
|
||||
|
||||
cv::Matx33d K;
|
||||
cv::Vec4d D;
|
||||
|
||||
cv::fisheye::calibrate(objectPoints, imagePoints, imageSize, K, D,
|
||||
cv::noArray(), cv::noArray(), flag, cv::TermCriteria(3, 20, 1e-6));
|
||||
|
||||
EXPECT_MAT_NEAR(K, this->K, 1e-10);
|
||||
EXPECT_MAT_NEAR(D, this->D, 1e-10);
|
||||
}
|
||||
|
||||
TEST_F(fisheyeTest, Homography)
|
||||
{
|
||||
const int n_images = 1;
|
||||
|
||||
std::vector<std::vector<cv::Point2d> > imagePoints(n_images);
|
||||
std::vector<std::vector<cv::Point3d> > objectPoints(n_images);
|
||||
|
||||
const std::string folder =combine(datasets_repository_path, "calib-3_stereo_from_JY");
|
||||
cv::FileStorage fs_left(combine(folder, "left.xml"), cv::FileStorage::READ);
|
||||
CV_Assert(fs_left.isOpened());
|
||||
for(int i = 0; i < n_images; ++i)
|
||||
fs_left[cv::format("image_%d", i )] >> imagePoints[i];
|
||||
fs_left.release();
|
||||
|
||||
cv::FileStorage fs_object(combine(folder, "object.xml"), cv::FileStorage::READ);
|
||||
CV_Assert(fs_object.isOpened());
|
||||
for(int i = 0; i < n_images; ++i)
|
||||
fs_object[cv::format("image_%d", i )] >> objectPoints[i];
|
||||
fs_object.release();
|
||||
|
||||
cv::internal::IntrinsicParams param;
|
||||
param.Init(cv::Vec2d(cv::max(imageSize.width, imageSize.height) / CV_PI, cv::max(imageSize.width, imageSize.height) / CV_PI),
|
||||
cv::Vec2d(imageSize.width / 2.0 - 0.5, imageSize.height / 2.0 - 0.5));
|
||||
|
||||
cv::Mat _imagePoints (imagePoints[0]);
|
||||
cv::Mat _objectPoints(objectPoints[0]);
|
||||
|
||||
cv::Mat imagePointsNormalized = NormalizePixels(_imagePoints, param).reshape(1).t();
|
||||
_objectPoints = _objectPoints.reshape(1).t();
|
||||
cv::Mat objectPointsMean, covObjectPoints;
|
||||
|
||||
int Np = imagePointsNormalized.cols;
|
||||
cv::calcCovarMatrix(_objectPoints, covObjectPoints, objectPointsMean, CV_COVAR_NORMAL | CV_COVAR_COLS);
|
||||
cv::SVD svd(covObjectPoints);
|
||||
cv::Mat R(svd.vt);
|
||||
|
||||
if (cv::norm(R(cv::Rect(2, 0, 1, 2))) < 1e-6)
|
||||
R = cv::Mat::eye(3,3, CV_64FC1);
|
||||
if (cv::determinant(R) < 0)
|
||||
R = -R;
|
||||
|
||||
cv::Mat T = -R * objectPointsMean;
|
||||
cv::Mat X_new = R * _objectPoints + T * cv::Mat::ones(1, Np, CV_64FC1);
|
||||
cv::Mat H = cv::internal::ComputeHomography(imagePointsNormalized, X_new.rowRange(0, 2));
|
||||
|
||||
cv::Mat M = cv::Mat::ones(3, X_new.cols, CV_64FC1);
|
||||
X_new.rowRange(0, 2).copyTo(M.rowRange(0, 2));
|
||||
cv::Mat mrep = H * M;
|
||||
|
||||
cv::divide(mrep, cv::Mat::ones(3,1, CV_64FC1) * mrep.row(2).clone(), mrep);
|
||||
|
||||
cv::Mat merr = (mrep.rowRange(0, 2) - imagePointsNormalized).t();
|
||||
|
||||
cv::Vec2d std_err;
|
||||
cv::meanStdDev(merr.reshape(2), cv::noArray(), std_err);
|
||||
std_err *= sqrt((double)merr.reshape(2).total() / (merr.reshape(2).total() - 1));
|
||||
|
||||
cv::Vec2d correct_std_err(0.00516740156010384, 0.00644205331553901);
|
||||
EXPECT_MAT_NEAR(std_err, correct_std_err, 1e-12);
|
||||
}
|
||||
|
||||
TEST_F(fisheyeTest, EtimateUncertainties)
|
||||
{
|
||||
const int n_images = 34;
|
||||
|
||||
std::vector<std::vector<cv::Point2d> > imagePoints(n_images);
|
||||
std::vector<std::vector<cv::Point3d> > objectPoints(n_images);
|
||||
|
||||
const std::string folder =combine(datasets_repository_path, "calib-3_stereo_from_JY");
|
||||
cv::FileStorage fs_left(combine(folder, "left.xml"), cv::FileStorage::READ);
|
||||
CV_Assert(fs_left.isOpened());
|
||||
for(int i = 0; i < n_images; ++i)
|
||||
fs_left[cv::format("image_%d", i )] >> imagePoints[i];
|
||||
fs_left.release();
|
||||
|
||||
cv::FileStorage fs_object(combine(folder, "object.xml"), cv::FileStorage::READ);
|
||||
CV_Assert(fs_object.isOpened());
|
||||
for(int i = 0; i < n_images; ++i)
|
||||
fs_object[cv::format("image_%d", i )] >> objectPoints[i];
|
||||
fs_object.release();
|
||||
|
||||
int flag = 0;
|
||||
flag |= cv::fisheye::CALIB_RECOMPUTE_EXTRINSIC;
|
||||
flag |= cv::fisheye::CALIB_CHECK_COND;
|
||||
flag |= cv::fisheye::CALIB_FIX_SKEW;
|
||||
|
||||
cv::Matx33d K;
|
||||
cv::Vec4d D;
|
||||
std::vector<cv::Vec3d> rvec;
|
||||
std::vector<cv::Vec3d> tvec;
|
||||
|
||||
cv::fisheye::calibrate(objectPoints, imagePoints, imageSize, K, D,
|
||||
rvec, tvec, flag, cv::TermCriteria(3, 20, 1e-6));
|
||||
|
||||
cv::internal::IntrinsicParams param, errors;
|
||||
cv::Vec2d err_std;
|
||||
double thresh_cond = 1e6;
|
||||
int check_cond = 1;
|
||||
param.Init(cv::Vec2d(K(0,0), K(1,1)), cv::Vec2d(K(0,2), K(1, 2)), D);
|
||||
param.isEstimate = std::vector<int>(9, 1);
|
||||
param.isEstimate[4] = 0;
|
||||
|
||||
errors.isEstimate = param.isEstimate;
|
||||
|
||||
double rms;
|
||||
|
||||
cv::internal::EstimateUncertainties(objectPoints, imagePoints, param, rvec, tvec,
|
||||
errors, err_std, thresh_cond, check_cond, rms);
|
||||
|
||||
EXPECT_MAT_NEAR(errors.f, cv::Vec2d(1.29837104202046, 1.31565641071524), 1e-10);
|
||||
EXPECT_MAT_NEAR(errors.c, cv::Vec2d(0.890439368129246, 0.816096854937896), 1e-10);
|
||||
EXPECT_MAT_NEAR(errors.k, cv::Vec4d(0.00516248605191506, 0.0168181467500934, 0.0213118690274604, 0.00916010877545648), 1e-10);
|
||||
EXPECT_MAT_NEAR(err_std, cv::Vec2d(0.187475975266883, 0.185678953263995), 1e-10);
|
||||
CV_Assert(abs(rms - 0.263782587133546) < 1e-10);
|
||||
CV_Assert(errors.alpha == 0);
|
||||
}
|
||||
|
||||
TEST_F(fisheyeTest, rectify)
|
||||
{
|
||||
const std::string folder =combine(datasets_repository_path, "calib-3_stereo_from_JY");
|
||||
|
||||
cv::Size calibration_size = this->imageSize, requested_size = calibration_size;
|
||||
cv::Matx33d K1 = this->K, K2 = K1;
|
||||
cv::Mat D1 = cv::Mat(this->D), D2 = D1;
|
||||
|
||||
cv::Vec3d T = this->T;
|
||||
cv::Matx33d R = this->R;
|
||||
|
||||
double balance = 0.0, fov_scale = 1.1;
|
||||
cv::Mat R1, R2, P1, P2, Q;
|
||||
cv::fisheye::stereoRectify(K1, D1, K2, D2, calibration_size, R, T, R1, R2, P1, P2, Q,
|
||||
cv::CALIB_ZERO_DISPARITY, requested_size, balance, fov_scale);
|
||||
|
||||
cv::Mat lmapx, lmapy, rmapx, rmapy;
|
||||
//rewrite for fisheye
|
||||
cv::fisheye::initUndistortRectifyMap(K1, D1, R1, P1, requested_size, CV_32F, lmapx, lmapy);
|
||||
cv::fisheye::initUndistortRectifyMap(K2, D2, R2, P2, requested_size, CV_32F, rmapx, rmapy);
|
||||
|
||||
cv::Mat l, r, lundist, rundist;
|
||||
cv::VideoCapture lcap(combine(folder, "left/stereo_pair_%03d.jpg")),
|
||||
rcap(combine(folder, "right/stereo_pair_%03d.jpg"));
|
||||
|
||||
for(int i = 0;; ++i)
|
||||
{
|
||||
lcap >> l; rcap >> r;
|
||||
if (l.empty() || r.empty())
|
||||
break;
|
||||
|
||||
int ndisp = 128;
|
||||
cv::rectangle(l, cv::Rect(255, 0, 829, l.rows-1), CV_RGB(255, 0, 0));
|
||||
cv::rectangle(r, cv::Rect(255, 0, 829, l.rows-1), CV_RGB(255, 0, 0));
|
||||
cv::rectangle(r, cv::Rect(255-ndisp, 0, 829+ndisp ,l.rows-1), CV_RGB(255, 0, 0));
|
||||
cv::remap(l, lundist, lmapx, lmapy, cv::INTER_LINEAR);
|
||||
cv::remap(r, rundist, rmapx, rmapy, cv::INTER_LINEAR);
|
||||
|
||||
cv::Mat rectification = mergeRectification(lundist, rundist);
|
||||
|
||||
cv::Mat correct = cv::imread(combine_format(datasets_repository_path, "rectification_AB_%03d.png", i));
|
||||
|
||||
if (correct.empty())
|
||||
cv::imwrite(combine_format(datasets_repository_path, "rectification_AB_%03d.png", i), rectification);
|
||||
else
|
||||
EXPECT_MAT_NEAR(correct, rectification, 1e-10);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(fisheyeTest, stereoCalibrate)
|
||||
{
|
||||
const int n_images = 34;
|
||||
|
||||
const std::string folder =combine(datasets_repository_path, "calib-3_stereo_from_JY");
|
||||
|
||||
std::vector<std::vector<cv::Point2d> > leftPoints(n_images);
|
||||
std::vector<std::vector<cv::Point2d> > rightPoints(n_images);
|
||||
std::vector<std::vector<cv::Point3d> > objectPoints(n_images);
|
||||
|
||||
cv::FileStorage fs_left(combine(folder, "left.xml"), cv::FileStorage::READ);
|
||||
CV_Assert(fs_left.isOpened());
|
||||
for(int i = 0; i < n_images; ++i)
|
||||
fs_left[cv::format("image_%d", i )] >> leftPoints[i];
|
||||
fs_left.release();
|
||||
|
||||
cv::FileStorage fs_right(combine(folder, "right.xml"), cv::FileStorage::READ);
|
||||
CV_Assert(fs_right.isOpened());
|
||||
for(int i = 0; i < n_images; ++i)
|
||||
fs_right[cv::format("image_%d", i )] >> rightPoints[i];
|
||||
fs_right.release();
|
||||
|
||||
cv::FileStorage fs_object(combine(folder, "object.xml"), cv::FileStorage::READ);
|
||||
CV_Assert(fs_object.isOpened());
|
||||
for(int i = 0; i < n_images; ++i)
|
||||
fs_object[cv::format("image_%d", i )] >> objectPoints[i];
|
||||
fs_object.release();
|
||||
|
||||
cv::Matx33d K1, K2, R;
|
||||
cv::Vec3d T;
|
||||
cv::Vec4d D1, D2;
|
||||
|
||||
int flag = 0;
|
||||
flag |= cv::fisheye::CALIB_RECOMPUTE_EXTRINSIC;
|
||||
flag |= cv::fisheye::CALIB_CHECK_COND;
|
||||
flag |= cv::fisheye::CALIB_FIX_SKEW;
|
||||
// flag |= cv::fisheye::CALIB_FIX_INTRINSIC;
|
||||
|
||||
cv::fisheye::stereoCalibrate(objectPoints, leftPoints, rightPoints,
|
||||
K1, D1, K2, D2, imageSize, R, T, flag,
|
||||
cv::TermCriteria(3, 12, 0));
|
||||
|
||||
cv::Matx33d R_correct( 0.9975587205950972, 0.06953016383322372, 0.006492709911733523,
|
||||
-0.06956823121068059, 0.9975601387249519, 0.005833595226966235,
|
||||
-0.006071257768382089, -0.006271040135405457, 0.9999619062167968);
|
||||
cv::Vec3d T_correct(-0.099402724724121, 0.00270812139265413, 0.00129330292472699);
|
||||
cv::Matx33d K1_correct (561.195925927249, 0, 621.282400272412,
|
||||
0, 562.849402029712, 380.555455380889,
|
||||
0, 0, 1);
|
||||
|
||||
cv::Matx33d K2_correct (560.395452535348, 0, 678.971652040359,
|
||||
0, 561.90171021422, 380.401340535339,
|
||||
0, 0, 1);
|
||||
|
||||
cv::Vec4d D1_correct (-7.44253716539556e-05, -0.00702662033932424, 0.00737569823650885, -0.00342230256441771);
|
||||
cv::Vec4d D2_correct (-0.0130785435677431, 0.0284434505383497, -0.0360333869900506, 0.0144724062347222);
|
||||
|
||||
EXPECT_MAT_NEAR(R, R_correct, 1e-10);
|
||||
EXPECT_MAT_NEAR(T, T_correct, 1e-10);
|
||||
|
||||
EXPECT_MAT_NEAR(K1, K1_correct, 1e-10);
|
||||
EXPECT_MAT_NEAR(K2, K2_correct, 1e-10);
|
||||
|
||||
EXPECT_MAT_NEAR(D1, D1_correct, 1e-10);
|
||||
EXPECT_MAT_NEAR(D2, D2_correct, 1e-10);
|
||||
|
||||
}
|
||||
|
||||
TEST_F(fisheyeTest, stereoCalibrateFixIntrinsic)
|
||||
{
|
||||
const int n_images = 34;
|
||||
|
||||
const std::string folder =combine(datasets_repository_path, "calib-3_stereo_from_JY");
|
||||
|
||||
std::vector<std::vector<cv::Point2d> > leftPoints(n_images);
|
||||
std::vector<std::vector<cv::Point2d> > rightPoints(n_images);
|
||||
std::vector<std::vector<cv::Point3d> > objectPoints(n_images);
|
||||
|
||||
cv::FileStorage fs_left(combine(folder, "left.xml"), cv::FileStorage::READ);
|
||||
CV_Assert(fs_left.isOpened());
|
||||
for(int i = 0; i < n_images; ++i)
|
||||
fs_left[cv::format("image_%d", i )] >> leftPoints[i];
|
||||
fs_left.release();
|
||||
|
||||
cv::FileStorage fs_right(combine(folder, "right.xml"), cv::FileStorage::READ);
|
||||
CV_Assert(fs_right.isOpened());
|
||||
for(int i = 0; i < n_images; ++i)
|
||||
fs_right[cv::format("image_%d", i )] >> rightPoints[i];
|
||||
fs_right.release();
|
||||
|
||||
cv::FileStorage fs_object(combine(folder, "object.xml"), cv::FileStorage::READ);
|
||||
CV_Assert(fs_object.isOpened());
|
||||
for(int i = 0; i < n_images; ++i)
|
||||
fs_object[cv::format("image_%d", i )] >> objectPoints[i];
|
||||
fs_object.release();
|
||||
|
||||
cv::Matx33d R;
|
||||
cv::Vec3d T;
|
||||
|
||||
int flag = 0;
|
||||
flag |= cv::fisheye::CALIB_RECOMPUTE_EXTRINSIC;
|
||||
flag |= cv::fisheye::CALIB_CHECK_COND;
|
||||
flag |= cv::fisheye::CALIB_FIX_SKEW;
|
||||
flag |= cv::fisheye::CALIB_FIX_INTRINSIC;
|
||||
|
||||
cv::Matx33d K1 (561.195925927249, 0, 621.282400272412,
|
||||
0, 562.849402029712, 380.555455380889,
|
||||
0, 0, 1);
|
||||
|
||||
cv::Matx33d K2 (560.395452535348, 0, 678.971652040359,
|
||||
0, 561.90171021422, 380.401340535339,
|
||||
0, 0, 1);
|
||||
|
||||
cv::Vec4d D1 (-7.44253716539556e-05, -0.00702662033932424, 0.00737569823650885, -0.00342230256441771);
|
||||
cv::Vec4d D2 (-0.0130785435677431, 0.0284434505383497, -0.0360333869900506, 0.0144724062347222);
|
||||
|
||||
cv::fisheye::stereoCalibrate(objectPoints, leftPoints, rightPoints,
|
||||
K1, D1, K2, D2, imageSize, R, T, flag,
|
||||
cv::TermCriteria(3, 12, 0));
|
||||
|
||||
cv::Matx33d R_correct( 0.9975587205950972, 0.06953016383322372, 0.006492709911733523,
|
||||
-0.06956823121068059, 0.9975601387249519, 0.005833595226966235,
|
||||
-0.006071257768382089, -0.006271040135405457, 0.9999619062167968);
|
||||
cv::Vec3d T_correct(-0.099402724724121, 0.00270812139265413, 0.00129330292472699);
|
||||
|
||||
|
||||
EXPECT_MAT_NEAR(R, R_correct, 1e-10);
|
||||
EXPECT_MAT_NEAR(T, T_correct, 1e-10);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// fisheyeTest::
|
||||
|
||||
const cv::Size fisheyeTest::imageSize(1280, 800);
|
||||
|
||||
const cv::Matx33d fisheyeTest::K(558.478087865323, 0, 620.458515360843,
|
||||
0, 560.506767351568, 381.939424848348,
|
||||
0, 0, 1);
|
||||
|
||||
const cv::Vec4d fisheyeTest::D(-0.0014613319981768, -0.00329861110580401, 0.00605760088590183, -0.00374209380722371);
|
||||
|
||||
const cv::Matx33d fisheyeTest::R ( 9.9756700084424932e-01, 6.9698277640183867e-02, 1.4929569991321144e-03,
|
||||
-6.9711825162322980e-02, 9.9748249845531767e-01, 1.2997180766418455e-02,
|
||||
-5.8331736398316541e-04,-1.3069635393884985e-02, 9.9991441852366736e-01);
|
||||
|
||||
const cv::Vec3d fisheyeTest::T(-9.9217369356044638e-02, 3.1741831972356663e-03, 1.8551007952921010e-04);
|
||||
|
||||
std::string fisheyeTest::combine(const std::string& _item1, const std::string& _item2)
|
||||
{
|
||||
std::string item1 = _item1, item2 = _item2;
|
||||
std::replace(item1.begin(), item1.end(), '\\', '/');
|
||||
std::replace(item2.begin(), item2.end(), '\\', '/');
|
||||
|
||||
if (item1.empty())
|
||||
return item2;
|
||||
|
||||
if (item2.empty())
|
||||
return item1;
|
||||
|
||||
char last = item1[item1.size()-1];
|
||||
return item1 + (last != '/' ? "/" : "") + item2;
|
||||
}
|
||||
|
||||
std::string fisheyeTest::combine_format(const std::string& item1, const std::string& item2, ...)
|
||||
{
|
||||
std::string fmt = combine(item1, item2);
|
||||
char buffer[1 << 16];
|
||||
va_list args;
|
||||
va_start( args, item2 );
|
||||
vsprintf( buffer, fmt.c_str(), args );
|
||||
va_end( args );
|
||||
return std::string(buffer);
|
||||
}
|
||||
|
||||
cv::Mat fisheyeTest::mergeRectification(const cv::Mat& l, const cv::Mat& r)
|
||||
{
|
||||
CV_Assert(l.type() == r.type() && l.size() == r.size());
|
||||
cv::Mat merged(l.rows, l.cols * 2, l.type());
|
||||
cv::Mat lpart = merged.colRange(0, l.cols);
|
||||
cv::Mat rpart = merged.colRange(l.cols, merged.cols);
|
||||
l.copyTo(lpart);
|
||||
r.copyTo(rpart);
|
||||
|
||||
for(int i = 0; i < l.rows; i+=20)
|
||||
cv::line(merged, cv::Point(0, i), cv::Point(merged.cols, i), CV_RGB(0, 255, 0));
|
||||
|
||||
return merged;
|
||||
}
|
Loading…
Reference in New Issue
Block a user