1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-29 23:33:05 +04:00

Merge pull request #26256 from vpisarev:expanded_tests_for_norm

extended Norm tests to prove that cv::norm() already supports all the types.

cv::norm() already provides enough functionality; just extended tests to prove it. See #24887

- [x] I agree to contribute to the project under Apache 2 License.
- [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
- [x] The PR is proposed to the proper branch
- [x] There is a reference to the original bug report and related work
- [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable
      Patch to opencv_extra has the same branch name.
- [x] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
Vadim Pisarevsky
2024-10-07 17:07:59 +03:00
committed by GitHub
parent ff9820ea5c
commit 68a81888ec
4 changed files with 142 additions and 19 deletions
+124 -12
View File
@@ -281,6 +281,61 @@ normL2_(const T* src, const uchar* mask, ST* _result, int len, int cn)
return 0;
}
static int
normInf_Bool(const uchar* src, const uchar* mask, int* _result, int len, int cn)
{
int result = *_result;
if( !mask )
{
for ( int i = 0; i < len*cn; i++ ) {
result = std::max(result, (int)(src[i] != 0));
if (result != 0)
break;
}
}
else
{
for( int i = 0; i < len; i++, src += cn )
if( mask[i] )
{
for( int k = 0; k < cn; k++ )
result = std::max(result, (int)(src[k] != 0));
if (result != 0)
break;
}
}
*_result = result;
return 0;
}
static int
normL1_Bool(const uchar* src, const uchar* mask, int* _result, int len, int cn)
{
int result = *_result;
if( !mask )
{
for ( int i = 0; i < len*cn; i++ )
result += (int)(src[i] != 0);
}
else
{
for( int i = 0; i < len; i++, src += cn )
if( mask[i] )
{
for( int k = 0; k < cn; k++ )
result += (int)(src[k] != 0);
}
}
*_result = result;
return 0;
}
static int
normL2_Bool(const uchar* src, const uchar* mask, int* _result, int len, int cn)
{
return normL1_Bool(src, mask, _result, len, cn);
}
template<typename T, typename ST> int
normDiffInf_(const T* src1, const T* src2, const uchar* mask, ST* _result, int len, int cn)
{
@@ -347,6 +402,61 @@ normDiffL2_(const T* src1, const T* src2, const uchar* mask, ST* _result, int le
return 0;
}
static int
normDiffInf_Bool(const uchar* src1, const uchar* src2, const uchar* mask, int* _result, int len, int cn)
{
int result = *_result;
if( !mask )
{
for( int i = 0; i < len*cn; i++ ) {
result = std::max(result, (int)((src1[i] != 0) != (src2[i] != 0)));
if (result != 0)
break;
}
}
else
{
for( int i = 0; i < len; i++, src1 += cn, src2 += cn )
if( mask[i] )
{
for( int k = 0; k < cn; k++ )
result = std::max(result, (int)((src1[k] != 0) != (src2[k] != 0)));
if (result != 0)
break;
}
}
*_result = result;
return 0;
}
static int
normDiffL1_Bool(const uchar* src1, const uchar* src2, const uchar* mask, int* _result, int len, int cn)
{
int result = *_result;
if( !mask )
{
for( int i = 0; i < len*cn; i++ )
result += (int)((src1[i] != 0) != (src2[i] != 0));
}
else
{
for( int i = 0; i < len; i++, src1 += cn, src2 += cn )
if( mask[i] )
{
for( int k = 0; k < cn; k++ )
result += (int)((src1[k] != 0) != (src2[k] != 0));
}
}
*_result = result;
return 0;
}
static int
normDiffL2_Bool(const uchar* src1, const uchar* src2, const uchar* mask, int* _result, int len, int cn)
{
return normDiffL1_Bool(src1, src2, mask, _result, len, cn);
}
#define CV_DEF_NORM_FUNC(L, suffix, type, ntype) \
static int norm##L##_##suffix(const type* src, const uchar* mask, ntype* r, int len, int cn) \
{ return norm##L##_<type, ntype>(src, mask, r, len, cn); } \
@@ -389,7 +499,7 @@ static NormFunc getNormFunc(int normType, int depth)
(NormFunc)normInf_64f,
(NormFunc)GET_OPTIMIZED(normInf_16f),
(NormFunc)GET_OPTIMIZED(normInf_16bf),
0,
(NormFunc)normInf_Bool,
(NormFunc)GET_OPTIMIZED(normInf_64u),
(NormFunc)GET_OPTIMIZED(normInf_64s),
(NormFunc)GET_OPTIMIZED(normInf_32u),
@@ -405,7 +515,7 @@ static NormFunc getNormFunc(int normType, int depth)
(NormFunc)normL1_64f,
(NormFunc)GET_OPTIMIZED(normL1_16f),
(NormFunc)GET_OPTIMIZED(normL1_16bf),
0,
(NormFunc)normL1_Bool,
(NormFunc)GET_OPTIMIZED(normL1_64u),
(NormFunc)GET_OPTIMIZED(normL1_64s),
(NormFunc)GET_OPTIMIZED(normL1_32u),
@@ -421,7 +531,7 @@ static NormFunc getNormFunc(int normType, int depth)
(NormFunc)normL2_64f,
(NormFunc)GET_OPTIMIZED(normL2_16f),
(NormFunc)GET_OPTIMIZED(normL2_16bf),
0,
(NormFunc)normL2_Bool,
(NormFunc)GET_OPTIMIZED(normL2_64u),
(NormFunc)GET_OPTIMIZED(normL2_64s),
(NormFunc)GET_OPTIMIZED(normL2_32u),
@@ -446,7 +556,7 @@ static NormDiffFunc getNormDiffFunc(int normType, int depth)
(NormDiffFunc)normDiffInf_64f,
(NormDiffFunc)GET_OPTIMIZED(normDiffInf_16f),
(NormDiffFunc)GET_OPTIMIZED(normDiffInf_16bf),
0,
(NormDiffFunc)normDiffInf_Bool,
(NormDiffFunc)GET_OPTIMIZED(normDiffInf_64u),
(NormDiffFunc)GET_OPTIMIZED(normDiffInf_64s),
(NormDiffFunc)GET_OPTIMIZED(normDiffInf_32u),
@@ -462,7 +572,7 @@ static NormDiffFunc getNormDiffFunc(int normType, int depth)
(NormDiffFunc)normDiffL1_64f,
(NormDiffFunc)GET_OPTIMIZED(normDiffL1_16f),
(NormDiffFunc)GET_OPTIMIZED(normDiffL1_16bf),
0,
(NormDiffFunc)normDiffL1_Bool,
(NormDiffFunc)GET_OPTIMIZED(normDiffL1_64u),
(NormDiffFunc)GET_OPTIMIZED(normDiffL1_64s),
(NormDiffFunc)GET_OPTIMIZED(normDiffL1_32u),
@@ -478,7 +588,7 @@ static NormDiffFunc getNormDiffFunc(int normType, int depth)
(NormDiffFunc)normDiffL2_64f,
(NormDiffFunc)GET_OPTIMIZED(normDiffL2_16f),
(NormDiffFunc)GET_OPTIMIZED(normDiffL2_16bf),
0,
(NormDiffFunc)normDiffL2_Bool,
(NormDiffFunc)GET_OPTIMIZED(normDiffL2_64u),
(NormDiffFunc)GET_OPTIMIZED(normDiffL2_64s),
(NormDiffFunc)GET_OPTIMIZED(normDiffL2_32u),
@@ -788,13 +898,14 @@ double norm( InputArray _src, int normType, InputArray _mask )
CV_CheckLT((size_t)it.size, (size_t)INT_MAX, "");
bool is_fp16 = depth == CV_16F || depth == CV_16BF;
if ((normType == NORM_L1 && (depth <= CV_16S || is_fp16)) ||
((normType == NORM_L2 || normType == NORM_L2SQR) && (depth <= CV_8S || is_fp16)))
if ((normType == NORM_L1 && (depth <= CV_16S || depth == CV_Bool || is_fp16)) ||
((normType == NORM_L2 || normType == NORM_L2SQR) && (depth <= CV_8S || depth == CV_Bool || is_fp16)))
{
// special case to handle "integer" overflow in accumulator
const size_t esz = src.elemSize();
const int total = (int)it.size;
const int blockSize0 = (is_fp16 ? (1 << 10) :
depth == CV_Bool ? (1 << 30) :
normType == NORM_L1 && depth <= CV_8S ? (1 << 23) : (1 << 15))/cn;
const int blockSize = std::min(total, blockSize0);
union {
@@ -834,7 +945,7 @@ double norm( InputArray _src, int normType, InputArray _mask )
if( normType == NORM_INF )
{
if(depth <= CV_32S || depth == CV_32U)
if(depth <= CV_32S || depth == CV_32U || depth == CV_Bool)
return result.u;
if (depth == CV_32F || is_fp16)
return result.f;
@@ -1243,13 +1354,14 @@ double norm( InputArray _src1, InputArray _src2, int normType, InputArray _mask
bool is_fp16 = depth == CV_16F || depth == CV_16BF;
if ((normType == NORM_L1 && (depth <= CV_16S || is_fp16)) ||
((normType == NORM_L2 || normType == NORM_L2SQR) && (depth <= CV_8S || is_fp16)))
if ((normType == NORM_L1 && (depth <= CV_16S || depth == CV_Bool || is_fp16)) ||
((normType == NORM_L2 || normType == NORM_L2SQR) && (depth <= CV_8S || depth == CV_Bool || is_fp16)))
{
// special case to handle "integer" overflow in accumulator
const size_t esz = src1.elemSize();
const int total = (int)it.size;
const int blockSize0 = (is_fp16 ? (1 << 10) :
depth == CV_Bool ? (1 << 30) :
normType == NORM_L1 && depth <= CV_8S ? (1 << 23) : (1 << 15))/cn;
const int blockSize = std::min(total, blockSize0);
union {
@@ -1290,7 +1402,7 @@ double norm( InputArray _src1, InputArray _src2, int normType, InputArray _mask
if( normType == NORM_INF )
{
if (depth <= CV_32S || depth == CV_32U)
if (depth <= CV_32S || depth == CV_32U || depth == CV_Bool)
return result.u;
if (depth == CV_32F || is_fp16)
return result.f;
+1 -1
View File
@@ -2038,7 +2038,7 @@ OCL_INSTANTIATE_TEST_CASE_P(Arithm, Magnitude, Combine(::testing::Values(CV_32F,
OCL_INSTANTIATE_TEST_CASE_P(Arithm, Flip, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool()));
OCL_INSTANTIATE_TEST_CASE_P(Arithm, MinMaxIdx, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool()));
OCL_INSTANTIATE_TEST_CASE_P(Arithm, MinMaxIdx_Mask, Combine(OCL_ALL_DEPTHS, ::testing::Values(Channels(1)), Bool()));
OCL_INSTANTIATE_TEST_CASE_P(Arithm, Norm, Combine(OCL_ALL_DEPTHS_16F, OCL_ALL_CHANNELS, Bool()));
OCL_INSTANTIATE_TEST_CASE_P(Arithm, Norm, Combine(OCL_ABSOLUTELY_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool()));
OCL_INSTANTIATE_TEST_CASE_P(Arithm, Sqrt, Combine(::testing::Values(CV_32F, CV_64F), OCL_ALL_CHANNELS, Bool()));
OCL_INSTANTIATE_TEST_CASE_P(Arithm, Normalize, Combine(OCL_ALL_DEPTHS, Values(Channels(1)), Bool()));
OCL_INSTANTIATE_TEST_CASE_P(Arithm, InRange, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool(), Bool()));
@@ -371,6 +371,7 @@ IMPLEMENT_PARAM_CLASS(Channels, int)
#define OCL_ON(...) cv::ocl::setUseOpenCL(true); __VA_ARGS__ ;
#define OCL_ALL_DEPTHS Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F)
#define OCL_ABSOLUTELY_ALL_DEPTHS Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32U, CV_64S, CV_64U, CV_16F, CV_16BF, CV_32F, CV_64F, CV_Bool)
//, CV_16F, CV_16BF, CV_64U, CV_64S, CV_32U)
#define OCL_ALL_DEPTHS_16F Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F, CV_16F)
#define OCL_ALL_CHANNELS Values(1, 2, 3, 4)
+16 -6
View File
@@ -86,9 +86,14 @@ double getMinVal(int depth)
{
depth = CV_MAT_DEPTH(depth);
double val = depth == CV_8U ? 0 : depth == CV_8S ? SCHAR_MIN : depth == CV_16U ? 0 :
depth == CV_16S ? SHRT_MIN : depth == CV_32S ? INT_MIN :
depth == CV_32F ? -FLT_MAX : depth == CV_64F ? -DBL_MAX :
depth == CV_16F ? -65504
depth == CV_16S ? SHRT_MIN : depth == CV_32S ? INT_MIN :
depth == CV_32F ? -FLT_MAX : depth == CV_64F ? -DBL_MAX :
depth == CV_16F ? -65504 :
depth == CV_16BF ? -FLT_MAX :
depth == CV_32U ? 0 :
depth == CV_64U ? 0 :
depth == CV_64S ? (double)0x8000000000000000LL :
depth == CV_Bool ? 0
: -1;
CV_Assert(val != -1);
return val;
@@ -98,9 +103,14 @@ double getMaxVal(int depth)
{
depth = CV_MAT_DEPTH(depth);
double val = depth == CV_8U ? UCHAR_MAX : depth == CV_8S ? SCHAR_MAX : depth == CV_16U ? USHRT_MAX :
depth == CV_16S ? SHRT_MAX : depth == CV_32S ? INT_MAX :
depth == CV_32F ? FLT_MAX : depth == CV_64F ? DBL_MAX :
depth == CV_16F ? 65504
depth == CV_16S ? SHRT_MAX : depth == CV_32S ? INT_MAX :
depth == CV_32F ? FLT_MAX : depth == CV_64F ? DBL_MAX :
depth == CV_16F ? 65504 :
depth == CV_16BF ? FLT_MAX :
depth == CV_32U ? UINT_MAX :
depth == CV_64U ? (double)0xFFFFFFFFFFFFFFFFULL :
depth == CV_64S ? (double)0x7fffffffffffffffLL :
depth == CV_Bool ? 1
: -1;
CV_Assert(val != -1);
return val;