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
2025-04-28 22:13:51 +03:00
243 changed files with 12965 additions and 3216 deletions
+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);