mirror of
https://github.com/opencv/opencv.git
synced 2026-07-31 00:03:03 +04:00
Merge pull request #23098 from savuor:nanMask
finiteMask() and doubles for patchNaNs() #23098 Related to #22826 Connected PR in extra: [#1037@extra](https://github.com/opencv/opencv_extra/pull/1037) ### TODOs: - [ ] Vectorize `finiteMask()` for 64FC3 and 64FC4 ### Changes This PR: * adds a new function `finiteMask()` * extends `patchNaNs()` by CV_64F support * moves `patchNaNs()` and `finiteMask()` to a separate file **NOTE:** now the function is called `finiteMask()` as discussed with the OpenCV core team ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [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:
committed by
GitHub
parent
34f34f6227
commit
53aad98a1a
@@ -1,4 +1,5 @@
|
||||
#include "perf_precomp.hpp"
|
||||
#include "opencv2/core/softfloat.hpp"
|
||||
#include <numeric>
|
||||
|
||||
namespace opencv_test
|
||||
@@ -451,4 +452,135 @@ INSTANTIATE_TEST_CASE_P(/*nothing*/ , BinaryOpTest,
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
///////////// PatchNaNs ////////////////////////
|
||||
|
||||
template<typename _Tp>
|
||||
_Tp randomNan(RNG& rng);
|
||||
|
||||
template<>
|
||||
float randomNan(RNG& rng)
|
||||
{
|
||||
uint32_t r = rng.next();
|
||||
Cv32suf v;
|
||||
v.u = r;
|
||||
// exp & set a bit to avoid zero mantissa
|
||||
v.u = v.u | 0x7f800001;
|
||||
return v.f;
|
||||
}
|
||||
|
||||
template<>
|
||||
double randomNan(RNG& rng)
|
||||
{
|
||||
uint32_t r0 = rng.next();
|
||||
uint32_t r1 = rng.next();
|
||||
Cv64suf v;
|
||||
v.u = (uint64_t(r0) << 32) | uint64_t(r1);
|
||||
// exp &set a bit to avoid zero mantissa
|
||||
v.u = v.u | 0x7ff0000000000001;
|
||||
return v.f;
|
||||
}
|
||||
|
||||
typedef Size_MatType PatchNaNsFixture;
|
||||
|
||||
PERF_TEST_P_(PatchNaNsFixture, PatchNaNs)
|
||||
{
|
||||
const Size_MatType_t params = GetParam();
|
||||
Size srcSize = get<0>(params);
|
||||
const int type = get<1>(params), cn = CV_MAT_CN(type), depth = CV_MAT_DEPTH(type);
|
||||
|
||||
Mat src(srcSize, type);
|
||||
declare.in(src, WARMUP_RNG).out(src);
|
||||
|
||||
// generating NaNs
|
||||
{
|
||||
srcSize.width *= cn;
|
||||
RNG& rng = theRNG();
|
||||
for (int y = 0; y < srcSize.height; ++y)
|
||||
{
|
||||
float *const ptrf = src.ptr<float>(y);
|
||||
double *const ptrd = src.ptr<double>(y);
|
||||
for (int x = 0; x < srcSize.width; ++x)
|
||||
{
|
||||
if (depth == CV_32F)
|
||||
{
|
||||
ptrf[x] = (x + y) % 2 == 0 ? randomNan<float >(rng) : ptrf[x];
|
||||
}
|
||||
else if (depth == CV_64F)
|
||||
{
|
||||
ptrd[x] = (x + y) % 2 == 0 ? randomNan<double>(rng) : ptrd[x];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CYCLE() cv::patchNaNs(src, 17.7);
|
||||
|
||||
SANITY_CHECK(src);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/*nothing*/ , PatchNaNsFixture,
|
||||
testing::Combine(
|
||||
testing::Values(szVGA, sz720p, sz1080p, sz2160p),
|
||||
testing::Values(CV_32FC1, CV_32FC2, CV_32FC3, CV_32FC4, CV_64FC1, CV_64FC2, CV_64FC3, CV_64FC4)
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
////////////// finiteMask ////////////////////////
|
||||
|
||||
typedef Size_MatType FiniteMaskFixture;
|
||||
|
||||
PERF_TEST_P_(FiniteMaskFixture, FiniteMask)
|
||||
{
|
||||
const Size_MatType_t params = GetParam();
|
||||
Size srcSize = get<0>(params);
|
||||
const int type = get<1>(params), cn = CV_MAT_CN(type), depth = CV_MAT_DEPTH(type);
|
||||
|
||||
Mat src(srcSize, type);
|
||||
Mat mask(srcSize, CV_8UC1);
|
||||
declare.in(src, WARMUP_RNG).out(mask);
|
||||
|
||||
// generating NaNs
|
||||
{
|
||||
srcSize.width *= cn;
|
||||
const softfloat fpinf = softfloat ::inf();
|
||||
const softfloat fninf = softfloat ::inf().setSign(true);
|
||||
const softdouble dpinf = softdouble::inf();
|
||||
const softdouble dninf = softdouble::inf().setSign(true);
|
||||
RNG& rng = theRNG();
|
||||
for (int y = 0; y < srcSize.height; ++y)
|
||||
{
|
||||
float *const ptrf = src.ptr<float>(y);
|
||||
double *const ptrd = src.ptr<double>(y);
|
||||
for (int x = 0; x < srcSize.width; ++x)
|
||||
{
|
||||
int rem = (x + y) % 10;
|
||||
if (depth == CV_32F)
|
||||
{
|
||||
ptrf[x] = rem < 4 ? randomNan<float >(rng) :
|
||||
rem == 5 ? (float )((x + y)%2 ? fpinf : fninf) : ptrf[x];
|
||||
}
|
||||
else if (depth == CV_64F)
|
||||
{
|
||||
ptrd[x] = rem < 4 ? randomNan<double>(rng) :
|
||||
rem == 5 ? (double)((x + y)%2 ? dpinf : dninf) : ptrd[x];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CYCLE() cv::finiteMask(src, mask);
|
||||
|
||||
SANITY_CHECK(mask);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/*nothing*/ , FiniteMaskFixture,
|
||||
testing::Combine(
|
||||
testing::Values(szVGA, sz720p, sz1080p, sz2160p),
|
||||
testing::Values(CV_32FC1, CV_32FC2, CV_32FC3, CV_32FC4, CV_64FC1, CV_64FC2, CV_64FC3, CV_64FC4)
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
Reference in New Issue
Block a user