mirror of
https://github.com/opencv/opencv.git
synced 2026-07-21 19:33:03 +04:00
Merge pull request #27950 from ismailabouzeidx:feat/estimate-translation2d
[calib3d] Add estimateTranslation2D() #27950 Merge with opencv_extra PR: opencv/opencv_extra#1286 ### **Description** This PR adds a new API, `cv::estimateTranslation2D()`, to the **calib3d** module. It computes a **pure 2D translation** between two sets of corresponding points using robust methods (`RANSAC` and `LMedS`). The function mirrors the interface and behavior of `estimateAffine2D()` and `estimateAffinePartial2D()`, but constrains the transformation to translation only. This model is particularly useful for cases where the motion between images is purely translational, such as: - Aerial stitching and planar mosaics. - Image alignment in fixed-camera systems. - Lightweight pipelines where affine or homography models are unnecessarily complex. The implementation introduces a new internal class `Translation2DEstimatorCallback` and integrates seamlessly into OpenCV’s existing robust estimation framework (`PointSetRegistrator`). --- ### **Key Features** - Implements `cv::estimateTranslation2D()` in the `calib3d` module. - Supports robust methods **RANSAC** and **LMedS**. - Adds accuracy and performance tests. - Provides full **C++ and Python bindings**. - Includes **Doxygen documentation** consistent with OpenCV’s standards. - Verified correctness across noise, outlier, and datatype variations. --- ### **Testing & Verification** **Unit Tests** (`modules/calib3d/`) - **Minimal sample:** `test1Point` validates that a single correspondence recovers the correct translation under both **RANSAC** and **LMedS** across 500 randomized trials. - **Robustness to noise and outliers:** `testNPoints` generates 100 correspondences, injects noise and outliers (≤40% for RANSAC, ≤50% for LMedS), and verifies that: - Estimated **T** closely matches ground truth (`cvtest::norm(..., NORM_L2)`). - Inlier mask consistency and correctness are maintained. - **Datatype conversion:** `testConversion` checks mixed input datatypes (integer → float) to ensure correct conversion and consistent results. - **Input immutability:** `dont_change_inputs` confirms that input arrays remain unchanged after function execution, mirroring affine behavior. **Performance Tests** (`modules/calib3d/`) - `EstimateTranslation2DPerf` benchmarks **RANSAC** and **LMedS** using: - Point counts: 1000 - Confidence levels: 0.95 - Refinement iterations: 10, 0 These tests confirm **numerical stability**, **performance scaling**, and **consistency** across datatypes and noise levels. --- ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch (`4.x`) - [x] There is a clear description, motivation, and validation summary in this PR - [x] There are accuracy and performance tests in the calib3d module - [x] The feature is well documented and sample code can be built with CMake - [x] The feature has Python bindings and verified documentation output - [x] There is test data or sample code in the opencv_extra repository (if applicable) - [ ] There is a reference to the original bug report or related issue (if applicable)
This commit is contained in:
@@ -3362,6 +3362,78 @@ CV_EXPORTS_W cv::Mat estimateAffinePartial2D(InputArray from, InputArray to, Out
|
||||
size_t maxIters = 2000, double confidence = 0.99,
|
||||
size_t refineIters = 10);
|
||||
|
||||
/** @brief Computes a pure 2D translation between two 2D point sets.
|
||||
|
||||
It computes
|
||||
\f[
|
||||
\begin{bmatrix}
|
||||
x\\
|
||||
y
|
||||
\end{bmatrix}
|
||||
=
|
||||
\begin{bmatrix}
|
||||
1 & 0\\
|
||||
0 & 1
|
||||
\end{bmatrix}
|
||||
\begin{bmatrix}
|
||||
X\\
|
||||
Y
|
||||
\end{bmatrix}
|
||||
+
|
||||
\begin{bmatrix}
|
||||
t_x\\
|
||||
t_y
|
||||
\end{bmatrix}.
|
||||
\f]
|
||||
|
||||
@param from First input 2D point set containing \f$(X,Y)\f$.
|
||||
@param to Second input 2D point set containing \f$(x,y)\f$.
|
||||
@param inliers Output vector indicating which points are inliers (1-inlier, 0-outlier).
|
||||
@param method Robust method used to compute the transformation. The following methods are possible:
|
||||
- @ref RANSAC - RANSAC-based robust method
|
||||
- @ref LMEDS - Least-Median robust method
|
||||
RANSAC is the default method.
|
||||
@param ransacReprojThreshold Maximum reprojection error in the RANSAC algorithm to consider
|
||||
a point as an inlier. Applies only to RANSAC.
|
||||
@param maxIters The maximum number of robust method iterations.
|
||||
@param confidence Confidence level, between 0 and 1, for the estimated transformation. Anything
|
||||
between 0.95 and 0.99 is usually good enough. Values too close to 1 can slow down the estimation
|
||||
significantly. Values lower than 0.8–0.9 can result in an incorrectly estimated transformation.
|
||||
@param refineIters Maximum number of iterations of the refining algorithm. For pure translation
|
||||
the least-squares solution on inliers is closed-form, so passing 0 is recommended (no additional refine).
|
||||
|
||||
@return A 2D translation vector \f$[t_x, t_y]^T\f$ as `cv::Vec2d`. If the translation could not be
|
||||
estimated, both components are set to NaN and, if @p inliers is provided, the mask is filled with zeros.
|
||||
|
||||
\par Converting to a 2x3 transformation matrix:
|
||||
\f[
|
||||
\begin{bmatrix}
|
||||
1 & 0 & t_x\\
|
||||
0 & 1 & t_y
|
||||
\end{bmatrix}
|
||||
\f]
|
||||
|
||||
@code{.cpp}
|
||||
cv::Vec2d t = cv::estimateTranslation2D(from, to, inliers);
|
||||
cv::Mat T = (cv::Mat_<double>(2,3) << 1,0,t[0], 0,1,t[1]);
|
||||
@endcode
|
||||
|
||||
The function estimates a pure 2D translation between two 2D point sets using the selected robust
|
||||
algorithm. Inliers are determined by the reprojection error threshold.
|
||||
|
||||
@note
|
||||
The RANSAC method can handle practically any ratio of outliers but needs a threshold to
|
||||
distinguish inliers from outliers. The method LMeDS does not need any threshold but works
|
||||
correctly only when there are more than 50% inliers.
|
||||
|
||||
@sa estimateAffine2D, estimateAffinePartial2D, getAffineTransform
|
||||
*/
|
||||
CV_EXPORTS_W cv::Vec2d estimateTranslation2D(InputArray from, InputArray to, OutputArray inliers = noArray(),
|
||||
int method = RANSAC,
|
||||
double ransacReprojThreshold = 3,
|
||||
size_t maxIters = 2000, double confidence = 0.99,
|
||||
size_t refineIters = 0);
|
||||
|
||||
/** @example samples/cpp/tutorial_code/features2D/Homography/decompose_homography.cpp
|
||||
An example program with homography decomposition.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user