diff --git a/modules/calib3d/include/opencv2/calib3d.hpp b/modules/calib3d/include/opencv2/calib3d.hpp index e2f7d1796b..67bbfb5d15 100644 --- a/modules/calib3d/include/opencv2/calib3d.hpp +++ b/modules/calib3d/include/opencv2/calib3d.hpp @@ -227,7 +227,7 @@ namespace cv //! @{ //! type of the robust estimation algorithm -enum { LMEDS = 4, //!< least-median algorithm +enum { LMEDS = 4, //!< least-median of squares algorithm RANSAC = 8, //!< RANSAC algorithm RHO = 16 //!< RHO algorithm }; @@ -281,8 +281,8 @@ enum { CALIB_USE_INTRINSIC_GUESS = 0x00001, //! the algorithm for finding fundamental matrix enum { FM_7POINT = 1, //!< 7-point algorithm FM_8POINT = 2, //!< 8-point algorithm - FM_LMEDS = 4, //!< least-median algorithm - FM_RANSAC = 8 //!< RANSAC algorithm + FM_LMEDS = 4, //!< least-median algorithm. 7-point algorithm is used. + FM_RANSAC = 8 //!< RANSAC algorithm. It needs at least 15 points. 7-point algorithm is used. }; @@ -1412,11 +1412,11 @@ floating-point (single or double precision). - **CV_FM_8POINT** for an 8-point algorithm. \f$N \ge 8\f$ - **CV_FM_RANSAC** for the RANSAC algorithm. \f$N \ge 8\f$ - **CV_FM_LMEDS** for the LMedS algorithm. \f$N \ge 8\f$ -@param param1 Parameter used for RANSAC. It is the maximum distance from a point to an epipolar +@param ransacReprojThreshold Parameter used only for RANSAC. It is the maximum distance from a point to an epipolar line in pixels, beyond which the point is considered an outlier and is not used for computing the final fundamental matrix. It can be set to something like 1-3, depending on the accuracy of the point localization, image resolution, and the image noise. -@param param2 Parameter used for the RANSAC or LMedS methods only. It specifies a desirable level +@param confidence Parameter used for the RANSAC and LMedS methods only. It specifies a desirable level of confidence (probability) that the estimated matrix is correct. @param mask @@ -1454,13 +1454,13 @@ stereoRectifyUncalibrated to compute the rectification transformation. : */ CV_EXPORTS_W Mat findFundamentalMat( InputArray points1, InputArray points2, int method = FM_RANSAC, - double param1 = 3., double param2 = 0.99, + double ransacReprojThreshold = 3., double confidence = 0.99, OutputArray mask = noArray() ); /** @overload */ CV_EXPORTS Mat findFundamentalMat( InputArray points1, InputArray points2, OutputArray mask, int method = FM_RANSAC, - double param1 = 3., double param2 = 0.99 ); + double ransacReprojThreshold = 3., double confidence = 0.99 ); /** @brief Calculates an essential matrix from the corresponding points in two images. @@ -1770,12 +1770,20 @@ CV_EXPORTS_W void reprojectImageTo3D( InputArray disparity, /** @brief Calculates the Sampson Distance between two points. -The function sampsonDistance calculates and returns the first order approximation of the geometric error as: -\f[sd( \texttt{pt1} , \texttt{pt2} )= \frac{(\texttt{pt2}^t \cdot \texttt{F} \cdot \texttt{pt1})^2}{(\texttt{F} \cdot \texttt{pt1})(0) + (\texttt{F} \cdot \texttt{pt1})(1) + (\texttt{F}^t \cdot \texttt{pt2})(0) + (\texttt{F}^t \cdot \texttt{pt2})(1)}\f] -The fundamental matrix may be calculated using the cv::findFundamentalMat function. See HZ 11.4.3 for details. +The function cv::sampsonDistance calculates and returns the first order approximation of the geometric error as: +\f[ +sd( \texttt{pt1} , \texttt{pt2} )= +\frac{(\texttt{pt2}^t \cdot \texttt{F} \cdot \texttt{pt1})^2} +{((\texttt{F} \cdot \texttt{pt1})(0))^2 + +((\texttt{F} \cdot \texttt{pt1})(1))^2 + +((\texttt{F}^t \cdot \texttt{pt2})(0))^2 + +((\texttt{F}^t \cdot \texttt{pt2})(1))^2} +\f] +The fundamental matrix may be calculated using the cv::findFundamentalMat function. See @cite HartleyZ00 11.4.3 for details. @param pt1 first homogeneous 2d point @param pt2 second homogeneous 2d point @param F fundamental matrix +@return The computed Sampson distance. */ CV_EXPORTS_W double sampsonDistance(InputArray pt1, InputArray pt2, InputArray F); @@ -2402,9 +2410,9 @@ optimization. It stays at the center or at a different location specified when C TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 100, DBL_EPSILON)); //! @} calib3d_fisheye -} +} // end namespace fisheye -} // cv +} //end namespace cv #ifndef DISABLE_OPENCV_24_COMPATIBILITY #include "opencv2/calib3d/calib3d_c.h" diff --git a/modules/calib3d/src/fundam.cpp b/modules/calib3d/src/fundam.cpp index bed91c50c0..693dc949da 100644 --- a/modules/calib3d/src/fundam.cpp +++ b/modules/calib3d/src/fundam.cpp @@ -47,6 +47,18 @@ namespace cv { +/** + * This class estimates a homography \f$H\in \mathbb{R}^{3\times 3}\f$ + * between \f$\mathbf{x} \in \mathbb{R}^3\f$ and + * \f$\mathbf{X} \in \mathbb{R}^3\f$ using DLT (direct linear transform) + * with algebraic distance. + * + * \f[ + * \lambda \mathbf{x} = H \mathbf{X} + * \f] + * where \f$\lambda \in \mathbb{R} \f$. + * + */ class HomographyEstimatorCallback : public PointSetRegistrator::Callback { public: @@ -87,6 +99,20 @@ public: return true; } + /** + * Normalization method: + * - $x$ and $y$ coordinates are normalized independently + * - first the coordinates are shifted so that the average coordinate is \f$(0,0)\f$ + * - then the coordinates are scaled so that the average L1 norm is 1, i.e, + * the average L1 norm of the \f$x\f$ coordinates is 1 and the average + * L1 norm of the \f$y\f$ coordinates is also 1. + * + * @param _m1 source points containing (X,Y), depth is CV_32F with 1 column 2 channels or + * 2 columns 1 channel + * @param _m2 destination points containing (x,y), depth is CV_32F with 1 column 2 channels or + * 2 columns 1 channel + * @param _model, CV_64FC1, 3x3, normalized, i.e., the last element is 1 + */ int runKernel( InputArray _m1, InputArray _m2, OutputArray _model ) const { Mat m1 = _m1.getMat(), m2 = _m2.getMat(); @@ -154,6 +180,14 @@ public: return 1; } + /** + * Compute the reprojection error. + * m2 = H*m1 + * @param _m1 depth CV_32F, 1-channel with 2 columns or 2-channel with 1 column + * @param _m2 depth CV_32F, 1-channel with 2 columns or 2-channel with 1 column + * @param _model CV_64FC1, 3x3 + * @param _err, output, CV_32FC1, square of the L2 norm + */ void computeError( InputArray _m1, InputArray _m2, InputArray _model, OutputArray _err ) const { Mat m1 = _m1.getMat(), m2 = _m2.getMat(), model = _model.getMat(); @@ -233,10 +267,7 @@ public: Mat src, dst; }; - -} - - +} // end namesapce cv namespace cv{ static bool createAndRunRHORegistrator(double confidence, @@ -277,7 +308,7 @@ static bool createAndRunRHORegistrator(double confidence, rhoEnsureCapacity(p, npoints, beta); /** - * The critical call. All parameters are heavily documented in rhorefc.h. + * The critical call. All parameters are heavily documented in rho.h. * * Currently, NR (Non-Randomness criterion) and Final Refinement (with * internal, optimized Levenberg-Marquardt method) are enabled. However, @@ -305,7 +336,7 @@ static bool createAndRunRHORegistrator(double confidence, /* Convert float homography to double precision. */ tmpH.convertTo(_H, CV_64FC1); - /* Maps non-zero mask elems to 1, for the sake of the testcase. */ + /* Maps non-zero mask elements to 1, for the sake of the test case. */ for(int k=0;k lambda*f1 + mu*f2 is an arbitrary f. matrix. + // f1, f2 is a basis => lambda*f1 + mu*f2 is an arbitrary fundamental matrix, // as it is determined up to a scale, normalize lambda & mu (lambda + mu = 1), // so f ~ lambda*f1 + (1 - lambda)*f2. // use the additional constraint det(f) = det(lambda*f1 + (1-lambda)*f2) to find lambda. @@ -529,7 +582,25 @@ static int run7Point( const Mat& _m1, const Mat& _m2, Mat& _fmatrix ) return n; } - +/** + * Compute the fundamental matrix using the 8-point algorithm. + * + * \f[ + * (\mathrm{m2}_i,1)^T \mathrm{fmatrix} (\mathrm{m1}_i,1) = 0 + * \f] + * + * @param _m1 Contain points in the reference view. Depth CV_32F with 2-channel + * 1 column or 1-channel 2 columns. It has 8 rows. + * @param _m2 Contain points in the other view. Depth CV_32F with 2-channel + * 1 column or 1-channel 2 columns. It has 8 rows. + * @param _fmatrix Output fundamental matrix (or matrices) of type CV_64FC1. + * The user is responsible for allocating the memory before calling + * this function. + * @return 1 on success, 0 on failure. + * + * Note that the computed fundamental matrix is normalized, i.e., + * the last element \f$F_{33}\f$ is 1. + */ static int run8Point( const Mat& _m1, const Mat& _m2, Mat& _fmatrix ) { Point2d m1c(0,0), m2c(0,0); @@ -690,7 +761,7 @@ public: } cv::Mat cv::findFundamentalMat( InputArray _points1, InputArray _points2, - int method, double param1, double param2, + int method, double ransacReprojThreshold, double confidence, OutputArray _mask ) { CV_INSTRUMENT_REGION() @@ -737,15 +808,15 @@ cv::Mat cv::findFundamentalMat( InputArray _points1, InputArray _points2, } else { - if( param1 <= 0 ) - param1 = 3; - if( param2 < DBL_EPSILON || param2 > 1 - DBL_EPSILON ) - param2 = 0.99; + if( ransacReprojThreshold <= 0 ) + ransacReprojThreshold = 3; + if( confidence < DBL_EPSILON || confidence > 1 - DBL_EPSILON ) + confidence = 0.99; if( (method & ~3) == FM_RANSAC && npoints >= 15 ) - result = createRANSACPointSetRegistrator(cb, 7, param1, param2)->run(m1, m2, F, _mask); + result = createRANSACPointSetRegistrator(cb, 7, ransacReprojThreshold, confidence)->run(m1, m2, F, _mask); else - result = createLMeDSPointSetRegistrator(cb, 7, param2)->run(m1, m2, F, _mask); + result = createLMeDSPointSetRegistrator(cb, 7, confidence)->run(m1, m2, F, _mask); } if( result <= 0 ) @@ -755,9 +826,10 @@ cv::Mat cv::findFundamentalMat( InputArray _points1, InputArray _points2, } cv::Mat cv::findFundamentalMat( InputArray _points1, InputArray _points2, - OutputArray _mask, int method, double param1, double param2 ) + OutputArray _mask, int method, + double ransacReprojThreshold , double confidence) { - return cv::findFundamentalMat(_points1, _points2, method, param1, param2, _mask); + return cv::findFundamentalMat(_points1, _points2, method, ransacReprojThreshold, confidence, _mask); } diff --git a/modules/calib3d/src/rho.h b/modules/calib3d/src/rho.h index 082a41603b..e45082d77c 100644 --- a/modules/calib3d/src/rho.h +++ b/modules/calib3d/src/rho.h @@ -95,7 +95,7 @@ typedef struct RHO_HEST RHO_HEST; * Initialize the estimator context, by allocating the aligned buffers * internally needed. * - * @return A pointer to the context if successful; NULL if an error occured. + * @return A pointer to the context if successful; NULL if an error occurred. */ Ptr rhoInit(void); diff --git a/modules/core/include/opencv2/core.hpp b/modules/core/include/opencv2/core.hpp index 5128e55d1a..2f8039dc47 100644 --- a/modules/core/include/opencv2/core.hpp +++ b/modules/core/include/opencv2/core.hpp @@ -1894,6 +1894,7 @@ The function solveCubic finds the real roots of a cubic equation: The roots are stored in the roots array. @param coeffs equation coefficients, an array of 3 or 4 elements. @param roots output array of real roots that has 1 or 3 elements. +@return number of real roots. It can be 0, 1 or 2. */ CV_EXPORTS_W int solveCubic(InputArray coeffs, OutputArray roots);