1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-30 07:43:03 +04:00

Merge branch 4.x

This commit is contained in:
Alexander Alekhin
2021-04-09 10:30:38 +00:00
1114 changed files with 64039 additions and 14611 deletions
+5 -1
View File
@@ -2,7 +2,7 @@
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
// Copyright (C) 2018-2020 Intel Corporation
// Copyright (C) 2018-2021 Intel Corporation
#ifndef OPENCV_GAPI_CORE_TESTS_HPP
@@ -151,6 +151,9 @@ GAPI_TEST_FIXTURE(WarpPerspectiveTest, initMatrixRandU,
GAPI_TEST_FIXTURE(WarpAffineTest, initMatrixRandU,
FIXTURE_API(CompareMats, double , double, int, int, cv::Scalar),
6, cmpF, angle, scale, flags, border_mode, border_value)
GAPI_TEST_FIXTURE(KMeansNDTest, initMatrixRandU, FIXTURE_API(CompareMats, int, cv::KmeansFlags), 3, cmpF, K, flags)
GAPI_TEST_FIXTURE(KMeans2DTest, initNothing, FIXTURE_API(int, cv::KmeansFlags), 2, K, flags)
GAPI_TEST_FIXTURE(KMeans3DTest, initNothing, FIXTURE_API(int, cv::KmeansFlags), 2, K, flags)
GAPI_TEST_EXT_BASE_FIXTURE(ParseSSDBLTest, ParserSSDTest, initNothing,
FIXTURE_API(float, int), 2, confidence_threshold, filter_label)
@@ -160,6 +163,7 @@ GAPI_TEST_EXT_BASE_FIXTURE(ParseYoloTest, ParserYoloTest, initNothing,
FIXTURE_API(float, float, int, std::pair<bool,int>), 4, confidence_threshold, nms_threshold, num_classes, dims_config)
GAPI_TEST_FIXTURE(SizeTest, initMatrixRandU, <>, 0)
GAPI_TEST_FIXTURE(SizeRTest, initNothing, <>, 0)
GAPI_TEST_FIXTURE(SizeMFTest, initNothing, <>, 0)
} // opencv_test
#endif //OPENCV_GAPI_CORE_TESTS_HPP
@@ -0,0 +1,180 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
// Copyright (C) 2021 Intel Corporation
#ifndef OPENCV_GAPI_CORE_TESTS_COMMON_HPP
#define OPENCV_GAPI_CORE_TESTS_COMMON_HPP
#include "gapi_tests_common.hpp"
#include "../../include/opencv2/gapi/core.hpp"
#include <opencv2/core.hpp>
namespace opencv_test
{
namespace
{
template <typename Elem, typename CmpF>
inline bool compareKMeansOutputs(const std::vector<Elem>& outGAPI,
const std::vector<Elem>& outOCV,
const CmpF& = AbsExact().to_compare_obj())
{
return AbsExactVector<Elem>().to_compare_f()(outGAPI, outOCV);
}
inline bool compareKMeansOutputs(const cv::Mat& outGAPI,
const cv::Mat& outOCV,
const CompareMats& cmpF)
{
return cmpF(outGAPI, outOCV);
}
}
// Overload with initializing the labels
template<typename Labels, typename In>
cv::GComputation kmeansTestGAPI(const In& in, const Labels& bestLabels, const int K,
const cv::KmeansFlags flags, cv::GCompileArgs&& args,
double& compact_gapi, Labels& labels_gapi, In& centers_gapi)
{
const cv::TermCriteria criteria(cv::TermCriteria::MAX_ITER + cv::TermCriteria::EPS, 30, 0);
const int attempts = 1;
cv::detail::g_type_of_t<In> gIn, centers;
cv::GOpaque<double> compactness;
cv::detail::g_type_of_t<Labels> inLabels, outLabels;
std::tie(compactness, outLabels, centers) =
cv::gapi::kmeans(gIn, K, inLabels, criteria, attempts, flags);
cv::GComputation c(cv::GIn(gIn, inLabels), cv::GOut(compactness, outLabels, centers));
c.apply(cv::gin(in, bestLabels), cv::gout(compact_gapi, labels_gapi, centers_gapi),
std::move(args));
return c;
}
// Overload for vector<Point> tests w/o initializing the labels
template<typename Pt>
cv::GComputation kmeansTestGAPI(const std::vector<Pt>& in, const int K,
const cv::KmeansFlags flags, cv::GCompileArgs&& args,
double& compact_gapi, std::vector<int>& labels_gapi,
std::vector<Pt>& centers_gapi)
{
const cv::TermCriteria criteria(cv::TermCriteria::MAX_ITER + cv::TermCriteria::EPS, 30, 0);
const int attempts = 1;
cv::GArray<Pt> gIn, centers;
cv::GOpaque<double> compactness;
cv::GArray<int> inLabels(std::vector<int>{}), outLabels;
std::tie(compactness, outLabels, centers) =
cv::gapi::kmeans(gIn, K, inLabels, criteria, attempts, flags);
cv::GComputation c(cv::GIn(gIn), cv::GOut(compactness, outLabels, centers));
c.apply(cv::gin(in), cv::gout(compact_gapi, labels_gapi, centers_gapi), std::move(args));
return c;
}
// Overload for Mat tests w/o initializing the labels
static cv::GComputation kmeansTestGAPI(const cv::Mat& in, const int K,
const cv::KmeansFlags flags, cv::GCompileArgs&& args,
double& compact_gapi, cv::Mat& labels_gapi,
cv::Mat& centers_gapi)
{
const cv::TermCriteria criteria(cv::TermCriteria::MAX_ITER + cv::TermCriteria::EPS, 30, 0);
const int attempts = 1;
cv::GMat gIn, centers, labels;
cv::GOpaque<double> compactness;
std::tie(compactness, labels, centers) = cv::gapi::kmeans(gIn, K, criteria, attempts, flags);
cv::GComputation c(cv::GIn(gIn), cv::GOut(compactness, labels, centers));
c.apply(cv::gin(in), cv::gout(compact_gapi, labels_gapi, centers_gapi), std::move(args));
return c;
}
template<typename Pt>
void kmeansTestValidate(const cv::Size& sz, const MatType2&, const int K,
const double compact_gapi, const std::vector<int>& labels_gapi,
const std::vector<Pt>& centers_gapi)
{
const int amount = sz.height;
// Validation
EXPECT_GE(compact_gapi, 0.);
EXPECT_EQ(labels_gapi.size(), static_cast<size_t>(amount));
EXPECT_EQ(centers_gapi.size(), static_cast<size_t>(K));
}
static void kmeansTestValidate(const cv::Size& sz, const MatType2& type, const int K,
const double compact_gapi, const cv::Mat& labels_gapi,
const cv::Mat& centers_gapi)
{
const int chan = (type >> CV_CN_SHIFT) + 1;
const int amount = sz.height != 1 ? sz.height : sz.width;
const int dim = sz.height != 1 ? sz.width * chan : chan;
// Validation
EXPECT_GE(compact_gapi, 0.);
EXPECT_FALSE(labels_gapi.empty());
EXPECT_FALSE(centers_gapi.empty());
EXPECT_EQ(labels_gapi.rows, amount);
EXPECT_EQ(labels_gapi.cols, 1);
EXPECT_EQ(centers_gapi.rows, K);
EXPECT_EQ(centers_gapi.cols, dim);
}
template<typename Labels, typename In>
void kmeansTestOpenCVCompare(const In& in, const Labels& bestLabels, const int K,
const cv::KmeansFlags flags, const double compact_gapi,
const Labels& labels_gapi, const In& centers_gapi,
const CompareMats& cmpF = AbsExact().to_compare_obj())
{
const cv::TermCriteria criteria(cv::TermCriteria::MAX_ITER + cv::TermCriteria::EPS, 30, 0);
const int attempts = 1;
Labels labels_ocv;
In centers_ocv;
{ // step to generalize cv::Mat & std::vector cases of bestLabels' types
cv::Mat bestLabelsMat(bestLabels);
bestLabelsMat.copyTo(labels_ocv);
}
// OpenCV code /////////////////////////////////////////////////////////////
double compact_ocv = cv::kmeans(in, K, labels_ocv, criteria, attempts, flags, centers_ocv);
// Comparison //////////////////////////////////////////////////////////////
EXPECT_TRUE(compact_gapi == compact_ocv);
EXPECT_TRUE(compareKMeansOutputs(labels_gapi, labels_ocv, cmpF));
EXPECT_TRUE(compareKMeansOutputs(centers_gapi, centers_ocv, cmpF));
}
// If an input type is cv::Mat, labels' type is also cv::Mat;
// in other cases, their type has to be std::vector<int>
template<typename In>
using KMeansLabelType = typename std::conditional<std::is_same<In, cv::Mat>::value,
cv::Mat,
std::vector<int>
>::type;
template<typename In, typename Labels = KMeansLabelType<In> >
void kmeansTestBody(const In& in, const cv::Size& sz, const MatType2& type, const int K,
const cv::KmeansFlags flags, cv::GCompileArgs&& args,
const CompareMats& cmpF = AbsExact().to_compare_obj())
{
double compact_gapi = -1.;
Labels labels_gapi;
In centers_gapi;
if (flags & cv::KMEANS_USE_INITIAL_LABELS)
{
Labels bestLabels;
{ // step to generalize cv::Mat & std::vector cases of bestLabels' types
const int amount = (sz.height != 1 || sz.width == -1) ? sz.height : sz.width;
cv::Mat bestLabelsMat(cv::Size{1, amount}, CV_32SC1);
cv::randu(bestLabelsMat, 0, K);
bestLabelsMat.copyTo(bestLabels);
}
kmeansTestGAPI(in, bestLabels, K, flags, std::move(args), compact_gapi, labels_gapi,
centers_gapi);
kmeansTestOpenCVCompare(in, bestLabels, K, flags, compact_gapi, labels_gapi,
centers_gapi, cmpF);
}
else
{
kmeansTestGAPI(in, K, flags, std::move(args), compact_gapi, labels_gapi, centers_gapi);
kmeansTestValidate(sz, type, K, compact_gapi, labels_gapi, centers_gapi);
}
}
} // namespace opencv_test
#endif // OPENCV_GAPI_CORE_TESTS_COMMON_HPP
@@ -2,7 +2,7 @@
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
// Copyright (C) 2018-2020 Intel Corporation
// Copyright (C) 2018-2021 Intel Corporation
#ifndef OPENCV_GAPI_CORE_TESTS_INL_HPP
@@ -12,9 +12,10 @@
#include <opencv2/gapi/infer/parsers.hpp>
#include "gapi_core_tests.hpp"
#include "gapi_core_tests_common.hpp"
namespace opencv_test
{
TEST_P(MathOpTest, MatricesAccuracyTest)
{
// G-API code & corresponding OpenCV code ////////////////////////////////
@@ -1287,7 +1288,11 @@ TEST_P(PhaseTest, AccuracyTest)
// Comparison //////////////////////////////////////////////////////////////
// FIXME: use a comparison functor instead (after enabling OpenCL)
{
#if defined(__aarch64__) || defined(__arm__)
EXPECT_NEAR(0, cvtest::norm(out_mat_ocv, out_mat_gapi, NORM_INF), 4e-6);
#else
EXPECT_EQ(0, cvtest::norm(out_mat_ocv, out_mat_gapi, NORM_INF));
#endif
}
}
@@ -1377,6 +1382,27 @@ TEST_P(NormalizeTest, Test)
}
}
TEST_P(KMeansNDTest, AccuracyTest)
{
kmeansTestBody(in_mat1, sz, type, K, flags, getCompileArgs(), cmpF);
}
TEST_P(KMeans2DTest, AccuracyTest)
{
const int amount = sz.height;
std::vector<cv::Point2f> in_vector{};
initPointsVectorRandU(amount, in_vector);
kmeansTestBody(in_vector, sz, type, K, flags, getCompileArgs());
}
TEST_P(KMeans3DTest, AccuracyTest)
{
const int amount = sz.height;
std::vector<cv::Point3f> in_vector{};
initPointsVectorRandU(amount, in_vector);
kmeansTestBody(in_vector, sz, type, K, flags, getCompileArgs());
}
// PLEASE DO NOT PUT NEW ACCURACY TESTS BELOW THIS POINT! //////////////////////
TEST_P(BackendOutputAllocationTest, EmptyOutput)
@@ -1711,6 +1737,39 @@ TEST_P(SizeRTest, ParseTest)
EXPECT_EQ(out_sz, sz);
}
namespace {
class TestMediaBGR final : public cv::MediaFrame::IAdapter {
cv::Mat m_mat;
public:
explicit TestMediaBGR(cv::Mat m)
: m_mat(m) {
}
cv::GFrameDesc meta() const override {
return cv::GFrameDesc{ cv::MediaFormat::BGR, cv::Size(m_mat.cols, m_mat.rows) };
}
cv::MediaFrame::View access(cv::MediaFrame::Access) override {
cv::MediaFrame::View::Ptrs pp = { m_mat.ptr(), nullptr, nullptr, nullptr };
cv::MediaFrame::View::Strides ss = { m_mat.step, 0u, 0u, 0u };
return cv::MediaFrame::View(std::move(pp), std::move(ss));
}
};
};
TEST_P(SizeMFTest, ParseTest)
{
cv::Size out_sz;
cv::Mat bgr = cv::Mat::eye(sz.height, sz.width, CV_8UC3);
cv::MediaFrame frame = cv::MediaFrame::Create<TestMediaBGR>(bgr);
cv::GFrame in;
auto out = cv::gapi::streaming::size(in);
cv::GComputation c(cv::GIn(in), cv::GOut(out));
c.apply(cv::gin(frame), cv::gout(out_sz), getCompileArgs());
EXPECT_EQ(out_sz, sz);
}
} // opencv_test
#endif //OPENCV_GAPI_CORE_TESTS_INL_HPP
@@ -46,7 +46,7 @@ GAPI_TEST_FIXTURE(Erode3x3Test, initMatrixRandN, FIXTURE_API(CompareMats,int), 2
GAPI_TEST_FIXTURE(DilateTest, initMatrixRandN, FIXTURE_API(CompareMats,int,int), 3,
cmpF, kernSize, kernType)
GAPI_TEST_FIXTURE(Dilate3x3Test, initMatrixRandN, FIXTURE_API(CompareMats,int), 2, cmpF, numIters)
GAPI_TEST_FIXTURE(MorphologyExTest, initMatrixRandN, FIXTURE_API(CompareMats,MorphTypes),
GAPI_TEST_FIXTURE(MorphologyExTest, initMatrixRandN, FIXTURE_API(CompareMats,cv::MorphTypes),
2, cmpF, op)
GAPI_TEST_FIXTURE(SobelTest, initMatrixRandN, FIXTURE_API(CompareMats,int,int,int), 4,
cmpF, kernSize, dx, dy)
@@ -68,21 +68,18 @@ GAPI_TEST_FIXTURE_SPEC_PARAMS(GoodFeaturesTest,
blockSize, useHarrisDetector)
GAPI_TEST_FIXTURE_SPEC_PARAMS(FindContoursNoOffsetTest,
FIXTURE_API(cv::Size,MatType2,cv::RetrievalModes,
cv::ContourApproximationModes),
4, sz, type, mode, method)
cv::ContourApproximationModes, CompareMats),
5, sz, type, mode, method, cmpF)
GAPI_TEST_FIXTURE_SPEC_PARAMS(FindContoursOffsetTest, <>, 0)
GAPI_TEST_FIXTURE_SPEC_PARAMS(FindContoursHNoOffsetTest,
FIXTURE_API(cv::Size,MatType2,cv::RetrievalModes,
cv::ContourApproximationModes),
4, sz, type, mode, method)
cv::ContourApproximationModes, CompareMats),
5, sz, type, mode, method, cmpF)
GAPI_TEST_FIXTURE_SPEC_PARAMS(FindContoursHOffsetTest, <>, 0)
GAPI_TEST_FIXTURE(BoundingRectMatTest, initMatrixRandU, FIXTURE_API(CompareRects), 1, cmpF)
GAPI_TEST_FIXTURE(BoundingRectMatVector32STest, initNothing, FIXTURE_API(CompareRects), 1, cmpF)
GAPI_TEST_FIXTURE(BoundingRectMatVector32FTest, initNothing, FIXTURE_API(CompareRects), 1, cmpF)
GAPI_TEST_FIXTURE(BoundingRectMatTest, initNothing, FIXTURE_API(CompareRects,bool),
2, cmpF, initByVector)
GAPI_TEST_FIXTURE(BoundingRectVector32STest, initNothing, FIXTURE_API(CompareRects), 1, cmpF)
GAPI_TEST_FIXTURE(BoundingRectVector32FTest, initNothing, FIXTURE_API(CompareRects), 1, cmpF)
GAPI_TEST_FIXTURE(BGR2RGBTest, initMatrixRandN, FIXTURE_API(CompareMats), 1, cmpF)
GAPI_TEST_FIXTURE(RGB2GrayTest, initMatrixRandN, FIXTURE_API(CompareMats), 1, cmpF)
GAPI_TEST_FIXTURE(FitLine2DMatVectorTest, initMatByPointsVectorRandU<cv::Point_>,
FIXTURE_API(CompareVecs<float, 4>,cv::DistanceTypes), 2, cmpF, distType)
GAPI_TEST_FIXTURE(FitLine2DVector32STest, initNothing,
@@ -99,6 +96,8 @@ GAPI_TEST_FIXTURE(FitLine3DVector32FTest, initNothing,
FIXTURE_API(CompareVecs<float, 6>,cv::DistanceTypes), 2, cmpF, distType)
GAPI_TEST_FIXTURE(FitLine3DVector64FTest, initNothing,
FIXTURE_API(CompareVecs<float, 6>,cv::DistanceTypes), 2, cmpF, distType)
GAPI_TEST_FIXTURE(BGR2RGBTest, initMatrixRandN, FIXTURE_API(CompareMats), 1, cmpF)
GAPI_TEST_FIXTURE(RGB2GrayTest, initMatrixRandN, FIXTURE_API(CompareMats), 1, cmpF)
GAPI_TEST_FIXTURE(BGR2GrayTest, initMatrixRandN, FIXTURE_API(CompareMats), 1, cmpF)
GAPI_TEST_FIXTURE(RGB2YUVTest, initMatrixRandN, FIXTURE_API(CompareMats), 1, cmpF)
GAPI_TEST_FIXTURE(BGR2I420Test, initMatrixRandN, FIXTURE_API(CompareMats), 1, cmpF)
@@ -0,0 +1,197 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
// Copyright (C) 2020 Intel Corporation
#ifndef OPENCV_GAPI_IMGPROC_TESTS_COMMON_HPP
#define OPENCV_GAPI_IMGPROC_TESTS_COMMON_HPP
#include "gapi_tests_common.hpp"
#include "../../include/opencv2/gapi/imgproc.hpp"
#include <opencv2/imgproc.hpp>
namespace opencv_test
{
// Draw random ellipses on given cv::Mat of given size and type
static void initMatForFindingContours(cv::Mat& mat, const cv::Size& sz, const int type)
{
cv::RNG& rng = theRNG();
mat = cv::Mat(sz, type, cv::Scalar::all(0));
const size_t numEllipses = rng.uniform(1, 10);
for( size_t i = 0; i < numEllipses; i++ )
{
cv::Point center;
cv::Size axes;
center.x = rng.uniform(0, sz.width);
center.y = rng.uniform(0, sz.height);
axes.width = rng.uniform(2, sz.width);
axes.height = rng.uniform(2, sz.height);
const int color = rng.uniform(1, 256);
const double angle = rng.uniform(0., 180.);
cv::ellipse(mat, center, axes, angle, 0., 360., color, 1, FILLED);
}
}
enum OptionalFindContoursOutput {NONE, HIERARCHY};
template<OptionalFindContoursOutput optional = NONE>
cv::GComputation findContoursTestGAPI(const cv::Mat& in, const cv::RetrievalModes mode,
const cv::ContourApproximationModes method,
cv::GCompileArgs&& args,
std::vector<std::vector<cv::Point>>& out_cnts_gapi,
std::vector<cv::Vec4i>& /*out_hier_gapi*/,
const cv::Point& offset = cv::Point())
{
cv::GMat g_in;
cv::GOpaque<cv::Point> gOffset;
cv::GArray<cv::GArray<cv::Point>> outCts;
outCts = cv::gapi::findContours(g_in, mode, method, gOffset);
cv::GComputation c(GIn(g_in, gOffset), GOut(outCts));
c.apply(gin(in, offset), gout(out_cnts_gapi), std::move(args));
return c;
}
template<> cv::GComputation findContoursTestGAPI<HIERARCHY> (
const cv::Mat& in, const cv::RetrievalModes mode, const cv::ContourApproximationModes method,
cv::GCompileArgs&& args, std::vector<std::vector<cv::Point>>& out_cnts_gapi,
std::vector<cv::Vec4i>& out_hier_gapi, const cv::Point& offset)
{
cv::GMat g_in;
cv::GOpaque<cv::Point> gOffset;
cv::GArray<cv::GArray<cv::Point>> outCts;
cv::GArray<cv::Vec4i> outHier;
std::tie(outCts, outHier) = cv::gapi::findContoursH(g_in, mode, method, gOffset);
cv::GComputation c(GIn(g_in, gOffset), GOut(outCts, outHier));
c.apply(gin(in, offset), gout(out_cnts_gapi, out_hier_gapi), std::move(args));
return c;
}
template<OptionalFindContoursOutput optional = NONE>
void findContoursTestOpenCVCompare(const cv::Mat& in, const cv::RetrievalModes mode,
const cv::ContourApproximationModes method,
const std::vector<std::vector<cv::Point>>& out_cnts_gapi,
const std::vector<cv::Vec4i>& out_hier_gapi,
const CompareMats& cmpF, const cv::Point& offset = cv::Point())
{
// OpenCV code /////////////////////////////////////////////////////////////
std::vector<std::vector<cv::Point>> out_cnts_ocv;
std::vector<cv::Vec4i> out_hier_ocv;
cv::findContours(in, out_cnts_ocv, out_hier_ocv, mode, method, offset);
// Comparison //////////////////////////////////////////////////////////////
EXPECT_TRUE(out_cnts_gapi.size() == out_cnts_ocv.size());
cv::Mat out_mat_ocv = cv::Mat(cv::Size{ in.cols, in.rows }, in.type(), cv::Scalar::all(0));
cv::Mat out_mat_gapi = cv::Mat(cv::Size{ in.cols, in.rows }, in.type(), cv::Scalar::all(0));
cv::fillPoly(out_mat_ocv, out_cnts_ocv, cv::Scalar::all(1));
cv::fillPoly(out_mat_gapi, out_cnts_gapi, cv::Scalar::all(1));
EXPECT_TRUE(cmpF(out_mat_ocv, out_mat_gapi));
if (optional == HIERARCHY)
{
EXPECT_TRUE(out_hier_ocv.size() == out_hier_gapi.size());
EXPECT_TRUE(AbsExactVector<cv::Vec4i>().to_compare_f()(out_hier_ocv, out_hier_gapi));
}
}
template<OptionalFindContoursOutput optional = NONE>
void findContoursTestBody(const cv::Size& sz, const MatType2& type, const cv::RetrievalModes mode,
const cv::ContourApproximationModes method, const CompareMats& cmpF,
cv::GCompileArgs&& args, const cv::Point& offset = cv::Point())
{
cv::Mat in;
initMatForFindingContours(in, sz, type);
std::vector<std::vector<cv::Point>> out_cnts_gapi;
std::vector<cv::Vec4i> out_hier_gapi;
findContoursTestGAPI<optional>(in, mode, method, std::move(args), out_cnts_gapi, out_hier_gapi,
offset);
findContoursTestOpenCVCompare<optional>(in, mode, method, out_cnts_gapi, out_hier_gapi, cmpF,
offset);
}
//-------------------------------------------------------------------------------------------------
template<typename In>
static cv::GComputation boundingRectTestGAPI(const In& in, cv::GCompileArgs&& args,
cv::Rect& out_rect_gapi)
{
cv::detail::g_type_of_t<In> g_in;
auto out = cv::gapi::boundingRect(g_in);
cv::GComputation c(cv::GIn(g_in), cv::GOut(out));
c.apply(cv::gin(in), cv::gout(out_rect_gapi), std::move(args));
return c;
}
template<typename In>
static void boundingRectTestOpenCVCompare(const In& in, const cv::Rect& out_rect_gapi,
const CompareRects& cmpF)
{
// OpenCV code /////////////////////////////////////////////////////////////
cv::Rect out_rect_ocv = cv::boundingRect(in);
// Comparison //////////////////////////////////////////////////////////////
EXPECT_TRUE(cmpF(out_rect_gapi, out_rect_ocv));
}
template<typename In>
static void boundingRectTestBody(const In& in, const CompareRects& cmpF, cv::GCompileArgs&& args)
{
cv::Rect out_rect_gapi;
boundingRectTestGAPI(in, std::move(args), out_rect_gapi);
boundingRectTestOpenCVCompare(in, out_rect_gapi, cmpF);
}
//-------------------------------------------------------------------------------------------------
template<typename In>
static cv::GComputation fitLineTestGAPI(const In& in, const cv::DistanceTypes distType,
cv::GCompileArgs&& args, cv::Vec4f& out_vec_gapi)
{
const double paramDefault = 0., repsDefault = 0., aepsDefault = 0.;
cv::detail::g_type_of_t<In> g_in;
auto out = cv::gapi::fitLine2D(g_in, distType, paramDefault, repsDefault, aepsDefault);
cv::GComputation c(cv::GIn(g_in), cv::GOut(out));
c.apply(cv::gin(in), cv::gout(out_vec_gapi), std::move(args));
return c;
}
template<typename In>
static cv::GComputation fitLineTestGAPI(const In& in, const cv::DistanceTypes distType,
cv::GCompileArgs&& args, cv::Vec6f& out_vec_gapi)
{
const double paramDefault = 0., repsDefault = 0., aepsDefault = 0.;
cv::detail::g_type_of_t<In> g_in;
auto out = cv::gapi::fitLine3D(g_in, distType, paramDefault, repsDefault, aepsDefault);
cv::GComputation c(cv::GIn(g_in), cv::GOut(out));
c.apply(cv::gin(in), cv::gout(out_vec_gapi), std::move(args));
return c;
}
template<typename In, int dim>
static void fitLineTestOpenCVCompare(const In& in, const cv::DistanceTypes distType,
const cv::Vec<float, dim>& out_vec_gapi,
const CompareVecs<float, dim>& cmpF)
{
const double paramDefault = 0., repsDefault = 0., aepsDefault = 0.;
// OpenCV code /////////////////////////////////////////////////////////////
cv::Vec<float, dim> out_vec_ocv;
cv::fitLine(in, out_vec_ocv, distType, paramDefault, repsDefault, aepsDefault);
// Comparison //////////////////////////////////////////////////////////////
EXPECT_TRUE(cmpF(out_vec_gapi, out_vec_ocv));
}
template<typename In, int dim>
static void fitLineTestBody(const In& in, const cv::DistanceTypes distType,
const CompareVecs<float, dim>& cmpF, cv::GCompileArgs&& args)
{
cv::Vec<float, dim> out_vec_gapi;
fitLineTestGAPI(in, distType, std::move(args), out_vec_gapi);
fitLineTestOpenCVCompare(in, distType, out_vec_gapi, cmpF);
}
} // namespace opencv_test
#endif // OPENCV_GAPI_IMGPROC_TESTS_COMMON_HPP
@@ -11,6 +11,8 @@
#include <opencv2/gapi/imgproc.hpp>
#include "gapi_imgproc_tests.hpp"
#include "gapi_imgproc_tests_common.hpp"
namespace opencv_test
{
@@ -50,27 +52,6 @@ namespace
rgb2yuyv(in_line_p, out_line_p, in.cols);
}
}
// Draw random ellipses on given mat of given size and type
void initMatForFindingContours(cv::Mat& mat, const cv::Size& sz, const int type)
{
cv::RNG& rng = theRNG();
mat = cv::Mat(sz, type, cv::Scalar::all(0));
size_t numEllipses = rng.uniform(1, 10);
for( size_t i = 0; i < numEllipses; i++ )
{
cv::Point center;
cv::Size axes;
center.x = rng.uniform(0, sz.width);
center.y = rng.uniform(0, sz.height);
axes.width = rng.uniform(2, sz.width);
axes.height = rng.uniform(2, sz.height);
int color = rng.uniform(1, 256);
double angle = rng.uniform(0., 180.);
cv::ellipse(mat, center, axes, angle, 0., 360., color, 1, FILLED);
}
}
}
TEST_P(Filter2DTest, AccuracyTest)
@@ -313,7 +294,7 @@ TEST_P(Dilate3x3Test, AccuracyTest)
TEST_P(MorphologyExTest, AccuracyTest)
{
MorphShapes defShape = cv::MORPH_RECT;
cv::MorphShapes defShape = cv::MORPH_RECT;
int defKernSize = 3;
cv::Mat kernel = cv::getStructuringElement(defShape, cv::Size(defKernSize, defKernSize));
@@ -493,29 +474,7 @@ TEST_P(GoodFeaturesTest, AccuracyTest)
TEST_P(FindContoursNoOffsetTest, AccuracyTest)
{
std::vector<std::vector<cv::Point>> outCtsOCV, outCtsGAPI;
initMatForFindingContours(in_mat1, sz, type);
out_mat_gapi = cv::Mat(sz, type, cv::Scalar::all(0));
out_mat_ocv = cv::Mat(sz, type, cv::Scalar::all(0));
// OpenCV code /////////////////////////////////////////////////////////////
{
cv::findContours(in_mat1, outCtsOCV, mode, method);
}
// G-API code //////////////////////////////////////////////////////////////
cv::GMat in;
cv::GArray<cv::GArray<cv::Point>> outCts;
outCts = cv::gapi::findContours(in, mode, method);
cv::GComputation c(GIn(in), GOut(outCts));
c.apply(gin(in_mat1), gout(outCtsGAPI), getCompileArgs());
// Comparison //////////////////////////////////////////////////////////////
EXPECT_TRUE(outCtsGAPI.size() == outCtsOCV.size());
cv::fillPoly(out_mat_ocv, outCtsOCV, cv::Scalar::all(1));
cv::fillPoly(out_mat_gapi, outCtsGAPI, cv::Scalar::all(1));
EXPECT_TRUE(AbsExact().to_compare_f()(out_mat_ocv, out_mat_gapi));
findContoursTestBody(sz, type, mode, method, cmpF, getCompileArgs());
}
TEST_P(FindContoursOffsetTest, AccuracyTest)
@@ -524,63 +483,15 @@ TEST_P(FindContoursOffsetTest, AccuracyTest)
const MatType2 type = CV_8UC1;
const cv::RetrievalModes mode = cv::RETR_EXTERNAL;
const cv::ContourApproximationModes method = cv::CHAIN_APPROX_NONE;
const CompareMats cmpF = AbsExact().to_compare_obj();
const cv::Point offset(15, 15);
std::vector<std::vector<cv::Point>> outCtsOCV, outCtsGAPI;
initMatForFindingContours(in_mat1, sz, type);
out_mat_gapi = cv::Mat(sz, type, cv::Scalar::all(0));
out_mat_ocv = cv::Mat(sz, type, cv::Scalar::all(0));
// OpenCV code /////////////////////////////////////////////////////////////
{
cv::findContours(in_mat1, outCtsOCV, mode, method, offset);
}
// G-API code //////////////////////////////////////////////////////////////
cv::GMat in;
GOpaque<Point> gOffset;
cv::GArray<cv::GArray<cv::Point>> outCts;
outCts = cv::gapi::findContours(in, mode, method, gOffset);
cv::GComputation c(GIn(in, gOffset), GOut(outCts));
c.apply(gin(in_mat1, offset), gout(outCtsGAPI), getCompileArgs());
// Comparison //////////////////////////////////////////////////////////////
EXPECT_TRUE(outCtsGAPI.size() == outCtsOCV.size());
cv::fillPoly(out_mat_ocv, outCtsOCV, cv::Scalar::all(1));
cv::fillPoly(out_mat_gapi, outCtsGAPI, cv::Scalar::all(1));
EXPECT_TRUE(AbsExact().to_compare_f()(out_mat_ocv, out_mat_gapi));
findContoursTestBody(sz, type, mode, method, cmpF, getCompileArgs(), offset);
}
TEST_P(FindContoursHNoOffsetTest, AccuracyTest)
{
std::vector<std::vector<cv::Point>> outCtsOCV, outCtsGAPI;
std::vector<cv::Vec4i> outHierOCV, outHierGAPI;
initMatForFindingContours(in_mat1, sz, type);
out_mat_gapi = cv::Mat(sz, type, cv::Scalar::all(0));
out_mat_ocv = cv::Mat(sz, type, cv::Scalar::all(0));
// OpenCV code /////////////////////////////////////////////////////////////
{
cv::findContours(in_mat1, outCtsOCV, outHierOCV, mode, method);
}
// G-API code //////////////////////////////////////////////////////////////
cv::GMat in;
cv::GArray<cv::GArray<cv::Point>> outCts;
cv::GArray<cv::Vec4i> outHier;
std::tie(outCts, outHier) = cv::gapi::findContoursH(in, mode, method);
cv::GComputation c(GIn(in), GOut(outCts, outHier));
c.apply(gin(in_mat1), gout(outCtsGAPI, outHierGAPI), getCompileArgs());
// Comparison //////////////////////////////////////////////////////////////
EXPECT_TRUE(outCtsGAPI.size() == outCtsOCV.size());
cv::fillPoly(out_mat_ocv, outCtsOCV, cv::Scalar::all(1));
cv::fillPoly(out_mat_gapi, outCtsGAPI, cv::Scalar::all(1));
EXPECT_TRUE(AbsExact().to_compare_f()(out_mat_ocv, out_mat_gapi));
EXPECT_TRUE(outCtsGAPI.size() == outCtsOCV.size());
EXPECT_TRUE(AbsExactVector<cv::Vec4i>().to_compare_f()(outHierOCV, outHierGAPI));
findContoursTestBody<HIERARCHY>(sz, type, mode, method, cmpF, getCompileArgs());
}
TEST_P(FindContoursHOffsetTest, AccuracyTest)
@@ -589,353 +500,100 @@ TEST_P(FindContoursHOffsetTest, AccuracyTest)
const MatType2 type = CV_8UC1;
const cv::RetrievalModes mode = cv::RETR_EXTERNAL;
const cv::ContourApproximationModes method = cv::CHAIN_APPROX_NONE;
const CompareMats cmpF = AbsExact().to_compare_obj();
const cv::Point offset(15, 15);
std::vector<std::vector<cv::Point>> outCtsOCV, outCtsGAPI;
std::vector<cv::Vec4i> outHierOCV, outHierGAPI;
initMatForFindingContours(in_mat1, sz, type);
out_mat_gapi = cv::Mat(sz, type, cv::Scalar::all(0));
out_mat_ocv = cv::Mat(sz, type, cv::Scalar::all(0));
// OpenCV code /////////////////////////////////////////////////////////////
{
cv::findContours(in_mat1, outCtsOCV, outHierOCV, mode, method, offset);
}
// G-API code //////////////////////////////////////////////////////////////
cv::GMat in;
GOpaque<Point> gOffset;
cv::GArray<cv::GArray<cv::Point>> outCts;
cv::GArray<cv::Vec4i> outHier;
std::tie(outCts, outHier) = cv::gapi::findContoursH(in, mode, method, gOffset);
cv::GComputation c(GIn(in, gOffset), GOut(outCts, outHier));
c.apply(gin(in_mat1, offset), gout(outCtsGAPI, outHierGAPI), getCompileArgs());
// Comparison //////////////////////////////////////////////////////////////
EXPECT_TRUE(outCtsGAPI.size() == outCtsOCV.size());
cv::fillPoly(out_mat_ocv, outCtsOCV, cv::Scalar::all(1));
cv::fillPoly(out_mat_gapi, outCtsGAPI, cv::Scalar::all(1));
EXPECT_TRUE(AbsExact().to_compare_f()(out_mat_ocv, out_mat_gapi));
EXPECT_TRUE(outCtsGAPI.size() == outCtsOCV.size());
EXPECT_TRUE(AbsExactVector<cv::Vec4i>().to_compare_f()(outHierOCV, outHierGAPI));
findContoursTestBody<HIERARCHY>(sz, type, mode, method, cmpF, getCompileArgs(), offset);
}
TEST_P(BoundingRectMatTest, AccuracyTest)
{
cv::Rect out_rect_gapi, out_rect_ocv;
// G-API code //////////////////////////////////////////////////////////////
cv::GMat in;
auto out = cv::gapi::boundingRect(in);
cv::GComputation c(cv::GIn(in), cv::GOut(out));
c.apply(cv::gin(in_mat1), cv::gout(out_rect_gapi), getCompileArgs());
// OpenCV code /////////////////////////////////////////////////////////////
if (initByVector)
{
out_rect_ocv = cv::boundingRect(in_mat1);
initMatByPointsVectorRandU<cv::Point_>(type, sz, dtype);
}
// Comparison //////////////////////////////////////////////////////////////
else
{
EXPECT_TRUE(cmpF(out_rect_gapi, out_rect_ocv));
initMatrixRandU(type, sz, dtype);
}
boundingRectTestBody(in_mat1, cmpF, getCompileArgs());
}
TEST_P(BoundingRectMatVector32STest, AccuracyTest)
{
cv::Rect out_rect_gapi, out_rect_ocv;
std::vector<cv::Point2i> in_vectorS(sz.width);
cv::randu(in_vectorS, cv::Scalar::all(0), cv::Scalar::all(255));
in_mat1 = cv::Mat(in_vectorS);
// G-API code //////////////////////////////////////////////////////////////
cv::GMat in;
auto out = cv::gapi::boundingRect(in);
cv::GComputation c(cv::GIn(in), cv::GOut(out));
c.apply(cv::gin(in_mat1), cv::gout(out_rect_gapi), getCompileArgs());
// OpenCV code /////////////////////////////////////////////////////////////
{
out_rect_ocv = cv::boundingRect(in_mat1);
}
// Comparison //////////////////////////////////////////////////////////////
{
EXPECT_TRUE(cmpF(out_rect_gapi, out_rect_ocv));
}
}
TEST_P(BoundingRectMatVector32FTest, AccuracyTest)
{
cv::RNG& rng = theRNG();
cv::Rect out_rect_gapi, out_rect_ocv;
std::vector<cv::Point2f> in_vectorF(sz.width);
const int fscale = 256; // avoid bits near ULP, generate stable test input
for (int i = 0; i < sz.width; i++)
{
cv::Point2f pt(rng.uniform(0, 255 * fscale) / static_cast<float>(fscale),
rng.uniform(0, 255 * fscale) / static_cast<float>(fscale));
in_vectorF.push_back(pt);
}
in_mat1 = cv::Mat(in_vectorF);
// G-API code //////////////////////////////////////////////////////////////
cv::GMat in;
auto out = cv::gapi::boundingRect(in);
cv::GComputation c(cv::GIn(in), cv::GOut(out));
c.apply(cv::gin(in_mat1), cv::gout(out_rect_gapi), getCompileArgs());
// OpenCV code /////////////////////////////////////////////////////////////
{
out_rect_ocv = cv::boundingRect(in_mat1);
}
// Comparison //////////////////////////////////////////////////////////////
{
EXPECT_TRUE(cmpF(out_rect_gapi, out_rect_ocv));
}
}
TEST_P(BoundingRectVector32STest, AccuracyTest)
{
cv::Rect out_rect_gapi, out_rect_ocv;
std::vector<cv::Point2i> in_vector;
initPointsVectorRandU(sz.width, in_vector);
std::vector<cv::Point2i> in_vectorS(sz.width);
cv::randu(in_vectorS, cv::Scalar::all(0), cv::Scalar::all(255));
// G-API code //////////////////////////////////////////////////////////////
cv::GArray<cv::Point2i> in;
auto out = cv::gapi::boundingRect(in);
cv::GComputation c(cv::GIn(in), cv::GOut(out));
c.apply(cv::gin(in_vectorS), cv::gout(out_rect_gapi), getCompileArgs());
// OpenCV code /////////////////////////////////////////////////////////////
{
out_rect_ocv = cv::boundingRect(in_vectorS);
}
// Comparison //////////////////////////////////////////////////////////////
{
EXPECT_TRUE(cmpF(out_rect_gapi, out_rect_ocv));
}
boundingRectTestBody(in_vector, cmpF, getCompileArgs());
}
TEST_P(BoundingRectVector32FTest, AccuracyTest)
{
cv::RNG& rng = theRNG();
cv::Rect out_rect_gapi, out_rect_ocv;
std::vector<cv::Point2f> in_vector;
initPointsVectorRandU(sz.width, in_vector);
std::vector<cv::Point2f> in_vectorF(sz.width);
const int fscale = 256; // avoid bits near ULP, generate stable test input
for (int i = 0; i < sz.width; i++)
{
cv::Point2f pt(rng.uniform(0, 255 * fscale) / static_cast<float>(fscale),
rng.uniform(0, 255 * fscale) / static_cast<float>(fscale));
in_vectorF.push_back(pt);
}
// G-API code //////////////////////////////////////////////////////////////
cv::GArray<cv::Point2f> in;
auto out = cv::gapi::boundingRect(in);
cv::GComputation c(cv::GIn(in), cv::GOut(out));
c.apply(cv::gin(in_vectorF), cv::gout(out_rect_gapi), getCompileArgs());
// OpenCV code /////////////////////////////////////////////////////////////
{
out_rect_ocv = cv::boundingRect(in_vectorF);
}
// Comparison //////////////////////////////////////////////////////////////
{
EXPECT_TRUE(cmpF(out_rect_gapi, out_rect_ocv));
}
boundingRectTestBody(in_vector, cmpF, getCompileArgs());
}
TEST_P(FitLine2DMatVectorTest, AccuracyTest)
{
cv::Vec4f out_vec_gapi, out_vec_ocv;
double paramDefault = 0., repsDefault = 0., aepsDefault = 0.;
// G-API code //////////////////////////////////////////////////////////////
cv::GMat in;
auto out = cv::gapi::fitLine2D(in, distType, paramDefault, repsDefault, aepsDefault);
cv::GComputation c(cv::GIn(in), cv::GOut(out));
c.apply(cv::gin(in_mat1), cv::gout(out_vec_gapi), getCompileArgs());
// OpenCV code /////////////////////////////////////////////////////////////
{
cv::fitLine(in_mat1, out_vec_ocv, distType, paramDefault, repsDefault, aepsDefault);
}
// Comparison //////////////////////////////////////////////////////////////
{
EXPECT_TRUE(cmpF(out_vec_gapi, out_vec_ocv));
}
fitLineTestBody(in_mat1, distType, cmpF, getCompileArgs());
}
TEST_P(FitLine2DVector32STest, AccuracyTest)
{
cv::Vec4f out_vec_gapi, out_vec_ocv;
double paramDefault = 0., repsDefault = 0., aepsDefault = 0.;
std::vector<cv::Point2i> in_vec;
initPointsVectorRandU(sz.width, in_vec);
// G-API code //////////////////////////////////////////////////////////////
cv::GArray<cv::Point2i> in;
auto out = cv::gapi::fitLine2D(in, distType, paramDefault, repsDefault, aepsDefault);
cv::GComputation c(cv::GIn(in), cv::GOut(out));
c.apply(cv::gin(in_vec), cv::gout(out_vec_gapi), getCompileArgs());
// OpenCV code /////////////////////////////////////////////////////////////
{
cv::fitLine(in_vec, out_vec_ocv, distType, paramDefault, repsDefault, aepsDefault);
}
// Comparison //////////////////////////////////////////////////////////////
{
EXPECT_TRUE(cmpF(out_vec_gapi, out_vec_ocv));
}
fitLineTestBody(in_vec, distType, cmpF, getCompileArgs());
}
TEST_P(FitLine2DVector32FTest, AccuracyTest)
{
cv::Vec4f out_vec_gapi, out_vec_ocv;
double paramDefault = 0., repsDefault = 0., aepsDefault = 0.;
std::vector<cv::Point2f> in_vec;
initPointsVectorRandU(sz.width, in_vec);
// G-API code //////////////////////////////////////////////////////////////
cv::GArray<cv::Point2f> in;
auto out = cv::gapi::fitLine2D(in, distType, paramDefault, repsDefault, aepsDefault);
cv::GComputation c(cv::GIn(in), cv::GOut(out));
c.apply(cv::gin(in_vec), cv::gout(out_vec_gapi), getCompileArgs());
// OpenCV code /////////////////////////////////////////////////////////////
{
cv::fitLine(in_vec, out_vec_ocv, distType, paramDefault, repsDefault, aepsDefault);
}
// Comparison //////////////////////////////////////////////////////////////
{
EXPECT_TRUE(cmpF(out_vec_gapi, out_vec_ocv));
}
fitLineTestBody(in_vec, distType, cmpF, getCompileArgs());
}
TEST_P(FitLine2DVector64FTest, AccuracyTest)
{
cv::Vec4f out_vec_gapi, out_vec_ocv;
double paramDefault = 0., repsDefault = 0., aepsDefault = 0.;
std::vector<cv::Point2d> in_vec;
initPointsVectorRandU(sz.width, in_vec);
// G-API code //////////////////////////////////////////////////////////////
cv::GArray<cv::Point2d> in;
auto out = cv::gapi::fitLine2D(in, distType, paramDefault, repsDefault, aepsDefault);
cv::GComputation c(cv::GIn(in), cv::GOut(out));
c.apply(cv::gin(in_vec), cv::gout(out_vec_gapi), getCompileArgs());
// OpenCV code /////////////////////////////////////////////////////////////
{
cv::fitLine(in_vec, out_vec_ocv, distType, paramDefault, repsDefault, aepsDefault);
}
// Comparison //////////////////////////////////////////////////////////////
{
EXPECT_TRUE(cmpF(out_vec_gapi, out_vec_ocv));
}
fitLineTestBody(in_vec, distType, cmpF, getCompileArgs());
}
TEST_P(FitLine3DMatVectorTest, AccuracyTest)
{
cv::Vec6f out_vec_gapi, out_vec_ocv;
double paramDefault = 0., repsDefault = 0., aepsDefault = 0.;
// G-API code //////////////////////////////////////////////////////////////
cv::GMat in;
auto out = cv::gapi::fitLine3D(in, distType, paramDefault, repsDefault, aepsDefault);
cv::GComputation c(cv::GIn(in), cv::GOut(out));
c.apply(cv::gin(in_mat1), cv::gout(out_vec_gapi), getCompileArgs());
// OpenCV code /////////////////////////////////////////////////////////////
{
cv::fitLine(in_mat1, out_vec_ocv, distType, paramDefault, repsDefault, aepsDefault);
}
// Comparison //////////////////////////////////////////////////////////////
{
EXPECT_TRUE(cmpF(out_vec_gapi, out_vec_ocv));
}
fitLineTestBody(in_mat1, distType, cmpF, getCompileArgs());
}
TEST_P(FitLine3DVector32STest, AccuracyTest)
{
cv::Vec6f out_vec_gapi, out_vec_ocv;
double paramDefault = 0., repsDefault = 0., aepsDefault = 0.;
std::vector<cv::Point3i> in_vec;
initPointsVectorRandU(sz.width, in_vec);
// G-API code //////////////////////////////////////////////////////////////
cv::GArray<cv::Point3i> in;
auto out = cv::gapi::fitLine3D(in, distType, paramDefault, repsDefault, aepsDefault);
cv::GComputation c(cv::GIn(in), cv::GOut(out));
c.apply(cv::gin(in_vec), cv::gout(out_vec_gapi), getCompileArgs());
// OpenCV code /////////////////////////////////////////////////////////////
{
cv::fitLine(in_vec, out_vec_ocv, distType, paramDefault, repsDefault, aepsDefault);
}
// Comparison //////////////////////////////////////////////////////////////
{
EXPECT_TRUE(cmpF(out_vec_gapi, out_vec_ocv));
}
fitLineTestBody(in_vec, distType, cmpF, getCompileArgs());
}
TEST_P(FitLine3DVector32FTest, AccuracyTest)
{
cv::Vec6f out_vec_gapi, out_vec_ocv;
double paramDefault = 0., repsDefault = 0., aepsDefault = 0.;
std::vector<cv::Point3f> in_vec;
initPointsVectorRandU(sz.width, in_vec);
// G-API code //////////////////////////////////////////////////////////////
cv::GArray<cv::Point3f> in;
auto out = cv::gapi::fitLine3D(in, distType, paramDefault, repsDefault, aepsDefault);
cv::GComputation c(cv::GIn(in), cv::GOut(out));
c.apply(cv::gin(in_vec), cv::gout(out_vec_gapi), getCompileArgs());
// OpenCV code /////////////////////////////////////////////////////////////
{
cv::fitLine(in_vec, out_vec_ocv, distType, paramDefault, repsDefault, aepsDefault);
}
// Comparison //////////////////////////////////////////////////////////////
{
EXPECT_TRUE(cmpF(out_vec_gapi, out_vec_ocv));
}
fitLineTestBody(in_vec, distType, cmpF, getCompileArgs());
}
TEST_P(FitLine3DVector64FTest, AccuracyTest)
{
cv::Vec6f out_vec_gapi, out_vec_ocv;
double paramDefault = 0., repsDefault = 0., aepsDefault = 0.;
std::vector<cv::Point3d> in_vec;
initPointsVectorRandU(sz.width, in_vec);
// G-API code //////////////////////////////////////////////////////////////
cv::GArray<cv::Point3d> in;
auto out = cv::gapi::fitLine3D(in, distType, paramDefault, repsDefault, aepsDefault);
cv::GComputation c(cv::GIn(in), cv::GOut(out));
c.apply(cv::gin(in_vec), cv::gout(out_vec_gapi), getCompileArgs());
// OpenCV code /////////////////////////////////////////////////////////////
{
cv::fitLine(in_vec, out_vec_ocv, distType, paramDefault, repsDefault, aepsDefault);
}
// Comparison //////////////////////////////////////////////////////////////
{
EXPECT_TRUE(cmpF(out_vec_gapi, out_vec_ocv));
}
fitLineTestBody(in_vec, distType, cmpF, getCompileArgs());
}
TEST_P(BGR2RGBTest, AccuracyTest)
@@ -130,6 +130,8 @@ struct Fixture : public RenderBGRTestBase API { \
#define GAPI_RENDER_TEST_FIXTURES(Fixture, API, Number, ...) \
GAPI_RENDER_TEST_FIXTURE_BGR(RenderBGR##Fixture, GET_VA_ARGS(API), Number, __VA_ARGS__) \
GAPI_RENDER_TEST_FIXTURE_NV12(RenderNV12##Fixture, GET_VA_ARGS(API), Number, __VA_ARGS__) \
GAPI_RENDER_TEST_FIXTURE_NV12(RenderMFrame##Fixture, GET_VA_ARGS(API), Number, __VA_ARGS__) \
using Points = std::vector<cv::Point>;
GAPI_RENDER_TEST_FIXTURES(TestTexts, FIXTURE_API(std::string, cv::Point, double, cv::Scalar), 4, text, org, fs, color)
@@ -0,0 +1,8 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
// Copyright (C) 2021 Intel Corporation
#include "../test_precomp.hpp"
#include "gapi_stereo_tests_inl.hpp"
@@ -0,0 +1,26 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
// Copyright (C) 2021 Intel Corporation
#ifndef OPENCV_GAPI_STEREO_TESTS_HPP
#define OPENCV_GAPI_STEREO_TESTS_HPP
#include <opencv2/gapi/stereo.hpp> // fore cv::gapi::StereoOutputFormat
#include "gapi_tests_common.hpp"
#include "gapi_parsers_tests_common.hpp"
namespace opencv_test
{
GAPI_TEST_FIXTURE(TestGAPIStereo, initMatsRandU, FIXTURE_API(cv::gapi::StereoOutputFormat, int, int, double, double, CompareMats), 6,
oF, numDisparities, blockSize, baseline,
focus, cmpF)
} // namespace opencv_test
#endif // OPENCV_GAPI_STEREO_TESTS_HPP
@@ -0,0 +1,74 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
// Copyright (C) 2021 Intel Corporation
#ifndef OPENCV_GAPI_STEREO_TESTS_INL_HPP
#define OPENCV_GAPI_STEREO_TESTS_INL_HPP
#include <opencv2/gapi/stereo.hpp>
#include <opencv2/gapi/cpu/stereo.hpp>
#include "gapi_stereo_tests.hpp"
#ifdef HAVE_OPENCV_STEREO
#include <opencv2/stereo.hpp>
namespace opencv_test {
TEST_P(TestGAPIStereo, DisparityDepthTest)
{
using format = cv::gapi::StereoOutputFormat;
switch(oF) {
case format::DEPTH_FLOAT16: dtype = CV_16FC1; break;
case format::DEPTH_FLOAT32: dtype = CV_32FC1; break;
case format::DISPARITY_FIXED16_12_4: dtype = CV_16SC1; break;
default: GAPI_Assert(false && "Unsupported format in test");
}
initOutMats(sz, dtype);
// G-API
cv::GMat inL, inR;
cv::GMat out = cv::gapi::stereo(inL, inR, oF);
cv::GComputation(cv::GIn(inL, inR), cv::GOut(out))
.apply(cv::gin(in_mat1, in_mat2), cv::gout(out_mat_gapi),
cv::compile_args(cv::gapi::calib3d::cpu::kernels(),
cv::gapi::calib3d::cpu::StereoInitParam {
numDisparities,
blockSize,
baseline,
focus}));
// OpenCV
cv::StereoBM::create(numDisparities, blockSize)->compute(in_mat1,
in_mat2,
out_mat_ocv);
static const int DISPARITY_SHIFT_16S = 4;
switch(oF) {
case format::DEPTH_FLOAT16:
out_mat_ocv.convertTo(out_mat_ocv, CV_32FC1, 1./(1 << DISPARITY_SHIFT_16S), 0);
out_mat_ocv = (focus * baseline) / out_mat_ocv;
out_mat_ocv.convertTo(out_mat_ocv, CV_16FC1);
break;
case format::DEPTH_FLOAT32:
out_mat_ocv.convertTo(out_mat_ocv, CV_32FC1, 1./(1 << DISPARITY_SHIFT_16S), 0);
out_mat_ocv = (focus * baseline) / out_mat_ocv;
break;
case format::DISPARITY_FIXED16_12_4:
break;
default:
GAPI_Assert(false && "Unsupported format in test");
}
EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
}
} // namespace opencv_test
#endif // HAVE_OPENCV_STEREO
#endif // OPENCV_GAPI_STEREO_TESTS_INL_HPP
+49 -8
View File
@@ -58,7 +58,7 @@ namespace
return o;
}
inline void initTestDataPath()
inline bool initTestDataPathSilent()
{
#ifndef WINRT
static bool initialized = false;
@@ -66,15 +66,32 @@ namespace
{
// Since G-API has no own test data (yet), it is taken from the common space
const char* testDataPath = getenv("OPENCV_TEST_DATA_PATH");
GAPI_Assert(testDataPath != nullptr &&
"OPENCV_TEST_DATA_PATH environment variable is either not set or set incorrectly.");
cvtest::addDataSearchPath(testDataPath);
initialized = true;
if (testDataPath != nullptr) {
cvtest::addDataSearchPath(testDataPath);
initialized = true;
}
}
return initialized;
#endif // WINRT
}
inline void initTestDataPath()
{
bool initialized = initTestDataPathSilent();
GAPI_Assert(initialized &&
"OPENCV_TEST_DATA_PATH environment variable is either not set or set incorrectly.");
}
inline void initTestDataPathOrSkip()
{
bool initialized = initTestDataPathSilent();
if (!initialized)
{
throw cvtest::SkipTestException("Can't find test data");
}
}
template <typename T> inline void initPointRandU(cv::RNG &rng, cv::Point_<T>& pt)
{
GAPI_Assert(std::is_integral<T>::value);
@@ -324,7 +341,7 @@ public:
}
template <typename T>
inline void initPointRandU(cv::RNG& rng, T& pt)
inline void initPointRandU(cv::RNG& rng, T& pt) const
{ ::initPointRandU(rng, pt); }
// Disable unreachable code warning for MSVS 2015
@@ -334,7 +351,7 @@ public:
#endif
// initialize std::vector<cv::Point_<T>>/std::vector<cv::Point3_<T>>
template <typename T, template <typename> class Pt>
void initPointsVectorRandU(const int sz_in, std::vector<Pt<T>> &vec_)
void initPointsVectorRandU(const int sz_in, std::vector<Pt<T>> &vec_) const
{
cv::RNG& rng = theRNG();
@@ -593,6 +610,8 @@ using compare_vec_f = std::function<bool(const cv::Vec<Elem, cn> &a, const cv::V
template<typename T1, typename T2>
struct CompareF
{
CompareF() = default;
using callable_t = std::function<bool(const T1& a, const T2& b)>;
CompareF(callable_t&& cmp, std::string&& cmp_name) :
_comparator(std::move(cmp)), _name(std::move(cmp_name)) {}
@@ -1174,6 +1193,28 @@ inline std::ostream& operator<<(std::ostream& os, DistanceTypes op)
#undef CASE
return os;
}
inline std::ostream& operator<<(std::ostream& os, KmeansFlags op)
{
int op_(op);
switch (op_)
{
case KmeansFlags::KMEANS_RANDOM_CENTERS:
os << "KMEANS_RANDOM_CENTERS";
break;
case KmeansFlags::KMEANS_PP_CENTERS:
os << "KMEANS_PP_CENTERS";
break;
case KmeansFlags::KMEANS_RANDOM_CENTERS | KmeansFlags::KMEANS_USE_INITIAL_LABELS:
os << "KMEANS_RANDOM_CENTERS | KMEANS_USE_INITIAL_LABELS";
break;
case KmeansFlags::KMEANS_PP_CENTERS | KmeansFlags::KMEANS_USE_INITIAL_LABELS:
os << "KMEANS_PP_CENTERS | KMEANS_USE_INITIAL_LABELS";
break;
default: GAPI_Assert(false && "unknown KmeansFlags value");
}
return os;
}
} // namespace cv
#endif //OPENCV_GAPI_TESTS_COMMON_HPP
@@ -28,6 +28,16 @@ GAPI_TEST_FIXTURE_SPEC_PARAMS(BuildPyr_CalcOptFlow_PipelineTest,
FIXTURE_API(std::string,int,int,bool), 4,
fileNamePattern, winSize, maxLevel, withDerivatives)
GAPI_TEST_FIXTURE_SPEC_PARAMS(BackgroundSubtractorTest, FIXTURE_API(tuple<cv::gapi::video::BackgroundSubtractorType,double>,
int, bool, double, std::string, std::size_t),
6, typeAndThreshold, histLength, detectShadows, learningRate, filePath, testNumFrames)
GAPI_TEST_FIXTURE_SPEC_PARAMS(KalmanFilterTest, FIXTURE_API(int, int, int, int, int), 5, type, dDim, mDim, cDim, numIter)
GAPI_TEST_FIXTURE_SPEC_PARAMS(KalmanFilterNoControlTest, FIXTURE_API(int, int, int, int), 4, type, dDim, mDim, numIter)
GAPI_TEST_FIXTURE_SPEC_PARAMS(KalmanFilterCircleSampleTest, FIXTURE_API(int, int), 2, type, numIter)
} // opencv_test
@@ -15,7 +15,6 @@
#endif // HAVE_OPENCV_VIDEO
namespace opencv_test
{
namespace
@@ -128,6 +127,54 @@ struct OptFlowLKTestParams
int flags = 0;
};
inline void compareOutputPyramids(const BuildOpticalFlowPyramidTestOutput& outGAPI,
const BuildOpticalFlowPyramidTestOutput& outOCV)
{
GAPI_Assert(outGAPI.maxLevel == outOCV.maxLevel);
GAPI_Assert(outOCV.maxLevel >= 0);
const size_t maxLevel = static_cast<size_t>(outOCV.maxLevel);
for (size_t i = 0; i <= maxLevel; i++)
{
EXPECT_TRUE(AbsExact().to_compare_f()(outGAPI.pyramid[i], outOCV.pyramid[i]));
}
}
template <typename Elem>
inline bool compareVectorsAbsExactForOptFlow(const std::vector<Elem>& outGAPI,
const std::vector<Elem>& outOCV)
{
return AbsExactVector<Elem>().to_compare_f()(outGAPI, outOCV);
}
inline void compareOutputsOptFlow(const OptFlowLKTestOutput& outGAPI,
const OptFlowLKTestOutput& outOCV)
{
EXPECT_TRUE(compareVectorsAbsExactForOptFlow(outGAPI.nextPoints, outOCV.nextPoints));
EXPECT_TRUE(compareVectorsAbsExactForOptFlow(outGAPI.statuses, outOCV.statuses));
EXPECT_TRUE(compareVectorsAbsExactForOptFlow(outGAPI.errors, outOCV.errors));
}
inline std::ostream& operator<<(std::ostream& os, const cv::TermCriteria& criteria)
{
os << "{";
switch (criteria.type) {
case cv::TermCriteria::COUNT:
os << "COUNT; ";
break;
case cv::TermCriteria::EPS:
os << "EPS; ";
break;
case cv::TermCriteria::COUNT | cv::TermCriteria::EPS:
os << "COUNT | EPS; ";
break;
default:
os << "TypeUndefined; ";
break;
};
return os << criteria.maxCount << "; " << criteria.epsilon <<"}";
}
#ifdef HAVE_OPENCV_VIDEO
inline GComputation runOCVnGAPIBuildOptFlowPyramid(TestFunctional& testInst,
@@ -321,6 +368,66 @@ inline GComputation runOCVnGAPIOptFlowPipeline(TestFunctional& testInst,
return c;
}
inline void testBackgroundSubtractorStreaming(cv::GStreamingCompiled& gapiBackSub,
const cv::Ptr<cv::BackgroundSubtractor>& pOCVBackSub,
const int diffPercent, const int tolerance,
const double lRate, const std::size_t testNumFrames)
{
cv::Mat frame, gapiForeground, ocvForeground;
double numDiff = diffPercent / 100.0;
gapiBackSub.start();
EXPECT_TRUE(gapiBackSub.running());
compare_f cmpF = AbsSimilarPoints(tolerance, numDiff).to_compare_f();
// Comparison of G-API and OpenCV substractors
std::size_t frames = 0u;
while (frames <= testNumFrames && gapiBackSub.pull(cv::gout(frame, gapiForeground)))
{
pOCVBackSub->apply(frame, ocvForeground, lRate);
EXPECT_TRUE(cmpF(gapiForeground, ocvForeground));
frames++;
}
if (gapiBackSub.running())
gapiBackSub.stop();
EXPECT_LT(0u, frames);
EXPECT_FALSE(gapiBackSub.running());
}
inline void initKalmanParams(const int type, const int dDim, const int mDim, const int cDim,
cv::gapi::KalmanParams& kp)
{
kp.state = Mat::zeros(dDim, 1, type);
cv::randu(kp.state, Scalar::all(0), Scalar::all(0.1));
kp.errorCov = Mat::eye(dDim, dDim, type);
kp.transitionMatrix = Mat::ones(dDim, dDim, type) * 2;
kp.processNoiseCov = Mat::eye(dDim, dDim, type) * (1e-5);
kp.measurementMatrix = Mat::eye(mDim, dDim, type) * 2;
kp.measurementNoiseCov = Mat::eye(mDim, mDim, type) * (1e-5);
if (cDim > 0)
kp.controlMatrix = Mat::eye(dDim, cDim, type) * (1e-3);
}
inline void initKalmanFilter(const cv::gapi::KalmanParams& kp, const bool control,
cv::KalmanFilter& ocvKalman)
{
kp.state.copyTo(ocvKalman.statePost);
kp.errorCov.copyTo(ocvKalman.errorCovPost);
kp.transitionMatrix.copyTo(ocvKalman.transitionMatrix);
kp.measurementMatrix.copyTo(ocvKalman.measurementMatrix);
kp.measurementNoiseCov.copyTo(ocvKalman.measurementNoiseCov);
kp.processNoiseCov.copyTo(ocvKalman.processNoiseCov);
if (control)
kp.controlMatrix.copyTo(ocvKalman.controlMatrix);
}
#else // !HAVE_OPENCV_VIDEO
inline cv::GComputation runOCVnGAPIBuildOptFlowPyramid(TestFunctional&,
@@ -361,54 +468,24 @@ inline GComputation runOCVnGAPIOptFlowPipeline(TestFunctional&,
#endif // HAVE_OPENCV_VIDEO
inline void compareOutputPyramids(const BuildOpticalFlowPyramidTestOutput& outOCV,
const BuildOpticalFlowPyramidTestOutput& outGAPI)
{
GAPI_Assert(outGAPI.maxLevel == outOCV.maxLevel);
GAPI_Assert(outOCV.maxLevel >= 0);
size_t maxLevel = static_cast<size_t>(outOCV.maxLevel);
for (size_t i = 0; i <= maxLevel; i++)
{
EXPECT_TRUE(AbsExact().to_compare_f()(outOCV.pyramid[i], outGAPI.pyramid[i]));
}
}
template <typename Elem>
inline bool compareVectorsAbsExactForOptFlow(std::vector<Elem> outOCV, std::vector<Elem> outGAPI)
{
return AbsExactVector<Elem>().to_compare_f()(outOCV, outGAPI);
}
inline void compareOutputsOptFlow(const OptFlowLKTestOutput& outOCV,
const OptFlowLKTestOutput& outGAPI)
{
EXPECT_TRUE(compareVectorsAbsExactForOptFlow(outGAPI.nextPoints, outOCV.nextPoints));
EXPECT_TRUE(compareVectorsAbsExactForOptFlow(outGAPI.statuses, outOCV.statuses));
EXPECT_TRUE(compareVectorsAbsExactForOptFlow(outGAPI.errors, outOCV.errors));
}
inline std::ostream& operator<<(std::ostream& os, const cv::TermCriteria& criteria)
{
os << "{";
switch (criteria.type) {
case cv::TermCriteria::COUNT:
os << "COUNT; ";
break;
case cv::TermCriteria::EPS:
os << "EPS; ";
break;
case cv::TermCriteria::COUNT | cv::TermCriteria::EPS:
os << "COUNT | EPS; ";
break;
default:
os << "TypeUndefined; ";
break;
};
return os << criteria.maxCount << "; " << criteria.epsilon <<"}";
}
} // namespace
} // namespace opencv_test
// Note: namespace must match the namespace of the type of the printed object
namespace cv { namespace gapi { namespace video
{
inline std::ostream& operator<<(std::ostream& os, const BackgroundSubtractorType op)
{
#define CASE(v) case BackgroundSubtractorType::v: os << #v; break
switch (op)
{
CASE(TYPE_BS_MOG2);
CASE(TYPE_BS_KNN);
default: GAPI_Assert(false && "unknown BackgroundSubtractor type");
}
#undef CASE
return os;
}
}}} // namespace cv::gapi::video
#endif // OPENCV_GAPI_VIDEO_TESTS_COMMON_HPP
@@ -8,6 +8,7 @@
#define OPENCV_GAPI_VIDEO_TESTS_INL_HPP
#include "gapi_video_tests.hpp"
#include <opencv2/gapi/streaming/cap.hpp>
namespace opencv_test
{
@@ -26,7 +27,7 @@ TEST_P(BuildOptFlowPyramidTest, AccuracyTest)
runOCVnGAPIBuildOptFlowPyramid(*this, params, outOCV, outGAPI);
compareOutputPyramids(outOCV, outGAPI);
compareOutputPyramids(outGAPI, outOCV);
}
TEST_P(OptFlowLKTest, AccuracyTest)
@@ -43,7 +44,7 @@ TEST_P(OptFlowLKTest, AccuracyTest)
runOCVnGAPIOptFlowLK(*this, inPts, params, outOCV, outGAPI);
compareOutputsOptFlow(outOCV, outGAPI);
compareOutputsOptFlow(outGAPI, outOCV);
}
TEST_P(OptFlowLKTestForPyr, AccuracyTest)
@@ -62,7 +63,7 @@ TEST_P(OptFlowLKTestForPyr, AccuracyTest)
runOCVnGAPIOptFlowLKForPyr(*this, in, params, withDeriv, outOCV, outGAPI);
compareOutputsOptFlow(outOCV, outGAPI);
compareOutputsOptFlow(outGAPI, outOCV);
}
TEST_P(BuildPyr_CalcOptFlow_PipelineTest, AccuracyTest)
@@ -85,9 +86,238 @@ TEST_P(BuildPyr_CalcOptFlow_PipelineTest, AccuracyTest)
runOCVnGAPIOptFlowPipeline(*this, params, outOCV, outGAPI, inPts);
compareOutputsOptFlow(outOCV, outGAPI);
compareOutputsOptFlow(outGAPI, outOCV);
}
#ifdef HAVE_OPENCV_VIDEO
TEST_P(BackgroundSubtractorTest, AccuracyTest)
{
initTestDataPath();
cv::gapi::video::BackgroundSubtractorType opType;
double thr = -1;
std::tie(opType, thr) = typeAndThreshold;
cv::gapi::video::BackgroundSubtractorParams bsp(opType, histLength, thr,
detectShadows, learningRate);
// G-API graph declaration
cv::GMat in;
cv::GMat out = cv::gapi::BackgroundSubtractor(in, bsp);
// Preserving 'in' in output to have possibility to compare with OpenCV reference
cv::GComputation c(cv::GIn(in), cv::GOut(cv::gapi::copy(in), out));
// G-API compilation of graph for streaming mode
auto gapiBackSub = c.compileStreaming(getCompileArgs());
// Testing G-API Background Substractor in streaming mode
const auto path = findDataFile(filePath);
try
{
gapiBackSub.setSource(gapi::wip::make_src<cv::gapi::wip::GCaptureSource>(path));
}
catch (...)
{ throw SkipTestException("Video file can't be opened."); }
cv::Ptr<cv::BackgroundSubtractor> pOCVBackSub;
if (opType == cv::gapi::video::TYPE_BS_MOG2)
pOCVBackSub = cv::createBackgroundSubtractorMOG2(histLength, thr,
detectShadows);
else if (opType == cv::gapi::video::TYPE_BS_KNN)
pOCVBackSub = cv::createBackgroundSubtractorKNN(histLength, thr,
detectShadows);
// Allowing 1% difference of all pixels between G-API and reference OpenCV results
testBackgroundSubtractorStreaming(gapiBackSub, pOCVBackSub, 1, 1, learningRate, testNumFrames);
}
TEST_P(KalmanFilterTest, AccuracyTest)
{
cv::gapi::KalmanParams kp;
initKalmanParams(type, dDim, mDim, cDim, kp);
// OpenCV reference KalmanFilter initialization
cv::KalmanFilter ocvKalman(dDim, mDim, cDim, type);
initKalmanFilter(kp, true, ocvKalman);
// measurement vector
cv::Mat measure_vec(mDim, 1, type);
// control vector
cv::Mat ctrl_vec = Mat::zeros(cDim > 0 ? cDim : 2, 1, type);
// G-API Kalman's output state
cv::Mat gapiKState(dDim, 1, type);
// OCV Kalman's output state
cv::Mat ocvKState(dDim, 1, type);
// G-API graph initialization
cv::GMat m, ctrl;
cv::GOpaque<bool> have_m;
cv::GMat out = cv::gapi::KalmanFilter(m, have_m, ctrl, kp);
cv::GComputation comp(cv::GIn(m, have_m, ctrl), cv::GOut(out));
cv::RNG& rng = cv::theRNG();
bool haveMeasure;
for (int i = 0; i < numIter; i++)
{
haveMeasure = (rng(2u) == 1); // returns 0 or 1 - whether we have measurement at this iteration or not
if (haveMeasure)
cv::randu(measure_vec, Scalar::all(-1), Scalar::all(1));
if (cDim > 0)
cv::randu(ctrl_vec, Scalar::all(-1), Scalar::all(1));
// G-API KalmanFilter call
comp.apply(cv::gin(measure_vec, haveMeasure, ctrl_vec), cv::gout(gapiKState));
// OpenCV KalmanFilter call
ocvKState = cDim > 0 ? ocvKalman.predict(ctrl_vec) : ocvKalman.predict();
if (haveMeasure)
ocvKState = ocvKalman.correct(measure_vec);
}
// Comparison //////////////////////////////////////////////////////////////
{
EXPECT_TRUE(AbsExact().to_compare_f()(gapiKState, ocvKState));
}
}
TEST_P(KalmanFilterNoControlTest, AccuracyTest)
{
cv::gapi::KalmanParams kp;
initKalmanParams(type, dDim, mDim, 0, kp);
// OpenCV reference KalmanFilter initialization
cv::KalmanFilter ocvKalman(dDim, mDim, 0, type);
initKalmanFilter(kp, false, ocvKalman);
// measurement vector
cv::Mat measure_vec(mDim, 1, type);
// G-API Kalman's output state
cv::Mat gapiKState(dDim, 1, type);
// OCV Kalman's output state
cv::Mat ocvKState(dDim, 1, type);
// G-API graph initialization
cv::GMat m;
cv::GOpaque<bool> have_m;
cv::GMat out = cv::gapi::KalmanFilter(m, have_m, kp);
cv::GComputation comp(cv::GIn(m, have_m), cv::GOut(out));
cv::RNG& rng = cv::theRNG();
bool haveMeasure;
for (int i = 0; i < numIter; i++)
{
haveMeasure = (rng(2u) == 1); // returns 0 or 1 - whether we have measurement at this iteration or not
if (haveMeasure)
cv::randu(measure_vec, Scalar::all(-1), Scalar::all(1));
// G-API
comp.apply(cv::gin(measure_vec, haveMeasure), cv::gout(gapiKState));
// OpenCV
ocvKState = ocvKalman.predict();
if (haveMeasure)
ocvKState = ocvKalman.correct(measure_vec);
}
// Comparison //////////////////////////////////////////////////////////////
{
EXPECT_TRUE(AbsExact().to_compare_f()(gapiKState, ocvKState));
}
}
TEST_P(KalmanFilterCircleSampleTest, AccuracyTest)
{
// auxiliary variables
cv::Mat processNoise(2, 1, type);
// Input measurement
cv::Mat measurement = Mat::zeros(1, 1, type);
// Angle and it's delta(phi, delta_phi)
cv::Mat state(2, 1, type);
// G-API graph initialization
cv::gapi::KalmanParams kp;
kp.state = Mat::zeros(2, 1, type);
cv::randn(kp.state, Scalar::all(0), Scalar::all(0.1));
kp.errorCov = Mat::eye(2, 2, type);
if (type == CV_32F)
kp.transitionMatrix = (Mat_<float>(2, 2) << 1, 1, 0, 1);
else
kp.transitionMatrix = (Mat_<double>(2, 2) << 1, 1, 0, 1);
kp.processNoiseCov = Mat::eye(2, 2, type) * (1e-5);
kp.measurementMatrix = Mat::eye(1, 2, type);
kp.measurementNoiseCov = Mat::eye(1, 1, type) * (1e-1);
cv::GMat m;
cv::GOpaque<bool> have_measure;
cv::GMat out = cv::gapi::KalmanFilter(m, have_measure, kp);
cv::GComputation comp(cv::GIn(m, have_measure), cv::GOut(out));
// OCV Kalman initialization
cv::KalmanFilter KF(2, 1, 0);
initKalmanFilter(kp, false, KF);
cv::randn(state, Scalar::all(0), Scalar::all(0.1));
// GAPI Corrected state
cv::Mat gapiState(2, 1, type);
// OCV Corrected state
cv::Mat ocvCorrState(2, 1, type);
// OCV Predicted state
cv::Mat ocvPreState(2, 1, type);
bool haveMeasure;
for (int i = 0; i < numIter; ++i)
{
// Get OCV Prediction
ocvPreState = KF.predict();
GAPI_DbgAssert(cv::norm(kp.measurementNoiseCov, KF.measurementNoiseCov, cv::NORM_INF) == 0);
// generation measurement
cv::randn(measurement, Scalar::all(0), Scalar::all((type == CV_32FC1) ?
kp.measurementNoiseCov.at<float>(0) : kp.measurementNoiseCov.at<double>(0)));
GAPI_DbgAssert(cv::norm(kp.measurementMatrix, KF.measurementMatrix, cv::NORM_INF) == 0);
measurement += kp.measurementMatrix*state;
if (cv::theRNG().uniform(0, 4) != 0)
{
haveMeasure = true;
ocvCorrState = KF.correct(measurement);
comp.apply(cv::gin(measurement, haveMeasure), cv::gout(gapiState));
EXPECT_TRUE(AbsExact().to_compare_f()(gapiState, ocvCorrState));
}
else
{
// Get GAPI Prediction
haveMeasure = false;
comp.apply(cv::gin(measurement, haveMeasure), cv::gout(gapiState));
EXPECT_TRUE(AbsExact().to_compare_f()(gapiState, ocvPreState));
}
GAPI_DbgAssert(cv::norm(kp.processNoiseCov, KF.processNoiseCov, cv::NORM_INF) == 0);
cv::randn(processNoise, Scalar(0), Scalar::all(sqrt(type == CV_32FC1 ?
kp.processNoiseCov.at<float>(0, 0):
kp.processNoiseCov.at<double>(0, 0))));
GAPI_DbgAssert(cv::norm(kp.transitionMatrix, KF.transitionMatrix, cv::NORM_INF) == 0);
state = kp.transitionMatrix*state + processNoise;
}
}
#endif
} // opencv_test
#endif // OPENCV_GAPI_VIDEO_TESTS_INL_HPP
+75 -1
View File
@@ -2,7 +2,7 @@
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
// Copyright (C) 2018-2020 Intel Corporation
// Copyright (C) 2018-2021 Intel Corporation
#include "../test_precomp.hpp"
@@ -484,6 +484,73 @@ INSTANTIATE_TEST_CASE_P(NormalizeTestCPU, NormalizeTest,
Values(NORM_MINMAX, NORM_INF, NORM_L1, NORM_L2),
Values(-1, CV_8U, CV_16U, CV_16S, CV_32F)));
INSTANTIATE_TEST_CASE_P(KMeansNDNoInitTestCPU, KMeansNDTest,
Combine(Values(CV_32FC1),
Values(cv::Size(2, 20)),
Values(-1),
Values(CORE_CPU),
Values(AbsTolerance(0.01).to_compare_obj()),
Values(5),
Values(cv::KMEANS_RANDOM_CENTERS, cv::KMEANS_PP_CENTERS)));
INSTANTIATE_TEST_CASE_P(KMeansNDInitTestCPU, KMeansNDTest,
Combine(Values(CV_32FC1, CV_32FC3),
Values(cv::Size(1, 20),
cv::Size(2, 20),
cv::Size(5, 720)),
Values(-1),
Values(CORE_CPU),
Values(AbsTolerance(0.01).to_compare_obj()),
Values(5, 15),
Values(cv::KMEANS_RANDOM_CENTERS | cv::KMEANS_USE_INITIAL_LABELS,
cv::KMEANS_PP_CENTERS | cv::KMEANS_USE_INITIAL_LABELS)));
INSTANTIATE_TEST_CASE_P(KMeansNDInitReverseTestCPU, KMeansNDTest,
Combine(Values(CV_32FC3),
Values(cv::Size(20, 1)),
Values(-1),
Values(CORE_CPU),
Values(AbsTolerance(0.01).to_compare_obj()),
Values(5, 15),
Values(cv::KMEANS_RANDOM_CENTERS | cv::KMEANS_USE_INITIAL_LABELS,
cv::KMEANS_PP_CENTERS | cv::KMEANS_USE_INITIAL_LABELS)));
INSTANTIATE_TEST_CASE_P(KMeans2DNoInitTestCPU, KMeans2DTest,
Combine(Values(-1),
Values(cv::Size(-1, 20)),
Values(-1),
Values(CORE_CPU),
Values(5),
Values(cv::KMEANS_RANDOM_CENTERS, cv::KMEANS_PP_CENTERS)));
INSTANTIATE_TEST_CASE_P(KMeans2DInitTestCPU, KMeans2DTest,
Combine(Values(-1),
Values(cv::Size(-1, 720),
cv::Size(-1, 20)),
Values(-1),
Values(CORE_CPU),
Values(5, 15),
Values(cv::KMEANS_RANDOM_CENTERS | cv::KMEANS_USE_INITIAL_LABELS,
cv::KMEANS_PP_CENTERS | cv::KMEANS_USE_INITIAL_LABELS)));
INSTANTIATE_TEST_CASE_P(KMeans3DNoInitTestCPU, KMeans3DTest,
Combine(Values(-1),
Values(cv::Size(-1, 20)),
Values(-1),
Values(CORE_CPU),
Values(5),
Values(cv::KMEANS_RANDOM_CENTERS, cv::KMEANS_PP_CENTERS)));
INSTANTIATE_TEST_CASE_P(KMeans3DInitTestCPU, KMeans3DTest,
Combine(Values(-1),
Values(cv::Size(-1, 720),
cv::Size(-1, 20)),
Values(-1),
Values(CORE_CPU),
Values(5, 15),
Values(cv::KMEANS_RANDOM_CENTERS | cv::KMEANS_USE_INITIAL_LABELS,
cv::KMEANS_PP_CENTERS | cv::KMEANS_USE_INITIAL_LABELS)));
// PLEASE DO NOT PUT NEW ACCURACY TESTS BELOW THIS POINT! //////////////////////
INSTANTIATE_TEST_CASE_P(BackendOutputAllocationTestCPU, BackendOutputAllocationTest,
@@ -551,4 +618,11 @@ INSTANTIATE_TEST_CASE_P(SizeRTestCPU, SizeRTest,
cv::Size(640, 320)),
Values(-1),
Values(CORE_CPU)));
INSTANTIATE_TEST_CASE_P(SizeMFTestCPU, SizeMFTest,
Combine(Values(CV_8UC1, CV_8UC3, CV_32FC1),
Values(cv::Size(32, 32),
cv::Size(640, 320)),
Values(-1),
Values(CORE_CPU)));
}
@@ -105,7 +105,9 @@ INSTANTIATE_TEST_CASE_P(AbsDiffTestFluid, AbsDiffTest,
Values(CORE_FLUID)));
INSTANTIATE_TEST_CASE_P(AbsDiffCTestFluid, AbsDiffCTest,
Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1),
Combine(Values(CV_8UC1, CV_16UC1, CV_16SC1, CV_8UC2,
CV_16UC2, CV_16SC2, CV_8UC3, CV_16UC3,
CV_16SC3, CV_8UC4, CV_16UC4, CV_16SC4),
Values(cv::Size(1280, 720),
cv::Size(640, 480),
cv::Size(128, 128)),
@@ -433,12 +435,4 @@ INSTANTIATE_TEST_CASE_P(ReInitOutTestFluid, ReInitOutTest,
Values(CORE_FLUID),
Values(cv::Size(640, 400),
cv::Size(10, 480))));
INSTANTIATE_TEST_CASE_P(CopyTestFluid, CopyTest,
Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
Values(cv::Size(1280, 720),
cv::Size(640, 480),
cv::Size(128, 128)),
Values(-1),
Values(CORE_FLUID)));
}
@@ -270,7 +270,8 @@ INSTANTIATE_TEST_CASE_P(FindContoursNoOffsetTestCPU, FindContoursNoOffsetTest,
Values(cv::Size(1280, 720)),
Values(CV_8UC1),
Values(RETR_EXTERNAL),
Values(CHAIN_APPROX_NONE)));
Values(CHAIN_APPROX_NONE),
Values(AbsExact().to_compare_obj())));
INSTANTIATE_TEST_CASE_P(FindContoursOffsetTestCPU, FindContoursOffsetTest,
Values(IMGPROC_CPU));
@@ -282,7 +283,8 @@ INSTANTIATE_TEST_CASE_P(FindContoursHNoOffsetTestCPU, FindContoursHNoOffsetTest,
Values(CV_8UC1),
Values(RETR_EXTERNAL, RETR_LIST, RETR_CCOMP, RETR_TREE),
Values(CHAIN_APPROX_NONE, CHAIN_APPROX_SIMPLE,
CHAIN_APPROX_TC89_L1, CHAIN_APPROX_TC89_KCOS)));
CHAIN_APPROX_TC89_L1, CHAIN_APPROX_TC89_KCOS),
Values(AbsExact().to_compare_obj())));
INSTANTIATE_TEST_CASE_P(FindContoursHNoOffset32STestCPU, FindContoursHNoOffsetTest,
Combine(Values(IMGPROC_CPU),
@@ -291,7 +293,8 @@ INSTANTIATE_TEST_CASE_P(FindContoursHNoOffset32STestCPU, FindContoursHNoOffsetTe
Values(CV_32SC1),
Values(RETR_CCOMP, RETR_FLOODFILL),
Values(CHAIN_APPROX_NONE, CHAIN_APPROX_SIMPLE,
CHAIN_APPROX_TC89_L1, CHAIN_APPROX_TC89_KCOS)));
CHAIN_APPROX_TC89_L1, CHAIN_APPROX_TC89_KCOS),
Values(AbsExact().to_compare_obj())));
INSTANTIATE_TEST_CASE_P(FindContoursHOffsetTestCPU, FindContoursHOffsetTest,
Values(IMGPROC_CPU));
@@ -303,23 +306,17 @@ INSTANTIATE_TEST_CASE_P(BoundingRectMatTestCPU, BoundingRectMatTest,
cv::Size(128, 128)),
Values(-1),
Values(IMGPROC_CPU),
Values(IoUToleranceRect(0).to_compare_obj())));
Values(IoUToleranceRect(0).to_compare_obj()),
Values(false)));
INSTANTIATE_TEST_CASE_P(BoundingRectMatVector32STestCPU, BoundingRectMatVector32STest,
Combine(Values(-1),
INSTANTIATE_TEST_CASE_P(BoundingRectMatVectorTestCPU, BoundingRectMatTest,
Combine(Values(CV_32S, CV_32F),
Values(cv::Size(1280, 1),
cv::Size(128, 1)),
Values(-1),
Values(IMGPROC_CPU),
Values(IoUToleranceRect(0).to_compare_obj())));
INSTANTIATE_TEST_CASE_P(BoundingRectMatVector32FTestCPU, BoundingRectMatVector32FTest,
Combine(Values(-1),
Values(cv::Size(1280, 1),
cv::Size(128, 1)),
Values(-1),
Values(IMGPROC_CPU),
Values(IoUToleranceRect(1e-5).to_compare_obj())));
Values(IoUToleranceRect(1e-5).to_compare_obj()),
Values(true)));
INSTANTIATE_TEST_CASE_P(BoundingRectVector32STestCPU, BoundingRectVector32STest,
Combine(Values(-1),
@@ -0,0 +1,36 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
// Copyright (C) 2021 Intel Corporation
#include "../test_precomp.hpp"
#include "../common/gapi_stereo_tests.hpp"
#include <opencv2/gapi/stereo.hpp> // For ::gapi::stereo::disparity/depth
#include <opencv2/gapi/cpu/stereo.hpp>
namespace
{
#define STEREO_CPU [] () { return cv::compile_args(cv::gapi::use_only{cv::gapi::calib3d::cpu::kernels()}); }
} // anonymous namespace
namespace opencv_test
{
INSTANTIATE_TEST_CASE_P(CPU_Tests, TestGAPIStereo,
Combine(Values(CV_8UC1),
Values(cv::Size(1280, 720)),
Values(CV_32FC1),
Values(STEREO_CPU),
Values(cv::gapi::StereoOutputFormat::DEPTH_FLOAT16,
cv::gapi::StereoOutputFormat::DEPTH_FLOAT32,
cv::gapi::StereoOutputFormat::DISPARITY_FIXED16_12_4),
Values(16),
Values(43),
Values(10.),
Values(100.),
Values(AbsExact().to_compare_obj())));
} // opencv_test
@@ -97,4 +97,42 @@ INSTANTIATE_TEST_CASE_MACRO_P(WITH_VIDEO(BuildPyr_CalcOptFlow_PipelineInternalTe
Values(15),
Values(3),
Values(true)));
INSTANTIATE_TEST_CASE_MACRO_P(WITH_VIDEO(BackgroundSubtractorTestCPU),
BackgroundSubtractorTest,
Combine(Values(VIDEO_CPU),
Values(std::make_tuple(cv::gapi::video::TYPE_BS_MOG2, 16),
std::make_tuple(cv::gapi::video::TYPE_BS_MOG2, 8),
std::make_tuple(cv::gapi::video::TYPE_BS_KNN, 400),
std::make_tuple(cv::gapi::video::TYPE_BS_KNN, 200)),
Values(500, 50),
testing::Bool(),
Values(-1, 0, 0.5, 1),
Values("cv/video/768x576.avi"),
Values(3)));
INSTANTIATE_TEST_CASE_MACRO_P(KalmanFilterTestCPU,
KalmanFilterTest,
Combine(Values(VIDEO_CPU),
Values(CV_32FC1, CV_64FC1),
Values(2,5),
Values(2,5),
Values(2),
Values(5)));
INSTANTIATE_TEST_CASE_MACRO_P(KalmanFilterTestCPU,
KalmanFilterNoControlTest,
Combine(Values(VIDEO_CPU),
Values(CV_32FC1, CV_64FC1),
Values(3),
Values(4),
Values(3)));
INSTANTIATE_TEST_CASE_MACRO_P(KalmanFilterTestCPU,
KalmanFilterCircleSampleTest,
Combine(Values(VIDEO_CPU),
Values(CV_32FC1, CV_64FC1),
Values(5)));
} // opencv_test
@@ -0,0 +1,178 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
// Copyright (C) 2020 Intel Corporation
// Deliberately include .cpp file instead of header as we use non exported function (execute)
#include <executor/gtbbexecutor.cpp>
#ifdef HAVE_TBB
#include <tbb/tbb.h>
#include <tbb/task.h>
#if TBB_INTERFACE_VERSION < 12000
#include <tbb/task_arena.h>
#include "../test_precomp.hpp"
#include <thread>
namespace {
tbb::task_arena create_task_arena(int max_concurrency = tbb::task_arena::automatic /* set to 1 for single thread */) {
unsigned int reserved_for_master_threads = 1;
if (max_concurrency == 1) {
// Leave no room for TBB worker threads, by reserving all to masters.
// TBB runtime guarantees that no worker threads will join the arena
// if max_concurrency is equal to reserved_for_master_threads
// except 1:1 + use of enqueued tasks for safety guarantee.
// So deliberately make it 2:2 to force TBB not to create extra thread.
//
// N.B. one slot will left empty as only one master thread(one that
// calls root->wait_for_all()) will join the arena.
// FIXME: strictly speaking master can take any free slot, not the first one.
// However at the moment master seems to pick 0 slot all the time.
max_concurrency = 2;
reserved_for_master_threads = 2;
}
return tbb::task_arena{max_concurrency, reserved_for_master_threads};
}
}
namespace opencv_test {
TEST(TBBExecutor, Basic) {
using namespace cv::gimpl::parallel;
bool executed = false;
prio_items_queue_t q;
tile_node n([&]() {
executed = true;
});
q.push(&n);
execute(q);
EXPECT_EQ(true, executed);
}
TEST(TBBExecutor, SerialExecution) {
using namespace cv::gimpl::parallel;
const int n = 10;
prio_items_queue_t q;
std::vector<tile_node> nodes; nodes.reserve(n+1);
std::vector<std::thread::id> thread_id(n);
for (int i=0; i <n; i++) {
nodes.push_back(tile_node([&, i]() {
thread_id[i] = std::this_thread::get_id();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}));
q.push(&nodes.back());
}
auto serial_arena = create_task_arena(1);
execute(q, serial_arena);
auto print_thread_ids = [&] {
std::stringstream str;
for (auto& i : thread_id) { str << i <<" ";}
return str.str();
};
EXPECT_NE(thread_id[0], std::thread::id{}) << print_thread_ids();
EXPECT_EQ(thread_id.size(), static_cast<size_t>(std::count(thread_id.begin(), thread_id.end(), thread_id[0])))
<< print_thread_ids();
}
TEST(TBBExecutor, AsyncBasic) {
using namespace cv::gimpl::parallel;
std::atomic<bool> callback_ready {false};
std::function<void()> callback;
std::atomic<bool> callback_called {false};
std::atomic<bool> master_is_waiting {true};
std::atomic<bool> master_was_blocked_until_callback_called {false};
auto async_thread = std::thread([&] {
bool slept = false;
while (!callback_ready) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
slept = true;
}
if (!slept) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
callback_called = true;
master_was_blocked_until_callback_called = (master_is_waiting == true);
callback();
});
auto async_task_body = [&](std::function<void()>&& cb, size_t /*total_order_index*/) {
callback = std::move(cb);
callback_ready = true;
};
tile_node n(async, std::move(async_task_body));
prio_items_queue_t q;
q.push(&n);
execute(q);
master_is_waiting = false;
async_thread.join();
EXPECT_EQ(true, callback_called);
EXPECT_EQ(true, master_was_blocked_until_callback_called);
}
TEST(TBBExecutor, Dependencies) {
using namespace cv::gimpl::parallel;
const int n = 10;
bool serial = true;
std::atomic<int> counter {0};
prio_items_queue_t q;
std::vector<tile_node> nodes; nodes.reserve(n+1);
const int invalid_order = -10;
std::vector<int> tiles_exec_order(n, invalid_order);
auto add_dependency_to = [](tile_node& node, tile_node& dependency) {
dependency.dependants.push_back(&node);
node.dependencies++;
node.dependency_count.fetch_add(1);
};
for (int i=0; i <n; i++) {
nodes.push_back(tile_node([&, i]() {
tiles_exec_order[i] = counter++;
if (!serial) {
//sleep gives a better chance for other threads to take part in the execution
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}));
if (i >0) {
auto last_node = nodes.end() - 1;
add_dependency_to(*last_node, *(last_node -1));
}
}
q.push(&nodes.front());
auto arena = serial ? create_task_arena(1) : create_task_arena();
execute(q, arena);
auto print_execution_order = [&] {
std::stringstream str;
for (auto& i : tiles_exec_order) { str << i <<" ";}
return str.str();
};
ASSERT_EQ(0, std::count(tiles_exec_order.begin(), tiles_exec_order.end(), invalid_order))
<< "Not all " << n << " task executed ?\n"
<<" execution order : " << print_execution_order();
for (size_t i=0; i <nodes.size(); i++) {
auto node_exec_order = tiles_exec_order[i];
for (auto* dependee : nodes[i].dependants) {
auto index = std::distance(&nodes.front(), dependee);
auto dependee_execution_order = tiles_exec_order[index];
ASSERT_LT(node_exec_order, dependee_execution_order) << "node number " << index << " is executed earlier than it's dependency " << i;
}
}
}
} // namespace opencv_test
#endif //TBB_INTERFACE_VERSION
#endif //HAVE_TBB
+30
View File
@@ -32,6 +32,10 @@ G_TYPED_KERNEL(PointIncrement, <GPointArray(GMat, GPointArray)>, "test.point_inc
{
static GArrayDesc outMeta(const GMatDesc&, const GArrayDesc&) { return empty_array_desc(); }
};
G_TYPED_KERNEL(CountContours, <GOpaque<size_t>(GArray<GPointArray>)>, "test.array.array.in")
{
static GOpaqueDesc outMeta(const GArrayDesc&) { return empty_gopaque_desc(); }
};
} // namespace ThisTest
namespace
@@ -70,6 +74,14 @@ GAPI_OCV_KERNEL(OCVPointIncrement, ThisTest::PointIncrement)
}
};
GAPI_OCV_KERNEL(OCVCountContours, ThisTest::CountContours)
{
static void run(const std::vector<std::vector<cv::Point>> &contours, size_t &out)
{
out = contours.size();
}
};
cv::Mat cross(int w, int h)
{
cv::Mat mat = cv::Mat::eye(h, w, CV_8UC1)*255;
@@ -177,6 +189,24 @@ TEST(GArray, TestIntermediateOutput)
EXPECT_EQ(10, out_count[0]);
}
TEST(GArray, TestGArrayGArrayKernelInput)
{
cv::GMat in;
auto contours = cv::gapi::findContours(in, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
auto out = ThisTest::CountContours::on(contours);
cv::GComputation c(GIn(in), GOut(out));
// Create input - two filled rectangles
cv::Mat in_mat = cv::Mat::zeros(50, 50, CV_8UC1);
cv::rectangle(in_mat, cv::Point{5,5}, cv::Point{20,20}, 255, cv::FILLED);
cv::rectangle(in_mat, cv::Point{25,25}, cv::Point{40,40}, 255, cv::FILLED);
size_t out_count = 0u;
c.apply(gin(in_mat), gout(out_count), cv::compile_args(cv::gapi::kernels<OCVCountContours>()));
EXPECT_EQ(2u, out_count) << "Two contours must be found";
}
TEST(GArray, GArrayConstValInitialization)
{
std::vector<cv::Point> initial_vec {Point(0,0), Point(1,1), Point(2,2)};
+7 -1
View File
@@ -356,7 +356,12 @@ template<typename case_t>
struct cancel : ::testing::Test{};
TYPED_TEST_CASE_P(cancel);
TYPED_TEST_P(cancel, basic){
TYPED_TEST_P(cancel, basic)
{
#if defined(__GNUC__) && __GNUC__ >= 11
// std::vector<TypeParam> requests can't handle type with ctor parameter (SelfCanceling)
FAIL() << "Test code is not available due to compilation error with GCC 11";
#else
constexpr int num_tasks = 100;
cancel_struct cancel_struct_ {num_tasks};
std::vector<TypeParam> requests; requests.reserve(num_tasks);
@@ -378,6 +383,7 @@ TYPED_TEST_P(cancel, basic){
}
}
ASSERT_GT(canceled, 0u);
#endif
}
namespace {
+5 -5
View File
@@ -862,11 +862,11 @@ uint64_t currMemoryConsumption()
}
std::string stat_line;
std::getline(proc_stat, stat_line);
uint64_t unused, rss;
// using resident set size
std::istringstream(stat_line) >> unused >> rss;
CV_Assert(rss != 0);
return rss;
uint64_t unused, data_and_stack;
std::istringstream(stat_line) >> unused >> unused >> unused >> unused >> unused
>> data_and_stack;
CV_Assert(data_and_stack != 0);
return data_and_stack;
}
#else
// FIXME: implement this part (at least for Windows?), right now it's enough to check Linux only
+21 -10
View File
@@ -81,7 +81,7 @@ namespace opencv_test
void check(const std::vector<cv::Mat>& out_mats)
{
for (const auto& it : ade::util::zip(ref_mats, out_mats))
for (const auto it : ade::util::zip(ref_mats, out_mats))
{
const auto& ref_mat = std::get<0>(it);
const auto& out_mat = std::get<1>(it);
@@ -91,8 +91,6 @@ namespace opencv_test
}
};
// NB: Check an apply specifically designed to be called from Python,
// but can also be used from C++
struct GComputationPythonApplyTest: public ::testing::Test
{
cv::Size sz;
@@ -103,22 +101,28 @@ namespace opencv_test
GComputationPythonApplyTest() : sz(cv::Size(300,300)), type(CV_8UC1),
in_mat1(sz, type), in_mat2(sz, type), out_mat_ocv(sz, type),
m_c([&](){
cv::GMat in1, in2;
cv::GMat out = in1 + in2;
return cv::GComputation(cv::GIn(in1, in2), cv::GOut(out));
})
cv::GMat in1, in2;
cv::GMat out = in1 + in2;
return cv::GComputation(cv::GIn(in1, in2), cv::GOut(out));
})
{
cv::randu(in_mat1, cv::Scalar::all(0), cv::Scalar::all(255));
cv::randu(in_mat2, cv::Scalar::all(0), cv::Scalar::all(255));
out_mat_ocv = in_mat1 + in_mat2;
}
};
}
TEST_F(GComputationPythonApplyTest, WithoutSerialization)
{
auto output = m_c.apply(cv::gin(in_mat1, in_mat2));
auto output = m_c.apply(cv::detail::ExtractArgsCallback{[this](const cv::GTypesInfo& info)
{
GAPI_Assert(info[0].shape == cv::GShape::GMAT);
GAPI_Assert(info[1].shape == cv::GShape::GMAT);
return cv::GRunArgs{in_mat1, in_mat2};
}
});
EXPECT_EQ(1u, output.size());
const auto& out_mat_gapi = cv::util::get<cv::Mat>(output[0]);
@@ -130,7 +134,14 @@ namespace opencv_test
auto p = cv::gapi::serialize(m_c);
auto c = cv::gapi::deserialize<cv::GComputation>(p);
auto output = c.apply(cv::gin(in_mat1, in_mat2));
auto output = c.apply(cv::detail::ExtractArgsCallback{[this](const cv::GTypesInfo& info)
{
GAPI_Assert(info[0].shape == cv::GShape::GMAT);
GAPI_Assert(info[1].shape == cv::GShape::GMAT);
return cv::GRunArgs{in_mat1, in_mat2};
}
});
EXPECT_EQ(1u, output.size());
const auto& out_mat_gapi = cv::util::get<cv::Mat>(output[0]);
+25 -1
View File
@@ -2,8 +2,9 @@
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
// Copyright (C) 2018 Intel Corporation
// Copyright (C) 2018-2021 Intel Corporation
#include <algorithm>
#include "test_precomp.hpp"
#include "gapi_mock_kernels.hpp"
@@ -146,6 +147,29 @@ TEST(KernelPackage, Includes)
EXPECT_FALSE(pkg.includes<J::Qux>());
}
TEST(KernelPackage, Include)
{
namespace J = Jupiter;
auto pkg = cv::gapi::kernels();
pkg.include(J::backend(), "test.kernels.foo");
pkg.include(J::backend(), "test.kernels.bar");
EXPECT_TRUE (pkg.includes<J::Foo>());
EXPECT_TRUE (pkg.includes<J::Bar>());
}
TEST(KernelPackage, GetIds)
{
namespace J = Jupiter;
auto pkg = cv::gapi::kernels();
pkg.include(J::backend(), "test.kernels.foo");
pkg.include(J::backend(), "test.kernels.bar");
pkg.include<J::Baz>();
auto ids = pkg.get_kernel_ids();
EXPECT_NE(ids.end(), std::find(ids.begin(), ids.end(), "test.kernels.foo"));
EXPECT_NE(ids.end(), std::find(ids.begin(), ids.end(), "test.kernels.bar"));
EXPECT_NE(ids.end(), std::find(ids.begin(), ids.end(), "test.kernels.baz"));
}
TEST(KernelPackage, IncludesAPI)
{
namespace J = Jupiter;
@@ -359,14 +359,6 @@ INSTANTIATE_TEST_CASE_P(CropTestGPU, CropTest,
Values(CORE_GPU),
Values(cv::Rect(10, 8, 20, 35), cv::Rect(4, 10, 37, 50))));
INSTANTIATE_TEST_CASE_P(CopyTestGPU, CopyTest,
Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
Values(cv::Size(1280, 720),
cv::Size(640, 480),
cv::Size(128, 128)),
Values(-1),
Values(CORE_GPU)));
INSTANTIATE_TEST_CASE_P(LUTTestGPU, LUTTest,
Combine(Values(CV_8UC1, CV_8UC3),
Values(cv::Size(1280, 720),
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -213,7 +213,7 @@ TEST(GModelBuilder, Check_Multiple_Outputs)
EXPECT_EQ(0u, gm.metadata(p.out_nhs[1]->inEdges().front()).get<cv::gimpl::Output>().port);
EXPECT_EQ(1u, gm.metadata(p.out_nhs[2]->inEdges().front()).get<cv::gimpl::Output>().port);
EXPECT_EQ(0u, gm.metadata(p.out_nhs[3]->inEdges().front()).get<cv::gimpl::Output>().port);
for (const auto& it : ade::util::indexed(p.out_nhs))
for (const auto it : ade::util::indexed(p.out_nhs))
{
const auto& out_nh = ade::util::value(it);
@@ -527,6 +527,7 @@ TEST(IslandFusion, Test_Desync_NoFuse)
//////////////////////////////////////////////////////////////////
// Compile the graph in "regular" mode, it should produce a single island
// Note: with copy moved to a separate backend there is always 3 islands in this test
{
using namespace cv::gimpl;
@@ -544,11 +545,12 @@ TEST(IslandFusion, Test_Desync_NoFuse)
const auto num_isl = std::count_if(gim.nodes().begin(),
gim.nodes().end(),
is_island);
EXPECT_EQ(1, num_isl);
EXPECT_EQ(3, num_isl);
}
//////////////////////////////////////////////////////////////////
// Now compile the graph in the streaming mode.
// It has to produce two islands
// Note: with copy moved to a separate backend there is always 3 islands in this test
{
using namespace cv::gimpl;
@@ -567,7 +569,7 @@ TEST(IslandFusion, Test_Desync_NoFuse)
const auto num_isl = std::count_if(gim.nodes().begin(),
gim.nodes().end(),
is_island);
EXPECT_EQ(2, num_isl);
EXPECT_EQ(3, num_isl);
}
}
@@ -73,6 +73,54 @@ TEST_P(RenderNV12OCVTestTexts, AccuracyTest)
}
}
class TestMediaNV12 final : public cv::MediaFrame::IAdapter {
cv::Mat m_y;
cv::Mat m_uv;
public:
TestMediaNV12(cv::Mat y, cv::Mat uv) : m_y(y), m_uv(uv) {
}
cv::GFrameDesc meta() const override {
return cv::GFrameDesc{ cv::MediaFormat::NV12, cv::Size(m_y.cols, m_y.rows) };
}
cv::MediaFrame::View access(cv::MediaFrame::Access) override {
cv::MediaFrame::View::Ptrs pp = {
m_y.ptr(), m_uv.ptr(), nullptr, nullptr
};
cv::MediaFrame::View::Strides ss = {
m_y.step, m_uv.step, 0u, 0u
};
return cv::MediaFrame::View(std::move(pp), std::move(ss));
}
};
TEST_P(RenderMFrameOCVTestTexts, AccuracyTest)
{
// G-API code //////////////////////////////////////////////////////////////
cv::gapi::wip::draw::Prims prims;
prims.emplace_back(cv::gapi::wip::draw::Text{ text, org, ff, fs, color, thick, lt, blo });
cv::MediaFrame nv12 = cv::MediaFrame::Create<TestMediaNV12>(y_gapi_mat, uv_gapi_mat);
cv::gapi::wip::draw::render(nv12, prims);
// OpenCV code //////////////////////////////////////////////////////////////
{
// NV12 -> YUV
cv::Mat yuv;
cv::gapi::wip::draw::cvtNV12ToYUV(y_ref_mat, uv_ref_mat, yuv);
cv::putText(yuv, text, org, ff, fs, cvtBGRToYUVC(color), thick, lt, blo);
// YUV -> NV12
cv::gapi::wip::draw::cvtYUVToNV12(yuv, y_ref_mat, uv_ref_mat);
}
// Comparison //////////////////////////////////////////////////////////////
{
EXPECT_EQ(0, cv::norm(y_gapi_mat, y_ref_mat));
EXPECT_EQ(0, cv::norm(uv_gapi_mat, uv_ref_mat));
}
}
# ifdef HAVE_FREETYPE
TEST_P(RenderBGROCVTestFTexts, AccuracyTest)
@@ -97,6 +145,23 @@ TEST_P(RenderNV12OCVTestFTexts, AccuracyTest)
})));
}
TEST_P(RenderMFrameOCVTestFTexts, AccuracyTest)
{
// G-API code //////////////////////////////////////////////////////////////
cv::Mat y_copy_mat = y_gapi_mat.clone();
cv::Mat uv_copy_mat = uv_gapi_mat.clone();
cv::gapi::wip::draw::Prims prims;
prims.emplace_back(cv::gapi::wip::draw::FText{ text, org, fh, color });
cv::MediaFrame nv12 = cv::MediaFrame::Create<TestMediaNV12>(y_gapi_mat, uv_gapi_mat);
EXPECT_NO_THROW(cv::gapi::wip::draw::render(nv12, prims,
cv::compile_args(cv::gapi::wip::draw::freetype_font{
"/usr/share/fonts/truetype/wqy/wqy-microhei.ttc"
})));
EXPECT_NE(0, cv::norm(y_gapi_mat, y_copy_mat));
EXPECT_NE(0, cv::norm(uv_gapi_mat, uv_copy_mat));
}
static std::wstring to_wstring(const char* bytes)
{
std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> converter;
@@ -164,6 +229,33 @@ TEST_P(RenderNV12OCVTestRects, AccuracyTest)
}
}
TEST_P(RenderMFrameOCVTestRects, AccuracyTest)
{
// G-API code //////////////////////////////////////////////////////////////
cv::gapi::wip::draw::Prims prims;
prims.emplace_back(cv::gapi::wip::draw::Rect{ rect, color, thick, lt, shift });
cv::MediaFrame nv12 = cv::MediaFrame::Create<TestMediaNV12>(y_gapi_mat, uv_gapi_mat);
cv::gapi::wip::draw::render(nv12, prims);
// OpenCV code //////////////////////////////////////////////////////////////
{
// NV12 -> YUV
cv::Mat yuv;
cv::gapi::wip::draw::cvtNV12ToYUV(y_ref_mat, uv_ref_mat, yuv);
cv::rectangle(yuv, rect, cvtBGRToYUVC(color), thick, lt, shift);
// YUV -> NV12
cv::gapi::wip::draw::cvtYUVToNV12(yuv, y_ref_mat, uv_ref_mat);
}
// Comparison //////////////////////////////////////////////////////////////
{
EXPECT_EQ(0, cv::norm(y_gapi_mat, y_ref_mat));
EXPECT_EQ(0, cv::norm(uv_gapi_mat, uv_ref_mat));
}
}
TEST_P(RenderBGROCVTestCircles, AccuracyTest)
{
// G-API code //////////////////////////////////////////////////////////////
@@ -208,6 +300,33 @@ TEST_P(RenderNV12OCVTestCircles, AccuracyTest)
}
}
TEST_P(RenderMFrameOCVTestCircles, AccuracyTest)
{
// G-API code //////////////////////////////////////////////////////////////
cv::gapi::wip::draw::Prims prims;
prims.emplace_back(cv::gapi::wip::draw::Circle{ center, radius, color, thick, lt, shift });
cv::MediaFrame nv12 = cv::MediaFrame::Create<TestMediaNV12>(y_gapi_mat, uv_gapi_mat);
cv::gapi::wip::draw::render(nv12, prims);
// OpenCV code //////////////////////////////////////////////////////////////
{
// NV12 -> YUV
cv::Mat yuv;
cv::gapi::wip::draw::cvtNV12ToYUV(y_ref_mat, uv_ref_mat, yuv);
cv::circle(yuv, center, radius, cvtBGRToYUVC(color), thick, lt, shift);
// YUV -> NV12
cv::gapi::wip::draw::cvtYUVToNV12(yuv, y_ref_mat, uv_ref_mat);
}
// Comparison //////////////////////////////////////////////////////////////
{
EXPECT_EQ(0, cv::norm(y_gapi_mat, y_ref_mat));
EXPECT_EQ(0, cv::norm(uv_gapi_mat, uv_ref_mat));
}
}
TEST_P(RenderBGROCVTestLines, AccuracyTest)
{
// G-API code //////////////////////////////////////////////////////////////
@@ -252,6 +371,33 @@ TEST_P(RenderNV12OCVTestLines, AccuracyTest)
}
}
TEST_P(RenderMFrameOCVTestLines, AccuracyTest)
{
// G-API code //////////////////////////////////////////////////////////////
cv::gapi::wip::draw::Prims prims;
prims.emplace_back(cv::gapi::wip::draw::Line{ pt1, pt2, color, thick, lt, shift });
cv::MediaFrame nv12 = cv::MediaFrame::Create<TestMediaNV12>(y_gapi_mat, uv_gapi_mat);
cv::gapi::wip::draw::render(nv12, prims);
// OpenCV code //////////////////////////////////////////////////////////////
{
// NV12 -> YUV
cv::Mat yuv;
cv::gapi::wip::draw::cvtNV12ToYUV(y_ref_mat, uv_ref_mat, yuv);
cv::line(yuv, pt1, pt2, cvtBGRToYUVC(color), thick, lt, shift);
// YUV -> NV12
cv::gapi::wip::draw::cvtYUVToNV12(yuv, y_ref_mat, uv_ref_mat);
}
// Comparison //////////////////////////////////////////////////////////////
{
EXPECT_EQ(0, cv::norm(y_gapi_mat, y_ref_mat));
EXPECT_EQ(0, cv::norm(uv_gapi_mat, uv_ref_mat));
}
}
TEST_P(RenderBGROCVTestMosaics, AccuracyTest)
{
// G-API code //////////////////////////////////////////////////////////////
@@ -296,6 +442,33 @@ TEST_P(RenderNV12OCVTestMosaics, AccuracyTest)
}
}
TEST_P(RenderMFrameOCVTestMosaics, AccuracyTest)
{
// G-API code //////////////////////////////////////////////////////////////
cv::gapi::wip::draw::Prims prims;
prims.emplace_back(cv::gapi::wip::draw::Mosaic{ mos, cellsz, decim });
cv::MediaFrame nv12 = cv::MediaFrame::Create<TestMediaNV12>(y_gapi_mat, uv_gapi_mat);
cv::gapi::wip::draw::render(nv12, prims);
// OpenCV code //////////////////////////////////////////////////////////////
{
// NV12 -> YUV
cv::Mat yuv;
cv::gapi::wip::draw::cvtNV12ToYUV(y_ref_mat, uv_ref_mat, yuv);
drawMosaicRef(yuv, mos, cellsz);
// YUV -> NV12
cv::gapi::wip::draw::cvtYUVToNV12(yuv, y_ref_mat, uv_ref_mat);
}
// Comparison //////////////////////////////////////////////////////////////
{
EXPECT_EQ(0, cv::norm(y_gapi_mat, y_ref_mat));
EXPECT_EQ(0, cv::norm(uv_gapi_mat, uv_ref_mat));
}
}
TEST_P(RenderBGROCVTestImages, AccuracyTest)
{
cv::Mat img(rect.size(), CV_8UC3, color);
@@ -352,6 +525,40 @@ TEST_P(RenderNV12OCVTestImages, AccuracyTest)
}
}
TEST_P(RenderMFrameOCVTestImages, AccuracyTest)
{
cv::Mat img(rect.size(), CV_8UC3, color);
cv::Mat alpha(rect.size(), CV_32FC1, transparency);
auto tl = rect.tl();
cv::Point org = { tl.x, tl.y + rect.size().height };
// G-API code //////////////////////////////////////////////////////////////
cv::gapi::wip::draw::Prims prims;
prims.emplace_back(cv::gapi::wip::draw::Image{ org, img, alpha });
cv::MediaFrame nv12 = cv::MediaFrame::Create<TestMediaNV12>(y_gapi_mat, uv_gapi_mat);
cv::gapi::wip::draw::render(nv12, prims);
// OpenCV code //////////////////////////////////////////////////////////////
{
// NV12 -> YUV
cv::Mat yuv;
cv::gapi::wip::draw::cvtNV12ToYUV(y_ref_mat, uv_ref_mat, yuv);
cv::Mat yuv_img;
cv::cvtColor(img, yuv_img, cv::COLOR_BGR2YUV);
blendImageRef(yuv, org, yuv_img, alpha);
// YUV -> NV12
cv::gapi::wip::draw::cvtYUVToNV12(yuv, y_ref_mat, uv_ref_mat);
}
// Comparison //////////////////////////////////////////////////////////////
{
EXPECT_EQ(0, cv::norm(y_gapi_mat, y_ref_mat));
EXPECT_EQ(0, cv::norm(uv_gapi_mat, uv_ref_mat));
}
}
TEST_P(RenderBGROCVTestPolylines, AccuracyTest)
{
// G-API code //////////////////////////////////////////////////////////////
@@ -398,6 +605,34 @@ TEST_P(RenderNV12OCVTestPolylines, AccuracyTest)
}
}
TEST_P(RenderMFrameOCVTestPolylines, AccuracyTest)
{
// G-API code //////////////////////////////////////////////////////////////
cv::gapi::wip::draw::Prims prims;
prims.emplace_back(cv::gapi::wip::draw::Poly{ points, color, thick, lt, shift });
cv::MediaFrame nv12 = cv::MediaFrame::Create<TestMediaNV12>(y_gapi_mat, uv_gapi_mat);
cv::gapi::wip::draw::render(nv12, prims);
// OpenCV code //////////////////////////////////////////////////////////////
{
// NV12 -> YUV
cv::Mat yuv;
cv::gapi::wip::draw::cvtNV12ToYUV(y_ref_mat, uv_ref_mat, yuv);
std::vector<std::vector<cv::Point>> pp{ points };
cv::fillPoly(yuv, pp, cvtBGRToYUVC(color), lt, shift);
// YUV -> NV12
cv::gapi::wip::draw::cvtYUVToNV12(yuv, y_ref_mat, uv_ref_mat);
}
// Comparison //////////////////////////////////////////////////////////////
{
EXPECT_EQ(0, cv::norm(y_gapi_mat, y_ref_mat));
EXPECT_EQ(0, cv::norm(uv_gapi_mat, uv_ref_mat));
}
}
// FIXME avoid code duplicate for NV12 and BGR cases
INSTANTIATE_TEST_CASE_P(RenderBGROCVTestRectsImpl, RenderBGROCVTestRects,
Combine(Values(cv::Size(1280, 720)),
@@ -415,6 +650,14 @@ INSTANTIATE_TEST_CASE_P(RenderNV12OCVTestRectsImpl, RenderNV12OCVTestRects,
Values(LINE_8),
Values(0)));
INSTANTIATE_TEST_CASE_P(RenderMFrameOCVTestRectsImpl, RenderMFrameOCVTestRects,
Combine(Values(cv::Size(1280, 720)),
Values(cv::Rect(100, 100, 200, 200)),
Values(cv::Scalar(100, 50, 150)),
Values(2),
Values(LINE_8),
Values(0)));
INSTANTIATE_TEST_CASE_P(RenderBGROCVTestCirclesImpl, RenderBGROCVTestCircles,
Combine(Values(cv::Size(1280, 720)),
Values(cv::Point(100, 100)),
@@ -433,6 +676,15 @@ INSTANTIATE_TEST_CASE_P(RenderNV12OCVTestCirclesImpl, RenderNV12OCVTestCircles,
Values(LINE_8),
Values(0)));
INSTANTIATE_TEST_CASE_P(RenderMFrameOCVTestCirclesImpl, RenderMFrameOCVTestCircles,
Combine(Values(cv::Size(1280, 720)),
Values(cv::Point(100, 100)),
Values(10),
Values(cv::Scalar(100, 50, 150)),
Values(2),
Values(LINE_8),
Values(0)));
INSTANTIATE_TEST_CASE_P(RenderBGROCVTestLinesImpl, RenderBGROCVTestLines,
Combine(Values(cv::Size(1280, 720)),
Values(cv::Point(100, 100)),
@@ -451,6 +703,15 @@ INSTANTIATE_TEST_CASE_P(RenderNV12OCVTestLinesImpl, RenderNV12OCVTestLines,
Values(LINE_8),
Values(0)));
INSTANTIATE_TEST_CASE_P(RenderMFrameOCVTestLinesImpl, RenderMFrameOCVTestLines,
Combine(Values(cv::Size(1280, 720)),
Values(cv::Point(100, 100)),
Values(cv::Point(200, 200)),
Values(cv::Scalar(100, 50, 150)),
Values(2),
Values(LINE_8),
Values(0)));
INSTANTIATE_TEST_CASE_P(RenderBGROCVTestTextsImpl, RenderBGROCVTestTexts,
Combine(Values(cv::Size(1280, 720)),
Values("SomeText"),
@@ -473,6 +734,18 @@ INSTANTIATE_TEST_CASE_P(RenderNV12OCVTestTextsImpl, RenderNV12OCVTestTexts,
Values(LINE_8),
Values(false)));
INSTANTIATE_TEST_CASE_P(RenderMFrameOCVTestTextsImpl, RenderMFrameOCVTestTexts,
Combine(Values(cv::Size(1280, 720)),
Values("SomeText"),
Values(cv::Point(200, 200)),
Values(FONT_HERSHEY_SIMPLEX),
Values(2.0),
Values(cv::Scalar(0, 255, 0)),
Values(2),
Values(LINE_8),
Values(false)));
#ifdef HAVE_FREETYPE
INSTANTIATE_TEST_CASE_P(RenderBGROCVTestFTextsImpl, RenderBGROCVTestFTexts,
@@ -490,6 +763,15 @@ INSTANTIATE_TEST_CASE_P(RenderNV12OCVTestFTextsImpl, RenderNV12OCVTestFTexts,
Values(cv::Point(200, 200)),
Values(64),
Values(cv::Scalar(0, 255, 0))));
INSTANTIATE_TEST_CASE_P(RenderMFrameOCVTestFTextsImpl, RenderMFrameOCVTestFTexts,
Combine(Values(cv::Size(1280, 720)),
Values(to_wstring("\xe4\xbd\xa0\xe5\xa5\xbd\xef\xbc\x8c\xe4\xb8\x96\xe7\x95\x8c"),
to_wstring("\xe3\x80\xa4\xe3\x80\xa5\xe3\x80\xa6\xe3\x80\xa7\xe3\x80\xa8\xe3\x80\x85\xe3\x80\x86")),
Values(cv::Point(200, 200)),
Values(64),
Values(cv::Scalar(0, 255, 0))));
#endif // HAVE_FREETYPE
// FIXME Implement a macros to instantiate the tests because BGR and NV12 have the same parameters
@@ -530,6 +812,24 @@ INSTANTIATE_TEST_CASE_P(RenderNV12OCVTestMosaicsImpl, RenderNV12OCVTestMosaics,
Values(25),
Values(0)));
INSTANTIATE_TEST_CASE_P(RenderMFrameOCVTestMosaicsImpl, RenderMFrameOCVTestMosaics,
Combine(Values(cv::Size(1280, 720)),
Values(cv::Rect(100, 100, 200, 200), // Normal case
cv::Rect(-50, -50, 200, 200), // Intersection with left-top corner
cv::Rect(-50, 100, 200, 200), // Intersection with left side
cv::Rect(-50, 600, 200, 200), // Intersection with left-bottom corner
cv::Rect(100, 600, 200, 200), // Intersection with bottom side
cv::Rect(1200, 700, 200, 200), // Intersection with right-bottom corner
cv::Rect(1200, 400, 200, 200), // Intersection with right side
cv::Rect(1200, -50, 200, 200), // Intersection with right-top corner
cv::Rect(500, -50, 200, 200), // Intersection with top side
cv::Rect(-100, 300, 1480, 300), // From left to right side with intersection
cv::Rect(5000, 2000, 100, 100), // Outside image
cv::Rect(-300, -300, 3000, 3000), // Cover all image
cv::Rect(100, 100, -500, -500)), // Negative width and height
Values(25),
Values(0)));
INSTANTIATE_TEST_CASE_P(RenderBGROCVTestImagesImpl, RenderBGROCVTestImages,
Combine(Values(cv::Size(1280, 720)),
Values(cv::Rect(100, 100, 200, 200)),
@@ -542,6 +842,12 @@ INSTANTIATE_TEST_CASE_P(RenderNV12OCVTestImagesImpl, RenderNV12OCVTestImages,
Values(cv::Scalar(100, 150, 60)),
Values(1.0)));
INSTANTIATE_TEST_CASE_P(RenderMFrameOCVTestImagesImpl, RenderMFrameOCVTestImages,
Combine(Values(cv::Size(1280, 720)),
Values(cv::Rect(100, 100, 200, 200)),
Values(cv::Scalar(100, 150, 60)),
Values(1.0)));
INSTANTIATE_TEST_CASE_P(RenderBGROCVTestPolylinesImpl, RenderBGROCVTestPolylines,
Combine(Values(cv::Size(1280, 720)),
Values(std::vector<cv::Point>{{100, 100}, {200, 200}, {150, 300}, {400, 150}}),
@@ -557,4 +863,12 @@ INSTANTIATE_TEST_CASE_P(RenderNV12OCVTestPolylinesImpl, RenderNV12OCVTestPolylin
Values(2),
Values(LINE_8),
Values(0)));
INSTANTIATE_TEST_CASE_P(RenderMFrameOCVTestPolylinesImpl, RenderMFrameOCVTestPolylines,
Combine(Values(cv::Size(1280, 720)),
Values(std::vector<cv::Point>{ {100, 100}, { 200, 200 }, { 150, 300 }, { 400, 150 }}),
Values(cv::Scalar(100, 150, 60)),
Values(2),
Values(LINE_8),
Values(0)));
}
@@ -571,6 +571,16 @@ TEST_F(S11N_Basic, Test_Bind_RunArgs_MatScalar) {
}
}
TEST_F(S11N_Basic, Test_Vector_Of_Strings) {
std::vector<std::string> vs{"hello", "world", "42"};
const std::vector<char> ser = cv::gapi::serialize(vs);
auto des = cv::gapi::deserialize<std::vector<std::string>>(ser);
EXPECT_EQ("hello", des[0]);
EXPECT_EQ("world", des[1]);
EXPECT_EQ("42", des[2]);
}
TEST_F(S11N_Basic, Test_RunArg_RMat) {
cv::Mat mat = cv::Mat::eye(cv::Size(128, 64), CV_8UC3);
cv::RMat rmat = cv::make_rmat<MyRMatAdapter>(mat, 42, "It actually works");
@@ -0,0 +1,220 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
// Copyright (C) 2021 Intel Corporation
#include "../test_precomp.hpp"
#include <opencv2/gapi/streaming/cap.hpp>
#include <opencv2/gapi/core.hpp>
#include <opencv2/gapi/fluid/imgproc.hpp>
#include <opencv2/gapi/streaming/cap.hpp>
#include <opencv2/gapi/streaming/sync.hpp>
namespace opencv_test {
namespace {
using ts_t = int64_t;
using ts_vec = std::vector<ts_t>;
using cv::gapi::streaming::sync_policy;
ts_t calcLeastCommonMultiple(const ts_vec& values) {
ts_t res = *std::max_element(values.begin(), values.end());
auto isDivisor = [&](ts_t v) { return res % v == 0; };
while(!std::all_of(values.begin(), values.end(), isDivisor)) {
res++;
}
return res;
}
struct TimestampGenerationParams {
const ts_vec frame_times;
sync_policy policy;
ts_t end_time;
TimestampGenerationParams(const ts_vec& ft, sync_policy sp, ts_t et = 25)
: frame_times(ft), policy(sp), end_time(et) {
}
};
class MultiFrameSource {
class SingleSource : public cv::gapi::wip::IStreamSource {
MultiFrameSource& m_source;
std::size_t m_idx;
public:
SingleSource(MultiFrameSource& s, std::size_t idx)
: m_source(s)
, m_idx(idx)
{}
virtual bool pull(cv::gapi::wip::Data& data) {
return m_source.pull(data, m_idx);
}
virtual GMetaArg descr_of() const { return GMetaArg{m_source.desc()}; }
};
TimestampGenerationParams p;
ts_vec m_current_times;
cv::Mat m_mat;
public:
MultiFrameSource(const TimestampGenerationParams& params)
: p(params)
, m_current_times(p.frame_times.size(), 0u)
, m_mat(8, 8, CV_8UC1) {
}
bool pull(cv::gapi::wip::Data& data, std::size_t idx) {
cv::randn(m_mat, 127, 32);
GAPI_Assert(idx < p.frame_times.size());
m_current_times[idx] += p.frame_times[idx];
if (m_current_times[idx] >= p.end_time) {
return false;
}
data = m_mat.clone();
data.meta[cv::gapi::streaming::meta_tag::timestamp] = m_current_times[idx];
return true;
}
cv::gapi::wip::IStreamSource::Ptr getSource(std::size_t idx) {
return cv::gapi::wip::IStreamSource::Ptr{new SingleSource(*this, idx)};
}
GMatDesc desc() const { return cv::descr_of(m_mat); }
};
class TimestampChecker {
TimestampGenerationParams p;
ts_t m_synced_time = 0u;
ts_t m_synced_frame_time = 0u;
public:
TimestampChecker(const TimestampGenerationParams& params)
: p(params)
, m_synced_frame_time(calcLeastCommonMultiple(p.frame_times)) {
}
void checkNext(const ts_vec& timestamps) {
if (p.policy == sync_policy::dont_sync) {
// don't check timestamps if the policy is dont_sync
return;
}
m_synced_time += m_synced_frame_time;
for (const auto& ts : timestamps) {
EXPECT_EQ(m_synced_time, ts);
}
}
std::size_t nFrames() const {
auto frame_time = p.policy == sync_policy::dont_sync
? *std::max_element(p.frame_times.begin(), p.frame_times.end())
: m_synced_frame_time;
auto n_frames = p.end_time / frame_time;
GAPI_Assert(n_frames > 0u);
return (std::size_t)n_frames;
}
};
struct TimestampSyncTest : public ::testing::TestWithParam<sync_policy> {
void run(cv::GProtoInputArgs&& ins, cv::GProtoOutputArgs&& outs,
const ts_vec& frame_times) {
auto video_in_n = frame_times.size();
GAPI_Assert(video_in_n <= ins.m_args.size());
// Assume that all remaining inputs are const
auto const_in_n = ins.m_args.size() - video_in_n;
auto out_n = outs.m_args.size();
auto policy = GetParam();
TimestampGenerationParams ts_params(frame_times, policy);
MultiFrameSource source(ts_params);
GRunArgs gins;
for (std::size_t i = 0; i < video_in_n; i++) {
gins += cv::gin(source.getSource(i));
}
auto desc = source.desc();
cv::Mat const_mat = cv::Mat::eye(desc.size.height,
desc.size.width,
CV_MAKE_TYPE(desc.depth, desc.chan));
for (std::size_t i = 0; i < const_in_n; i++) {
gins += cv::gin(const_mat);
}
ts_vec out_timestamps(out_n);
cv::GRunArgsP gouts{};
for (auto& t : out_timestamps) {
gouts += cv::gout(t);
}
auto pipe = cv::GComputation(std::move(ins), std::move(outs))
.compileStreaming(cv::compile_args(policy));
pipe.setSource(std::move(gins));
pipe.start();
std::size_t frames = 0u;
TimestampChecker checker(ts_params);
while(pipe.pull(std::move(gouts))) {
checker.checkNext(out_timestamps);
frames++;
}
EXPECT_EQ(checker.nFrames(), frames);
}
};
} // anonymous namespace
TEST_P(TimestampSyncTest, Basic)
{
cv::GMat in1, in2;
auto out = cv::gapi::add(in1, in2);
auto ts = cv::gapi::streaming::timestamp(out);
run(cv::GIn(in1, in2), cv::GOut(ts), {1,2});
}
TEST_P(TimestampSyncTest, ThreeInputs)
{
cv::GMat in1, in2, in3;
auto tmp = cv::gapi::add(in1, in2);
auto out = cv::gapi::add(tmp, in3);
auto ts = cv::gapi::streaming::timestamp(out);
run(cv::GIn(in1, in2, in3), cv::GOut(ts), {2,4,3});
}
TEST_P(TimestampSyncTest, TwoOutputs)
{
cv::GMat in1, in2, in3;
auto out1 = cv::gapi::add(in1, in3);
auto out2 = cv::gapi::add(in2, in3);
auto ts1 = cv::gapi::streaming::timestamp(out1);
auto ts2 = cv::gapi::streaming::timestamp(out2);
run(cv::GIn(in1, in2, in3), cv::GOut(ts1, ts2), {1,4,2});
}
TEST_P(TimestampSyncTest, ConstInput)
{
cv::GMat in1, in2, in3;
auto out1 = cv::gapi::add(in1, in3);
auto out2 = cv::gapi::add(in2, in3);
auto ts1 = cv::gapi::streaming::timestamp(out1);
auto ts2 = cv::gapi::streaming::timestamp(out2);
run(cv::GIn(in1, in2, in3), cv::GOut(ts1, ts2), {1,2});
}
TEST_P(TimestampSyncTest, ChangeSource)
{
cv::GMat in1, in2, in3;
auto out1 = cv::gapi::add(in1, in3);
auto out2 = cv::gapi::add(in2, in3);
auto ts1 = cv::gapi::streaming::timestamp(out1);
auto ts2 = cv::gapi::streaming::timestamp(out2);
run(cv::GIn(in1, in2, in3), cv::GOut(ts1, ts2), {1,2});
run(cv::GIn(in1, in2, in3), cv::GOut(ts1, ts2), {1,2});
}
INSTANTIATE_TEST_CASE_P(InputSynchronization, TimestampSyncTest,
Values(sync_policy::dont_sync,
sync_policy::drop));
} // namespace opencv_test
@@ -7,6 +7,8 @@
#include "../test_precomp.hpp"
#include "../common/gapi_tests_common.hpp"
#include <thread> // sleep_for (Delay)
#include <opencv2/gapi/cpu/core.hpp>
@@ -21,6 +23,7 @@
#include <opencv2/gapi/streaming/cap.hpp>
#include <opencv2/gapi/streaming/desync.hpp>
#include <opencv2/gapi/streaming/format.hpp>
namespace opencv_test
{
@@ -113,6 +116,111 @@ GAPI_OCV_KERNEL(OCVDelay, Delay) {
}
};
class TestMediaBGR final: public cv::MediaFrame::IAdapter {
cv::Mat m_mat;
using Cb = cv::MediaFrame::View::Callback;
Cb m_cb;
public:
explicit TestMediaBGR(cv::Mat m, Cb cb = [](){})
: m_mat(m), m_cb(cb) {
}
cv::GFrameDesc meta() const override {
return cv::GFrameDesc{cv::MediaFormat::BGR, cv::Size(m_mat.cols, m_mat.rows)};
}
cv::MediaFrame::View access(cv::MediaFrame::Access) override {
cv::MediaFrame::View::Ptrs pp = { m_mat.ptr(), nullptr, nullptr, nullptr };
cv::MediaFrame::View::Strides ss = { m_mat.step, 0u, 0u, 0u };
return cv::MediaFrame::View(std::move(pp), std::move(ss), Cb{m_cb});
}
};
class TestMediaNV12 final: public cv::MediaFrame::IAdapter {
cv::Mat m_y;
cv::Mat m_uv;
public:
TestMediaNV12(cv::Mat y, cv::Mat uv) : m_y(y), m_uv(uv) {
}
cv::GFrameDesc meta() const override {
return cv::GFrameDesc{cv::MediaFormat::NV12, m_y.size()};
}
cv::MediaFrame::View access(cv::MediaFrame::Access) override {
cv::MediaFrame::View::Ptrs pp = {
m_y.ptr(), m_uv.ptr(), nullptr, nullptr
};
cv::MediaFrame::View::Strides ss = {
m_y.step, m_uv.step, 0u, 0u
};
return cv::MediaFrame::View(std::move(pp), std::move(ss));
}
};
class BGRSource : public cv::gapi::wip::GCaptureSource {
public:
explicit BGRSource(const std::string& pipeline)
: cv::gapi::wip::GCaptureSource(pipeline) {
}
bool pull(cv::gapi::wip::Data& data) {
if (cv::gapi::wip::GCaptureSource::pull(data)) {
data = cv::MediaFrame::Create<TestMediaBGR>(cv::util::get<cv::Mat>(data));
return true;
}
return false;
}
GMetaArg descr_of() const override {
return cv::GMetaArg{cv::GFrameDesc{cv::MediaFormat::BGR,
cv::util::get<cv::GMatDesc>(
cv::gapi::wip::GCaptureSource::descr_of()).size}};
}
};
void cvtBGR2NV12(const cv::Mat& bgr, cv::Mat& y, cv::Mat& uv) {
cv::Size frame_sz = bgr.size();
cv::Size half_sz = frame_sz / 2;
cv::Mat yuv;
cv::cvtColor(bgr, yuv, cv::COLOR_BGR2YUV_I420);
// Copy Y plane
yuv.rowRange(0, frame_sz.height).copyTo(y);
// Merge sampled U and V planes
std::vector<int> dims = {half_sz.height, half_sz.width};
auto start = frame_sz.height;
auto range_h = half_sz.height/2;
std::vector<cv::Mat> uv_planes = {
yuv.rowRange(start, start + range_h) .reshape(0, dims),
yuv.rowRange(start + range_h, start + range_h*2).reshape(0, dims)
};
cv::merge(uv_planes, uv);
}
class NV12Source : public cv::gapi::wip::GCaptureSource {
public:
explicit NV12Source(const std::string& pipeline)
: cv::gapi::wip::GCaptureSource(pipeline) {
}
bool pull(cv::gapi::wip::Data& data) {
if (cv::gapi::wip::GCaptureSource::pull(data)) {
cv::Mat bgr = cv::util::get<cv::Mat>(data);
cv::Mat y, uv;
cvtBGR2NV12(bgr, y, uv);
data = cv::MediaFrame::Create<TestMediaNV12>(y, uv);
return true;
}
return false;
}
GMetaArg descr_of() const override {
return cv::GMetaArg{cv::GFrameDesc{cv::MediaFormat::NV12,
cv::util::get<cv::GMatDesc>(
cv::gapi::wip::GCaptureSource::descr_of()).size}};
}
};
} // anonymous namespace
TEST_P(GAPI_Streaming, SmokeTest_ConstInput_GMat)
@@ -996,25 +1104,35 @@ struct GAPI_Streaming_Unit: public ::testing::Test {
// FIXME: (GAPI_Streaming_Types, XChangeOpaque) test is missing here!
// FIXME: (GAPI_Streaming_Types, OutputOpaque) test is missing here!
TEST_F(GAPI_Streaming_Unit, TestTwoVideoSourcesFail)
TEST(GAPI_Streaming, TestTwoVideosDifferentLength)
{
auto c_desc = cv::GMatDesc{CV_8U,3,{768,576}};
auto m_desc = cv::descr_of(m);
auto path = findDataFile("cv/video/768x576.avi");
initTestDataPath();
auto desc = cv::GMatDesc{CV_8U,3,{768,576}};
auto path1 = findDataFile("cv/video/768x576.avi");
auto path2 = findDataFile("highgui/video/big_buck_bunny.avi");
cv::GMat in1, in2;
auto out = in1 + cv::gapi::resize(in2, desc.size);
cv::GComputation cc(cv::GIn(in1, in2), cv::GOut(out));
auto sc = cc.compileStreaming();
try {
sc = cc.compileStreaming(c_desc, m_desc);
// FIXME: it should be EXPECT_NO_THROW()
sc.setSource(cv::gin(gapi::wip::make_src<cv::gapi::wip::GCaptureSource>(path), m));
sc = cc.compileStreaming(m_desc, c_desc);
// FIXME: it should be EXPECT_NO_THROW()
sc.setSource(cv::gin(m, gapi::wip::make_src<cv::gapi::wip::GCaptureSource>(path)));
sc.setSource(cv::gin(gapi::wip::make_src<cv::gapi::wip::GCaptureSource>(path1),
gapi::wip::make_src<cv::gapi::wip::GCaptureSource>(path2)));
} catch(...) {
throw SkipTestException("Video file can not be opened");
throw SkipTestException("Video file can not be found");
}
sc.start();
cv::Mat out_mat;
std::size_t frames = 0u;
while(sc.pull(cv::gout(out_mat))) {
frames++;
}
sc = cc.compileStreaming(c_desc, c_desc);
auto c_ptr = gapi::wip::make_src<cv::gapi::wip::GCaptureSource>(path);
EXPECT_ANY_THROW(sc.setSource(cv::gin(c_ptr, c_ptr)));
// big_buck_bunny.avi has 125 frames, 768x576.avi - 100 frames,
// expect framework to stop after 100 frames
EXPECT_EQ(100u, frames);
}
TEST_F(GAPI_Streaming_Unit, TestStartWithoutnSetSource)
@@ -1176,7 +1294,7 @@ TEST(Streaming, Python_Pull_Overload)
cv::Mat in_mat(sz, CV_8UC3);
cv::randu(in_mat, cv::Scalar::all(0), cv::Scalar(255));
auto ccomp = c.compileStreaming(cv::descr_of(in_mat));
auto ccomp = c.compileStreaming();
EXPECT_TRUE(ccomp);
EXPECT_FALSE(ccomp.running());
@@ -1247,7 +1365,6 @@ TEST(GAPI_Streaming_Desync, SmokeTest_Streaming)
}
EXPECT_EQ(100u, out1_hits); // out1 must be available for all frames
EXPECT_LE(out2_hits, out1_hits); // out2 must appear less times than out1
std::cout << "Got " << out1_hits << " out1's and " << out2_hits << " out2's" << std::endl;
}
TEST(GAPI_Streaming_Desync, SmokeTest_Streaming_TwoParts)
@@ -1540,37 +1657,20 @@ TEST(GAPI_Streaming_Desync, StartStop_Stress) {
}
}
GAPI_FLUID_KERNEL(FluidCopy, cv::gapi::core::GCopy, false) {
static const int Window = 1;
static void run(const cv::gapi::fluid::View &in,
cv::gapi::fluid::Buffer &out) {
const uint8_t *in_ptr = in.InLineB(0);
uint8_t *out_ptr = out.OutLineB(0);
const auto in_type = CV_MAKETYPE(in.meta().depth, in.meta().chan);
const auto out_type = CV_MAKETYPE(out.meta().depth, out.meta().chan);
GAPI_Assert(in_type == out_type);
std::copy_n(in_ptr, in.length()*CV_ELEM_SIZE(in_type), out_ptr);
}
};
TEST(GAPI_Streaming_Desync, DesyncObjectConsumedByTwoIslandsViaSeparateDesync) {
// See comment in the implementation of cv::gapi::streaming::desync (.cpp)
cv::GMat in;
cv::GMat tmp = cv::gapi::boxFilter(in, -1, cv::Size(3,3));
cv::GMat tmp1 = cv::gapi::streaming::desync(tmp);
cv::GMat out1 = cv::gapi::copy(tmp1); // ran via Fluid backend
cv::GMat out1 = cv::gapi::copy(tmp1); // ran via Streaming backend
cv::GMat tmp2 = cv::gapi::streaming::desync(tmp);
cv::GMat out2 = tmp2 * 0.5; // ran via OCV backend
auto c = cv::GComputation(cv::GIn(in), cv::GOut(out1, out2));
auto p = cv::gapi::kernels<FluidCopy>();
EXPECT_NO_THROW(c.compileStreaming(cv::compile_args(p)));
EXPECT_NO_THROW(c.compileStreaming());
}
TEST(GAPI_Streaming_Desync, DesyncObjectConsumedByTwoIslandsViaSameDesync) {
@@ -1579,13 +1679,440 @@ TEST(GAPI_Streaming_Desync, DesyncObjectConsumedByTwoIslandsViaSameDesync) {
cv::GMat tmp = cv::gapi::boxFilter(in, -1, cv::Size(3,3));
cv::GMat tmp1 = cv::gapi::streaming::desync(tmp);
cv::GMat out1 = cv::gapi::copy(tmp1); // ran via Fluid backend
cv::GMat out1 = cv::gapi::copy(tmp1); // ran via Streaming backend
cv::GMat out2 = out1 - 0.5*tmp1; // ran via OCV backend
auto c = cv::GComputation(cv::GIn(in), cv::GOut(out1, out2));
auto p = cv::gapi::kernels<FluidCopy>();
EXPECT_NO_THROW(c.compileStreaming(cv::compile_args(p)));
EXPECT_NO_THROW(c.compileStreaming());
}
TEST(GAPI_Streaming, CopyFrame)
{
initTestDataPath();
std::string filepath = findDataFile("cv/video/768x576.avi");
cv::GFrame in;
auto out = cv::gapi::copy(in);
cv::GComputation comp(cv::GIn(in), cv::GOut(out));
auto cc = comp.compileStreaming();
try {
cc.setSource<BGRSource>(filepath);
} catch(...) {
throw SkipTestException("Video file can not be opened");
}
cv::VideoCapture cap;
cap.open(filepath);
if (!cap.isOpened())
throw SkipTestException("Video file can not be opened");
cv::MediaFrame frame;
cv::Mat ocv_mat;
std::size_t num_frames = 0u;
std::size_t max_frames = 10u;
cc.start();
while (cc.pull(cv::gout(frame)) && num_frames < max_frames)
{
auto view = frame.access(cv::MediaFrame::Access::R);
cv::Mat gapi_mat(frame.desc().size, CV_8UC3, view.ptr[0]);
num_frames++;
cap >> ocv_mat;
EXPECT_EQ(0, cvtest::norm(ocv_mat, gapi_mat, NORM_INF));
}
}
TEST(GAPI_Streaming, CopyMat)
{
initTestDataPath();
std::string filepath = findDataFile("cv/video/768x576.avi");
cv::GMat in;
auto out = cv::gapi::copy(in);
cv::GComputation comp(cv::GIn(in), cv::GOut(out));
auto cc = comp.compileStreaming();
try {
cc.setSource<cv::gapi::wip::GCaptureSource>(filepath);
} catch(...) {
throw SkipTestException("Video file can not be opened");
}
cv::VideoCapture cap;
cap.open(filepath);
if (!cap.isOpened())
throw SkipTestException("Video file can not be opened");
cv::Mat out_mat;
cv::Mat ocv_mat;
std::size_t num_frames = 0u;
std::size_t max_frames = 10u;
cc.start();
while (cc.pull(cv::gout(out_mat)) && num_frames < max_frames)
{
num_frames++;
cap >> ocv_mat;
EXPECT_EQ(0, cvtest::norm(ocv_mat, out_mat, NORM_INF));
}
}
TEST(GAPI_Streaming, Reshape)
{
initTestDataPath();
std::string filepath = findDataFile("cv/video/768x576.avi");
cv::GFrame in;
auto out = cv::gapi::copy(in);
cv::GComputation comp(cv::GIn(in), cv::GOut(out));
auto cc = comp.compileStreaming();
try {
cc.setSource<BGRSource>(filepath);
} catch(...) {
throw SkipTestException("Video file can not be opened");
}
cv::VideoCapture cap;
cap.open(filepath);
if (!cap.isOpened())
throw SkipTestException("Video file can not be opened");
cv::MediaFrame frame;
cv::Mat ocv_mat;
std::size_t num_frames = 0u;
std::size_t max_frames = 10u;
cc.start();
while (cc.pull(cv::gout(frame)) && num_frames < max_frames)
{
auto view = frame.access(cv::MediaFrame::Access::R);
cv::Mat gapi_mat(frame.desc().size, CV_8UC3, view.ptr[0]);
num_frames++;
cap >> ocv_mat;
EXPECT_EQ(0, cvtest::norm(ocv_mat, gapi_mat, NORM_INF));
}
// Reshape the graph meta
filepath = findDataFile("cv/video/1920x1080.avi");
cc.stop();
try {
cc.setSource<BGRSource>(filepath);
} catch(...) {
throw SkipTestException("Video file can not be opened");
}
cap.open(filepath);
if (!cap.isOpened())
throw SkipTestException("Video file can not be opened");
cv::MediaFrame frame2;
cv::Mat ocv_mat2;
num_frames = 0u;
cc.start();
while (cc.pull(cv::gout(frame2)) && num_frames < max_frames)
{
auto view = frame2.access(cv::MediaFrame::Access::R);
cv::Mat gapi_mat(frame2.desc().size, CV_8UC3, view.ptr[0]);
num_frames++;
cap >> ocv_mat2;
EXPECT_EQ(0, cvtest::norm(ocv_mat2, gapi_mat, NORM_INF));
}
}
namespace {
enum class TestSourceType {
BGR,
NV12
};
std::ostream& operator<<(std::ostream& os, TestSourceType a) {
os << "Source:";
switch (a) {
case TestSourceType::BGR: return os << "BGR";
case TestSourceType::NV12: return os << "NV12";
default: CV_Assert(false && "unknown TestSourceType");
}
}
cv::gapi::wip::IStreamSource::Ptr createTestSource(TestSourceType sourceType,
const std::string& pipeline) {
assert(sourceType == TestSourceType::BGR || sourceType == TestSourceType::NV12);
cv::gapi::wip::IStreamSource::Ptr ptr { };
switch (sourceType) {
case TestSourceType::BGR: {
try {
ptr = cv::gapi::wip::make_src<BGRSource>(pipeline);
}
catch(...) {
throw SkipTestException(std::string("BGRSource for '") + pipeline +
"' couldn't be created!");
}
break;
}
case TestSourceType::NV12: {
try {
ptr = cv::gapi::wip::make_src<NV12Source>(pipeline);
}
catch(...) {
throw SkipTestException(std::string("NV12Source for '") + pipeline +
"' couldn't be created!");
}
break;
}
default: {
throw SkipTestException("Incorrect type of source! "
"Something went wrong in the test!");
}
}
return ptr;
}
enum class TestAccessType {
BGR,
Y,
UV
};
std::ostream& operator<<(std::ostream& os, TestAccessType a) {
os << "Accessor:";
switch (a) {
case TestAccessType::BGR: return os << "BGR";
case TestAccessType::Y: return os << "Y";
case TestAccessType::UV: return os << "UV";
default: CV_Assert(false && "unknown TestAccessType");
}
}
using GapiFunction = std::function<cv::GMat(const cv::GFrame&)>;
static std::map<TestAccessType, GapiFunction> gapi_functions = {
{ TestAccessType::BGR, cv::gapi::streaming::BGR },
{ TestAccessType::Y, cv::gapi::streaming::Y },
{ TestAccessType::UV, cv::gapi::streaming::UV }
};
using RefFunction = std::function<cv::Mat(const cv::Mat&)>;
static std::map<std::pair<TestSourceType,TestAccessType>, RefFunction> ref_functions = {
{ std::make_pair(TestSourceType::BGR, TestAccessType::BGR),
[](const cv::Mat& bgr) { return bgr; } },
{ std::make_pair(TestSourceType::BGR, TestAccessType::Y),
[](const cv::Mat& bgr) {
cv::Mat y, uv;
cvtBGR2NV12(bgr, y, uv);
return y;
} },
{ std::make_pair(TestSourceType::BGR, TestAccessType::UV),
[](const cv::Mat& bgr) {
cv::Mat y, uv;
cvtBGR2NV12(bgr, y, uv);
return uv;
} },
{ std::make_pair(TestSourceType::NV12, TestAccessType::BGR),
[](const cv::Mat& bgr) {
cv::Mat y, uv, out_bgr;
cvtBGR2NV12(bgr, y, uv);
cv::cvtColorTwoPlane(y, uv, out_bgr,
cv::COLOR_YUV2BGR_NV12);
return out_bgr;
} },
{ std::make_pair(TestSourceType::NV12, TestAccessType::Y),
[](const cv::Mat& bgr) {
cv::Mat y, uv;
cvtBGR2NV12(bgr, y, uv);
return y;
} },
{ std::make_pair(TestSourceType::NV12, TestAccessType::UV),
[](const cv::Mat& bgr) {
cv::Mat y, uv;
cvtBGR2NV12(bgr, y, uv);
return uv;
} },
};
} // anonymous namespace
struct GAPI_Accessors_In_Streaming : public TestWithParam<
std::tuple<std::string,TestSourceType,TestAccessType>>
{ };
TEST_P(GAPI_Accessors_In_Streaming, AccuracyTest)
{
std::string filepath{};
TestSourceType sourceType = TestSourceType::BGR;
TestAccessType accessType = TestAccessType::BGR;
std::tie(filepath, sourceType, accessType) = GetParam();
auto accessor = gapi_functions[accessType];
auto fromBGR = ref_functions[std::make_pair(sourceType, accessType)];
initTestDataPathOrSkip();
const std::string& absFilePath = findDataFile(filepath, false);
cv::GFrame in;
cv::GMat out = accessor(in);
cv::GComputation comp(cv::GIn(in), cv::GOut(out));
auto cc = comp.compileStreaming();
auto src = createTestSource(sourceType, absFilePath);
cc.setSource(src);
cv::VideoCapture cap;
cap.open(absFilePath);
if (!cap.isOpened())
throw SkipTestException("Video file can not be opened");
cv::Mat cap_mat, ocv_mat, gapi_mat;
std::size_t num_frames = 0u;
std::size_t max_frames = 10u;
cc.start();
while (num_frames < max_frames && cc.pull(cv::gout(gapi_mat)))
{
num_frames++;
cap >> cap_mat;
ocv_mat = fromBGR(cap_mat);
EXPECT_EQ(0, cvtest::norm(ocv_mat, gapi_mat, NORM_INF));
}
cc.stop();
}
INSTANTIATE_TEST_CASE_P(TestAccessor, GAPI_Accessors_In_Streaming,
Combine(Values("cv/video/768x576.avi"),
Values(TestSourceType::BGR, TestSourceType::NV12),
Values(TestAccessType::BGR, TestAccessType::Y, TestAccessType::UV)
));
struct GAPI_Accessors_Meta_In_Streaming : public TestWithParam<
std::tuple<std::string,TestSourceType,TestAccessType>>
{ };
TEST_P(GAPI_Accessors_Meta_In_Streaming, AccuracyTest)
{
std::string filepath{};
TestSourceType sourceType = TestSourceType::BGR;
TestAccessType accessType = TestAccessType::BGR;
std::tie(filepath, sourceType, accessType) = GetParam();
auto accessor = gapi_functions[accessType];
auto fromBGR = ref_functions[std::make_pair(sourceType, accessType)];
initTestDataPathOrSkip();
const std::string& absFilePath = findDataFile(filepath, false);
cv::GFrame in;
cv::GMat gmat = accessor(in);
cv::GMat resized = cv::gapi::resize(gmat, cv::Size(1920, 1080));
cv::GOpaque<int64_t> outId = cv::gapi::streaming::seq_id(resized);
cv::GOpaque<int64_t> outTs = cv::gapi::streaming::timestamp(resized);
cv::GComputation comp(cv::GIn(in), cv::GOut(resized, outId, outTs));
auto cc = comp.compileStreaming();
auto src = createTestSource(sourceType, absFilePath);
cc.setSource(src);
cv::VideoCapture cap;
cap.open(absFilePath);
if (!cap.isOpened())
throw SkipTestException("Video file can not be opened");
cv::Mat cap_mat, req_mat, ocv_mat, gapi_mat;
int64_t seq_id = 0, timestamp = 0;
std::set<int64_t> all_seq_ids;
std::vector<int64_t> all_timestamps;
std::size_t num_frames = 0u;
std::size_t max_frames = 10u;
cc.start();
while (num_frames < max_frames && cc.pull(cv::gout(gapi_mat, seq_id, timestamp)))
{
num_frames++;
cap >> cap_mat;
req_mat = fromBGR(cap_mat);
cv::resize(req_mat, ocv_mat, cv::Size(1920, 1080));
EXPECT_EQ(0, cvtest::norm(ocv_mat, gapi_mat, NORM_INF));
all_seq_ids.insert(seq_id);
all_timestamps.push_back(timestamp);
}
cc.stop();
EXPECT_EQ(all_seq_ids.begin(), all_seq_ids.find(0L));
auto last_elem_it = --all_seq_ids.end();
EXPECT_EQ(last_elem_it, all_seq_ids.find(int64_t(max_frames - 1L)));
EXPECT_EQ(max_frames, all_seq_ids.size());
EXPECT_EQ(max_frames, all_timestamps.size());
EXPECT_TRUE(std::is_sorted(all_timestamps.begin(), all_timestamps.end()));
}
INSTANTIATE_TEST_CASE_P(AccessorMeta, GAPI_Accessors_Meta_In_Streaming,
Combine(Values("cv/video/768x576.avi"),
Values(TestSourceType::BGR, TestSourceType::NV12),
Values(TestAccessType::BGR, TestAccessType::Y, TestAccessType::UV)
));
TEST(GAPI_Streaming, TestPythonAPI)
{
cv::Size sz(200, 200);
cv::Mat in_mat(sz, CV_8UC3);
cv::randu(in_mat, cv::Scalar::all(0), cv::Scalar(255));
const auto crop_rc = cv::Rect(13, 75, 100, 100);
// OpenCV reference image
cv::Mat ocv_mat;
{
ocv_mat = in_mat(crop_rc);
}
cv::GMat in;
auto roi = cv::gapi::crop(in, crop_rc);
cv::GComputation comp(cv::GIn(in), cv::GOut(roi));
// NB: Used by python bridge
auto cc = comp.compileStreaming(cv::detail::ExtractMetaCallback{[&](const cv::GTypesInfo& info)
{
GAPI_Assert(info.size() == 1u);
GAPI_Assert(info[0].shape == cv::GShape::GMAT);
return cv::GMetaArgs{cv::GMetaArg{cv::descr_of(in_mat)}};
}});
// NB: Used by python bridge
cc.setSource(cv::detail::ExtractArgsCallback{[&](const cv::GTypesInfo& info)
{
GAPI_Assert(info.size() == 1u);
GAPI_Assert(info[0].shape == cv::GShape::GMAT);
return cv::GRunArgs{in_mat};
}});
cc.start();
bool is_over = false;
cv::GRunArgs out_args;
// NB: Used by python bridge
std::tie(is_over, out_args) = cc.pull();
ASSERT_EQ(1u, out_args.size());
ASSERT_TRUE(cv::util::holds_alternative<cv::Mat>(out_args[0]));
EXPECT_EQ(0, cvtest::norm(ocv_mat, cv::util::get<cv::Mat>(out_args[0]), NORM_INF));
EXPECT_TRUE(is_over);
cc.stop();
}
} // namespace opencv_test
+1
View File
@@ -11,6 +11,7 @@
#define __OPENCV_GAPI_TEST_PRECOMP_HPP__
#include <cstdint>
#include <thread>
#include <vector>
#include <opencv2/ts.hpp>