1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-31 00:03:03 +04:00

Merge branch 4.x

This commit is contained in:
Alexander Smorkalov
2023-07-12 13:42:01 +03:00
128 changed files with 9936 additions and 932 deletions
+107
View File
@@ -0,0 +1,107 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
#include "precomp.hpp"
#include "opencl_kernels_core.hpp"
#include "stat.hpp"
#include "has_non_zero.simd.hpp"
#include "has_non_zero.simd_declarations.hpp" // defines CV_CPU_DISPATCH_MODES_ALL=AVX2,...,BASELINE based on CMakeLists.txt content
namespace cv {
static HasNonZeroFunc getHasNonZeroTab(int depth)
{
CV_INSTRUMENT_REGION();
CV_CPU_DISPATCH(getHasNonZeroTab, (depth),
CV_CPU_DISPATCH_MODES_ALL);
}
#ifdef HAVE_OPENCL
static bool ocl_hasNonZero( InputArray _src, bool & res )
{
int type = _src.type(), depth = CV_MAT_DEPTH(type), kercn = ocl::predictOptimalVectorWidth(_src);
bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0;
if (depth == CV_64F && !doubleSupport)
return false;
int dbsize = ocl::Device::getDefault().maxComputeUnits();
size_t wgs = ocl::Device::getDefault().maxWorkGroupSize();
int wgs2_aligned = 1;
while (wgs2_aligned < (int)wgs)
wgs2_aligned <<= 1;
wgs2_aligned >>= 1;
ocl::Kernel k("reduce", ocl::core::reduce_oclsrc,
format("-D srcT=%s -D srcT1=%s -D cn=1 -D OP_COUNT_NON_ZERO"
" -D WGS=%d -D kercn=%d -D WGS2_ALIGNED=%d%s%s",
ocl::typeToStr(CV_MAKE_TYPE(depth, kercn)),
ocl::typeToStr(depth), (int)wgs, kercn,
wgs2_aligned, doubleSupport ? " -D DOUBLE_SUPPORT" : "",
_src.isContinuous() ? " -D HAVE_SRC_CONT" : ""));
if (k.empty())
return false;
UMat src = _src.getUMat(), db(1, dbsize, CV_32SC1);
k.args(ocl::KernelArg::ReadOnlyNoSize(src), src.cols, (int)src.total(),
dbsize, ocl::KernelArg::PtrWriteOnly(db));
size_t globalsize = dbsize * wgs;
if (k.run(1, &globalsize, &wgs, true))
return res = (saturate_cast<int>(cv::sum(db.getMat(ACCESS_READ))[0])>0), true;
return false;
}
#endif
bool hasNonZero(InputArray _src)
{
CV_INSTRUMENT_REGION();
int type = _src.type(), cn = CV_MAT_CN(type);
CV_Assert( cn == 1 );
bool res = false;
#ifdef HAVE_OPENCL
CV_OCL_RUN_(OCL_PERFORMANCE_CHECK(_src.isUMat()) && _src.dims() <= 2,
ocl_hasNonZero(_src, res),
res)
#endif
Mat src = _src.getMat();
HasNonZeroFunc func = getHasNonZeroTab(src.depth());
CV_Assert( func != 0 );
if (src.dims == 2)//fast path to avoid creating planes of single rows
{
if (src.isContinuous())
res |= func(src.ptr<uchar>(0), src.total());
else
for(int row = 0, rowsCount = src.rows ; !res && (row<rowsCount) ; ++row)
res |= func(src.ptr<uchar>(row), src.cols);
}
else//if (src.dims != 2)
{
const Mat* arrays[] = {&src, nullptr};
Mat planes[1];
NAryMatIterator itNAry(arrays, planes, 1);
for(size_t p = 0 ; !res && (p<itNAry.nplanes) ; ++p, ++itNAry)
{
const Mat& plane = itNAry.planes[0];
if (plane.isContinuous())
res |= func(plane.ptr<uchar>(0), plane.total());
else
for(int row = 0, rowsCount = plane.rows ; !res && (row<rowsCount) ; ++row)
res |= func(plane.ptr<uchar>(row), plane.cols);
}
}
return res;
}
} // namespace
+327
View File
@@ -0,0 +1,327 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
#include "precomp.hpp"
namespace cv {
typedef bool (*HasNonZeroFunc)(const uchar*, size_t);
CV_CPU_OPTIMIZATION_NAMESPACE_BEGIN
HasNonZeroFunc getHasNonZeroTab(int depth);
#ifndef CV_CPU_OPTIMIZATION_DECLARATIONS_ONLY
template<typename T>
inline bool hasNonZero_(const T* src, size_t len )
{
bool res = false;
if (len > 0)
{
size_t i=0;
#if CV_ENABLE_UNROLLED
for(; !res && (i+4 <= len); i += 4 )
res |= ((src[i] | src[i+1] | src[i+2] | src[i+3]) != 0);
#endif
for( ; !res && (i < len); i++ )
res |= (src[i] != 0);
}
return res;
}
template<>
inline bool hasNonZero_(const float* src, size_t len )
{
bool res = false;
if (len > 0)
{
size_t i=0;
if (sizeof(float) == sizeof(unsigned int))
{
#if CV_ENABLE_UNROLLED
typedef unsigned int float_as_uint_t;
const float_as_uint_t* src_as_ui = reinterpret_cast<const float_as_uint_t*>(src);
for(; !res && (i+4 <= len); i += 4 )
{
const float_as_uint_t gathered = (src_as_ui[i] | src_as_ui[i+1] | src_as_ui[i+2] | src_as_ui[i+3]);
res |= ((gathered<<1) != 0);//remove what would be the sign bit
}
#endif
}
for( ; !res && (i < len); i++ )
res |= (src[i] != 0);
}
return res;
}
template<>
inline bool hasNonZero_(const double* src, size_t len )
{
bool res = false;
if (len > 0)
{
size_t i=0;
if (sizeof(double) == sizeof(uint64_t))
{
#if CV_ENABLE_UNROLLED
typedef uint64_t double_as_uint_t;
const double_as_uint_t* src_as_ui = reinterpret_cast<const double_as_uint_t*>(src);
for(; !res && (i+4 <= len); i += 4 )
{
const double_as_uint_t gathered = (src_as_ui[i] | src_as_ui[i+1] | src_as_ui[i+2] | src_as_ui[i+3]);
res |= ((gathered<<1) != 0);//remove what would be the sign bit
}
#endif
}
for( ; !res && (i < len); i++ )
res |= (src[i] != 0);
}
return res;
}
static bool hasNonZero8u( const uchar* src, size_t len )
{
bool res = false;
const uchar* srcEnd = src+len;
#if CV_SIMD
typedef v_uint8 v_type;
const v_type v_zero = vx_setzero_u8();
constexpr const int unrollCount = 2;
int step = v_type::nlanes * unrollCount;
int len0 = len & -step;
const uchar* srcSimdEnd = src+len0;
int countSIMD = static_cast<int>((srcSimdEnd-src)/step);
while(!res && countSIMD--)
{
v_type v0 = vx_load(src);
src += v_type::nlanes;
v_type v1 = vx_load(src);
src += v_type::nlanes;
res = v_check_any(((v0 | v1) != v_zero));
}
v_cleanup();
#endif
return res || hasNonZero_(src, srcEnd-src);
}
static bool hasNonZero16u( const ushort* src, size_t len )
{
bool res = false;
const ushort* srcEnd = src+len;
#if CV_SIMD
typedef v_uint16 v_type;
const v_type v_zero = vx_setzero_u16();
constexpr const int unrollCount = 4;
int step = v_type::nlanes * unrollCount;
int len0 = len & -step;
const ushort* srcSimdEnd = src+len0;
int countSIMD = static_cast<int>((srcSimdEnd-src)/step);
while(!res && countSIMD--)
{
v_type v0 = vx_load(src);
src += v_type::nlanes;
v_type v1 = vx_load(src);
src += v_type::nlanes;
v_type v2 = vx_load(src);
src += v_type::nlanes;
v_type v3 = vx_load(src);
src += v_type::nlanes;
v0 |= v1;
v2 |= v3;
res = v_check_any(((v0 | v2) != v_zero));
}
v_cleanup();
#endif
return res || hasNonZero_(src, srcEnd-src);
}
static bool hasNonZero32s( const int* src, size_t len )
{
bool res = false;
const int* srcEnd = src+len;
#if CV_SIMD
typedef v_int32 v_type;
const v_type v_zero = vx_setzero_s32();
constexpr const int unrollCount = 8;
int step = v_type::nlanes * unrollCount;
int len0 = len & -step;
const int* srcSimdEnd = src+len0;
int countSIMD = static_cast<int>((srcSimdEnd-src)/step);
while(!res && countSIMD--)
{
v_type v0 = vx_load(src);
src += v_type::nlanes;
v_type v1 = vx_load(src);
src += v_type::nlanes;
v_type v2 = vx_load(src);
src += v_type::nlanes;
v_type v3 = vx_load(src);
src += v_type::nlanes;
v_type v4 = vx_load(src);
src += v_type::nlanes;
v_type v5 = vx_load(src);
src += v_type::nlanes;
v_type v6 = vx_load(src);
src += v_type::nlanes;
v_type v7 = vx_load(src);
src += v_type::nlanes;
v0 |= v1;
v2 |= v3;
v4 |= v5;
v6 |= v7;
v0 |= v2;
v4 |= v6;
res = v_check_any(((v0 | v4) != v_zero));
}
v_cleanup();
#endif
return res || hasNonZero_(src, srcEnd-src);
}
static bool hasNonZero32f( const float* src, size_t len )
{
bool res = false;
const float* srcEnd = src+len;
#if CV_SIMD
typedef v_float32 v_type;
const v_type v_zero = vx_setzero_f32();
constexpr const int unrollCount = 8;
int step = v_type::nlanes * unrollCount;
int len0 = len & -step;
const float* srcSimdEnd = src+len0;
int countSIMD = static_cast<int>((srcSimdEnd-src)/step);
while(!res && countSIMD--)
{
v_type v0 = vx_load(src);
src += v_type::nlanes;
v_type v1 = vx_load(src);
src += v_type::nlanes;
v_type v2 = vx_load(src);
src += v_type::nlanes;
v_type v3 = vx_load(src);
src += v_type::nlanes;
v_type v4 = vx_load(src);
src += v_type::nlanes;
v_type v5 = vx_load(src);
src += v_type::nlanes;
v_type v6 = vx_load(src);
src += v_type::nlanes;
v_type v7 = vx_load(src);
src += v_type::nlanes;
v0 |= v1;
v2 |= v3;
v4 |= v5;
v6 |= v7;
v0 |= v2;
v4 |= v6;
//res = v_check_any(((v0 | v4) != v_zero));//beware : (NaN != 0) returns "false" since != is mapped to _CMP_NEQ_OQ and not _CMP_NEQ_UQ
res = !v_check_all(((v0 | v4) == v_zero));
}
v_cleanup();
#endif
return res || hasNonZero_(src, srcEnd-src);
}
static bool hasNonZero64f( const double* src, size_t len )
{
bool res = false;
const double* srcEnd = src+len;
#if CV_SIMD_64F
typedef v_float64 v_type;
const v_type v_zero = vx_setzero_f64();
constexpr const int unrollCount = 16;
int step = v_type::nlanes * unrollCount;
int len0 = len & -step;
const double* srcSimdEnd = src+len0;
int countSIMD = static_cast<int>((srcSimdEnd-src)/step);
while(!res && countSIMD--)
{
v_type v0 = vx_load(src);
src += v_type::nlanes;
v_type v1 = vx_load(src);
src += v_type::nlanes;
v_type v2 = vx_load(src);
src += v_type::nlanes;
v_type v3 = vx_load(src);
src += v_type::nlanes;
v_type v4 = vx_load(src);
src += v_type::nlanes;
v_type v5 = vx_load(src);
src += v_type::nlanes;
v_type v6 = vx_load(src);
src += v_type::nlanes;
v_type v7 = vx_load(src);
src += v_type::nlanes;
v_type v8 = vx_load(src);
src += v_type::nlanes;
v_type v9 = vx_load(src);
src += v_type::nlanes;
v_type v10 = vx_load(src);
src += v_type::nlanes;
v_type v11 = vx_load(src);
src += v_type::nlanes;
v_type v12 = vx_load(src);
src += v_type::nlanes;
v_type v13 = vx_load(src);
src += v_type::nlanes;
v_type v14 = vx_load(src);
src += v_type::nlanes;
v_type v15 = vx_load(src);
src += v_type::nlanes;
v0 |= v1;
v2 |= v3;
v4 |= v5;
v6 |= v7;
v8 |= v9;
v10 |= v11;
v12 |= v13;
v14 |= v15;
v0 |= v2;
v4 |= v6;
v8 |= v10;
v12 |= v14;
v0 |= v4;
v8 |= v12;
//res = v_check_any(((v0 | v8) != v_zero));//beware : (NaN != 0) returns "false" since != is mapped to _CMP_NEQ_OQ and not _CMP_NEQ_UQ
res = !v_check_all(((v0 | v8) == v_zero));
}
v_cleanup();
#endif
return res || hasNonZero_(src, srcEnd-src);
}
HasNonZeroFunc getHasNonZeroTab(int depth)
{
static HasNonZeroFunc hasNonZeroTab[] =
{
(HasNonZeroFunc)GET_OPTIMIZED(hasNonZero8u), (HasNonZeroFunc)GET_OPTIMIZED(hasNonZero8u),
(HasNonZeroFunc)GET_OPTIMIZED(hasNonZero16u), (HasNonZeroFunc)GET_OPTIMIZED(hasNonZero16u),
(HasNonZeroFunc)GET_OPTIMIZED(hasNonZero32s), (HasNonZeroFunc)GET_OPTIMIZED(hasNonZero32f),
(HasNonZeroFunc)GET_OPTIMIZED(hasNonZero64f), 0
};
return hasNonZeroTab[depth];
}
#endif
CV_CPU_OPTIMIZATION_NAMESPACE_END
} // namespace