mirror of
https://github.com/opencv/opencv.git
synced 2026-07-30 07:43:03 +04:00
Merge pull request #29077 from vrabaud:throw
Homogeneize some calib/3d behavior #29077 - use CV_Check to validate input sizes (thus throwing for invalid inputs) - return bool to validate a function result This fixes #22746 ### 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 - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
@@ -1885,12 +1885,14 @@ an inlier.
|
||||
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.
|
||||
|
||||
@return Whether a solution was found.
|
||||
|
||||
The function estimates an optimal 3D affine transformation between two 3D point sets using the
|
||||
RANSAC algorithm.
|
||||
*/
|
||||
CV_EXPORTS_W int estimateAffine3D(InputArray src, InputArray dst,
|
||||
OutputArray out, OutputArray inliers,
|
||||
double ransacThreshold = 3, double confidence = 0.99);
|
||||
CV_EXPORTS_W bool estimateAffine3D(InputArray src, InputArray dst,
|
||||
OutputArray out, OutputArray inliers,
|
||||
double ransacThreshold = 3, double confidence = 0.99);
|
||||
|
||||
/** @brief Computes an optimal affine transformation between two 3D point sets.
|
||||
|
||||
@@ -1959,12 +1961,14 @@ CV_EXPORTS_W cv::Mat estimateAffine3D(InputArray src, InputArray dst,
|
||||
* 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.
|
||||
*
|
||||
* @return Whether a translation was found.
|
||||
*
|
||||
* The function estimates an optimal 3D translation between two 3D point sets using the
|
||||
* RANSAC algorithm.
|
||||
* */
|
||||
CV_EXPORTS_W int estimateTranslation3D(InputArray src, InputArray dst,
|
||||
OutputArray out, OutputArray inliers,
|
||||
double ransacThreshold = 3, double confidence = 0.99);
|
||||
CV_EXPORTS_W bool estimateTranslation3D(InputArray src, InputArray dst,
|
||||
OutputArray out, OutputArray inliers,
|
||||
double ransacThreshold = 3, double confidence = 0.99);
|
||||
|
||||
/** @brief Computes an optimal affine transformation between two 2D point sets.
|
||||
|
||||
|
||||
@@ -320,13 +320,10 @@ Mat findHomography( InputArray _points1, InputArray _points2,
|
||||
npoints = p.checkVector(3, -1, false);
|
||||
if( npoints < 0 )
|
||||
CV_Error(Error::StsBadArg, "The input arrays should be 2D or 3D point sets");
|
||||
if( npoints == 0 )
|
||||
return Mat();
|
||||
convertPointsFromHomogeneous(p, p);
|
||||
}
|
||||
// Need at least 4 point correspondences to calculate Homography
|
||||
if( npoints < 4 )
|
||||
CV_Error(Error::StsVecLengthErr , "The input arrays should have at least 4 corresponding point sets to calculate Homography");
|
||||
CV_CheckGE(npoints, 4, "The input arrays should have at least 4 corresponding point sets to calculate Homography");
|
||||
p.reshape(2, npoints).convertTo(m, CV_32F);
|
||||
}
|
||||
|
||||
|
||||
@@ -829,16 +829,18 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
int estimateAffine3D(InputArray _from, InputArray _to,
|
||||
OutputArray _out, OutputArray _inliers,
|
||||
double ransacThreshold, double confidence)
|
||||
bool estimateAffine3D(InputArray _from, InputArray _to,
|
||||
OutputArray _out, OutputArray _inliers,
|
||||
double ransacThreshold, double confidence)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
Mat from = _from.getMat(), to = _to.getMat();
|
||||
int count = from.checkVector(3);
|
||||
|
||||
CV_Assert( count >= 0 && to.checkVector(3) == count );
|
||||
CV_CheckGE( count, 0, "Points need to be 3d");
|
||||
CV_CheckGE( count, 3, "At least 3 points are needed for affine transformation estimation.");
|
||||
CV_CheckEQ(to.checkVector(3), count, "Point matches need to have the same size");
|
||||
|
||||
Mat dFrom, dTo;
|
||||
from.convertTo(dFrom, CV_32F);
|
||||
@@ -857,11 +859,13 @@ Mat estimateAffine3D(InputArray _from, InputArray _to,
|
||||
CV_OUT double* _scale, bool force_rotation)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
Mat from = _from.getMat(), to = _to.getMat();
|
||||
int count = from.checkVector(3);
|
||||
|
||||
CV_CheckGE(count, 3, "Umeyama algorithm needs at least 3 points for affine transformation estimation.");
|
||||
CV_CheckEQ(to.checkVector(3), count, "Point sets need to have the same size");
|
||||
CV_CheckGE(count, 3, "At least 3 points are needed for affine transformation estimation.");
|
||||
CV_CheckEQ(to.checkVector(3), count, "Point matches need to have the same size");
|
||||
|
||||
from = from.reshape(1, count);
|
||||
to = to.reshape(1, count);
|
||||
if(from.type() != CV_64F)
|
||||
@@ -933,16 +937,17 @@ Mat estimateAffine3D(InputArray _from, InputArray _to,
|
||||
return transform;
|
||||
}
|
||||
|
||||
int estimateTranslation3D(InputArray _from, InputArray _to,
|
||||
OutputArray _out, OutputArray _inliers,
|
||||
double ransacThreshold, double confidence)
|
||||
bool estimateTranslation3D(InputArray _from, InputArray _to,
|
||||
OutputArray _out, OutputArray _inliers,
|
||||
double ransacThreshold, double confidence)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
Mat from = _from.getMat(), to = _to.getMat();
|
||||
int count = from.checkVector(3);
|
||||
|
||||
CV_Assert( count >= 0 && to.checkVector(3) == count );
|
||||
CV_CheckGE(count, 0, "Points need to be 3d");
|
||||
CV_CheckEQ(to.checkVector(3), count, "Point matches need to have the same size");
|
||||
|
||||
Mat dFrom, dTo;
|
||||
from.convertTo(dFrom, CV_32F);
|
||||
@@ -972,7 +977,9 @@ Mat estimateAffine2D(InputArray _from, InputArray _to, OutputArray _inliers,
|
||||
bool result = false;
|
||||
Mat H;
|
||||
|
||||
CV_Assert( count >= 0 && to.checkVector(2) == count );
|
||||
CV_CheckGE(count, 0, "Points need to be 2d");
|
||||
CV_CheckGE(count, 2, "At least 2 points for partial affine transformation estimation.");
|
||||
CV_CheckEQ(to.checkVector(2), count, "Point matches need to have the same size");
|
||||
|
||||
if (from.type() != CV_32FC2 || to.type() != CV_32FC2)
|
||||
{
|
||||
@@ -1108,7 +1115,9 @@ Mat estimateAffinePartial2D(InputArray _from, InputArray _to, OutputArray _inlie
|
||||
bool result = false;
|
||||
Mat H;
|
||||
|
||||
CV_Assert( count >= 0 && to.checkVector(2) == count );
|
||||
CV_CheckGE(count, 0, "Points need to be 2d");
|
||||
CV_CheckGE(count, 2, "At least 2 points for partial affine transformation estimation.");
|
||||
CV_CheckEQ(to.checkVector(2), count, "Point matches need to have the same size");
|
||||
|
||||
if (from.type() != CV_32FC2 || to.type() != CV_32FC2)
|
||||
{
|
||||
@@ -1253,7 +1262,9 @@ Vec2d estimateTranslation2D(InputArray _from, InputArray _to,
|
||||
Mat from = _from.getMat(), to = _to.getMat();
|
||||
int count = from.checkVector(2);
|
||||
bool result = false;
|
||||
CV_Assert(count >= 0 && to.checkVector(2) == count);
|
||||
|
||||
CV_CheckGE(count, 0, "Points need to be 2d");
|
||||
CV_CheckEQ(to.checkVector(2), count, "Point matches need to have the same size");
|
||||
|
||||
if (from.type() != CV_32FC2 || to.type() != CV_32FC2) {
|
||||
Mat tmp1, tmp2;
|
||||
|
||||
@@ -50,6 +50,13 @@ static float rngIn(float from, float to) { return from + (to-from) * (float)theR
|
||||
|
||||
TEST_P(EstimateAffine2D, test3Points)
|
||||
{
|
||||
const int method = GetParam();
|
||||
for (size_t i = 0; i < 2; ++i)
|
||||
{
|
||||
std::vector<cv::Vec2f> fpts(i), tpts(i);
|
||||
vector<uchar> inliers;
|
||||
EXPECT_THROW(estimateAffine2D(fpts, tpts, inliers, method), cv::Exception);
|
||||
}
|
||||
// try more transformations
|
||||
for (size_t i = 0; i < 500; ++i)
|
||||
{
|
||||
@@ -67,7 +74,7 @@ TEST_P(EstimateAffine2D, test3Points)
|
||||
transform(fpts, tpts, aff);
|
||||
|
||||
vector<uchar> inliers;
|
||||
Mat aff_est = estimateAffine2D(fpts, tpts, inliers, GetParam() /* method */);
|
||||
Mat aff_est = estimateAffine2D(fpts, tpts, inliers, method);
|
||||
|
||||
EXPECT_NEAR(0., cvtest::norm(aff_est, aff, NORM_INF), 1e-3);
|
||||
|
||||
|
||||
@@ -62,6 +62,13 @@ static Mat rngPartialAffMat() {
|
||||
|
||||
TEST_P(EstimateAffinePartial2D, test2Points)
|
||||
{
|
||||
const int method = GetParam();
|
||||
for (size_t i = 0; i < 2; ++i)
|
||||
{
|
||||
std::vector<cv::Vec2f> fpts(i), tpts(i);
|
||||
vector<uchar> inliers;
|
||||
EXPECT_THROW(estimateAffinePartial2D(fpts, tpts, inliers, method), cv::Exception);
|
||||
}
|
||||
// try more transformations
|
||||
for (size_t i = 0; i < 500; ++i)
|
||||
{
|
||||
@@ -77,7 +84,7 @@ TEST_P(EstimateAffinePartial2D, test2Points)
|
||||
transform(fpts, tpts, aff);
|
||||
|
||||
vector<uchar> inliers;
|
||||
Mat aff_est = estimateAffinePartial2D(fpts, tpts, inliers, GetParam() /* method */);
|
||||
Mat aff_est = estimateAffinePartial2D(fpts, tpts, inliers, method);
|
||||
|
||||
EXPECT_NEAR(0., cvtest::norm(aff_est, aff, NORM_INF), 1e-3);
|
||||
|
||||
|
||||
@@ -354,14 +354,16 @@ No image processing is done to improve to find the checkerboard. This has the ef
|
||||
execution of the function but could lead to not recognizing the checkerboard if the image
|
||||
is not previously binarized in the appropriate manner.
|
||||
|
||||
@return True if all of the corners are found and placed in a certain order (row by row,
|
||||
left to right in every row). Otherwise, if the function fails to find all the corners or reorder them,
|
||||
it returns false.
|
||||
|
||||
The function attempts to determine whether the input image is a view of the chessboard pattern and
|
||||
locate the internal chessboard corners. The function returns a non-zero value if all of the corners
|
||||
are found and they are placed in a certain order (row by row, left to right in every row).
|
||||
Otherwise, if the function fails to find all the corners or reorder them, it returns 0. For example,
|
||||
a regular chessboard has 8 x 8 squares and 7 x 7 internal corners, that is, points where the black
|
||||
squares touch each other. The detected coordinates are approximate, and to determine their positions
|
||||
more accurately, the function calls #cornerSubPix. You also may use the function #cornerSubPix with
|
||||
different parameters if returned coordinates are not accurate enough.
|
||||
locate the internal chessboard corners. For example, a regular chessboard has 8 x 8 squares and
|
||||
7 x 7 internal corners, that is, points where the black squares touch each other. The detected
|
||||
coordinates are approximate, and to determine their positions more accurately, the function
|
||||
calls #cornerSubPix. You also may use the function #cornerSubPix with different parameters if
|
||||
returned coordinates are not accurate enough.
|
||||
|
||||
Sample usage of detecting and drawing chessboard corners: :
|
||||
@code
|
||||
@@ -392,9 +394,12 @@ to create the desired checkerboard pattern.
|
||||
CV_EXPORTS_W bool findChessboardCorners( InputArray image, Size patternSize, OutputArray corners,
|
||||
int flags = CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE );
|
||||
|
||||
/*
|
||||
Checks whether the image contains chessboard of the specific size or not.
|
||||
If yes, nonzero value is returned.
|
||||
/** @brief Checks whether the image contains chessboard of the specific size or not.
|
||||
|
||||
@param img Source chessboard view.
|
||||
@param size Size of the chessboard.
|
||||
|
||||
@return Whether a chessboard was found.
|
||||
*/
|
||||
CV_EXPORTS_W bool checkChessboard(InputArray img, Size size);
|
||||
|
||||
@@ -552,10 +557,12 @@ perspective distortions but much more sensitive to background clutter.
|
||||
If `blobDetector` is NULL then `image` represents Point2f array of candidates.
|
||||
@param parameters struct for finding circles in a grid pattern.
|
||||
|
||||
return True if all of the centers have been found and they have been placed in a certain order
|
||||
(row by row, left to right in every row). Otherwise, if the function fails to find all the corners
|
||||
or reorder them, it returns false.
|
||||
|
||||
The function attempts to determine whether the input image contains a grid of circles. If it is, the
|
||||
function locates centers of the circles. The function returns a non-zero value if all of the centers
|
||||
have been found and they have been placed in a certain order (row by row, left to right in every
|
||||
row). Otherwise, if the function fails to find all the corners or reorder them, it returns 0.
|
||||
function locates centers of the circles.
|
||||
|
||||
Sample usage of detecting and drawing the centers of circles: :
|
||||
@code
|
||||
|
||||
Reference in New Issue
Block a user