added tests for cv::merge, cv::split, cv::phase
authorMaria Dimashova <maria.dimashova@gmail.com>
Sat, 20 Oct 2012 15:37:19 +0000 (19:37 +0400)
committerMaria Dimashova <maria.dimashova@gmail.com>
Sun, 21 Oct 2012 08:22:39 +0000 (12:22 +0400)
modules/core/test/test_mat.cpp
modules/core/test/test_math.cpp

index 8c72789..e30da72 100644 (file)
@@ -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 <class ElemType>
+int calcDiffElemCountImpl(const vector<Mat>& 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<ElemType>(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<ElemType>(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<Mat>& mv, const Mat& m)
+{
+    int depth = m.depth();
+    switch (depth)
+    {
+    case CV_8U:
+        return calcDiffElemCountImpl<uchar>(mv, m);
+    case CV_8S:
+        return calcDiffElemCountImpl<char>(mv, m);
+    case CV_16U:
+        return calcDiffElemCountImpl<unsigned short>(mv, m);
+    case CV_16S:
+        return calcDiffElemCountImpl<short int>(mv, m);
+    case CV_32S:
+        return calcDiffElemCountImpl<int>(mv, m);
+    case CV_32F:
+        return calcDiffElemCountImpl<float>(mv, m);
+    case CV_64F:
+        return calcDiffElemCountImpl<double>(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<Mat>
+        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<Mat> 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<float>(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<Mat> 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<float>(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)
 {
index dfc58b7..5dd8450 100644 (file)
@@ -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<float>(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<float>(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(?)),