From 53e685461ead4dda09cc7ac4d3c9f1c9e1a16e90 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Tue, 28 Feb 2017 18:50:09 +0300 Subject: [PATCH 1/3] stitching: force "stable" RNG --- modules/stitching/src/matchers.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/stitching/src/matchers.cpp b/modules/stitching/src/matchers.cpp index edd6b61931..a02bd8b593 100644 --- a/modules/stitching/src/matchers.cpp +++ b/modules/stitching/src/matchers.cpp @@ -70,9 +70,12 @@ struct MatchPairsBody : ParallelLoopBody void operator ()(const Range &r) const { + cv::RNG rng = cv::theRNG(); // save entry rng state const int num_images = static_cast(features.size()); for (int i = r.start; i < r.end; ++i) { + cv::theRNG() = cv::RNG(rng.state + i); // force "stable" RNG seed for each processed pair + int from = near_pairs[i].first; int to = near_pairs[i].second; int pair_idx = from*num_images + to; From 147f3ebf0add6e281b5fc0a4d0c2826502ce88cd Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Tue, 28 Feb 2017 18:50:56 +0300 Subject: [PATCH 2/3] flann: use OpenCV theRNG() std::rand() has no thread-safe guarantee. --- .../include/opencv2/flann/kdtree_index.h | 5 ++++ .../flann/include/opencv2/flann/lsh_table.h | 4 +++ modules/flann/include/opencv2/flann/random.h | 28 +++++++++++++++++-- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/modules/flann/include/opencv2/flann/kdtree_index.h b/modules/flann/include/opencv2/flann/kdtree_index.h index dc0971c9ef..3f6ee01740 100644 --- a/modules/flann/include/opencv2/flann/kdtree_index.h +++ b/modules/flann/include/opencv2/flann/kdtree_index.h @@ -125,7 +125,12 @@ public: /* Construct the randomized trees. */ for (int i = 0; i < trees_; i++) { /* Randomize the order of vectors to allow for unbiased sampling. */ +#ifndef OPENCV_FLANN_USE_STD_RAND + cv::randShuffle(vind_); +#else std::random_shuffle(vind_.begin(), vind_.end()); +#endif + tree_roots_[i] = divideTree(&vind_[0], int(size_) ); } } diff --git a/modules/flann/include/opencv2/flann/lsh_table.h b/modules/flann/include/opencv2/flann/lsh_table.h index 8ef2bd3810..2a52fbcf7e 100644 --- a/modules/flann/include/opencv2/flann/lsh_table.h +++ b/modules/flann/include/opencv2/flann/lsh_table.h @@ -350,7 +350,11 @@ inline LshTable::LshTable(unsigned int feature_size, unsigned int // A bit brutal but fast to code std::vector indices(feature_size * CHAR_BIT); for (size_t i = 0; i < feature_size * CHAR_BIT; ++i) indices[i] = i; +#ifndef OPENCV_FLANN_USE_STD_RAND + cv::randShuffle(indices); +#else std::random_shuffle(indices.begin(), indices.end()); +#endif // Generate a random set of order of subsignature_size_ bits for (unsigned int i = 0; i < key_size_; ++i) { diff --git a/modules/flann/include/opencv2/flann/random.h b/modules/flann/include/opencv2/flann/random.h index a3cf5ec53d..d6784747c0 100644 --- a/modules/flann/include/opencv2/flann/random.h +++ b/modules/flann/include/opencv2/flann/random.h @@ -40,13 +40,31 @@ namespace cvflann { +inline int rand() +{ +#ifndef OPENCV_FLANN_USE_STD_RAND +# if INT_MAX == RAND_MAX + int v = cv::theRNG().next() & INT_MAX; +# else + int v = cv::theRNG().uniform(0, RAND_MAX + 1); +# endif +#else + int v = std::rand(); +#endif // OPENCV_FLANN_USE_STD_RAND + return v; +} + /** * Seeds the random number generator * @param seed Random seed */ inline void seed_random(unsigned int seed) { - srand(seed); +#ifndef OPENCV_FLANN_USE_STD_RAND + cv::theRNG() = cv::RNG(seed); +#else + std::srand(seed); +#endif } /* @@ -60,7 +78,7 @@ inline void seed_random(unsigned int seed) */ inline double rand_double(double high = 1.0, double low = 0) { - return low + ((high-low) * (std::rand() / (RAND_MAX + 1.0))); + return low + ((high-low) * (rand() / (RAND_MAX + 1.0))); } /** @@ -71,7 +89,7 @@ inline double rand_double(double high = 1.0, double low = 0) */ inline int rand_int(int high = RAND_MAX, int low = 0) { - return low + (int) ( double(high-low) * (std::rand() / (RAND_MAX + 1.0))); + return low + (int) ( double(high-low) * (rand() / (RAND_MAX + 1.0))); } /** @@ -107,7 +125,11 @@ public: for (int i = 0; i < size_; ++i) vals_[i] = i; // shuffle the elements in the array +#ifndef OPENCV_FLANN_USE_STD_RAND + cv::randShuffle(vals_); +#else std::random_shuffle(vals_.begin(), vals_.end()); +#endif counter_ = 0; } From e65c6270bf080ab3802c12fe024af9a4bde2ead6 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Wed, 1 Mar 2017 14:28:23 +0300 Subject: [PATCH 3/3] stitching(perf): workaround test failures force other RNG seed --- modules/stitching/perf/perf_stich.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/stitching/perf/perf_stich.cpp b/modules/stitching/perf/perf_stich.cpp index ded2571585..ee78d6d2f4 100644 --- a/modules/stitching/perf/perf_stich.cpp +++ b/modules/stitching/perf/perf_stich.cpp @@ -2,6 +2,8 @@ #include "opencv2/imgcodecs.hpp" #include "opencv2/opencv_modules.hpp" +#include "opencv2/core/ocl.hpp" + using namespace std; using namespace cv; using namespace perf; @@ -161,6 +163,9 @@ PERF_TEST_P(stitchDatasets, affine, testing::Combine(AFFINE_DATASETS, TEST_DETEC Ptr stitcher = Stitcher::create(Stitcher::SCANS, false); stitcher->setFeaturesFinder(featuresFinder); + if (cv::ocl::useOpenCL()) + cv::theRNG() = cv::RNG(12345); // prevent fails of Windows OpenCL builds (see #8294) + startTimer(); stitcher->stitch(imgs, pano); stopTimer();