From 90673101666ed52d953fed8fea7ccff0188c0252 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Wed, 21 Jun 2017 01:59:07 +0000 Subject: [PATCH] core(test): added cv::sortIdx accuracy tests --- modules/core/test/test_operations.cpp | 159 ++++++++++++++++++-- modules/ts/include/opencv2/ts.hpp | 28 ++-- modules/ts/include/opencv2/ts/cuda_test.hpp | 2 + modules/ts/include/opencv2/ts/ocl_test.hpp | 4 +- 4 files changed, 170 insertions(+), 23 deletions(-) diff --git a/modules/core/test/test_operations.cpp b/modules/core/test/test_operations.cpp index 2526ef8a10..aea5d5daee 100644 --- a/modules/core/test/test_operations.cpp +++ b/modules/core/test/test_operations.cpp @@ -41,17 +41,10 @@ //M*/ #include "test_precomp.hpp" +#include "opencv2/ts/ocl_test.hpp" // T-API like tests -#include -#include -#include -#include -#include -#include - -using namespace cv; -using namespace std; - +namespace cvtest { +namespace { class CV_OperationsTest : public cvtest::BaseTest { @@ -1120,8 +1113,8 @@ void CV_OperationsTest::run( int /* start_from */) if (!TestTemplateMat()) return; - /* if (!TestMatND()) - return;*/ + if (!TestMatND()) + return; if (!TestSparseMat()) return; @@ -1254,3 +1247,145 @@ TEST(MatTestRoi, adjustRoiOverflow) ASSERT_EQ(roi.rows, m.rows); } + + +CV_ENUM(SortRowCol, SORT_EVERY_COLUMN, SORT_EVERY_ROW) +CV_ENUM(SortOrder, SORT_ASCENDING, SORT_DESCENDING) + +PARAM_TEST_CASE(sortIdx, MatDepth, SortRowCol, SortOrder, Size, bool) +{ + int type; + Size size; + int flags; + bool use_roi; + + Mat src, src_roi; + Mat dst, dst_roi; + + virtual void SetUp() + { + int depth = GET_PARAM(0); + int rowFlags = GET_PARAM(1); + int orderFlags = GET_PARAM(2); + size = GET_PARAM(3); + use_roi = GET_PARAM(4); + + type = CV_MAKE_TYPE(depth, 1); + + flags = rowFlags | orderFlags; + } + + void generateTestData() + { + Border srcBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); + randomSubMat(src, src_roi, size, srcBorder, type, -100, 100); + + Border dstBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); + randomSubMat(dst, dst_roi, size, dstBorder, CV_32S, 5, 16); + } + + template + void check_(const cv::Mat& values_, const cv::Mat_& idx_) + { + cv::Mat_& values = (cv::Mat_&)values_; + cv::Mat_& idx = (cv::Mat_&)idx_; + size_t N = values.total(); + std::vector processed(N, false); + int prevIdx = idx(0); + T prevValue = values(prevIdx); + processed[prevIdx] = true; + for (size_t i = 1; i < N; i++) + { + int nextIdx = idx((int)i); + T value = values(nextIdx); + ASSERT_EQ(false, processed[nextIdx]) << "Indexes must be unique. i=" << i << " idx=" << nextIdx << std::endl << idx; + processed[nextIdx] = true; + if ((flags & SORT_DESCENDING) == SORT_DESCENDING) + ASSERT_GE(prevValue, value) << "i=" << i << " prevIdx=" << prevIdx << " idx=" << nextIdx; + else + ASSERT_LE(prevValue, value) << "i=" << i << " prevIdx=" << prevIdx << " idx=" << nextIdx; + prevValue = value; + prevIdx = nextIdx; + } + } + + void validate() + { + ASSERT_EQ(CV_32SC1, dst_roi.type()); + ASSERT_EQ(size, dst_roi.size()); + bool isColumn = (flags & SORT_EVERY_COLUMN) == SORT_EVERY_COLUMN; + size_t N = isColumn ? src_roi.cols : src_roi.rows; + Mat values_row((int)N, 1, type), idx_row((int)N, 1, CV_32S); + for (size_t i = 0; i < N; i++) + { + SCOPED_TRACE(cv::format("row/col=%d", (int)i)); + if (isColumn) + { + src_roi.col((int)i).copyTo(values_row); + dst_roi.col((int)i).copyTo(idx_row); + } + else + { + src_roi.row((int)i).copyTo(values_row); + dst_roi.row((int)i).copyTo(idx_row); + } + switch(type) + { + case CV_8U: check_(values_row, idx_row); break; + case CV_8S: check_(values_row, idx_row); break; + case CV_16S: check_(values_row, idx_row); break; + case CV_32S: check_(values_row, idx_row); break; + case CV_32F: check_(values_row, idx_row); break; + case CV_64F: check_(values_row, idx_row); break; + default: ASSERT_FALSE(true) << "Unsupported type: " << type; + } + } + } +}; + +TEST_P(sortIdx, simple) +{ + for (int j = 0; j < 5; j++) + { + generateTestData(); + + cv::sortIdx(src_roi, dst_roi, flags); + validate(); + } +} + +INSTANTIATE_TEST_CASE_P(Core, sortIdx, Combine( + Values(CV_8U, CV_8S, CV_16S, CV_32S, CV_32F, CV_64F), // depth + Values(SORT_EVERY_COLUMN, SORT_EVERY_ROW), + Values(SORT_ASCENDING, SORT_DESCENDING), + Values(Size(3, 3), Size(16, 8)), + ::testing::Bool() +)); + + +TEST(Core_sortIdx, regression_8941) +{ + cv::Mat src = (cv::Mat_(3, 3) << + 1, 2, 3, + 0, 9, 5, + 8, 1, 6 + ); + cv::Mat expected = (cv::Mat_(3, 1) << + 1, + 0, + 2 + ); + + cv::Mat result; + cv::sortIdx(src.col(0), result, CV_SORT_EVERY_COLUMN | CV_SORT_ASCENDING); +#if 0 + std::cout << src.col(0) << std::endl; + std::cout << result << std::endl; +#endif + ASSERT_EQ(expected.size(), result.size()); + EXPECT_EQ(0, cvtest::norm(expected, result, NORM_INF)) << + "result=" << std::endl << result << std::endl << + "expected=" << std::endl << expected; +} + +}} // namespace diff --git a/modules/ts/include/opencv2/ts.hpp b/modules/ts/include/opencv2/ts.hpp index a1981926ff..382a087dde 100644 --- a/modules/ts/include/opencv2/ts.hpp +++ b/modules/ts/include/opencv2/ts.hpp @@ -6,6 +6,14 @@ #include "cvconfig.h" +#include +#include +#include +#include +#include +#include +#include + #ifdef WINRT #pragma warning(disable:4447) // Disable warning 'main' signature found without threading model #endif @@ -46,14 +54,10 @@ namespace cvtest using std::vector; using std::string; -using cv::RNG; -using cv::Mat; -using cv::Scalar; -using cv::Size; -using cv::Point; -using cv::Rect; -using cv::InputArray; -using cv::noArray; +using namespace cv; +using testing::Values; +using testing::Combine; + class SkipTestException: public cv::Exception { @@ -632,10 +636,12 @@ int main(int argc, char **argv) \ } //namespace cvtest -#endif // OPENCV_TS_HPP - #include "opencv2/ts/ts_perf.hpp" +namespace cvtest { +using perf::MatDepth; +} + #ifdef WINRT #ifndef __FSTREAM_EMULATED__ #define __FSTREAM_EMULATED__ @@ -734,3 +740,5 @@ public: } // namespace std #endif // __FSTREAM_EMULATED__ #endif // WINRT + +#endif // OPENCV_TS_HPP diff --git a/modules/ts/include/opencv2/ts/cuda_test.hpp b/modules/ts/include/opencv2/ts/cuda_test.hpp index 2780927304..b1077614cb 100644 --- a/modules/ts/include/opencv2/ts/cuda_test.hpp +++ b/modules/ts/include/opencv2/ts/cuda_test.hpp @@ -109,6 +109,7 @@ namespace cvtest CV_EXPORTS testing::AssertionResult assertMatNear(const char* expr1, const char* expr2, const char* eps_expr, cv::InputArray m1, cv::InputArray m2, double eps); + #undef EXPECT_MAT_NEAR #define EXPECT_MAT_NEAR(m1, m2, eps) EXPECT_PRED_FORMAT3(cvtest::assertMatNear, m1, m2, eps) #define ASSERT_MAT_NEAR(m1, m2, eps) ASSERT_PRED_FORMAT3(cvtest::assertMatNear, m1, m2, eps) @@ -153,6 +154,7 @@ namespace cvtest CV_EXPORTS double checkSimilarity(cv::InputArray m1, cv::InputArray m2); + #undef EXPECT_MAT_SIMILAR #define EXPECT_MAT_SIMILAR(mat1, mat2, eps) \ { \ ASSERT_EQ(mat1.type(), mat2.type()); \ diff --git a/modules/ts/include/opencv2/ts/ocl_test.hpp b/modules/ts/include/opencv2/ts/ocl_test.hpp index c967cd7efa..8c94ede4f9 100644 --- a/modules/ts/include/opencv2/ts/ocl_test.hpp +++ b/modules/ts/include/opencv2/ts/ocl_test.hpp @@ -94,6 +94,7 @@ do \ EXPECT_LE(TestUtils::checkNorm1(mat), eps) \ } while ((void)0, 0) +#undef EXPECT_MAT_NEAR #define EXPECT_MAT_NEAR(mat1, mat2, eps) \ do \ { \ @@ -178,6 +179,7 @@ do \ << "Size: " << name ## _roi.size() << std::endl; \ } while ((void)0, 0) +#undef EXPECT_MAT_SIMILAR #define EXPECT_MAT_SIMILAR(mat1, mat2, eps) \ do \ { \ @@ -325,7 +327,7 @@ struct CV_EXPORTS TSTestWithParam : public TestUtils, public ::testing::TestWith }; #undef PARAM_TEST_CASE -#define PARAM_TEST_CASE(name, ...) struct name : public TSTestWithParam< std::tr1::tuple< __VA_ARGS__ > > +#define PARAM_TEST_CASE(name, ...) struct name : public ::cvtest::ocl::TSTestWithParam< std::tr1::tuple< __VA_ARGS__ > > #ifndef IMPLEMENT_PARAM_CLASS #define IMPLEMENT_PARAM_CLASS(name, type) \ -- GitLab