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)
{
}
}
+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:
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(?)),