mirror of
https://github.com/opencv/opencv.git
synced 2026-07-30 07:43:03 +04:00
Merge remote-tracking branch 'upstream/3.4' into merge-3.4
This commit is contained in:
@@ -177,8 +177,6 @@ pattern (every view is described by several 3D-2D point correspondences).
|
||||
opencv_source_code/samples/cpp/calibration.cpp
|
||||
- A calibration sample in order to do 3D reconstruction can be found at
|
||||
opencv_source_code/samples/cpp/build3dmodel.cpp
|
||||
- A calibration sample of an artificially generated camera and chessboard patterns can be
|
||||
found at opencv_source_code/samples/cpp/calibration_artificial.cpp
|
||||
- A calibration example on stereo calibration can be found at
|
||||
opencv_source_code/samples/cpp/stereo_calib.cpp
|
||||
- A calibration example on stereo matching can be found at
|
||||
|
||||
@@ -3,7 +3,7 @@ set(the_description "The Core Functionality")
|
||||
ocv_add_dispatched_file(mathfuncs_core SSE2 AVX AVX2)
|
||||
ocv_add_dispatched_file(stat SSE4_2 AVX2)
|
||||
ocv_add_dispatched_file(arithm SSE2 SSE4_1 AVX2 VSX3)
|
||||
ocv_add_dispatched_file(convert SSE2 AVX2)
|
||||
ocv_add_dispatched_file(convert SSE2 AVX2 VSX3)
|
||||
ocv_add_dispatched_file(convert_scale SSE2 AVX2)
|
||||
ocv_add_dispatched_file(count_non_zero SSE2 AVX2)
|
||||
ocv_add_dispatched_file(matmul SSE2 AVX2)
|
||||
|
||||
@@ -11,11 +11,6 @@
|
||||
#define CV_SIMD128 1
|
||||
#define CV_SIMD128_64F 1
|
||||
|
||||
/**
|
||||
* todo: supporting half precision for power9
|
||||
* convert instractions xvcvhpsp, xvcvsphp
|
||||
**/
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
@@ -1077,117 +1072,188 @@ inline v_float64x2 v_lut_pairs(const double* tab, const int* idx) { return v_loa
|
||||
|
||||
inline v_int32x4 v_lut(const int* tab, const v_int32x4& idxvec)
|
||||
{
|
||||
int CV_DECL_ALIGNED(32) idx[4];
|
||||
v_store_aligned(idx, idxvec);
|
||||
const int idx[4] = {
|
||||
vec_extract(idxvec.val, 0),
|
||||
vec_extract(idxvec.val, 1),
|
||||
vec_extract(idxvec.val, 2),
|
||||
vec_extract(idxvec.val, 3)
|
||||
};
|
||||
return v_int32x4(tab[idx[0]], tab[idx[1]], tab[idx[2]], tab[idx[3]]);
|
||||
}
|
||||
|
||||
inline v_uint32x4 v_lut(const unsigned* tab, const v_int32x4& idxvec)
|
||||
{
|
||||
int CV_DECL_ALIGNED(32) idx[4];
|
||||
v_store_aligned(idx, idxvec);
|
||||
const int idx[4] = {
|
||||
vec_extract(idxvec.val, 0),
|
||||
vec_extract(idxvec.val, 1),
|
||||
vec_extract(idxvec.val, 2),
|
||||
vec_extract(idxvec.val, 3)
|
||||
};
|
||||
return v_uint32x4(tab[idx[0]], tab[idx[1]], tab[idx[2]], tab[idx[3]]);
|
||||
}
|
||||
|
||||
inline v_float32x4 v_lut(const float* tab, const v_int32x4& idxvec)
|
||||
{
|
||||
int CV_DECL_ALIGNED(32) idx[4];
|
||||
v_store_aligned(idx, idxvec);
|
||||
const int idx[4] = {
|
||||
vec_extract(idxvec.val, 0),
|
||||
vec_extract(idxvec.val, 1),
|
||||
vec_extract(idxvec.val, 2),
|
||||
vec_extract(idxvec.val, 3)
|
||||
};
|
||||
return v_float32x4(tab[idx[0]], tab[idx[1]], tab[idx[2]], tab[idx[3]]);
|
||||
}
|
||||
|
||||
inline v_float64x2 v_lut(const double* tab, const v_int32x4& idxvec)
|
||||
{
|
||||
int CV_DECL_ALIGNED(32) idx[4];
|
||||
v_store_aligned(idx, idxvec);
|
||||
const int idx[2] = {
|
||||
vec_extract(idxvec.val, 0),
|
||||
vec_extract(idxvec.val, 1)
|
||||
};
|
||||
return v_float64x2(tab[idx[0]], tab[idx[1]]);
|
||||
}
|
||||
|
||||
inline void v_lut_deinterleave(const float* tab, const v_int32x4& idxvec, v_float32x4& x, v_float32x4& y)
|
||||
{
|
||||
int CV_DECL_ALIGNED(32) idx[4];
|
||||
v_store_aligned(idx, idxvec);
|
||||
x = v_float32x4(tab[idx[0]], tab[idx[1]], tab[idx[2]], tab[idx[3]]);
|
||||
y = v_float32x4(tab[idx[0]+1], tab[idx[1]+1], tab[idx[2]+1], tab[idx[3]+1]);
|
||||
vec_float4 xy0 = vec_ld_l8(tab + vec_extract(idxvec.val, 0));
|
||||
vec_float4 xy1 = vec_ld_l8(tab + vec_extract(idxvec.val, 1));
|
||||
vec_float4 xy2 = vec_ld_l8(tab + vec_extract(idxvec.val, 2));
|
||||
vec_float4 xy3 = vec_ld_l8(tab + vec_extract(idxvec.val, 3));
|
||||
vec_float4 xy02 = vec_mergeh(xy0, xy2); // x0, x2, y0, y2
|
||||
vec_float4 xy13 = vec_mergeh(xy1, xy3); // x1, x3, y1, y3
|
||||
x.val = vec_mergeh(xy02, xy13);
|
||||
y.val = vec_mergel(xy02, xy13);
|
||||
}
|
||||
|
||||
inline void v_lut_deinterleave(const double* tab, const v_int32x4& idxvec, v_float64x2& x, v_float64x2& y)
|
||||
{
|
||||
int CV_DECL_ALIGNED(32) idx[4];
|
||||
v_store_aligned(idx, idxvec);
|
||||
x = v_float64x2(tab[idx[0]], tab[idx[1]]);
|
||||
y = v_float64x2(tab[idx[0]+1], tab[idx[1]+1]);
|
||||
vec_double2 xy0 = vsx_ld(vec_extract(idxvec.val, 0), tab);
|
||||
vec_double2 xy1 = vsx_ld(vec_extract(idxvec.val, 1), tab);
|
||||
x.val = vec_mergeh(xy0, xy1);
|
||||
y.val = vec_mergel(xy0, xy1);
|
||||
}
|
||||
|
||||
inline v_int8x16 v_interleave_pairs(const v_int8x16& vec)
|
||||
{
|
||||
vec_short8 vec0 = vec_mergeh((vec_short8)vec.val, (vec_short8)vec_mergesql(vec.val, vec.val));
|
||||
vec0 = vec_mergeh(vec0, vec_mergesql(vec0, vec0));
|
||||
return v_int8x16(vec_mergeh((vec_char16)vec0, (vec_char16)vec_mergesql(vec0, vec0)));
|
||||
static const vec_uchar16 perm = {0, 2, 1, 3, 4, 6, 5, 7, 8, 10, 9, 11, 12, 14, 13, 15};
|
||||
return v_int8x16(vec_perm(vec.val, vec.val, perm));
|
||||
}
|
||||
inline v_uint8x16 v_interleave_pairs(const v_uint8x16& vec) { return v_reinterpret_as_u8(v_interleave_pairs(v_reinterpret_as_s8(vec))); }
|
||||
inline v_uint8x16 v_interleave_pairs(const v_uint8x16& vec)
|
||||
{ return v_reinterpret_as_u8(v_interleave_pairs(v_reinterpret_as_s8(vec))); }
|
||||
|
||||
inline v_int8x16 v_interleave_quads(const v_int8x16& vec)
|
||||
{
|
||||
vec_char16 vec0 = (vec_char16)vec_mergeh((vec_int4)vec.val, (vec_int4)vec_mergesql(vec.val, vec.val));
|
||||
return v_int8x16(vec_mergeh(vec0, vec_mergesql(vec0, vec0)));
|
||||
static const vec_uchar16 perm = {0, 4, 1, 5, 2, 6, 3, 7, 8, 12, 9, 13, 10, 14, 11, 15};
|
||||
return v_int8x16(vec_perm(vec.val, vec.val, perm));
|
||||
}
|
||||
inline v_uint8x16 v_interleave_quads(const v_uint8x16& vec) { return v_reinterpret_as_u8(v_interleave_quads(v_reinterpret_as_s8(vec))); }
|
||||
inline v_uint8x16 v_interleave_quads(const v_uint8x16& vec)
|
||||
{ return v_reinterpret_as_u8(v_interleave_quads(v_reinterpret_as_s8(vec))); }
|
||||
|
||||
inline v_int16x8 v_interleave_pairs(const v_int16x8& vec)
|
||||
{
|
||||
vec_short8 vec0 = (vec_short8)vec_mergeh((vec_int4)vec.val, (vec_int4)vec_mergesql(vec.val, vec.val));
|
||||
return v_int16x8(vec_mergeh(vec0, vec_mergesql(vec0, vec0)));
|
||||
static const vec_uchar16 perm = {0,1, 4,5, 2,3, 6,7, 8,9, 12,13, 10,11, 14,15};
|
||||
return v_int16x8(vec_perm(vec.val, vec.val, perm));
|
||||
}
|
||||
inline v_uint16x8 v_interleave_pairs(const v_uint16x8& vec) { return v_reinterpret_as_u16(v_interleave_pairs(v_reinterpret_as_s16(vec))); }
|
||||
inline v_uint16x8 v_interleave_pairs(const v_uint16x8& vec)
|
||||
{ return v_reinterpret_as_u16(v_interleave_pairs(v_reinterpret_as_s16(vec))); }
|
||||
|
||||
inline v_int16x8 v_interleave_quads(const v_int16x8& vec)
|
||||
{
|
||||
return v_int16x8(vec_mergeh(vec.val, vec_mergesql(vec.val, vec.val)));
|
||||
static const vec_uchar16 perm = {0,1, 8,9, 2,3, 10,11, 4,5, 12,13, 6,7, 14,15};
|
||||
return v_int16x8(vec_perm(vec.val, vec.val, perm));
|
||||
}
|
||||
inline v_uint16x8 v_interleave_quads(const v_uint16x8& vec) { return v_reinterpret_as_u16(v_interleave_quads(v_reinterpret_as_s16(vec))); }
|
||||
inline v_uint16x8 v_interleave_quads(const v_uint16x8& vec)
|
||||
{ return v_reinterpret_as_u16(v_interleave_quads(v_reinterpret_as_s16(vec))); }
|
||||
|
||||
inline v_int32x4 v_interleave_pairs(const v_int32x4& vec)
|
||||
{
|
||||
return v_int32x4(vec_mergeh(vec.val, vec_mergesql(vec.val, vec.val)));
|
||||
static const vec_uchar16 perm = {0,1,2,3, 8,9,10,11, 4,5,6,7, 12,13,14,15};
|
||||
return v_int32x4(vec_perm(vec.val, vec.val, perm));
|
||||
}
|
||||
inline v_uint32x4 v_interleave_pairs(const v_uint32x4& vec) { return v_reinterpret_as_u32(v_interleave_pairs(v_reinterpret_as_s32(vec))); }
|
||||
inline v_float32x4 v_interleave_pairs(const v_float32x4& vec) { return v_reinterpret_as_f32(v_interleave_pairs(v_reinterpret_as_s32(vec))); }
|
||||
inline v_uint32x4 v_interleave_pairs(const v_uint32x4& vec)
|
||||
{ return v_reinterpret_as_u32(v_interleave_pairs(v_reinterpret_as_s32(vec))); }
|
||||
inline v_float32x4 v_interleave_pairs(const v_float32x4& vec)
|
||||
{ return v_reinterpret_as_f32(v_interleave_pairs(v_reinterpret_as_s32(vec))); }
|
||||
|
||||
inline v_int8x16 v_pack_triplets(const v_int8x16& vec)
|
||||
{
|
||||
schar CV_DECL_ALIGNED(32) val[16];
|
||||
v_store_aligned(val, vec);
|
||||
return v_int8x16(val[0], val[1], val[2], val[4], val[5], val[6], val[8], val[9], val[10], val[12], val[13], val[14], val[15], val[15], val[15], val[15]);
|
||||
static const vec_uchar16 perm = {0, 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, 15, 15, 15, 15};
|
||||
return v_int8x16(vec_perm(vec.val, vec.val, perm));
|
||||
}
|
||||
inline v_uint8x16 v_pack_triplets(const v_uint8x16& vec) { return v_reinterpret_as_u8(v_pack_triplets(v_reinterpret_as_s8(vec))); }
|
||||
inline v_uint8x16 v_pack_triplets(const v_uint8x16& vec)
|
||||
{ return v_reinterpret_as_u8(v_pack_triplets(v_reinterpret_as_s8(vec))); }
|
||||
|
||||
inline v_int16x8 v_pack_triplets(const v_int16x8& vec)
|
||||
{
|
||||
short CV_DECL_ALIGNED(32) val[8];
|
||||
v_store_aligned(val, vec);
|
||||
return v_int16x8(val[0], val[1], val[2], val[4], val[5], val[6], val[7], val[7]);
|
||||
static const vec_uchar16 perm = {0,1, 2,3, 4,5, 8,9, 10,11, 12,13, 14,15, 14,15};
|
||||
return v_int16x8(vec_perm(vec.val, vec.val, perm));
|
||||
}
|
||||
inline v_uint16x8 v_pack_triplets(const v_uint16x8& vec) { return v_reinterpret_as_u16(v_pack_triplets(v_reinterpret_as_s16(vec))); }
|
||||
inline v_uint16x8 v_pack_triplets(const v_uint16x8& vec)
|
||||
{ return v_reinterpret_as_u16(v_pack_triplets(v_reinterpret_as_s16(vec))); }
|
||||
|
||||
inline v_int32x4 v_pack_triplets(const v_int32x4& vec) { return vec; }
|
||||
inline v_uint32x4 v_pack_triplets(const v_uint32x4& vec) { return vec; }
|
||||
inline v_float32x4 v_pack_triplets(const v_float32x4& vec) { return vec; }
|
||||
inline v_int32x4 v_pack_triplets(const v_int32x4& vec)
|
||||
{ return vec; }
|
||||
inline v_uint32x4 v_pack_triplets(const v_uint32x4& vec)
|
||||
{ return vec; }
|
||||
inline v_float32x4 v_pack_triplets(const v_float32x4& vec)
|
||||
{ return vec; }
|
||||
|
||||
/////// FP16 support ////////
|
||||
|
||||
// [TODO] implement these 2 using VSX or universal intrinsics (copy from intrin_sse.cpp and adopt)
|
||||
inline v_float32x4 v_load_expand(const float16_t* ptr)
|
||||
{
|
||||
return v_float32x4((float)ptr[0], (float)ptr[1], (float)ptr[2], (float)ptr[3]);
|
||||
vec_ushort8 vf16 = vec_ld_l8((const ushort*)ptr);
|
||||
#if CV_VSX3 && defined(vec_extract_fp_from_shorth)
|
||||
return v_float32x4(vec_extract_fp_from_shorth(vf16));
|
||||
#elif CV_VSX3 && !defined(CV_COMPILER_VSX_BROKEN_ASM)
|
||||
vec_float4 vf32;
|
||||
__asm__ __volatile__ ("xvcvhpsp %x0,%x1" : "=wf" (vf32) : "wa" (vec_mergeh(vf16, vf16)));
|
||||
return v_float32x4(vf32);
|
||||
#else
|
||||
const vec_int4 z = vec_int4_z, delta = vec_int4_sp(0x38000000);
|
||||
const vec_int4 signmask = vec_int4_sp(0x80000000);
|
||||
const vec_int4 maxexp = vec_int4_sp(0x7c000000);
|
||||
const vec_float4 deltaf = vec_float4_c(vec_int4_sp(0x38800000));
|
||||
|
||||
vec_int4 bits = vec_int4_c(vec_mergeh(vec_short8_c(z), vec_short8_c(vf16)));
|
||||
vec_int4 e = vec_and(bits, maxexp), sign = vec_and(bits, signmask);
|
||||
vec_int4 t = vec_add(vec_sr(vec_xor(bits, sign), vec_uint4_sp(3)), delta); // ((h & 0x7fff) << 13) + delta
|
||||
vec_int4 zt = vec_int4_c(vec_sub(vec_float4_c(vec_add(t, vec_int4_sp(1 << 23))), deltaf));
|
||||
|
||||
t = vec_add(t, vec_and(delta, vec_cmpeq(maxexp, e)));
|
||||
vec_bint4 zmask = vec_cmpeq(e, z);
|
||||
vec_int4 ft = vec_sel(t, zt, zmask);
|
||||
return v_float32x4(vec_float4_c(vec_or(ft, sign)));
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void v_pack_store(float16_t* ptr, const v_float32x4& v)
|
||||
{
|
||||
float CV_DECL_ALIGNED(32) f[4];
|
||||
v_store_aligned(f, v);
|
||||
ptr[0] = float16_t(f[0]);
|
||||
ptr[1] = float16_t(f[1]);
|
||||
ptr[2] = float16_t(f[2]);
|
||||
ptr[3] = float16_t(f[3]);
|
||||
// fixme: Is there any buitin op or intrinsic that cover "xvcvsphp"?
|
||||
#if CV_VSX3 && !defined(CV_COMPILER_VSX_BROKEN_ASM)
|
||||
vec_ushort8 vf16;
|
||||
__asm__ __volatile__ ("xvcvsphp %x0,%x1" : "=wa" (vf16) : "wf" (v.val));
|
||||
vec_st_l8(vec_mergesqe(vf16, vf16), ptr);
|
||||
#else
|
||||
const vec_int4 signmask = vec_int4_sp(0x80000000);
|
||||
const vec_int4 rval = vec_int4_sp(0x3f000000);
|
||||
|
||||
vec_int4 t = vec_int4_c(v.val);
|
||||
vec_int4 sign = vec_sra(vec_and(t, signmask), vec_uint4_sp(16));
|
||||
t = vec_and(vec_nor(signmask, signmask), t);
|
||||
|
||||
vec_bint4 finitemask = vec_cmpgt(vec_int4_sp(0x47800000), t);
|
||||
vec_bint4 isnan = vec_cmpgt(t, vec_int4_sp(0x7f800000));
|
||||
vec_int4 naninf = vec_sel(vec_int4_sp(0x7c00), vec_int4_sp(0x7e00), isnan);
|
||||
vec_bint4 tinymask = vec_cmpgt(vec_int4_sp(0x38800000), t);
|
||||
vec_int4 tt = vec_int4_c(vec_add(vec_float4_c(t), vec_float4_c(rval)));
|
||||
tt = vec_sub(tt, rval);
|
||||
vec_int4 odd = vec_and(vec_sr(t, vec_uint4_sp(13)), vec_int4_sp(1));
|
||||
vec_int4 nt = vec_add(t, vec_int4_sp(0xc8000fff));
|
||||
nt = vec_sr(vec_add(nt, odd), vec_uint4_sp(13));
|
||||
t = vec_sel(nt, tt, tinymask);
|
||||
t = vec_sel(naninf, t, finitemask);
|
||||
t = vec_or(t, sign);
|
||||
vec_st_l8(vec_packs(t, t), ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void v_cleanup() {}
|
||||
|
||||
@@ -291,6 +291,8 @@ VSX_IMPL_1RG(vec_udword2, wi, vec_float4, wf, xvcvspuxds, vec_ctulo)
|
||||
*
|
||||
* So we're not able to use inline asm and only use built-in functions that CLANG supports
|
||||
* and use __builtin_convertvector if clang missng any of vector conversions built-in functions
|
||||
*
|
||||
* todo: clang asm template bug is fixed, need to reconsider the current workarounds.
|
||||
*/
|
||||
|
||||
// convert vector helper
|
||||
|
||||
@@ -322,6 +322,8 @@ private:
|
||||
// Fortran subroutine in EISPACK.
|
||||
|
||||
// Initialize
|
||||
const int max_iters_count = 1000 * this->n;
|
||||
|
||||
int nn = this->n;
|
||||
int n1 = nn - 1;
|
||||
int low = 0;
|
||||
@@ -487,7 +489,9 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
iter = iter + 1; // (Could check iteration count here.)
|
||||
iter = iter + 1;
|
||||
if (iter > max_iters_count)
|
||||
CV_Error(Error::StsNoConv, "Algorithm doesn't converge (complex eigen values?)");
|
||||
|
||||
// Look for two consecutive small sub-diagonal elements
|
||||
int m = n1 - 2;
|
||||
|
||||
+164
-180
@@ -1451,115 +1451,82 @@ transform_( const T* src, T* dst, const WT* m, int len, int scn, int dcn )
|
||||
}
|
||||
}
|
||||
|
||||
#if CV_SIMD128 && !defined(__aarch64__)
|
||||
static inline void
|
||||
load3x3Matrix(const float* m, v_float32x4& m0, v_float32x4& m1, v_float32x4& m2, v_float32x4& m3)
|
||||
{
|
||||
m0 = v_float32x4(m[0], m[4], m[8], 0);
|
||||
m1 = v_float32x4(m[1], m[5], m[9], 0);
|
||||
m2 = v_float32x4(m[2], m[6], m[10], 0);
|
||||
m3 = v_float32x4(m[3], m[7], m[11], 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CV_SIMD128
|
||||
static inline v_int16x8
|
||||
v_matmulvec(const v_int16x8 &v0, const v_int16x8 &m0, const v_int16x8 &m1, const v_int16x8 &m2, const v_int32x4 &m3, const int BITS)
|
||||
{
|
||||
// v0 : 0 b0 g0 r0 b1 g1 r1 ?
|
||||
v_int32x4 t0 = v_dotprod(v0, m0); // a0 b0 a1 b1
|
||||
v_int32x4 t1 = v_dotprod(v0, m1); // c0 d0 c1 d1
|
||||
v_int32x4 t2 = v_dotprod(v0, m2); // e0 f0 e1 f1
|
||||
v_int32x4 t3 = v_setzero_s32();
|
||||
v_int32x4 s0, s1, s2, s3;
|
||||
v_transpose4x4(t0, t1, t2, t3, s0, s1, s2, s3);
|
||||
s0 = s0 + s1 + m3; // B0 G0 R0 ?
|
||||
s2 = s2 + s3 + m3; // B1 G1 R1 ?
|
||||
|
||||
s0 = s0 >> BITS;
|
||||
s2 = s2 >> BITS;
|
||||
|
||||
v_int16x8 result = v_pack(s0, v_setzero_s32()); // B0 G0 R0 0 0 0 0 0
|
||||
result = v_reinterpret_as_s16(v_reinterpret_as_s64(result) << 16); // 0 B0 G0 R0 0 0 0 0
|
||||
result = result | v_pack(v_setzero_s32(), s2); // 0 B0 G0 R0 B1 G1 R1 0
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
transform_8u( const uchar* src, uchar* dst, const float* m, int len, int scn, int dcn )
|
||||
{
|
||||
#if CV_SIMD128
|
||||
#if CV_SIMD
|
||||
const int BITS = 10, SCALE = 1 << BITS;
|
||||
const float MAX_M = (float)(1 << (15 - BITS));
|
||||
|
||||
if( hasSIMD128() && scn == 3 && dcn == 3 &&
|
||||
std::abs(m[0]) < MAX_M && std::abs(m[1]) < MAX_M && std::abs(m[2]) < MAX_M && std::abs(m[3]) < MAX_M*256 &&
|
||||
std::abs(m[4]) < MAX_M && std::abs(m[5]) < MAX_M && std::abs(m[6]) < MAX_M && std::abs(m[7]) < MAX_M*256 &&
|
||||
std::abs(m[8]) < MAX_M && std::abs(m[9]) < MAX_M && std::abs(m[10]) < MAX_M && std::abs(m[11]) < MAX_M*256 )
|
||||
if( scn == 3 && dcn == 3 &&
|
||||
std::abs(m[0]) < MAX_M && std::abs(m[1]) < MAX_M && std::abs(m[ 2]) < MAX_M*256 && std::abs(m[ 3]) < MAX_M*256 &&
|
||||
std::abs(m[4]) < MAX_M && std::abs(m[5]) < MAX_M && std::abs(m[ 6]) < MAX_M*256 && std::abs(m[ 7]) < MAX_M*256 &&
|
||||
std::abs(m[8]) < MAX_M && std::abs(m[9]) < MAX_M && std::abs(m[10]) < MAX_M*256 && std::abs(m[11]) < MAX_M*256 )
|
||||
{
|
||||
const int nChannels = 3;
|
||||
const int cWidth = v_int16x8::nlanes;
|
||||
// faster fixed-point transformation
|
||||
short m00 = saturate_cast<short>(m[0]*SCALE), m01 = saturate_cast<short>(m[1]*SCALE),
|
||||
m02 = saturate_cast<short>(m[2]*SCALE), m10 = saturate_cast<short>(m[4]*SCALE),
|
||||
m11 = saturate_cast<short>(m[5]*SCALE), m12 = saturate_cast<short>(m[6]*SCALE),
|
||||
m20 = saturate_cast<short>(m[8]*SCALE), m21 = saturate_cast<short>(m[9]*SCALE),
|
||||
m22 = saturate_cast<short>(m[10]*SCALE);
|
||||
int m03 = saturate_cast<int>((m[3]+0.5f)*SCALE), m13 = saturate_cast<int>((m[7]+0.5f)*SCALE ),
|
||||
m23 = saturate_cast<int>((m[11]+0.5f)*SCALE);
|
||||
|
||||
v_int16x8 m0 = v_int16x8(0, m00, m01, m02, m00, m01, m02, 0);
|
||||
v_int16x8 m1 = v_int16x8(0, m10, m11, m12, m10, m11, m12, 0);
|
||||
v_int16x8 m2 = v_int16x8(0, m20, m21, m22, m20, m21, m22, 0);
|
||||
v_int32x4 m3 = v_int32x4(m03, m13, m23, 0);
|
||||
union {
|
||||
short s[6];
|
||||
int p[3];
|
||||
} m16;
|
||||
m16.s[0] = saturate_cast<short>(m[0] * SCALE); m16.s[1] = saturate_cast<short>(m[1] * SCALE);
|
||||
m16.s[2] = saturate_cast<short>(m[4] * SCALE); m16.s[3] = saturate_cast<short>(m[5] * SCALE);
|
||||
m16.s[4] = saturate_cast<short>(m[8] * SCALE); m16.s[5] = saturate_cast<short>(m[9] * SCALE);
|
||||
int m32[] = {saturate_cast<int>(m[ 2] * SCALE), saturate_cast<int>(m[ 3] * SCALE),
|
||||
saturate_cast<int>(m[ 6] * SCALE), saturate_cast<int>(m[ 7] * SCALE),
|
||||
saturate_cast<int>(m[10] * SCALE), saturate_cast<int>(m[11] * SCALE)};
|
||||
v_int16 m01 = v_reinterpret_as_s16(vx_setall_s32(m16.p[0]));
|
||||
v_int32 m2 = vx_setall_s32(m32[0]);
|
||||
v_int32 m3 = vx_setall_s32(m32[1]);
|
||||
v_int16 m45 = v_reinterpret_as_s16(vx_setall_s32(m16.p[1]));
|
||||
v_int32 m6 = vx_setall_s32(m32[2]);
|
||||
v_int32 m7 = vx_setall_s32(m32[3]);
|
||||
v_int16 m89 = v_reinterpret_as_s16(vx_setall_s32(m16.p[2]));
|
||||
v_int32 m10 = vx_setall_s32(m32[4]);
|
||||
v_int32 m11 = vx_setall_s32(m32[5]);
|
||||
int x = 0;
|
||||
|
||||
for (; x <= (len - cWidth) * nChannels; x += cWidth * nChannels)
|
||||
for (; x <= (len - v_uint8::nlanes) * nChannels; x += v_uint8::nlanes * nChannels)
|
||||
{
|
||||
// load 8 pixels
|
||||
v_int16x8 v0 = v_reinterpret_as_s16(v_load_expand(src + x));
|
||||
v_int16x8 v1 = v_reinterpret_as_s16(v_load_expand(src + x + cWidth));
|
||||
v_int16x8 v2 = v_reinterpret_as_s16(v_load_expand(src + x + cWidth * 2));
|
||||
v_int16x8 v3;
|
||||
v_uint8 b, g, r;
|
||||
v_load_deinterleave(src + x, b, g, r);
|
||||
v_uint8 bgl, bgh;
|
||||
v_zip(b, g, bgl, bgh);
|
||||
v_uint16 rl, rh;
|
||||
v_expand(r, rl, rh);
|
||||
|
||||
// rotate and pack
|
||||
v3 = v_rotate_right<1>(v2); // 0 b6 g6 r6 b7 g7 r7 0
|
||||
v2 = v_rotate_left <5>(v2, v1); // 0 b4 g4 r4 b5 g5 r5 0
|
||||
v1 = v_rotate_left <3>(v1, v0); // 0 b2 g2 r2 b3 g3 r3 0
|
||||
v0 = v_rotate_left <1>(v0); // 0 b0 g0 r0 b1 g1 r1 0
|
||||
|
||||
// multiply with matrix and normalize
|
||||
v0 = v_matmulvec(v0, m0, m1, m2, m3, BITS); // 0 B0 G0 R0 B1 G1 R1 0
|
||||
v1 = v_matmulvec(v1, m0, m1, m2, m3, BITS); // 0 B2 G2 R2 B3 G3 R3 0
|
||||
v2 = v_matmulvec(v2, m0, m1, m2, m3, BITS); // 0 B4 G4 R4 B5 G5 R5 0
|
||||
v3 = v_matmulvec(v3, m0, m1, m2, m3, BITS); // 0 B6 G6 R6 B7 G7 R7 0
|
||||
|
||||
// narrow down as uint8x16
|
||||
v_uint8x16 z0 = v_pack_u(v0, v_setzero_s16()); // 0 B0 G0 R0 B1 G1 R1 0 0 0 0 0 0 0 0 0
|
||||
v_uint8x16 z1 = v_pack_u(v1, v_setzero_s16()); // 0 B2 G2 R2 B3 G3 R3 0 0 0 0 0 0 0 0 0
|
||||
v_uint8x16 z2 = v_pack_u(v2, v_setzero_s16()); // 0 B4 G4 R4 B5 G5 R5 0 0 0 0 0 0 0 0 0
|
||||
v_uint8x16 z3 = v_pack_u(v3, v_setzero_s16()); // 0 B6 G6 R6 B7 G7 R7 0 0 0 0 0 0 0 0 0
|
||||
|
||||
// rotate and pack
|
||||
z0 = v_reinterpret_as_u8(v_reinterpret_as_u64(z0) >> 8) | v_reinterpret_as_u8(v_reinterpret_as_u64(z1) << 40); // B0 G0 R0 B1 G1 R1 B2 G2 0 0 0 0 0 0 0 0
|
||||
z1 = v_reinterpret_as_u8(v_reinterpret_as_u64(z1) >> 24) | v_reinterpret_as_u8(v_reinterpret_as_u64(z2) << 24); // R2 B3 G3 R3 B4 G4 R4 B5 0 0 0 0 0 0 0 0
|
||||
z2 = v_reinterpret_as_u8(v_reinterpret_as_u64(z2) >> 40) | v_reinterpret_as_u8(v_reinterpret_as_u64(z3) << 8); // G5 R6 B6 G6 R6 B7 G7 R7 0 0 0 0 0 0 0 0
|
||||
|
||||
// store on memory
|
||||
v_store_low(dst + x, z0);
|
||||
v_store_low(dst + x + cWidth, z1);
|
||||
v_store_low(dst + x + cWidth * 2, z2);
|
||||
v_int16 dbl, dbh, dgl, dgh, drl, drh;
|
||||
v_uint16 p0, p2;
|
||||
v_int32 p1, p3;
|
||||
v_expand(bgl, p0, p2);
|
||||
v_expand(v_reinterpret_as_s16(rl), p1, p3);
|
||||
dbl = v_rshr_pack<BITS>(v_dotprod(v_reinterpret_as_s16(p0), m01) + p1 * m2 + m3,
|
||||
v_dotprod(v_reinterpret_as_s16(p2), m01) + p3 * m2 + m3);
|
||||
dgl = v_rshr_pack<BITS>(v_dotprod(v_reinterpret_as_s16(p0), m45) + p1 * m6 + m7,
|
||||
v_dotprod(v_reinterpret_as_s16(p2), m45) + p3 * m6 + m7);
|
||||
drl = v_rshr_pack<BITS>(v_dotprod(v_reinterpret_as_s16(p0), m89) + p1 * m10 + m11,
|
||||
v_dotprod(v_reinterpret_as_s16(p2), m89) + p3 * m10 + m11);
|
||||
v_expand(bgh, p0, p2);
|
||||
v_expand(v_reinterpret_as_s16(rh), p1, p3);
|
||||
dbh = v_rshr_pack<BITS>(v_dotprod(v_reinterpret_as_s16(p0), m01) + p1 * m2 + m3,
|
||||
v_dotprod(v_reinterpret_as_s16(p2), m01) + p3 * m2 + m3);
|
||||
dgh = v_rshr_pack<BITS>(v_dotprod(v_reinterpret_as_s16(p0), m45) + p1 * m6 + m7,
|
||||
v_dotprod(v_reinterpret_as_s16(p2), m45) + p3 * m6 + m7);
|
||||
drh = v_rshr_pack<BITS>(v_dotprod(v_reinterpret_as_s16(p0), m89) + p1 * m10 + m11,
|
||||
v_dotprod(v_reinterpret_as_s16(p2), m89) + p3 * m10 + m11);
|
||||
v_store_interleave(dst + x, v_pack_u(dbl, dbh), v_pack_u(dgl, dgh), v_pack_u(drl, drh));
|
||||
}
|
||||
|
||||
m32[1] = saturate_cast<int>((m[3] + 0.5f)*SCALE);
|
||||
m32[3] = saturate_cast<int>((m[7] + 0.5f)*SCALE);
|
||||
m32[5] = saturate_cast<int>((m[11] + 0.5f)*SCALE);
|
||||
for( ; x < len * nChannels; x += nChannels )
|
||||
{
|
||||
int v0 = src[x], v1 = src[x+1], v2 = src[x+2];
|
||||
uchar t0 = saturate_cast<uchar>((m00*v0 + m01*v1 + m02*v2 + m03)>>BITS);
|
||||
uchar t1 = saturate_cast<uchar>((m10*v0 + m11*v1 + m12*v2 + m13)>>BITS);
|
||||
uchar t2 = saturate_cast<uchar>((m20*v0 + m21*v1 + m22*v2 + m23)>>BITS);
|
||||
uchar t0 = saturate_cast<uchar>((m16.s[0] * v0 + m16.s[1] * v1 + m32[0] * v2 + m32[1]) >> BITS);
|
||||
uchar t1 = saturate_cast<uchar>((m16.s[2] * v0 + m16.s[3] * v1 + m32[2] * v2 + m32[3]) >> BITS);
|
||||
uchar t2 = saturate_cast<uchar>((m16.s[4] * v0 + m16.s[5] * v1 + m32[4] * v2 + m32[5]) >> BITS);
|
||||
dst[x] = t0; dst[x+1] = t1; dst[x+2] = t2;
|
||||
}
|
||||
vx_cleanup();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -1570,64 +1537,65 @@ transform_8u( const uchar* src, uchar* dst, const float* m, int len, int scn, in
|
||||
static void
|
||||
transform_16u( const ushort* src, ushort* dst, const float* m, int len, int scn, int dcn )
|
||||
{
|
||||
#if CV_SIMD128 && !defined(__aarch64__)
|
||||
if( hasSIMD128() && scn == 3 && dcn == 3 )
|
||||
#if CV_SIMD && !defined(__aarch64__)
|
||||
if( scn == 3 && dcn == 3 )
|
||||
{
|
||||
const int nChannels = 3;
|
||||
const int cWidth = v_float32x4::nlanes;
|
||||
v_int16x8 delta = v_int16x8(0, -32768, -32768, -32768, -32768, -32768, -32768, 0);
|
||||
v_float32x4 m0, m1, m2, m3;
|
||||
load3x3Matrix(m, m0, m1, m2, m3);
|
||||
m3 -= v_float32x4(32768.f, 32768.f, 32768.f, 0.f);
|
||||
|
||||
int x = 0;
|
||||
for( ; x <= (len - cWidth) * nChannels; x += cWidth * nChannels )
|
||||
#if CV_SIMD_WIDTH > 16
|
||||
v_float32 m0 = vx_setall_f32(m[ 0]);
|
||||
v_float32 m1 = vx_setall_f32(m[ 1]);
|
||||
v_float32 m2 = vx_setall_f32(m[ 2]);
|
||||
v_float32 m3 = vx_setall_f32(m[ 3] - 32768.f);
|
||||
v_float32 m4 = vx_setall_f32(m[ 4]);
|
||||
v_float32 m5 = vx_setall_f32(m[ 5]);
|
||||
v_float32 m6 = vx_setall_f32(m[ 6]);
|
||||
v_float32 m7 = vx_setall_f32(m[ 7] - 32768.f);
|
||||
v_float32 m8 = vx_setall_f32(m[ 8]);
|
||||
v_float32 m9 = vx_setall_f32(m[ 9]);
|
||||
v_float32 m10 = vx_setall_f32(m[10]);
|
||||
v_float32 m11 = vx_setall_f32(m[11] - 32768.f);
|
||||
v_int16 delta = vx_setall_s16(-32768);
|
||||
for (; x <= (len - v_uint16::nlanes)*3; x += v_uint16::nlanes*3)
|
||||
{
|
||||
// load 4 pixels
|
||||
v_uint16x8 v0_16 = v_load(src + x); // b0 g0 r0 b1 g1 r1 b2 g2
|
||||
v_uint16x8 v2_16 = v_load_low(src + x + cWidth * 2); // r2 b3 g3 r3 ? ? ? ?
|
||||
v_uint16 b, g, r;
|
||||
v_load_deinterleave(src + x, b, g, r);
|
||||
v_uint32 bl, bh, gl, gh, rl, rh;
|
||||
v_expand(b, bl, bh);
|
||||
v_expand(g, gl, gh);
|
||||
v_expand(r, rl, rh);
|
||||
|
||||
// expand to 4 vectors
|
||||
v_uint32x4 v0_32, v1_32, v2_32, v3_32, dummy_32;
|
||||
v_expand(v_rotate_right<3>(v0_16), v1_32, dummy_32); // b1 g1 r1
|
||||
v_expand(v_rotate_right<1>(v2_16), v3_32, dummy_32); // b3 g3 r3
|
||||
v_expand(v_rotate_right<6>(v0_16, v2_16), v2_32, dummy_32); // b2 g2 r2
|
||||
v_expand(v0_16, v0_32, dummy_32); // b0 g0 r0
|
||||
|
||||
// convert to float32x4
|
||||
v_float32x4 x0 = v_cvt_f32(v_reinterpret_as_s32(v0_32)); // b0 g0 r0
|
||||
v_float32x4 x1 = v_cvt_f32(v_reinterpret_as_s32(v1_32)); // b1 g1 r1
|
||||
v_float32x4 x2 = v_cvt_f32(v_reinterpret_as_s32(v2_32)); // b2 g2 r2
|
||||
v_float32x4 x3 = v_cvt_f32(v_reinterpret_as_s32(v3_32)); // b3 g3 r3
|
||||
|
||||
// multiply and convert back to int32x4
|
||||
v_int32x4 y0, y1, y2, y3;
|
||||
y0 = v_round(v_matmuladd(x0, m0, m1, m2, m3)); // B0 G0 R0
|
||||
y1 = v_round(v_matmuladd(x1, m0, m1, m2, m3)); // B1 G1 R1
|
||||
y2 = v_round(v_matmuladd(x2, m0, m1, m2, m3)); // B2 G2 R2
|
||||
y3 = v_round(v_matmuladd(x3, m0, m1, m2, m3)); // B3 G3 R3
|
||||
|
||||
// narrow down to int16x8
|
||||
v_int16x8 v0 = v_add_wrap(v_pack(v_rotate_left<1>(y0), y1), delta); // 0 B0 G0 R0 B1 G1 R1 0
|
||||
v_int16x8 v2 = v_add_wrap(v_pack(v_rotate_left<1>(y2), y3), delta); // 0 B2 G2 R2 B3 G3 R3 0
|
||||
|
||||
// rotate and pack
|
||||
v0 = v_rotate_right<1>(v0) | v_rotate_left<5>(v2); // B0 G0 R0 B1 G1 R1 B2 G2
|
||||
v2 = v_rotate_right<3>(v2); // R2 B3 G3 R3 0 0 0 0
|
||||
|
||||
// store 4 pixels
|
||||
v_store(dst + x, v_reinterpret_as_u16(v0));
|
||||
v_store_low(dst + x + cWidth * 2, v_reinterpret_as_u16(v2));
|
||||
v_int16 db, dg, dr;
|
||||
db = v_add_wrap(v_pack(v_round(v_muladd(v_cvt_f32(v_reinterpret_as_s32(bl)), m0, v_muladd(v_cvt_f32(v_reinterpret_as_s32(gl)), m1, v_muladd(v_cvt_f32(v_reinterpret_as_s32(rl)), m2, m3)))),
|
||||
v_round(v_muladd(v_cvt_f32(v_reinterpret_as_s32(bh)), m0, v_muladd(v_cvt_f32(v_reinterpret_as_s32(gh)), m1, v_muladd(v_cvt_f32(v_reinterpret_as_s32(rh)), m2, m3))))), delta);
|
||||
dg = v_add_wrap(v_pack(v_round(v_muladd(v_cvt_f32(v_reinterpret_as_s32(bl)), m4, v_muladd(v_cvt_f32(v_reinterpret_as_s32(gl)), m5, v_muladd(v_cvt_f32(v_reinterpret_as_s32(rl)), m6, m7)))),
|
||||
v_round(v_muladd(v_cvt_f32(v_reinterpret_as_s32(bh)), m4, v_muladd(v_cvt_f32(v_reinterpret_as_s32(gh)), m5, v_muladd(v_cvt_f32(v_reinterpret_as_s32(rh)), m6, m7))))), delta);
|
||||
dr = v_add_wrap(v_pack(v_round(v_muladd(v_cvt_f32(v_reinterpret_as_s32(bl)), m8, v_muladd(v_cvt_f32(v_reinterpret_as_s32(gl)), m9, v_muladd(v_cvt_f32(v_reinterpret_as_s32(rl)), m10, m11)))),
|
||||
v_round(v_muladd(v_cvt_f32(v_reinterpret_as_s32(bh)), m8, v_muladd(v_cvt_f32(v_reinterpret_as_s32(gh)), m9, v_muladd(v_cvt_f32(v_reinterpret_as_s32(rh)), m10, m11))))), delta);
|
||||
v_store_interleave(dst + x, v_reinterpret_as_u16(db), v_reinterpret_as_u16(dg), v_reinterpret_as_u16(dr));
|
||||
}
|
||||
|
||||
for( ; x < len * nChannels; x += nChannels )
|
||||
#endif
|
||||
v_float32x4 _m0l(m[0], m[4], m[ 8], 0.f);
|
||||
v_float32x4 _m1l(m[1], m[5], m[ 9], 0.f);
|
||||
v_float32x4 _m2l(m[2], m[6], m[10], 0.f);
|
||||
v_float32x4 _m3l(m[3] - 32768.f, m[7] - 32768.f, m[11] - 32768.f, 0.f);
|
||||
v_float32x4 _m0h = v_rotate_left<1>(_m0l);
|
||||
v_float32x4 _m1h = v_rotate_left<1>(_m1l);
|
||||
v_float32x4 _m2h = v_rotate_left<1>(_m2l);
|
||||
v_float32x4 _m3h = v_rotate_left<1>(_m3l);
|
||||
v_int16x8 _delta(0, -32768, -32768, -32768, -32768, -32768, -32768, 0);
|
||||
for( ; x <= len*3 - v_uint16x8::nlanes; x += 3*v_uint16x8::nlanes/4 )
|
||||
v_store(dst + x, v_rotate_right<1>(v_reinterpret_as_u16(v_add_wrap(v_pack(
|
||||
v_round(v_matmuladd(v_cvt_f32(v_reinterpret_as_s32(v_load_expand(src + x ))), _m0h, _m1h, _m2h, _m3h)),
|
||||
v_round(v_matmuladd(v_cvt_f32(v_reinterpret_as_s32(v_load_expand(src + x + 3))), _m0l, _m1l, _m2l, _m3l))), _delta))));
|
||||
for( ; x < len * 3; x += 3 )
|
||||
{
|
||||
float v0 = src[x], v1 = src[x + 1], v2 = src[x + 2];
|
||||
ushort t0 = saturate_cast<ushort>(m[0] * v0 + m[1] * v1 + m[2] * v2 + m[3]);
|
||||
ushort t1 = saturate_cast<ushort>(m[4] * v0 + m[5] * v1 + m[6] * v2 + m[7]);
|
||||
ushort t0 = saturate_cast<ushort>(m[0] * v0 + m[1] * v1 + m[ 2] * v2 + m[ 3]);
|
||||
ushort t1 = saturate_cast<ushort>(m[4] * v0 + m[5] * v1 + m[ 6] * v2 + m[ 7]);
|
||||
ushort t2 = saturate_cast<ushort>(m[8] * v0 + m[9] * v1 + m[10] * v2 + m[11]);
|
||||
dst[x] = t0; dst[x + 1] = t1; dst[x + 2] = t2;
|
||||
}
|
||||
vx_cleanup();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -1638,52 +1606,68 @@ transform_16u( const ushort* src, ushort* dst, const float* m, int len, int scn,
|
||||
static void
|
||||
transform_32f( const float* src, float* dst, const float* m, int len, int scn, int dcn )
|
||||
{
|
||||
#if CV_SIMD128 && !defined(__aarch64__)
|
||||
if( hasSIMD128() )
|
||||
#if CV_SIMD && !defined(__aarch64__)
|
||||
int x = 0;
|
||||
if( scn == 3 && dcn == 3 )
|
||||
{
|
||||
int x = 0;
|
||||
if( scn == 3 && dcn == 3 )
|
||||
int idx[v_float32::nlanes/2];
|
||||
for( int i = 0; i < v_float32::nlanes/4; i++ )
|
||||
{
|
||||
const int cWidth = 3;
|
||||
v_float32x4 m0, m1, m2, m3;
|
||||
load3x3Matrix(m, m0, m1, m2, m3);
|
||||
|
||||
for( ; x < (len - 1)*cWidth; x += cWidth )
|
||||
{
|
||||
v_float32x4 x0 = v_load(src + x);
|
||||
v_float32x4 y0 = v_matmuladd(x0, m0, m1, m2, m3);
|
||||
v_store_low(dst + x, y0);
|
||||
dst[x + 2] = v_combine_high(y0, y0).get0();
|
||||
}
|
||||
|
||||
for( ; x < len*cWidth; x += cWidth )
|
||||
{
|
||||
float v0 = src[x], v1 = src[x+1], v2 = src[x+2];
|
||||
float t0 = saturate_cast<float>(m[0]*v0 + m[1]*v1 + m[2]*v2 + m[3]);
|
||||
float t1 = saturate_cast<float>(m[4]*v0 + m[5]*v1 + m[6]*v2 + m[7]);
|
||||
float t2 = saturate_cast<float>(m[8]*v0 + m[9]*v1 + m[10]*v2 + m[11]);
|
||||
dst[x] = t0; dst[x+1] = t1; dst[x+2] = t2;
|
||||
}
|
||||
return;
|
||||
idx[i] = 3*i;
|
||||
idx[i + v_float32::nlanes/4] = 0;
|
||||
}
|
||||
|
||||
if( scn == 4 && dcn == 4 )
|
||||
float _m[] = { m[0], m[4], m[ 8], 0.f,
|
||||
m[1], m[5], m[ 9], 0.f,
|
||||
m[2], m[6], m[10], 0.f,
|
||||
m[3], m[7], m[11], 0.f };
|
||||
v_float32 m0 = vx_lut_quads(_m , idx + v_float32::nlanes/4);
|
||||
v_float32 m1 = vx_lut_quads(_m + 4, idx + v_float32::nlanes/4);
|
||||
v_float32 m2 = vx_lut_quads(_m + 8, idx + v_float32::nlanes/4);
|
||||
v_float32 m3 = vx_lut_quads(_m + 12, idx + v_float32::nlanes/4);
|
||||
for( ; x <= len*3 - v_float32::nlanes; x += 3*v_float32::nlanes/4 )
|
||||
v_store(dst + x, v_pack_triplets(v_matmuladd(vx_lut_quads(src + x, idx), m0, m1, m2, m3)));
|
||||
for( ; x < len*3; x += 3 )
|
||||
{
|
||||
const int cWidth = 4;
|
||||
v_float32x4 m0 = v_float32x4(m[0], m[5], m[10], m[15]);
|
||||
v_float32x4 m1 = v_float32x4(m[1], m[6], m[11], m[16]);
|
||||
v_float32x4 m2 = v_float32x4(m[2], m[7], m[12], m[17]);
|
||||
v_float32x4 m3 = v_float32x4(m[3], m[8], m[13], m[18]);
|
||||
v_float32x4 m4 = v_float32x4(m[4], m[9], m[14], m[19]);
|
||||
|
||||
for( ; x < len*cWidth; x += cWidth )
|
||||
{
|
||||
v_float32x4 x0 = v_load(src + x);
|
||||
v_float32x4 y0 = v_matmul(x0, m0, m1, m2, m3) + m4;
|
||||
v_store(dst + x, y0);
|
||||
}
|
||||
return;
|
||||
float v0 = src[x], v1 = src[x+1], v2 = src[x+2];
|
||||
float t0 = saturate_cast<float>(m[0]*v0 + m[1]*v1 + m[ 2]*v2 + m[ 3]);
|
||||
float t1 = saturate_cast<float>(m[4]*v0 + m[5]*v1 + m[ 6]*v2 + m[ 7]);
|
||||
float t2 = saturate_cast<float>(m[8]*v0 + m[9]*v1 + m[10]*v2 + m[11]);
|
||||
dst[x] = t0; dst[x+1] = t1; dst[x+2] = t2;
|
||||
}
|
||||
vx_cleanup();
|
||||
return;
|
||||
}
|
||||
|
||||
if( scn == 4 && dcn == 4 )
|
||||
{
|
||||
#if CV_SIMD_WIDTH > 16
|
||||
int idx[v_float32::nlanes/4];
|
||||
for( int i = 0; i < v_float32::nlanes/4; i++ )
|
||||
idx[i] = 0;
|
||||
float _m[] = { m[4], m[9], m[14], m[19] };
|
||||
v_float32 m0 = vx_lut_quads(m , idx);
|
||||
v_float32 m1 = vx_lut_quads(m+ 5, idx);
|
||||
v_float32 m2 = vx_lut_quads(m+10, idx);
|
||||
v_float32 m3 = vx_lut_quads(m+15, idx);
|
||||
v_float32 m4 = vx_lut_quads(_m, idx);
|
||||
for( ; x <= len*4 - v_float32::nlanes; x += v_float32::nlanes )
|
||||
{
|
||||
v_float32 v_src = vx_load(src + x);
|
||||
v_store(dst + x, v_reduce_sum4(v_src * m0, v_src * m1, v_src * m2, v_src * m3) + m4);
|
||||
}
|
||||
#endif
|
||||
v_float32x4 _m0 = v_load(m );
|
||||
v_float32x4 _m1 = v_load(m + 5);
|
||||
v_float32x4 _m2 = v_load(m + 10);
|
||||
v_float32x4 _m3 = v_load(m + 15);
|
||||
v_float32x4 _m4(m[4], m[9], m[14], m[19]);
|
||||
for( ; x < len*4; x += v_float32x4::nlanes )
|
||||
{
|
||||
v_float32x4 v_src = v_load(src + x);
|
||||
v_store(dst + x, v_reduce_sum4(v_src * _m0, v_src * _m1, v_src * _m2, v_src * _m3) + _m4);
|
||||
}
|
||||
vx_cleanup();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -519,4 +519,27 @@ TEST_P(Core_EigenZero, double)
|
||||
}
|
||||
INSTANTIATE_TEST_CASE_P(/**/, Core_EigenZero, testing::Values(2, 3, 5));
|
||||
|
||||
TEST(Core_EigenNonSymmetric, convergence)
|
||||
{
|
||||
Matx33d m(
|
||||
0, -1, 0,
|
||||
1, 0, 1,
|
||||
0, -1, 0);
|
||||
Mat eigenvalues, eigenvectors;
|
||||
// eigen values are complex, algorithm doesn't converge
|
||||
try
|
||||
{
|
||||
cv::eigenNonSymmetric(m, eigenvalues, eigenvectors);
|
||||
std::cout << Mat(eigenvalues.t()) << std::endl;
|
||||
}
|
||||
catch (const cv::Exception& e)
|
||||
{
|
||||
EXPECT_EQ(Error::StsNoConv, e.code) << e.what();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
FAIL() << "Unknown exception has been raised";
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
|
||||
@@ -276,17 +276,15 @@ public:
|
||||
public:
|
||||
KMeansDistanceComputer(Distance _distance, const Matrix<ElementType>& _dataset,
|
||||
const int _branching, const int* _indices, const Matrix<double>& _dcenters, const size_t _veclen,
|
||||
int* _count, int* _belongs_to, std::vector<DistanceType>& _radiuses, bool& _converged)
|
||||
std::vector<int> &_new_centroids, std::vector<DistanceType> &_sq_dists)
|
||||
: distance(_distance)
|
||||
, dataset(_dataset)
|
||||
, branching(_branching)
|
||||
, indices(_indices)
|
||||
, dcenters(_dcenters)
|
||||
, veclen(_veclen)
|
||||
, count(_count)
|
||||
, belongs_to(_belongs_to)
|
||||
, radiuses(_radiuses)
|
||||
, converged(_converged)
|
||||
, new_centroids(_new_centroids)
|
||||
, sq_dists(_sq_dists)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -297,8 +295,8 @@ public:
|
||||
|
||||
for( int i = begin; i<end; ++i)
|
||||
{
|
||||
DistanceType sq_dist = distance(dataset[indices[i]], dcenters[0], veclen);
|
||||
int new_centroid = 0;
|
||||
DistanceType sq_dist(distance(dataset[indices[i]], dcenters[0], veclen));
|
||||
int new_centroid(0);
|
||||
for (int j=1; j<branching; ++j) {
|
||||
DistanceType new_sq_dist = distance(dataset[indices[i]], dcenters[j], veclen);
|
||||
if (sq_dist>new_sq_dist) {
|
||||
@@ -306,15 +304,8 @@ public:
|
||||
sq_dist = new_sq_dist;
|
||||
}
|
||||
}
|
||||
if (sq_dist > radiuses[new_centroid]) {
|
||||
radiuses[new_centroid] = sq_dist;
|
||||
}
|
||||
if (new_centroid != belongs_to[i]) {
|
||||
CV_XADD(&count[belongs_to[i]], -1);
|
||||
CV_XADD(&count[new_centroid], 1);
|
||||
belongs_to[i] = new_centroid;
|
||||
converged = false;
|
||||
}
|
||||
sq_dists[i] = sq_dist;
|
||||
new_centroids[i] = new_centroid;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -325,10 +316,8 @@ public:
|
||||
const int* indices;
|
||||
const Matrix<double>& dcenters;
|
||||
const size_t veclen;
|
||||
int* count;
|
||||
int* belongs_to;
|
||||
std::vector<DistanceType>& radiuses;
|
||||
bool& converged;
|
||||
std::vector<int> &new_centroids;
|
||||
std::vector<DistanceType> &sq_dists;
|
||||
KMeansDistanceComputer& operator=( const KMeansDistanceComputer & ) { return *this; }
|
||||
};
|
||||
|
||||
@@ -796,10 +785,27 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<int> new_centroids(indices_length);
|
||||
std::vector<DistanceType> sq_dists(indices_length);
|
||||
|
||||
// reassign points to clusters
|
||||
KMeansDistanceComputer invoker(distance_, dataset_, branching, indices, dcenters, veclen_, count, belongs_to, radiuses, converged);
|
||||
KMeansDistanceComputer invoker(distance_, dataset_, branching, indices, dcenters, veclen_, new_centroids, sq_dists);
|
||||
parallel_for_(cv::Range(0, (int)indices_length), invoker);
|
||||
|
||||
for (int i=0; i < (int)indices_length; ++i) {
|
||||
DistanceType sq_dist(sq_dists[i]);
|
||||
int new_centroid(new_centroids[i]);
|
||||
if (sq_dist > radiuses[new_centroid]) {
|
||||
radiuses[new_centroid] = sq_dist;
|
||||
}
|
||||
if (new_centroid != belongs_to[i]) {
|
||||
count[belongs_to[i]]--;
|
||||
count[new_centroid]++;
|
||||
belongs_to[i] = new_centroid;
|
||||
converged = false;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i<branching; ++i) {
|
||||
// if one cluster converges to an empty cluster,
|
||||
// move an element into that cluster
|
||||
|
||||
Reference in New Issue
Block a user