mirror of
https://github.com/opencv/opencv.git
synced 2026-07-31 08:13:04 +04:00
Merge branch 4.x
This commit is contained in:
@@ -708,9 +708,15 @@ __CV_ENUM_FLAGS_BITWISE_XOR_EQ (EnumType, EnumType)
|
||||
#endif
|
||||
|
||||
#if defined(__clang__) || defined(__GNUC__)
|
||||
#define CV_DISABLE_UBSAN __attribute__((no_sanitize("undefined")))
|
||||
#else
|
||||
#define CV_DISABLE_UBSAN
|
||||
# if defined(__has_attribute)
|
||||
# if __has_attribute(no_sanitize)
|
||||
# define CV_DISABLE_UBSAN __attribute__((no_sanitize("undefined")))
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef CV_DISABLE_UBSAN
|
||||
# define CV_DISABLE_UBSAN
|
||||
#endif
|
||||
|
||||
/****************************************************************************************\
|
||||
|
||||
@@ -2620,23 +2620,25 @@ inline v_float32 v_matmul(const v_float32& v, const v_float32& mat0,
|
||||
const v_float32& mat1, const v_float32& mat2,
|
||||
const v_float32& mat3)
|
||||
{
|
||||
vfloat32m2_t res;
|
||||
res = __riscv_vfmul_vf_f32m2(mat0, v_extract_n(v, 0), VTraits<v_float32>::vlanes());
|
||||
res = __riscv_vfmacc_vf_f32m2(res, v_extract_n(v, 1), mat1, VTraits<v_float32>::vlanes());
|
||||
res = __riscv_vfmacc_vf_f32m2(res, v_extract_n(v, 2), mat2, VTraits<v_float32>::vlanes());
|
||||
res = __riscv_vfmacc_vf_f32m2(res, v_extract_n(v, 3), mat3, VTraits<v_float32>::vlanes());
|
||||
return res;
|
||||
const int vl = VTraits<v_float32>::vlanes();
|
||||
vuint32m2_t idx = __riscv_vand(__riscv_vid_v_u32m2(vl), 0xfffffffc, vl);
|
||||
v_float32 v0 = __riscv_vrgather(v, idx, vl);
|
||||
v_float32 v1 = __riscv_vrgather(v, __riscv_vadd(idx, 1, vl), vl);
|
||||
v_float32 v2 = __riscv_vrgather(v, __riscv_vadd(idx, 2, vl), vl);
|
||||
v_float32 v3 = __riscv_vrgather(v, __riscv_vadd(idx, 3, vl), vl);
|
||||
return v_fma(v0, mat0, v_fma(v1, mat1, v_fma(v2, mat2, v_mul(v3, mat3))));
|
||||
}
|
||||
|
||||
// TODO: only 128 bit now.
|
||||
inline v_float32 v_matmuladd(const v_float32& v, const v_float32& mat0,
|
||||
const v_float32& mat1, const v_float32& mat2,
|
||||
const v_float32& a)
|
||||
{
|
||||
vfloat32m2_t res = __riscv_vfmul_vf_f32m2(mat0, v_extract_n(v,0), VTraits<v_float32>::vlanes());
|
||||
res = __riscv_vfmacc_vf_f32m2(res, v_extract_n(v,1), mat1, VTraits<v_float32>::vlanes());
|
||||
res = __riscv_vfmacc_vf_f32m2(res, v_extract_n(v,2), mat2, VTraits<v_float32>::vlanes());
|
||||
return __riscv_vfadd(res, a, VTraits<v_float32>::vlanes());
|
||||
const int vl = VTraits<v_float32>::vlanes();
|
||||
vuint32m2_t idx = __riscv_vand(__riscv_vid_v_u32m2(vl), 0xfffffffc, vl);
|
||||
v_float32 v0 = __riscv_vrgather(v, idx, vl);
|
||||
v_float32 v1 = __riscv_vrgather(v, __riscv_vadd(idx, 1, vl), vl);
|
||||
v_float32 v2 = __riscv_vrgather(v, __riscv_vadd(idx, 2, vl), vl);
|
||||
return v_fma(v0, mat0, v_fma(v1, mat1, v_fma(v2, mat2, a)));
|
||||
}
|
||||
|
||||
inline void v_cleanup() {}
|
||||
|
||||
@@ -1820,12 +1820,18 @@ public class CoreTest extends OpenCVTestCase {
|
||||
|
||||
assertGE(1e-6, Math.abs(Core.solvePoly(coeffs, roots)));
|
||||
|
||||
truth = new Mat(3, 1, CvType.CV_32FC2) {
|
||||
List<Mat> rootsReIm = new ArrayList<Mat>();
|
||||
Core.split(roots, rootsReIm);
|
||||
Core.sort(rootsReIm.get(0), dst, Core.SORT_EVERY_COLUMN);
|
||||
|
||||
Mat truthRe = new Mat(3, 1, CvType.CV_32F) {
|
||||
{
|
||||
put(0, 0, 1, 0, 2, 0, 3, 0);
|
||||
put(0, 0, 1, 2, 3);
|
||||
}
|
||||
};
|
||||
assertMatEqual(truth, roots, EPS);
|
||||
Mat truthIm = Mat.zeros(3, 1, CvType.CV_32F);
|
||||
assertMatEqual(truthRe, dst, EPS);
|
||||
assertMatEqual(truthIm, rootsReIm.get(1), EPS);
|
||||
}
|
||||
|
||||
public void testSolvePolyMatMatInt() {
|
||||
@@ -1836,14 +1842,20 @@ public class CoreTest extends OpenCVTestCase {
|
||||
};
|
||||
Mat roots = new Mat();
|
||||
|
||||
assertEquals(10.198039027185569, Core.solvePoly(coeffs, roots, 1));
|
||||
assertGE(1e-6, Core.solvePoly(coeffs, roots, 10));
|
||||
|
||||
truth = new Mat(3, 1, CvType.CV_32FC2) {
|
||||
List<Mat> rootsReIm = new ArrayList<Mat>();
|
||||
Core.split(roots, rootsReIm);
|
||||
Core.sort(rootsReIm.get(0), dst, Core.SORT_EVERY_COLUMN);
|
||||
|
||||
Mat truthRe = new Mat(3, 1, CvType.CV_32F) {
|
||||
{
|
||||
put(0, 0, 1, 0, -1, 2, -2, 12);
|
||||
put(0, 0, 1, 2, 3);
|
||||
}
|
||||
};
|
||||
assertMatEqual(truth, roots, EPS);
|
||||
Mat truthIm = Mat.zeros(3, 1, CvType.CV_32F);
|
||||
assertMatEqual(truthRe, dst, EPS);
|
||||
assertMatEqual(truthIm, rootsReIm.get(1), EPS);
|
||||
}
|
||||
|
||||
public void testSort() {
|
||||
|
||||
@@ -1585,7 +1585,40 @@ double cv::solvePoly( InputArray _coeffs0, OutputArray _roots0, int maxIters )
|
||||
break;
|
||||
}
|
||||
|
||||
C p(1, 0), r(1, 1);
|
||||
// Related issue: https://github.com/opencv/opencv/issues/23644,
|
||||
// This the initialization scheme of "Initial approximations in Durand-Kerner's root finding method" by Guggenheimer.
|
||||
// https://link.springer.com/article/10.1007/BF01935059
|
||||
// We put the initial points equidistantly on a circle on the complex plane. This code computes the circle radius as in the paper.
|
||||
Mat absCoeffs(n + 1, 1, CV_64F);
|
||||
for( i = 0; i <= n; i++ )
|
||||
absCoeffs.at<double>(i) = abs(coeffs[i]);
|
||||
|
||||
int nonZeroCoeffs = 0;
|
||||
Mat u(n, 1, CV_64F, Scalar(0)), v(n, 1, CV_64F, Scalar(0));
|
||||
for( i = 0; i <= n; i++ )
|
||||
{
|
||||
double coeff = absCoeffs.at<double>(i);
|
||||
if( coeff > DBL_EPSILON )
|
||||
{
|
||||
if( i != n )
|
||||
u.at<double>(i) = 2.0 * pow(coeff / absCoeffs.at<double>(n), 1.0 / (n - i));
|
||||
if( i != 0 )
|
||||
v.at<double>(i - 1) = 0.5 * pow(absCoeffs.at<double>(0) / coeff, 1.0 / i);
|
||||
nonZeroCoeffs++;
|
||||
}
|
||||
}
|
||||
double scale = 1;
|
||||
if( nonZeroCoeffs > 2 )
|
||||
{
|
||||
Point maxU, minV;
|
||||
minMaxLoc(u, nullptr, nullptr, nullptr, &maxU);
|
||||
minMaxLoc(v, nullptr, nullptr, &minV);
|
||||
u.at<double>(maxU) = 0;
|
||||
v.at<double>(minV) = 0;
|
||||
scale = (sum(u).val[0] + sum(v).val[0]) / (2 * nonZeroCoeffs - 2);
|
||||
}
|
||||
|
||||
C p(scale, 0), r(cos(CV_2PI / n), sin(CV_2PI / n));
|
||||
|
||||
for( i = 0; i < n; i++ )
|
||||
{
|
||||
|
||||
@@ -1596,8 +1596,7 @@ static void
|
||||
transform_32f( const float* src, float* dst, const float* m, int len, int scn, int dcn )
|
||||
{
|
||||
// Disabled for RISC-V Vector (scalable), because of:
|
||||
// 1. v_matmuladd for RVV is 128-bit only but not scalable, this will fail the test `Core_Transform.accuracy`.
|
||||
// 2. Both gcc and clang can autovectorize this, with better performance than using Universal intrinsic.
|
||||
// 1. Both gcc and clang can autovectorize this, with better performance than using Universal intrinsic.
|
||||
#if (CV_SIMD || CV_SIMD_SCALABLE) && !defined(__aarch64__) && !defined(_M_ARM64) && !defined(_M_ARM64EC) && !(CV_TRY_RVV && CV_RVV)
|
||||
int x = 0;
|
||||
if( scn == 3 && dcn == 3 )
|
||||
|
||||
@@ -1283,7 +1283,7 @@ struct MaskedNormInf_SIMD<float, float> {
|
||||
v_float32 acc = vx_setzero_f32();
|
||||
|
||||
for (; i <= len - vstep; i += vstep) {
|
||||
v_uint32 m = v_reinterpret_as_u32(vx_load_expand(mask + i));
|
||||
v_uint32 m = vx_load_expand_q(mask + i);
|
||||
v_uint32 cmp = v_gt(m, vx_setzero_u32());
|
||||
v_float32 s = vx_load(src + i);
|
||||
s = v_abs(s);
|
||||
|
||||
@@ -1570,9 +1570,8 @@ template<typename R> struct TheTest
|
||||
R v = dataV, a = dataA, b = dataB, c = dataC, d = dataD;
|
||||
|
||||
Data<R> res = v_matmul(v, a, b, c, d);
|
||||
// for (int i = 0; i < VTraits<R>::vlanes(); i += 4)
|
||||
// {
|
||||
int i = 0;
|
||||
for (int i = 0; i < VTraits<R>::vlanes(); i += 4)
|
||||
{
|
||||
for (int j = i; j < i + 4; ++j)
|
||||
{
|
||||
SCOPED_TRACE(cv::format("i=%d j=%d", i, j));
|
||||
@@ -1582,12 +1581,11 @@ template<typename R> struct TheTest
|
||||
+ dataV[i + 3] * dataD[j];
|
||||
EXPECT_COMPARE_EQ(val, res[j]);
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
Data<R> resAdd = v_matmuladd(v, a, b, c, d);
|
||||
// for (int i = 0; i < VTraits<R>::vlanes(); i += 4)
|
||||
// {
|
||||
i = 0;
|
||||
for (int i = 0; i < VTraits<R>::vlanes(); i += 4)
|
||||
{
|
||||
for (int j = i; j < i + 4; ++j)
|
||||
{
|
||||
SCOPED_TRACE(cv::format("i=%d j=%d", i, j));
|
||||
@@ -1597,7 +1595,7 @@ template<typename R> struct TheTest
|
||||
+ dataD[j];
|
||||
EXPECT_COMPARE_EQ(val, resAdd[j]);
|
||||
}
|
||||
// }
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@@ -1978,6 +1978,93 @@ TEST(Core_SolvePoly, regression_5599)
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Core_SolvePoly, regression_23644)
|
||||
{
|
||||
// x^2 - 2x - 3 = 0, roots: 3, -1
|
||||
cv::Mat coefs = (cv::Mat_<float>(1,3) << -3, -2, 1 );
|
||||
cv::Mat r;
|
||||
double prec;
|
||||
prec = cv::solvePoly(coefs, r);
|
||||
EXPECT_LE(prec, 1e-6);
|
||||
EXPECT_EQ(2u, r.total());
|
||||
ASSERT_EQ(CV_32FC2, r.type());
|
||||
checkRoot<float>(r, 3, 0);
|
||||
checkRoot<float>(r, -1, 0);
|
||||
}
|
||||
|
||||
TEST(Core_SolvePoly, degree_2_polynomials)
|
||||
{
|
||||
cv::Mat_<float> coefs(1,3);
|
||||
cv::Mat r;
|
||||
double prec;
|
||||
for (float c0 = -20; c0 <= 20; c0++)
|
||||
{
|
||||
coefs.at<float>(0) = c0;
|
||||
for (float c1 = -20; c1 <= 20; c1++)
|
||||
{
|
||||
coefs.at<float>(1) = c1;
|
||||
for (float c2 = -20; c2 <= 20; c2++)
|
||||
{
|
||||
coefs.at<float>(2) = c2;
|
||||
prec = cv::solvePoly(coefs, r);
|
||||
EXPECT_LE(prec, 1e-6);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Core_SolvePoly, degree_4_polynomials)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_VERYLONG);
|
||||
|
||||
cv::Mat_<float> coefs(1,5);
|
||||
cv::Mat r;
|
||||
double prec;
|
||||
for (float c0 = -10; c0 <= 10; c0++)
|
||||
{
|
||||
coefs.at<float>(0) = c0;
|
||||
for (float c1 = -10; c1 <= 10; c1++)
|
||||
{
|
||||
coefs.at<float>(1) = c1;
|
||||
for (float c2 = -10; c2 <= 10; c2++)
|
||||
{
|
||||
coefs.at<float>(2) = c2;
|
||||
for (float c3 = -10; c3 <= 10; c3++)
|
||||
{
|
||||
coefs.at<float>(3) = c3;
|
||||
for (float c4 = -10; c4 <= 10; c4++)
|
||||
{
|
||||
coefs.at<float>(4) = c4;
|
||||
prec = cv::solvePoly(coefs, r);
|
||||
EXPECT_LE(prec, 1e-3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Core_SolvePoly, different_magnitudes_polynomials)
|
||||
{
|
||||
cv::Mat_<float> coefs(1,3);
|
||||
cv::Mat r;
|
||||
double prec;
|
||||
for (float i = -10; i < 10; i++)
|
||||
{
|
||||
coefs.at<float>(0) = pow(2.f, i);
|
||||
for (float j = -10; j < 10; j++)
|
||||
{
|
||||
coefs.at<float>(1) = pow(2.f, j);
|
||||
for (float k = -10; k < 10; k++)
|
||||
{
|
||||
coefs.at<float>(2) = pow(2.f, k);
|
||||
prec = cv::solvePoly(coefs, r);
|
||||
EXPECT_LE(prec, 1e-6);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Core_PhaseTest : public cvtest::BaseTest
|
||||
{
|
||||
int t;
|
||||
|
||||
Reference in New Issue
Block a user