From 78dd1893bb854b314ea22a6a61cda0f910354dfb Mon Sep 17 00:00:00 2001 From: Maria Dimashova Date: Sat, 20 Oct 2012 19:37:19 +0400 Subject: [PATCH] added tests for cv::merge, cv::split, cv::phase --- modules/core/test/test_mat.cpp | 214 ++++++++++++++++++++++++++++++++ modules/core/test/test_math.cpp | 94 ++++++++++++++ 2 files changed, 308 insertions(+) diff --git a/modules/core/test/test_mat.cpp b/modules/core/test/test_mat.cpp index 8c72789b06..e30da7258d 100644 --- a/modules/core/test/test_mat.cpp +++ b/modules/core/test/test_mat.cpp @@ -858,10 +858,224 @@ void Core_ArrayOpTest::run( int /* start_from */) ts->set_failed_test_info(errcount == 0 ? cvtest::TS::OK : cvtest::TS::FAIL_INVALID_OUTPUT); } + +template +int calcDiffElemCountImpl(const vector& mv, const Mat& m) +{ + int diffElemCount = 0; + const size_t mChannels = m.channels(); + for(int y = 0; y < m.rows; y++) + { + for(int x = 0; x < m.cols; x++) + { + const ElemType* mElem = &m.at(y,x*mChannels); + size_t loc = 0; + for(size_t i = 0; i < mv.size(); i++) + { + const size_t mvChannel = mv[i].channels(); + const ElemType* mvElem = &mv[i].at(y,x*mvChannel); + for(size_t li = 0; li < mvChannel; li++) + if(mElem[loc + li] != mvElem[li]) + diffElemCount++; + loc += mvChannel; + } + CV_Assert(loc == mChannels); + } + } + return diffElemCount; +} + +static +int calcDiffElemCount(const vector& mv, const Mat& m) +{ + int depth = m.depth(); + switch (depth) + { + case CV_8U: + return calcDiffElemCountImpl(mv, m); + case CV_8S: + return calcDiffElemCountImpl(mv, m); + case CV_16U: + return calcDiffElemCountImpl(mv, m); + case CV_16S: + return calcDiffElemCountImpl(mv, m); + case CV_32S: + return calcDiffElemCountImpl(mv, m); + case CV_32F: + return calcDiffElemCountImpl(mv, m); + case CV_64F: + return calcDiffElemCountImpl(mv, m); + } + + return INT_MAX; +} + +class Core_MergeSplitBaseTest : public cvtest::BaseTest +{ +protected: + virtual int run_case(int depth, size_t channels, const Size& size, RNG& rng) = 0; + + virtual void run(int) + { + // m is Mat + // mv is vector + const int minMSize = 1; + const int maxMSize = 100; + const size_t maxMvSize = 10; + + RNG& rng = theRNG(); + Size mSize(rng.uniform(minMSize, maxMSize), rng.uniform(minMSize, maxMSize)); + size_t mvSize = rng(maxMvSize); + + int res = cvtest::TS::OK, curRes = res; + curRes = run_case(CV_8U, mvSize, mSize, rng); + res = curRes != cvtest::TS::OK ? curRes : res; + + curRes = run_case(CV_8S, mvSize, mSize, rng); + res = curRes != cvtest::TS::OK ? curRes : res; + + curRes = run_case(CV_16U, mvSize, mSize, rng); + res = curRes != cvtest::TS::OK ? curRes : res; + + curRes = run_case(CV_16S, mvSize, mSize, rng); + res = curRes != cvtest::TS::OK ? curRes : res; + + curRes = run_case(CV_32S, mvSize, mSize, rng); + res = curRes != cvtest::TS::OK ? curRes : res; + + curRes = run_case(CV_32F, mvSize, mSize, rng); + res = curRes != cvtest::TS::OK ? curRes : res; + + curRes = run_case(CV_64F, mvSize, mSize, rng); + res = curRes != cvtest::TS::OK ? curRes : res; + + ts->set_failed_test_info(res); + } +}; + +class Core_MergeTest : public Core_MergeSplitBaseTest +{ +public: + Core_MergeTest() {} + ~Core_MergeTest() {} + +protected: + virtual int run_case(int depth, size_t matCount, const Size& size, RNG& rng) + { + const int maxMatChannels = 10; + + vector src(matCount); + int channels = 0; + for(size_t i = 0; i < src.size(); i++) + { + Mat m(size, CV_MAKETYPE(depth, rng.uniform(1,maxMatChannels))); + rng.fill(m, RNG::UNIFORM, 0, 100, true); + channels += m.channels(); + src[i] = m; + } + + Mat dst; + merge(src, dst); + + // check result + stringstream commonLog; + commonLog << "Depth " << depth << " :"; + if(dst.depth() != depth) + { + ts->printf(cvtest::TS::LOG, "%s incorrect depth of dst (%d instead of %d)\n", + commonLog.str().c_str(), dst.depth(), depth); + return cvtest::TS::FAIL_INVALID_OUTPUT; + } + if(dst.size() != size) + { + ts->printf(cvtest::TS::LOG, "%s incorrect size of dst (%d x %d instead of %d x %d)\n", + commonLog.str().c_str(), dst.rows, dst.cols, size.height, size.width); + return cvtest::TS::FAIL_INVALID_OUTPUT; + } + if(dst.channels() != channels) + { + ts->printf(cvtest::TS::LOG, "%s: incorrect channels count of dst (%d instead of %d)\n", + commonLog.str().c_str(), dst.channels(), channels); + return cvtest::TS::FAIL_INVALID_OUTPUT; + } + + int diffElemCount = calcDiffElemCount(src, dst); + if(diffElemCount > 0) + { + ts->printf(cvtest::TS::LOG, "%s: there are incorrect elements in dst (part of them is %f)\n", + commonLog.str().c_str(), static_cast(diffElemCount)/(channels*size.area())); + return cvtest::TS::FAIL_INVALID_OUTPUT; + } + + return cvtest::TS::OK; + } +}; + +class Core_SplitTest : public Core_MergeSplitBaseTest +{ +public: + Core_SplitTest() {} + ~Core_SplitTest() {} + +protected: + virtual int run_case(int depth, size_t channels, const Size& size, RNG& rng) + { + Mat src(size, CV_MAKETYPE(depth, channels)); + rng.fill(src, RNG::UNIFORM, 0, 100, true); + + vector dst; + split(src, dst); + + // check result + stringstream commonLog; + commonLog << "Depth " << depth << " :"; + if(dst.size() != channels) + { + ts->printf(cvtest::TS::LOG, "%s incorrect count of matrices in dst (%d instead of %d)\n", + commonLog.str().c_str(), dst.size(), channels); + return cvtest::TS::FAIL_INVALID_OUTPUT; + } + for(size_t i = 0; i < dst.size(); i++) + { + if(dst[i].size() != size) + { + ts->printf(cvtest::TS::LOG, "%s incorrect size of dst[%d] (%d x %d instead of %d x %d)\n", + commonLog.str().c_str(), i, dst[i].rows, dst[i].cols, size.height, size.width); + return cvtest::TS::FAIL_INVALID_OUTPUT; + } + if(dst[i].depth() != depth) + { + ts->printf(cvtest::TS::LOG, "%s: incorrect depth of dst[%d] (%d instead of %d)\n", + commonLog.str().c_str(), i, dst[i].depth(), depth); + return cvtest::TS::FAIL_INVALID_OUTPUT; + } + if(dst[i].channels() != 1) + { + ts->printf(cvtest::TS::LOG, "%s: incorrect channels count of dst[%d] (%d instead of %d)\n", + commonLog.str().c_str(), i, dst[i].channels(), 1); + return cvtest::TS::FAIL_INVALID_OUTPUT; + } + } + + int diffElemCount = calcDiffElemCount(dst, src); + if(diffElemCount > 0) + { + ts->printf(cvtest::TS::LOG, "%s: there are incorrect elements in dst (part of them is %f)\n", + commonLog.str().c_str(), static_cast(diffElemCount)/(channels*size.area())); + return cvtest::TS::FAIL_INVALID_OUTPUT; + } + + return cvtest::TS::OK; + } +}; + TEST(Core_PCA, accuracy) { Core_PCATest test; test.safe_run(); } TEST(Core_Reduce, accuracy) { Core_ReduceTest test; test.safe_run(); } TEST(Core_Array, basic_operations) { Core_ArrayOpTest test; test.safe_run(); } +TEST(Core_Merge, shape_operations) { Core_MergeTest test; test.safe_run(); } +TEST(Core_Split, shape_operations) { Core_SplitTest test; test.safe_run(); } + TEST(Core_IOArray, submat_assignment) { diff --git a/modules/core/test/test_math.cpp b/modules/core/test/test_math.cpp index dfc58b72ff..5dd8450623 100644 --- a/modules/core/test/test_math.cpp +++ b/modules/core/test/test_math.cpp @@ -2348,6 +2348,99 @@ void Core_SolvePolyTest::run( int ) } } +class Core_PhaseTest : public cvtest::BaseTest +{ +public: + Core_PhaseTest() {} + ~Core_PhaseTest() {} +protected: + virtual void run(int) + { + const float maxAngleDiff = 0.5; //in degrees + const int axisCount = 8; + const int dim = theRNG().uniform(1,10); + const float scale = theRNG().uniform(1.f, 100.f); + Mat x(axisCount + 1, dim, CV_32FC1), + y(axisCount + 1, dim, CV_32FC1); + Mat anglesInDegrees(axisCount + 1, dim, CV_32FC1); + + // fill the data + x.row(0).setTo(Scalar(0)); + y.row(0).setTo(Scalar(0)); + anglesInDegrees.row(0).setTo(Scalar(0)); + + x.row(1).setTo(Scalar(scale)); + y.row(1).setTo(Scalar(0)); + anglesInDegrees.row(1).setTo(Scalar(0)); + + x.row(2).setTo(Scalar(scale)); + y.row(2).setTo(Scalar(scale)); + anglesInDegrees.row(2).setTo(Scalar(45)); + + x.row(3).setTo(Scalar(0)); + y.row(3).setTo(Scalar(scale)); + anglesInDegrees.row(3).setTo(Scalar(90)); + + x.row(4).setTo(Scalar(-scale)); + y.row(4).setTo(Scalar(scale)); + anglesInDegrees.row(4).setTo(Scalar(135)); + + x.row(5).setTo(Scalar(-scale)); + y.row(5).setTo(Scalar(0)); + anglesInDegrees.row(5).setTo(Scalar(180)); + + x.row(6).setTo(Scalar(-scale)); + y.row(6).setTo(Scalar(-scale)); + anglesInDegrees.row(6).setTo(Scalar(225)); + + x.row(7).setTo(Scalar(0)); + y.row(7).setTo(Scalar(-scale)); + anglesInDegrees.row(7).setTo(Scalar(270)); + + x.row(8).setTo(Scalar(scale)); + y.row(8).setTo(Scalar(-scale)); + anglesInDegrees.row(8).setTo(Scalar(315)); + + Mat resInRad, resInDeg; + phase(x, y, resInRad, false); + phase(x, y, resInDeg, true); + + CV_Assert(resInRad.size() == x.size()); + CV_Assert(resInRad.type() == x.type()); + + CV_Assert(resInDeg.size() == x.size()); + CV_Assert(resInDeg.type() == x.type()); + + // check the result + int outOfRangeCount = countNonZero((resInDeg > 360) | (resInDeg < 0)); + if(outOfRangeCount > 0) + { + ts->printf(cvtest::TS::LOG, "There are result angles that are out of range [0, 360] (part of them is %f)\n", + static_cast(outOfRangeCount)/resInDeg.total()); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + } + + Mat diff = abs(anglesInDegrees - resInDeg); + int errDegCount = diff.total() - countNonZero((diff < maxAngleDiff) | ((360 - diff) < maxAngleDiff)); + if(errDegCount > 0) + { + ts->printf(cvtest::TS::LOG, "There are incorrect result angles (in degrees) (part of them is %f)\n", + static_cast(errDegCount)/resInDeg.total()); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + } + + Mat convertedRes = resInRad * 180. / CV_PI; + double normDiff = norm(convertedRes - resInDeg); + if(normDiff > FLT_EPSILON) + { + ts->printf(cvtest::TS::LOG, "There are incorrect result angles (in radians)\n"); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + } + + ts->set_failed_test_info(cvtest::TS::OK); + } +}; + class Core_CheckRange_Empty : public cvtest::BaseTest { public: @@ -2471,6 +2564,7 @@ TEST(Core_SVD, accuracy) { Core_SVDTest test; test.safe_run(); } TEST(Core_SVBkSb, accuracy) { Core_SVBkSbTest test; test.safe_run(); } TEST(Core_Trace, accuracy) { Core_TraceTest test; test.safe_run(); } TEST(Core_SolvePoly, accuracy) { Core_SolvePolyTest test; test.safe_run(); } +TEST(Core_Phase, accuracy) { Core_PhaseTest test; test.safe_run(); } // TODO: eigenvv, invsqrt, cbrt, fastarctan, (round, floor, ceil(?)),