mirror of
https://github.com/opencv/opencv.git
synced 2026-07-31 00:03:03 +04:00
Merge remote-tracking branch 'upstream/3.4' into merge-3.4
This commit is contained in:
@@ -472,6 +472,9 @@ void v_rshr_pack_store(ushort* ptr, const v_uint32x4& a)
|
||||
|
||||
inline v_uint16x8 v_pack_u(const v_int32x4& a, const v_int32x4& b)
|
||||
{
|
||||
#if CV_SSE4_1
|
||||
return v_uint16x8(_mm_packus_epi32(a.val, b.val));
|
||||
#else
|
||||
__m128i delta32 = _mm_set1_epi32(32768);
|
||||
|
||||
// preliminary saturate negative values to zero
|
||||
@@ -480,34 +483,51 @@ inline v_uint16x8 v_pack_u(const v_int32x4& a, const v_int32x4& b)
|
||||
|
||||
__m128i r = _mm_packs_epi32(_mm_sub_epi32(a1, delta32), _mm_sub_epi32(b1, delta32));
|
||||
return v_uint16x8(_mm_sub_epi16(r, _mm_set1_epi16(-32768)));
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void v_pack_u_store(ushort* ptr, const v_int32x4& a)
|
||||
{
|
||||
#if CV_SSE4_1
|
||||
_mm_storel_epi64((__m128i*)ptr, _mm_packus_epi32(a.val, a.val));
|
||||
#else
|
||||
__m128i delta32 = _mm_set1_epi32(32768);
|
||||
__m128i a1 = _mm_sub_epi32(a.val, delta32);
|
||||
__m128i r = _mm_sub_epi16(_mm_packs_epi32(a1, a1), _mm_set1_epi16(-32768));
|
||||
_mm_storel_epi64((__m128i*)ptr, r);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<int n> inline
|
||||
v_uint16x8 v_rshr_pack_u(const v_int32x4& a, const v_int32x4& b)
|
||||
{
|
||||
#if CV_SSE4_1
|
||||
__m128i delta = _mm_set1_epi32(1 << (n - 1));
|
||||
return v_uint16x8(_mm_packus_epi32(_mm_srai_epi32(_mm_add_epi32(a.val, delta), n),
|
||||
_mm_srai_epi32(_mm_add_epi32(b.val, delta), n)));
|
||||
#else
|
||||
__m128i delta = _mm_set1_epi32(1 << (n-1)), delta32 = _mm_set1_epi32(32768);
|
||||
__m128i a1 = _mm_sub_epi32(_mm_srai_epi32(_mm_add_epi32(a.val, delta), n), delta32);
|
||||
__m128i a2 = _mm_sub_epi16(_mm_packs_epi32(a1, a1), _mm_set1_epi16(-32768));
|
||||
__m128i b1 = _mm_sub_epi32(_mm_srai_epi32(_mm_add_epi32(b.val, delta), n), delta32);
|
||||
__m128i b2 = _mm_sub_epi16(_mm_packs_epi32(b1, b1), _mm_set1_epi16(-32768));
|
||||
return v_uint16x8(_mm_unpacklo_epi64(a2, b2));
|
||||
#endif
|
||||
}
|
||||
|
||||
template<int n> inline
|
||||
void v_rshr_pack_u_store(ushort* ptr, const v_int32x4& a)
|
||||
{
|
||||
#if CV_SSE4_1
|
||||
__m128i delta = _mm_set1_epi32(1 << (n - 1));
|
||||
__m128i a1 = _mm_srai_epi32(_mm_add_epi32(a.val, delta), n);
|
||||
_mm_storel_epi64((__m128i*)ptr, _mm_packus_epi32(a1, a1));
|
||||
#else
|
||||
__m128i delta = _mm_set1_epi32(1 << (n-1)), delta32 = _mm_set1_epi32(32768);
|
||||
__m128i a1 = _mm_sub_epi32(_mm_srai_epi32(_mm_add_epi32(a.val, delta), n), delta32);
|
||||
__m128i a2 = _mm_sub_epi16(_mm_packs_epi32(a1, a1), _mm_set1_epi16(-32768));
|
||||
_mm_storel_epi64((__m128i*)ptr, a2);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline v_int16x8 v_pack(const v_int32x4& a, const v_int32x4& b)
|
||||
|
||||
@@ -4776,6 +4776,10 @@ public:
|
||||
|
||||
void deallocate_(UMatData* u) const
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (cv::__termination) // process is not in consistent state (after ExitProcess call) and terminating
|
||||
return; // avoid any OpenCL calls
|
||||
#endif
|
||||
if(u->tempUMat())
|
||||
{
|
||||
CV_Assert(u->origdata);
|
||||
|
||||
@@ -447,7 +447,16 @@ static int numThreads = -1;
|
||||
#elif defined HAVE_HPX
|
||||
// nothing for HPX
|
||||
#elif defined HAVE_OPENMP
|
||||
static int numThreadsMax = omp_get_max_threads();
|
||||
static inline int _initMaxThreads()
|
||||
{
|
||||
int maxThreads = omp_get_max_threads();
|
||||
if (!utils::getConfigurationParameterBool("OPENCV_FOR_OPENMP_DYNAMIC_DISABLE", false))
|
||||
{
|
||||
omp_set_dynamic(maxThreads);
|
||||
}
|
||||
return numThreads;
|
||||
}
|
||||
static int numThreadsMax = _initMaxThreads();
|
||||
#elif defined HAVE_GCD
|
||||
// nothing for GCD
|
||||
#elif defined WINRT
|
||||
|
||||
@@ -298,8 +298,9 @@ TLSData<CoreTLSData>& getCoreTlsData();
|
||||
#define CL_RUNTIME_EXPORT
|
||||
#endif
|
||||
|
||||
extern bool __termination; // skip some cleanups, because process is terminating
|
||||
// (for example, if ExitProcess() was already called)
|
||||
extern CV_EXPORTS
|
||||
bool __termination; // skip some cleanups, because process is terminating
|
||||
// (for example, if ExitProcess() was already called)
|
||||
|
||||
cv::Mutex& getInitializationMutex();
|
||||
|
||||
|
||||
+168
-627
@@ -43,6 +43,7 @@
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include "opencl_kernels_imgproc.hpp"
|
||||
#include "opencv2/core/hal/intrin.hpp"
|
||||
|
||||
#include "opencv2/core/openvx/ovx_defs.hpp"
|
||||
|
||||
@@ -73,69 +74,55 @@ template<typename T1, typename T2> struct PyrUpNoVec
|
||||
int operator()(T1**, T2**, int, int) const { return 0; }
|
||||
};
|
||||
|
||||
#if CV_SSE2
|
||||
#if CV_SIMD
|
||||
|
||||
struct PyrDownVec_32s8u
|
||||
{
|
||||
int operator()(int** src, uchar* dst, int, int width) const
|
||||
{
|
||||
if( !checkHardwareSupport(CV_CPU_SSE2) )
|
||||
return 0;
|
||||
|
||||
int x = 0;
|
||||
const int *row0 = src[0], *row1 = src[1], *row2 = src[2], *row3 = src[3], *row4 = src[4];
|
||||
__m128i delta = _mm_set1_epi16(128);
|
||||
|
||||
for( ; x <= width - 16; x += 16 )
|
||||
for( ; x <= width - v_uint8::nlanes; x += v_uint8::nlanes )
|
||||
{
|
||||
__m128i r0, r1, r2, r3, r4, t0, t1;
|
||||
r0 = _mm_packs_epi32(_mm_load_si128((const __m128i*)(row0 + x)),
|
||||
_mm_load_si128((const __m128i*)(row0 + x + 4)));
|
||||
r1 = _mm_packs_epi32(_mm_load_si128((const __m128i*)(row1 + x)),
|
||||
_mm_load_si128((const __m128i*)(row1 + x + 4)));
|
||||
r2 = _mm_packs_epi32(_mm_load_si128((const __m128i*)(row2 + x)),
|
||||
_mm_load_si128((const __m128i*)(row2 + x + 4)));
|
||||
r3 = _mm_packs_epi32(_mm_load_si128((const __m128i*)(row3 + x)),
|
||||
_mm_load_si128((const __m128i*)(row3 + x + 4)));
|
||||
r4 = _mm_packs_epi32(_mm_load_si128((const __m128i*)(row4 + x)),
|
||||
_mm_load_si128((const __m128i*)(row4 + x + 4)));
|
||||
r0 = _mm_add_epi16(r0, r4);
|
||||
r1 = _mm_add_epi16(_mm_add_epi16(r1, r3), r2);
|
||||
r0 = _mm_add_epi16(r0, _mm_add_epi16(r2, r2));
|
||||
t0 = _mm_add_epi16(r0, _mm_slli_epi16(r1, 2));
|
||||
r0 = _mm_packs_epi32(_mm_load_si128((const __m128i*)(row0 + x + 8)),
|
||||
_mm_load_si128((const __m128i*)(row0 + x + 12)));
|
||||
r1 = _mm_packs_epi32(_mm_load_si128((const __m128i*)(row1 + x + 8)),
|
||||
_mm_load_si128((const __m128i*)(row1 + x + 12)));
|
||||
r2 = _mm_packs_epi32(_mm_load_si128((const __m128i*)(row2 + x + 8)),
|
||||
_mm_load_si128((const __m128i*)(row2 + x + 12)));
|
||||
r3 = _mm_packs_epi32(_mm_load_si128((const __m128i*)(row3 + x + 8)),
|
||||
_mm_load_si128((const __m128i*)(row3 + x + 12)));
|
||||
r4 = _mm_packs_epi32(_mm_load_si128((const __m128i*)(row4 + x + 8)),
|
||||
_mm_load_si128((const __m128i*)(row4 + x + 12)));
|
||||
r0 = _mm_add_epi16(r0, r4);
|
||||
r1 = _mm_add_epi16(_mm_add_epi16(r1, r3), r2);
|
||||
r0 = _mm_add_epi16(r0, _mm_add_epi16(r2, r2));
|
||||
t1 = _mm_add_epi16(r0, _mm_slli_epi16(r1, 2));
|
||||
t0 = _mm_srli_epi16(_mm_add_epi16(t0, delta), 8);
|
||||
t1 = _mm_srli_epi16(_mm_add_epi16(t1, delta), 8);
|
||||
_mm_storeu_si128((__m128i*)(dst + x), _mm_packus_epi16(t0, t1));
|
||||
v_uint16 r0, r1, r2, r3, r4, t0, t1;
|
||||
r0 = v_reinterpret_as_u16(v_pack(vx_load(row0 + x), vx_load(row0 + x + v_int32::nlanes)));
|
||||
r1 = v_reinterpret_as_u16(v_pack(vx_load(row1 + x), vx_load(row1 + x + v_int32::nlanes)));
|
||||
r2 = v_reinterpret_as_u16(v_pack(vx_load(row2 + x), vx_load(row2 + x + v_int32::nlanes)));
|
||||
r3 = v_reinterpret_as_u16(v_pack(vx_load(row3 + x), vx_load(row3 + x + v_int32::nlanes)));
|
||||
r4 = v_reinterpret_as_u16(v_pack(vx_load(row4 + x), vx_load(row4 + x + v_int32::nlanes)));
|
||||
t0 = r0 + r4 + (r2 + r2) + ((r1 + r3 + r2) << 2);
|
||||
r0 = v_reinterpret_as_u16(v_pack(vx_load(row0 + x + 2*v_int32::nlanes), vx_load(row0 + x + 3*v_int32::nlanes)));
|
||||
r1 = v_reinterpret_as_u16(v_pack(vx_load(row1 + x + 2*v_int32::nlanes), vx_load(row1 + x + 3*v_int32::nlanes)));
|
||||
r2 = v_reinterpret_as_u16(v_pack(vx_load(row2 + x + 2*v_int32::nlanes), vx_load(row2 + x + 3*v_int32::nlanes)));
|
||||
r3 = v_reinterpret_as_u16(v_pack(vx_load(row3 + x + 2*v_int32::nlanes), vx_load(row3 + x + 3*v_int32::nlanes)));
|
||||
r4 = v_reinterpret_as_u16(v_pack(vx_load(row4 + x + 2*v_int32::nlanes), vx_load(row4 + x + 3*v_int32::nlanes)));
|
||||
t1 = r0 + r4 + (r2 + r2) + ((r1 + r3 + r2) << 2);
|
||||
v_store(dst + x, v_rshr_pack<8>(t0, t1));
|
||||
}
|
||||
|
||||
for( ; x <= width - 4; x += 4 )
|
||||
if (x <= width - v_int16::nlanes)
|
||||
{
|
||||
__m128i r0, r1, r2, r3, r4, z = _mm_setzero_si128();
|
||||
r0 = _mm_packs_epi32(_mm_load_si128((const __m128i*)(row0 + x)), z);
|
||||
r1 = _mm_packs_epi32(_mm_load_si128((const __m128i*)(row1 + x)), z);
|
||||
r2 = _mm_packs_epi32(_mm_load_si128((const __m128i*)(row2 + x)), z);
|
||||
r3 = _mm_packs_epi32(_mm_load_si128((const __m128i*)(row3 + x)), z);
|
||||
r4 = _mm_packs_epi32(_mm_load_si128((const __m128i*)(row4 + x)), z);
|
||||
r0 = _mm_add_epi16(r0, r4);
|
||||
r1 = _mm_add_epi16(_mm_add_epi16(r1, r3), r2);
|
||||
r0 = _mm_add_epi16(r0, _mm_add_epi16(r2, r2));
|
||||
r0 = _mm_add_epi16(r0, _mm_slli_epi16(r1, 2));
|
||||
r0 = _mm_srli_epi16(_mm_add_epi16(r0, delta), 8);
|
||||
*(int*)(dst + x) = _mm_cvtsi128_si32(_mm_packus_epi16(r0, r0));
|
||||
v_uint16 r0, r1, r2, r3, r4, t0;
|
||||
r0 = v_reinterpret_as_u16(v_pack(vx_load(row0 + x), vx_load(row0 + x + v_int32::nlanes)));
|
||||
r1 = v_reinterpret_as_u16(v_pack(vx_load(row1 + x), vx_load(row1 + x + v_int32::nlanes)));
|
||||
r2 = v_reinterpret_as_u16(v_pack(vx_load(row2 + x), vx_load(row2 + x + v_int32::nlanes)));
|
||||
r3 = v_reinterpret_as_u16(v_pack(vx_load(row3 + x), vx_load(row3 + x + v_int32::nlanes)));
|
||||
r4 = v_reinterpret_as_u16(v_pack(vx_load(row4 + x), vx_load(row4 + x + v_int32::nlanes)));
|
||||
t0 = r0 + r4 + (r2 + r2) + ((r1 + r3 + r2) << 2);
|
||||
v_rshr_pack_store<8>(dst + x, t0);
|
||||
x += v_uint16::nlanes;
|
||||
}
|
||||
for ( ; x <= width - v_int32x4::nlanes; x += v_int32x4::nlanes)
|
||||
{
|
||||
v_int32x4 r0, r1, r2, r3, r4, t0;
|
||||
r0 = v_load(row0 + x);
|
||||
r1 = v_load(row1 + x);
|
||||
r2 = v_load(row2 + x);
|
||||
r3 = v_load(row3 + x);
|
||||
r4 = v_load(row4 + x);
|
||||
t0 = r0 + r4 + (r2 + r2) + ((r1 + r3 + r2) << 2);
|
||||
|
||||
*(int*)(dst + x) = v_reinterpret_as_s32(v_rshr_pack<8>(v_pack_u(t0, t0), v_setzero_u16())).get0();
|
||||
}
|
||||
|
||||
return x;
|
||||
@@ -146,152 +133,105 @@ struct PyrDownVec_32f
|
||||
{
|
||||
int operator()(float** src, float* dst, int, int width) const
|
||||
{
|
||||
if( !checkHardwareSupport(CV_CPU_SSE) )
|
||||
return 0;
|
||||
|
||||
int x = 0;
|
||||
const float *row0 = src[0], *row1 = src[1], *row2 = src[2], *row3 = src[3], *row4 = src[4];
|
||||
__m128 _4 = _mm_set1_ps(4.f), _scale = _mm_set1_ps(1.f/256);
|
||||
for( ; x <= width - 8; x += 8 )
|
||||
|
||||
v_float32 _4 = vx_setall_f32(4.f), _scale = vx_setall_f32(1.f/256);
|
||||
for( ; x <= width - v_float32::nlanes; x += v_float32::nlanes)
|
||||
{
|
||||
__m128 r0, r1, r2, r3, r4, t0, t1;
|
||||
r0 = _mm_load_ps(row0 + x);
|
||||
r1 = _mm_load_ps(row1 + x);
|
||||
r2 = _mm_load_ps(row2 + x);
|
||||
r3 = _mm_load_ps(row3 + x);
|
||||
r4 = _mm_load_ps(row4 + x);
|
||||
r0 = _mm_add_ps(r0, r4);
|
||||
r1 = _mm_add_ps(_mm_add_ps(r1, r3), r2);
|
||||
r0 = _mm_add_ps(r0, _mm_add_ps(r2, r2));
|
||||
t0 = _mm_add_ps(r0, _mm_mul_ps(r1, _4));
|
||||
|
||||
r0 = _mm_load_ps(row0 + x + 4);
|
||||
r1 = _mm_load_ps(row1 + x + 4);
|
||||
r2 = _mm_load_ps(row2 + x + 4);
|
||||
r3 = _mm_load_ps(row3 + x + 4);
|
||||
r4 = _mm_load_ps(row4 + x + 4);
|
||||
r0 = _mm_add_ps(r0, r4);
|
||||
r1 = _mm_add_ps(_mm_add_ps(r1, r3), r2);
|
||||
r0 = _mm_add_ps(r0, _mm_add_ps(r2, r2));
|
||||
t1 = _mm_add_ps(r0, _mm_mul_ps(r1, _4));
|
||||
|
||||
t0 = _mm_mul_ps(t0, _scale);
|
||||
t1 = _mm_mul_ps(t1, _scale);
|
||||
|
||||
_mm_storeu_ps(dst + x, t0);
|
||||
_mm_storeu_ps(dst + x + 4, t1);
|
||||
v_float32 r0, r1, r2, r3, r4;
|
||||
r0 = vx_load(row0 + x);
|
||||
r1 = vx_load(row1 + x);
|
||||
r2 = vx_load(row2 + x);
|
||||
r3 = vx_load(row3 + x);
|
||||
r4 = vx_load(row4 + x);
|
||||
v_store(dst + x, v_muladd(r1 + r3 + r2, _4, r0 + r4 + (r2 + r2)) * _scale);
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
};
|
||||
|
||||
#if CV_SSE4_1
|
||||
#if CV_SSE4_1 || CV_NEON
|
||||
|
||||
struct PyrDownVec_32s16u
|
||||
{
|
||||
PyrDownVec_32s16u()
|
||||
{
|
||||
haveSSE = checkHardwareSupport(CV_CPU_SSE4_1);
|
||||
}
|
||||
|
||||
int operator()(int** src, ushort* dst, int, int width) const
|
||||
{
|
||||
int x = 0;
|
||||
|
||||
if (!haveSSE)
|
||||
return x;
|
||||
|
||||
const int *row0 = src[0], *row1 = src[1], *row2 = src[2], *row3 = src[3], *row4 = src[4];
|
||||
__m128i v_delta = _mm_set1_epi32(128);
|
||||
|
||||
for( ; x <= width - 8; x += 8 )
|
||||
for( ; x <= width - v_uint16::nlanes; x += v_uint16::nlanes)
|
||||
{
|
||||
__m128i v_r00 = _mm_loadu_si128((__m128i const *)(row0 + x)),
|
||||
v_r01 = _mm_loadu_si128((__m128i const *)(row0 + x + 4));
|
||||
__m128i v_r10 = _mm_loadu_si128((__m128i const *)(row1 + x)),
|
||||
v_r11 = _mm_loadu_si128((__m128i const *)(row1 + x + 4));
|
||||
__m128i v_r20 = _mm_loadu_si128((__m128i const *)(row2 + x)),
|
||||
v_r21 = _mm_loadu_si128((__m128i const *)(row2 + x + 4));
|
||||
__m128i v_r30 = _mm_loadu_si128((__m128i const *)(row3 + x)),
|
||||
v_r31 = _mm_loadu_si128((__m128i const *)(row3 + x + 4));
|
||||
__m128i v_r40 = _mm_loadu_si128((__m128i const *)(row4 + x)),
|
||||
v_r41 = _mm_loadu_si128((__m128i const *)(row4 + x + 4));
|
||||
|
||||
v_r00 = _mm_add_epi32(_mm_add_epi32(v_r00, v_r40), _mm_add_epi32(v_r20, v_r20));
|
||||
v_r10 = _mm_add_epi32(_mm_add_epi32(v_r10, v_r20), v_r30);
|
||||
|
||||
v_r10 = _mm_slli_epi32(v_r10, 2);
|
||||
__m128i v_dst0 = _mm_srli_epi32(_mm_add_epi32(_mm_add_epi32(v_r00, v_r10), v_delta), 8);
|
||||
|
||||
v_r01 = _mm_add_epi32(_mm_add_epi32(v_r01, v_r41), _mm_add_epi32(v_r21, v_r21));
|
||||
v_r11 = _mm_add_epi32(_mm_add_epi32(v_r11, v_r21), v_r31);
|
||||
v_r11 = _mm_slli_epi32(v_r11, 2);
|
||||
__m128i v_dst1 = _mm_srli_epi32(_mm_add_epi32(_mm_add_epi32(v_r01, v_r11), v_delta), 8);
|
||||
|
||||
_mm_storeu_si128((__m128i *)(dst + x), _mm_packus_epi32(v_dst0, v_dst1));
|
||||
v_int32 r00 = vx_load(row0 + x),
|
||||
r01 = vx_load(row0 + x + v_int32::nlanes),
|
||||
r10 = vx_load(row1 + x),
|
||||
r11 = vx_load(row1 + x + v_int32::nlanes),
|
||||
r20 = vx_load(row2 + x),
|
||||
r21 = vx_load(row2 + x + v_int32::nlanes),
|
||||
r30 = vx_load(row3 + x),
|
||||
r31 = vx_load(row3 + x + v_int32::nlanes),
|
||||
r40 = vx_load(row4 + x),
|
||||
r41 = vx_load(row4 + x + v_int32::nlanes);
|
||||
v_store(dst + x, v_rshr_pack_u<8>(r00 + r40 + (r20 + r20) + ((r10 + r20 + r30) << 2),
|
||||
r01 + r41 + (r21 + r21) + ((r11 + r21 + r31) << 2)));
|
||||
}
|
||||
if (x <= width - v_int32::nlanes)
|
||||
{
|
||||
v_int32 r00 = vx_load(row0 + x),
|
||||
r10 = vx_load(row1 + x),
|
||||
r20 = vx_load(row2 + x),
|
||||
r30 = vx_load(row3 + x),
|
||||
r40 = vx_load(row4 + x);
|
||||
v_rshr_pack_u_store<8>(dst + x, r00 + r40 + (r20 + r20) + ((r10 + r20 + r30) << 2));
|
||||
x += v_int32::nlanes;
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
bool haveSSE;
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
typedef PyrDownNoVec<int, ushort> PyrDownVec_32s16u;
|
||||
|
||||
#endif // CV_SSE4_1
|
||||
#endif
|
||||
|
||||
struct PyrDownVec_32s16s
|
||||
{
|
||||
PyrDownVec_32s16s()
|
||||
{
|
||||
haveSSE = checkHardwareSupport(CV_CPU_SSE2);
|
||||
}
|
||||
|
||||
int operator()(int** src, short* dst, int, int width) const
|
||||
{
|
||||
int x = 0;
|
||||
|
||||
if (!haveSSE)
|
||||
return x;
|
||||
|
||||
const int *row0 = src[0], *row1 = src[1], *row2 = src[2], *row3 = src[3], *row4 = src[4];
|
||||
__m128i v_delta = _mm_set1_epi32(128);
|
||||
|
||||
for( ; x <= width - 8; x += 8 )
|
||||
for( ; x <= width - v_int16::nlanes; x += v_int16::nlanes)
|
||||
{
|
||||
__m128i v_r00 = _mm_loadu_si128((__m128i const *)(row0 + x)),
|
||||
v_r01 = _mm_loadu_si128((__m128i const *)(row0 + x + 4));
|
||||
__m128i v_r10 = _mm_loadu_si128((__m128i const *)(row1 + x)),
|
||||
v_r11 = _mm_loadu_si128((__m128i const *)(row1 + x + 4));
|
||||
__m128i v_r20 = _mm_loadu_si128((__m128i const *)(row2 + x)),
|
||||
v_r21 = _mm_loadu_si128((__m128i const *)(row2 + x + 4));
|
||||
__m128i v_r30 = _mm_loadu_si128((__m128i const *)(row3 + x)),
|
||||
v_r31 = _mm_loadu_si128((__m128i const *)(row3 + x + 4));
|
||||
__m128i v_r40 = _mm_loadu_si128((__m128i const *)(row4 + x)),
|
||||
v_r41 = _mm_loadu_si128((__m128i const *)(row4 + x + 4));
|
||||
|
||||
v_r00 = _mm_add_epi32(_mm_add_epi32(v_r00, v_r40), _mm_add_epi32(v_r20, v_r20));
|
||||
v_r10 = _mm_add_epi32(_mm_add_epi32(v_r10, v_r20), v_r30);
|
||||
|
||||
v_r10 = _mm_slli_epi32(v_r10, 2);
|
||||
__m128i v_dst0 = _mm_srai_epi32(_mm_add_epi32(_mm_add_epi32(v_r00, v_r10), v_delta), 8);
|
||||
|
||||
v_r01 = _mm_add_epi32(_mm_add_epi32(v_r01, v_r41), _mm_add_epi32(v_r21, v_r21));
|
||||
v_r11 = _mm_add_epi32(_mm_add_epi32(v_r11, v_r21), v_r31);
|
||||
v_r11 = _mm_slli_epi32(v_r11, 2);
|
||||
__m128i v_dst1 = _mm_srai_epi32(_mm_add_epi32(_mm_add_epi32(v_r01, v_r11), v_delta), 8);
|
||||
|
||||
_mm_storeu_si128((__m128i *)(dst + x), _mm_packs_epi32(v_dst0, v_dst1));
|
||||
v_int32 r00 = vx_load(row0 + x),
|
||||
r01 = vx_load(row0 + x + v_int32::nlanes),
|
||||
r10 = vx_load(row1 + x),
|
||||
r11 = vx_load(row1 + x + v_int32::nlanes),
|
||||
r20 = vx_load(row2 + x),
|
||||
r21 = vx_load(row2 + x + v_int32::nlanes),
|
||||
r30 = vx_load(row3 + x),
|
||||
r31 = vx_load(row3 + x + v_int32::nlanes),
|
||||
r40 = vx_load(row4 + x),
|
||||
r41 = vx_load(row4 + x + v_int32::nlanes);
|
||||
v_store(dst + x, v_rshr_pack<8>(r00 + r40 + (r20 + r20) + ((r10 + r20 + r30) << 2),
|
||||
r01 + r41 + (r21 + r21) + ((r11 + r21 + r31) << 2)));
|
||||
}
|
||||
if (x <= width - v_int32::nlanes)
|
||||
{
|
||||
v_int32 r00 = vx_load(row0 + x),
|
||||
r10 = vx_load(row1 + x),
|
||||
r20 = vx_load(row2 + x),
|
||||
r30 = vx_load(row3 + x),
|
||||
r40 = vx_load(row4 + x);
|
||||
v_rshr_pack_store<8>(dst + x, r00 + r40 + (r20 + r20) + ((r10 + r20 + r30) << 2));
|
||||
x += v_int32::nlanes;
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
bool haveSSE;
|
||||
};
|
||||
|
||||
struct PyrUpVec_32s8u
|
||||
@@ -299,59 +239,40 @@ struct PyrUpVec_32s8u
|
||||
int operator()(int** src, uchar** dst, int, int width) const
|
||||
{
|
||||
int x = 0;
|
||||
|
||||
if (!checkHardwareSupport(CV_CPU_SSE2))
|
||||
return x;
|
||||
|
||||
uchar *dst0 = dst[0], *dst1 = dst[1];
|
||||
const uint *row0 = (uint *)src[0], *row1 = (uint *)src[1], *row2 = (uint *)src[2];
|
||||
__m128i v_delta = _mm_set1_epi16(32), v_zero = _mm_setzero_si128();
|
||||
const int *row0 = src[0], *row1 = src[1], *row2 = src[2];
|
||||
|
||||
for( ; x <= width - 16; x += 16 )
|
||||
for( ; x <= width - v_uint8::nlanes; x += v_uint8::nlanes)
|
||||
{
|
||||
__m128i v_r0 = _mm_packs_epi32(_mm_loadu_si128((__m128i const *)(row0 + x)),
|
||||
_mm_loadu_si128((__m128i const *)(row0 + x + 4)));
|
||||
__m128i v_r1 = _mm_packs_epi32(_mm_loadu_si128((__m128i const *)(row1 + x)),
|
||||
_mm_loadu_si128((__m128i const *)(row1 + x + 4)));
|
||||
__m128i v_r2 = _mm_packs_epi32(_mm_loadu_si128((__m128i const *)(row2 + x)),
|
||||
_mm_loadu_si128((__m128i const *)(row2 + x + 4)));
|
||||
|
||||
__m128i v_2r1 = _mm_adds_epu16(v_r1, v_r1), v_4r1 = _mm_adds_epu16(v_2r1, v_2r1);
|
||||
__m128i v_dst00 = _mm_adds_epu16(_mm_adds_epu16(v_r0, v_r2), _mm_adds_epu16(v_2r1, v_4r1));
|
||||
__m128i v_dst10 = _mm_slli_epi16(_mm_adds_epu16(v_r1, v_r2), 2);
|
||||
|
||||
v_r0 = _mm_packs_epi32(_mm_loadu_si128((__m128i const *)(row0 + x + 8)),
|
||||
_mm_loadu_si128((__m128i const *)(row0 + x + 12)));
|
||||
v_r1 = _mm_packs_epi32(_mm_loadu_si128((__m128i const *)(row1 + x + 8)),
|
||||
_mm_loadu_si128((__m128i const *)(row1 + x + 12)));
|
||||
v_r2 = _mm_packs_epi32(_mm_loadu_si128((__m128i const *)(row2 + x + 8)),
|
||||
_mm_loadu_si128((__m128i const *)(row2 + x + 12)));
|
||||
|
||||
v_2r1 = _mm_adds_epu16(v_r1, v_r1), v_4r1 = _mm_adds_epu16(v_2r1, v_2r1);
|
||||
__m128i v_dst01 = _mm_adds_epu16(_mm_adds_epu16(v_r0, v_r2), _mm_adds_epu16(v_2r1, v_4r1));
|
||||
__m128i v_dst11 = _mm_slli_epi16(_mm_adds_epu16(v_r1, v_r2), 2);
|
||||
|
||||
_mm_storeu_si128((__m128i *)(dst0 + x), _mm_packus_epi16(_mm_srli_epi16(_mm_adds_epu16(v_dst00, v_delta), 6),
|
||||
_mm_srli_epi16(_mm_adds_epu16(v_dst01, v_delta), 6)));
|
||||
_mm_storeu_si128((__m128i *)(dst1 + x), _mm_packus_epi16(_mm_srli_epi16(_mm_adds_epu16(v_dst10, v_delta), 6),
|
||||
_mm_srli_epi16(_mm_adds_epu16(v_dst11, v_delta), 6)));
|
||||
v_int16 v_r00 = v_pack(vx_load(row0 + x), vx_load(row0 + x + v_int32::nlanes)),
|
||||
v_r01 = v_pack(vx_load(row0 + x + 2 * v_int32::nlanes), vx_load(row0 + x + 3 * v_int32::nlanes)),
|
||||
v_r10 = v_pack(vx_load(row1 + x), vx_load(row1 + x + v_int32::nlanes)),
|
||||
v_r11 = v_pack(vx_load(row1 + x + 2 * v_int32::nlanes), vx_load(row1 + x + 3 * v_int32::nlanes)),
|
||||
v_r20 = v_pack(vx_load(row2 + x), vx_load(row2 + x + v_int32::nlanes)),
|
||||
v_r21 = v_pack(vx_load(row2 + x + 2 * v_int32::nlanes), vx_load(row2 + x + 3 * v_int32::nlanes));
|
||||
v_int16 v_2r10 = v_r10 + v_r10, v_2r11 = (v_r11 + v_r11);
|
||||
v_store(dst0 + x, v_rshr_pack_u<6>(v_r00 + v_r20 + (v_2r10 + v_2r10 + v_2r10), v_r01 + v_r21 + (v_2r11 + v_2r11 + v_2r11)));
|
||||
v_store(dst1 + x, v_rshr_pack_u<6>((v_r10 + v_r20) << 2, (v_r11 + v_r21) << 2));
|
||||
}
|
||||
|
||||
for( ; x <= width - 8; x += 8 )
|
||||
if(x <= width - v_uint16::nlanes)
|
||||
{
|
||||
__m128i v_r0 = _mm_packs_epi32(_mm_loadu_si128((__m128i const *)(row0 + x)),
|
||||
_mm_loadu_si128((__m128i const *)(row0 + x + 4)));
|
||||
__m128i v_r1 = _mm_packs_epi32(_mm_loadu_si128((__m128i const *)(row1 + x)),
|
||||
_mm_loadu_si128((__m128i const *)(row1 + x + 4)));
|
||||
__m128i v_r2 = _mm_packs_epi32(_mm_loadu_si128((__m128i const *)(row2 + x)),
|
||||
_mm_loadu_si128((__m128i const *)(row2 + x + 4)));
|
||||
|
||||
__m128i v_2r1 = _mm_adds_epu16(v_r1, v_r1), v_4r1 = _mm_adds_epu16(v_2r1, v_2r1);
|
||||
__m128i v_dst0 = _mm_adds_epu16(_mm_adds_epu16(v_r0, v_r2), _mm_adds_epu16(v_2r1, v_4r1));
|
||||
__m128i v_dst1 = _mm_slli_epi16(_mm_adds_epu16(v_r1, v_r2), 2);
|
||||
|
||||
_mm_storel_epi64((__m128i *)(dst0 + x), _mm_packus_epi16(_mm_srli_epi16(_mm_adds_epu16(v_dst0, v_delta), 6), v_zero));
|
||||
_mm_storel_epi64((__m128i *)(dst1 + x), _mm_packus_epi16(_mm_srli_epi16(_mm_adds_epu16(v_dst1, v_delta), 6), v_zero));
|
||||
v_int16 v_r00 = v_pack(vx_load(row0 + x), vx_load(row0 + x + v_int32::nlanes)),
|
||||
v_r10 = v_pack(vx_load(row1 + x), vx_load(row1 + x + v_int32::nlanes)),
|
||||
v_r20 = v_pack(vx_load(row2 + x), vx_load(row2 + x + v_int32::nlanes));
|
||||
v_int16 v_2r10 = v_r10 + v_r10;
|
||||
v_rshr_pack_u_store<6>(dst0 + x, v_r00 + v_r20 + (v_2r10 + v_2r10 + v_2r10));
|
||||
v_rshr_pack_u_store<6>(dst1 + x, (v_r10 + v_r20) << 2);
|
||||
x += v_uint16::nlanes;
|
||||
}
|
||||
for (; x <= width - v_int32x4::nlanes; x += v_int32x4::nlanes)
|
||||
{
|
||||
v_int32 v_r00 = vx_load(row0 + x),
|
||||
v_r10 = vx_load(row1 + x),
|
||||
v_r20 = vx_load(row2 + x);
|
||||
v_int32 v_2r10 = v_r10 + v_r10;
|
||||
v_int16 d = v_pack(v_r00 + v_r20 + (v_2r10 + v_2r10 + v_2r10), (v_r10 + v_r20) << 2);
|
||||
*(int*)(dst0 + x) = v_reinterpret_as_s32(v_rshr_pack_u<6>(d, vx_setzero_s16())).get0();
|
||||
*(int*)(dst1 + x) = v_reinterpret_as_s32(v_rshr_pack_u<6>(v_combine_high(d, d), vx_setzero_s16())).get0();
|
||||
}
|
||||
|
||||
return x;
|
||||
@@ -363,113 +284,63 @@ struct PyrUpVec_32s16s
|
||||
int operator()(int** src, short** dst, int, int width) const
|
||||
{
|
||||
int x = 0;
|
||||
|
||||
if (!checkHardwareSupport(CV_CPU_SSE2))
|
||||
return x;
|
||||
|
||||
short *dst0 = dst[0], *dst1 = dst[1];
|
||||
const uint *row0 = (uint *)src[0], *row1 = (uint *)src[1], *row2 = (uint *)src[2];
|
||||
__m128i v_delta = _mm_set1_epi32(32), v_zero = _mm_setzero_si128();
|
||||
const int *row0 = src[0], *row1 = src[1], *row2 = src[2];
|
||||
|
||||
for( ; x <= width - 8; x += 8 )
|
||||
for( ; x <= width - v_int16::nlanes; x += v_int16::nlanes)
|
||||
{
|
||||
__m128i v_r0 = _mm_loadu_si128((__m128i const *)(row0 + x)),
|
||||
v_r1 = _mm_loadu_si128((__m128i const *)(row1 + x)),
|
||||
v_r2 = _mm_loadu_si128((__m128i const *)(row2 + x));
|
||||
__m128i v_2r1 = _mm_slli_epi32(v_r1, 1), v_4r1 = _mm_slli_epi32(v_r1, 2);
|
||||
__m128i v_dst00 = _mm_add_epi32(_mm_add_epi32(v_r0, v_r2), _mm_add_epi32(v_2r1, v_4r1));
|
||||
__m128i v_dst10 = _mm_slli_epi32(_mm_add_epi32(v_r1, v_r2), 2);
|
||||
|
||||
v_r0 = _mm_loadu_si128((__m128i const *)(row0 + x + 4));
|
||||
v_r1 = _mm_loadu_si128((__m128i const *)(row1 + x + 4));
|
||||
v_r2 = _mm_loadu_si128((__m128i const *)(row2 + x + 4));
|
||||
v_2r1 = _mm_slli_epi32(v_r1, 1);
|
||||
v_4r1 = _mm_slli_epi32(v_r1, 2);
|
||||
__m128i v_dst01 = _mm_add_epi32(_mm_add_epi32(v_r0, v_r2), _mm_add_epi32(v_2r1, v_4r1));
|
||||
__m128i v_dst11 = _mm_slli_epi32(_mm_add_epi32(v_r1, v_r2), 2);
|
||||
|
||||
_mm_storeu_si128((__m128i *)(dst0 + x),
|
||||
_mm_packs_epi32(_mm_srai_epi32(_mm_add_epi32(v_dst00, v_delta), 6),
|
||||
_mm_srai_epi32(_mm_add_epi32(v_dst01, v_delta), 6)));
|
||||
_mm_storeu_si128((__m128i *)(dst1 + x),
|
||||
_mm_packs_epi32(_mm_srai_epi32(_mm_add_epi32(v_dst10, v_delta), 6),
|
||||
_mm_srai_epi32(_mm_add_epi32(v_dst11, v_delta), 6)));
|
||||
v_int32 v_r00 = vx_load(row0 + x),
|
||||
v_r01 = vx_load(row0 + x + v_int32::nlanes),
|
||||
v_r10 = vx_load(row1 + x),
|
||||
v_r11 = vx_load(row1 + x + v_int32::nlanes),
|
||||
v_r20 = vx_load(row2 + x),
|
||||
v_r21 = vx_load(row2 + x + v_int32::nlanes);
|
||||
v_store(dst0 + x, v_rshr_pack<6>(v_r00 + v_r20 + ((v_r10 << 1) + (v_r10 << 2)), v_r01 + v_r21 + ((v_r11 << 1) + (v_r11 << 2))));
|
||||
v_store(dst1 + x, v_rshr_pack<6>((v_r10 + v_r20) << 2, (v_r11 + v_r21) << 2));
|
||||
}
|
||||
|
||||
for( ; x <= width - 4; x += 4 )
|
||||
if(x <= width - v_int32::nlanes)
|
||||
{
|
||||
__m128i v_r0 = _mm_loadu_si128((__m128i const *)(row0 + x)),
|
||||
v_r1 = _mm_loadu_si128((__m128i const *)(row1 + x)),
|
||||
v_r2 = _mm_loadu_si128((__m128i const *)(row2 + x));
|
||||
__m128i v_2r1 = _mm_slli_epi32(v_r1, 1), v_4r1 = _mm_slli_epi32(v_r1, 2);
|
||||
|
||||
__m128i v_dst0 = _mm_add_epi32(_mm_add_epi32(v_r0, v_r2), _mm_add_epi32(v_2r1, v_4r1));
|
||||
__m128i v_dst1 = _mm_slli_epi32(_mm_add_epi32(v_r1, v_r2), 2);
|
||||
|
||||
_mm_storel_epi64((__m128i *)(dst0 + x),
|
||||
_mm_packs_epi32(_mm_srai_epi32(_mm_add_epi32(v_dst0, v_delta), 6), v_zero));
|
||||
_mm_storel_epi64((__m128i *)(dst1 + x),
|
||||
_mm_packs_epi32(_mm_srai_epi32(_mm_add_epi32(v_dst1, v_delta), 6), v_zero));
|
||||
v_int32 v_r00 = vx_load(row0 + x),
|
||||
v_r10 = vx_load(row1 + x),
|
||||
v_r20 = vx_load(row2 + x);
|
||||
v_rshr_pack_store<6>(dst0 + x, v_r00 + v_r20 + ((v_r10 << 1) + (v_r10 << 2)));
|
||||
v_rshr_pack_store<6>(dst1 + x, (v_r10 + v_r20) << 2);
|
||||
x += v_int32::nlanes;
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
};
|
||||
|
||||
#if CV_SSE4_1
|
||||
#if CV_SSE4_1 || CV_NEON
|
||||
|
||||
struct PyrUpVec_32s16u
|
||||
{
|
||||
int operator()(int** src, ushort** dst, int, int width) const
|
||||
{
|
||||
int x = 0;
|
||||
|
||||
if (!checkHardwareSupport(CV_CPU_SSE4_1))
|
||||
return x;
|
||||
|
||||
ushort *dst0 = dst[0], *dst1 = dst[1];
|
||||
const uint *row0 = (uint *)src[0], *row1 = (uint *)src[1], *row2 = (uint *)src[2];
|
||||
__m128i v_delta = _mm_set1_epi32(32), v_zero = _mm_setzero_si128();
|
||||
const int *row0 = src[0], *row1 = src[1], *row2 = src[2];
|
||||
|
||||
for( ; x <= width - 8; x += 8 )
|
||||
for( ; x <= width - v_uint16::nlanes; x += v_uint16::nlanes)
|
||||
{
|
||||
__m128i v_r0 = _mm_loadu_si128((__m128i const *)(row0 + x)),
|
||||
v_r1 = _mm_loadu_si128((__m128i const *)(row1 + x)),
|
||||
v_r2 = _mm_loadu_si128((__m128i const *)(row2 + x));
|
||||
__m128i v_2r1 = _mm_slli_epi32(v_r1, 1), v_4r1 = _mm_slli_epi32(v_r1, 2);
|
||||
__m128i v_dst00 = _mm_add_epi32(_mm_add_epi32(v_r0, v_r2), _mm_add_epi32(v_2r1, v_4r1));
|
||||
__m128i v_dst10 = _mm_slli_epi32(_mm_add_epi32(v_r1, v_r2), 2);
|
||||
|
||||
v_r0 = _mm_loadu_si128((__m128i const *)(row0 + x + 4));
|
||||
v_r1 = _mm_loadu_si128((__m128i const *)(row1 + x + 4));
|
||||
v_r2 = _mm_loadu_si128((__m128i const *)(row2 + x + 4));
|
||||
v_2r1 = _mm_slli_epi32(v_r1, 1);
|
||||
v_4r1 = _mm_slli_epi32(v_r1, 2);
|
||||
__m128i v_dst01 = _mm_add_epi32(_mm_add_epi32(v_r0, v_r2), _mm_add_epi32(v_2r1, v_4r1));
|
||||
__m128i v_dst11 = _mm_slli_epi32(_mm_add_epi32(v_r1, v_r2), 2);
|
||||
|
||||
_mm_storeu_si128((__m128i *)(dst0 + x),
|
||||
_mm_packus_epi32(_mm_srli_epi32(_mm_add_epi32(v_dst00, v_delta), 6),
|
||||
_mm_srli_epi32(_mm_add_epi32(v_dst01, v_delta), 6)));
|
||||
_mm_storeu_si128((__m128i *)(dst1 + x),
|
||||
_mm_packus_epi32(_mm_srli_epi32(_mm_add_epi32(v_dst10, v_delta), 6),
|
||||
_mm_srli_epi32(_mm_add_epi32(v_dst11, v_delta), 6)));
|
||||
v_int32 v_r00 = vx_load(row0 + x),
|
||||
v_r01 = vx_load(row0 + x + v_int32::nlanes),
|
||||
v_r10 = vx_load(row1 + x),
|
||||
v_r11 = vx_load(row1 + x + v_int32::nlanes),
|
||||
v_r20 = vx_load(row2 + x),
|
||||
v_r21 = vx_load(row2 + x + v_int32::nlanes);
|
||||
v_store(dst0 + x, v_rshr_pack_u<6>(v_r00 + v_r20 + ((v_r10 << 1) + (v_r10 << 2)), v_r01 + v_r21 + ((v_r11 << 1) + (v_r11 << 2))));
|
||||
v_store(dst1 + x, v_rshr_pack_u<6>((v_r10 + v_r20) << 2, (v_r11 + v_r21) << 2));
|
||||
}
|
||||
|
||||
for( ; x <= width - 4; x += 4 )
|
||||
if(x <= width - v_int32::nlanes)
|
||||
{
|
||||
__m128i v_r0 = _mm_loadu_si128((__m128i const *)(row0 + x)),
|
||||
v_r1 = _mm_loadu_si128((__m128i const *)(row1 + x)),
|
||||
v_r2 = _mm_loadu_si128((__m128i const *)(row2 + x));
|
||||
__m128i v_2r1 = _mm_slli_epi32(v_r1, 1), v_4r1 = _mm_slli_epi32(v_r1, 2);
|
||||
|
||||
__m128i v_dst0 = _mm_add_epi32(_mm_add_epi32(v_r0, v_r2), _mm_add_epi32(v_2r1, v_4r1));
|
||||
__m128i v_dst1 = _mm_slli_epi32(_mm_add_epi32(v_r1, v_r2), 2);
|
||||
|
||||
_mm_storel_epi64((__m128i *)(dst0 + x),
|
||||
_mm_packus_epi32(_mm_srli_epi32(_mm_add_epi32(v_dst0, v_delta), 6), v_zero));
|
||||
_mm_storel_epi64((__m128i *)(dst1 + x),
|
||||
_mm_packus_epi32(_mm_srli_epi32(_mm_add_epi32(v_dst1, v_delta), 6), v_zero));
|
||||
v_int32 v_r00 = vx_load(row0 + x),
|
||||
v_r10 = vx_load(row1 + x),
|
||||
v_r20 = vx_load(row2 + x);
|
||||
v_rshr_pack_u_store<6>(dst0 + x, v_r00 + v_r20 + ((v_r10 << 1) + (v_r10 << 2)));
|
||||
v_rshr_pack_u_store<6>(dst1 + x, (v_r10 + v_r20) << 2);
|
||||
x += v_int32::nlanes;
|
||||
}
|
||||
|
||||
return x;
|
||||
@@ -487,347 +358,17 @@ struct PyrUpVec_32f
|
||||
int operator()(float** src, float** dst, int, int width) const
|
||||
{
|
||||
int x = 0;
|
||||
|
||||
if (!checkHardwareSupport(CV_CPU_SSE2))
|
||||
return x;
|
||||
|
||||
const float *row0 = src[0], *row1 = src[1], *row2 = src[2];
|
||||
float *dst0 = dst[0], *dst1 = dst[1];
|
||||
__m128 v_6 = _mm_set1_ps(6.0f), v_scale = _mm_set1_ps(1.f/64.0f),
|
||||
v_scale4 = _mm_mul_ps(v_scale, _mm_set1_ps(4.0f));
|
||||
|
||||
for( ; x <= width - 8; x += 8 )
|
||||
v_float32 v_6 = vx_setall_f32(6.0f), v_scale = vx_setall_f32(1.f/64.f), v_scale4 = vx_setall_f32(1.f/16.f);
|
||||
for( ; x <= width - v_float32::nlanes; x += v_float32::nlanes)
|
||||
{
|
||||
__m128 v_r0 = _mm_loadu_ps(row0 + x);
|
||||
__m128 v_r1 = _mm_loadu_ps(row1 + x);
|
||||
__m128 v_r2 = _mm_loadu_ps(row2 + x);
|
||||
|
||||
_mm_storeu_ps(dst1 + x, _mm_mul_ps(v_scale4, _mm_add_ps(v_r1, v_r2)));
|
||||
_mm_storeu_ps(dst0 + x, _mm_mul_ps(v_scale, _mm_add_ps(_mm_add_ps(v_r0, _mm_mul_ps(v_6, v_r1)), v_r2)));
|
||||
|
||||
v_r0 = _mm_loadu_ps(row0 + x + 4);
|
||||
v_r1 = _mm_loadu_ps(row1 + x + 4);
|
||||
v_r2 = _mm_loadu_ps(row2 + x + 4);
|
||||
|
||||
_mm_storeu_ps(dst1 + x + 4, _mm_mul_ps(v_scale4, _mm_add_ps(v_r1, v_r2)));
|
||||
_mm_storeu_ps(dst0 + x + 4, _mm_mul_ps(v_scale, _mm_add_ps(_mm_add_ps(v_r0, _mm_mul_ps(v_6, v_r1)), v_r2)));
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
};
|
||||
|
||||
#elif CV_NEON
|
||||
|
||||
struct PyrDownVec_32s8u
|
||||
{
|
||||
int operator()(int** src, uchar* dst, int, int width) const
|
||||
{
|
||||
int x = 0;
|
||||
const unsigned int *row0 = (unsigned int*)src[0], *row1 = (unsigned int*)src[1],
|
||||
*row2 = (unsigned int*)src[2], *row3 = (unsigned int*)src[3],
|
||||
*row4 = (unsigned int*)src[4];
|
||||
uint16x8_t v_delta = vdupq_n_u16(128);
|
||||
|
||||
for( ; x <= width - 16; x += 16 )
|
||||
{
|
||||
uint16x8_t v_r0 = vcombine_u16(vqmovn_u32(vld1q_u32(row0 + x)), vqmovn_u32(vld1q_u32(row0 + x + 4)));
|
||||
uint16x8_t v_r1 = vcombine_u16(vqmovn_u32(vld1q_u32(row1 + x)), vqmovn_u32(vld1q_u32(row1 + x + 4)));
|
||||
uint16x8_t v_r2 = vcombine_u16(vqmovn_u32(vld1q_u32(row2 + x)), vqmovn_u32(vld1q_u32(row2 + x + 4)));
|
||||
uint16x8_t v_r3 = vcombine_u16(vqmovn_u32(vld1q_u32(row3 + x)), vqmovn_u32(vld1q_u32(row3 + x + 4)));
|
||||
uint16x8_t v_r4 = vcombine_u16(vqmovn_u32(vld1q_u32(row4 + x)), vqmovn_u32(vld1q_u32(row4 + x + 4)));
|
||||
|
||||
v_r0 = vaddq_u16(vaddq_u16(v_r0, v_r4), vaddq_u16(v_r2, v_r2));
|
||||
v_r1 = vaddq_u16(vaddq_u16(v_r1, v_r2), v_r3);
|
||||
uint16x8_t v_dst0 = vaddq_u16(v_r0, vshlq_n_u16(v_r1, 2));
|
||||
|
||||
v_r0 = vcombine_u16(vqmovn_u32(vld1q_u32(row0 + x + 8)), vqmovn_u32(vld1q_u32(row0 + x + 12)));
|
||||
v_r1 = vcombine_u16(vqmovn_u32(vld1q_u32(row1 + x + 8)), vqmovn_u32(vld1q_u32(row1 + x + 12)));
|
||||
v_r2 = vcombine_u16(vqmovn_u32(vld1q_u32(row2 + x + 8)), vqmovn_u32(vld1q_u32(row2 + x + 12)));
|
||||
v_r3 = vcombine_u16(vqmovn_u32(vld1q_u32(row3 + x + 8)), vqmovn_u32(vld1q_u32(row3 + x + 12)));
|
||||
v_r4 = vcombine_u16(vqmovn_u32(vld1q_u32(row4 + x + 8)), vqmovn_u32(vld1q_u32(row4 + x + 12)));
|
||||
|
||||
v_r0 = vaddq_u16(vaddq_u16(v_r0, v_r4), vaddq_u16(v_r2, v_r2));
|
||||
v_r1 = vaddq_u16(vaddq_u16(v_r1, v_r2), v_r3);
|
||||
uint16x8_t v_dst1 = vaddq_u16(v_r0, vshlq_n_u16(v_r1, 2));
|
||||
|
||||
vst1q_u8(dst + x, vcombine_u8(vqmovn_u16(vshrq_n_u16(vaddq_u16(v_dst0, v_delta), 8)),
|
||||
vqmovn_u16(vshrq_n_u16(vaddq_u16(v_dst1, v_delta), 8))));
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
};
|
||||
|
||||
struct PyrDownVec_32s16u
|
||||
{
|
||||
int operator()(int** src, ushort* dst, int, int width) const
|
||||
{
|
||||
int x = 0;
|
||||
const int *row0 = src[0], *row1 = src[1], *row2 = src[2], *row3 = src[3], *row4 = src[4];
|
||||
int32x4_t v_delta = vdupq_n_s32(128);
|
||||
|
||||
for( ; x <= width - 8; x += 8 )
|
||||
{
|
||||
int32x4_t v_r00 = vld1q_s32(row0 + x), v_r01 = vld1q_s32(row0 + x + 4);
|
||||
int32x4_t v_r10 = vld1q_s32(row1 + x), v_r11 = vld1q_s32(row1 + x + 4);
|
||||
int32x4_t v_r20 = vld1q_s32(row2 + x), v_r21 = vld1q_s32(row2 + x + 4);
|
||||
int32x4_t v_r30 = vld1q_s32(row3 + x), v_r31 = vld1q_s32(row3 + x + 4);
|
||||
int32x4_t v_r40 = vld1q_s32(row4 + x), v_r41 = vld1q_s32(row4 + x + 4);
|
||||
|
||||
v_r00 = vaddq_s32(vaddq_s32(v_r00, v_r40), vaddq_s32(v_r20, v_r20));
|
||||
v_r10 = vaddq_s32(vaddq_s32(v_r10, v_r20), v_r30);
|
||||
|
||||
v_r10 = vshlq_n_s32(v_r10, 2);
|
||||
int32x4_t v_dst0 = vshrq_n_s32(vaddq_s32(vaddq_s32(v_r00, v_r10), v_delta), 8);
|
||||
|
||||
v_r01 = vaddq_s32(vaddq_s32(v_r01, v_r41), vaddq_s32(v_r21, v_r21));
|
||||
v_r11 = vaddq_s32(vaddq_s32(v_r11, v_r21), v_r31);
|
||||
v_r11 = vshlq_n_s32(v_r11, 2);
|
||||
int32x4_t v_dst1 = vshrq_n_s32(vaddq_s32(vaddq_s32(v_r01, v_r11), v_delta), 8);
|
||||
|
||||
vst1q_u16(dst + x, vcombine_u16(vqmovun_s32(v_dst0), vqmovun_s32(v_dst1)));
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
};
|
||||
|
||||
struct PyrDownVec_32s16s
|
||||
{
|
||||
int operator()(int** src, short* dst, int, int width) const
|
||||
{
|
||||
int x = 0;
|
||||
const int *row0 = src[0], *row1 = src[1], *row2 = src[2], *row3 = src[3], *row4 = src[4];
|
||||
int32x4_t v_delta = vdupq_n_s32(128);
|
||||
|
||||
for( ; x <= width - 8; x += 8 )
|
||||
{
|
||||
int32x4_t v_r00 = vld1q_s32(row0 + x), v_r01 = vld1q_s32(row0 + x + 4);
|
||||
int32x4_t v_r10 = vld1q_s32(row1 + x), v_r11 = vld1q_s32(row1 + x + 4);
|
||||
int32x4_t v_r20 = vld1q_s32(row2 + x), v_r21 = vld1q_s32(row2 + x + 4);
|
||||
int32x4_t v_r30 = vld1q_s32(row3 + x), v_r31 = vld1q_s32(row3 + x + 4);
|
||||
int32x4_t v_r40 = vld1q_s32(row4 + x), v_r41 = vld1q_s32(row4 + x + 4);
|
||||
|
||||
v_r00 = vaddq_s32(vaddq_s32(v_r00, v_r40), vaddq_s32(v_r20, v_r20));
|
||||
v_r10 = vaddq_s32(vaddq_s32(v_r10, v_r20), v_r30);
|
||||
v_r10 = vshlq_n_s32(v_r10, 2);
|
||||
int32x4_t v_dst0 = vshrq_n_s32(vaddq_s32(vaddq_s32(v_r00, v_r10), v_delta), 8);
|
||||
|
||||
v_r01 = vaddq_s32(vaddq_s32(v_r01, v_r41), vaddq_s32(v_r21, v_r21));
|
||||
v_r11 = vaddq_s32(vaddq_s32(v_r11, v_r21), v_r31);
|
||||
v_r11 = vshlq_n_s32(v_r11, 2);
|
||||
int32x4_t v_dst1 = vshrq_n_s32(vaddq_s32(vaddq_s32(v_r01, v_r11), v_delta), 8);
|
||||
|
||||
vst1q_s16(dst + x, vcombine_s16(vqmovn_s32(v_dst0), vqmovn_s32(v_dst1)));
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
};
|
||||
|
||||
struct PyrDownVec_32f
|
||||
{
|
||||
int operator()(float** src, float* dst, int, int width) const
|
||||
{
|
||||
int x = 0;
|
||||
const float *row0 = src[0], *row1 = src[1], *row2 = src[2], *row3 = src[3], *row4 = src[4];
|
||||
float32x4_t v_4 = vdupq_n_f32(4.0f), v_scale = vdupq_n_f32(1.f/256.0f);
|
||||
|
||||
for( ; x <= width - 8; x += 8 )
|
||||
{
|
||||
float32x4_t v_r0 = vld1q_f32(row0 + x);
|
||||
float32x4_t v_r1 = vld1q_f32(row1 + x);
|
||||
float32x4_t v_r2 = vld1q_f32(row2 + x);
|
||||
float32x4_t v_r3 = vld1q_f32(row3 + x);
|
||||
float32x4_t v_r4 = vld1q_f32(row4 + x);
|
||||
|
||||
v_r0 = vaddq_f32(vaddq_f32(v_r0, v_r4), vaddq_f32(v_r2, v_r2));
|
||||
v_r1 = vaddq_f32(vaddq_f32(v_r1, v_r2), v_r3);
|
||||
vst1q_f32(dst + x, vmulq_f32(vmlaq_f32(v_r0, v_4, v_r1), v_scale));
|
||||
|
||||
v_r0 = vld1q_f32(row0 + x + 4);
|
||||
v_r1 = vld1q_f32(row1 + x + 4);
|
||||
v_r2 = vld1q_f32(row2 + x + 4);
|
||||
v_r3 = vld1q_f32(row3 + x + 4);
|
||||
v_r4 = vld1q_f32(row4 + x + 4);
|
||||
|
||||
v_r0 = vaddq_f32(vaddq_f32(v_r0, v_r4), vaddq_f32(v_r2, v_r2));
|
||||
v_r1 = vaddq_f32(vaddq_f32(v_r1, v_r2), v_r3);
|
||||
vst1q_f32(dst + x + 4, vmulq_f32(vmlaq_f32(v_r0, v_4, v_r1), v_scale));
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
};
|
||||
|
||||
struct PyrUpVec_32s8u
|
||||
{
|
||||
int operator()(int** src, uchar** dst, int, int width) const
|
||||
{
|
||||
int x = 0;
|
||||
uchar *dst0 = dst[0], *dst1 = dst[1];
|
||||
const uint *row0 = (uint *)src[0], *row1 = (uint *)src[1], *row2 = (uint *)src[2];
|
||||
uint16x8_t v_delta = vdupq_n_u16(32);
|
||||
|
||||
for( ; x <= width - 16; x += 16 )
|
||||
{
|
||||
uint16x8_t v_r0 = vcombine_u16(vqmovn_u32(vld1q_u32(row0 + x)), vqmovn_u32(vld1q_u32(row0 + x + 4)));
|
||||
uint16x8_t v_r1 = vcombine_u16(vqmovn_u32(vld1q_u32(row1 + x)), vqmovn_u32(vld1q_u32(row1 + x + 4)));
|
||||
uint16x8_t v_r2 = vcombine_u16(vqmovn_u32(vld1q_u32(row2 + x)), vqmovn_u32(vld1q_u32(row2 + x + 4)));
|
||||
|
||||
uint16x8_t v_2r1 = vaddq_u16(v_r1, v_r1), v_4r1 = vaddq_u16(v_2r1, v_2r1);
|
||||
uint16x8_t v_dst00 = vaddq_u16(vaddq_u16(v_r0, v_r2), vaddq_u16(v_2r1, v_4r1));
|
||||
uint16x8_t v_dst10 = vshlq_n_u16(vaddq_u16(v_r1, v_r2), 2);
|
||||
|
||||
v_r0 = vcombine_u16(vqmovn_u32(vld1q_u32(row0 + x + 8)), vqmovn_u32(vld1q_u32(row0 + x + 12)));
|
||||
v_r1 = vcombine_u16(vqmovn_u32(vld1q_u32(row1 + x + 8)), vqmovn_u32(vld1q_u32(row1 + x + 12)));
|
||||
v_r2 = vcombine_u16(vqmovn_u32(vld1q_u32(row2 + x + 8)), vqmovn_u32(vld1q_u32(row2 + x + 12)));
|
||||
|
||||
v_2r1 = vaddq_u16(v_r1, v_r1), v_4r1 = vaddq_u16(v_2r1, v_2r1);
|
||||
uint16x8_t v_dst01 = vaddq_u16(vaddq_u16(v_r0, v_r2), vaddq_u16(v_2r1, v_4r1));
|
||||
uint16x8_t v_dst11 = vshlq_n_u16(vaddq_u16(v_r1, v_r2), 2);
|
||||
|
||||
vst1q_u8(dst0 + x, vcombine_u8(vqmovn_u16(vshrq_n_u16(vaddq_u16(v_dst00, v_delta), 6)),
|
||||
vqmovn_u16(vshrq_n_u16(vaddq_u16(v_dst01, v_delta), 6))));
|
||||
vst1q_u8(dst1 + x, vcombine_u8(vqmovn_u16(vshrq_n_u16(vaddq_u16(v_dst10, v_delta), 6)),
|
||||
vqmovn_u16(vshrq_n_u16(vaddq_u16(v_dst11, v_delta), 6))));
|
||||
}
|
||||
|
||||
for( ; x <= width - 8; x += 8 )
|
||||
{
|
||||
uint16x8_t v_r0 = vcombine_u16(vqmovn_u32(vld1q_u32(row0 + x)), vqmovn_u32(vld1q_u32(row0 + x + 4)));
|
||||
uint16x8_t v_r1 = vcombine_u16(vqmovn_u32(vld1q_u32(row1 + x)), vqmovn_u32(vld1q_u32(row1 + x + 4)));
|
||||
uint16x8_t v_r2 = vcombine_u16(vqmovn_u32(vld1q_u32(row2 + x)), vqmovn_u32(vld1q_u32(row2 + x + 4)));
|
||||
|
||||
uint16x8_t v_2r1 = vaddq_u16(v_r1, v_r1), v_4r1 = vaddq_u16(v_2r1, v_2r1);
|
||||
uint16x8_t v_dst0 = vaddq_u16(vaddq_u16(v_r0, v_r2), vaddq_u16(v_2r1, v_4r1));
|
||||
uint16x8_t v_dst1 = vshlq_n_u16(vaddq_u16(v_r1, v_r2), 2);
|
||||
|
||||
vst1_u8(dst0 + x, vqmovn_u16(vshrq_n_u16(vaddq_u16(v_dst0, v_delta), 6)));
|
||||
vst1_u8(dst1 + x, vqmovn_u16(vshrq_n_u16(vaddq_u16(v_dst1, v_delta), 6)));
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
};
|
||||
|
||||
struct PyrUpVec_32s16u
|
||||
{
|
||||
int operator()(int** src, ushort** dst, int, int width) const
|
||||
{
|
||||
int x = 0;
|
||||
ushort *dst0 = dst[0], *dst1 = dst[1];
|
||||
const uint *row0 = (uint *)src[0], *row1 = (uint *)src[1], *row2 = (uint *)src[2];
|
||||
uint32x4_t v_delta = vdupq_n_u32(32);
|
||||
|
||||
for( ; x <= width - 8; x += 8 )
|
||||
{
|
||||
uint32x4_t v_r0 = vld1q_u32(row0 + x), v_r1 = vld1q_u32(row1 + x), v_r2 = vld1q_u32(row2 + x);
|
||||
uint32x4_t v_2r1 = vshlq_n_u32(v_r1, 1), v_4r1 = vshlq_n_u32(v_r1, 2);
|
||||
uint32x4_t v_dst00 = vaddq_u32(vaddq_u32(v_r0, v_r2), vaddq_u32(v_2r1, v_4r1));
|
||||
uint32x4_t v_dst10 = vshlq_n_u32(vaddq_u32(v_r1, v_r2), 2);
|
||||
|
||||
v_r0 = vld1q_u32(row0 + x + 4);
|
||||
v_r1 = vld1q_u32(row1 + x + 4);
|
||||
v_r2 = vld1q_u32(row2 + x + 4);
|
||||
v_2r1 = vshlq_n_u32(v_r1, 1);
|
||||
v_4r1 = vshlq_n_u32(v_r1, 2);
|
||||
uint32x4_t v_dst01 = vaddq_u32(vaddq_u32(v_r0, v_r2), vaddq_u32(v_2r1, v_4r1));
|
||||
uint32x4_t v_dst11 = vshlq_n_u32(vaddq_u32(v_r1, v_r2), 2);
|
||||
|
||||
vst1q_u16(dst0 + x, vcombine_u16(vmovn_u32(vshrq_n_u32(vaddq_u32(v_dst00, v_delta), 6)),
|
||||
vmovn_u32(vshrq_n_u32(vaddq_u32(v_dst01, v_delta), 6))));
|
||||
vst1q_u16(dst1 + x, vcombine_u16(vmovn_u32(vshrq_n_u32(vaddq_u32(v_dst10, v_delta), 6)),
|
||||
vmovn_u32(vshrq_n_u32(vaddq_u32(v_dst11, v_delta), 6))));
|
||||
}
|
||||
|
||||
for( ; x <= width - 4; x += 4 )
|
||||
{
|
||||
uint32x4_t v_r0 = vld1q_u32(row0 + x), v_r1 = vld1q_u32(row1 + x), v_r2 = vld1q_u32(row2 + x);
|
||||
uint32x4_t v_2r1 = vshlq_n_u32(v_r1, 1), v_4r1 = vshlq_n_u32(v_r1, 2);
|
||||
|
||||
uint32x4_t v_dst0 = vaddq_u32(vaddq_u32(v_r0, v_r2), vaddq_u32(v_2r1, v_4r1));
|
||||
uint32x4_t v_dst1 = vshlq_n_u32(vaddq_u32(v_r1, v_r2), 2);
|
||||
|
||||
vst1_u16(dst0 + x, vmovn_u32(vshrq_n_u32(vaddq_u32(v_dst0, v_delta), 6)));
|
||||
vst1_u16(dst1 + x, vmovn_u32(vshrq_n_u32(vaddq_u32(v_dst1, v_delta), 6)));
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
};
|
||||
|
||||
struct PyrUpVec_32s16s
|
||||
{
|
||||
int operator()(int** src, short** dst, int, int width) const
|
||||
{
|
||||
int x = 0;
|
||||
short *dst0 = dst[0], *dst1 = dst[1];
|
||||
const int *row0 = src[0], *row1 = src[1], *row2 = src[2];
|
||||
int32x4_t v_delta = vdupq_n_s32(32);
|
||||
|
||||
for( ; x <= width - 8; x += 8 )
|
||||
{
|
||||
int32x4_t v_r0 = vld1q_s32(row0 + x), v_r1 = vld1q_s32(row1 + x), v_r2 = vld1q_s32(row2 + x);
|
||||
int32x4_t v_2r1 = vshlq_n_s32(v_r1, 1), v_4r1 = vshlq_n_s32(v_r1, 2);
|
||||
int32x4_t v_dst00 = vaddq_s32(vaddq_s32(v_r0, v_r2), vaddq_s32(v_2r1, v_4r1));
|
||||
int32x4_t v_dst10 = vshlq_n_s32(vaddq_s32(v_r1, v_r2), 2);
|
||||
|
||||
v_r0 = vld1q_s32(row0 + x + 4);
|
||||
v_r1 = vld1q_s32(row1 + x + 4);
|
||||
v_r2 = vld1q_s32(row2 + x + 4);
|
||||
v_2r1 = vshlq_n_s32(v_r1, 1);
|
||||
v_4r1 = vshlq_n_s32(v_r1, 2);
|
||||
int32x4_t v_dst01 = vaddq_s32(vaddq_s32(v_r0, v_r2), vaddq_s32(v_2r1, v_4r1));
|
||||
int32x4_t v_dst11 = vshlq_n_s32(vaddq_s32(v_r1, v_r2), 2);
|
||||
|
||||
vst1q_s16(dst0 + x, vcombine_s16(vqmovn_s32(vshrq_n_s32(vaddq_s32(v_dst00, v_delta), 6)),
|
||||
vqmovn_s32(vshrq_n_s32(vaddq_s32(v_dst01, v_delta), 6))));
|
||||
vst1q_s16(dst1 + x, vcombine_s16(vqmovn_s32(vshrq_n_s32(vaddq_s32(v_dst10, v_delta), 6)),
|
||||
vqmovn_s32(vshrq_n_s32(vaddq_s32(v_dst11, v_delta), 6))));
|
||||
}
|
||||
|
||||
for( ; x <= width - 4; x += 4 )
|
||||
{
|
||||
int32x4_t v_r0 = vld1q_s32(row0 + x), v_r1 = vld1q_s32(row1 + x), v_r2 = vld1q_s32(row2 + x);
|
||||
int32x4_t v_2r1 = vshlq_n_s32(v_r1, 1), v_4r1 = vshlq_n_s32(v_r1, 2);
|
||||
|
||||
int32x4_t v_dst0 = vaddq_s32(vaddq_s32(v_r0, v_r2), vaddq_s32(v_2r1, v_4r1));
|
||||
int32x4_t v_dst1 = vshlq_n_s32(vaddq_s32(v_r1, v_r2), 2);
|
||||
|
||||
vst1_s16(dst0 + x, vqmovn_s32(vshrq_n_s32(vaddq_s32(v_dst0, v_delta), 6)));
|
||||
vst1_s16(dst1 + x, vqmovn_s32(vshrq_n_s32(vaddq_s32(v_dst1, v_delta), 6)));
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
};
|
||||
|
||||
struct PyrUpVec_32f
|
||||
{
|
||||
int operator()(float** src, float** dst, int, int width) const
|
||||
{
|
||||
int x = 0;
|
||||
const float *row0 = src[0], *row1 = src[1], *row2 = src[2];
|
||||
float *dst0 = dst[0], *dst1 = dst[1];
|
||||
float32x4_t v_6 = vdupq_n_f32(6.0f), v_scale = vdupq_n_f32(1.f/64.0f), v_scale4 = vmulq_n_f32(v_scale, 4.0f);
|
||||
|
||||
for( ; x <= width - 8; x += 8 )
|
||||
{
|
||||
float32x4_t v_r0 = vld1q_f32(row0 + x);
|
||||
float32x4_t v_r1 = vld1q_f32(row1 + x);
|
||||
float32x4_t v_r2 = vld1q_f32(row2 + x);
|
||||
|
||||
vst1q_f32(dst1 + x, vmulq_f32(v_scale4, vaddq_f32(v_r1, v_r2)));
|
||||
vst1q_f32(dst0 + x, vmulq_f32(v_scale, vaddq_f32(vmlaq_f32(v_r0, v_6, v_r1), v_r2)));
|
||||
|
||||
v_r0 = vld1q_f32(row0 + x + 4);
|
||||
v_r1 = vld1q_f32(row1 + x + 4);
|
||||
v_r2 = vld1q_f32(row2 + x + 4);
|
||||
|
||||
vst1q_f32(dst1 + x + 4, vmulq_f32(v_scale4, vaddq_f32(v_r1, v_r2)));
|
||||
vst1q_f32(dst0 + x + 4, vmulq_f32(v_scale, vaddq_f32(vmlaq_f32(v_r0, v_6, v_r1), v_r2)));
|
||||
v_float32 v_r0 = vx_load(row0 + x),
|
||||
v_r1 = vx_load(row1 + x),
|
||||
v_r2 = vx_load(row2 + x);
|
||||
v_store(dst1 + x, v_scale4 * (v_r1 + v_r2));
|
||||
v_store(dst0 + x, v_scale * (v_muladd(v_6, v_r1, v_r0) + v_r2));
|
||||
}
|
||||
|
||||
return x;
|
||||
|
||||
+461
-901
File diff suppressed because it is too large
Load Diff
@@ -1,2 +1,8 @@
|
||||
set(the_description "Object Detection")
|
||||
ocv_define_module(objdetect opencv_core opencv_imgproc WRAP java python js)
|
||||
ocv_define_module(objdetect opencv_core opencv_imgproc opencv_calib3d WRAP java python js)
|
||||
|
||||
if(HAVE_QUIRC)
|
||||
get_property(QUIRC_INCLUDE GLOBAL PROPERTY QUIRC_INCLUDE_DIR)
|
||||
ocv_include_directories(${QUIRC_INCLUDE})
|
||||
ocv_target_link_libraries(${PROJECT_NAME} quirc)
|
||||
endif()
|
||||
|
||||
@@ -690,6 +690,13 @@ protected:
|
||||
*/
|
||||
CV_EXPORTS bool detectQRCode(InputArray in, std::vector<Point> &points, double eps_x = 0.2, double eps_y = 0.1);
|
||||
|
||||
/** @brief Decode QR code in image and return text that is encrypted in QR code.
|
||||
@param in Matrix of the type CV_8UC1 containing an image where QR code are detected.
|
||||
@param points Input vector of vertices of a quadrangle of minimal area that describes QR code.
|
||||
@param decoded_info String information that is encrypted in QR code.
|
||||
@param straight_qrcode Matrix of the type CV_8UC1 containing an binary straight QR code.
|
||||
*/
|
||||
CV_EXPORTS bool decodeQRCode(InputArray in, InputArray points, std::string &decoded_info, OutputArray straight_qrcode = noArray());
|
||||
//! @} objdetect
|
||||
|
||||
}
|
||||
|
||||
@@ -7,10 +7,16 @@
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include "opencv2/objdetect.hpp"
|
||||
#include "opencv2/calib3d.hpp"
|
||||
|
||||
#ifdef HAVE_QUIRC
|
||||
#include "quirc.h"
|
||||
#endif
|
||||
|
||||
#include <limits>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <queue>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
@@ -25,11 +31,11 @@ public:
|
||||
Mat getBinBarcode() { return bin_barcode; }
|
||||
Mat getStraightBarcode() { return straight_barcode; }
|
||||
vector<Point2f> getTransformationPoints() { return transformation_points; }
|
||||
static Point2f intersectionLines(Point2f a1, Point2f a2, Point2f b1, Point2f b2);
|
||||
protected:
|
||||
vector<Vec3d> searchHorizontalLines();
|
||||
vector<Point2f> separateVerticalLines(const vector<Vec3d> &list_lines);
|
||||
void fixationPoints(vector<Point2f> &local_point);
|
||||
Point2f intersectionLines(Point2f a1, Point2f a2, Point2f b1, Point2f b2);
|
||||
vector<Point2f> getQuadrilateral(vector<Point2f> angle_list);
|
||||
bool testBypassRoute(vector<Point2f> hull, int start, int finish);
|
||||
inline double getCosVectors(Point2f a, Point2f b, Point2f c);
|
||||
@@ -61,6 +67,7 @@ void QRDetect::init(const Mat& src, double eps_vertical_, double eps_horizontal_
|
||||
eps_vertical = eps_vertical_;
|
||||
eps_horizontal = eps_horizontal_;
|
||||
adaptiveThreshold(barcode, bin_barcode, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY, 83, 2);
|
||||
|
||||
}
|
||||
|
||||
vector<Vec3d> QRDetect::searchHorizontalLines()
|
||||
@@ -538,7 +545,7 @@ vector<Point2f> QRDetect::getQuadrilateral(vector<Point2f> angle_list)
|
||||
vector<Point> locations;
|
||||
Mat mask_roi = mask(Range(1, bin_barcode.rows - 1), Range(1, bin_barcode.cols - 1));
|
||||
|
||||
cv::findNonZero(mask_roi, locations);
|
||||
findNonZero(mask_roi, locations);
|
||||
|
||||
for (size_t i = 0; i < angle_list.size(); i++)
|
||||
{
|
||||
@@ -783,7 +790,7 @@ bool QRCodeDetector::detect(InputArray in, OutputArray points) const
|
||||
return true;
|
||||
}
|
||||
|
||||
CV_EXPORTS bool detectQRCode(InputArray in, std::vector<Point> &points, double eps_x, double eps_y)
|
||||
CV_EXPORTS bool detectQRCode(InputArray in, vector<Point> &points, double eps_x, double eps_y)
|
||||
{
|
||||
QRCodeDetector qrdetector;
|
||||
qrdetector.setEpsX(eps_x);
|
||||
@@ -792,4 +799,276 @@ CV_EXPORTS bool detectQRCode(InputArray in, std::vector<Point> &points, double e
|
||||
return qrdetector.detect(in, points);
|
||||
}
|
||||
|
||||
class QRDecode
|
||||
{
|
||||
public:
|
||||
void init(const Mat &src, const vector<Point2f> &points);
|
||||
Mat getIntermediateBarcode() { return intermediate; }
|
||||
Mat getStraightBarcode() { return straight; }
|
||||
size_t getVersion() { return version; }
|
||||
std::string getDecodeInformation() { return result_info; }
|
||||
bool fullDecodingProcess();
|
||||
protected:
|
||||
bool updatePerspective();
|
||||
bool versionDefinition();
|
||||
bool samplingForVersion();
|
||||
bool decodingProcess();
|
||||
Mat original, no_border_intermediate, intermediate, straight;
|
||||
vector<Point2f> original_points;
|
||||
std::string result_info;
|
||||
uint8_t version, version_size;
|
||||
float test_perspective_size;
|
||||
};
|
||||
|
||||
void QRDecode::init(const Mat &src, const vector<Point2f> &points)
|
||||
{
|
||||
original = src.clone();
|
||||
intermediate = Mat::zeros(src.size(), CV_8UC1);
|
||||
original_points = points;
|
||||
version = 0;
|
||||
version_size = 0;
|
||||
test_perspective_size = 251;
|
||||
result_info = "";
|
||||
}
|
||||
|
||||
bool QRDecode::updatePerspective()
|
||||
{
|
||||
const Size temporary_size(cvRound(test_perspective_size), cvRound(test_perspective_size));
|
||||
|
||||
vector<Point2f> perspective_points;
|
||||
perspective_points.push_back(Point2f(0.f, 0.f));
|
||||
perspective_points.push_back(Point2f(test_perspective_size, 0.f));
|
||||
|
||||
perspective_points.push_back(Point2f(static_cast<float>(test_perspective_size * 0.5),
|
||||
static_cast<float>(test_perspective_size * 0.5)));
|
||||
original_points.insert(original_points.begin() + 2,
|
||||
QRDetect::intersectionLines(
|
||||
original_points[0], original_points[2],
|
||||
original_points[1], original_points[3]));
|
||||
|
||||
perspective_points.push_back(Point2f(test_perspective_size, test_perspective_size));
|
||||
perspective_points.push_back(Point2f(0.f, test_perspective_size));
|
||||
|
||||
Mat H = findHomography(original_points, perspective_points);
|
||||
Mat bin_original = Mat::zeros(original.size(), CV_8UC1);
|
||||
adaptiveThreshold(original, bin_original, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY, 83, 2);
|
||||
Mat temp_intermediate = Mat::zeros(temporary_size, CV_8UC1);
|
||||
warpPerspective(bin_original, temp_intermediate, H, temporary_size, INTER_NEAREST);
|
||||
no_border_intermediate = temp_intermediate(Range(1, temp_intermediate.rows), Range(1, temp_intermediate.cols));
|
||||
|
||||
const int border = cvRound(0.1 * test_perspective_size);
|
||||
const int borderType = BORDER_CONSTANT;
|
||||
copyMakeBorder(no_border_intermediate, intermediate, border, border, border, border, borderType, Scalar(255));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QRDecode::versionDefinition()
|
||||
{
|
||||
LineIterator line_iter(intermediate, Point2f(0, 0), Point2f(test_perspective_size, test_perspective_size));
|
||||
Point black_point = Point(0, 0);
|
||||
for(int j = 0; j < line_iter.count; j++, ++line_iter)
|
||||
{
|
||||
const uint8_t value = intermediate.at<uint8_t>(line_iter.pos());
|
||||
if (value == 0) { black_point = line_iter.pos(); break; }
|
||||
}
|
||||
|
||||
Mat mask = Mat::zeros(intermediate.rows + 2, intermediate.cols + 2, CV_8UC1);
|
||||
floodFill(intermediate, mask, black_point, 255, 0, Scalar(), Scalar(), FLOODFILL_MASK_ONLY);
|
||||
|
||||
vector<Point> locations, non_zero_elem;
|
||||
Mat mask_roi = mask(Range(1, intermediate.rows - 1), Range(1, intermediate.cols - 1));
|
||||
findNonZero(mask_roi, non_zero_elem);
|
||||
convexHull(Mat(non_zero_elem), locations);
|
||||
|
||||
Point temp_remote = locations[0], remote_point;
|
||||
const Point delta_diff = Point(4, 4);
|
||||
for (size_t i = 0; i < locations.size(); i++)
|
||||
{
|
||||
if (norm(black_point - temp_remote) < norm(black_point - locations[i]))
|
||||
{
|
||||
const uint8_t value = intermediate.at<uint8_t>(temp_remote - delta_diff);
|
||||
if (value == 0) { remote_point = temp_remote - delta_diff; }
|
||||
else { remote_point = temp_remote; }
|
||||
temp_remote = locations[i];
|
||||
}
|
||||
}
|
||||
|
||||
size_t transition_x = 0 , transition_y = 0;
|
||||
|
||||
uint8_t future_pixel = 255;
|
||||
const uint8_t *intermediate_row = intermediate.ptr<uint8_t>(remote_point.y);
|
||||
for(int i = remote_point.x; i < intermediate.cols; i++)
|
||||
{
|
||||
if (intermediate_row[i] == future_pixel)
|
||||
{
|
||||
future_pixel = 255 - future_pixel;
|
||||
transition_x++;
|
||||
}
|
||||
}
|
||||
|
||||
future_pixel = 255;
|
||||
for(int j = remote_point.y; j < intermediate.rows; j++)
|
||||
{
|
||||
const uint8_t value = intermediate.at<uint8_t>(Point(j, remote_point.x));
|
||||
if (value == future_pixel)
|
||||
{
|
||||
future_pixel = 255 - future_pixel;
|
||||
transition_y++;
|
||||
}
|
||||
}
|
||||
|
||||
version = saturate_cast<uint8_t>((std::min(transition_x, transition_y) - 1) * 0.25 - 1);
|
||||
if ( !( 0 < version && version <= 40 ) ) { return false; }
|
||||
version_size = 21 + (version - 1) * 4;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QRDecode::samplingForVersion()
|
||||
{
|
||||
const double multiplyingFactor = (version < 3) ? 1 :
|
||||
(version == 3) ? 1.5 :
|
||||
version * (5 + version - 4);
|
||||
const Size newFactorSize(
|
||||
cvRound(no_border_intermediate.size().width * multiplyingFactor),
|
||||
cvRound(no_border_intermediate.size().height * multiplyingFactor));
|
||||
Mat postIntermediate(newFactorSize, CV_8UC1);
|
||||
resize(no_border_intermediate, postIntermediate, newFactorSize, 0, 0, INTER_AREA);
|
||||
|
||||
const int no_inter_rows = postIntermediate.rows;
|
||||
const int no_inter_cols = postIntermediate.cols;
|
||||
const int delta_rows = cvRound((no_inter_rows * 1.0) / version_size);
|
||||
const int delta_cols = cvRound((no_inter_cols * 1.0) / version_size);
|
||||
|
||||
vector<double> listFrequencyElem;
|
||||
for (int r = 0; r < no_inter_rows; r += delta_rows)
|
||||
{
|
||||
for (int c = 0; c < no_inter_cols; c += delta_cols)
|
||||
{
|
||||
Mat tile = postIntermediate(
|
||||
Range(r, min(r + delta_rows, no_inter_rows)),
|
||||
Range(c, min(c + delta_cols, no_inter_cols)));
|
||||
const double frequencyElem = (countNonZero(tile) * 1.0) / tile.total();
|
||||
listFrequencyElem.push_back(frequencyElem);
|
||||
}
|
||||
}
|
||||
|
||||
double dispersionEFE = std::numeric_limits<double>::max();
|
||||
double experimentalFrequencyElem = 0;
|
||||
for (double expVal = 0; expVal < 1; expVal+=0.001)
|
||||
{
|
||||
double testDispersionEFE = 0.0;
|
||||
for (size_t i = 0; i < listFrequencyElem.size(); i++)
|
||||
{
|
||||
testDispersionEFE += (listFrequencyElem[i] - expVal) *
|
||||
(listFrequencyElem[i] - expVal);
|
||||
}
|
||||
testDispersionEFE /= (listFrequencyElem.size() - 1);
|
||||
if (dispersionEFE > testDispersionEFE)
|
||||
{
|
||||
dispersionEFE = testDispersionEFE;
|
||||
experimentalFrequencyElem = expVal;
|
||||
}
|
||||
}
|
||||
|
||||
straight = Mat(Size(version_size, version_size), CV_8UC1, Scalar(0));
|
||||
size_t k = 0;
|
||||
for (int r = 0; r < no_inter_rows &&
|
||||
k < listFrequencyElem.size() &&
|
||||
floor((r * 1.0) / delta_rows) < version_size; r += delta_rows)
|
||||
{
|
||||
for (int c = 0; c < no_inter_cols &&
|
||||
k < listFrequencyElem.size() &&
|
||||
floor((c * 1.0) / delta_cols) < version_size; c += delta_cols, k++)
|
||||
{
|
||||
Mat tile = postIntermediate(
|
||||
Range(r, min(r + delta_rows, no_inter_rows)),
|
||||
Range(c, min(c + delta_cols, no_inter_cols)));
|
||||
|
||||
if (listFrequencyElem[k] < experimentalFrequencyElem) { tile.setTo(0); }
|
||||
else
|
||||
{
|
||||
tile.setTo(255);
|
||||
straight.at<uint8_t>(cvRound(floor((r * 1.0) / delta_rows)),
|
||||
cvRound(floor((c * 1.0) / delta_cols))) = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QRDecode::decodingProcess()
|
||||
{
|
||||
#ifdef HAVE_QUIRC
|
||||
if (straight.empty()) { return false; }
|
||||
|
||||
quirc_code qr_code;
|
||||
memset(&qr_code, 0, sizeof(qr_code));
|
||||
|
||||
qr_code.size = straight.size().width;
|
||||
for (int x = 0; x < qr_code.size; x++)
|
||||
{
|
||||
for (int y = 0; y < qr_code.size; y++)
|
||||
{
|
||||
int position = y * qr_code.size + x;
|
||||
qr_code.cell_bitmap[position >> 3]
|
||||
|= straight.at<uint8_t>(y, x) ? 0 : (1 << (position & 7));
|
||||
}
|
||||
}
|
||||
|
||||
quirc_data qr_code_data;
|
||||
quirc_decode_error_t errorCode = quirc_decode(&qr_code, &qr_code_data);
|
||||
if (errorCode != 0) { return false; }
|
||||
|
||||
for (int i = 0; i < qr_code_data.payload_len; i++)
|
||||
{
|
||||
result_info += qr_code_data.payload[i];
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
bool QRDecode::fullDecodingProcess()
|
||||
{
|
||||
#ifdef HAVE_QUIRC
|
||||
if (!updatePerspective()) { return false; }
|
||||
if (!versionDefinition()) { return false; }
|
||||
if (!samplingForVersion()) { return false; }
|
||||
if (!decodingProcess()) { return false; }
|
||||
return true;
|
||||
#else
|
||||
std::cout << "Library QUIRC is not linked. No decoding is performed. Take it to the OpenCV repository." << std::endl;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
CV_EXPORTS bool decodeQRCode(InputArray in, InputArray points, std::string &decoded_info, OutputArray straight_qrcode)
|
||||
{
|
||||
Mat inarr = in.getMat();
|
||||
CV_Assert(!inarr.empty());
|
||||
inarr.convertTo(inarr, CV_8UC1);
|
||||
|
||||
CV_Assert(points.isVector());
|
||||
vector<Point2f> src_points;
|
||||
points.copyTo(src_points);
|
||||
CV_Assert(src_points.size() == 4);
|
||||
|
||||
QRDecode qrdec;
|
||||
qrdec.init(inarr, src_points);
|
||||
bool exit_flag = qrdec.fullDecodingProcess();
|
||||
|
||||
decoded_info = qrdec.getDecodeInformation();
|
||||
|
||||
if (straight_qrcode.needed())
|
||||
{
|
||||
qrdec.getStraightBarcode().convertTo(straight_qrcode,
|
||||
straight_qrcode.fixedType() ?
|
||||
straight_qrcode.type() : CV_32FC2);
|
||||
}
|
||||
|
||||
return exit_flag;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,19 +4,15 @@
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
std::string qrcode_images_name[] = {
|
||||
// "20110817_030.jpg",
|
||||
"20110817_048.jpg",
|
||||
"img_20120226_161648.jpg",
|
||||
"img_2714.jpg",
|
||||
"img_2716.jpg",
|
||||
"img_3011.jpg",
|
||||
"img_3029.jpg",
|
||||
"img_3070.jpg",
|
||||
"qr_test_030.jpg"
|
||||
"version_1_down.jpg", "version_1_left.jpg", "version_1_right.jpg", "version_1_up.jpg", "version_1_top.jpg",
|
||||
"version_2_down.jpg", "version_2_left.jpg", "version_2_right.jpg", "version_2_up.jpg", "version_2_top.jpg",
|
||||
"version_3_down.jpg", "version_3_left.jpg", "version_3_right.jpg", "version_3_up.jpg", "version_3_top.jpg",
|
||||
"version_4_down.jpg", "version_4_left.jpg", "version_4_right.jpg", "version_4_up.jpg", "version_4_top.jpg",
|
||||
"version_5_down.jpg", "version_5_left.jpg", "version_5_right.jpg", "version_5_up.jpg", "version_5_top.jpg",
|
||||
"russian.jpg", "kanji.jpg", "link_github_ocv.jpg", "link_ocv.jpg", "link_wiki_cv.jpg"
|
||||
};
|
||||
|
||||
// #define UPDATE_QRCODE_TEST_DATA
|
||||
@@ -35,15 +31,21 @@ TEST(Objdetect_QRCode, generate_test_data)
|
||||
file_config << "{:" << "image_name" << qrcode_images_name[i];
|
||||
std::string image_path = findDataFile(root + qrcode_images_name[i]);
|
||||
std::vector<Point> corners;
|
||||
Mat src = imread(image_path, IMREAD_GRAYSCALE);
|
||||
Mat src = imread(image_path, IMREAD_GRAYSCALE), straight_barcode;
|
||||
std::string decoded_info;
|
||||
ASSERT_FALSE(src.empty()) << "Can't read image: " << image_path;
|
||||
EXPECT_TRUE(detectQRCode(src, corners));
|
||||
#ifdef HAVE_QUIRC
|
||||
EXPECT_TRUE(decodeQRCode(src, corners, decoded_info, straight_barcode));
|
||||
#endif
|
||||
file_config << "x" << "[:";
|
||||
for (size_t j = 0; j < corners.size(); j++) { file_config << corners[j].x; }
|
||||
file_config << "]";
|
||||
file_config << "y" << "[:";
|
||||
for (size_t j = 0; j < corners.size(); j++) { file_config << corners[j].y; }
|
||||
file_config << "]" << "}";
|
||||
file_config << "]";
|
||||
file_config << "info" << decoded_info;
|
||||
file_config << "}";
|
||||
}
|
||||
file_config << "]";
|
||||
file_config.release();
|
||||
@@ -59,11 +61,15 @@ TEST_P(Objdetect_QRCode, regression)
|
||||
const int pixels_error = 3;
|
||||
|
||||
std::string image_path = findDataFile(root + name_current_image);
|
||||
Mat src = imread(image_path, IMREAD_GRAYSCALE);
|
||||
Mat src = imread(image_path, IMREAD_GRAYSCALE), straight_barcode;
|
||||
ASSERT_FALSE(src.empty()) << "Can't read image: " << image_path;
|
||||
|
||||
std::vector<Point> corners;
|
||||
std::string decoded_info;
|
||||
ASSERT_TRUE(detectQRCode(src, corners));
|
||||
#ifdef HAVE_QUIRC
|
||||
ASSERT_TRUE(decodeQRCode(src, corners, decoded_info, straight_barcode));
|
||||
#endif
|
||||
|
||||
const std::string dataset_config = findDataFile(root + "dataset_config.json", false);
|
||||
FileStorage file_config(dataset_config, FileStorage::READ);
|
||||
@@ -86,6 +92,12 @@ TEST_P(Objdetect_QRCode, regression)
|
||||
EXPECT_NEAR(x, corners[i].x, pixels_error);
|
||||
EXPECT_NEAR(y, corners[i].y, pixels_error);
|
||||
}
|
||||
|
||||
#ifdef HAVE_QUIRC
|
||||
std::string original_info = config["info"];
|
||||
EXPECT_EQ(decoded_info, original_info);
|
||||
#endif
|
||||
|
||||
return; // done
|
||||
}
|
||||
}
|
||||
@@ -103,9 +115,14 @@ INSTANTIATE_TEST_CASE_P(/**/, Objdetect_QRCode, testing::ValuesIn(qrcode_images_
|
||||
|
||||
TEST(Objdetect_QRCode_basic, not_found_qrcode)
|
||||
{
|
||||
std::vector<Point> corners;
|
||||
std::vector<Point> corners, straight_barcode;
|
||||
std::string decoded_info;
|
||||
Mat zero_image = Mat::zeros(256, 256, CV_8UC1);
|
||||
EXPECT_FALSE(detectQRCode(zero_image, corners));
|
||||
#ifdef HAVE_QUIRC
|
||||
corners = std::vector<Point>(4);
|
||||
EXPECT_FALSE(decodeQRCode(zero_image, corners, decoded_info, straight_barcode));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -52,6 +52,10 @@ using namespace cv::cuda;
|
||||
#include "opencv2/xfeatures2d.hpp"
|
||||
using xfeatures2d::SURF;
|
||||
using xfeatures2d::SIFT;
|
||||
#else
|
||||
# if defined(_MSC_VER)
|
||||
# pragma warning(disable:4702) // unreachable code
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENCV_CUDAIMGPROC
|
||||
|
||||
Reference in New Issue
Block a user