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

Merge branch 4.x

This commit is contained in:
Alexander Smorkalov
2025-04-28 22:13:51 +03:00
243 changed files with 12965 additions and 3216 deletions
@@ -2565,7 +2565,17 @@ inline v_int64 v_dotprod_expand_fast(const v_int16& a, const v_int16& b, const v
// 32 >> 64f
#if CV_SIMD_SCALABLE_64F
inline v_float64 v_dotprod_expand_fast(const v_int32& a, const v_int32& b)
{ return v_cvt_f64(v_dotprod_fast(a, b)); }
{
vfloat64m1_t zero = __riscv_vfmv_v_f_f64m1(0, VTraits<vuint64m1_t>::vlanes());
auto prod_i64 = __riscv_vwmul(a, b, VTraits<v_int32>::vlanes());
// Convert to f64 before reduction to avoid overflow: #27003
auto prod_f64 = __riscv_vfcvt_f(prod_i64, VTraits<v_int32>::vlanes());
return __riscv_vset( // Needs v_float64 (vfloat64m2_t) here.
v_setall_f64(0.0f), // zero_f64m2
0,
__riscv_vfredusum_tu(zero, prod_f64, zero, VTraits<v_int32>::vlanes())
);
}
inline v_float64 v_dotprod_expand_fast(const v_int32& a, const v_int32& b, const v_float64& c)
{ return v_add(v_dotprod_expand_fast(a, b) , c); }
#endif
+10
View File
@@ -494,6 +494,7 @@ public:
void clear() const;
void setTo(const _InputArray& value, const _InputArray & mask = _InputArray()) const;
void setZero() const;
Mat reinterpret( int type ) const;
void assign(const UMat& u) const;
void assign(const Mat& m) const;
@@ -1540,6 +1541,15 @@ public:
*/
Mat reshape(int cn, std::initializer_list<int> newshape) const;
/** @brief Reset the type of matrix.
The methods reset the data type of matrix. If the new type and the old type of the matrix
have the same element size, the current buffer can be reused. The method needs to consider whether the
current mat is a submatrix or has any references.
@param type New data type.
*/
Mat reinterpret( int type ) const;
/** @brief Transposes a matrix.
The method performs matrix transposition by means of matrix expressions. It does not perform the
@@ -206,7 +206,6 @@ T* allocSingletonNew() { return new(allocSingletonNewBuffer(sizeof(T))) T(); }
// Temporary disabled named IPP region. Performance
#define IPP_DISABLE_PERF_COPYMAKE 1 // performance variations
#define IPP_DISABLE_PERF_LUT 1 // there are no performance benefits (PR #2653)
#define IPP_DISABLE_PERF_TRUE_DIST_MT 1 // cv::distanceTransform OpenCV MT performance is better
#define IPP_DISABLE_PERF_CANNY_MT 1 // cv::Canny OpenCV MT performance is better
@@ -43,6 +43,44 @@ CV_EXPORTS void writeLogMessage(LogLevel logLevel, const char* message);
/** Write log message */
CV_EXPORTS void writeLogMessageEx(LogLevel logLevel, const char* tag, const char* file, int line, const char* func, const char* message);
/**
* @brief Function pointer type for writeLogMessage. Used by replaceWriteLogMessage.
*/
typedef void (*WriteLogMessageFuncType)(LogLevel, const char*);
/**
* @brief Function pointer type for writeLogMessageEx. Used by replaceWriteLogMessageEx.
*/
typedef void (*WriteLogMessageExFuncType)(LogLevel, const char*, const char*, int, const char*, const char*);
/**
* @brief Replaces the OpenCV writeLogMessage function with a user-defined function.
* @note The user-defined function must have the same signature as writeLogMessage.
* @note The user-defined function must accept arguments that can be potentially null.
* @note The user-defined function must be thread-safe, as OpenCV logging may be called
* from multiple threads.
* @note The user-defined function must not perform any action that can trigger
* deadlocks or infinite loop. Many OpenCV functions are not re-entrant.
* @note Once replaced, logs will not go through the OpenCV writeLogMessage function.
* @note To restore, call this function with a nullptr.
*/
CV_EXPORTS void replaceWriteLogMessage(WriteLogMessageFuncType f);
/**
* @brief Replaces the OpenCV writeLogMessageEx function with a user-defined function.
* @note The user-defined function must have the same signature as writeLogMessage.
* @note The user-defined function must accept arguments that can be potentially null.
* @note The user-defined function must be thread-safe, as OpenCV logging may be called
* from multiple threads.
* @note The user-defined function must not perform any action that can trigger
* deadlocks or infinite loop. Many OpenCV functions are not re-entrant.
* @note Once replaced, logs will not go through any of the OpenCV logging functions
* such as writeLogMessage or writeLogMessageEx, until their respective restore
* methods are called.
* @note To restore, call this function with a nullptr.
*/
CV_EXPORTS void replaceWriteLogMessageEx(WriteLogMessageExFuncType f);
} // namespace
struct LogTagAuto
+13
View File
@@ -422,6 +422,19 @@ PERF_TEST_P_(BinaryOpTest, reciprocal)
SANITY_CHECK_NOTHING();
}
PERF_TEST_P_(BinaryOpTest, transpose2d)
{
Size sz = get<0>(GetParam());
int type = get<1>(GetParam());
Size tsz = Size(sz.height, sz.width);
cv::Mat a(sz, type), b(tsz, type);;
declare.in(a, WARMUP_RNG).out(b);
TEST_CYCLE() cv::transpose(a, b);
SANITY_CHECK_NOTHING();
}
PERF_TEST_P_(BinaryOpTest, transposeND)
{
+1 -1
View File
@@ -15,7 +15,7 @@ enum
};
#define FLIP_SIZES szQVGA, szVGA, sz1080p
#define FLIP_TYPES CV_8UC1, CV_8UC3, CV_8UC4
#define FLIP_TYPES CV_8UC1, CV_8UC2, CV_8UC3, CV_8UC4, CV_8SC1, CV_16SC1, CV_16SC2, CV_16SC3, CV_16SC4, CV_32SC1, CV_32FC1
#define FLIP_CODES FLIP_X, FLIP_Y, FLIP_XY
CV_FLAGS(FlipCode, FLIP_X, FLIP_Y, FLIP_XY);
+1 -1
View File
@@ -99,7 +99,7 @@ PERF_TEST_P(Size_MatType, Mat_Clone_Roi,
PERF_TEST_P(Size_MatType, Mat_CopyToWithMask,
testing::Combine(testing::Values(::perf::sz1080p, ::perf::szODD),
testing::Values(CV_8UC1, CV_8UC2, CV_8UC3, CV_16UC1, CV_32SC1, CV_32FC4))
testing::Values(CV_8UC1, CV_8UC2, CV_8UC3, CV_16UC1, CV_16UC3, CV_32SC1, CV_32SC2, CV_32FC4))
)
{
const Size_MatType_t params = GetParam();
+65
View File
@@ -36,6 +36,71 @@ PERF_TEST_P(VectorLength, phase64f, testing::Values(128, 1000, 128*1024, 512*102
SANITY_CHECK(angle, 5e-5);
}
///////////// Magnitude /////////////
typedef Size_MatType MagnitudeFixture;
PERF_TEST_P(MagnitudeFixture, Magnitude,
testing::Combine(testing::Values(TYPICAL_MAT_SIZES), testing::Values(CV_32F, CV_64F)))
{
cv::Size size = std::get<0>(GetParam());
int type = std::get<1>(GetParam());
cv::Mat x(size, type);
cv::Mat y(size, type);
cv::Mat magnitude(size, type);
declare.in(x, y, WARMUP_RNG).out(magnitude);
TEST_CYCLE() cv::magnitude(x, y, magnitude);
SANITY_CHECK_NOTHING();
}
///////////// Cart to Polar /////////////
typedef Size_MatType CartToPolarFixture;
PERF_TEST_P(CartToPolarFixture, CartToPolar,
testing::Combine(testing::Values(TYPICAL_MAT_SIZES), testing::Values(CV_32F, CV_64F)))
{
cv::Size size = std::get<0>(GetParam());
int type = std::get<1>(GetParam());
cv::Mat x(size, type);
cv::Mat y(size, type);
cv::Mat magnitude(size, type);
cv::Mat angle(size, type);
declare.in(x, y, WARMUP_RNG).out(magnitude, angle);
TEST_CYCLE() cv::cartToPolar(x, y, magnitude, angle);
SANITY_CHECK_NOTHING();
}
///////////// Polar to Cart /////////////
typedef Size_MatType PolarToCartFixture;
PERF_TEST_P(PolarToCartFixture, PolarToCart,
testing::Combine(testing::Values(TYPICAL_MAT_SIZES), testing::Values(CV_32F, CV_64F)))
{
cv::Size size = std::get<0>(GetParam());
int type = std::get<1>(GetParam());
cv::Mat magnitude(size, type);
cv::Mat angle(size, type);
cv::Mat x(size, type);
cv::Mat y(size, type);
declare.in(magnitude, angle, WARMUP_RNG).out(x, y);
TEST_CYCLE() cv::polarToCart(magnitude, angle, x, y);
SANITY_CHECK_NOTHING();
}
// generates random vectors, performs Gram-Schmidt orthogonalization on them
Mat randomOrtho(int rows, int ftype, RNG& rng)
{
+134
View File
@@ -12,6 +12,7 @@
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved.
// Copyright (C) 2014, Itseez Inc., all rights reserved.
// Copyright (C) 2025, SpaceMIT Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
@@ -192,6 +193,41 @@ copyMask_<uchar>(const uchar* _src, size_t sstep, const uchar* mask, size_t mste
}
}
template<> void
copyMask_<Vec3b>(const uchar* _src, size_t sstep, const uchar* mask, size_t mstep, uchar* _dst, size_t dstep, Size size)
{
for( ; size.height--; mask += mstep, _src += sstep, _dst += dstep )
{
const uchar* src = (const uchar*)_src;
uchar* dst = (uchar*)_dst;
int x = 0;
#if (CV_SIMD || CV_SIMD_SCALABLE)
for( ; x <= size.width - VTraits<v_uint8>::vlanes(); x += VTraits<v_uint8>::vlanes() )
{
v_uint8 v_nmask = v_eq(vx_load(mask + x), vx_setzero_u8());
v_uint8 v_src0, v_src1, v_src2;
v_uint8 v_dst0, v_dst1, v_dst2;
v_load_deinterleave(src + 3 * x, v_src0, v_src1, v_src2);
v_load_deinterleave(dst + 3 * x, v_dst0, v_dst1, v_dst2);
v_dst0 = v_select(v_nmask, v_dst0, v_src0);
v_dst1 = v_select(v_nmask, v_dst1, v_src1);
v_dst2 = v_select(v_nmask, v_dst2, v_src2);
v_store_interleave(dst + 3 * x, v_dst0, v_dst1, v_dst2);
}
vx_cleanup();
#endif
for( ; x < size.width; x++ )
if( mask[x] ) {
dst[3 * x] = src[3 * x];
dst[3 * x + 1] = src[3 * x + 1];
dst[3 * x + 2] = src[3 * x + 2];
}
}
}
template<> void
copyMask_<ushort>(const uchar* _src, size_t sstep, const uchar* mask, size_t mstep, uchar* _dst, size_t dstep, Size size)
{
@@ -229,6 +265,92 @@ copyMask_<ushort>(const uchar* _src, size_t sstep, const uchar* mask, size_t mst
}
}
template<> void
copyMask_<Vec3s>(const uchar* _src, size_t sstep, const uchar* mask, size_t mstep, uchar* _dst, size_t dstep, Size size)
{
for( ; size.height--; mask += mstep, _src += sstep, _dst += dstep )
{
const ushort* src = (const ushort*)_src;
ushort* dst = (ushort*)_dst;
int x = 0;
#if (CV_SIMD || CV_SIMD_SCALABLE)
for( ; x <= size.width - VTraits<v_uint8>::vlanes(); x += VTraits<v_uint8>::vlanes() )
{
v_uint8 v_nmask = v_eq(vx_load(mask + x), vx_setzero_u8());
v_uint8 v_nmask0, v_nmask1;
v_zip(v_nmask, v_nmask, v_nmask0, v_nmask1);
v_uint16 v_src0, v_src1, v_src2;
v_uint16 v_dst0, v_dst1, v_dst2;
v_load_deinterleave(src + 3 * x, v_src0, v_src1, v_src2);
v_load_deinterleave(dst + 3 * x, v_dst0, v_dst1, v_dst2);
v_uint16 v_src3, v_src4, v_src5;
v_uint16 v_dst3, v_dst4, v_dst5;
v_load_deinterleave(src + 3 * (x + VTraits<v_uint16>::vlanes()), v_src3, v_src4, v_src5);
v_load_deinterleave(dst + 3 * (x + VTraits<v_uint16>::vlanes()), v_dst3, v_dst4, v_dst5);
v_dst0 = v_select(v_reinterpret_as_u16(v_nmask0), v_dst0, v_src0);
v_dst1 = v_select(v_reinterpret_as_u16(v_nmask0), v_dst1, v_src1);
v_dst2 = v_select(v_reinterpret_as_u16(v_nmask0), v_dst2, v_src2);
v_dst3 = v_select(v_reinterpret_as_u16(v_nmask1), v_dst3, v_src3);
v_dst4 = v_select(v_reinterpret_as_u16(v_nmask1), v_dst4, v_src4);
v_dst5 = v_select(v_reinterpret_as_u16(v_nmask1), v_dst5, v_src5);
v_store_interleave(dst + 3 * x, v_dst0, v_dst1, v_dst2);
v_store_interleave(dst + 3 * (x + VTraits<v_uint16>::vlanes()), v_dst3, v_dst4, v_dst5);
}
vx_cleanup();
#endif
for( ; x < size.width; x++ )
if( mask[x] ) {
dst[3 * x] = src[3 * x];
dst[3 * x + 1] = src[3 * x + 1];
dst[3 * x + 2] = src[3 * x + 2];
}
}
}
template<> void
copyMask_<int>(const uchar* _src, size_t sstep, const uchar* mask, size_t mstep, uchar* _dst, size_t dstep, Size size)
{
for( ; size.height--; mask += mstep, _src += sstep, _dst += dstep )
{
const int* src = (const int*)_src;
int* dst = (int*)_dst;
int x = 0;
#if (CV_SIMD || CV_SIMD_SCALABLE)
for (; x <= size.width - VTraits<v_uint8>::vlanes(); x += VTraits<v_uint8>::vlanes())
{
v_int32 v_src0 = vx_load(src + x), v_dst0 = vx_load(dst + x);
v_int32 v_src1 = vx_load(src + x + VTraits<v_int32>::vlanes()), v_dst1 = vx_load(dst + x + VTraits<v_int32>::vlanes());
v_int32 v_src2 = vx_load(src + x + 2 * VTraits<v_int32>::vlanes()), v_dst2 = vx_load(dst + x + 2 * VTraits<v_int32>::vlanes());
v_int32 v_src3 = vx_load(src + x + 3 * VTraits<v_int32>::vlanes()), v_dst3 = vx_load(dst + x + 3 * VTraits<v_int32>::vlanes());
v_uint8 v_nmask = v_eq(vx_load(mask + x), vx_setzero_u8());
v_uint8 v_nmask0, v_nmask1;
v_zip(v_nmask, v_nmask, v_nmask0, v_nmask1);
v_uint8 v_nmask00, v_nmask01, v_nmask10, v_nmask11;
v_zip(v_nmask0, v_nmask0, v_nmask00, v_nmask01);
v_zip(v_nmask1, v_nmask1, v_nmask10, v_nmask11);
v_dst0 = v_select(v_reinterpret_as_s32(v_nmask00), v_dst0, v_src0);
v_dst1 = v_select(v_reinterpret_as_s32(v_nmask01), v_dst1, v_src1);
v_dst2 = v_select(v_reinterpret_as_s32(v_nmask10), v_dst2, v_src2);
v_dst3 = v_select(v_reinterpret_as_s32(v_nmask11), v_dst3, v_src3);
vx_store(dst + x, v_dst0);
vx_store(dst + x + VTraits<v_int32>::vlanes(), v_dst1);
vx_store(dst + x + 2 * VTraits<v_int32>::vlanes(), v_dst2);
vx_store(dst + x + 3 * VTraits<v_int32>::vlanes(), v_dst3);
}
vx_cleanup();
#endif
for (; x < size.width; x++)
if ( mask[x] )
dst[x] = src[x];
}
}
static void
copyMaskGeneric(const uchar* _src, size_t sstep, const uchar* mask, size_t mstep, uchar* _dst, size_t dstep, Size size, void* _esz)
{
@@ -487,6 +609,18 @@ void Mat::copyTo( OutputArray _dst, InputArray _mask ) const
}
CV_IPP_RUN_FAST(ipp_copyTo(*this, dst, mask))
if ( this->dims <= 2 ) {
if ( this->size() == dst.size() && this->size() == dst.size() ) {
CALL_HAL(copyToMask, cv_hal_copyToMasked, this->data, this->step, dst.data, dst.step, this->cols, this->rows, this->type(), mask.data, mask.step, mask.type());
}
}
else if ( this->isContinuous() && dst.isContinuous() && mask.isContinuous() )
{
size_t sz = this->total();
if (sz < INT_MAX) {
CALL_HAL(copyToMask, cv_hal_copyToMasked, this->data, 0, dst.data, 0, (int)sz, 1, this->type(), mask.data, 0, mask.type());
}
}
size_t esz = colorMask ? elemSize1() : elemSize();
BinaryFunc copymask = getCopyMaskFunc(esz);
+16
View File
@@ -1207,6 +1207,22 @@ inline int hal_ni_transpose2d(const uchar* src_data, size_t src_step, uchar* dst
#define cv_hal_transpose2d hal_ni_transpose2d
//! @endcond
/**
@brief copyTo with mask
@param src_data, src_step Source image
@param dst_data, dst_step Destination image
@param width, height Image dimensions of source, destination and mask
@param type Type of source and destination images, for example CV_8UC1 or CV_32FC3
@param mask_data, mask_step, mask_type Mask
*/
inline int hal_ni_copyToMasked(const uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, int width, int height,
int type, const uchar* mask_data, size_t mask_step, int mask_type)
{ return CV_HAL_ERROR_NOT_IMPLEMENTED; }
//! @cond IGNORED
#define cv_hal_copyToMasked hal_ni_copyToMasked
//! @endcond
//! @}
+41
View File
@@ -12,6 +12,7 @@
#include <sstream>
#include <iostream>
#include <fstream>
#include <atomic>
#ifdef __ANDROID__
# include <android/log.h>
@@ -181,6 +182,12 @@ LogLevel getLogLevel()
namespace internal {
namespace //unnamed
{
std::atomic<WriteLogMessageFuncType> stc_userWriteLogMessageFunc{};
std::atomic<WriteLogMessageExFuncType> stc_userWriteLogMessageExFunc{};
} //unnamed
static int getShowTimestampMode()
{
static bool param_timestamp_enable = utils::getConfigurationParameterBool("OPENCV_LOG_TIMESTAMP", true);
@@ -190,6 +197,13 @@ static int getShowTimestampMode()
void writeLogMessage(LogLevel logLevel, const char* message)
{
WriteLogMessageFuncType userFunc = stc_userWriteLogMessageFunc.load();
if (userFunc && userFunc != writeLogMessage)
{
(*userFunc)(logLevel, message);
return;
}
const int threadID = cv::utils::getThreadID();
std::string message_id;
@@ -230,7 +244,9 @@ void writeLogMessage(LogLevel logLevel, const char* message)
std::ostream* out = (logLevel <= LOG_LEVEL_WARNING) ? &std::cerr : &std::cout;
(*out) << ss.str();
if (logLevel <= LOG_LEVEL_WARNING)
{
(*out) << std::flush;
}
}
static const char* stripSourceFilePathPrefix(const char* file)
@@ -252,6 +268,13 @@ static const char* stripSourceFilePathPrefix(const char* file)
void writeLogMessageEx(LogLevel logLevel, const char* tag, const char* file, int line, const char* func, const char* message)
{
WriteLogMessageExFuncType userFunc = stc_userWriteLogMessageExFunc.load();
if (userFunc && userFunc != writeLogMessageEx)
{
(*userFunc)(logLevel, tag, file, line, func, message);
return;
}
std::ostringstream strm;
if (tag)
{
@@ -274,6 +297,24 @@ void writeLogMessageEx(LogLevel logLevel, const char* tag, const char* file, int
writeLogMessage(logLevel, strm.str().c_str());
}
void replaceWriteLogMessage(WriteLogMessageFuncType f)
{
if (f == writeLogMessage)
{
f = nullptr;
}
stc_userWriteLogMessageFunc.store(f);
}
void replaceWriteLogMessageEx(WriteLogMessageExFuncType f)
{
if (f == writeLogMessageEx)
{
f = nullptr;
}
stc_userWriteLogMessageExFunc.store(f);
}
} // namespace
}}} // namespace
-182
View File
@@ -122,184 +122,6 @@ static bool ocl_LUT(InputArray _src, InputArray _lut, OutputArray _dst)
#endif
#if defined(HAVE_IPP)
#if !IPP_DISABLE_PERF_LUT // there are no performance benefits (PR #2653)
namespace ipp {
class IppLUTParallelBody_LUTC1 : public ParallelLoopBody
{
public:
bool* ok;
const Mat& src_;
const Mat& lut_;
Mat& dst_;
int width;
size_t elemSize1;
IppLUTParallelBody_LUTC1(const Mat& src, const Mat& lut, Mat& dst, bool* _ok)
: ok(_ok), src_(src), lut_(lut), dst_(dst)
{
width = dst.cols * dst.channels();
elemSize1 = CV_ELEM_SIZE1(dst.depth());
CV_DbgAssert(elemSize1 == 1 || elemSize1 == 4);
*ok = true;
}
void operator()( const cv::Range& range ) const
{
if (!*ok)
return;
const int row0 = range.start;
const int row1 = range.end;
Mat src = src_.rowRange(row0, row1);
Mat dst = dst_.rowRange(row0, row1);
IppiSize sz = { width, dst.rows };
if (elemSize1 == 1)
{
if (CV_INSTRUMENT_FUN_IPP(ippiLUTPalette_8u_C1R, (const Ipp8u*)src.data, (int)src.step[0], dst.data, (int)dst.step[0], sz, lut_.data, 8) >= 0)
return;
}
else if (elemSize1 == 4)
{
if (CV_INSTRUMENT_FUN_IPP(ippiLUTPalette_8u32u_C1R, (const Ipp8u*)src.data, (int)src.step[0], (Ipp32u*)dst.data, (int)dst.step[0], sz, (Ipp32u*)lut_.data, 8) >= 0)
return;
}
*ok = false;
}
private:
IppLUTParallelBody_LUTC1(const IppLUTParallelBody_LUTC1&);
IppLUTParallelBody_LUTC1& operator=(const IppLUTParallelBody_LUTC1&);
};
class IppLUTParallelBody_LUTCN : public ParallelLoopBody
{
public:
bool *ok;
const Mat& src_;
const Mat& lut_;
Mat& dst_;
int lutcn;
uchar* lutBuffer;
uchar* lutTable[4];
IppLUTParallelBody_LUTCN(const Mat& src, const Mat& lut, Mat& dst, bool* _ok)
: ok(_ok), src_(src), lut_(lut), dst_(dst), lutBuffer(NULL)
{
lutcn = lut.channels();
IppiSize sz256 = {256, 1};
size_t elemSize1 = dst.elemSize1();
CV_DbgAssert(elemSize1 == 1);
lutBuffer = (uchar*)CV_IPP_MALLOC(256 * (int)elemSize1 * 4);
lutTable[0] = lutBuffer + 0;
lutTable[1] = lutBuffer + 1 * 256 * elemSize1;
lutTable[2] = lutBuffer + 2 * 256 * elemSize1;
lutTable[3] = lutBuffer + 3 * 256 * elemSize1;
CV_DbgAssert(lutcn == 3 || lutcn == 4);
if (lutcn == 3)
{
IppStatus status = CV_INSTRUMENT_FUN_IPP(ippiCopy_8u_C3P3R, lut.ptr(), (int)lut.step[0], lutTable, (int)lut.step[0], sz256);
if (status < 0)
return;
}
else if (lutcn == 4)
{
IppStatus status = CV_INSTRUMENT_FUN_IPP(ippiCopy_8u_C4P4R, lut.ptr(), (int)lut.step[0], lutTable, (int)lut.step[0], sz256);
if (status < 0)
return;
}
*ok = true;
}
~IppLUTParallelBody_LUTCN()
{
if (lutBuffer != NULL)
ippFree(lutBuffer);
lutBuffer = NULL;
lutTable[0] = NULL;
}
void operator()( const cv::Range& range ) const
{
if (!*ok)
return;
const int row0 = range.start;
const int row1 = range.end;
Mat src = src_.rowRange(row0, row1);
Mat dst = dst_.rowRange(row0, row1);
if (lutcn == 3)
{
if (CV_INSTRUMENT_FUN_IPP(ippiLUTPalette_8u_C3R, src.ptr(), (int)src.step[0], dst.ptr(), (int)dst.step[0], ippiSize(dst.size()), lutTable, 8) >= 0)
return;
}
else if (lutcn == 4)
{
if (CV_INSTRUMENT_FUN_IPP(ippiLUTPalette_8u_C4R, src.ptr(), (int)src.step[0], dst.ptr(), (int)dst.step[0], ippiSize(dst.size()), lutTable, 8) >= 0)
return;
}
*ok = false;
}
private:
IppLUTParallelBody_LUTCN(const IppLUTParallelBody_LUTCN&);
IppLUTParallelBody_LUTCN& operator=(const IppLUTParallelBody_LUTCN&);
};
} // namespace ipp
static bool ipp_lut(Mat &src, Mat &lut, Mat &dst)
{
CV_INSTRUMENT_REGION_IPP();
int lutcn = lut.channels();
if(src.dims > 2)
return false;
bool ok = false;
Ptr<ParallelLoopBody> body;
size_t elemSize1 = CV_ELEM_SIZE1(dst.depth());
if (lutcn == 1)
{
ParallelLoopBody* p = new ipp::IppLUTParallelBody_LUTC1(src, lut, dst, &ok);
body.reset(p);
}
else if ((lutcn == 3 || lutcn == 4) && elemSize1 == 1)
{
ParallelLoopBody* p = new ipp::IppLUTParallelBody_LUTCN(src, lut, dst, &ok);
body.reset(p);
}
if (body != NULL && ok)
{
Range all(0, dst.rows);
if (dst.total()>>18)
parallel_for_(all, *body, (double)std::max((size_t)1, dst.total()>>16));
else
(*body)(all);
if (ok)
return true;
}
return false;
}
#endif
#endif // IPP
class LUTParallelBody : public ParallelLoopBody
{
public:
@@ -366,10 +188,6 @@ void cv::LUT( InputArray _src, InputArray _lut, OutputArray _dst )
CALL_HAL(LUT, cv_hal_lut, src.data, src.step, src.type(), lut.data,
lut.elemSize1(), lutcn, dst.data, dst.step, src.cols, src.rows);
#if !IPP_DISABLE_PERF_LUT
CV_IPP_RUN(_src.dims() <= 2, ipp_lut(src, lut, dst));
#endif
if (_src.dims() <= 2)
{
bool ok = false;
+4 -284
View File
@@ -328,149 +328,6 @@ void cartToPolar( InputArray src1, InputArray src2,
* Polar -> Cartezian *
\****************************************************************************************/
static void SinCos_32f( const float *angle, float *sinval, float* cosval,
int len, int angle_in_degrees )
{
const int N = 64;
static const double sin_table[] =
{
0.00000000000000000000, 0.09801714032956060400,
0.19509032201612825000, 0.29028467725446233000,
0.38268343236508978000, 0.47139673682599764000,
0.55557023301960218000, 0.63439328416364549000,
0.70710678118654746000, 0.77301045336273699000,
0.83146961230254524000, 0.88192126434835494000,
0.92387953251128674000, 0.95694033573220894000,
0.98078528040323043000, 0.99518472667219682000,
1.00000000000000000000, 0.99518472667219693000,
0.98078528040323043000, 0.95694033573220894000,
0.92387953251128674000, 0.88192126434835505000,
0.83146961230254546000, 0.77301045336273710000,
0.70710678118654757000, 0.63439328416364549000,
0.55557023301960218000, 0.47139673682599786000,
0.38268343236508989000, 0.29028467725446239000,
0.19509032201612861000, 0.09801714032956082600,
0.00000000000000012246, -0.09801714032956059000,
-0.19509032201612836000, -0.29028467725446211000,
-0.38268343236508967000, -0.47139673682599764000,
-0.55557023301960196000, -0.63439328416364527000,
-0.70710678118654746000, -0.77301045336273666000,
-0.83146961230254524000, -0.88192126434835494000,
-0.92387953251128652000, -0.95694033573220882000,
-0.98078528040323032000, -0.99518472667219693000,
-1.00000000000000000000, -0.99518472667219693000,
-0.98078528040323043000, -0.95694033573220894000,
-0.92387953251128663000, -0.88192126434835505000,
-0.83146961230254546000, -0.77301045336273688000,
-0.70710678118654768000, -0.63439328416364593000,
-0.55557023301960218000, -0.47139673682599792000,
-0.38268343236509039000, -0.29028467725446250000,
-0.19509032201612872000, -0.09801714032956050600,
};
static const double k2 = (2*CV_PI)/N;
static const double sin_a0 = -0.166630293345647*k2*k2*k2;
static const double sin_a2 = k2;
static const double cos_a0 = -0.499818138450326*k2*k2;
/*static const double cos_a2 = 1;*/
double k1;
int i = 0;
if( !angle_in_degrees )
k1 = N/(2*CV_PI);
else
k1 = N/360.;
#if CV_AVX2
if (USE_AVX2)
{
__m128d v_k1 = _mm_set1_pd(k1);
__m128d v_1 = _mm_set1_pd(1);
__m128i v_N1 = _mm_set1_epi32(N - 1);
__m128i v_N4 = _mm_set1_epi32(N >> 2);
__m128d v_sin_a0 = _mm_set1_pd(sin_a0);
__m128d v_sin_a2 = _mm_set1_pd(sin_a2);
__m128d v_cos_a0 = _mm_set1_pd(cos_a0);
for ( ; i <= len - 4; i += 4)
{
__m128 v_angle = _mm_loadu_ps(angle + i);
// 0-1
__m128d v_t = _mm_mul_pd(_mm_cvtps_pd(v_angle), v_k1);
__m128i v_it = _mm_cvtpd_epi32(v_t);
v_t = _mm_sub_pd(v_t, _mm_cvtepi32_pd(v_it));
__m128i v_sin_idx = _mm_and_si128(v_it, v_N1);
__m128i v_cos_idx = _mm_and_si128(_mm_sub_epi32(v_N4, v_sin_idx), v_N1);
__m128d v_t2 = _mm_mul_pd(v_t, v_t);
__m128d v_sin_b = _mm_mul_pd(_mm_add_pd(_mm_mul_pd(v_sin_a0, v_t2), v_sin_a2), v_t);
__m128d v_cos_b = _mm_add_pd(_mm_mul_pd(v_cos_a0, v_t2), v_1);
__m128d v_sin_a = _mm_i32gather_pd(sin_table, v_sin_idx, 8);
__m128d v_cos_a = _mm_i32gather_pd(sin_table, v_cos_idx, 8);
__m128d v_sin_val_0 = _mm_add_pd(_mm_mul_pd(v_sin_a, v_cos_b),
_mm_mul_pd(v_cos_a, v_sin_b));
__m128d v_cos_val_0 = _mm_sub_pd(_mm_mul_pd(v_cos_a, v_cos_b),
_mm_mul_pd(v_sin_a, v_sin_b));
// 2-3
v_t = _mm_mul_pd(_mm_cvtps_pd(_mm_castsi128_ps(_mm_srli_si128(_mm_castps_si128(v_angle), 8))), v_k1);
v_it = _mm_cvtpd_epi32(v_t);
v_t = _mm_sub_pd(v_t, _mm_cvtepi32_pd(v_it));
v_sin_idx = _mm_and_si128(v_it, v_N1);
v_cos_idx = _mm_and_si128(_mm_sub_epi32(v_N4, v_sin_idx), v_N1);
v_t2 = _mm_mul_pd(v_t, v_t);
v_sin_b = _mm_mul_pd(_mm_add_pd(_mm_mul_pd(v_sin_a0, v_t2), v_sin_a2), v_t);
v_cos_b = _mm_add_pd(_mm_mul_pd(v_cos_a0, v_t2), v_1);
v_sin_a = _mm_i32gather_pd(sin_table, v_sin_idx, 8);
v_cos_a = _mm_i32gather_pd(sin_table, v_cos_idx, 8);
__m128d v_sin_val_1 = _mm_add_pd(_mm_mul_pd(v_sin_a, v_cos_b),
_mm_mul_pd(v_cos_a, v_sin_b));
__m128d v_cos_val_1 = _mm_sub_pd(_mm_mul_pd(v_cos_a, v_cos_b),
_mm_mul_pd(v_sin_a, v_sin_b));
_mm_storeu_ps(sinval + i, _mm_movelh_ps(_mm_cvtpd_ps(v_sin_val_0),
_mm_cvtpd_ps(v_sin_val_1)));
_mm_storeu_ps(cosval + i, _mm_movelh_ps(_mm_cvtpd_ps(v_cos_val_0),
_mm_cvtpd_ps(v_cos_val_1)));
}
}
#endif
for( ; i < len; i++ )
{
double t = angle[i]*k1;
int it = cvRound(t);
t -= it;
int sin_idx = it & (N - 1);
int cos_idx = (N/4 - sin_idx) & (N - 1);
double sin_b = (sin_a0*t*t + sin_a2)*t;
double cos_b = cos_a0*t*t + 1;
double sin_a = sin_table[sin_idx];
double cos_a = sin_table[cos_idx];
double sin_val = sin_a*cos_b + cos_a*sin_b;
double cos_val = cos_a*cos_b - sin_a*sin_b;
sinval[i] = (float)sin_val;
cosval[i] = (float)cos_val;
}
}
#ifdef HAVE_OPENCL
static bool ocl_polarToCart( InputArray _mag, InputArray _angle,
@@ -521,65 +378,6 @@ static bool ocl_polarToCart( InputArray _mag, InputArray _angle,
#endif
#ifdef HAVE_IPP
static bool ipp_polarToCart(Mat &mag, Mat &angle, Mat &x, Mat &y)
{
CV_INSTRUMENT_REGION_IPP();
int depth = angle.depth();
if(depth != CV_32F && depth != CV_64F)
return false;
if(angle.dims <= 2)
{
int len = (int)(angle.cols*angle.channels());
if(depth == CV_32F)
{
for (int h = 0; h < angle.rows; h++)
{
if(CV_INSTRUMENT_FUN_IPP(ippsPolarToCart_32f, (const float*)mag.ptr(h), (const float*)angle.ptr(h), (float*)x.ptr(h), (float*)y.ptr(h), len) < 0)
return false;
}
}
else
{
for (int h = 0; h < angle.rows; h++)
{
if(CV_INSTRUMENT_FUN_IPP(ippsPolarToCart_64f, (const double*)mag.ptr(h), (const double*)angle.ptr(h), (double*)x.ptr(h), (double*)y.ptr(h), len) < 0)
return false;
}
}
return true;
}
else
{
const Mat *arrays[] = {&mag, &angle, &x, &y, NULL};
uchar *ptrs[4] = {NULL};
NAryMatIterator it(arrays, ptrs);
int len = (int)(it.size*angle.channels());
if(depth == CV_32F)
{
for (size_t i = 0; i < it.nplanes; i++, ++it)
{
if(CV_INSTRUMENT_FUN_IPP(ippsPolarToCart_32f, (const float*)ptrs[0], (const float*)ptrs[1], (float*)ptrs[2], (float*)ptrs[3], len) < 0)
return false;
}
}
else
{
for (size_t i = 0; i < it.nplanes; i++, ++it)
{
if(CV_INSTRUMENT_FUN_IPP(ippsPolarToCart_64f, (const double*)ptrs[0], (const double*)ptrs[1], (double*)ptrs[2], (double*)ptrs[3], len) < 0)
return false;
}
}
return true;
}
}
#endif
void polarToCart( InputArray src1, InputArray src2,
OutputArray dst1, OutputArray dst2, bool angleInDegrees )
{
@@ -587,12 +385,6 @@ void polarToCart( InputArray src1, InputArray src2,
CV_Assert(dst1.getObj() != dst2.getObj());
const bool isInPlace =
(src1.getObj() == dst1.getObj()) ||
(src1.getObj() == dst2.getObj()) ||
(src2.getObj() == dst1.getObj()) ||
(src2.getObj() == dst2.getObj());
int type = src2.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
CV_Assert((depth == CV_32F || depth == CV_64F) && (src1.empty() || src1.type() == type));
@@ -605,100 +397,28 @@ void polarToCart( InputArray src1, InputArray src2,
dst2.create( Angle.dims, Angle.size, type );
Mat X = dst1.getMat(), Y = dst2.getMat();
CV_IPP_RUN(!angleInDegrees && !isInPlace, ipp_polarToCart(Mag, Angle, X, Y));
const Mat* arrays[] = {&Mag, &Angle, &X, &Y, 0};
uchar* ptrs[4] = {};
NAryMatIterator it(arrays, ptrs);
cv::AutoBuffer<float> _buf;
float* buf[2] = {0, 0};
int j, k, total = (int)(it.size*cn), blockSize = std::min(total, ((BLOCK_SIZE+cn-1)/cn)*cn);
int j, total = (int)(it.size*cn), blockSize = std::min(total, ((BLOCK_SIZE+cn-1)/cn)*cn);
size_t esz1 = Angle.elemSize1();
if (( depth == CV_64F ) || isInPlace)
{
_buf.allocate(blockSize*2);
buf[0] = _buf.data();
buf[1] = buf[0] + blockSize;
}
for( size_t i = 0; i < it.nplanes; i++, ++it )
{
for( j = 0; j < total; j += blockSize )
{
int len = std::min(total - j, blockSize);
if (( depth == CV_32F ) && !isInPlace)
if ( depth == CV_32F )
{
const float *mag = (const float*)ptrs[0], *angle = (const float*)ptrs[1];
float *x = (float*)ptrs[2], *y = (float*)ptrs[3];
SinCos_32f( angle, y, x, len, angleInDegrees );
if( mag )
{
k = 0;
#if (CV_SIMD || CV_SIMD_SCALABLE)
int cWidth = VTraits<v_float32>::vlanes();
for( ; k <= len - cWidth; k += cWidth )
{
v_float32 v_m = vx_load(mag + k);
v_store(x + k, v_mul(vx_load(x + k), v_m));
v_store(y + k, v_mul(vx_load(y + k), v_m));
}
vx_cleanup();
#endif
for( ; k < len; k++ )
{
float m = mag[k];
x[k] *= m; y[k] *= m;
}
}
}
else if (( depth == CV_32F ) && isInPlace)
{
const float *mag = (const float*)ptrs[0], *angle = (const float*)ptrs[1];
float *x = (float*)ptrs[2], *y = (float*)ptrs[3];
for( k = 0; k < len; k++ )
buf[0][k] = (float)angle[k];
SinCos_32f( buf[0], buf[1], buf[0], len, angleInDegrees );
if( mag )
for( k = 0; k < len; k++ )
{
float m = mag[k];
x[k] = buf[0][k]*m; y[k] = buf[1][k]*m;
}
else
{
std::memcpy(x, buf[0], sizeof(float) * len);
std::memcpy(y, buf[1], sizeof(float) * len);
}
hal::polarToCart32f( mag, angle, x, y, len, angleInDegrees );
}
else
{
const double *mag = (const double*)ptrs[0], *angle = (const double*)ptrs[1];
double *x = (double*)ptrs[2], *y = (double*)ptrs[3];
for( k = 0; k < len; k++ )
buf[0][k] = (float)angle[k];
SinCos_32f( buf[0], buf[1], buf[0], len, angleInDegrees );
if( mag )
for( k = 0; k < len; k++ )
{
double m = mag[k];
x[k] = buf[0][k]*m; y[k] = buf[1][k]*m;
}
else
{
for( k = 0; k < len; k++ )
{
x[k] = buf[0][k];
y[k] = buf[1][k];
}
}
hal::polarToCart64f( mag, angle, x, y, len, angleInDegrees );
}
if( ptrs[0] )
@@ -29,6 +29,26 @@ void cartToPolar64f(const double* x, const double* y, double* mag, double* angle
CV_CPU_DISPATCH_MODES_ALL);
}
void polarToCart32f(const float* mag, const float* angle, float* x, float* y, int len, bool angleInDegrees)
{
CV_INSTRUMENT_REGION();
CALL_HAL(polarToCart32f, cv_hal_polarToCart32f, mag, angle, x, y, len, angleInDegrees);
CV_CPU_DISPATCH(polarToCart32f, (mag, angle, x, y, len, angleInDegrees),
CV_CPU_DISPATCH_MODES_ALL);
}
void polarToCart64f(const double* mag, const double* angle, double* x, double* y, int len, bool angleInDegrees)
{
CV_INSTRUMENT_REGION();
CALL_HAL(polarToCart64f, cv_hal_polarToCart64f, mag, angle, x, y, len, angleInDegrees);
CV_CPU_DISPATCH(polarToCart64f, (mag, angle, x, y, len, angleInDegrees),
CV_CPU_DISPATCH_MODES_ALL);
}
void fastAtan32f(const float *Y, const float *X, float *angle, int len, bool angleInDegrees )
{
CV_INSTRUMENT_REGION();
+194 -49
View File
@@ -11,6 +11,8 @@ CV_CPU_OPTIMIZATION_NAMESPACE_BEGIN
// forward declarations
void cartToPolar32f(const float *X, const float *Y, float* mag, float *angle, int len, bool angleInDegrees);
void cartToPolar64f(const double *X, const double *Y, double* mag, double *angle, int len, bool angleInDegrees);
void polarToCart32f(const float *mag, const float *angle, float *X, float *Y, int len, bool angleInDegrees);
void polarToCart64f(const double *mag, const double *angle, double *X, double *Y, int len, bool angleInDegrees);
void fastAtan32f(const float *Y, const float *X, float *angle, int len, bool angleInDegrees);
void fastAtan64f(const double *Y, const double *X, double *angle, int len, bool angleInDegrees);
void fastAtan2(const float *Y, const float *X, float *angle, int len, bool angleInDegrees);
@@ -73,48 +75,30 @@ static inline float atan_f32(float y, float x)
}
#endif
#if CV_SIMD
#if (CV_SIMD || CV_SIMD_SCALABLE)
struct v_atan_f32
v_float32 v_atan_f32(const v_float32& y, const v_float32& x)
{
explicit v_atan_f32(const float& scale)
{
eps = vx_setall_f32((float)DBL_EPSILON);
z = vx_setzero_f32();
p7 = vx_setall_f32(atan2_p7);
p5 = vx_setall_f32(atan2_p5);
p3 = vx_setall_f32(atan2_p3);
p1 = vx_setall_f32(atan2_p1);
val90 = vx_setall_f32(90.f);
val180 = vx_setall_f32(180.f);
val360 = vx_setall_f32(360.f);
s = vx_setall_f32(scale);
}
v_float32 eps = vx_setall_f32((float)DBL_EPSILON);
v_float32 z = vx_setzero_f32();
v_float32 p7 = vx_setall_f32(atan2_p7);
v_float32 p5 = vx_setall_f32(atan2_p5);
v_float32 p3 = vx_setall_f32(atan2_p3);
v_float32 p1 = vx_setall_f32(atan2_p1);
v_float32 val90 = vx_setall_f32(90.f);
v_float32 val180 = vx_setall_f32(180.f);
v_float32 val360 = vx_setall_f32(360.f);
v_float32 compute(const v_float32& y, const v_float32& x)
{
v_float32 ax = v_abs(x);
v_float32 ay = v_abs(y);
v_float32 c = v_div(v_min(ax, ay), v_add(v_max(ax, ay), this->eps));
v_float32 cc = v_mul(c, c);
v_float32 a = v_mul(v_fma(v_fma(v_fma(cc, this->p7, this->p5), cc, this->p3), cc, this->p1), c);
a = v_select(v_ge(ax, ay), a, v_sub(this->val90, a));
a = v_select(v_lt(x, this->z), v_sub(this->val180, a), a);
a = v_select(v_lt(y, this->z), v_sub(this->val360, a), a);
return v_mul(a, this->s);
}
v_float32 eps;
v_float32 z;
v_float32 p7;
v_float32 p5;
v_float32 p3;
v_float32 p1;
v_float32 val90;
v_float32 val180;
v_float32 val360;
v_float32 s;
};
v_float32 ax = v_abs(x);
v_float32 ay = v_abs(y);
v_float32 c = v_div(v_min(ax, ay), v_add(v_max(ax, ay), eps));
v_float32 cc = v_mul(c, c);
v_float32 a = v_mul(v_fma(v_fma(v_fma(cc, p7, p5), cc, p3), cc, p1), c);
a = v_select(v_ge(ax, ay), a, v_sub(val90, a));
a = v_select(v_lt(x, z), v_sub(val180, a), a);
a = v_select(v_lt(y, z), v_sub(val360, a), a);
return a;
}
#endif
@@ -124,9 +108,9 @@ static void cartToPolar32f_(const float *X, const float *Y, float *mag, float *a
{
float scale = angleInDegrees ? 1.f : (float)(CV_PI/180);
int i = 0;
#if CV_SIMD
#if (CV_SIMD || CV_SIMD_SCALABLE)
const int VECSZ = VTraits<v_float32>::vlanes();
v_atan_f32 v(scale);
v_float32 s = vx_setall_f32(scale);
for( ; i < len; i += VECSZ*2 )
{
@@ -148,8 +132,8 @@ static void cartToPolar32f_(const float *X, const float *Y, float *mag, float *a
v_float32 m0 = v_sqrt(v_muladd(x0, x0, v_mul(y0, y0)));
v_float32 m1 = v_sqrt(v_muladd(x1, x1, v_mul(y1, y1)));
v_float32 r0 = v.compute(y0, x0);
v_float32 r1 = v.compute(y1, x1);
v_float32 r0 = v_mul(v_atan_f32(y0, x0), s);
v_float32 r1 = v_mul(v_atan_f32(y1, x1), s);
v_store(mag + i, m0);
v_store(mag + i + VECSZ, m1);
@@ -196,13 +180,174 @@ void cartToPolar64f(const double *X, const double *Y, double *mag, double *angle
}
}
namespace {
static inline void SinCos_32f(const float* mag, const float* angle, float* cosval, float* sinval, int len, int angle_in_degrees)
{
const int N = 64;
static const double sin_table[] =
{
0.00000000000000000000, 0.09801714032956060400,
0.19509032201612825000, 0.29028467725446233000,
0.38268343236508978000, 0.47139673682599764000,
0.55557023301960218000, 0.63439328416364549000,
0.70710678118654746000, 0.77301045336273699000,
0.83146961230254524000, 0.88192126434835494000,
0.92387953251128674000, 0.95694033573220894000,
0.98078528040323043000, 0.99518472667219682000,
1.00000000000000000000, 0.99518472667219693000,
0.98078528040323043000, 0.95694033573220894000,
0.92387953251128674000, 0.88192126434835505000,
0.83146961230254546000, 0.77301045336273710000,
0.70710678118654757000, 0.63439328416364549000,
0.55557023301960218000, 0.47139673682599786000,
0.38268343236508989000, 0.29028467725446239000,
0.19509032201612861000, 0.09801714032956082600,
0.00000000000000012246, -0.09801714032956059000,
-0.19509032201612836000, -0.29028467725446211000,
-0.38268343236508967000, -0.47139673682599764000,
-0.55557023301960196000, -0.63439328416364527000,
-0.70710678118654746000, -0.77301045336273666000,
-0.83146961230254524000, -0.88192126434835494000,
-0.92387953251128652000, -0.95694033573220882000,
-0.98078528040323032000, -0.99518472667219693000,
-1.00000000000000000000, -0.99518472667219693000,
-0.98078528040323043000, -0.95694033573220894000,
-0.92387953251128663000, -0.88192126434835505000,
-0.83146961230254546000, -0.77301045336273688000,
-0.70710678118654768000, -0.63439328416364593000,
-0.55557023301960218000, -0.47139673682599792000,
-0.38268343236509039000, -0.29028467725446250000,
-0.19509032201612872000, -0.09801714032956050600,
};
static const double k2 = (2*CV_PI)/N;
static const double sin_a0 = -0.166630293345647*k2*k2*k2;
static const double sin_a2 = k2;
static const double cos_a0 = -0.499818138450326*k2*k2;
/*static const double cos_a2 = 1;*/
double k1;
int i = 0;
if( !angle_in_degrees )
k1 = N/(2*CV_PI);
else
k1 = N/360.;
#if (CV_SIMD || CV_SIMD_SCALABLE)
const int VECSZ = VTraits<v_float32>::vlanes();
const v_float32 scale = vx_setall_f32(angle_in_degrees ? (float)CV_PI / 180.f : 1.f);
for( ; i < len; i += VECSZ*2 )
{
if( i + VECSZ*2 > len )
{
// if it's inplace operation, we cannot repeatedly process
// the tail for the second time, so we have to use the
// scalar code
if( i == 0 || angle == cosval || angle == sinval || mag == cosval || mag == sinval )
break;
i = len - VECSZ*2;
}
v_float32 r0 = v_mul(vx_load(angle + i), scale);
v_float32 r1 = v_mul(vx_load(angle + i + VECSZ), scale);
v_float32 c0, c1, s0, s1;
v_sincos(r0, s0, c0);
v_sincos(r1, s1, c1);
if( mag )
{
v_float32 m0 = vx_load(mag + i);
v_float32 m1 = vx_load(mag + i + VECSZ);
c0 = v_mul(c0, m0);
c1 = v_mul(c1, m1);
s0 = v_mul(s0, m0);
s1 = v_mul(s1, m1);
}
v_store(cosval + i, c0);
v_store(cosval + i + VECSZ, c1);
v_store(sinval + i, s0);
v_store(sinval + i + VECSZ, s1);
}
vx_cleanup();
#endif
for( ; i < len; i++ )
{
double t = angle[i]*k1;
int it = cvRound(t);
t -= it;
int sin_idx = it & (N - 1);
int cos_idx = (N/4 - sin_idx) & (N - 1);
double sin_b = (sin_a0*t*t + sin_a2)*t;
double cos_b = cos_a0*t*t + 1;
double sin_a = sin_table[sin_idx];
double cos_a = sin_table[cos_idx];
double sin_val = sin_a*cos_b + cos_a*sin_b;
double cos_val = cos_a*cos_b - sin_a*sin_b;
if (mag)
{
double mag_val = mag[i];
sin_val *= mag_val;
cos_val *= mag_val;
}
sinval[i] = (float)sin_val;
cosval[i] = (float)cos_val;
}
}
} // anonymous::
void polarToCart32f(const float *mag, const float *angle, float *X, float *Y, int len, bool angleInDegrees)
{
CV_INSTRUMENT_REGION();
SinCos_32f(mag, angle, X, Y, len, angleInDegrees);
}
void polarToCart64f(const double *mag, const double *angle, double *X, double *Y, int len, bool angleInDegrees)
{
CV_INSTRUMENT_REGION();
const int BLKSZ = 128;
float ybuf[BLKSZ], xbuf[BLKSZ], _mbuf[BLKSZ], abuf[BLKSZ];
float* mbuf = mag ? _mbuf : nullptr;
for( int i = 0; i < len; i += BLKSZ )
{
int j, blksz = std::min(BLKSZ, len - i);
for( j = 0; j < blksz; j++ )
{
if (mbuf)
mbuf[j] = (float)mag[i + j];
abuf[j] = (float)angle[i + j];
}
SinCos_32f(mbuf, abuf, xbuf, ybuf, blksz, angleInDegrees);
for( j = 0; j < blksz; j++ )
X[i + j] = xbuf[j];
for( j = 0; j < blksz; j++ )
Y[i + j] = ybuf[j];
}
}
static void fastAtan32f_(const float *Y, const float *X, float *angle, int len, bool angleInDegrees )
{
float scale = angleInDegrees ? 1.f : (float)(CV_PI/180);
int i = 0;
#if CV_SIMD
#if (CV_SIMD || CV_SIMD_SCALABLE)
const int VECSZ = VTraits<v_float32>::vlanes();
v_atan_f32 v(scale);
v_float32 s = vx_setall_f32(scale);
for( ; i < len; i += VECSZ*2 )
{
@@ -221,8 +366,8 @@ static void fastAtan32f_(const float *Y, const float *X, float *angle, int len,
v_float32 y1 = vx_load(Y + i + VECSZ);
v_float32 x1 = vx_load(X + i + VECSZ);
v_float32 r0 = v.compute(y0, x0);
v_float32 r1 = v.compute(y1, x1);
v_float32 r0 = v_mul(v_atan_f32(y0, x0), s);
v_float32 r1 = v_mul(v_atan_f32(y1, x1), s);
v_store(angle + i, r0);
v_store(angle + i + VECSZ, r1);
@@ -273,7 +418,7 @@ void magnitude32f(const float* x, const float* y, float* mag, int len)
int i = 0;
#if CV_SIMD
#if (CV_SIMD || CV_SIMD_SCALABLE)
const int VECSZ = VTraits<v_float32>::vlanes();
for( ; i < len; i += VECSZ*2 )
{
@@ -306,7 +451,7 @@ void magnitude64f(const double* x, const double* y, double* mag, int len)
int i = 0;
#if CV_SIMD_64F
#if (CV_SIMD_64F || CV_SIMD_SCALABLE_64F)
const int VECSZ = VTraits<v_float64>::vlanes();
for( ; i < len; i += VECSZ*2 )
{
+2 -2
View File
@@ -3068,7 +3068,7 @@ double dotProd_32s(const int* src1, const int* src2, int len)
#if CV_SIMD_WIDTH == 16
const int wstep = step * 2;
v_float64 v_sum1 = vx_setzero_f64();
for (; i < len - wstep; i += wstep, src1 += wstep, src2 += wstep)
for (; i <= len - wstep; i += wstep, src1 += wstep, src2 += wstep)
{
v_int32 v_src10 = vx_load(src1);
v_int32 v_src20 = vx_load(src2);
@@ -3079,7 +3079,7 @@ double dotProd_32s(const int* src1, const int* src2, int len)
}
v_sum0 = v_add(v_sum0, v_sum1);
#endif
for (; i < len - step; i += step, src1 += step, src2 += step)
for (; i <= len - step; i += step, src1 += step, src2 += step)
{
v_int32 v_src1 = vx_load(src1);
v_int32 v_src2 = vx_load(src2);
+10
View File
@@ -1876,6 +1876,16 @@ Mat Mat::reshape(int _cn, std::initializer_list<int> newshape_) const
return reshape(_cn, (int)newshape_dims, newshape);
}
Mat Mat::reinterpret(int type) const
{
type = CV_MAT_TYPE(type);
CV_Assert(CV_ELEM_SIZE(this->type()) == CV_ELEM_SIZE(type));
Mat m = *this;
m.flags = (m.flags & ~CV_MAT_TYPE_MASK) | type;
m.updateContinuityFlag();
return m;
}
Mat Mat::diag(const Mat& d)
{
CV_Assert( d.cols == 1 || d.rows == 1 );
-114
View File
@@ -173,74 +173,6 @@ static bool ocl_transpose( InputArray _src, OutputArray _dst )
#endif
#ifdef HAVE_IPP
static bool ipp_transpose( Mat &src, Mat &dst )
{
CV_INSTRUMENT_REGION_IPP();
int type = src.type();
typedef IppStatus (CV_STDCALL * IppiTranspose)(const void * pSrc, int srcStep, void * pDst, int dstStep, IppiSize roiSize);
typedef IppStatus (CV_STDCALL * IppiTransposeI)(const void * pSrcDst, int srcDstStep, IppiSize roiSize);
IppiTranspose ippiTranspose = 0;
IppiTransposeI ippiTranspose_I = 0;
if (dst.data == src.data && dst.cols == dst.rows)
{
CV_SUPPRESS_DEPRECATED_START
ippiTranspose_I =
type == CV_8UC1 ? (IppiTransposeI)ippiTranspose_8u_C1IR :
type == CV_8UC3 ? (IppiTransposeI)ippiTranspose_8u_C3IR :
type == CV_8UC4 ? (IppiTransposeI)ippiTranspose_8u_C4IR :
type == CV_16UC1 ? (IppiTransposeI)ippiTranspose_16u_C1IR :
type == CV_16UC3 ? (IppiTransposeI)ippiTranspose_16u_C3IR :
type == CV_16UC4 ? (IppiTransposeI)ippiTranspose_16u_C4IR :
type == CV_16SC1 ? (IppiTransposeI)ippiTranspose_16s_C1IR :
type == CV_16SC3 ? (IppiTransposeI)ippiTranspose_16s_C3IR :
type == CV_16SC4 ? (IppiTransposeI)ippiTranspose_16s_C4IR :
type == CV_32SC1 ? (IppiTransposeI)ippiTranspose_32s_C1IR :
type == CV_32SC3 ? (IppiTransposeI)ippiTranspose_32s_C3IR :
type == CV_32SC4 ? (IppiTransposeI)ippiTranspose_32s_C4IR :
type == CV_32FC1 ? (IppiTransposeI)ippiTranspose_32f_C1IR :
type == CV_32FC3 ? (IppiTransposeI)ippiTranspose_32f_C3IR :
type == CV_32FC4 ? (IppiTransposeI)ippiTranspose_32f_C4IR : 0;
CV_SUPPRESS_DEPRECATED_END
}
else
{
ippiTranspose =
type == CV_8UC1 ? (IppiTranspose)ippiTranspose_8u_C1R :
type == CV_8UC3 ? (IppiTranspose)ippiTranspose_8u_C3R :
type == CV_8UC4 ? (IppiTranspose)ippiTranspose_8u_C4R :
type == CV_16UC1 ? (IppiTranspose)ippiTranspose_16u_C1R :
type == CV_16UC3 ? (IppiTranspose)ippiTranspose_16u_C3R :
type == CV_16UC4 ? (IppiTranspose)ippiTranspose_16u_C4R :
type == CV_16SC1 ? (IppiTranspose)ippiTranspose_16s_C1R :
type == CV_16SC3 ? (IppiTranspose)ippiTranspose_16s_C3R :
type == CV_16SC4 ? (IppiTranspose)ippiTranspose_16s_C4R :
type == CV_32SC1 ? (IppiTranspose)ippiTranspose_32s_C1R :
type == CV_32SC3 ? (IppiTranspose)ippiTranspose_32s_C3R :
type == CV_32SC4 ? (IppiTranspose)ippiTranspose_32s_C4R :
type == CV_32FC1 ? (IppiTranspose)ippiTranspose_32f_C1R :
type == CV_32FC3 ? (IppiTranspose)ippiTranspose_32f_C3R :
type == CV_32FC4 ? (IppiTranspose)ippiTranspose_32f_C4R : 0;
}
IppiSize roiSize = { src.cols, src.rows };
if (ippiTranspose != 0)
{
if (CV_INSTRUMENT_FUN_IPP(ippiTranspose, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roiSize) >= 0)
return true;
}
else if (ippiTranspose_I != 0)
{
if (CV_INSTRUMENT_FUN_IPP(ippiTranspose_I, dst.ptr(), (int)dst.step, roiSize) >= 0)
return true;
}
return false;
}
#endif
void transpose( InputArray _src, OutputArray _dst )
{
CV_INSTRUMENT_REGION();
@@ -271,8 +203,6 @@ void transpose( InputArray _src, OutputArray _dst )
CALL_HAL(transpose2d, cv_hal_transpose2d, src.data, src.step, dst.data, dst.step, src.cols, src.rows, esz);
CV_IPP_RUN_FAST(ipp_transpose(src, dst))
if( dst.data == src.data )
{
TransposeInplaceFunc func = transposeInplaceTab[esz];
@@ -735,48 +665,6 @@ static bool ocl_flip(InputArray _src, OutputArray _dst, int flipCode )
#endif
#if defined HAVE_IPP
static bool ipp_flip(Mat &src, Mat &dst, int flip_mode)
{
#ifdef HAVE_IPP_IW
CV_INSTRUMENT_REGION_IPP();
// Details: https://github.com/opencv/opencv/issues/12943
if (flip_mode <= 0 /* swap rows */
&& cv::ipp::getIppTopFeatures() != ippCPUID_SSE42
&& (int64_t)(src.total()) * src.elemSize() >= CV_BIG_INT(0x80000000)/*2Gb*/
)
return false;
IppiAxis ippMode;
if(flip_mode < 0)
ippMode = ippAxsBoth;
else if(flip_mode == 0)
ippMode = ippAxsHorizontal;
else
ippMode = ippAxsVertical;
try
{
::ipp::IwiImage iwSrc = ippiGetImage(src);
::ipp::IwiImage iwDst = ippiGetImage(dst);
CV_INSTRUMENT_FUN_IPP(::ipp::iwiMirror, iwSrc, iwDst, ippMode);
}
catch(const ::ipp::IwException &)
{
return false;
}
return true;
#else
CV_UNUSED(src); CV_UNUSED(dst); CV_UNUSED(flip_mode);
return false;
#endif
}
#endif
void flip( InputArray _src, OutputArray _dst, int flip_mode )
{
CV_INSTRUMENT_REGION();
@@ -808,8 +696,6 @@ void flip( InputArray _src, OutputArray _dst, int flip_mode )
CALL_HAL(flip, cv_hal_flip, type, src.ptr(), src.step, src.cols, src.rows,
dst.ptr(), dst.step, flip_mode);
CV_IPP_RUN_FAST(ipp_flip(src, dst, flip_mode));
size_t esz = CV_ELEM_SIZE(type);
if( flip_mode <= 0 )
+6
View File
@@ -1718,6 +1718,12 @@ void _OutputArray::create(const MatShape& shape, int mtype, int i,
}
}
Mat _OutputArray::reinterpret(int mtype) const
{
mtype = CV_MAT_TYPE(mtype);
return getMat().reinterpret(mtype);
}
void _OutputArray::createSameSize(const _InputArray& arr, int mtype) const
{
int arrsz[CV_MAX_DIM], d = arr.sizend(arrsz);
-249
View File
@@ -7,120 +7,12 @@
#include "opencl_kernels_core.hpp"
#include "stat.hpp"
#ifndef OPENCV_IPP_MEAN
#undef HAVE_IPP
#undef CV_IPP_RUN_FAST
#define CV_IPP_RUN_FAST(f, ...)
#undef CV_IPP_RUN
#define CV_IPP_RUN(c, f, ...)
#endif // OPENCV_IPP_MEAN
#include "mean.simd.hpp"
#include "mean.simd_declarations.hpp" // defines CV_CPU_DISPATCH_MODES_ALL=AVX2,...,BASELINE based on CMakeLists.txt content
#ifndef OPENCV_IPP_MEAN
#undef HAVE_IPP
#undef CV_IPP_RUN_FAST
#define CV_IPP_RUN_FAST(f, ...)
#undef CV_IPP_RUN
#define CV_IPP_RUN(c, f, ...)
#endif // OPENCV_IPP_MEAN
namespace cv {
#if defined HAVE_IPP
static bool ipp_mean( Mat &src, Mat &mask, Scalar &ret )
{
CV_INSTRUMENT_REGION_IPP();
#if IPP_VERSION_X100 >= 700
size_t total_size = src.total();
int cn = src.channels();
if (cn > 4)
return false;
int rows = src.size[0], cols = rows ? (int)(total_size/rows) : 0;
if( src.dims <= 2 || (src.isContinuous() && mask.isContinuous() && cols > 0 && (size_t)rows*cols == total_size) )
{
IppiSize sz = { cols, rows };
int type = src.type();
if( !mask.empty() )
{
typedef IppStatus (CV_STDCALL* ippiMaskMeanFuncC1)(const void *, int, const void *, int, IppiSize, Ipp64f *);
ippiMaskMeanFuncC1 ippiMean_C1MR =
type == CV_8UC1 ? (ippiMaskMeanFuncC1)ippiMean_8u_C1MR :
type == CV_16UC1 ? (ippiMaskMeanFuncC1)ippiMean_16u_C1MR :
type == CV_32FC1 ? (ippiMaskMeanFuncC1)ippiMean_32f_C1MR :
0;
if( ippiMean_C1MR )
{
Ipp64f res;
if( CV_INSTRUMENT_FUN_IPP(ippiMean_C1MR, src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, &res) >= 0 )
{
ret = Scalar(res);
return true;
}
}
typedef IppStatus (CV_STDCALL* ippiMaskMeanFuncC3)(const void *, int, const void *, int, IppiSize, int, Ipp64f *);
ippiMaskMeanFuncC3 ippiMean_C3MR =
type == CV_8UC3 ? (ippiMaskMeanFuncC3)ippiMean_8u_C3CMR :
type == CV_16UC3 ? (ippiMaskMeanFuncC3)ippiMean_16u_C3CMR :
type == CV_32FC3 ? (ippiMaskMeanFuncC3)ippiMean_32f_C3CMR :
0;
if( ippiMean_C3MR )
{
Ipp64f res1, res2, res3;
if( CV_INSTRUMENT_FUN_IPP(ippiMean_C3MR, src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, 1, &res1) >= 0 &&
CV_INSTRUMENT_FUN_IPP(ippiMean_C3MR, src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, 2, &res2) >= 0 &&
CV_INSTRUMENT_FUN_IPP(ippiMean_C3MR, src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, 3, &res3) >= 0 )
{
ret = Scalar(res1, res2, res3);
return true;
}
}
}
else
{
typedef IppStatus (CV_STDCALL* ippiMeanFuncHint)(const void*, int, IppiSize, double *, IppHintAlgorithm);
typedef IppStatus (CV_STDCALL* ippiMeanFuncNoHint)(const void*, int, IppiSize, double *);
ippiMeanFuncHint ippiMeanHint =
type == CV_32FC1 ? (ippiMeanFuncHint)ippiMean_32f_C1R :
type == CV_32FC3 ? (ippiMeanFuncHint)ippiMean_32f_C3R :
type == CV_32FC4 ? (ippiMeanFuncHint)ippiMean_32f_C4R :
0;
ippiMeanFuncNoHint ippiMean =
type == CV_8UC1 ? (ippiMeanFuncNoHint)ippiMean_8u_C1R :
type == CV_8UC3 ? (ippiMeanFuncNoHint)ippiMean_8u_C3R :
type == CV_8UC4 ? (ippiMeanFuncNoHint)ippiMean_8u_C4R :
type == CV_16UC1 ? (ippiMeanFuncNoHint)ippiMean_16u_C1R :
type == CV_16UC3 ? (ippiMeanFuncNoHint)ippiMean_16u_C3R :
type == CV_16UC4 ? (ippiMeanFuncNoHint)ippiMean_16u_C4R :
type == CV_16SC1 ? (ippiMeanFuncNoHint)ippiMean_16s_C1R :
type == CV_16SC3 ? (ippiMeanFuncNoHint)ippiMean_16s_C3R :
type == CV_16SC4 ? (ippiMeanFuncNoHint)ippiMean_16s_C4R :
0;
// Make sure only zero or one version of the function pointer is valid
CV_Assert(!ippiMeanHint || !ippiMean);
if( ippiMeanHint || ippiMean )
{
Ipp64f res[4];
IppStatus status = ippiMeanHint ? CV_INSTRUMENT_FUN_IPP(ippiMeanHint, src.ptr(), (int)src.step[0], sz, res, ippAlgHintAccurate) :
CV_INSTRUMENT_FUN_IPP(ippiMean, src.ptr(), (int)src.step[0], sz, res);
if( status >= 0 )
{
for( int i = 0; i < cn; i++ )
ret[i] = res[i];
return true;
}
}
}
}
return false;
#else
return false;
#endif
}
#endif
Scalar mean(InputArray _src, InputArray _mask)
{
CV_INSTRUMENT_REGION();
@@ -133,8 +25,6 @@ Scalar mean(InputArray _src, InputArray _mask)
CV_Assert( cn <= 4 );
CV_IPP_RUN(IPP_VERSION_X100 >= 700, ipp_mean(src, mask, s), s)
if (src.isContinuous() && mask.isContinuous())
{
CALL_HAL_RET2(meanStdDev, cv_hal_meanStdDev, s, src.data, 0, (int)src.total(), 1, src.type(),
@@ -334,143 +224,6 @@ static bool ocl_meanStdDev( InputArray _src, OutputArray _mean, OutputArray _sdv
}
#endif
#ifdef HAVE_IPP
static bool ipp_meanStdDev(Mat& src, OutputArray _mean, OutputArray _sdv, Mat& mask)
{
CV_INSTRUMENT_REGION_IPP();
#if IPP_VERSION_X100 >= 700
int cn = src.channels();
#if IPP_VERSION_X100 < 201801
// IPP_DISABLE: C3C functions can read outside of allocated memory
if (cn > 1)
return false;
#endif
#if IPP_VERSION_X100 >= 201900 && IPP_VERSION_X100 < 201901
// IPP_DISABLE: 32f C3C functions can read outside of allocated memory
if (cn > 1 && src.depth() == CV_32F)
return false;
// SSE4.2 buffer overrun
#if defined(_WIN32) && !defined(_WIN64)
// IPPICV doesn't have AVX2 in 32-bit builds
// However cv::ipp::getIppTopFeatures() may return AVX2 value on AVX2 capable H/W
// details #12959
#else
if (cv::ipp::getIppTopFeatures() == ippCPUID_SSE42) // Linux x64 + OPENCV_IPP=SSE42 is affected too
#endif
{
if (src.depth() == CV_32F && src.dims > 1 && src.size[src.dims - 1] == 6)
return false;
}
#endif
size_t total_size = src.total();
int rows = src.size[0], cols = rows ? (int)(total_size/rows) : 0;
if( src.dims <= 2 || (src.isContinuous() && mask.isContinuous() && cols > 0 && (size_t)rows*cols == total_size) )
{
Ipp64f mean_temp[3];
Ipp64f stddev_temp[3];
Ipp64f *pmean = &mean_temp[0];
Ipp64f *pstddev = &stddev_temp[0];
Mat mean, stddev;
int dcn_mean = -1;
if( _mean.needed() )
{
if( !_mean.fixedSize() )
_mean.create(cn, 1, CV_64F, -1, true);
mean = _mean.getMat();
dcn_mean = (int)mean.total();
pmean = mean.ptr<Ipp64f>();
}
int dcn_stddev = -1;
if( _sdv.needed() )
{
if( !_sdv.fixedSize() )
_sdv.create(cn, 1, CV_64F, -1, true);
stddev = _sdv.getMat();
dcn_stddev = (int)stddev.total();
pstddev = stddev.ptr<Ipp64f>();
}
for( int c = cn; c < dcn_mean; c++ )
pmean[c] = 0;
for( int c = cn; c < dcn_stddev; c++ )
pstddev[c] = 0;
IppiSize sz = { cols, rows };
int type = src.type();
if( !mask.empty() )
{
typedef IppStatus (CV_STDCALL* ippiMaskMeanStdDevFuncC1)(const void *, int, const void *, int, IppiSize, Ipp64f *, Ipp64f *);
ippiMaskMeanStdDevFuncC1 ippiMean_StdDev_C1MR =
type == CV_8UC1 ? (ippiMaskMeanStdDevFuncC1)ippiMean_StdDev_8u_C1MR :
type == CV_16UC1 ? (ippiMaskMeanStdDevFuncC1)ippiMean_StdDev_16u_C1MR :
type == CV_32FC1 ? (ippiMaskMeanStdDevFuncC1)ippiMean_StdDev_32f_C1MR :
0;
if( ippiMean_StdDev_C1MR )
{
if( CV_INSTRUMENT_FUN_IPP(ippiMean_StdDev_C1MR, src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, pmean, pstddev) >= 0 )
{
return true;
}
}
typedef IppStatus (CV_STDCALL* ippiMaskMeanStdDevFuncC3)(const void *, int, const void *, int, IppiSize, int, Ipp64f *, Ipp64f *);
ippiMaskMeanStdDevFuncC3 ippiMean_StdDev_C3CMR =
type == CV_8UC3 ? (ippiMaskMeanStdDevFuncC3)ippiMean_StdDev_8u_C3CMR :
type == CV_16UC3 ? (ippiMaskMeanStdDevFuncC3)ippiMean_StdDev_16u_C3CMR :
type == CV_32FC3 ? (ippiMaskMeanStdDevFuncC3)ippiMean_StdDev_32f_C3CMR :
0;
if( ippiMean_StdDev_C3CMR )
{
if( CV_INSTRUMENT_FUN_IPP(ippiMean_StdDev_C3CMR, src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, 1, &pmean[0], &pstddev[0]) >= 0 &&
CV_INSTRUMENT_FUN_IPP(ippiMean_StdDev_C3CMR, src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, 2, &pmean[1], &pstddev[1]) >= 0 &&
CV_INSTRUMENT_FUN_IPP(ippiMean_StdDev_C3CMR, src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, 3, &pmean[2], &pstddev[2]) >= 0 )
{
return true;
}
}
}
else
{
typedef IppStatus (CV_STDCALL* ippiMeanStdDevFuncC1)(const void *, int, IppiSize, Ipp64f *, Ipp64f *);
ippiMeanStdDevFuncC1 ippiMean_StdDev_C1R =
type == CV_8UC1 ? (ippiMeanStdDevFuncC1)ippiMean_StdDev_8u_C1R :
type == CV_16UC1 ? (ippiMeanStdDevFuncC1)ippiMean_StdDev_16u_C1R :
#if (IPP_VERSION_X100 >= 810)
type == CV_32FC1 ? (ippiMeanStdDevFuncC1)ippiMean_StdDev_32f_C1R ://Aug 2013: bug in IPP 7.1, 8.0
#endif
0;
if( ippiMean_StdDev_C1R )
{
if( CV_INSTRUMENT_FUN_IPP(ippiMean_StdDev_C1R, src.ptr(), (int)src.step[0], sz, pmean, pstddev) >= 0 )
{
return true;
}
}
typedef IppStatus (CV_STDCALL* ippiMeanStdDevFuncC3)(const void *, int, IppiSize, int, Ipp64f *, Ipp64f *);
ippiMeanStdDevFuncC3 ippiMean_StdDev_C3CR =
type == CV_8UC3 ? (ippiMeanStdDevFuncC3)ippiMean_StdDev_8u_C3CR :
type == CV_16UC3 ? (ippiMeanStdDevFuncC3)ippiMean_StdDev_16u_C3CR :
type == CV_32FC3 ? (ippiMeanStdDevFuncC3)ippiMean_StdDev_32f_C3CR :
0;
if( ippiMean_StdDev_C3CR )
{
if( CV_INSTRUMENT_FUN_IPP(ippiMean_StdDev_C3CR, src.ptr(), (int)src.step[0], sz, 1, &pmean[0], &pstddev[0]) >= 0 &&
CV_INSTRUMENT_FUN_IPP(ippiMean_StdDev_C3CR, src.ptr(), (int)src.step[0], sz, 2, &pmean[1], &pstddev[1]) >= 0 &&
CV_INSTRUMENT_FUN_IPP(ippiMean_StdDev_C3CR, src.ptr(), (int)src.step[0], sz, 3, &pmean[2], &pstddev[2]) >= 0 )
{
return true;
}
}
}
}
#else
CV_UNUSED(src); CV_UNUSED(_mean); CV_UNUSED(_sdv); CV_UNUSED(mask);
#endif
return false;
}
#endif
void meanStdDev(InputArray _src, OutputArray _mean, OutputArray _sdv, InputArray _mask)
{
CV_INSTRUMENT_REGION();
@@ -485,8 +238,6 @@ void meanStdDev(InputArray _src, OutputArray _mean, OutputArray _sdv, InputArray
CV_Assert(mask.empty() || ((mask.type() == CV_8U || mask.type() == CV_8S || mask.type() == CV_Bool) && src.size == mask.size));
CV_IPP_RUN(IPP_VERSION_X100 >= 700, ipp_meanStdDev(src, _mean, _sdv, mask));
int k, cn = src.channels(), depth = src.depth();
Mat mean_mat, stddev_mat;
+2 -375
View File
@@ -274,137 +274,6 @@ static bool ocl_norm( InputArray _src, int normType, InputArray _mask, double &
#endif
#ifdef HAVE_IPP
static bool ipp_norm(Mat &src, int normType, Mat &mask, double &result)
{
CV_INSTRUMENT_REGION_IPP();
#if IPP_VERSION_X100 >= 700
size_t total_size = src.total();
int rows = src.size[0], cols = rows ? (int)(total_size/rows) : 0;
if( (src.dims <= 2 || (src.isContinuous() && mask.isContinuous()))
&& cols > 0 && (size_t)rows*cols == total_size )
{
if( !mask.empty() )
{
IppiSize sz = { cols, rows };
int type = src.type();
typedef IppStatus (CV_STDCALL* ippiMaskNormFuncC1)(const void *, int, const void *, int, IppiSize, Ipp64f *);
ippiMaskNormFuncC1 ippiNorm_C1MR =
normType == NORM_INF ?
(type == CV_8UC1 ? (ippiMaskNormFuncC1)ippiNorm_Inf_8u_C1MR :
type == CV_16UC1 ? (ippiMaskNormFuncC1)ippiNorm_Inf_16u_C1MR :
type == CV_32FC1 ? (ippiMaskNormFuncC1)ippiNorm_Inf_32f_C1MR :
0) :
normType == NORM_L1 ?
(type == CV_8UC1 ? (ippiMaskNormFuncC1)ippiNorm_L1_8u_C1MR :
type == CV_16UC1 ? (ippiMaskNormFuncC1)ippiNorm_L1_16u_C1MR :
type == CV_32FC1 ? (ippiMaskNormFuncC1)ippiNorm_L1_32f_C1MR :
0) :
normType == NORM_L2 || normType == NORM_L2SQR ?
(type == CV_8UC1 ? (ippiMaskNormFuncC1)ippiNorm_L2_8u_C1MR :
type == CV_16UC1 ? (ippiMaskNormFuncC1)ippiNorm_L2_16u_C1MR :
type == CV_32FC1 ? (ippiMaskNormFuncC1)ippiNorm_L2_32f_C1MR :
0) : 0;
if( ippiNorm_C1MR )
{
Ipp64f norm;
if( CV_INSTRUMENT_FUN_IPP(ippiNorm_C1MR, src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, &norm) >= 0 )
{
result = (normType == NORM_L2SQR ? (double)(norm * norm) : (double)norm);
return true;
}
}
typedef IppStatus (CV_STDCALL* ippiMaskNormFuncC3)(const void *, int, const void *, int, IppiSize, int, Ipp64f *);
ippiMaskNormFuncC3 ippiNorm_C3CMR =
normType == NORM_INF ?
(type == CV_8UC3 ? (ippiMaskNormFuncC3)ippiNorm_Inf_8u_C3CMR :
type == CV_16UC3 ? (ippiMaskNormFuncC3)ippiNorm_Inf_16u_C3CMR :
type == CV_32FC3 ? (ippiMaskNormFuncC3)ippiNorm_Inf_32f_C3CMR :
0) :
normType == NORM_L1 ?
(type == CV_8UC3 ? (ippiMaskNormFuncC3)ippiNorm_L1_8u_C3CMR :
type == CV_16UC3 ? (ippiMaskNormFuncC3)ippiNorm_L1_16u_C3CMR :
type == CV_32FC3 ? (ippiMaskNormFuncC3)ippiNorm_L1_32f_C3CMR :
0) :
normType == NORM_L2 || normType == NORM_L2SQR ?
(type == CV_8UC3 ? (ippiMaskNormFuncC3)ippiNorm_L2_8u_C3CMR :
type == CV_16UC3 ? (ippiMaskNormFuncC3)ippiNorm_L2_16u_C3CMR :
type == CV_32FC3 ? (ippiMaskNormFuncC3)ippiNorm_L2_32f_C3CMR :
0) : 0;
if( ippiNorm_C3CMR )
{
Ipp64f norm1, norm2, norm3;
if( CV_INSTRUMENT_FUN_IPP(ippiNorm_C3CMR, src.data, (int)src.step[0], mask.data, (int)mask.step[0], sz, 1, &norm1) >= 0 &&
CV_INSTRUMENT_FUN_IPP(ippiNorm_C3CMR, src.data, (int)src.step[0], mask.data, (int)mask.step[0], sz, 2, &norm2) >= 0 &&
CV_INSTRUMENT_FUN_IPP(ippiNorm_C3CMR, src.data, (int)src.step[0], mask.data, (int)mask.step[0], sz, 3, &norm3) >= 0)
{
Ipp64f norm =
normType == NORM_INF ? std::max(std::max(norm1, norm2), norm3) :
normType == NORM_L1 ? norm1 + norm2 + norm3 :
normType == NORM_L2 || normType == NORM_L2SQR ? std::sqrt(norm1 * norm1 + norm2 * norm2 + norm3 * norm3) :
0;
result = (normType == NORM_L2SQR ? (double)(norm * norm) : (double)norm);
return true;
}
}
}
else
{
IppiSize sz = { cols*src.channels(), rows };
int type = src.depth();
typedef IppStatus (CV_STDCALL* ippiNormFuncHint)(const void *, int, IppiSize, Ipp64f *, IppHintAlgorithm hint);
typedef IppStatus (CV_STDCALL* ippiNormFuncNoHint)(const void *, int, IppiSize, Ipp64f *);
ippiNormFuncHint ippiNormHint =
normType == NORM_L1 ?
(type == CV_32FC1 ? (ippiNormFuncHint)ippiNorm_L1_32f_C1R :
0) :
normType == NORM_L2 || normType == NORM_L2SQR ?
(type == CV_32FC1 ? (ippiNormFuncHint)ippiNorm_L2_32f_C1R :
0) : 0;
ippiNormFuncNoHint ippiNorm =
normType == NORM_INF ?
(type == CV_8UC1 ? (ippiNormFuncNoHint)ippiNorm_Inf_8u_C1R :
type == CV_16UC1 ? (ippiNormFuncNoHint)ippiNorm_Inf_16u_C1R :
type == CV_16SC1 ? (ippiNormFuncNoHint)ippiNorm_Inf_16s_C1R :
type == CV_32FC1 ? (ippiNormFuncNoHint)ippiNorm_Inf_32f_C1R :
0) :
normType == NORM_L1 ?
(type == CV_8UC1 ? (ippiNormFuncNoHint)ippiNorm_L1_8u_C1R :
type == CV_16UC1 ? (ippiNormFuncNoHint)ippiNorm_L1_16u_C1R :
type == CV_16SC1 ? (ippiNormFuncNoHint)ippiNorm_L1_16s_C1R :
0) :
normType == NORM_L2 || normType == NORM_L2SQR ?
(
#if !IPP_DISABLE_NORM_8U
type == CV_8UC1 ? (ippiNormFuncNoHint)ippiNorm_L2_8u_C1R :
#endif
type == CV_16UC1 ? (ippiNormFuncNoHint)ippiNorm_L2_16u_C1R :
type == CV_16SC1 ? (ippiNormFuncNoHint)ippiNorm_L2_16s_C1R :
0) : 0;
if( ippiNormHint || ippiNorm )
{
Ipp64f norm;
IppStatus ret = ippiNormHint ? CV_INSTRUMENT_FUN_IPP(ippiNormHint, src.ptr(), (int)src.step[0], sz, &norm, ippAlgHintAccurate) :
CV_INSTRUMENT_FUN_IPP(ippiNorm, src.ptr(), (int)src.step[0], sz, &norm);
if( ret >= 0 )
{
result = (normType == NORM_L2SQR) ? norm * norm : norm;
return true;
}
}
}
}
#else
CV_UNUSED(src); CV_UNUSED(normType); CV_UNUSED(mask); CV_UNUSED(result);
#endif
return false;
} // ipp_norm()
#endif // HAVE_IPP
static NormFunc getNormFunc(int normType, int depth) {
CV_INSTRUMENT_REGION();
CV_CPU_DISPATCH(getNormFunc, (normType, depth), CV_CPU_DISPATCH_MODES_ALL);
@@ -423,7 +292,7 @@ double norm( InputArray _src, int normType, InputArray _mask )
normType == NORM_L2 || normType == NORM_L2SQR ||
((normType == NORM_HAMMING || normType == NORM_HAMMING2) && _src.type() == CV_8U) );
#if defined HAVE_OPENCL || defined HAVE_IPP
#if defined HAVE_OPENCL
double _result = 0;
#endif
@@ -446,8 +315,6 @@ double norm( InputArray _src, int normType, InputArray _mask )
CALL_HAL_RET(norm, cv_hal_norm, result, src.data, 0, mask.data, 0, (int)src.total(), 1, src.type(), normType);
}
CV_IPP_RUN(IPP_VERSION_X100 >= 700, ipp_norm(src, normType, mask, _result), _result);
NormFunc func = getNormFunc(normType >> 1, depth);
CV_Assert( func != 0 );
@@ -651,244 +518,6 @@ static bool ocl_norm( InputArray _src1, InputArray _src2, int normType, InputArr
} // ocl_norm()
#endif // HAVE_OPENCL
#ifdef HAVE_IPP
static bool ipp_norm(InputArray _src1, InputArray _src2, int normType, InputArray _mask, double &result)
{
CV_INSTRUMENT_REGION_IPP();
#if IPP_VERSION_X100 >= 700
Mat src1 = _src1.getMat(), src2 = _src2.getMat(), mask = _mask.getMat();
if( normType & NORM_RELATIVE )
{
normType &= NORM_TYPE_MASK;
size_t total_size = src1.total();
int rows = src1.size[0], cols = rows ? (int)(total_size/rows) : 0;
if( (src1.dims <= 2 || (src1.isContinuous() && src2.isContinuous() && mask.isContinuous()))
&& cols > 0 && (size_t)rows*cols == total_size )
{
if( !mask.empty() )
{
IppiSize sz = { cols, rows };
int type = src1.type();
typedef IppStatus (CV_STDCALL* ippiMaskNormDiffFuncC1)(const void *, int, const void *, int, const void *, int, IppiSize, Ipp64f *);
ippiMaskNormDiffFuncC1 ippiNormRel_C1MR =
normType == NORM_INF ?
(type == CV_8UC1 ? (ippiMaskNormDiffFuncC1)ippiNormRel_Inf_8u_C1MR :
type == CV_16UC1 ? (ippiMaskNormDiffFuncC1)ippiNormRel_Inf_16u_C1MR :
type == CV_32FC1 ? (ippiMaskNormDiffFuncC1)ippiNormRel_Inf_32f_C1MR :
0) :
normType == NORM_L1 ?
(type == CV_8UC1 ? (ippiMaskNormDiffFuncC1)ippiNormRel_L1_8u_C1MR :
type == CV_16UC1 ? (ippiMaskNormDiffFuncC1)ippiNormRel_L1_16u_C1MR :
type == CV_32FC1 ? (ippiMaskNormDiffFuncC1)ippiNormRel_L1_32f_C1MR :
0) :
normType == NORM_L2 || normType == NORM_L2SQR ?
(type == CV_8UC1 ? (ippiMaskNormDiffFuncC1)ippiNormRel_L2_8u_C1MR :
type == CV_16UC1 ? (ippiMaskNormDiffFuncC1)ippiNormRel_L2_16u_C1MR :
type == CV_32FC1 ? (ippiMaskNormDiffFuncC1)ippiNormRel_L2_32f_C1MR :
0) : 0;
if( ippiNormRel_C1MR )
{
Ipp64f norm;
if( CV_INSTRUMENT_FUN_IPP(ippiNormRel_C1MR, src1.ptr(), (int)src1.step[0], src2.ptr(), (int)src2.step[0], mask.ptr(), (int)mask.step[0], sz, &norm) >= 0 )
{
result = (normType == NORM_L2SQR ? (double)(norm * norm) : (double)norm);
return true;
}
}
}
else
{
IppiSize sz = { cols*src1.channels(), rows };
int type = src1.depth();
typedef IppStatus (CV_STDCALL* ippiNormRelFuncHint)(const void *, int, const void *, int, IppiSize, Ipp64f *, IppHintAlgorithm hint);
typedef IppStatus (CV_STDCALL* ippiNormRelFuncNoHint)(const void *, int, const void *, int, IppiSize, Ipp64f *);
ippiNormRelFuncHint ippiNormRelHint =
normType == NORM_L1 ?
(type == CV_32F ? (ippiNormRelFuncHint)ippiNormRel_L1_32f_C1R :
0) :
normType == NORM_L2 || normType == NORM_L2SQR ?
(type == CV_32F ? (ippiNormRelFuncHint)ippiNormRel_L2_32f_C1R :
0) : 0;
ippiNormRelFuncNoHint ippiNormRel =
normType == NORM_INF ?
(
#if !IPP_DISABLE_NORM_8U
type == CV_8U ? (ippiNormRelFuncNoHint)ippiNormRel_Inf_8u_C1R :
#endif
type == CV_16U ? (ippiNormRelFuncNoHint)ippiNormRel_Inf_16u_C1R :
type == CV_16S ? (ippiNormRelFuncNoHint)ippiNormRel_Inf_16s_C1R :
type == CV_32F ? (ippiNormRelFuncNoHint)ippiNormRel_Inf_32f_C1R :
0) :
normType == NORM_L1 ?
(
#if !IPP_DISABLE_NORM_8U
type == CV_8U ? (ippiNormRelFuncNoHint)ippiNormRel_L1_8u_C1R :
#endif
type == CV_16U ? (ippiNormRelFuncNoHint)ippiNormRel_L1_16u_C1R :
type == CV_16S ? (ippiNormRelFuncNoHint)ippiNormRel_L1_16s_C1R :
0) :
normType == NORM_L2 || normType == NORM_L2SQR ?
(
#if !IPP_DISABLE_NORM_8U
type == CV_8U ? (ippiNormRelFuncNoHint)ippiNormRel_L2_8u_C1R :
#endif
type == CV_16U ? (ippiNormRelFuncNoHint)ippiNormRel_L2_16u_C1R :
type == CV_16S ? (ippiNormRelFuncNoHint)ippiNormRel_L2_16s_C1R :
0) : 0;
if( ippiNormRelHint || ippiNormRel )
{
Ipp64f norm;
IppStatus ret = ippiNormRelHint ? CV_INSTRUMENT_FUN_IPP(ippiNormRelHint, src1.ptr(), (int)src1.step[0], src2.ptr(), (int)src2.step[0], sz, &norm, ippAlgHintAccurate) :
CV_INSTRUMENT_FUN_IPP(ippiNormRel, src1.ptr(), (int)src1.step[0], src2.ptr(), (int)src2.step[0], sz, &norm);
if( ret >= 0 )
{
result = (normType == NORM_L2SQR) ? norm * norm : norm;
return true;
}
}
}
}
return false;
}
normType &= NORM_TYPE_MASK;
size_t total_size = src1.total();
int rows = src1.size[0], cols = rows ? (int)(total_size/rows) : 0;
if( (src1.dims <= 2 || (src1.isContinuous() && src2.isContinuous() && mask.isContinuous()))
&& cols > 0 && (size_t)rows*cols == total_size )
{
if( !mask.empty() )
{
IppiSize sz = { cols, rows };
int type = src1.type();
typedef IppStatus (CV_STDCALL* ippiMaskNormDiffFuncC1)(const void *, int, const void *, int, const void *, int, IppiSize, Ipp64f *);
ippiMaskNormDiffFuncC1 ippiNormDiff_C1MR =
normType == NORM_INF ?
(type == CV_8UC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_Inf_8u_C1MR :
type == CV_16UC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_Inf_16u_C1MR :
type == CV_32FC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_Inf_32f_C1MR :
0) :
normType == NORM_L1 ?
(type == CV_8UC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_L1_8u_C1MR :
type == CV_16UC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_L1_16u_C1MR :
type == CV_32FC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_L1_32f_C1MR :
0) :
normType == NORM_L2 || normType == NORM_L2SQR ?
(type == CV_8UC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_L2_8u_C1MR :
type == CV_16UC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_L2_16u_C1MR :
type == CV_32FC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_L2_32f_C1MR :
0) : 0;
if( ippiNormDiff_C1MR )
{
Ipp64f norm;
if( CV_INSTRUMENT_FUN_IPP(ippiNormDiff_C1MR, src1.ptr(), (int)src1.step[0], src2.ptr(), (int)src2.step[0], mask.ptr(), (int)mask.step[0], sz, &norm) >= 0 )
{
result = (normType == NORM_L2SQR ? (double)(norm * norm) : (double)norm);
return true;
}
}
typedef IppStatus (CV_STDCALL* ippiMaskNormDiffFuncC3)(const void *, int, const void *, int, const void *, int, IppiSize, int, Ipp64f *);
ippiMaskNormDiffFuncC3 ippiNormDiff_C3CMR =
normType == NORM_INF ?
(type == CV_8UC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_Inf_8u_C3CMR :
type == CV_16UC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_Inf_16u_C3CMR :
type == CV_32FC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_Inf_32f_C3CMR :
0) :
normType == NORM_L1 ?
(type == CV_8UC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_L1_8u_C3CMR :
type == CV_16UC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_L1_16u_C3CMR :
type == CV_32FC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_L1_32f_C3CMR :
0) :
normType == NORM_L2 || normType == NORM_L2SQR ?
(type == CV_8UC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_L2_8u_C3CMR :
type == CV_16UC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_L2_16u_C3CMR :
type == CV_32FC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_L2_32f_C3CMR :
0) : 0;
if( ippiNormDiff_C3CMR )
{
Ipp64f norm1, norm2, norm3;
if( CV_INSTRUMENT_FUN_IPP(ippiNormDiff_C3CMR, src1.data, (int)src1.step[0], src2.data, (int)src2.step[0], mask.data, (int)mask.step[0], sz, 1, &norm1) >= 0 &&
CV_INSTRUMENT_FUN_IPP(ippiNormDiff_C3CMR, src1.data, (int)src1.step[0], src2.data, (int)src2.step[0], mask.data, (int)mask.step[0], sz, 2, &norm2) >= 0 &&
CV_INSTRUMENT_FUN_IPP(ippiNormDiff_C3CMR, src1.data, (int)src1.step[0], src2.data, (int)src2.step[0], mask.data, (int)mask.step[0], sz, 3, &norm3) >= 0)
{
Ipp64f norm =
normType == NORM_INF ? std::max(std::max(norm1, norm2), norm3) :
normType == NORM_L1 ? norm1 + norm2 + norm3 :
normType == NORM_L2 || normType == NORM_L2SQR ? std::sqrt(norm1 * norm1 + norm2 * norm2 + norm3 * norm3) :
0;
result = (normType == NORM_L2SQR ? (double)(norm * norm) : (double)norm);
return true;
}
}
}
else
{
IppiSize sz = { cols*src1.channels(), rows };
int type = src1.depth();
typedef IppStatus (CV_STDCALL* ippiNormDiffFuncHint)(const void *, int, const void *, int, IppiSize, Ipp64f *, IppHintAlgorithm hint);
typedef IppStatus (CV_STDCALL* ippiNormDiffFuncNoHint)(const void *, int, const void *, int, IppiSize, Ipp64f *);
ippiNormDiffFuncHint ippiNormDiffHint =
normType == NORM_L1 ?
(type == CV_32F ? (ippiNormDiffFuncHint)ippiNormDiff_L1_32f_C1R :
0) :
normType == NORM_L2 || normType == NORM_L2SQR ?
(type == CV_32F ? (ippiNormDiffFuncHint)ippiNormDiff_L2_32f_C1R :
0) : 0;
ippiNormDiffFuncNoHint ippiNormDiff =
normType == NORM_INF ?
(
#if !IPP_DISABLE_NORM_8U
type == CV_8U ? (ippiNormDiffFuncNoHint)ippiNormDiff_Inf_8u_C1R :
#endif
type == CV_16U ? (ippiNormDiffFuncNoHint)ippiNormDiff_Inf_16u_C1R :
type == CV_16S ? (ippiNormDiffFuncNoHint)ippiNormDiff_Inf_16s_C1R :
type == CV_32F ? (ippiNormDiffFuncNoHint)ippiNormDiff_Inf_32f_C1R :
0) :
normType == NORM_L1 ?
(
#if !IPP_DISABLE_NORM_8U
type == CV_8U ? (ippiNormDiffFuncNoHint)ippiNormDiff_L1_8u_C1R :
#endif
type == CV_16U ? (ippiNormDiffFuncNoHint)ippiNormDiff_L1_16u_C1R :
type == CV_16S ? (ippiNormDiffFuncNoHint)ippiNormDiff_L1_16s_C1R :
0) :
normType == NORM_L2 || normType == NORM_L2SQR ?
(
#if !IPP_DISABLE_NORM_8U
type == CV_8U ? (ippiNormDiffFuncNoHint)ippiNormDiff_L2_8u_C1R :
#endif
type == CV_16U ? (ippiNormDiffFuncNoHint)ippiNormDiff_L2_16u_C1R :
type == CV_16S ? (ippiNormDiffFuncNoHint)ippiNormDiff_L2_16s_C1R :
0) : 0;
if( ippiNormDiffHint || ippiNormDiff )
{
Ipp64f norm;
IppStatus ret = ippiNormDiffHint ? CV_INSTRUMENT_FUN_IPP(ippiNormDiffHint, src1.ptr(), (int)src1.step[0], src2.ptr(), (int)src2.step[0], sz, &norm, ippAlgHintAccurate) :
CV_INSTRUMENT_FUN_IPP(ippiNormDiff, src1.ptr(), (int)src1.step[0], src2.ptr(), (int)src2.step[0], sz, &norm);
if( ret >= 0 )
{
result = (normType == NORM_L2SQR) ? norm * norm : norm;
return true;
}
}
}
}
#else
CV_UNUSED(_src1); CV_UNUSED(_src2); CV_UNUSED(normType); CV_UNUSED(_mask); CV_UNUSED(result);
#endif
return false;
} // ipp_norm
#endif // HAVE_IPP
double norm( InputArray _src1, InputArray _src2, int normType, InputArray _mask )
{
CV_INSTRUMENT_REGION();
@@ -896,7 +525,7 @@ double norm( InputArray _src1, InputArray _src2, int normType, InputArray _mask
CV_CheckTypeEQ(_src1.type(), _src2.type(), "Input type mismatch");
CV_Assert(_src1.sameSize(_src2));
#if defined HAVE_OPENCL || defined HAVE_IPP
#if defined HAVE_OPENCL
double _result = 0;
#endif
@@ -919,8 +548,6 @@ double norm( InputArray _src1, InputArray _src2, int normType, InputArray _mask
CALL_HAL_RET(normDiff, cv_hal_normDiff, result, src1.data, 0, src2.data, 0, mask.data, 0, (int)src1.total(), 1, src1.type(), normType);
}
CV_IPP_RUN(IPP_VERSION_X100 >= 700, ipp_norm(_src1, _src2, normType, _mask, _result), _result);
if( normType & NORM_RELATIVE )
{
return norm(_src1, _src2, normType & ~NORM_RELATIVE, _mask)/(norm(_src2, normType, _mask) + DBL_EPSILON);
+115
View File
@@ -0,0 +1,115 @@
// 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 "test_precomp.hpp"
#include <atomic>
#include <opencv2/core/utils/logger.hpp>
namespace opencv_test {
namespace {
using namespace cv::utils::logging;
using namespace cv::utils::logging::internal;
TEST(Core_Logger_Replace, WriteLogMessageRestoreCallWithNullOk)
{
replaceWriteLogMessage(nullptr);
writeLogMessage(cv::utils::logging::LOG_LEVEL_DEBUG, "msg");
SUCCEED();
}
TEST(Core_Logger_Replace, WriteLogMessageExRestoreCallWithNullOk)
{
replaceWriteLogMessageEx(nullptr);
writeLogMessageEx(cv::utils::logging::LOG_LEVEL_DEBUG, "tag", "file", 1000, "func", "msg");
SUCCEED();
}
std::atomic<uint32_t>& getCallFlagger()
{
static std::atomic<uint32_t> callFlagger(0);
return callFlagger;
}
std::atomic<uint32_t>& getCallCounter()
{
static std::atomic<uint32_t> callCounter(0);
return callCounter;
}
void myWriteLogMessage(LogLevel, const char*)
{
getCallFlagger().fetch_or(1024u);
getCallCounter().fetch_add(1u);
}
void myWriteLogMessageEx(LogLevel, const char*, const char*, int, const char*, const char*)
{
getCallFlagger().fetch_or(2048u);
getCallCounter().fetch_add(1u);
}
TEST(Core_Logger_Replace, WriteLogMessageReplaceRestore)
{
uint32_t step_0 = getCallCounter().load();
writeLogMessage(cv::utils::logging::LOG_LEVEL_DEBUG, "msg");
uint32_t step_1 = getCallCounter().load();
EXPECT_EQ(step_0, step_1);
replaceWriteLogMessage(nullptr);
uint32_t step_2 = getCallCounter().load();
EXPECT_EQ(step_1, step_2);
writeLogMessage(cv::utils::logging::LOG_LEVEL_DEBUG, "msg");
uint32_t step_3 = getCallCounter().load();
EXPECT_EQ(step_2, step_3);
replaceWriteLogMessage(myWriteLogMessage);
uint32_t step_4 = getCallCounter().load();
EXPECT_EQ(step_3, step_4);
writeLogMessage(cv::utils::logging::LOG_LEVEL_DEBUG, "msg");
uint32_t step_5 = getCallCounter().load();
EXPECT_EQ(step_4 + 1, step_5);
writeLogMessage(cv::utils::logging::LOG_LEVEL_DEBUG, "msg");
uint32_t step_6 = getCallCounter().load();
EXPECT_EQ(step_5 + 1, step_6);
replaceWriteLogMessage(nullptr);
uint32_t step_7 = getCallCounter().load();
EXPECT_EQ(step_6, step_7);
writeLogMessage(cv::utils::logging::LOG_LEVEL_DEBUG, "msg");
uint32_t step_8 = getCallCounter().load();
EXPECT_EQ(step_7, step_8);
uint32_t flags = getCallFlagger().load();
EXPECT_NE(flags & 1024u, 0u);
}
TEST(Core_Logger_Replace, WriteLogMessageExReplaceRestore)
{
uint32_t step_0 = getCallCounter().load();
writeLogMessageEx(cv::utils::logging::LOG_LEVEL_DEBUG, "tag", "file", 0, "func", "msg");
uint32_t step_1 = getCallCounter().load();
EXPECT_EQ(step_0, step_1);
replaceWriteLogMessageEx(nullptr);
uint32_t step_2 = getCallCounter().load();
EXPECT_EQ(step_1, step_2);
writeLogMessageEx(cv::utils::logging::LOG_LEVEL_DEBUG, "tag", "file", 0, "func", "msg");
uint32_t step_3 = getCallCounter().load();
EXPECT_EQ(step_2, step_3);
replaceWriteLogMessageEx(myWriteLogMessageEx);
uint32_t step_4 = getCallCounter().load();
EXPECT_EQ(step_3, step_4);
writeLogMessageEx(cv::utils::logging::LOG_LEVEL_DEBUG, "tag", "file", 0, "func", "msg");
uint32_t step_5 = getCallCounter().load();
EXPECT_EQ(step_4 + 1, step_5);
writeLogMessageEx(cv::utils::logging::LOG_LEVEL_DEBUG, "tag", "file", 0, "func", "msg");
uint32_t step_6 = getCallCounter().load();
EXPECT_EQ(step_5 + 1, step_6);
replaceWriteLogMessageEx(nullptr);
uint32_t step_7 = getCallCounter().load();
EXPECT_EQ(step_6, step_7);
writeLogMessageEx(cv::utils::logging::LOG_LEVEL_DEBUG, "tag", "file", 0, "func", "msg");
uint32_t step_8 = getCallCounter().load();
EXPECT_EQ(step_7, step_8);
uint32_t flags = getCallFlagger().load();
EXPECT_NE(flags & 2048u, 0u);
}
}} // namespace
+36
View File
@@ -1208,6 +1208,42 @@ TEST(Core_Mat, reshape_ndims_4)
}
}
TEST(Core_Mat, reinterpret_Mat_8UC3_8SC3)
{
cv::Mat A(8, 16, CV_8UC3, cv::Scalar(1, 2, 3));
cv::Mat B = A.reinterpret(CV_8SC3);
EXPECT_EQ(A.data, B.data);
EXPECT_EQ(B.type(), CV_8SC3);
}
TEST(Core_Mat, reinterpret_Mat_8UC4_32FC1)
{
cv::Mat A(8, 16, CV_8UC4, cv::Scalar(1, 2, 3, 4));
cv::Mat B = A.reinterpret(CV_32FC1);
EXPECT_EQ(A.data, B.data);
EXPECT_EQ(B.type(), CV_32FC1);
}
TEST(Core_Mat, reinterpret_OutputArray_8UC3_8SC3) {
cv::Mat A(8, 16, CV_8UC3, cv::Scalar(1, 2, 3));
cv::OutputArray C(A);
cv::Mat B = C.reinterpret(CV_8SC3);
EXPECT_EQ(A.data, B.data);
EXPECT_EQ(B.type(), CV_8SC3);
}
TEST(Core_Mat, reinterpret_OutputArray_8UC4_32FC1) {
cv::Mat A(8, 16, CV_8UC4, cv::Scalar(1, 2, 3, 4));
cv::OutputArray C(A);
cv::Mat B = C.reinterpret(CV_32FC1);
EXPECT_EQ(A.data, B.data);
EXPECT_EQ(B.type(), CV_32FC1);
}
TEST(Core_Mat, push_back)
{
Mat a = (Mat_<float>(1,2) << 3.4884074f, 1.4159607f);
+1 -1
View File
@@ -1214,7 +1214,7 @@ bool CV_OperationsTest::TestSVD()
cvtest::norm(Vt*Vt.t(), I, NORM_INF) > FLT_EPSILON ||
W.at<float>(2) < 0 || W.at<float>(1) < W.at<float>(2) ||
W.at<float>(0) < W.at<float>(1) ||
cvtest::norm(U*Mat::diag(W)*Vt, Q, NORM_INF) > FLT_EPSILON )
cvtest::norm(U*Mat::diag(W)*Vt, Q, NORM_INF) > FLT_EPSILON*2 )
throw test_excep();
}
catch(const test_excep&)