1
0
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:
Rostislav Vasilikhin
2023-11-09 08:32:47 +01:00
committed by GitHub
parent 34f34f6227
commit 53aad98a1a
15 changed files with 1190 additions and 138 deletions
+132
View File
@@ -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