mirror of
https://github.com/zebrajr/opencv.git
synced 2025-12-06 12:19:50 +01:00
Merge pull request #26810 from MaximSmolskiy:improve-robustness-for-fitEllipseAMS
Improve robustness for fitEllipseAMS #26810 ### Pull Request Readiness Checklist Related to #26694 Added functionality to add noise to points in degenerate cases and try again for `fitEllipseAMS`. `fitEllipseNoDirect` and `fitEllipseDirect` already have this 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:
parent
ea023b72ce
commit
8ab0ad6e1b
|
|
@ -516,6 +516,7 @@ cv::RotatedRect cv::fitEllipseAMS( InputArray _points )
|
||||||
Mat points = _points.getMat();
|
Mat points = _points.getMat();
|
||||||
int i, n = points.checkVector(2);
|
int i, n = points.checkVector(2);
|
||||||
int depth = points.depth();
|
int depth = points.depth();
|
||||||
|
float eps = 0;
|
||||||
CV_Assert( n >= 0 && (depth == CV_32F || depth == CV_32S));
|
CV_Assert( n >= 0 && (depth == CV_32F || depth == CV_32S));
|
||||||
|
|
||||||
RotatedRect box;
|
RotatedRect box;
|
||||||
|
|
@ -553,10 +554,16 @@ cv::RotatedRect cv::fitEllipseAMS( InputArray _points )
|
||||||
}
|
}
|
||||||
double scale = 100./(s > FLT_EPSILON ? s : (double)FLT_EPSILON);
|
double scale = 100./(s > FLT_EPSILON ? s : (double)FLT_EPSILON);
|
||||||
|
|
||||||
|
// first, try the original pointset.
|
||||||
|
// if it's singular, try to shift the points a bit
|
||||||
|
int iter = 0;
|
||||||
|
for( iter = 0; iter < 2; iter++ )
|
||||||
|
{
|
||||||
for( i = 0; i < n; i++ )
|
for( i = 0; i < n; i++ )
|
||||||
{
|
{
|
||||||
Point2f p = is_float ? ptsf[i] : Point2f((float)ptsi[i].x, (float)ptsi[i].y);
|
Point2f p = is_float ? ptsf[i] : Point2f((float)ptsi[i].x, (float)ptsi[i].y);
|
||||||
double px = (p.x - c.x)*scale, py = (p.y - c.y)*scale;
|
const Point2f delta = getOfs(eps);
|
||||||
|
const double px = (p.x + delta.x - c.x)*scale, py = (p.y + delta.y - c.y)*scale;
|
||||||
|
|
||||||
A.at<double>(i,0) = px*px;
|
A.at<double>(i,0) = px*px;
|
||||||
A.at<double>(i,1) = px*py;
|
A.at<double>(i,1) = px*py;
|
||||||
|
|
@ -604,6 +611,13 @@ cv::RotatedRect cv::fitEllipseAMS( InputArray _points )
|
||||||
M(4,4)=DM(4,4);
|
M(4,4)=DM(4,4);
|
||||||
|
|
||||||
if (fabs(cv::determinant(M)) > 1.0e-10) {
|
if (fabs(cv::determinant(M)) > 1.0e-10) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
eps = (float)(s/(n*2)*1e-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iter < 2) {
|
||||||
Mat eVal, eVec;
|
Mat eVal, eVec;
|
||||||
eigenNonSymmetric(M, eVal, eVec);
|
eigenNonSymmetric(M, eVal, eVec);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -341,10 +341,10 @@ TEST(Imgproc_FitEllipseAMS_HorizontalLine, accuracy) {
|
||||||
vector<Point2f> pts({{-300, 100}, {-200, 100}, {-100, 100}, {0, 100}, {100, 100}, {200, 100}, {300, 100}});
|
vector<Point2f> pts({{-300, 100}, {-200, 100}, {-100, 100}, {0, 100}, {100, 100}, {200, 100}, {300, 100}});
|
||||||
const RotatedRect el = fitEllipseAMS(pts);
|
const RotatedRect el = fitEllipseAMS(pts);
|
||||||
|
|
||||||
EXPECT_NEAR(el.center.x, -100, 100);
|
EXPECT_NEAR(el.center.x, 0, 200);
|
||||||
EXPECT_NEAR(el.center.y, 100, 1);
|
EXPECT_NEAR(el.center.y, 100, 1);
|
||||||
EXPECT_NEAR(el.size.width, 1, 1);
|
EXPECT_NEAR(el.size.width, 1, 1);
|
||||||
EXPECT_GE(el.size.height, 150);
|
EXPECT_NEAR(el.size.height, 600, 100);
|
||||||
EXPECT_NEAR(el.angle, 90, 0.1);
|
EXPECT_NEAR(el.angle, 90, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user