mirror of
https://github.com/opencv/opencv.git
synced 2026-11-09 18:04:29 -06:00
Merge pull request #30715 from sshivensolanki:core-carttopolar-inplace-5x
core: fix in-place cartToPolar when only the magnitude overwrites an input (5.x) - #30715 5.x port of #30646, as requested in its review. Fixes #30645 on 5.x. ### Problem `cv::cartToPolar` gives wrong results on `CV_32F` when only the magnitude output is the same `Mat` as `x` or `y`. The SIMD tail handling repeats the last full block, and `cartToPolar32f_` only skipped that for in-place calls when the angle was aliased. ### Fix Same as #30646: added `mag == X || mag == Y` to the check, so these calls handle the leftover elements with the scalar code. ### Tests Same `Core_CartToPolar_inplace_mag.accuracy` test as #30646 (`CV_32F`, lengths 1 to 39, magnitude overwriting `x`, then `y`). On Apple M1 Pro it fails without the fix on 5.x and passes with it. The full `opencv_test_core` passes. ### 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. - [ ] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
@@ -115,7 +115,7 @@ static void cartToPolar32f_(const float *X, const float *Y, float *mag, float *a
|
||||
// if it's inplace operation, we cannot repeatedly process
|
||||
// the tail for the second time, so we have to use the
|
||||
// scalar code
|
||||
if( i == 0 || angle == X || angle == Y )
|
||||
if( i == 0 || mag == X || mag == Y || angle == X || angle == Y )
|
||||
break;
|
||||
i = len - VECSZ*2;
|
||||
}
|
||||
|
||||
@@ -4022,6 +4022,35 @@ INSTANTIATE_TEST_CASE_P(Core_CartPolar, Core_CartToPolar_inplace,
|
||||
)
|
||||
);
|
||||
|
||||
typedef testing::TestWithParam<int> Core_CartToPolar_inplace_mag;
|
||||
|
||||
// only the magnitude overwrites an input, so the last elements must not be processed twice.
|
||||
// CV_64F is not tested: it works on separate float buffers, so it can't hit this.
|
||||
TEST_P(Core_CartToPolar_inplace_mag, accuracy)
|
||||
{
|
||||
const int len = GetParam();
|
||||
cv::Mat x(1, len, CV_32F), y(1, len, CV_32F);
|
||||
cv::randu(x, cv::Scalar::all(-1000), cv::Scalar::all(1000));
|
||||
cv::randu(y, cv::Scalar::all(-1000), cv::Scalar::all(1000));
|
||||
|
||||
cv::Mat expectedMag, expectedAngle;
|
||||
cv::cartToPolar(x, y, expectedMag, expectedAngle);
|
||||
|
||||
// magnitude into x
|
||||
cv::Mat x1 = x.clone(), angle1;
|
||||
cv::cartToPolar(x1, y, x1, angle1);
|
||||
EXPECT_MAT_NEAR(expectedMag, x1, 1e-2);
|
||||
EXPECT_MAT_NEAR(expectedAngle, angle1, 1e-2);
|
||||
|
||||
// magnitude into y
|
||||
cv::Mat y1 = y.clone(), angle2;
|
||||
cv::cartToPolar(x, y1, y1, angle2);
|
||||
EXPECT_MAT_NEAR(expectedMag, y1, 1e-2);
|
||||
EXPECT_MAT_NEAR(expectedAngle, angle2, 1e-2);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(Core_CartPolar, Core_CartToPolar_inplace_mag, testing::Range(1, 40));
|
||||
|
||||
PARAM_TEST_CASE(Core_PolarToCart_inplace, int, bool, bool)
|
||||
{
|
||||
int depth;
|
||||
|
||||
Reference in New Issue
Block a user