feat: 切换后端至PaddleOCR-NCNN,切换工程为CMake
1.项目后端整体迁移至PaddleOCR-NCNN算法,已通过基本的兼容性测试 2.工程改为使用CMake组织,后续为了更好地兼容第三方库,不再提供QMake工程 3.重整权利声明文件,重整代码工程,确保最小化侵权风险 Log: 切换后端至PaddleOCR-NCNN,切换工程为CMake Change-Id: I4d5d2c5d37505a4a24b389b1a4c5d12f17bfa38c
This commit is contained in:
86
3rdparty/opencv-4.5.4/modules/gapi/test/internal/gapi_int_backend_tests.cpp
vendored
Normal file
86
3rdparty/opencv-4.5.4/modules/gapi/test/internal/gapi_int_backend_tests.cpp
vendored
Normal file
@ -0,0 +1,86 @@
|
||||
// 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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#include "../test_precomp.hpp"
|
||||
#include "../gapi_mock_kernels.hpp"
|
||||
|
||||
#include "compiler/gmodel.hpp"
|
||||
#include "compiler/gcompiler.hpp"
|
||||
|
||||
namespace opencv_test {
|
||||
|
||||
namespace {
|
||||
|
||||
struct MockMeta
|
||||
{
|
||||
static const char* name() { return "MockMeta"; }
|
||||
};
|
||||
|
||||
class GMockBackendImpl final: public cv::gapi::GBackend::Priv
|
||||
{
|
||||
virtual void unpackKernel(ade::Graph &,
|
||||
const ade::NodeHandle &,
|
||||
const cv::GKernelImpl &) override
|
||||
{
|
||||
// Do nothing here
|
||||
}
|
||||
|
||||
virtual EPtr compile(const ade::Graph &,
|
||||
const cv::GCompileArgs &,
|
||||
const std::vector<ade::NodeHandle> &) const override
|
||||
{
|
||||
// Do nothing here as well
|
||||
return {};
|
||||
}
|
||||
|
||||
virtual void addBackendPasses(ade::ExecutionEngineSetupContext &ectx) override
|
||||
{
|
||||
ectx.addPass("transform", "set_mock_meta", [](ade::passes::PassContext &ctx) {
|
||||
ade::TypedGraph<MockMeta> me(ctx.graph);
|
||||
for (const auto &nh : me.nodes())
|
||||
{
|
||||
me.metadata(nh).set(MockMeta{});
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
static cv::gapi::GBackend mock_backend(std::make_shared<GMockBackendImpl>());
|
||||
|
||||
GAPI_OCV_KERNEL(MockFoo, I::Foo)
|
||||
{
|
||||
static void run(const cv::Mat &, cv::Mat &) { /*Do nothing*/ }
|
||||
static cv::gapi::GBackend backend() { return mock_backend; } // FIXME: Must be removed
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
TEST(GBackend, CustomPassesExecuted)
|
||||
{
|
||||
cv::GMat in;
|
||||
cv::GMat out = I::Foo::on(in);
|
||||
cv::GComputation c(in, out);
|
||||
|
||||
// Prepare compilation parameters manually
|
||||
const auto in_meta = cv::GMetaArg(cv::GMatDesc{CV_8U,1,cv::Size(32,32)});
|
||||
const auto pkg = cv::gapi::kernels<MockFoo>();
|
||||
|
||||
// Directly instantiate G-API graph compiler and run partial compilation
|
||||
cv::gimpl::GCompiler compiler(c, {in_meta}, cv::compile_args(pkg));
|
||||
cv::gimpl::GCompiler::GPtr graph = compiler.generateGraph();
|
||||
compiler.runPasses(*graph);
|
||||
|
||||
// Inspect the graph and verify the metadata written by Mock backend
|
||||
ade::TypedGraph<MockMeta> me(*graph);
|
||||
EXPECT_LT(0u, static_cast<std::size_t>(me.nodes().size()));
|
||||
for (const auto &nh : me.nodes())
|
||||
{
|
||||
EXPECT_TRUE(me.metadata(nh).contains<MockMeta>());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace opencv_test
|
331
3rdparty/opencv-4.5.4/modules/gapi/test/internal/gapi_int_dynamic_graph.cpp
vendored
Normal file
331
3rdparty/opencv-4.5.4/modules/gapi/test/internal/gapi_int_dynamic_graph.cpp
vendored
Normal file
@ -0,0 +1,331 @@
|
||||
// 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
|
||||
|
||||
#include "../test_precomp.hpp"
|
||||
|
||||
#include <opencv2/gapi/cpu/core.hpp>
|
||||
#include <opencv2/gapi/cpu/imgproc.hpp>
|
||||
|
||||
namespace opencv_test
|
||||
{
|
||||
typedef ::testing::Types<cv::GMat, cv::GMatP, cv::GFrame,
|
||||
cv::GScalar, cv::GOpaque<int>,
|
||||
cv::GArray<int>> VectorProtoTypes;
|
||||
|
||||
template<typename T> struct DynamicGraphProtoArgs: public ::testing::Test { using Type = T; };
|
||||
|
||||
TYPED_TEST_CASE(DynamicGraphProtoArgs, VectorProtoTypes);
|
||||
|
||||
TYPED_TEST(DynamicGraphProtoArgs, AddProtoInputArgsSmoke)
|
||||
{
|
||||
using T = typename TestFixture::Type;
|
||||
auto ins = GIn();
|
||||
T in;
|
||||
EXPECT_NO_THROW(ins += GIn(in));
|
||||
}
|
||||
|
||||
TYPED_TEST(DynamicGraphProtoArgs, AddProtoInputArgs)
|
||||
{
|
||||
using T = typename TestFixture::Type;
|
||||
T in1, in2;
|
||||
|
||||
auto ins1 = GIn();
|
||||
ins1 += GIn(in1);
|
||||
ins1 += GIn(in2);
|
||||
|
||||
auto ins2 = GIn(in1, in2);
|
||||
|
||||
EXPECT_EQ(ins1.m_args.size(), ins2.m_args.size());
|
||||
}
|
||||
|
||||
TYPED_TEST(DynamicGraphProtoArgs, AddProtoOutputArgsSmoke)
|
||||
{
|
||||
using T = typename TestFixture::Type;
|
||||
auto outs = GOut();
|
||||
T out;
|
||||
EXPECT_NO_THROW(outs += GOut(out));
|
||||
}
|
||||
|
||||
TYPED_TEST(DynamicGraphProtoArgs, AddProtoOutputArgs)
|
||||
{
|
||||
using T = typename TestFixture::Type;
|
||||
T out1, out2;
|
||||
|
||||
auto outs1 = GOut();
|
||||
outs1 += GOut(out1);
|
||||
outs1 += GOut(out2);
|
||||
|
||||
auto outs2 = GOut(out1, out2);
|
||||
|
||||
EXPECT_EQ(outs1.m_args.size(), outs2.m_args.size());
|
||||
}
|
||||
|
||||
typedef ::testing::Types<cv::Mat,
|
||||
#if !defined(GAPI_STANDALONE)
|
||||
cv::UMat,
|
||||
#endif // !defined(GAPI_STANDALONE)
|
||||
cv::Scalar,
|
||||
cv::detail::VectorRef,
|
||||
cv::detail::OpaqueRef> VectorRunTypes;
|
||||
|
||||
template<typename T> struct DynamicGraphRunArgs: public ::testing::Test { using Type = T; };
|
||||
|
||||
TYPED_TEST_CASE(DynamicGraphRunArgs, VectorRunTypes);
|
||||
|
||||
TYPED_TEST(DynamicGraphRunArgs, AddRunArgsSmoke)
|
||||
{
|
||||
auto in_vector = cv::gin();
|
||||
|
||||
using T = typename TestFixture::Type;
|
||||
T in;
|
||||
EXPECT_NO_THROW(in_vector += cv::gin(in));
|
||||
}
|
||||
|
||||
TYPED_TEST(DynamicGraphRunArgs, AddRunArgs)
|
||||
{
|
||||
using T = typename TestFixture::Type;
|
||||
T in1, in2;
|
||||
|
||||
auto in_vector1 = cv::gin();
|
||||
in_vector1 += cv::gin(in1);
|
||||
in_vector1 += cv::gin(in2);
|
||||
|
||||
auto in_vector2 = cv::gin(in1, in2);
|
||||
|
||||
EXPECT_EQ(in_vector1.size(), in_vector2.size());
|
||||
}
|
||||
|
||||
TYPED_TEST(DynamicGraphRunArgs, AddRunArgsPSmoke)
|
||||
{
|
||||
auto out_vector = cv::gout();
|
||||
|
||||
using T = typename TestFixture::Type;
|
||||
T out;
|
||||
EXPECT_NO_THROW(out_vector += cv::gout(out));
|
||||
}
|
||||
|
||||
TYPED_TEST(DynamicGraphRunArgs, AddRunArgsP)
|
||||
{
|
||||
using T = typename TestFixture::Type;
|
||||
T out1, out2;
|
||||
|
||||
auto out_vector1 = cv::gout();
|
||||
out_vector1 += cv::gout(out1);
|
||||
out_vector1 += cv::gout(out2);
|
||||
|
||||
auto out_vector2 = cv::gout(out1, out2);
|
||||
|
||||
EXPECT_EQ(out_vector1.size(), out_vector2.size());
|
||||
}
|
||||
|
||||
TEST(DynamicGraph, ProtoInputArgsExecute)
|
||||
{
|
||||
cv::GComputation cc([]() {
|
||||
cv::GMat in1;
|
||||
auto ins = GIn(in1);
|
||||
|
||||
cv::GMat in2;
|
||||
ins += GIn(in2);
|
||||
|
||||
cv::GMat out = cv::gapi::copy(in1 + in2);
|
||||
|
||||
return cv::GComputation(std::move(ins), GOut(out));
|
||||
});
|
||||
|
||||
cv::Mat in_mat1 = cv::Mat::eye(32, 32, CV_8UC1);
|
||||
cv::Mat in_mat2 = cv::Mat::eye(32, 32, CV_8UC1);
|
||||
cv::Mat out_mat;
|
||||
|
||||
EXPECT_NO_THROW(cc.apply(cv::gin(in_mat1, in_mat2), cv::gout(out_mat)));
|
||||
}
|
||||
|
||||
TEST(DynamicGraph, ProtoOutputArgsExecute)
|
||||
{
|
||||
cv::GComputation cc([]() {
|
||||
cv::GMat in;
|
||||
cv::GMat out1 = cv::gapi::copy(in);
|
||||
auto outs = GOut(out1);
|
||||
|
||||
cv::GMat out2 = cv::gapi::copy(in);
|
||||
outs += GOut(out2);
|
||||
|
||||
return cv::GComputation(cv::GIn(in), std::move(outs));
|
||||
});
|
||||
|
||||
cv::Mat in_mat1 = cv::Mat::eye(32, 32, CV_8UC1);
|
||||
cv::Mat out_mat1;
|
||||
cv::Mat out_mat2;
|
||||
|
||||
EXPECT_NO_THROW(cc.apply(cv::gin(in_mat1), cv::gout(out_mat1, out_mat1)));
|
||||
}
|
||||
|
||||
TEST(DynamicGraph, ProtoOutputInputArgsExecute)
|
||||
{
|
||||
cv::GComputation cc([]() {
|
||||
cv::GMat in1;
|
||||
auto ins = GIn(in1);
|
||||
|
||||
cv::GMat in2;
|
||||
ins += GIn(in2);
|
||||
|
||||
cv::GMat out1 = cv::gapi::copy(in1 + in2);
|
||||
auto outs = GOut(out1);
|
||||
|
||||
cv::GMat out2 = cv::gapi::copy(in1 + in2);
|
||||
outs += GOut(out2);
|
||||
|
||||
return cv::GComputation(std::move(ins), std::move(outs));
|
||||
});
|
||||
|
||||
cv::Mat in_mat1 = cv::Mat::eye(32, 32, CV_8UC1);
|
||||
cv::Mat in_mat2 = cv::Mat::eye(32, 32, CV_8UC1);
|
||||
cv::Mat out_mat1, out_mat2;
|
||||
|
||||
EXPECT_NO_THROW(cc.apply(cv::gin(in_mat1, in_mat2), cv::gout(out_mat1, out_mat2)));
|
||||
}
|
||||
|
||||
TEST(DynamicGraph, ProtoArgsExecute)
|
||||
{
|
||||
cv::GComputation cc([]() {
|
||||
cv::GMat in1;
|
||||
auto ins = GIn(in1);
|
||||
|
||||
cv::GMat in2;
|
||||
ins += GIn(in2);
|
||||
|
||||
cv::GMat out1 = cv::gapi::copy(in1 + in2);
|
||||
auto outs = GOut(out1);
|
||||
|
||||
cv::GMat out2 = cv::gapi::copy(in1 + in2);
|
||||
outs += GOut(out2);
|
||||
|
||||
return cv::GComputation(std::move(ins), std::move(outs));
|
||||
});
|
||||
|
||||
cv::Mat in_mat1 = cv::Mat::eye(32, 32, CV_8UC1);
|
||||
cv::Mat in_mat2 = cv::Mat::eye(32, 32, CV_8UC1);
|
||||
cv::Mat out_mat1, out_mat2;
|
||||
|
||||
EXPECT_NO_THROW(cc.apply(cv::gin(in_mat1, in_mat2), cv::gout(out_mat1, out_mat2)));
|
||||
}
|
||||
|
||||
TEST(DynamicGraph, ProtoOutputInputArgsAccuracy)
|
||||
{
|
||||
cv::Size szOut(4, 4);
|
||||
cv::GComputation cc([&](){
|
||||
cv::GMat in1;
|
||||
auto ins = GIn(in1);
|
||||
|
||||
cv::GMat in2;
|
||||
ins += GIn(in2);
|
||||
|
||||
cv::GMat out1 = cv::gapi::resize(in1, szOut);
|
||||
auto outs = GOut(out1);
|
||||
|
||||
cv::GMat out2 = cv::gapi::resize(in2, szOut);
|
||||
outs += GOut(out2);
|
||||
|
||||
return cv::GComputation(std::move(ins), std::move(outs));
|
||||
});
|
||||
|
||||
// G-API test code
|
||||
cv::Mat in_mat1( 8, 8, CV_8UC3);
|
||||
cv::Mat in_mat2(16, 16, CV_8UC3);
|
||||
cv::randu(in_mat1, cv::Scalar::all(0), cv::Scalar::all(255));
|
||||
cv::randu(in_mat2, cv::Scalar::all(0), cv::Scalar::all(255));
|
||||
|
||||
auto in_vector = cv::gin();
|
||||
in_vector += cv::gin(in_mat1);
|
||||
in_vector += cv::gin(in_mat2);
|
||||
|
||||
cv::Mat out_mat1, out_mat2;
|
||||
auto out_vector = cv::gout();
|
||||
out_vector += cv::gout(out_mat1);
|
||||
out_vector += cv::gout(out_mat2);
|
||||
|
||||
cc.apply(std::move(in_vector), std::move(out_vector));
|
||||
|
||||
// OCV ref code
|
||||
cv::Mat cv_out_mat1, cv_out_mat2;
|
||||
cv::resize(in_mat1, cv_out_mat1, szOut);
|
||||
cv::resize(in_mat2, cv_out_mat2, szOut);
|
||||
|
||||
EXPECT_EQ(0, cvtest::norm(out_mat1, cv_out_mat1, NORM_INF));
|
||||
EXPECT_EQ(0, cvtest::norm(out_mat2, cv_out_mat2, NORM_INF));
|
||||
}
|
||||
|
||||
TEST(DynamicGraph, Streaming)
|
||||
{
|
||||
cv::GComputation cc([&](){
|
||||
cv::Size szOut(4, 4);
|
||||
|
||||
cv::GMat in1;
|
||||
auto ins = GIn(in1);
|
||||
|
||||
cv::GMat in2;
|
||||
ins += GIn(in2);
|
||||
|
||||
cv::GMat out1 = cv::gapi::resize(in1, szOut);
|
||||
auto outs = GOut(out1);
|
||||
|
||||
cv::GMat out2 = cv::gapi::resize(in2, szOut);
|
||||
outs += GOut(out2);
|
||||
|
||||
return cv::GComputation(std::move(ins), std::move(outs));
|
||||
});
|
||||
|
||||
EXPECT_NO_THROW(cc.compileStreaming(cv::compile_args(cv::gapi::core::cpu::kernels())));
|
||||
}
|
||||
|
||||
TEST(DynamicGraph, StreamingAccuracy)
|
||||
{
|
||||
cv::Size szOut(4, 4);
|
||||
cv::GComputation cc([&](){
|
||||
cv::GMat in1;
|
||||
auto ins = GIn(in1);
|
||||
|
||||
cv::GMat in2;
|
||||
ins += GIn(in2);
|
||||
|
||||
cv::GMat out1 = cv::gapi::resize(in1, szOut);
|
||||
cv::GProtoOutputArgs outs = GOut(out1);
|
||||
|
||||
cv::GMat out2 = cv::gapi::resize(in2, szOut);
|
||||
outs += GOut(out2);
|
||||
return cv::GComputation(std::move(ins), std::move(outs));
|
||||
});
|
||||
|
||||
// G-API test code
|
||||
cv::Mat in_mat1( 8, 8, CV_8UC3);
|
||||
cv::Mat in_mat2(16, 16, CV_8UC3);
|
||||
cv::randu(in_mat1, cv::Scalar::all(0), cv::Scalar::all(255));
|
||||
cv::randu(in_mat2, cv::Scalar::all(0), cv::Scalar::all(255));
|
||||
|
||||
auto in_vector = cv::gin();
|
||||
in_vector += cv::gin(in_mat1);
|
||||
in_vector += cv::gin(in_mat2);
|
||||
|
||||
cv::Mat out_mat1, out_mat2;
|
||||
auto out_vector = cv::gout();
|
||||
out_vector += cv::gout(out_mat1);
|
||||
out_vector += cv::gout(out_mat2);
|
||||
|
||||
auto stream = cc.compileStreaming(cv::compile_args(cv::gapi::core::cpu::kernels()));
|
||||
stream.setSource(std::move(in_vector));
|
||||
|
||||
stream.start();
|
||||
stream.pull(std::move(out_vector));
|
||||
stream.stop();
|
||||
|
||||
// OCV ref code
|
||||
cv::Mat cv_out_mat1, cv_out_mat2;
|
||||
cv::resize(in_mat1, cv_out_mat1, szOut);
|
||||
cv::resize(in_mat2, cv_out_mat2, szOut);
|
||||
|
||||
EXPECT_EQ(0, cvtest::norm(out_mat1, cv_out_mat1, NORM_INF));
|
||||
EXPECT_EQ(0, cvtest::norm(out_mat2, cv_out_mat2, NORM_INF));
|
||||
}
|
||||
} // namespace opencv_test
|
300
3rdparty/opencv-4.5.4/modules/gapi/test/internal/gapi_int_executor_tests.cpp
vendored
Normal file
300
3rdparty/opencv-4.5.4/modules/gapi/test/internal/gapi_int_executor_tests.cpp
vendored
Normal file
@ -0,0 +1,300 @@
|
||||
// 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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#include "../test_precomp.hpp"
|
||||
#include "../gapi_mock_kernels.hpp"
|
||||
|
||||
namespace opencv_test
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
class GMockExecutable final: public cv::gimpl::GIslandExecutable
|
||||
{
|
||||
virtual inline bool canReshape() const override {
|
||||
return m_priv->m_can_reshape;
|
||||
}
|
||||
|
||||
virtual void reshape(ade::Graph&, const GCompileArgs&) override
|
||||
{
|
||||
m_priv->m_reshape_counter++;
|
||||
}
|
||||
virtual void handleNewStream() override { }
|
||||
virtual void run(std::vector<InObj>&&, std::vector<OutObj>&&) { }
|
||||
virtual bool allocatesOutputs() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual cv::RMat allocate(const cv::GMatDesc&) const override
|
||||
{
|
||||
m_priv->m_allocate_counter++;
|
||||
return cv::RMat();
|
||||
}
|
||||
|
||||
// NB: GMockBackendImpl creates new unique_ptr<GMockExecutable>
|
||||
// on every compile call. Need to share counters between instances in order
|
||||
// to validate it in tests.
|
||||
struct Priv
|
||||
{
|
||||
bool m_can_reshape;
|
||||
int m_reshape_counter;
|
||||
int m_allocate_counter;
|
||||
};
|
||||
|
||||
std::shared_ptr<Priv> m_priv;
|
||||
|
||||
public:
|
||||
GMockExecutable(bool can_reshape = true)
|
||||
: m_priv(new Priv{can_reshape, 0, 0})
|
||||
{
|
||||
};
|
||||
|
||||
void setReshape(bool can_reshape) { m_priv->m_can_reshape = can_reshape; }
|
||||
|
||||
int getReshapeCounter() const { return m_priv->m_reshape_counter; }
|
||||
int getAllocateCounter() const { return m_priv->m_allocate_counter; }
|
||||
};
|
||||
|
||||
class GMockBackendImpl final: public cv::gapi::GBackend::Priv
|
||||
{
|
||||
virtual void unpackKernel(ade::Graph &,
|
||||
const ade::NodeHandle &,
|
||||
const cv::GKernelImpl &) override { }
|
||||
|
||||
virtual EPtr compile(const ade::Graph &,
|
||||
const cv::GCompileArgs &,
|
||||
const std::vector<ade::NodeHandle> &) const override
|
||||
{
|
||||
++m_compile_counter;
|
||||
return EPtr{new GMockExecutable(m_exec)};
|
||||
}
|
||||
|
||||
mutable int m_compile_counter = 0;
|
||||
GMockExecutable m_exec;
|
||||
|
||||
virtual bool controlsMerge() const override {
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool allowsMerge(const cv::gimpl::GIslandModel::Graph &,
|
||||
const ade::NodeHandle &,
|
||||
const ade::NodeHandle &,
|
||||
const ade::NodeHandle &) const override {
|
||||
return false;
|
||||
}
|
||||
|
||||
public:
|
||||
GMockBackendImpl(const GMockExecutable& exec) : m_exec(exec) { };
|
||||
int getCompileCounter() const { return m_compile_counter; }
|
||||
};
|
||||
|
||||
class GMockFunctor : public gapi::cpu::GOCVFunctor
|
||||
{
|
||||
public:
|
||||
GMockFunctor(cv::gapi::GBackend backend,
|
||||
const char* id,
|
||||
const Meta &meta,
|
||||
const Impl& impl)
|
||||
: gapi::cpu::GOCVFunctor(id, meta, impl), m_backend(backend)
|
||||
{
|
||||
}
|
||||
|
||||
cv::gapi::GBackend backend() const override { return m_backend; }
|
||||
|
||||
private:
|
||||
cv::gapi::GBackend m_backend;
|
||||
};
|
||||
|
||||
template<typename K, typename Callable>
|
||||
GMockFunctor mock_kernel(const cv::gapi::GBackend& backend, Callable c)
|
||||
{
|
||||
using P = cv::detail::OCVCallHelper<Callable, typename K::InArgs, typename K::OutArgs>;
|
||||
return GMockFunctor{ backend
|
||||
, K::id()
|
||||
, &K::getOutMeta
|
||||
, std::bind(&P::callFunctor, std::placeholders::_1, c)
|
||||
};
|
||||
}
|
||||
|
||||
void dummyFooImpl(const cv::Mat&, cv::Mat&) { };
|
||||
void dummyBarImpl(const cv::Mat&, const cv::Mat&, cv::Mat&) { };
|
||||
|
||||
struct GExecutorReshapeTest: public ::testing::Test
|
||||
{
|
||||
GExecutorReshapeTest()
|
||||
: comp([](){
|
||||
cv::GMat in;
|
||||
cv::GMat out = I::Bar::on(I::Foo::on(in), in);
|
||||
return cv::GComputation(in, out);
|
||||
})
|
||||
{
|
||||
backend_impl1 = std::make_shared<GMockBackendImpl>(island1);
|
||||
backend1 = cv::gapi::GBackend{backend_impl1};
|
||||
backend_impl2 = std::make_shared<GMockBackendImpl>(island2);
|
||||
backend2 = cv::gapi::GBackend{backend_impl2};
|
||||
auto kernel1 = mock_kernel<I::Foo>(backend1, dummyFooImpl);
|
||||
auto kernel2 = mock_kernel<I::Bar>(backend2, dummyBarImpl);
|
||||
pkg = cv::gapi::kernels(kernel1, kernel2);
|
||||
in_mat1 = cv::Mat::eye(32, 32, CV_8UC1);
|
||||
in_mat2 = cv::Mat::eye(64, 64, CV_8UC1);
|
||||
}
|
||||
|
||||
cv::GComputation comp;
|
||||
GMockExecutable island1;
|
||||
std::shared_ptr<GMockBackendImpl> backend_impl1;
|
||||
cv::gapi::GBackend backend1;
|
||||
GMockExecutable island2;
|
||||
std::shared_ptr<GMockBackendImpl> backend_impl2;
|
||||
cv::gapi::GBackend backend2;
|
||||
cv::gapi::GKernelPackage pkg;
|
||||
cv::Mat in_mat1, in_mat2, out_mat;;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// FIXME: avoid code duplication
|
||||
// The below graph and config is taken from ComplexIslands test suite
|
||||
TEST(GExecutor, SmokeTest)
|
||||
{
|
||||
cv::GMat in[2];
|
||||
cv::GMat tmp[4];
|
||||
cv::GScalar scl;
|
||||
cv::GMat out[2];
|
||||
|
||||
tmp[0] = cv::gapi::bitwise_not(cv::gapi::bitwise_not(in[0]));
|
||||
tmp[1] = cv::gapi::boxFilter(in[1], -1, cv::Size(3,3));
|
||||
tmp[2] = tmp[0] + tmp[1]; // FIXME: handle tmp[2] = tmp[0]+tmp[2] typo
|
||||
scl = cv::gapi::sum(tmp[1]);
|
||||
tmp[3] = cv::gapi::medianBlur(tmp[1], 3);
|
||||
out[0] = tmp[2] + scl;
|
||||
out[1] = cv::gapi::boxFilter(tmp[3], -1, cv::Size(3,3));
|
||||
|
||||
// isl0 #internal1
|
||||
// ........................... .........
|
||||
// (in1) -> NotNot ->(tmp0) --> Add ---------> (tmp2) --> AddC -------> (out1)
|
||||
// :.....................^...: :..^....:
|
||||
// : :
|
||||
// : :
|
||||
// #internal0 : :
|
||||
// .....................:......... :
|
||||
// (in2) -> Blur -> (tmp1) ----'--> Sum ----> (scl0) ----'
|
||||
// :..........:..................: isl1
|
||||
// : ..............................
|
||||
// `------------> Median -> (tmp3) --> Blur -------> (out2)
|
||||
// :............................:
|
||||
|
||||
cv::gapi::island("isl0", cv::GIn(in[0], tmp[1]), cv::GOut(tmp[2]));
|
||||
cv::gapi::island("isl1", cv::GIn(tmp[1]), cv::GOut(out[1]));
|
||||
|
||||
cv::Mat in_mat1 = cv::Mat::eye(32, 32, CV_8UC1);
|
||||
cv::Mat in_mat2 = cv::Mat::eye(32, 32, CV_8UC1);
|
||||
cv::Mat out_gapi[2];
|
||||
|
||||
// Run G-API:
|
||||
cv::GComputation(cv::GIn(in[0], in[1]), cv::GOut(out[0], out[1]))
|
||||
.apply(cv::gin(in_mat1, in_mat2), cv::gout(out_gapi[0], out_gapi[1]));
|
||||
|
||||
// Run OpenCV
|
||||
cv::Mat out_ocv[2];
|
||||
{
|
||||
cv::Mat ocv_tmp0;
|
||||
cv::Mat ocv_tmp1;
|
||||
cv::Mat ocv_tmp2;
|
||||
cv::Mat ocv_tmp3;
|
||||
cv::Scalar ocv_scl;
|
||||
|
||||
ocv_tmp0 = in_mat1; // skip !(!)
|
||||
cv::boxFilter(in_mat2, ocv_tmp1, -1, cv::Size(3,3));
|
||||
ocv_tmp2 = ocv_tmp0 + ocv_tmp1;
|
||||
ocv_scl = cv::sum(ocv_tmp1);
|
||||
cv::medianBlur(ocv_tmp1, ocv_tmp3, 3);
|
||||
out_ocv[0] = ocv_tmp2 + ocv_scl;
|
||||
cv::boxFilter(ocv_tmp3, out_ocv[1], -1, cv::Size(3,3));
|
||||
}
|
||||
|
||||
EXPECT_EQ(0, cvtest::norm(out_gapi[0], out_ocv[0], NORM_INF));
|
||||
EXPECT_EQ(0, cvtest::norm(out_gapi[1], out_ocv[1], NORM_INF));
|
||||
|
||||
// FIXME: check that GIslandModel has more than 1 island (e.g. fusion
|
||||
// with breakdown worked)
|
||||
}
|
||||
|
||||
TEST_F(GExecutorReshapeTest, ReshapeInsteadOfRecompile)
|
||||
{
|
||||
// NB: Initial state
|
||||
EXPECT_EQ(0, backend_impl1->getCompileCounter());
|
||||
EXPECT_EQ(0, backend_impl2->getCompileCounter());
|
||||
EXPECT_EQ(0, island1.getReshapeCounter());
|
||||
EXPECT_EQ(0, island2.getReshapeCounter());
|
||||
|
||||
// NB: First compilation.
|
||||
comp.apply(cv::gin(in_mat1), cv::gout(out_mat), cv::compile_args(pkg));
|
||||
EXPECT_EQ(1, backend_impl1->getCompileCounter());
|
||||
EXPECT_EQ(1, backend_impl2->getCompileCounter());
|
||||
EXPECT_EQ(0, island1.getReshapeCounter());
|
||||
EXPECT_EQ(0, island2.getReshapeCounter());
|
||||
|
||||
// NB: GMockBackendImpl implements "reshape" method,
|
||||
// so it won't be recompiled if the meta is changed.
|
||||
comp.apply(cv::gin(in_mat2), cv::gout(out_mat), cv::compile_args(pkg));
|
||||
EXPECT_EQ(1, backend_impl1->getCompileCounter());
|
||||
EXPECT_EQ(1, backend_impl2->getCompileCounter());
|
||||
EXPECT_EQ(1, island1.getReshapeCounter());
|
||||
EXPECT_EQ(1, island2.getReshapeCounter());
|
||||
}
|
||||
|
||||
TEST_F(GExecutorReshapeTest, OneBackendNotReshapable)
|
||||
{
|
||||
// NB: Make first island not reshapable
|
||||
island1.setReshape(false);
|
||||
|
||||
// NB: Initial state
|
||||
EXPECT_EQ(0, backend_impl1->getCompileCounter());
|
||||
EXPECT_EQ(0, island1.getReshapeCounter());
|
||||
EXPECT_EQ(0, backend_impl2->getCompileCounter());
|
||||
EXPECT_EQ(0, island2.getReshapeCounter());
|
||||
|
||||
// NB: First compilation.
|
||||
comp.apply(cv::gin(in_mat1), cv::gout(out_mat), cv::compile_args(pkg));
|
||||
EXPECT_EQ(1, backend_impl1->getCompileCounter());
|
||||
EXPECT_EQ(1, backend_impl2->getCompileCounter());
|
||||
EXPECT_EQ(0, island1.getReshapeCounter());
|
||||
EXPECT_EQ(0, island2.getReshapeCounter());
|
||||
|
||||
// NB: Since one of islands isn't reshapable
|
||||
// the entire graph isn't reshapable as well.
|
||||
comp.apply(cv::gin(in_mat2), cv::gout(out_mat), cv::compile_args(pkg));
|
||||
EXPECT_EQ(2, backend_impl1->getCompileCounter());
|
||||
EXPECT_EQ(2, backend_impl2->getCompileCounter());
|
||||
EXPECT_EQ(0, island1.getReshapeCounter());
|
||||
EXPECT_EQ(0, island2.getReshapeCounter());
|
||||
}
|
||||
|
||||
TEST_F(GExecutorReshapeTest, ReshapeCallAllocate)
|
||||
{
|
||||
// NB: Initial state
|
||||
EXPECT_EQ(0, island1.getAllocateCounter());
|
||||
EXPECT_EQ(0, island1.getReshapeCounter());
|
||||
|
||||
// NB: First compilation.
|
||||
comp.apply(cv::gin(in_mat1), cv::gout(out_mat), cv::compile_args(pkg));
|
||||
EXPECT_EQ(1, island1.getAllocateCounter());
|
||||
EXPECT_EQ(0, island1.getReshapeCounter());
|
||||
|
||||
// NB: The entire graph is reshapable, so it won't be recompiled, but reshaped.
|
||||
// Check that reshape call "allocate" to reallocate buffers.
|
||||
comp.apply(cv::gin(in_mat2), cv::gout(out_mat), cv::compile_args(pkg));
|
||||
EXPECT_EQ(2, island1.getAllocateCounter());
|
||||
EXPECT_EQ(1, island1.getReshapeCounter());
|
||||
}
|
||||
|
||||
// FIXME: Add explicit tests on GMat/GScalar/GArray<T> being connectors
|
||||
// between executed islands
|
||||
|
||||
} // namespace opencv_test
|
118
3rdparty/opencv-4.5.4/modules/gapi/test/internal/gapi_int_garg_test.cpp
vendored
Normal file
118
3rdparty/opencv-4.5.4/modules/gapi/test/internal/gapi_int_garg_test.cpp
vendored
Normal file
@ -0,0 +1,118 @@
|
||||
// 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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#include "../test_precomp.hpp"
|
||||
|
||||
namespace opencv_test {
|
||||
// Tests on T/Spec/Kind matching ///////////////////////////////////////////////
|
||||
// {{
|
||||
|
||||
template<class T, cv::detail::ArgKind Exp>
|
||||
struct Expected
|
||||
{
|
||||
using type = T;
|
||||
static const constexpr cv::detail::ArgKind kind = Exp;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct GArgKind: public ::testing::Test
|
||||
{
|
||||
using Type = typename T::type;
|
||||
const cv::detail::ArgKind Kind = T::kind;
|
||||
};
|
||||
|
||||
// The reason here is to _manually_ list types and their kinds
|
||||
// (and NOT reuse cv::detail::ArgKind::Traits<>, since it is a subject of testing)
|
||||
using GArg_Test_Types = ::testing::Types
|
||||
<
|
||||
// G-API types
|
||||
Expected<cv::GMat, cv::detail::ArgKind::GMAT>
|
||||
, Expected<cv::GMatP, cv::detail::ArgKind::GMATP>
|
||||
, Expected<cv::GFrame, cv::detail::ArgKind::GFRAME>
|
||||
, Expected<cv::GScalar, cv::detail::ArgKind::GSCALAR>
|
||||
, Expected<cv::GArray<int>, cv::detail::ArgKind::GARRAY>
|
||||
, Expected<cv::GArray<float>, cv::detail::ArgKind::GARRAY>
|
||||
, Expected<cv::GArray<cv::Point>, cv::detail::ArgKind::GARRAY>
|
||||
, Expected<cv::GArray<cv::Rect>, cv::detail::ArgKind::GARRAY>
|
||||
, Expected<cv::GOpaque<int>, cv::detail::ArgKind::GOPAQUE>
|
||||
, Expected<cv::GOpaque<float>, cv::detail::ArgKind::GOPAQUE>
|
||||
, Expected<cv::GOpaque<cv::Point>, cv::detail::ArgKind::GOPAQUE>
|
||||
, Expected<cv::GOpaque<cv::Rect>, cv::detail::ArgKind::GOPAQUE>
|
||||
|
||||
// Built-in types
|
||||
, Expected<int, cv::detail::ArgKind::OPAQUE_VAL>
|
||||
, Expected<float, cv::detail::ArgKind::OPAQUE_VAL>
|
||||
, Expected<int*, cv::detail::ArgKind::OPAQUE_VAL>
|
||||
, Expected<cv::Point, cv::detail::ArgKind::OPAQUE_VAL>
|
||||
, Expected<std::string, cv::detail::ArgKind::OPAQUE_VAL>
|
||||
, Expected<cv::Mat, cv::detail::ArgKind::OPAQUE_VAL>
|
||||
, Expected<std::vector<int>, cv::detail::ArgKind::OPAQUE_VAL>
|
||||
, Expected<std::vector<cv::Point>, cv::detail::ArgKind::OPAQUE_VAL>
|
||||
>;
|
||||
|
||||
TYPED_TEST_CASE(GArgKind, GArg_Test_Types);
|
||||
|
||||
TYPED_TEST(GArgKind, LocalVar)
|
||||
{
|
||||
typename TestFixture::Type val{};
|
||||
cv::GArg arg(val);
|
||||
EXPECT_EQ(TestFixture::Kind, arg.kind);
|
||||
}
|
||||
|
||||
TYPED_TEST(GArgKind, ConstLocalVar)
|
||||
{
|
||||
const typename TestFixture::Type val{};
|
||||
cv::GArg arg(val);
|
||||
EXPECT_EQ(TestFixture::Kind, arg.kind);
|
||||
}
|
||||
|
||||
TYPED_TEST(GArgKind, RValue)
|
||||
{
|
||||
cv::GArg arg = cv::GArg(typename TestFixture::Type());
|
||||
EXPECT_EQ(TestFixture::Kind, arg.kind);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TEST(GArg, HasWrap)
|
||||
{
|
||||
static_assert(!cv::detail::has_custom_wrap<cv::GMat>::value,
|
||||
"GMat has no custom marshalling logic");
|
||||
static_assert(!cv::detail::has_custom_wrap<cv::GScalar>::value,
|
||||
"GScalar has no custom marshalling logic");
|
||||
|
||||
static_assert(cv::detail::has_custom_wrap<cv::GArray<int> >::value,
|
||||
"GArray<int> has custom marshalling logic");
|
||||
static_assert(cv::detail::has_custom_wrap<cv::GArray<std::string> >::value,
|
||||
"GArray<int> has custom marshalling logic");
|
||||
|
||||
static_assert(cv::detail::has_custom_wrap<cv::GOpaque<int> >::value,
|
||||
"GOpaque<int> has custom marshalling logic");
|
||||
static_assert(cv::detail::has_custom_wrap<cv::GOpaque<std::string> >::value,
|
||||
"GOpaque<int> has custom marshalling logic");
|
||||
}
|
||||
|
||||
TEST(GArg, GArrayU)
|
||||
{
|
||||
// Placing a GArray<T> into GArg automatically strips it to GArrayU
|
||||
cv::GArg arg1 = cv::GArg(cv::GArray<int>());
|
||||
EXPECT_NO_THROW(arg1.get<cv::detail::GArrayU>());
|
||||
|
||||
cv::GArg arg2 = cv::GArg(cv::GArray<cv::Point>());
|
||||
EXPECT_NO_THROW(arg2.get<cv::detail::GArrayU>());
|
||||
}
|
||||
|
||||
TEST(GArg, GOpaqueU)
|
||||
{
|
||||
// Placing a GOpaque<T> into GArg automatically strips it to GOpaqueU
|
||||
cv::GArg arg1 = cv::GArg(cv::GOpaque<int>());
|
||||
EXPECT_NO_THROW(arg1.get<cv::detail::GOpaqueU>());
|
||||
|
||||
cv::GArg arg2 = cv::GArg(cv::GOpaque<cv::Point>());
|
||||
EXPECT_NO_THROW(arg2.get<cv::detail::GOpaqueU>());
|
||||
}
|
||||
} // namespace opencv_test
|
201
3rdparty/opencv-4.5.4/modules/gapi/test/internal/gapi_int_gmetaarg_test.cpp
vendored
Normal file
201
3rdparty/opencv-4.5.4/modules/gapi/test/internal/gapi_int_gmetaarg_test.cpp
vendored
Normal file
@ -0,0 +1,201 @@
|
||||
// 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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#include "../test_precomp.hpp"
|
||||
|
||||
#include "api/gcomputation_priv.hpp"
|
||||
|
||||
namespace opencv_test
|
||||
{
|
||||
|
||||
TEST(GMetaArg, Traits_Is_Positive)
|
||||
{
|
||||
using namespace cv::detail;
|
||||
|
||||
static_assert(is_meta_descr<cv::GScalarDesc>::value,
|
||||
"GScalarDesc is a meta description type");
|
||||
|
||||
static_assert(is_meta_descr<cv::GMatDesc>::value,
|
||||
"GMatDesc is a meta description type");
|
||||
}
|
||||
|
||||
TEST(GMetaArg, Traits_Is_Negative)
|
||||
{
|
||||
using namespace cv::detail;
|
||||
|
||||
static_assert(!is_meta_descr<cv::GCompileArgs>::value,
|
||||
"GCompileArgs is NOT a meta description type");
|
||||
|
||||
static_assert(!is_meta_descr<int>::value,
|
||||
"int is NOT a meta description type");
|
||||
|
||||
static_assert(!is_meta_descr<std::string>::value,
|
||||
"str::string is NOT a meta description type");
|
||||
}
|
||||
|
||||
TEST(GMetaArg, Traits_Are_EntireList_Positive)
|
||||
{
|
||||
using namespace cv::detail;
|
||||
|
||||
static_assert(are_meta_descrs<cv::GScalarDesc>::value,
|
||||
"GScalarDesc is a meta description type");
|
||||
|
||||
static_assert(are_meta_descrs<cv::GMatDesc>::value,
|
||||
"GMatDesc is a meta description type");
|
||||
|
||||
static_assert(are_meta_descrs<cv::GMatDesc, cv::GScalarDesc>::value,
|
||||
"Both GMatDesc and GScalarDesc are meta types");
|
||||
}
|
||||
|
||||
TEST(GMetaArg, Traits_Are_EntireList_Negative)
|
||||
{
|
||||
using namespace cv::detail;
|
||||
|
||||
static_assert(!are_meta_descrs<cv::GCompileArgs>::value,
|
||||
"GCompileArgs is NOT among meta types");
|
||||
|
||||
static_assert(!are_meta_descrs<int, std::string>::value,
|
||||
"Both int and std::string is NOT among meta types");
|
||||
|
||||
static_assert(!are_meta_descrs<cv::GMatDesc, cv::GScalarDesc, int>::value,
|
||||
"List of type is not valid for meta as there\'s int");
|
||||
|
||||
static_assert(!are_meta_descrs<cv::GMatDesc, cv::GScalarDesc, cv::GCompileArgs>::value,
|
||||
"List of type is not valid for meta as there\'s GCompileArgs");
|
||||
}
|
||||
|
||||
TEST(GMetaArg, Traits_Are_ButLast_Positive)
|
||||
{
|
||||
using namespace cv::detail;
|
||||
|
||||
static_assert(are_meta_descrs_but_last<cv::GScalarDesc, int>::value,
|
||||
"List is valid (int is omitted)");
|
||||
|
||||
static_assert(are_meta_descrs_but_last<cv::GMatDesc, cv::GScalarDesc, cv::GCompileArgs>::value,
|
||||
"List is valid (GCompileArgs are omitted)");
|
||||
}
|
||||
|
||||
TEST(GMetaArg, Traits_Are_ButLast_Negative)
|
||||
{
|
||||
using namespace cv::detail;
|
||||
|
||||
static_assert(!are_meta_descrs_but_last<int, std::string>::value,
|
||||
"Both int is NOT among meta types (std::string is omitted)");
|
||||
|
||||
static_assert(!are_meta_descrs_but_last<cv::GMatDesc, cv::GScalarDesc, int, int>::value,
|
||||
"List of type is not valid for meta as there\'s two ints");
|
||||
|
||||
static_assert(!are_meta_descrs_but_last<cv::GMatDesc, cv::GScalarDesc, cv::GCompileArgs, float>::value,
|
||||
"List of type is not valid for meta as there\'s GCompileArgs");
|
||||
}
|
||||
|
||||
TEST(GMetaArg, Can_Get_Metas_From_Input_Run_Args)
|
||||
{
|
||||
cv::Mat m(3, 3, CV_8UC3);
|
||||
cv::Scalar s;
|
||||
std::vector<int> v;
|
||||
|
||||
GMatDesc m_desc;
|
||||
GMetaArgs meta_args = descr_of(cv::gin(m, s, v));
|
||||
|
||||
EXPECT_EQ(meta_args.size(), 3u);
|
||||
EXPECT_NO_THROW(m_desc = util::get<cv::GMatDesc>(meta_args[0]));
|
||||
EXPECT_NO_THROW(util::get<cv::GScalarDesc>(meta_args[1]));
|
||||
EXPECT_NO_THROW(util::get<cv::GArrayDesc>(meta_args[2]));
|
||||
|
||||
EXPECT_EQ(CV_8U, m_desc.depth);
|
||||
EXPECT_EQ(3, m_desc.chan);
|
||||
EXPECT_EQ(cv::gapi::own::Size(3, 3), m_desc.size);
|
||||
}
|
||||
|
||||
TEST(GMetaArg, Can_Get_Metas_From_Output_Run_Args)
|
||||
{
|
||||
cv::Mat m(3, 3, CV_8UC3);
|
||||
cv::Scalar s;
|
||||
std::vector<int> v;
|
||||
|
||||
GMatDesc m_desc;
|
||||
GRunArgsP out_run_args = cv::gout(m, s, v);
|
||||
GMetaArg m_meta = descr_of(out_run_args[0]);
|
||||
GMetaArg s_meta = descr_of(out_run_args[1]);
|
||||
GMetaArg v_meta = descr_of(out_run_args[2]);
|
||||
|
||||
EXPECT_NO_THROW(m_desc = util::get<cv::GMatDesc>(m_meta));
|
||||
EXPECT_NO_THROW(util::get<cv::GScalarDesc>(s_meta));
|
||||
EXPECT_NO_THROW(util::get<cv::GArrayDesc>(v_meta));
|
||||
|
||||
EXPECT_EQ(CV_8U, m_desc.depth);
|
||||
EXPECT_EQ(3, m_desc.chan);
|
||||
EXPECT_EQ(cv::Size(3, 3), m_desc.size);
|
||||
}
|
||||
|
||||
TEST(GMetaArg, Can_Describe_RunArg)
|
||||
{
|
||||
cv::Mat m(3, 3, CV_8UC3);
|
||||
cv::UMat um(3, 3, CV_8UC3);
|
||||
cv::Scalar s;
|
||||
constexpr int w = 3, h = 3, c = 3;
|
||||
uchar data[w*h*c];
|
||||
cv::gapi::own::Mat om(h, w, CV_8UC3, data);
|
||||
cv::Scalar os;
|
||||
std::vector<int> v;
|
||||
|
||||
GMetaArgs metas = {GMetaArg(descr_of(m)),
|
||||
GMetaArg(descr_of(um)),
|
||||
GMetaArg(descr_of(s)),
|
||||
GMetaArg(descr_of(om)),
|
||||
GMetaArg(descr_of(os)),
|
||||
GMetaArg(descr_of(v))};
|
||||
|
||||
auto in_run_args = cv::gin(m, um, s, om, os, v);
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
EXPECT_TRUE(can_describe(metas[i], in_run_args[i]));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(GMetaArg, Can_Describe_RunArgs)
|
||||
{
|
||||
cv::Mat m(3, 3, CV_8UC3);
|
||||
cv::Scalar s;
|
||||
std::vector<int> v;
|
||||
|
||||
GMetaArgs metas0 = {GMetaArg(descr_of(m)), GMetaArg(descr_of(s)), GMetaArg(descr_of(v))};
|
||||
auto in_run_args0 = cv::gin(m, s, v);
|
||||
|
||||
EXPECT_TRUE(can_describe(metas0, in_run_args0));
|
||||
|
||||
auto in_run_args01 = cv::gin(m, s);
|
||||
EXPECT_FALSE(can_describe(metas0, in_run_args01));
|
||||
}
|
||||
|
||||
TEST(GMetaArg, Can_Describe_RunArgP)
|
||||
{
|
||||
cv::Mat m(3, 3, CV_8UC3);
|
||||
cv::UMat um(3, 3, CV_8UC3);
|
||||
cv::Scalar s;
|
||||
constexpr int w = 3, h = 3, c = 3;
|
||||
uchar data[w*h*c];
|
||||
cv::gapi::own::Mat om(h, w, CV_8UC3, data);
|
||||
cv::Scalar os;
|
||||
std::vector<int> v;
|
||||
|
||||
GMetaArgs metas = {GMetaArg(descr_of(m)),
|
||||
GMetaArg(descr_of(um)),
|
||||
GMetaArg(descr_of(s)),
|
||||
GMetaArg(descr_of(om)),
|
||||
GMetaArg(descr_of(os)),
|
||||
GMetaArg(descr_of(v))};
|
||||
|
||||
auto out_run_args = cv::gout(m, um, s, om, os, v);
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
EXPECT_TRUE(can_describe(metas[i], out_run_args[i]));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace opencv_test
|
378
3rdparty/opencv-4.5.4/modules/gapi/test/internal/gapi_int_gmodel_builder_test.cpp
vendored
Normal file
378
3rdparty/opencv-4.5.4/modules/gapi/test/internal/gapi_int_gmodel_builder_test.cpp
vendored
Normal file
@ -0,0 +1,378 @@
|
||||
// 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) 2018-2020 Intel Corporation
|
||||
|
||||
|
||||
#include "../test_precomp.hpp"
|
||||
|
||||
#include <ade/util/zip_range.hpp> // util::indexed
|
||||
|
||||
#include <opencv2/gapi/gkernel.hpp>
|
||||
#include <opencv2/gapi/gcommon.hpp>
|
||||
#include "compiler/gmodelbuilder.hpp"
|
||||
#include "compiler/gmodel.hpp" // RcDesc, GModel::init
|
||||
|
||||
namespace opencv_test
|
||||
{
|
||||
|
||||
namespace test
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
namespace D = cv::detail;
|
||||
cv::GMat unaryOp(cv::GMat m)
|
||||
{
|
||||
return cv::GCall(cv::GKernel{ "gapi.test.unaryop"
|
||||
, ""
|
||||
, nullptr
|
||||
, { GShape::GMAT }
|
||||
, { D::OpaqueKind::CV_UNKNOWN }
|
||||
, { cv::detail::HostCtor{cv::util::monostate{}} }
|
||||
}).pass(m).yield(0);
|
||||
}
|
||||
|
||||
cv::GMat binaryOp(cv::GMat m1, cv::GMat m2)
|
||||
{
|
||||
return cv::GCall(cv::GKernel{ "gapi.test.binaryOp"
|
||||
, ""
|
||||
, nullptr
|
||||
, { GShape::GMAT }
|
||||
, { D::OpaqueKind::CV_UNKNOWN, D::OpaqueKind::CV_UNKNOWN }
|
||||
, { cv::detail::HostCtor{cv::util::monostate{}} }
|
||||
}).pass(m1, m2).yield(0);
|
||||
}
|
||||
|
||||
std::vector<ade::NodeHandle> collectOperations(const cv::gimpl::GModel::Graph& gr)
|
||||
{
|
||||
std::vector<ade::NodeHandle> ops;
|
||||
for (const auto& nh : gr.nodes())
|
||||
{
|
||||
if (gr.metadata(nh).get<cv::gimpl::NodeType>().t == cv::gimpl::NodeType::OP)
|
||||
ops.push_back(nh);
|
||||
}
|
||||
return ops;
|
||||
}
|
||||
|
||||
ade::NodeHandle inputOf(cv::gimpl::GModel::Graph& gm, ade::NodeHandle nh, std::size_t port)
|
||||
{
|
||||
for (const auto& eh : nh->inEdges())
|
||||
{
|
||||
if (gm.metadata(eh).get<cv::gimpl::Input>().port == port)
|
||||
{
|
||||
return eh->srcNode();
|
||||
}
|
||||
}
|
||||
util::throw_error(std::logic_error("port " + std::to_string(port) + " not found"));
|
||||
}
|
||||
}
|
||||
}// namespace opencv_test::test
|
||||
|
||||
TEST(GModelBuilder, Unroll_TestUnary)
|
||||
{
|
||||
cv::GMat in;
|
||||
cv::GMat out = test::unaryOp(in);
|
||||
|
||||
auto unrolled = cv::gimpl::unrollExpr(cv::GIn(in).m_args, cv::GOut(out).m_args);
|
||||
|
||||
EXPECT_EQ(1u, unrolled.all_ops.size()); // There is one operation
|
||||
EXPECT_EQ(2u, unrolled.all_data.size()); // And two data objects (in, out)
|
||||
|
||||
// TODO check what the operation is, and so on, and so on
|
||||
}
|
||||
|
||||
TEST(GModelBuilder, Unroll_TestUnaryOfUnary)
|
||||
{
|
||||
cv::GMat in;
|
||||
cv::GMat out = test::unaryOp(test::unaryOp(in));
|
||||
|
||||
auto unrolled = cv::gimpl::unrollExpr(cv::GIn(in).m_args, cv::GOut(out).m_args);
|
||||
|
||||
EXPECT_EQ(2u, unrolled.all_ops.size()); // There're two operations
|
||||
EXPECT_EQ(3u, unrolled.all_data.size()); // And three data objects (in, out)
|
||||
|
||||
// TODO check what the operation is, and so on, and so on
|
||||
}
|
||||
|
||||
TEST(GModelBuilder, Unroll_Not_All_Protocol_Inputs_Are_Reached)
|
||||
{
|
||||
cv::GMat in1, in2; // in1 -> unaryOp() -> u_op1 -> unaryOp() -> out
|
||||
auto u_op1 = test::unaryOp(in1); // in2 -> unaryOp() -> u_op2
|
||||
auto u_op2 = test::unaryOp(in2);
|
||||
auto out = test::unaryOp(u_op1);
|
||||
|
||||
EXPECT_THROW(cv::gimpl::unrollExpr(cv::GIn(in1, in2).m_args, cv::GOut(out).m_args), std::logic_error);
|
||||
}
|
||||
|
||||
TEST(GModelBuilder, Unroll_Parallel_Path)
|
||||
{
|
||||
cv::GMat in1, in2; // in1 -> unaryOp() -> out1
|
||||
auto out1 = test::unaryOp(in1); // in2 -> unaryOp() -> out2
|
||||
auto out2 = test::unaryOp(in2);
|
||||
|
||||
auto unrolled = cv::gimpl::unrollExpr(cv::GIn(in1, in2).m_args, cv::GOut(out1, out2).m_args);
|
||||
|
||||
EXPECT_EQ(unrolled.all_ops.size(), 2u);
|
||||
EXPECT_EQ(unrolled.all_data.size(), 4u);
|
||||
}
|
||||
|
||||
TEST(GModelBuilder, Unroll_WithBranch)
|
||||
{
|
||||
// in -> unaryOp() -> tmp -->unaryOp() -> out1
|
||||
// `---->unaryOp() -> out2
|
||||
|
||||
GMat in;
|
||||
auto tmp = test::unaryOp(in);
|
||||
auto out1 = test::unaryOp(tmp);
|
||||
auto out2 = test::unaryOp(tmp);
|
||||
|
||||
auto unrolled = cv::gimpl::unrollExpr(cv::GIn(in).m_args, cv::GOut(out1, out2).m_args);
|
||||
|
||||
EXPECT_EQ(unrolled.all_ops.size(), 3u);
|
||||
EXPECT_EQ(unrolled.all_data.size(), 4u);
|
||||
}
|
||||
|
||||
TEST(GModelBuilder, Build_Unary)
|
||||
{
|
||||
cv::GMat in;
|
||||
cv::GMat out = test::unaryOp(in);
|
||||
|
||||
ade::Graph g;
|
||||
cv::gimpl::GModel::Graph gm(g);
|
||||
cv::gimpl::GModel::init(gm);
|
||||
cv::gimpl::GModelBuilder(g).put(cv::GIn(in).m_args, cv::GOut(out).m_args);
|
||||
|
||||
EXPECT_EQ(3u, static_cast<std::size_t>(g.nodes().size())); // Generated graph should have three nodes
|
||||
|
||||
// TODO: Check what the nodes are
|
||||
}
|
||||
|
||||
TEST(GModelBuilder, Constant_GScalar)
|
||||
{
|
||||
// in -> addC()-----(GMat)---->mulC()-----(GMat)---->unaryOp()----out
|
||||
// ^ ^
|
||||
// | |
|
||||
// 3-------` c_s-------'
|
||||
|
||||
cv::GMat in;
|
||||
cv::GScalar c_s = 5;
|
||||
auto out = test::unaryOp((in + 3) * c_s); // 3 converted to GScalar
|
||||
|
||||
ade::Graph g;
|
||||
cv::gimpl::GModel::Graph gm(g);
|
||||
cv::gimpl::GModel::init(gm);
|
||||
auto proto_slots = cv::gimpl::GModelBuilder(g).put(cv::GIn(in).m_args, cv::GOut(out).m_args);
|
||||
cv::gimpl::Protocol p;
|
||||
std::tie(p.inputs, p.outputs, p.in_nhs, p.out_nhs) = proto_slots;
|
||||
|
||||
auto in_nh = p.in_nhs.front();
|
||||
auto addC_nh = in_nh->outNodes().front();
|
||||
auto mulC_nh = addC_nh->outNodes().front()->outNodes().front();
|
||||
|
||||
ASSERT_TRUE(gm.metadata(addC_nh).get<cv::gimpl::NodeType>().t == cv::gimpl::NodeType::OP);
|
||||
ASSERT_TRUE(gm.metadata(mulC_nh).get<cv::gimpl::NodeType>().t == cv::gimpl::NodeType::OP);
|
||||
|
||||
auto s_3 = test::inputOf(gm, addC_nh, 1);
|
||||
auto s_5 = test::inputOf(gm, mulC_nh, 1);
|
||||
|
||||
EXPECT_EQ(9u, static_cast<std::size_t>(g.nodes().size())); // 6 data nodes (1 -input, 1 output, 2 constant, 2 temp) and 3 op nodes
|
||||
EXPECT_EQ(2u, static_cast<std::size_t>(addC_nh->inNodes().size())); // in and 3
|
||||
EXPECT_EQ(2u, static_cast<std::size_t>(mulC_nh->inNodes().size())); // addC output and c_s
|
||||
EXPECT_EQ(3, (util::get<cv::Scalar>(gm.metadata(s_3).get<cv::gimpl::ConstValue>().arg))[0]);
|
||||
EXPECT_EQ(5, (util::get<cv::Scalar>(gm.metadata(s_5).get<cv::gimpl::ConstValue>().arg))[0]);
|
||||
}
|
||||
|
||||
TEST(GModelBuilder, Check_Multiple_Outputs)
|
||||
{
|
||||
// ------------------------------> r
|
||||
// '
|
||||
// ' -----------> i_out1
|
||||
// ' '
|
||||
// in ----> split3() ---> g ---> integral()
|
||||
// ' '
|
||||
// ' -----------> i_out2
|
||||
// '
|
||||
// '---------> b ---> unaryOp() ---> u_out
|
||||
|
||||
cv::GMat in, r, g, b, i_out1, i_out2, u_out;
|
||||
std::tie(r, g, b) = cv::gapi::split3(in);
|
||||
std::tie(i_out1, i_out2) = cv::gapi::integral(g, 1, 1);
|
||||
u_out = test::unaryOp(b);
|
||||
|
||||
ade::Graph gr;
|
||||
cv::gimpl::GModel::Graph gm(gr);
|
||||
cv::gimpl::GModel::init(gm);
|
||||
auto proto_slots = cv::gimpl::GModelBuilder(gr).put(cv::GIn(in).m_args, cv::GOut(r, i_out1, i_out2, u_out).m_args);
|
||||
cv::gimpl::Protocol p;
|
||||
std::tie(p.inputs, p.outputs, p.in_nhs, p.out_nhs) = proto_slots;
|
||||
|
||||
EXPECT_EQ(4u, static_cast<std::size_t>(p.out_nhs.size()));
|
||||
EXPECT_EQ(0u, gm.metadata(p.out_nhs[0]->inEdges().front()).get<cv::gimpl::Output>().port);
|
||||
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))
|
||||
{
|
||||
const auto& out_nh = ade::util::value(it);
|
||||
|
||||
EXPECT_EQ(cv::gimpl::NodeType::DATA, gm.metadata(out_nh).get<cv::gimpl::NodeType>().t);
|
||||
EXPECT_EQ(GShape::GMAT, gm.metadata(out_nh).get<cv::gimpl::Data>().shape);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(GModelBuilder, Unused_Outputs)
|
||||
{
|
||||
cv::GMat in;
|
||||
auto yuv_p = cv::gapi::split3(in);
|
||||
|
||||
ade::Graph g;
|
||||
cv::gimpl::GModel::Graph gm(g);
|
||||
cv::gimpl::GModel::init(gm);
|
||||
cv::gimpl::GModelBuilder(g).put(cv::GIn(in).m_args, cv::GOut(std::get<0>(yuv_p)).m_args);
|
||||
|
||||
EXPECT_EQ(5u, static_cast<std::size_t>(g.nodes().size())); // 1 input, 1 operation, 3 outputs
|
||||
}
|
||||
|
||||
TEST(GModelBuilder, Work_With_One_Channel_From_Split3)
|
||||
{
|
||||
cv::GMat in, y, u, v;
|
||||
std::tie(y, u, v) = cv::gapi::split3(in);
|
||||
auto y_blur = cv::gapi::gaussianBlur(y, cv::Size(3, 3), 1);
|
||||
|
||||
ade::Graph g;
|
||||
cv::gimpl::GModel::Graph gm(g);
|
||||
cv::gimpl::GModel::init(gm);
|
||||
cv::gimpl::GModelBuilder(g).put(cv::GIn(in).m_args, cv::GOut(y_blur).m_args);
|
||||
|
||||
EXPECT_EQ(7u, static_cast<std::size_t>(g.nodes().size())); // 1 input, 2 operation, 3 nodes from split3, 1 output
|
||||
}
|
||||
|
||||
TEST(GModelBuilder, Add_Nodes_To_Unused_Nodes)
|
||||
{
|
||||
cv::GMat in, y, u, v;
|
||||
std::tie(y, u, v) = cv::gapi::split3(in);
|
||||
auto y_blur = cv::gapi::gaussianBlur(y, cv::Size(3, 3), 1);
|
||||
// unused nodes
|
||||
auto u_blur = cv::gapi::gaussianBlur(y, cv::Size(3, 3), 1);
|
||||
auto v_blur = cv::gapi::gaussianBlur(y, cv::Size(3, 3), 1);
|
||||
|
||||
ade::Graph g;
|
||||
cv::gimpl::GModel::Graph gm(g);
|
||||
cv::gimpl::GModel::init(gm);
|
||||
cv::gimpl::GModelBuilder(g).put(cv::GIn(in).m_args, cv::GOut(y_blur).m_args);
|
||||
|
||||
EXPECT_EQ(7u, static_cast<std::size_t>(g.nodes().size())); // 1 input, 2 operation, 3 nodes from split3, 1 output
|
||||
}
|
||||
|
||||
TEST(GModelBuilder, Unlisted_Inputs)
|
||||
{
|
||||
// in1 -> binaryOp() -> out
|
||||
// ^
|
||||
// |
|
||||
// in2 ----'
|
||||
|
||||
cv::GMat in1, in2;
|
||||
auto out = test::binaryOp(in1, in2);
|
||||
|
||||
ade::Graph g;
|
||||
cv::gimpl::GModel::Graph gm(g);
|
||||
cv::gimpl::GModel::init(gm);
|
||||
// add required 2 inputs but pass 1
|
||||
EXPECT_THROW(cv::gimpl::GModelBuilder(g).put(cv::GIn(in1).m_args, cv::GOut(out).m_args), std::logic_error);
|
||||
}
|
||||
|
||||
TEST(GModelBuilder, Unroll_No_Link_Between_In_And_Out)
|
||||
{
|
||||
// in -> unaryOp() -> u_op
|
||||
// other -> unaryOp() -> out
|
||||
|
||||
cv::GMat in, other;
|
||||
auto u_op = test::unaryOp(in);
|
||||
auto out = test::unaryOp(other);
|
||||
|
||||
EXPECT_THROW(cv::gimpl::unrollExpr(cv::GIn(in).m_args, cv::GOut(out).m_args), std::logic_error);
|
||||
}
|
||||
|
||||
|
||||
TEST(GModel_builder, Check_Binary_Op)
|
||||
{
|
||||
// in1 -> binaryOp() -> out
|
||||
// ^
|
||||
// |
|
||||
// in2 -----'
|
||||
|
||||
cv::GMat in1, in2;
|
||||
auto out = test::binaryOp(in1, in2);
|
||||
|
||||
ade::Graph g;
|
||||
cv::gimpl::GModel::Graph gm(g);
|
||||
cv::gimpl::GModel::init(gm);
|
||||
auto proto_slots = cv::gimpl::GModelBuilder(g).put(cv::GIn(in1, in2).m_args, cv::GOut(out).m_args);
|
||||
|
||||
cv::gimpl::Protocol p;
|
||||
std::tie(p.inputs, p.outputs, p.in_nhs, p.out_nhs) = proto_slots;
|
||||
auto ops = test::collectOperations(g);
|
||||
|
||||
EXPECT_EQ(1u, ops.size());
|
||||
EXPECT_EQ("gapi.test.binaryOp", gm.metadata(ops.front()).get<cv::gimpl::Op>().k.name);
|
||||
EXPECT_EQ(2u, static_cast<std::size_t>(ops.front()->inEdges().size()));
|
||||
EXPECT_EQ(1u, static_cast<std::size_t>(ops.front()->outEdges().size()));
|
||||
EXPECT_EQ(1u, static_cast<std::size_t>(ops.front()->outNodes().size()));
|
||||
}
|
||||
|
||||
TEST(GModelBuilder, Add_Operation_With_Two_Out_One_Time)
|
||||
{
|
||||
// in -> integral() --> out_b1 -> unaryOp() -> out1
|
||||
// |
|
||||
// '-------> out_b2 -> unaryOp() -> out2
|
||||
|
||||
cv::GMat in, out_b1, out_b2;
|
||||
std::tie(out_b1, out_b2) = cv::gapi::integral(in, 1, 1);
|
||||
auto out1 = test::unaryOp(out_b1);
|
||||
auto out2 = test::unaryOp(out_b1);
|
||||
|
||||
ade::Graph g;
|
||||
cv::gimpl::GModel::Graph gm(g);
|
||||
cv::gimpl::GModel::init(gm);
|
||||
auto proto_slots = cv::gimpl::GModelBuilder(g).put(cv::GIn(in).m_args, cv::GOut(out1, out2).m_args);
|
||||
|
||||
auto ops = test::collectOperations(gm);
|
||||
|
||||
cv::gimpl::Protocol p;
|
||||
std::tie(p.inputs, p.outputs, p.in_nhs, p.out_nhs) = proto_slots;
|
||||
auto integral_nh = p.in_nhs.front()->outNodes().front();
|
||||
|
||||
EXPECT_EQ(3u, ops.size());
|
||||
EXPECT_EQ("org.opencv.core.matrixop.integral", gm.metadata(integral_nh).get<cv::gimpl::Op>().k.name);
|
||||
EXPECT_EQ(1u, static_cast<std::size_t>(integral_nh->inEdges().size()));
|
||||
EXPECT_EQ(2u, static_cast<std::size_t>(integral_nh->outEdges().size()));
|
||||
EXPECT_EQ(2u, static_cast<std::size_t>(integral_nh->outNodes().size()));
|
||||
}
|
||||
TEST(GModelBuilder, Add_Operation_With_One_Out_One_Time)
|
||||
{
|
||||
// in1 -> binaryOp() -> b_out -> unaryOp() -> out1
|
||||
// ^ |
|
||||
// | |
|
||||
// in2 ------- '----> unaryOp() -> out2
|
||||
|
||||
cv::GMat in1, in2;
|
||||
auto b_out = test::binaryOp(in1, in2);
|
||||
auto out1 = test::unaryOp(b_out);
|
||||
auto out2 = test::unaryOp(b_out);
|
||||
|
||||
ade::Graph g;
|
||||
cv::gimpl::GModel::Graph gm(g);
|
||||
cv::gimpl::GModel::init(gm);
|
||||
auto proto_slots = cv::gimpl::GModelBuilder(g).put(cv::GIn(in1, in2).m_args, cv::GOut(out1, out2).m_args);
|
||||
cv::gimpl::Protocol p;
|
||||
std::tie(p.inputs, p.outputs, p.in_nhs, p.out_nhs) = proto_slots;
|
||||
cv::gimpl::GModel::Graph gr(g);
|
||||
auto binaryOp_nh = p.in_nhs.front()->outNodes().front();
|
||||
|
||||
EXPECT_EQ(2u, static_cast<std::size_t>(binaryOp_nh->inEdges().size()));
|
||||
EXPECT_EQ(1u, static_cast<std::size_t>(binaryOp_nh->outEdges().size()));
|
||||
EXPECT_EQ(8u, static_cast<std::size_t>(g.nodes().size()));
|
||||
}
|
||||
} // namespace opencv_test
|
588
3rdparty/opencv-4.5.4/modules/gapi/test/internal/gapi_int_island_fusion_tests.cpp
vendored
Normal file
588
3rdparty/opencv-4.5.4/modules/gapi/test/internal/gapi_int_island_fusion_tests.cpp
vendored
Normal file
@ -0,0 +1,588 @@
|
||||
// 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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#include "../test_precomp.hpp"
|
||||
#include "compiler/transactions.hpp"
|
||||
|
||||
#include "../gapi_mock_kernels.hpp"
|
||||
|
||||
#include "compiler/gislandmodel.hpp"
|
||||
#include "compiler/gcompiler.hpp"
|
||||
#include "compiler/gmodel_priv.hpp"
|
||||
|
||||
namespace opencv_test
|
||||
{
|
||||
|
||||
TEST(IslandFusion, TwoOps_OneIsland)
|
||||
{
|
||||
namespace J = Jupiter; // see mock_kernels.cpp
|
||||
|
||||
// Define a computation:
|
||||
//
|
||||
// (in) -> J::Foo1 -> (tmp0) -> J::Foo2 -> (out)
|
||||
// : :
|
||||
// : "island0" :
|
||||
// :<----------------------------->:
|
||||
|
||||
cv::GMat in;
|
||||
cv::GMat tmp0 = I::Foo::on(in);
|
||||
cv::GMat out = I::Foo::on(tmp0);
|
||||
cv::GComputation cc(in, out);
|
||||
|
||||
// Prepare compilation parameters manually
|
||||
const auto in_meta = cv::GMetaArg(cv::GMatDesc{CV_8U,1,cv::Size(32,32)});
|
||||
const auto pkg = cv::gapi::kernels<J::Foo>();
|
||||
|
||||
// Directly instantiate G-API graph compiler and run partial compilation
|
||||
cv::gimpl::GCompiler compiler(cc, {in_meta}, cv::compile_args(pkg));
|
||||
cv::gimpl::GCompiler::GPtr graph = compiler.generateGraph();
|
||||
compiler.runPasses(*graph);
|
||||
|
||||
// Inspect the graph and verify the islands configuration
|
||||
cv::gimpl::GModel::ConstGraph gm(*graph);
|
||||
cv::gimpl::GModel::ConstLayoutGraph glm(*graph);
|
||||
|
||||
auto in_nh = cv::gimpl::GModel::dataNodeOf(glm, in);
|
||||
auto tmp_nh = cv::gimpl::GModel::dataNodeOf(glm, tmp0);
|
||||
auto out_nh = cv::gimpl::GModel::dataNodeOf(glm, out);
|
||||
|
||||
// in/out mats shouldn't be assigned to any Island
|
||||
EXPECT_FALSE(gm.metadata(in_nh ).contains<cv::gimpl::Island>());
|
||||
EXPECT_FALSE(gm.metadata(out_nh).contains<cv::gimpl::Island>());
|
||||
|
||||
// Since tmp is surrounded by two J kernels, tmp should be assigned
|
||||
// to island J
|
||||
EXPECT_TRUE(gm.metadata(tmp_nh).contains<cv::gimpl::Island>());
|
||||
}
|
||||
|
||||
TEST(IslandFusion, TwoOps_TwoIslands)
|
||||
{
|
||||
namespace J = Jupiter; // see mock_kernels.cpp
|
||||
namespace S = Saturn; // see mock_kernels.cpp
|
||||
|
||||
// Define a computation:
|
||||
//
|
||||
// (in) -> J::Foo --> (tmp0) -> S::Bar --> (out)
|
||||
// : : -> :
|
||||
// : : : :
|
||||
// :<-------->: :<-------->:
|
||||
|
||||
cv::GMat in;
|
||||
cv::GMat tmp0 = I::Foo::on(in);
|
||||
cv::GMat out = I::Bar::on(tmp0, tmp0);
|
||||
cv::GComputation cc(in, out);
|
||||
|
||||
// Prepare compilation parameters manually
|
||||
const auto in_meta = cv::GMetaArg(cv::GMatDesc{CV_8U,1,cv::Size(32,32)});
|
||||
const auto pkg = cv::gapi::kernels<J::Foo, S::Bar>();
|
||||
|
||||
// Directly instantiate G-API graph compiler and run partial compilation
|
||||
cv::gimpl::GCompiler compiler(cc, {in_meta}, cv::compile_args(pkg));
|
||||
cv::gimpl::GCompiler::GPtr graph = compiler.generateGraph();
|
||||
compiler.runPasses(*graph);
|
||||
|
||||
// Inspect the graph and verify the islands configuration
|
||||
cv::gimpl::GModel::ConstGraph gm(*graph);
|
||||
|
||||
auto in_nh = cv::gimpl::GModel::dataNodeOf(gm, in);
|
||||
auto tmp_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp0);
|
||||
auto out_nh = cv::gimpl::GModel::dataNodeOf(gm, out);
|
||||
|
||||
// in/tmp/out mats shouldn't be assigned to any Island
|
||||
EXPECT_FALSE(gm.metadata(in_nh ).contains<cv::gimpl::Island>());
|
||||
EXPECT_FALSE(gm.metadata(out_nh).contains<cv::gimpl::Island>());
|
||||
EXPECT_FALSE(gm.metadata(tmp_nh).contains<cv::gimpl::Island>());
|
||||
|
||||
auto isl_model = gm.metadata().get<cv::gimpl::IslandModel>().model;
|
||||
cv::gimpl::GIslandModel::ConstGraph gim(*isl_model);
|
||||
|
||||
// There should be two islands in the GIslandModel
|
||||
const auto is_island = [&](ade::NodeHandle nh) {
|
||||
return (cv::gimpl::NodeKind::ISLAND
|
||||
== gim.metadata(nh).get<cv::gimpl::NodeKind>().k);
|
||||
};
|
||||
const std::size_t num_isl = std::count_if(gim.nodes().begin(),
|
||||
gim.nodes().end(),
|
||||
is_island);
|
||||
EXPECT_EQ(2u, num_isl);
|
||||
|
||||
auto isl_foo_nh = cv::gimpl::GIslandModel::producerOf(gim, tmp_nh);
|
||||
auto isl_bar_nh = cv::gimpl::GIslandModel::producerOf(gim, out_nh);
|
||||
ASSERT_NE(nullptr, isl_foo_nh);
|
||||
ASSERT_NE(nullptr, isl_bar_nh);
|
||||
|
||||
// Islands should be different
|
||||
auto isl_foo_obj = gim.metadata(isl_foo_nh).get<cv::gimpl::FusedIsland>().object;
|
||||
auto isl_bar_obj = gim.metadata(isl_bar_nh).get<cv::gimpl::FusedIsland>().object;
|
||||
EXPECT_FALSE(isl_foo_obj == isl_bar_obj);
|
||||
}
|
||||
|
||||
TEST(IslandFusion, ConsumerHasTwoInputs)
|
||||
{
|
||||
namespace J = Jupiter; // see mock_kernels.cpp
|
||||
|
||||
// Define a computation: island
|
||||
// ............................
|
||||
// (in0) ->:J::Foo -> (tmp) -> S::Bar :--> (out)
|
||||
// :....................^.....:
|
||||
// |
|
||||
// (in1) -----------------------`
|
||||
//
|
||||
|
||||
// Check that island is build correctly, when consumer has two inputs
|
||||
|
||||
GMat in[2];
|
||||
GMat tmp = I::Foo::on(in[0]);
|
||||
GMat out = I::Bar::on(tmp, in[1]);
|
||||
|
||||
cv::GComputation cc(cv::GIn(in[0], in[1]), cv::GOut(out));
|
||||
|
||||
// Prepare compilation parameters manually
|
||||
cv::GMetaArgs in_metas = {GMetaArg(cv::GMatDesc{CV_8U,1,cv::Size(32,32)}),
|
||||
GMetaArg(cv::GMatDesc{CV_8U,1,cv::Size(32,32)})};
|
||||
const auto pkg = cv::gapi::kernels<J::Foo, J::Bar>();
|
||||
|
||||
// Directly instantiate G-API graph compiler and run partial compilation
|
||||
cv::gimpl::GCompiler compiler(cc, std::move(in_metas), cv::compile_args(pkg));
|
||||
cv::gimpl::GCompiler::GPtr graph = compiler.generateGraph();
|
||||
compiler.runPasses(*graph);
|
||||
|
||||
cv::gimpl::GModel::ConstGraph gm(*graph);
|
||||
|
||||
auto in0_nh = cv::gimpl::GModel::dataNodeOf(gm, in[0]);
|
||||
auto in1_nh = cv::gimpl::GModel::dataNodeOf(gm, in[1]);
|
||||
auto tmp_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp);
|
||||
auto out_nh = cv::gimpl::GModel::dataNodeOf(gm, out);
|
||||
|
||||
EXPECT_FALSE(gm.metadata(in0_nh ).contains<cv::gimpl::Island>());
|
||||
EXPECT_FALSE(gm.metadata(in1_nh ).contains<cv::gimpl::Island>());
|
||||
EXPECT_FALSE(gm.metadata(out_nh).contains<cv::gimpl::Island>());
|
||||
EXPECT_TRUE(gm.metadata(tmp_nh).contains<cv::gimpl::Island>());
|
||||
|
||||
auto isl_model = gm.metadata().get<cv::gimpl::IslandModel>().model;
|
||||
cv::gimpl::GIslandModel::ConstGraph gim(*isl_model);
|
||||
|
||||
const auto is_island = [&](ade::NodeHandle nh) {
|
||||
return (cv::gimpl::NodeKind::ISLAND
|
||||
== gim.metadata(nh).get<cv::gimpl::NodeKind>().k);
|
||||
};
|
||||
const std::size_t num_isl = std::count_if(gim.nodes().begin(),
|
||||
gim.nodes().end(),
|
||||
is_island);
|
||||
EXPECT_EQ(1u, num_isl);
|
||||
|
||||
auto isl_nh = cv::gimpl::GIslandModel::producerOf(gim, out_nh);
|
||||
auto isl_obj = gim.metadata(isl_nh).get<cv::gimpl::FusedIsland>().object;
|
||||
|
||||
EXPECT_TRUE(ade::util::contains(isl_obj->contents(), tmp_nh));
|
||||
|
||||
EXPECT_EQ(2u, static_cast<std::size_t>(isl_nh->inNodes().size()));
|
||||
EXPECT_EQ(1u, static_cast<std::size_t>(isl_nh->outNodes().size()));
|
||||
}
|
||||
|
||||
TEST(IslandFusion, DataNodeUsedDifferentBackend)
|
||||
{
|
||||
// Define a computation:
|
||||
//
|
||||
// internal isl isl0
|
||||
// ...........................
|
||||
// (in1) -> :J::Foo--> (tmp) -> J::Foo: --> (out0)
|
||||
// :............|............:
|
||||
// | ........
|
||||
// `---->:S::Baz: --> (out1)
|
||||
// :......:
|
||||
|
||||
// Check that the node was not dropped out of the island
|
||||
// because it is used by the kernel from another backend
|
||||
|
||||
namespace J = Jupiter;
|
||||
namespace S = Saturn;
|
||||
|
||||
cv::GMat in, tmp, out0;
|
||||
cv::GScalar out1;
|
||||
tmp = I::Foo::on(in);
|
||||
out0 = I::Foo::on(tmp);
|
||||
out1 = I::Baz::on(tmp);
|
||||
|
||||
cv::GComputation cc(cv::GIn(in), cv::GOut(out0, out1));
|
||||
|
||||
// Prepare compilation parameters manually
|
||||
const auto in_meta = cv::GMetaArg(cv::GMatDesc{CV_8U,1,cv::Size(32,32)});
|
||||
const auto pkg = cv::gapi::kernels<J::Foo, S::Baz>();
|
||||
|
||||
// Directly instantiate G-API graph compiler and run partial compilation
|
||||
cv::gimpl::GCompiler compiler(cc, {in_meta}, cv::compile_args(pkg));
|
||||
cv::gimpl::GCompiler::GPtr graph = compiler.generateGraph();
|
||||
compiler.runPasses(*graph);
|
||||
|
||||
// Inspect the graph and verify the islands configuration
|
||||
cv::gimpl::GModel::ConstGraph gm(*graph);
|
||||
|
||||
auto in_nh = cv::gimpl::GModel::dataNodeOf(gm, in);
|
||||
auto tmp_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp);
|
||||
auto out0_nh = cv::gimpl::GModel::dataNodeOf(gm, out0);
|
||||
auto out1_nh = cv::gimpl::GModel::dataNodeOf(gm, out1);
|
||||
|
||||
EXPECT_TRUE(gm.metadata(tmp_nh).contains<cv::gimpl::Island>());
|
||||
|
||||
auto isl_model = gm.metadata().get<cv::gimpl::IslandModel>().model;
|
||||
cv::gimpl::GIslandModel::ConstGraph gim(*isl_model);
|
||||
|
||||
auto isl_nh = cv::gimpl::GIslandModel::producerOf(gim, tmp_nh);
|
||||
auto isl_obj = gim.metadata(isl_nh).get<cv::gimpl::FusedIsland>().object;
|
||||
|
||||
EXPECT_TRUE(ade::util::contains(isl_obj->contents(), tmp_nh));
|
||||
|
||||
EXPECT_EQ(2u, static_cast<std::size_t>(isl_nh->outNodes().size()));
|
||||
EXPECT_EQ(7u, static_cast<std::size_t>(gm.nodes().size()));
|
||||
EXPECT_EQ(6u, static_cast<std::size_t>(gim.nodes().size()));
|
||||
}
|
||||
|
||||
TEST(IslandFusion, LoopBetweenDifferentBackends)
|
||||
{
|
||||
// Define a computation:
|
||||
//
|
||||
//
|
||||
// .............................
|
||||
// (in) -> :J::Baz -> (tmp0) -> J::Quux: -> (out0)
|
||||
// | :............|..........^....
|
||||
// | ........ | | ........
|
||||
// `---->:S::Foo: `----------|-------->:S::Qux:-> (out1)
|
||||
// :....|.: | :....^.:
|
||||
// | | |
|
||||
// `-------------- (tmp1) -----------`
|
||||
|
||||
// Kernels S::Foo and S::Qux cannot merge, because there will be a cycle between islands
|
||||
|
||||
namespace J = Jupiter;
|
||||
namespace S = Saturn;
|
||||
|
||||
cv::GScalar tmp0;
|
||||
cv::GMat in, tmp1, out0, out1;
|
||||
|
||||
tmp0 = I::Baz::on(in);
|
||||
tmp1 = I::Foo::on(in);
|
||||
out1 = I::Qux::on(tmp1, tmp0);
|
||||
out0 = I::Quux::on(tmp0, tmp1);
|
||||
|
||||
cv::GComputation cc(cv::GIn(in), cv::GOut(out1, out0));
|
||||
|
||||
// Prepare compilation parameters manually
|
||||
const auto in_meta = cv::GMetaArg(cv::GMatDesc{CV_8U,1,cv::Size(32,32)});
|
||||
const auto pkg = cv::gapi::kernels<J::Baz, J::Quux, S::Foo, S::Qux>();
|
||||
|
||||
// Directly instantiate G-API graph compiler and run partial compilation
|
||||
cv::gimpl::GCompiler compiler(cc, {in_meta}, cv::compile_args(pkg));
|
||||
cv::gimpl::GCompiler::GPtr graph = compiler.generateGraph();
|
||||
compiler.runPasses(*graph);
|
||||
|
||||
cv::gimpl::GModel::ConstGraph gm(*graph);
|
||||
auto isl_model = gm.metadata().get<cv::gimpl::IslandModel>().model;
|
||||
cv::gimpl::GIslandModel::ConstGraph gim(*isl_model);
|
||||
|
||||
auto in_nh = cv::gimpl::GModel::dataNodeOf(gm, in);
|
||||
auto tmp0_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp0);
|
||||
auto tmp1_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp1);
|
||||
auto out0_nh = cv::gimpl::GModel::dataNodeOf(gm, out0);
|
||||
auto out1_nh = cv::gimpl::GModel::dataNodeOf(gm, out1);
|
||||
|
||||
EXPECT_FALSE(gm.metadata(in_nh ).contains<cv::gimpl::Island>());
|
||||
EXPECT_FALSE(gm.metadata(out0_nh).contains<cv::gimpl::Island>());
|
||||
EXPECT_FALSE(gm.metadata(out1_nh).contains<cv::gimpl::Island>());
|
||||
// The node does not belong to the island so as not to form a cycle
|
||||
EXPECT_FALSE(gm.metadata(tmp1_nh).contains<cv::gimpl::Island>());
|
||||
|
||||
EXPECT_TRUE(gm.metadata(tmp0_nh).contains<cv::gimpl::Island>());
|
||||
|
||||
// There should be three islands in the GIslandModel
|
||||
const auto is_island = [&](ade::NodeHandle nh) {
|
||||
return (cv::gimpl::NodeKind::ISLAND
|
||||
== gim.metadata(nh).get<cv::gimpl::NodeKind>().k);
|
||||
};
|
||||
const std::size_t num_isl = std::count_if(gim.nodes().begin(),
|
||||
gim.nodes().end(),
|
||||
is_island);
|
||||
EXPECT_EQ(3u, num_isl);
|
||||
}
|
||||
|
||||
TEST(IslandsFusion, PartionOverlapUserIsland)
|
||||
{
|
||||
// Define a computation:
|
||||
//
|
||||
// internal isl isl0
|
||||
// ........ ........
|
||||
// (in0) -> :J::Foo:--> (tmp) ->:S::Bar: --> (out)
|
||||
// :......: :......:
|
||||
// ^
|
||||
// |
|
||||
// (in1) --------------------------`
|
||||
|
||||
// Check that internal islands doesn't overlap user island
|
||||
|
||||
namespace J = Jupiter;
|
||||
namespace S = Saturn;
|
||||
|
||||
GMat in[2];
|
||||
GMat tmp = I::Foo::on(in[0]);
|
||||
GMat out = I::Bar::on(tmp, in[1]);
|
||||
|
||||
cv::gapi::island("isl0", cv::GIn(tmp, in[1]), cv::GOut(out));
|
||||
cv::GComputation cc(cv::GIn(in[0], in[1]), cv::GOut(out));
|
||||
|
||||
// Prepare compilation parameters manually
|
||||
cv::GMetaArgs in_metas = {GMetaArg(cv::GMatDesc{CV_8U,1,cv::Size(32,32)}),
|
||||
GMetaArg(cv::GMatDesc{CV_8U,1,cv::Size(32,32)})};
|
||||
const auto pkg = cv::gapi::kernels<J::Foo, J::Bar>();
|
||||
|
||||
// Directly instantiate G-API graph compiler and run partial compilation
|
||||
cv::gimpl::GCompiler compiler(cc, std::move(in_metas), cv::compile_args(pkg));
|
||||
cv::gimpl::GCompiler::GPtr graph = compiler.generateGraph();
|
||||
compiler.runPasses(*graph);
|
||||
|
||||
cv::gimpl::GModel::ConstGraph gm(*graph);
|
||||
auto isl_model = gm.metadata().get<cv::gimpl::IslandModel>().model;
|
||||
cv::gimpl::GIslandModel::ConstGraph gim(*isl_model);
|
||||
|
||||
auto in0_nh = cv::gimpl::GModel::dataNodeOf(gm, in[0]);
|
||||
auto in1_nh = cv::gimpl::GModel::dataNodeOf(gm, in[1]);
|
||||
auto tmp_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp);
|
||||
auto out_nh = cv::gimpl::GModel::dataNodeOf(gm, out);
|
||||
|
||||
auto foo_nh = cv::gimpl::GIslandModel::producerOf(gim, tmp_nh);
|
||||
auto foo_obj = gim.metadata(foo_nh).get<cv::gimpl::FusedIsland>().object;
|
||||
|
||||
auto bar_nh = cv::gimpl::GIslandModel::producerOf(gim, out_nh);
|
||||
auto bar_obj = gim.metadata(bar_nh).get<cv::gimpl::FusedIsland>().object;
|
||||
|
||||
EXPECT_FALSE(gm.metadata(in0_nh ).contains<cv::gimpl::Island>());
|
||||
EXPECT_FALSE(gm.metadata(in1_nh ).contains<cv::gimpl::Island>());
|
||||
EXPECT_FALSE(gm.metadata(out_nh).contains<cv::gimpl::Island>());
|
||||
EXPECT_FALSE(gm.metadata(tmp_nh).contains<cv::gimpl::Island>());
|
||||
EXPECT_FALSE(foo_obj->is_user_specified());
|
||||
EXPECT_TRUE(bar_obj->is_user_specified());
|
||||
}
|
||||
|
||||
TEST(IslandsFusion, DISABLED_IslandContainsDifferentBackends)
|
||||
{
|
||||
// Define a computation:
|
||||
//
|
||||
// isl0
|
||||
// ............................
|
||||
// (in0) -> :J::Foo:--> (tmp) -> S::Bar: --> (out)
|
||||
// :..........................:
|
||||
// ^
|
||||
// |
|
||||
// (in1) --------------------------`
|
||||
|
||||
// Try create island contains different backends
|
||||
|
||||
namespace J = Jupiter;
|
||||
namespace S = Saturn;
|
||||
|
||||
GMat in[2];
|
||||
GMat tmp = I::Foo::on(in[0]);
|
||||
GMat out = I::Bar::on(tmp, in[1]);
|
||||
|
||||
cv::gapi::island("isl0", cv::GIn(in[0], in[1]), cv::GOut(out));
|
||||
cv::GComputation cc(cv::GIn(in[0], in[1]), cv::GOut(out));
|
||||
|
||||
// Prepare compilation parameters manually
|
||||
cv::GMetaArgs in_metas = {GMetaArg(cv::GMatDesc{CV_8U,1,cv::Size(32,32)}),
|
||||
GMetaArg(cv::GMatDesc{CV_8U,1,cv::Size(32,32)})};
|
||||
const auto pkg = cv::gapi::kernels<J::Foo, S::Bar>();
|
||||
|
||||
// Directly instantiate G-API graph compiler and run partial compilation
|
||||
cv::gimpl::GCompiler compiler(cc, std::move(in_metas), cv::compile_args(pkg));
|
||||
cv::gimpl::GCompiler::GPtr graph = compiler.generateGraph();
|
||||
EXPECT_ANY_THROW(compiler.runPasses(*graph));
|
||||
}
|
||||
|
||||
TEST(IslandFusion, WithLoop)
|
||||
{
|
||||
namespace J = Jupiter; // see mock_kernels.cpp
|
||||
|
||||
// Define a computation:
|
||||
//
|
||||
// (in) -> J::Foo --> (tmp0) -> J::Foo --> (tmp1) -> J::Qux -> (out)
|
||||
// : ^
|
||||
// '--> J::Baz --> (scl0) --'
|
||||
//
|
||||
// The whole thing should be merged to a single island
|
||||
// There's a cycle warning if Foo/Foo/Qux are merged first
|
||||
// Then this island both produces data for Baz and consumes data
|
||||
// from Baz. This is a cycle and it should be avoided by the merging code.
|
||||
//
|
||||
cv::GMat in;
|
||||
cv::GMat tmp0 = I::Foo::on(in);
|
||||
cv::GMat tmp1 = I::Foo::on(tmp0);
|
||||
cv::GScalar scl0 = I::Baz::on(tmp0);
|
||||
cv::GMat out = I::Qux::on(tmp1, scl0);
|
||||
cv::GComputation cc(in, out);
|
||||
|
||||
// Prepare compilation parameters manually
|
||||
const auto in_meta = cv::GMetaArg(cv::GMatDesc{CV_8U,1,cv::Size(32,32)});
|
||||
const auto pkg = cv::gapi::kernels<J::Foo, J::Baz, J::Qux>();
|
||||
|
||||
// Directly instantiate G-API graph compiler and run partial compilation
|
||||
cv::gimpl::GCompiler compiler(cc, {in_meta}, cv::compile_args(pkg));
|
||||
cv::gimpl::GCompiler::GPtr graph = compiler.generateGraph();
|
||||
compiler.runPasses(*graph);
|
||||
|
||||
// Inspect the graph and verify the islands configuration
|
||||
cv::gimpl::GModel::ConstGraph gm(*graph);
|
||||
|
||||
auto in_nh = cv::gimpl::GModel::dataNodeOf(gm, in);
|
||||
auto tmp0_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp0);
|
||||
auto tmp1_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp1);
|
||||
auto scl0_nh = cv::gimpl::GModel::dataNodeOf(gm, scl0);
|
||||
auto out_nh = cv::gimpl::GModel::dataNodeOf(gm, out);
|
||||
|
||||
// in/out mats shouldn't be assigned to any Island
|
||||
EXPECT_FALSE(gm.metadata(in_nh ).contains<cv::gimpl::Island>());
|
||||
EXPECT_FALSE(gm.metadata(out_nh).contains<cv::gimpl::Island>());
|
||||
|
||||
// tmp0/tmp1/scl should be assigned to island
|
||||
EXPECT_TRUE(gm.metadata(tmp0_nh).contains<cv::gimpl::Island>());
|
||||
EXPECT_TRUE(gm.metadata(tmp1_nh).contains<cv::gimpl::Island>());
|
||||
EXPECT_TRUE(gm.metadata(scl0_nh).contains<cv::gimpl::Island>());
|
||||
|
||||
// Check that there's a single island object and it contains all
|
||||
// that data object handles
|
||||
|
||||
cv::gimpl::GModel::ConstGraph cg(*graph);
|
||||
auto isl_model = cg.metadata().get<cv::gimpl::IslandModel>().model;
|
||||
cv::gimpl::GIslandModel::ConstGraph gim(*isl_model);
|
||||
|
||||
const auto is_island = [&](ade::NodeHandle nh) {
|
||||
return (cv::gimpl::NodeKind::ISLAND
|
||||
== gim.metadata(nh).get<cv::gimpl::NodeKind>().k);
|
||||
};
|
||||
const std::size_t num_isl = std::count_if(gim.nodes().begin(),
|
||||
gim.nodes().end(),
|
||||
is_island);
|
||||
EXPECT_EQ(1u, num_isl);
|
||||
|
||||
auto isl_nh = cv::gimpl::GIslandModel::producerOf(gim, out_nh);
|
||||
auto isl_obj = gim.metadata(isl_nh).get<cv::gimpl::FusedIsland>().object;
|
||||
EXPECT_TRUE(ade::util::contains(isl_obj->contents(), tmp0_nh));
|
||||
EXPECT_TRUE(ade::util::contains(isl_obj->contents(), tmp1_nh));
|
||||
EXPECT_TRUE(ade::util::contains(isl_obj->contents(), scl0_nh));
|
||||
}
|
||||
|
||||
TEST(IslandFusion, Regression_ShouldFuseAll)
|
||||
{
|
||||
// Initially the merge procedure didn't work as expected and
|
||||
// stopped fusion even if it could be continued (e.g. full
|
||||
// GModel graph could be fused into a single GIsland node).
|
||||
// Example of this is custom RGB 2 YUV pipeline as shown below:
|
||||
|
||||
cv::GMat r, g, b;
|
||||
cv::GMat y = 0.299f*r + 0.587f*g + 0.114f*b;
|
||||
cv::GMat u = 0.492f*(b - y);
|
||||
cv::GMat v = 0.877f*(r - y);
|
||||
|
||||
cv::GComputation customCvt({r, g, b}, {y, u, v});
|
||||
|
||||
const auto in_meta = cv::GMetaArg(cv::GMatDesc{CV_8U,1,cv::Size(32,32)});
|
||||
|
||||
// Directly instantiate G-API graph compiler and run partial compilation
|
||||
cv::gimpl::GCompiler compiler(customCvt, {in_meta,in_meta,in_meta}, cv::compile_args());
|
||||
cv::gimpl::GCompiler::GPtr graph = compiler.generateGraph();
|
||||
compiler.runPasses(*graph);
|
||||
|
||||
cv::gimpl::GModel::ConstGraph cg(*graph);
|
||||
auto isl_model = cg.metadata().get<cv::gimpl::IslandModel>().model;
|
||||
cv::gimpl::GIslandModel::ConstGraph gim(*isl_model);
|
||||
|
||||
std::vector<ade::NodeHandle> data_nhs;
|
||||
std::vector<ade::NodeHandle> isl_nhs;
|
||||
for (auto &&nh : gim.nodes())
|
||||
{
|
||||
if (gim.metadata(nh).contains<cv::gimpl::FusedIsland>())
|
||||
isl_nhs.push_back(std::move(nh));
|
||||
else if (gim.metadata(nh).contains<cv::gimpl::DataSlot>())
|
||||
data_nhs.push_back(std::move(nh));
|
||||
else FAIL() << "GIslandModel node with unexpected metadata type";
|
||||
}
|
||||
|
||||
EXPECT_EQ(6u, data_nhs.size()); // 3 input nodes + 3 output nodes
|
||||
EXPECT_EQ(1u, isl_nhs.size()); // 1 island
|
||||
}
|
||||
|
||||
TEST(IslandFusion, Test_Desync_NoFuse)
|
||||
{
|
||||
cv::GMat in;
|
||||
cv::GMat tmp1 = in*0.5f;
|
||||
cv::GMat tmp2 = tmp1 + in;
|
||||
|
||||
cv::GMat tmp3 = cv::gapi::streaming::desync(tmp1);
|
||||
cv::GMat tmp4 = tmp3*0.1f;
|
||||
|
||||
const auto in_meta = cv::GMetaArg(cv::GMatDesc{CV_8U,1,cv::Size(32,32)});
|
||||
cv::GComputation comp(cv::GIn(in), cv::GOut(tmp2, tmp4));
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// 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;
|
||||
|
||||
GCompiler compiler(comp, {in_meta}, cv::compile_args());
|
||||
GCompiler::GPtr graph = compiler.generateGraph();
|
||||
compiler.runPasses(*graph);
|
||||
|
||||
auto isl_model = GModel::ConstGraph(*graph).metadata()
|
||||
.get<IslandModel>().model;
|
||||
GIslandModel::ConstGraph gim(*isl_model);
|
||||
|
||||
const auto is_island = [&](ade::NodeHandle nh) {
|
||||
return (NodeKind::ISLAND == gim.metadata(nh).get<NodeKind>().k);
|
||||
};
|
||||
const auto num_isl = std::count_if(gim.nodes().begin(),
|
||||
gim.nodes().end(),
|
||||
is_island);
|
||||
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;
|
||||
|
||||
GCompiler compiler(comp, {in_meta}, cv::compile_args());
|
||||
GCompiler::GPtr graph = compiler.generateGraph();
|
||||
GModel::Graph(*graph).metadata().set(Streaming{});
|
||||
compiler.runPasses(*graph);
|
||||
|
||||
auto isl_model = GModel::ConstGraph(*graph).metadata()
|
||||
.get<IslandModel>().model;
|
||||
GIslandModel::ConstGraph gim(*isl_model);
|
||||
|
||||
const auto is_island = [&](ade::NodeHandle nh) {
|
||||
return (NodeKind::ISLAND == gim.metadata(nh).get<NodeKind>().k);
|
||||
};
|
||||
const auto num_isl = std::count_if(gim.nodes().begin(),
|
||||
gim.nodes().end(),
|
||||
is_island);
|
||||
EXPECT_EQ(3, num_isl);
|
||||
}
|
||||
}
|
||||
|
||||
// Fixme: add more tests on mixed (hetero) graphs
|
||||
// ADE-222, ADE-223
|
||||
|
||||
// FIXME: add test on combination of user-specified island
|
||||
// which should be heterogeneous (based on kernel availability)
|
||||
// but as we don't support this, compilation should fail
|
||||
|
||||
// FIXME: add tests on automatic inferred islands which are
|
||||
// connected via 1) gmat 2) gscalar 3) garray,
|
||||
// check the case with executor
|
||||
// check the case when this 1/2/3 interim object is also gcomputation output
|
||||
|
||||
} // namespace opencv_test
|
654
3rdparty/opencv-4.5.4/modules/gapi/test/internal/gapi_int_island_tests.cpp
vendored
Normal file
654
3rdparty/opencv-4.5.4/modules/gapi/test/internal/gapi_int_island_tests.cpp
vendored
Normal file
@ -0,0 +1,654 @@
|
||||
// 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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#include "../test_precomp.hpp"
|
||||
|
||||
#include "compiler/gmodel.hpp"
|
||||
#include "compiler/gcompiled_priv.hpp"
|
||||
#include "compiler/gmodel_priv.hpp"
|
||||
|
||||
namespace opencv_test
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Tests on a plain graph
|
||||
//
|
||||
// (in) -> Blur1 -> (tmp0) -> Blur2 -> (tmp1) -> Blur3 -> (tmp2) -> Blur4 -> (out)
|
||||
//
|
||||
namespace
|
||||
{
|
||||
struct PlainIslandsFixture
|
||||
{
|
||||
cv::GMat in;
|
||||
cv::GMat tmp[3];
|
||||
cv::GMat out;
|
||||
|
||||
PlainIslandsFixture()
|
||||
{
|
||||
tmp[0] = cv::gapi::boxFilter(in, -1, cv::Size(3,3));
|
||||
tmp[1] = cv::gapi::boxFilter(tmp[0], -1, cv::Size(3,3));
|
||||
tmp[2] = cv::gapi::boxFilter(tmp[1], -1, cv::Size(3,3));
|
||||
out = cv::gapi::boxFilter(tmp[2], -1, cv::Size(3,3));
|
||||
}
|
||||
};
|
||||
|
||||
struct Islands: public ::testing::Test, public PlainIslandsFixture {};
|
||||
|
||||
using GIntArray = GArray<int>;
|
||||
|
||||
G_TYPED_KERNEL(CreateMatWithDiag, <GMat(GIntArray)>, "test.array.create_mat_with_diag")
|
||||
{
|
||||
static GMatDesc outMeta(const GArrayDesc&) { return cv::GMatDesc{CV_32S, 1,{3, 3}}; }
|
||||
};
|
||||
|
||||
GAPI_OCV_KERNEL(CreateMatWithDiagImpl, CreateMatWithDiag)
|
||||
{
|
||||
static void run(const std::vector<int> &in, cv::Mat& out)
|
||||
{
|
||||
auto size = static_cast<int>(in.size());
|
||||
out = Mat::zeros(size, size, CV_32SC1);
|
||||
for(int i = 0; i < out.rows; i++)
|
||||
{
|
||||
auto* row = out.ptr<int>(i);
|
||||
row[i] = in[i];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
G_TYPED_KERNEL(Mat2Array, <GIntArray(GMat)>, "test.array.mat2array")
|
||||
{
|
||||
static GArrayDesc outMeta(const GMatDesc&) { return empty_array_desc(); }
|
||||
};
|
||||
|
||||
GAPI_OCV_KERNEL(Mat2ArrayImpl, Mat2Array)
|
||||
{
|
||||
static void run(const cv::Mat& in, std::vector<int> &out)
|
||||
{
|
||||
GAPI_Assert(in.depth() == CV_32S && in.isContinuous());
|
||||
out.reserve(in.cols * in.rows);
|
||||
out.assign((int*)in.datastart, (int*)in.dataend);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
TEST_F(Islands, SmokeTest)
|
||||
{
|
||||
// (in) -> Blur1 -> (tmp0) -> Blur2 -> (tmp1) -> Blur3 -> (tmp2) -> Blur4 -> (out)
|
||||
// : "test" :
|
||||
// :<------------------------->:
|
||||
cv::gapi::island("test", cv::GIn(tmp[0]), cv::GOut(tmp[2]));
|
||||
auto cc = cv::GComputation(in, out).compile(cv::GMatDesc{CV_8U,1,{640,480}});
|
||||
|
||||
const auto &gm = cc.priv().model();
|
||||
const auto tmp0_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[0]);
|
||||
const auto tmp1_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[1]);
|
||||
const auto tmp2_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[2]);
|
||||
|
||||
// tmp1 and tmp3 is not a part of any island
|
||||
EXPECT_FALSE(gm.metadata(tmp0_nh).contains<cv::gimpl::Island>());
|
||||
EXPECT_FALSE(gm.metadata(tmp2_nh).contains<cv::gimpl::Island>());
|
||||
|
||||
// tmp2 is part of "test" island
|
||||
EXPECT_TRUE(gm.metadata(tmp1_nh).contains<cv::gimpl::Island>());
|
||||
EXPECT_EQ("test", gm.metadata(tmp1_nh).get<cv::gimpl::Island>().island);
|
||||
}
|
||||
|
||||
TEST_F(Islands, TwoIslands)
|
||||
{
|
||||
// (in) -> Blur1 -> (tmp0) -> Blur2 -> (tmp1) -> Blur3 -> (tmp2) -> Blur4 -> (out)
|
||||
// : "test1" : : "test2" :
|
||||
// :<---------------------------->: :<--------------------------------->
|
||||
EXPECT_NO_THROW(cv::gapi::island("test1", cv::GIn(in), cv::GOut(tmp[1])));
|
||||
EXPECT_NO_THROW(cv::gapi::island("test2", cv::GIn(tmp[1]), cv::GOut(out)));
|
||||
|
||||
auto cc = cv::GComputation(in, out).compile(cv::GMatDesc{CV_8U,1,{640,480}});
|
||||
const auto &gm = cc.priv().model();
|
||||
const auto in_nh = cv::gimpl::GModel::dataNodeOf(gm, in);
|
||||
const auto tmp0_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[0]);
|
||||
const auto tmp1_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[1]);
|
||||
const auto tmp2_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[2]);
|
||||
const auto out_nh = cv::gimpl::GModel::dataNodeOf(gm, out);
|
||||
|
||||
// Only tmp0 and tmp2 should be listed in islands.
|
||||
EXPECT_TRUE (gm.metadata(tmp0_nh).contains<cv::gimpl::Island>());
|
||||
EXPECT_TRUE (gm.metadata(tmp2_nh).contains<cv::gimpl::Island>());
|
||||
EXPECT_FALSE(gm.metadata(in_nh) .contains<cv::gimpl::Island>());
|
||||
EXPECT_FALSE(gm.metadata(tmp1_nh).contains<cv::gimpl::Island>());
|
||||
EXPECT_FALSE(gm.metadata(out_nh) .contains<cv::gimpl::Island>());
|
||||
|
||||
EXPECT_EQ("test1", gm.metadata(tmp0_nh).get<cv::gimpl::Island>().island);
|
||||
EXPECT_EQ("test2", gm.metadata(tmp2_nh).get<cv::gimpl::Island>().island);
|
||||
}
|
||||
|
||||
// FIXME: Disabled since currently merge procedure merges two into one
|
||||
// successfully
|
||||
TEST_F(Islands, DISABLED_Two_Islands_With_Same_Name_Should_Fail)
|
||||
{
|
||||
// (in) -> Blur1 -> (tmp0) -> Blur2 -> (tmp1) -> Blur3 -> (tmp2) -> Blur4 -> (out)
|
||||
// : "test1" : : "test1" :
|
||||
// :<---------------------------->: :<--------------------------------->
|
||||
|
||||
EXPECT_NO_THROW(cv::gapi::island("test1", cv::GIn(in), cv::GOut(tmp[1])));
|
||||
EXPECT_NO_THROW(cv::gapi::island("test1", cv::GIn(tmp[1]), cv::GOut(out)));
|
||||
|
||||
EXPECT_ANY_THROW(cv::GComputation(in, out).compile(cv::GMatDesc{CV_8U,1,{640,480}}));
|
||||
}
|
||||
|
||||
|
||||
// (in) -> Blur1 -> (tmp0) -> Blur2 -> (tmp1) -> Blur3 -> (tmp2) -> Blur4 -> (out)
|
||||
// : "test1": : :
|
||||
// :<----------------:----------->: :
|
||||
// : :
|
||||
// : "test2" :
|
||||
// :<------------------------->:
|
||||
TEST_F(Islands, OverlappingIslands1)
|
||||
{
|
||||
EXPECT_NO_THROW (cv::gapi::island("test1", cv::GIn(in), cv::GOut(tmp[1])));
|
||||
EXPECT_ANY_THROW(cv::gapi::island("test2", cv::GIn(tmp[0]), cv::GOut(tmp[2])));
|
||||
}
|
||||
|
||||
TEST_F(Islands, OverlappingIslands2)
|
||||
{
|
||||
EXPECT_NO_THROW (cv::gapi::island("test2", cv::GIn(tmp[0]), cv::GOut(tmp[2])));
|
||||
EXPECT_ANY_THROW(cv::gapi::island("test1", cv::GIn(in), cv::GOut(tmp[1])));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Tests on a complex graph
|
||||
//
|
||||
// (in0) -> Not -> (tmp0) --> Add ---------> (tmp2) --> AddC -------> (out0)
|
||||
// ^ ^
|
||||
// (in1) -> Blur -> (tmp1) ----'--> Sum ----> (scl0) ----'
|
||||
// :
|
||||
// `------------> Median -> (tmp3) --> Blur -------> (out1)
|
||||
//
|
||||
namespace
|
||||
{
|
||||
struct ComplexIslandsFixture
|
||||
{
|
||||
cv::GMat in[2];
|
||||
cv::GMat tmp[4];
|
||||
cv::GScalar scl;
|
||||
cv::GMat out[2];
|
||||
|
||||
ComplexIslandsFixture()
|
||||
{
|
||||
tmp[0] = cv::gapi::bitwise_not(in[0]);
|
||||
tmp[1] = cv::gapi::boxFilter(in[1], -1, cv::Size(3,3));
|
||||
tmp[2] = tmp[0] + tmp[1]; // FIXME: handle tmp[2] = tmp[0]+tmp[2] typo
|
||||
scl = cv::gapi::sum(tmp[1]);
|
||||
tmp[3] = cv::gapi::medianBlur(tmp[1], 3);
|
||||
out[0] = tmp[2] + scl;
|
||||
out[1] = cv::gapi::boxFilter(tmp[3], -1, cv::Size(3,3));
|
||||
}
|
||||
};
|
||||
|
||||
struct ComplexIslands: public ::testing::Test, public ComplexIslandsFixture {};
|
||||
} // namespace
|
||||
|
||||
TEST_F(ComplexIslands, SmokeTest)
|
||||
{
|
||||
// isl0 #internal1
|
||||
// ........................... ........
|
||||
// (in0) -> Not -> (tmp0) --> Add ---------> (tmp2) --> AddC -------> (out0)
|
||||
// :............ ........^...: :.^....:
|
||||
// ... : :
|
||||
// (in1) -> Blur -> (tmp1) ----'--> Sum ----> (scl0) ----'
|
||||
// : isl1
|
||||
// : ..............................
|
||||
// `------------> Median -> (tmp3) --> Blur -------> (out1)
|
||||
// :............................:
|
||||
|
||||
cv::gapi::island("isl0", cv::GIn(in[0], tmp[1]), cv::GOut(tmp[2]));
|
||||
cv::gapi::island("isl1", cv::GIn(tmp[1]), cv::GOut(out[1]));
|
||||
auto cc = cv::GComputation(cv::GIn(in[0], in[1]), cv::GOut(out[0], out[1]))
|
||||
.compile(cv::GMatDesc{CV_8U,1,{640,480}},
|
||||
cv::GMatDesc{CV_8U,1,{640,480}});
|
||||
const auto &gm = cc.priv().model();
|
||||
const auto in0_nh = cv::gimpl::GModel::dataNodeOf(gm, in[0]);
|
||||
const auto in1_nh = cv::gimpl::GModel::dataNodeOf(gm, in[1]);
|
||||
const auto tmp0_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[0]);
|
||||
const auto tmp1_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[1]);
|
||||
const auto tmp2_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[2]);
|
||||
const auto tmp3_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[3]);
|
||||
const auto scl_nh = cv::gimpl::GModel::dataNodeOf(gm, scl);
|
||||
const auto out0_nh = cv::gimpl::GModel::dataNodeOf(gm, out[0]);
|
||||
const auto out1_nh = cv::gimpl::GModel::dataNodeOf(gm, out[1]);
|
||||
|
||||
// tmp0, tmp3 are in islands, others are not
|
||||
EXPECT_TRUE(gm.metadata(tmp0_nh) .contains<cv::gimpl::Island>()); // isl0
|
||||
EXPECT_TRUE(gm.metadata(tmp3_nh) .contains<cv::gimpl::Island>()); // isl1
|
||||
EXPECT_FALSE(gm.metadata(in0_nh) .contains<cv::gimpl::Island>()); // (input is never fused)
|
||||
EXPECT_FALSE(gm.metadata(in1_nh) .contains<cv::gimpl::Island>()); // (input is never fused)
|
||||
EXPECT_TRUE (gm.metadata(tmp1_nh).contains<cv::gimpl::Island>()); // <internal island>
|
||||
EXPECT_FALSE(gm.metadata(tmp2_nh).contains<cv::gimpl::Island>()); // #not fused as cycle-causing#
|
||||
EXPECT_FALSE(gm.metadata(scl_nh) .contains<cv::gimpl::Island>()); // #not fused as cycle-causing#
|
||||
EXPECT_FALSE(gm.metadata(out0_nh).contains<cv::gimpl::Island>()); // (output is never fused)
|
||||
EXPECT_FALSE(gm.metadata(out1_nh).contains<cv::gimpl::Island>()); // (output is never fused)
|
||||
|
||||
EXPECT_EQ("isl0", gm.metadata(tmp0_nh).get<cv::gimpl::Island>().island);
|
||||
EXPECT_EQ("isl1", gm.metadata(tmp3_nh).get<cv::gimpl::Island>().island);
|
||||
|
||||
EXPECT_NE("isl0", gm.metadata(tmp1_nh).get<cv::gimpl::Island>().island);
|
||||
EXPECT_NE("isl1", gm.metadata(tmp1_nh).get<cv::gimpl::Island>().island);
|
||||
|
||||
// FIXME: Add a test with same graph for Fusion and check GIslandModel
|
||||
}
|
||||
|
||||
TEST_F(ComplexIslands, DistinictIslandsWithSameName)
|
||||
{
|
||||
// isl0
|
||||
// ...........................
|
||||
// (in0) -> Not -> (tmp0) --> Add ---------> (tmp2) --> AddC -------> (out0)
|
||||
// :............ ........^...: ^
|
||||
// ... : :
|
||||
// (in1) -> Blur -> (tmp1) ----'--> Sum ----> (scl0) ----'
|
||||
// : isl0
|
||||
// : ..............................
|
||||
// `------------> Median -> (tmp3) --> Blur -------> (out1)
|
||||
// :............................:
|
||||
|
||||
cv::gapi::island("isl0", cv::GIn(in[0], tmp[1]), cv::GOut(tmp[2]));
|
||||
cv::gapi::island("isl0", cv::GIn(tmp[1]), cv::GOut(out[1]));
|
||||
|
||||
auto cc = cv::GComputation(cv::GIn(in[0], in[1]), cv::GOut(out[0], out[1]));
|
||||
|
||||
EXPECT_ANY_THROW(cc.compile(cv::GMatDesc{CV_8U,1,{640,480}},
|
||||
cv::GMatDesc{CV_8U,1,{640,480}}));
|
||||
}
|
||||
|
||||
TEST_F(ComplexIslands, FullGraph)
|
||||
{
|
||||
cv::gapi::island("isl0", cv::GIn(in[0], in[1]), cv::GOut(out[0], out[1]));
|
||||
auto cc = cv::GComputation(cv::GIn(in[0], in[1]), cv::GOut(out[0], out[1]))
|
||||
.compile(cv::GMatDesc{CV_8U,1,{640,480}},
|
||||
cv::GMatDesc{CV_8U,1,{640,480}});
|
||||
const auto &gm = cc.priv().model();
|
||||
std::vector<ade::NodeHandle> handles_inside = {
|
||||
cv::gimpl::GModel::dataNodeOf(gm, tmp[0]),
|
||||
cv::gimpl::GModel::dataNodeOf(gm, tmp[1]),
|
||||
cv::gimpl::GModel::dataNodeOf(gm, tmp[2]),
|
||||
cv::gimpl::GModel::dataNodeOf(gm, tmp[3]),
|
||||
cv::gimpl::GModel::dataNodeOf(gm, scl),
|
||||
};
|
||||
std::vector<ade::NodeHandle> handles_outside = {
|
||||
cv::gimpl::GModel::dataNodeOf(gm, in[0]),
|
||||
cv::gimpl::GModel::dataNodeOf(gm, in[1]),
|
||||
cv::gimpl::GModel::dataNodeOf(gm, out[0]),
|
||||
cv::gimpl::GModel::dataNodeOf(gm, out[1]),
|
||||
};
|
||||
|
||||
for (auto nh_inside : handles_inside)
|
||||
{
|
||||
EXPECT_EQ("isl0", gm.metadata(nh_inside).get<cv::gimpl::Island>().island);
|
||||
}
|
||||
for (auto nh_outside : handles_outside)
|
||||
{
|
||||
EXPECT_FALSE(gm.metadata(nh_outside).contains<cv::gimpl::Island>());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ComplexIslands, ViaScalar)
|
||||
{
|
||||
//
|
||||
// .........................................#internal0.
|
||||
// (in0) -> Not -> (tmp0) --> Add ---------> (tmp2) --> AddC -------> (out0)
|
||||
// :....................^.........................^...:
|
||||
// : :
|
||||
// .....................:.........(isl0). :
|
||||
// (in1) -> Blur -> (tmp1) ----'--> Sum ----> (scl0) ----'
|
||||
// :..........:.........................:
|
||||
// :
|
||||
// : ..................#internal1.
|
||||
// `------------> Median -> (tmp3) --> Blur -------> (out1)
|
||||
// :...........................:
|
||||
|
||||
cv::gapi::island("isl0", cv::GIn(in[1]), cv::GOut(scl));
|
||||
auto cc = cv::GComputation(cv::GIn(in[0], in[1]), cv::GOut(out[0], out[1]))
|
||||
.compile(cv::GMatDesc{CV_8U,1,{640,480}},
|
||||
cv::GMatDesc{CV_8U,1,{640,480}});
|
||||
const auto &gm = cc.priv().model();
|
||||
|
||||
const auto tmp0_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[0]);
|
||||
const auto tmp1_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[1]);
|
||||
const auto tmp2_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[2]);
|
||||
const auto tmp3_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[3]);
|
||||
|
||||
EXPECT_NE("isl0", gm.metadata(tmp0_nh).get<cv::gimpl::Island>().island); // <internal>
|
||||
EXPECT_EQ("isl0", gm.metadata(tmp1_nh).get<cv::gimpl::Island>().island); // isl0
|
||||
EXPECT_NE("isl0", gm.metadata(tmp2_nh).get<cv::gimpl::Island>().island); // <internal>
|
||||
EXPECT_NE("isl0", gm.metadata(tmp3_nh).get<cv::gimpl::Island>().island); // <internal>
|
||||
|
||||
std::vector<ade::NodeHandle> handles_outside = {
|
||||
cv::gimpl::GModel::dataNodeOf(gm, in[0]),
|
||||
cv::gimpl::GModel::dataNodeOf(gm, in[1]),
|
||||
cv::gimpl::GModel::dataNodeOf(gm, scl),
|
||||
cv::gimpl::GModel::dataNodeOf(gm, out[0]),
|
||||
cv::gimpl::GModel::dataNodeOf(gm, out[1]),
|
||||
};
|
||||
for (auto nh_outside : handles_outside)
|
||||
{
|
||||
EXPECT_FALSE(gm.metadata(nh_outside).contains<cv::gimpl::Island>());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ComplexIslands, BorderDataIsland)
|
||||
{
|
||||
// .................................(isl0)..
|
||||
// : :
|
||||
// (in0) -> Not -> (tmp0) --> Add ---------> (tmp2) --> AddC -------> (out0)
|
||||
// : ^ : ^
|
||||
// : : : :
|
||||
// (in1) -> Blur -> (tmp1) ----'--> Sum ----> (scl0) ----'
|
||||
// :...........:...........................:
|
||||
// : : :
|
||||
// : : :.........................................(isl1)..
|
||||
// : `------------> Median -> (tmp3) --> Blur -------> (out1)
|
||||
// : :
|
||||
// :......................................................:
|
||||
|
||||
cv::gapi::island("isl0", cv::GIn(in[0], in[1]), cv::GOut(tmp[2], scl));
|
||||
cv::gapi::island("isl1", cv::GIn(tmp[1]), cv::GOut(out[1]));
|
||||
|
||||
auto cc = cv::GComputation(cv::GIn(in[0], in[1]), cv::GOut(out[0], out[1]))
|
||||
.compile(cv::GMatDesc{CV_8U,1,{640,480}},
|
||||
cv::GMatDesc{CV_8U,1,{640,480}});
|
||||
const auto &gm = cc.priv().model();
|
||||
const auto in0_nh = cv::gimpl::GModel::dataNodeOf(gm, in[0]);
|
||||
const auto in1_nh = cv::gimpl::GModel::dataNodeOf(gm, in[1]);
|
||||
const auto tmp0_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[0]);
|
||||
const auto tmp1_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[1]);
|
||||
const auto tmp2_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[2]);
|
||||
const auto tmp3_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[3]);
|
||||
const auto scl_nh = cv::gimpl::GModel::dataNodeOf(gm, scl);
|
||||
const auto out0_nh = cv::gimpl::GModel::dataNodeOf(gm, out[0]);
|
||||
const auto out1_nh = cv::gimpl::GModel::dataNodeOf(gm, out[1]);
|
||||
|
||||
// Check handles inside isl0
|
||||
EXPECT_EQ("isl0", gm.metadata(tmp0_nh).get<cv::gimpl::Island>().island);
|
||||
EXPECT_EQ("isl0", gm.metadata(tmp1_nh).get<cv::gimpl::Island>().island);
|
||||
// ^^^ Important - tmp1 is assigned to isl0, not isl1
|
||||
|
||||
// Check handles inside isl1
|
||||
EXPECT_EQ("isl1", gm.metadata(tmp3_nh).get<cv::gimpl::Island>().island);
|
||||
|
||||
// Check outside handles
|
||||
EXPECT_FALSE(gm.metadata(in0_nh) .contains<cv::gimpl::Island>());
|
||||
EXPECT_FALSE(gm.metadata(in1_nh) .contains<cv::gimpl::Island>());
|
||||
EXPECT_FALSE(gm.metadata(tmp2_nh).contains<cv::gimpl::Island>());
|
||||
EXPECT_FALSE(gm.metadata(scl_nh) .contains<cv::gimpl::Island>());
|
||||
EXPECT_FALSE(gm.metadata(out0_nh).contains<cv::gimpl::Island>());
|
||||
EXPECT_FALSE(gm.metadata(out1_nh).contains<cv::gimpl::Island>());
|
||||
}
|
||||
|
||||
|
||||
TEST_F(ComplexIslands, IncompleteSpec)
|
||||
{
|
||||
// isl0
|
||||
// ...........................
|
||||
// (in0) -> Not -> (tmp0) --> Add ---------> (tmp2) --> AddC -------> (out0)
|
||||
// :...........xxx.......^...: ^
|
||||
// : :
|
||||
// (in1) -> Blur -> (tmp1) ----'--> Sum ----> (scl0) ----'
|
||||
// :
|
||||
// :
|
||||
// `------------> Median -> (tmp3) --> Blur -------> (out1)
|
||||
//
|
||||
|
||||
// tmp1 is missing in the below spec
|
||||
EXPECT_ANY_THROW(cv::gapi::island("isl0", cv::GIn(in[0]), cv::GOut(tmp[2])));
|
||||
|
||||
// empty range
|
||||
EXPECT_ANY_THROW(cv::gapi::island("isl1", cv::GIn(tmp[2]), cv::GOut(tmp[2])));
|
||||
}
|
||||
|
||||
TEST_F(ComplexIslands, InputOperationFromDifferentIslands)
|
||||
{
|
||||
// isl1
|
||||
// ........................... ........
|
||||
// (in0)--> Not -> (tmp0) --> Add :--------> (tmp2)-->: AddC : -------> (out0)
|
||||
// :......................^..: : ^ :
|
||||
// isl0 : : : :
|
||||
// .......................:....................... : :
|
||||
// (in1) :-> Blur -> (tmp1) ----'--> Sum ----> (scl0) ----- :
|
||||
// :....................................................:
|
||||
// isl0 :
|
||||
// `------------> Median -> (tmp3) --> Blur -------> (out1)
|
||||
//
|
||||
|
||||
cv::gapi::island("isl0", cv::GIn(in[1], tmp[2]), cv::GOut(out[0]));
|
||||
cv::gapi::island("isl1", cv::GIn(in[0], tmp[1]), cv::GOut(tmp[2]));
|
||||
auto cc = cv::GComputation(cv::GIn(in[0], in[1]), cv::GOut(out[0], out[1]))
|
||||
.compile(cv::GMatDesc{CV_8U,1,{640,480}},
|
||||
cv::GMatDesc{CV_8U,1,{640,480}});
|
||||
|
||||
const auto &gm = cc.priv().model();
|
||||
const auto tmp0_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[0]);
|
||||
const auto tmp1_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[1]);
|
||||
const auto tmp2_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[2]);
|
||||
|
||||
EXPECT_EQ("isl1", gm.metadata(tmp0_nh).get<cv::gimpl::Island>().island);
|
||||
EXPECT_EQ("isl0", gm.metadata(tmp1_nh).get<cv::gimpl::Island>().island);
|
||||
EXPECT_FALSE(gm.metadata(tmp2_nh).contains<cv::gimpl::Island>());
|
||||
}
|
||||
|
||||
TEST_F(ComplexIslands, NoWayBetweenNodes)
|
||||
{
|
||||
// (in0) -> Not -> (tmp0) --> Add ---------> (tmp2) --> AddC -------> (out0)
|
||||
// ^ ^
|
||||
// (in1) -> Blur -> (tmp1) ----'--> Sum ----> (scl0) ----'
|
||||
// :
|
||||
// `------------> Median -> (tmp3) --> Blur -------> (out1)
|
||||
|
||||
EXPECT_ANY_THROW(cv::gapi::island("isl0", cv::GIn(in[1]), cv::GOut(tmp[0])));
|
||||
}
|
||||
|
||||
TEST_F(ComplexIslands, IslandsContainUnusedPart)
|
||||
{
|
||||
// Unused part of the graph
|
||||
// x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x
|
||||
// x x
|
||||
// x(in0) -> Not -> (tmp0) --> Add ---------> (tmp2)---> AddC ---------> (out0) x
|
||||
// x ^ ^ x
|
||||
// x x x x x x x x x x x x x x x | x x | x
|
||||
// | x | x
|
||||
// ...... | x | x
|
||||
// (in1) -> :Blur:----------> (tmp1) x-----> Sum ------> (scl0) x
|
||||
// ...... : x x x x x x x x x x x x x x x x x x x x x x x x
|
||||
// isl0
|
||||
// :
|
||||
// `------------> Median -> (tmp3) --> Blur -------> (out1)
|
||||
|
||||
cv::gapi::island("isl0", cv::GIn(in[1]), cv::GOut(scl));
|
||||
auto cc = cv::GComputation(cv::GIn(in[1]), cv::GOut(out[1]))
|
||||
.compile(cv::GMatDesc{CV_8U,1,{640,480}});
|
||||
|
||||
const auto &gm = cc.priv().model();
|
||||
const auto tmp1_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[1]);
|
||||
|
||||
//The output 0 is not specified in the graph
|
||||
//means that there will not be a node scl, so that tmp1 will not assign to the island
|
||||
// FIXME Check that blur assigned to island using the function producerOf
|
||||
// After merge islands fusion
|
||||
EXPECT_FALSE(gm.metadata(tmp1_nh) .contains<cv::gimpl::Island>());
|
||||
}
|
||||
|
||||
TEST_F(ComplexIslands, FullGraphInTwoIslands)
|
||||
{
|
||||
// isl0
|
||||
// ..................................................
|
||||
// (in0) -> :Not -> (tmp0) --> Add ---------> (tmp2) --> AddC: -------> (out0)
|
||||
// ...................^.... ^ :
|
||||
// ............... | : : :
|
||||
// (in1) -> :Blur-> (tmp1):----'-->:Sum ----> (scl0) ----' :
|
||||
// ........ | : ...........................
|
||||
// isl1 : | :............................................
|
||||
// : `------------> Median -> (tmp3) --> Blur ------->:(out1)
|
||||
// ....................................................
|
||||
|
||||
cv::gapi::island("isl0", cv::GIn(in[0], tmp[1]), cv::GOut(out[0]));
|
||||
cv::gapi::island("isl1", cv::GIn(in[1]), cv::GOut(out[1]));
|
||||
auto cc = cv::GComputation(cv::GIn(in[0], in[1]), cv::GOut(out[0], out[1]))
|
||||
.compile(cv::GMatDesc{CV_8U,1,{640,480}},
|
||||
cv::GMatDesc{CV_8U,1,{640,480}});
|
||||
|
||||
const auto &gm = cc.priv().model();
|
||||
const auto in0_nh = cv::gimpl::GModel::dataNodeOf(gm, in[0]);
|
||||
const auto in1_nh = cv::gimpl::GModel::dataNodeOf(gm, in[1]);
|
||||
const auto tmp0_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[0]);
|
||||
const auto tmp1_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[1]);
|
||||
const auto tmp2_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[2]);
|
||||
const auto tmp3_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[3]);
|
||||
const auto scl_nh = cv::gimpl::GModel::dataNodeOf(gm, scl);
|
||||
const auto out0_nh = cv::gimpl::GModel::dataNodeOf(gm, out[0]);
|
||||
const auto out1_nh = cv::gimpl::GModel::dataNodeOf(gm, out[1]);
|
||||
|
||||
// Check handles inside isl0
|
||||
EXPECT_EQ("isl0", gm.metadata(tmp0_nh).get<cv::gimpl::Island>().island);
|
||||
EXPECT_EQ("isl0", gm.metadata(tmp2_nh).get<cv::gimpl::Island>().island);
|
||||
EXPECT_EQ("isl0", gm.metadata(scl_nh).get<cv::gimpl::Island>().island);
|
||||
|
||||
// Check handles inside isl1
|
||||
EXPECT_EQ("isl1", gm.metadata(tmp1_nh).get<cv::gimpl::Island>().island);
|
||||
EXPECT_EQ("isl1", gm.metadata(tmp3_nh).get<cv::gimpl::Island>().island);
|
||||
|
||||
// Check outside handles
|
||||
EXPECT_FALSE(gm.metadata(in0_nh) .contains<cv::gimpl::Island>());
|
||||
EXPECT_FALSE(gm.metadata(in1_nh) .contains<cv::gimpl::Island>());
|
||||
EXPECT_FALSE(gm.metadata(out0_nh).contains<cv::gimpl::Island>());
|
||||
EXPECT_FALSE(gm.metadata(out1_nh).contains<cv::gimpl::Island>());
|
||||
}
|
||||
|
||||
TEST_F(ComplexIslands, OnlyOperationsAssignedToIslands)
|
||||
{
|
||||
cv::gapi::island("isl0", cv::GIn(in[1]), cv::GOut(tmp[1]));
|
||||
cv::gapi::island("isl1", cv::GIn(tmp[1]), cv::GOut(scl));
|
||||
cv::gapi::island("isl2", cv::GIn(scl, tmp[2]), cv::GOut(out[0]));
|
||||
cv::gapi::island("isl3", cv::GIn(in[0]), cv::GOut(tmp[0]));
|
||||
cv::gapi::island("isl4", cv::GIn(tmp[0], tmp[1]), cv::GOut(tmp[2]));
|
||||
cv::gapi::island("isl5", cv::GIn(tmp[1]), cv::GOut(tmp[3]));
|
||||
cv::gapi::island("isl6", cv::GIn(tmp[3]), cv::GOut(out[1]));
|
||||
|
||||
auto cc = cv::GComputation(cv::GIn(in[0], in[1]), cv::GOut(out[0], out[1]))
|
||||
.compile(cv::GMatDesc{CV_8U,1,{640,480}},
|
||||
cv::GMatDesc{CV_8U,1,{640,480}});
|
||||
|
||||
const auto &gm = cc.priv().model();
|
||||
//FIXME: Check that operation handles are really assigned to isl0..isl6
|
||||
const auto in0_nh = cv::gimpl::GModel::dataNodeOf(gm, in[0]);
|
||||
const auto in1_nh = cv::gimpl::GModel::dataNodeOf(gm, in[1]);
|
||||
const auto tmp0_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[0]);
|
||||
const auto tmp1_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[1]);
|
||||
const auto tmp2_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[2]);
|
||||
const auto tmp3_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp[3]);
|
||||
const auto scl_nh = cv::gimpl::GModel::dataNodeOf(gm, scl);
|
||||
const auto out0_nh = cv::gimpl::GModel::dataNodeOf(gm, out[0]);
|
||||
const auto out1_nh = cv::gimpl::GModel::dataNodeOf(gm, out[1]);
|
||||
|
||||
EXPECT_FALSE(gm.metadata(in0_nh) .contains<cv::gimpl::Island>());
|
||||
EXPECT_FALSE(gm.metadata(in1_nh) .contains<cv::gimpl::Island>());
|
||||
EXPECT_FALSE(gm.metadata(tmp0_nh) .contains<cv::gimpl::Island>());
|
||||
EXPECT_FALSE(gm.metadata(tmp1_nh) .contains<cv::gimpl::Island>());
|
||||
EXPECT_FALSE(gm.metadata(tmp2_nh) .contains<cv::gimpl::Island>());
|
||||
EXPECT_FALSE(gm.metadata(tmp3_nh) .contains<cv::gimpl::Island>());
|
||||
EXPECT_FALSE(gm.metadata(scl_nh) .contains<cv::gimpl::Island>());
|
||||
EXPECT_FALSE(gm.metadata(out0_nh).contains<cv::gimpl::Island>());
|
||||
EXPECT_FALSE(gm.metadata(out1_nh).contains<cv::gimpl::Island>());
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
struct IslandStructureWithGArray
|
||||
{
|
||||
GIntArray in, out;
|
||||
GMat tmp;
|
||||
|
||||
IslandStructureWithGArray()
|
||||
{
|
||||
tmp = CreateMatWithDiag::on(in);
|
||||
out = Mat2Array::on(tmp);
|
||||
}
|
||||
};
|
||||
|
||||
struct IslandsWithGArray: public ::testing::Test, public IslandStructureWithGArray {};
|
||||
} // namespace
|
||||
|
||||
TEST_F(IslandsWithGArray, IslandWithGArrayAsInput)
|
||||
{
|
||||
cv::gapi::island("isl0", cv::GIn(in), cv::GOut(tmp));
|
||||
|
||||
const auto pkg = cv::gapi::kernels<CreateMatWithDiagImpl, Mat2ArrayImpl>();
|
||||
auto cc = cv::GComputation(cv::GIn(in), GOut(out)).compile(cv::empty_array_desc(), cv::compile_args(pkg));
|
||||
const auto &gm = cc.priv().model();
|
||||
|
||||
const auto in_nh = cv::gimpl::GModel::dataNodeOf(gm, in.strip());
|
||||
const auto out_nh = cv::gimpl::GModel::dataNodeOf(gm, out.strip());
|
||||
const auto tmp_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp);
|
||||
GAPI_Assert(tmp_nh->inNodes().size() == 1);
|
||||
const auto create_diag_mat_nh = tmp_nh->inNodes().front();
|
||||
|
||||
EXPECT_EQ("isl0", gm.metadata(create_diag_mat_nh).get<cv::gimpl::Island>().island);
|
||||
EXPECT_FALSE(gm.metadata(in_nh) .contains<cv::gimpl::Island>());
|
||||
EXPECT_FALSE(gm.metadata(out_nh) .contains<cv::gimpl::Island>());
|
||||
EXPECT_FALSE(gm.metadata(tmp_nh) .contains<cv::gimpl::Island>());
|
||||
}
|
||||
|
||||
TEST_F(IslandsWithGArray, IslandWithGArrayAsOutput)
|
||||
{
|
||||
cv::gapi::island("isl0", cv::GIn(tmp), cv::GOut(out));
|
||||
|
||||
const auto pkg = cv::gapi::kernels<CreateMatWithDiagImpl, Mat2ArrayImpl>();
|
||||
auto cc = cv::GComputation(cv::GIn(in), GOut(out)).compile(cv::empty_array_desc(), cv::compile_args(pkg));
|
||||
const auto &gm = cc.priv().model();
|
||||
|
||||
const auto in_nh = cv::gimpl::GModel::dataNodeOf(gm, in.strip());
|
||||
const auto out_nh = cv::gimpl::GModel::dataNodeOf(gm, out.strip());
|
||||
const auto tmp_nh = cv::gimpl::GModel::dataNodeOf(gm, tmp);
|
||||
GAPI_Assert(tmp_nh->inNodes().size() == 1);
|
||||
const auto mat2array_nh = out_nh->inNodes().front();
|
||||
|
||||
EXPECT_EQ("isl0", gm.metadata(mat2array_nh).get<cv::gimpl::Island>().island);
|
||||
EXPECT_FALSE(gm.metadata(in_nh) .contains<cv::gimpl::Island>());
|
||||
EXPECT_FALSE(gm.metadata(out_nh) .contains<cv::gimpl::Island>());
|
||||
EXPECT_FALSE(gm.metadata(tmp_nh) .contains<cv::gimpl::Island>());
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Wrong input tests on island name
|
||||
//
|
||||
namespace
|
||||
{
|
||||
struct CheckName : public TestWithParam<std::tuple<bool, const char*> >,
|
||||
public PlainIslandsFixture
|
||||
{
|
||||
void assignIsland(const std::string &s)
|
||||
{
|
||||
cv::gapi::island(s, cv::GIn(tmp[0]), cv::GOut(tmp[2]));
|
||||
};
|
||||
};
|
||||
TEST_P(CheckName, Test)
|
||||
{
|
||||
bool correct = false;
|
||||
const char *name = "";
|
||||
std::tie(correct, name) = GetParam();
|
||||
if (correct) EXPECT_NO_THROW(assignIsland(name));
|
||||
else EXPECT_ANY_THROW(assignIsland(name));
|
||||
}
|
||||
} // namespace
|
||||
INSTANTIATE_TEST_CASE_P(IslandName, CheckName,
|
||||
Values(std::make_tuple(true, "name"),
|
||||
std::make_tuple(true, " name "),
|
||||
std::make_tuple(true, " n a m e "),
|
||||
std::make_tuple(true, " 123 $$ %%"),
|
||||
std::make_tuple(true, ".: -"),
|
||||
std::make_tuple(false, ""),
|
||||
std::make_tuple(false, " "),
|
||||
std::make_tuple(false, " \t "),
|
||||
std::make_tuple(false, " \t \t ")));
|
||||
|
||||
// FIXME: add <internal> test on unrollExpr() use for islands
|
||||
|
||||
} // opencv_test
|
997
3rdparty/opencv-4.5.4/modules/gapi/test/internal/gapi_int_pattern_matching_test.cpp
vendored
Normal file
997
3rdparty/opencv-4.5.4/modules/gapi/test/internal/gapi_int_pattern_matching_test.cpp
vendored
Normal file
@ -0,0 +1,997 @@
|
||||
// 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) 2019 Intel Corporation
|
||||
|
||||
|
||||
#include "../test_precomp.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "compiler/gmodel.hpp"
|
||||
#include "compiler/gmodel_priv.hpp"
|
||||
|
||||
#include "api/gcomputation_priv.hpp"
|
||||
#include "compiler/gcompiler.hpp"
|
||||
#include "compiler/gmodelbuilder.hpp"
|
||||
#include "compiler/passes/passes.hpp"
|
||||
|
||||
#include "compiler/passes/pattern_matching.hpp"
|
||||
|
||||
#include "../common/gapi_tests_common.hpp"
|
||||
|
||||
#include "logger.hpp"
|
||||
|
||||
namespace opencv_test
|
||||
{
|
||||
|
||||
namespace matching_test {
|
||||
namespace {
|
||||
using V = std::vector<ade::NodeHandle>;
|
||||
using S = std::unordered_set< ade::NodeHandle
|
||||
, ade::HandleHasher<ade::Node>
|
||||
>;
|
||||
|
||||
void initGModel(ade::Graph& gr,
|
||||
cv::GProtoInputArgs&& in,
|
||||
cv::GProtoOutputArgs&& out) {
|
||||
|
||||
cv::gimpl::GModel::Graph gm(gr);
|
||||
cv::gimpl::GModel::init(gm);
|
||||
auto proto_slots = cv::gimpl::GModelBuilder(gr)
|
||||
.put(in.m_args, out.m_args);
|
||||
|
||||
cv::gimpl::Protocol p;
|
||||
std::tie(p.inputs, p.outputs, p.in_nhs, p.out_nhs) = proto_slots;
|
||||
gm.metadata().set(p);
|
||||
}
|
||||
|
||||
bool isConsumedBy(const cv::gimpl::GModel::ConstGraph &gm, ade::NodeHandle data_nh, ade::NodeHandle op_nh) {
|
||||
auto oi = cv::gimpl::GModel::orderedInputs(gm, op_nh);
|
||||
return std::find(oi.begin(), oi.end(), data_nh) != oi.end();
|
||||
}
|
||||
|
||||
std::string opName(const cv::gimpl::GModel::ConstGraph &gm, ade::NodeHandle op_nh) {
|
||||
return gm.metadata(op_nh).get<cv::gimpl::Op>().k.name;
|
||||
}
|
||||
|
||||
}
|
||||
} // matching_test
|
||||
|
||||
TEST(PatternMatching, TestFuncDoesNotChangeTestGraph)
|
||||
{
|
||||
// Pattern
|
||||
ade::Graph pg;
|
||||
{
|
||||
GMat in;
|
||||
GMat out = cv::gapi::bitwise_not(in);
|
||||
matching_test::initGModel(pg, cv::GIn(in), cv::GOut(out));
|
||||
}
|
||||
|
||||
// Test
|
||||
ade::Graph tg;
|
||||
GMat in;
|
||||
GMat out = cv::gapi::bitwise_not(in);
|
||||
matching_test::initGModel(tg, cv::GIn(in), cv::GOut(out));
|
||||
|
||||
// Pattern Matching
|
||||
cv::gimpl::GModel::Graph pgm(pg);
|
||||
cv::gimpl::GModel::Graph tgm(tg);
|
||||
cv::gimpl::findMatches(pg, tg);
|
||||
|
||||
// Inspecting results:
|
||||
matching_test::S nodes{ tgm.nodes().begin(), tgm.nodes().end() };
|
||||
|
||||
const auto in_nh = cv::gimpl::GModel::dataNodeOf(tgm, in);
|
||||
const auto out_nh = cv::gimpl::GModel::dataNodeOf(tgm, out);
|
||||
|
||||
auto input_data_nhs = tgm.metadata().get<cv::gimpl::Protocol>().in_nhs;
|
||||
auto output_data_nhs = tgm.metadata().get<cv::gimpl::Protocol>().out_nhs;
|
||||
|
||||
EXPECT_EQ(1u, input_data_nhs.size());
|
||||
EXPECT_EQ(1u, output_data_nhs.size());
|
||||
EXPECT_EQ(in_nh, *input_data_nhs.begin());
|
||||
EXPECT_EQ(out_nh, *output_data_nhs.begin());
|
||||
EXPECT_EQ(0u, in_nh->inEdges().size());
|
||||
EXPECT_EQ(0u, out_nh->outEdges().size());
|
||||
EXPECT_EQ(1u, in_nh->outEdges().size());
|
||||
EXPECT_EQ(1u, out_nh->inEdges().size());
|
||||
|
||||
const auto op_nh = cv::gimpl::GModel::producerOf(tgm, out_nh); //bitwise_not
|
||||
EXPECT_EQ(cv::gapi::core::GNot::id(), matching_test::opName(tgm, op_nh));
|
||||
EXPECT_EQ(1u, op_nh->inEdges().size());
|
||||
EXPECT_TRUE(matching_test::isConsumedBy(tgm, in_nh, op_nh));
|
||||
EXPECT_EQ(1u, op_nh->outEdges().size());
|
||||
}
|
||||
|
||||
TEST(PatternMatching, TestSimple1)
|
||||
{
|
||||
// Pattern
|
||||
ade::Graph pg;
|
||||
{
|
||||
GMat in;
|
||||
GMat out = cv::gapi::bitwise_not(in);
|
||||
matching_test::initGModel(pg, cv::GIn(in), cv::GOut(out));
|
||||
}
|
||||
|
||||
// Test
|
||||
ade::Graph tg;
|
||||
GMat in;
|
||||
GMat out = cv::gapi::bitwise_not(in);
|
||||
matching_test::initGModel(tg, cv::GIn(in), cv::GOut(out));
|
||||
|
||||
// Pattern Matching
|
||||
cv::gimpl::GModel::Graph pgm(pg);
|
||||
cv::gimpl::GModel::Graph tgm(tg);
|
||||
cv::gimpl::SubgraphMatch match = cv::gimpl::findMatches(pg, tg);
|
||||
|
||||
// Inspecting results:
|
||||
EXPECT_TRUE(match.ok());
|
||||
|
||||
auto nodes = match.nodes();
|
||||
EXPECT_EQ(3u, nodes.size());
|
||||
|
||||
const auto in_nh = cv::gimpl::GModel::dataNodeOf(tgm, in);
|
||||
const auto out_nh = cv::gimpl::GModel::dataNodeOf(tgm, out);
|
||||
const auto op_nh = cv::gimpl::GModel::producerOf(tgm, out_nh);
|
||||
|
||||
EXPECT_EQ(matching_test::S({in_nh, out_nh, op_nh}), nodes);
|
||||
EXPECT_EQ(cv::gapi::core::GNot::id(), matching_test::opName(tgm, op_nh));
|
||||
EXPECT_TRUE(matching_test::isConsumedBy(tgm, in_nh, op_nh));
|
||||
EXPECT_EQ(matching_test::S{op_nh}, match.startOps());
|
||||
EXPECT_EQ(matching_test::S{op_nh}, match.finishOps());
|
||||
EXPECT_EQ(matching_test::V{in_nh}, match.protoIns());
|
||||
EXPECT_EQ(matching_test::V{out_nh}, match.protoOuts());
|
||||
}
|
||||
|
||||
TEST(PatternMatching, TestSimple2)
|
||||
{
|
||||
// Pattern
|
||||
ade::Graph pg;
|
||||
{
|
||||
GMat in;
|
||||
GMat out = cv::gapi::bitwise_not(in);
|
||||
matching_test::initGModel(pg, cv::GIn(in), cv::GOut(out));
|
||||
}
|
||||
|
||||
// Test
|
||||
ade::Graph tg;
|
||||
GMat in;
|
||||
GMat tmp = cv::gapi::bitwise_not(in);
|
||||
GMat out = cv::gapi::blur(tmp, cv::Size(3, 3));
|
||||
matching_test::initGModel(tg, cv::GIn(in), cv::GOut(out));
|
||||
|
||||
// Pattern Matching
|
||||
cv::gimpl::GModel::Graph pgm(pg);
|
||||
cv::gimpl::GModel::Graph tgm(tg);
|
||||
cv::gimpl::SubgraphMatch match = cv::gimpl::findMatches(pg, tg);
|
||||
|
||||
// Inspecting results:
|
||||
EXPECT_TRUE(match.ok());
|
||||
|
||||
auto nodes = match.nodes();
|
||||
EXPECT_EQ(3u, nodes.size());
|
||||
|
||||
const auto in_nh = cv::gimpl::GModel::dataNodeOf(tgm, in);
|
||||
const auto tmp_nh = cv::gimpl::GModel::dataNodeOf(tgm, tmp);
|
||||
const auto op_nh = cv::gimpl::GModel::producerOf(tgm, tmp_nh);
|
||||
|
||||
EXPECT_EQ(matching_test::S({in_nh, tmp_nh, op_nh}), nodes);
|
||||
EXPECT_EQ(cv::gapi::core::GNot::id(), matching_test::opName(tgm, op_nh));
|
||||
EXPECT_TRUE(matching_test::isConsumedBy(tgm, in_nh, op_nh));
|
||||
EXPECT_EQ(matching_test::S{op_nh}, match.startOps());
|
||||
EXPECT_EQ(matching_test::S{op_nh}, match.finishOps());
|
||||
EXPECT_EQ(matching_test::V{in_nh}, match.protoIns());
|
||||
EXPECT_EQ(matching_test::V{tmp_nh}, match.protoOuts());
|
||||
}
|
||||
|
||||
TEST(PatternMatching, TestSimple3)
|
||||
{
|
||||
// Pattern
|
||||
ade::Graph pg;
|
||||
{
|
||||
GMat in;
|
||||
GMat out = cv::gapi::bitwise_not(in);
|
||||
matching_test::initGModel(pg, cv::GIn(in), cv::GOut(out));
|
||||
}
|
||||
|
||||
// Test
|
||||
ade::Graph tg;
|
||||
GMat in;
|
||||
GMat tmp = cv::gapi::blur(in, cv::Size(3, 3));
|
||||
GMat out = cv::gapi::bitwise_not(tmp);
|
||||
matching_test::initGModel(tg, cv::GIn(in), cv::GOut(out));
|
||||
|
||||
// Pattern Matching
|
||||
cv::gimpl::GModel::Graph pgm(pg);
|
||||
cv::gimpl::GModel::Graph tgm(tg);
|
||||
cv::gimpl::SubgraphMatch match = cv::gimpl::findMatches(pg, tg);
|
||||
|
||||
// Inspecting results:
|
||||
EXPECT_TRUE(match.ok());
|
||||
|
||||
auto nodes = match.nodes();
|
||||
EXPECT_EQ(3u, nodes.size());
|
||||
|
||||
const auto tmp_nh = cv::gimpl::GModel::dataNodeOf(tgm, tmp);
|
||||
const auto out_nh = cv::gimpl::GModel::dataNodeOf(tgm, out);
|
||||
const auto op_nh = cv::gimpl::GModel::producerOf(tgm, out_nh);
|
||||
|
||||
EXPECT_EQ(matching_test::S({tmp_nh, out_nh, op_nh}), nodes);
|
||||
EXPECT_EQ(cv::gapi::core::GNot::id(), matching_test::opName(tgm, op_nh));
|
||||
EXPECT_TRUE(matching_test::isConsumedBy(tgm, tmp_nh, op_nh));
|
||||
EXPECT_EQ(matching_test::S{op_nh}, match.startOps());
|
||||
EXPECT_EQ(matching_test::S{op_nh}, match.finishOps());
|
||||
EXPECT_EQ(matching_test::V{tmp_nh}, match.protoIns());
|
||||
EXPECT_EQ(matching_test::V{out_nh}, match.protoOuts());
|
||||
}
|
||||
|
||||
TEST(PatternMatching, TestMultiplePatternOuts)
|
||||
{
|
||||
// Pattern
|
||||
ade::Graph pg;
|
||||
{
|
||||
GMat in;
|
||||
GMat dx, dy;
|
||||
std::tie(dx, dy) = cv::gapi::SobelXY(in, -1, 1);
|
||||
matching_test::initGModel(pg, cv::GIn(in), cv::GOut(dx, dy));
|
||||
}
|
||||
|
||||
// Test
|
||||
ade::Graph tg;
|
||||
GMat in;
|
||||
GMat dx, dy;
|
||||
std::tie(dx, dy) = cv::gapi::SobelXY(in, -1, 1);
|
||||
matching_test::initGModel(tg, cv::GIn(in), cv::GOut(dx, dy));
|
||||
|
||||
// Pattern Matching
|
||||
cv::gimpl::GModel::Graph pgm(pg);
|
||||
cv::gimpl::GModel::Graph tgm(tg);
|
||||
cv::gimpl::SubgraphMatch match = cv::gimpl::findMatches(pg, tg);
|
||||
|
||||
// Inspecting results:
|
||||
EXPECT_TRUE(match.ok());
|
||||
|
||||
auto nodes = match.nodes();
|
||||
EXPECT_EQ(4u, nodes.size());
|
||||
|
||||
const auto in_nh = cv::gimpl::GModel::dataNodeOf(tgm, in);
|
||||
const auto dx_nh = cv::gimpl::GModel::dataNodeOf(tgm, dx);
|
||||
const auto dy_nh = cv::gimpl::GModel::dataNodeOf(tgm, dy);
|
||||
const auto op_nh = cv::gimpl::GModel::producerOf(tgm, dx_nh);
|
||||
EXPECT_EQ(op_nh, cv::gimpl::GModel::producerOf(tgm, dy_nh));
|
||||
|
||||
EXPECT_EQ(matching_test::S({in_nh, dx_nh, dy_nh, op_nh}), nodes);
|
||||
EXPECT_EQ(cv::gapi::imgproc::GSobelXY::id(), matching_test::opName(tgm, op_nh));
|
||||
EXPECT_TRUE(matching_test::isConsumedBy(tgm, in_nh, op_nh));
|
||||
EXPECT_EQ(matching_test::S{op_nh}, match.startOps());
|
||||
EXPECT_EQ(matching_test::S{op_nh}, match.finishOps());
|
||||
EXPECT_EQ(matching_test::V{in_nh}, match.protoIns());
|
||||
EXPECT_EQ(matching_test::V({dx_nh, dy_nh}), match.protoOuts());
|
||||
}
|
||||
|
||||
TEST(PatternMatching, TestPrepResizeSplit3)
|
||||
{
|
||||
// Pattern
|
||||
ade::Graph pg;
|
||||
{
|
||||
GMat in;
|
||||
GMat tmp = cv::gapi::resize(in, cv::Size{224, 224});
|
||||
GMat b, g, r;
|
||||
std::tie(b, g, r) = cv::gapi::split3(tmp);
|
||||
matching_test::initGModel(pg, cv::GIn(in), cv::GOut(b, g, r));
|
||||
}
|
||||
|
||||
// Test
|
||||
ade::Graph tg;
|
||||
GMat y, uv;
|
||||
GMat bgr = cv::gapi::NV12toBGR(y, uv);
|
||||
GMat tmp = cv::gapi::resize(bgr, cv::Size{224, 224});
|
||||
GMat b, g, r;
|
||||
std::tie(b, g, r) = cv::gapi::split3(tmp);
|
||||
matching_test::initGModel(tg, cv::GIn(y, uv), cv::GOut(b, g, r));
|
||||
|
||||
// Pattern Matching
|
||||
cv::gimpl::GModel::Graph pgm(pg);
|
||||
cv::gimpl::GModel::Graph tgm(tg);
|
||||
cv::gimpl::SubgraphMatch match = cv::gimpl::findMatches(pg, tg);
|
||||
|
||||
// Inspecting results:
|
||||
EXPECT_TRUE(match.ok());
|
||||
|
||||
auto nodes = match.nodes();
|
||||
EXPECT_EQ(7u, nodes.size());
|
||||
|
||||
const auto bgr_nh = cv::gimpl::GModel::dataNodeOf(tgm, bgr);
|
||||
const auto tmp_nh = cv::gimpl::GModel::dataNodeOf(tgm, tmp);
|
||||
const auto b_nh = cv::gimpl::GModel::dataNodeOf(tgm, b);
|
||||
const auto g_nh = cv::gimpl::GModel::dataNodeOf(tgm, g);
|
||||
const auto r_nh = cv::gimpl::GModel::dataNodeOf(tgm, r);
|
||||
|
||||
const auto op1_nh = cv::gimpl::GModel::producerOf(tgm, tmp_nh); // 1st resize
|
||||
const auto op2_nh = cv::gimpl::GModel::producerOf(tgm, b_nh); // 2nd split3
|
||||
EXPECT_EQ(op2_nh, cv::gimpl::GModel::producerOf(tgm, g_nh));
|
||||
EXPECT_EQ(op2_nh, cv::gimpl::GModel::producerOf(tgm, r_nh));
|
||||
|
||||
EXPECT_EQ(matching_test::S({bgr_nh, tmp_nh, b_nh, g_nh,
|
||||
r_nh, op1_nh, op2_nh}),
|
||||
nodes);
|
||||
|
||||
EXPECT_EQ(cv::gapi::core::GResize::id(), matching_test::opName(tgm, op1_nh));
|
||||
EXPECT_EQ(cv::gapi::core::GSplit3::id(), matching_test::opName(tgm, op2_nh));
|
||||
|
||||
EXPECT_EQ(1u, tmp_nh->outEdges().size());
|
||||
EXPECT_TRUE(matching_test::isConsumedBy(tgm, bgr_nh, op1_nh));
|
||||
EXPECT_TRUE(matching_test::isConsumedBy(tgm, tmp_nh, op2_nh));
|
||||
|
||||
EXPECT_EQ(matching_test::S{ op1_nh }, match.startOps());
|
||||
EXPECT_EQ(matching_test::S{ op2_nh }, match.finishOps());
|
||||
EXPECT_EQ(matching_test::V{ bgr_nh }, match.protoIns());
|
||||
EXPECT_EQ(matching_test::V({ b_nh, g_nh, r_nh }), match.protoOuts());
|
||||
}
|
||||
|
||||
G_TYPED_KERNEL(GToNCHW, <GMatP(GMat)>, "test.toNCHW") {
|
||||
static GMatDesc outMeta(GMatDesc in) {
|
||||
GAPI_Assert(in.depth == CV_8U);
|
||||
GAPI_Assert(in.chan == 3);
|
||||
GAPI_Assert(in.planar == false);
|
||||
return in.asPlanar();
|
||||
}
|
||||
};
|
||||
|
||||
static GMatP toNCHW(const GMat& src)
|
||||
{
|
||||
return GToNCHW::on(src);
|
||||
}
|
||||
|
||||
TEST(PatternMatching, TestPrepResizeToNCHW)
|
||||
{
|
||||
// Pattern
|
||||
ade::Graph pg;
|
||||
{
|
||||
GMat in;
|
||||
GMat tmp = cv::gapi::resize(in, cv::Size{224, 224});
|
||||
GMatP plr = toNCHW(tmp);
|
||||
matching_test::initGModel(pg, cv::GIn(in), cv::GOut(plr));
|
||||
}
|
||||
|
||||
// Test
|
||||
ade::Graph tg;
|
||||
GMat y, uv;
|
||||
GMat bgr = cv::gapi::NV12toBGR(y, uv);
|
||||
GMat tmp = cv::gapi::resize(bgr, cv::Size{224, 224});
|
||||
GMatP plr = toNCHW(tmp);
|
||||
matching_test::initGModel(tg, cv::GIn(y, uv), cv::GOut(plr));
|
||||
|
||||
// Pattern Matching
|
||||
cv::gimpl::GModel::Graph pgm(pg);
|
||||
cv::gimpl::GModel::Graph tgm(tg);
|
||||
cv::gimpl::SubgraphMatch match = cv::gimpl::findMatches(pg, tg);
|
||||
|
||||
// Inspecting results:
|
||||
EXPECT_TRUE(match.ok());
|
||||
|
||||
auto nodes = match.nodes();
|
||||
EXPECT_EQ(5u, nodes.size());
|
||||
|
||||
const auto bgr_nh = cv::gimpl::GModel::dataNodeOf(tgm, bgr);
|
||||
const auto tmp_nh = cv::gimpl::GModel::dataNodeOf(tgm, tmp);
|
||||
const auto plr_nh = cv::gimpl::GModel::dataNodeOf(tgm, plr);
|
||||
|
||||
const auto op1_nh = cv::gimpl::GModel::producerOf(tgm, tmp_nh); // 1st resize
|
||||
const auto op2_nh = cv::gimpl::GModel::producerOf(tgm, plr_nh); // 2nd toNCHW
|
||||
|
||||
EXPECT_EQ(matching_test::S({bgr_nh, tmp_nh, plr_nh, op1_nh, op2_nh}),
|
||||
nodes);
|
||||
|
||||
EXPECT_EQ(cv::gapi::core::GResize::id(), matching_test::opName(tgm, op1_nh));
|
||||
EXPECT_EQ(GToNCHW::id(), matching_test::opName(tgm, op2_nh));
|
||||
|
||||
EXPECT_EQ(1u, tmp_nh->outEdges().size());
|
||||
EXPECT_TRUE(matching_test::isConsumedBy(tgm, bgr_nh, op1_nh));
|
||||
EXPECT_TRUE(matching_test::isConsumedBy(tgm, tmp_nh, op2_nh));
|
||||
|
||||
EXPECT_EQ(matching_test::S{ op1_nh }, match.startOps());
|
||||
EXPECT_EQ(matching_test::S{ op2_nh }, match.finishOps());
|
||||
EXPECT_EQ(matching_test::V{ bgr_nh }, match.protoIns());
|
||||
EXPECT_EQ(matching_test::V{ plr_nh }, match.protoOuts());
|
||||
}
|
||||
|
||||
TEST(PatternMatching, TestPrepNV12toBGRToNCHW)
|
||||
{
|
||||
// Pattern
|
||||
ade::Graph pg;
|
||||
{
|
||||
GMat y, uv;
|
||||
GMat bgr = cv::gapi::NV12toBGR(y, uv);
|
||||
GMatP plr = toNCHW(bgr);
|
||||
matching_test::initGModel(pg, cv::GIn(y, uv), cv::GOut(plr));
|
||||
}
|
||||
|
||||
// Test
|
||||
ade::Graph tg;
|
||||
GMat y, uv;
|
||||
GMat bgr = cv::gapi::NV12toBGR(y, uv);
|
||||
GMatP plr = toNCHW(bgr);
|
||||
GMat rsz = cv::gapi::resizeP(plr, cv::Size{224, 224});
|
||||
matching_test::initGModel(tg, cv::GIn(y, uv), cv::GOut(rsz));
|
||||
|
||||
// Pattern Matching
|
||||
cv::gimpl::GModel::Graph pgm(pg);
|
||||
cv::gimpl::GModel::Graph tgm(tg);
|
||||
cv::gimpl::SubgraphMatch match = cv::gimpl::findMatches(pg, tg);
|
||||
|
||||
// Inspecting results:
|
||||
EXPECT_TRUE(match.ok());
|
||||
|
||||
auto nodes = match.nodes();
|
||||
EXPECT_EQ(6u, nodes.size());
|
||||
|
||||
const auto y_nh = cv::gimpl::GModel::dataNodeOf(tgm, y);
|
||||
const auto uv_nh = cv::gimpl::GModel::dataNodeOf(tgm, uv);
|
||||
const auto bgr_nh = cv::gimpl::GModel::dataNodeOf(tgm, bgr);
|
||||
const auto plr_nh = cv::gimpl::GModel::dataNodeOf(tgm, plr);
|
||||
|
||||
const auto op1_nh = cv::gimpl::GModel::producerOf(tgm, bgr_nh); // 1st NV12toBGR
|
||||
const auto op2_nh = cv::gimpl::GModel::producerOf(tgm, plr_nh); // 2nd toNCHW
|
||||
|
||||
EXPECT_EQ(matching_test::S({y_nh, uv_nh, bgr_nh, plr_nh, op1_nh, op2_nh}),
|
||||
nodes);
|
||||
|
||||
EXPECT_EQ(cv::gapi::imgproc::GNV12toBGR::id(), matching_test::opName(tgm, op1_nh));
|
||||
EXPECT_EQ(GToNCHW::id(), matching_test::opName(tgm, op2_nh));
|
||||
|
||||
EXPECT_EQ(1u, bgr_nh->outEdges().size());
|
||||
EXPECT_TRUE(matching_test::isConsumedBy(tgm, y_nh, op1_nh));
|
||||
EXPECT_TRUE(matching_test::isConsumedBy(tgm, uv_nh, op1_nh));
|
||||
EXPECT_TRUE(matching_test::isConsumedBy(tgm, bgr_nh, op2_nh));
|
||||
|
||||
EXPECT_EQ(matching_test::S{ op1_nh }, match.startOps());
|
||||
EXPECT_EQ(matching_test::S{ op2_nh }, match.finishOps());
|
||||
EXPECT_EQ(matching_test::V({ y_nh, uv_nh }), match.protoIns());
|
||||
EXPECT_EQ(matching_test::V{ plr_nh }, match.protoOuts());
|
||||
}
|
||||
|
||||
//FIXME: To switch from filter2d kernel (which shall be matched by params too) to another one
|
||||
TEST(PatternMatching, MatchChainInTheMiddle)
|
||||
{
|
||||
// Pattern
|
||||
ade::Graph pg;
|
||||
{
|
||||
GMat in;
|
||||
GMat tmp = cv::gapi::filter2D(in, -1, {});
|
||||
GMat out = cv::gapi::filter2D(tmp, -1, {});
|
||||
matching_test::initGModel(pg, cv::GIn(in), cv::GOut(out));
|
||||
}
|
||||
|
||||
// Test
|
||||
ade::Graph tg;
|
||||
GMat in;
|
||||
GMat tmp1 = cv::gapi::erode3x3(in);
|
||||
GMat tmp2 = cv::gapi::filter2D(tmp1, -1, {});
|
||||
GMat tmp3 = cv::gapi::filter2D(tmp2, -1, {});
|
||||
GMat out = cv::gapi::dilate3x3(tmp3);
|
||||
matching_test::initGModel(tg, cv::GIn(in), cv::GOut(out));
|
||||
|
||||
// Pattern Matching
|
||||
cv::gimpl::GModel::Graph pgm(pg);
|
||||
cv::gimpl::GModel::Graph tgm(tg);
|
||||
cv::gimpl::SubgraphMatch match = cv::gimpl::findMatches(pg, tg);
|
||||
|
||||
// Inspecting results:
|
||||
EXPECT_TRUE(match.ok());
|
||||
|
||||
auto nodes = match.nodes();
|
||||
EXPECT_EQ(5u, nodes.size());
|
||||
|
||||
const auto tmp1_nh = cv::gimpl::GModel::dataNodeOf(tgm, tmp1);
|
||||
const auto tmp2_nh = cv::gimpl::GModel::dataNodeOf(tgm, tmp2);
|
||||
const auto tmp3_nh = cv::gimpl::GModel::dataNodeOf(tgm, tmp3);
|
||||
const auto op1_nh = cv::gimpl::GModel::producerOf(tgm, tmp2_nh); // 1st filter2D
|
||||
const auto op2_nh = cv::gimpl::GModel::producerOf(tgm, tmp3_nh); // 2nd filter2D
|
||||
|
||||
EXPECT_EQ(matching_test::S({tmp1_nh, tmp2_nh, tmp3_nh, op1_nh, op2_nh}), nodes);
|
||||
|
||||
EXPECT_EQ(cv::gapi::imgproc::GFilter2D::id(), matching_test::opName(tgm, op1_nh));
|
||||
EXPECT_EQ(cv::gapi::imgproc::GFilter2D::id(), matching_test::opName(tgm, op2_nh));
|
||||
|
||||
EXPECT_EQ(1u, tmp2_nh->outEdges().size());
|
||||
EXPECT_TRUE(matching_test::isConsumedBy(tgm, tmp1_nh, op1_nh));
|
||||
EXPECT_TRUE(matching_test::isConsumedBy(tgm, tmp2_nh, op2_nh));
|
||||
|
||||
EXPECT_EQ(matching_test::S({op1_nh}), match.startOps());
|
||||
EXPECT_EQ(matching_test::S({op2_nh}), match.finishOps());
|
||||
EXPECT_EQ(matching_test::V{ tmp1_nh }, match.protoIns());
|
||||
EXPECT_EQ(matching_test::V{ tmp3_nh }, match.protoOuts());
|
||||
}
|
||||
|
||||
TEST(PatternMatching, TestMultipleStartOps1)
|
||||
{
|
||||
// Pattern
|
||||
ade::Graph pg;
|
||||
{
|
||||
GMat in1, in2;
|
||||
GMat er = cv::gapi::erode3x3(in1);
|
||||
GMat dil = cv::gapi::dilate3x3(in2);
|
||||
GMat out = cv::gapi::add(er, dil);
|
||||
matching_test::initGModel(pg, cv::GIn(in1, in2), cv::GOut(out));
|
||||
}
|
||||
|
||||
// Test
|
||||
ade::Graph tg;
|
||||
|
||||
GMat in1, in2, in3, in4, in5, in6;
|
||||
GMat er1 = cv::gapi::erode3x3(in1);
|
||||
GMat er2 = cv::gapi::erode3x3(in2);
|
||||
GMat er3 = cv::gapi::erode3x3(in3);
|
||||
GMat er4 = cv::gapi::erode3x3(in4);
|
||||
GMat dil1 = cv::gapi::dilate3x3(in5);
|
||||
GMat dil2 = cv::gapi::dilate3x3(in6);
|
||||
GMat out1 = cv::gapi::add(er1, er2);
|
||||
GMat out2 = cv::gapi::add(er3, dil2);
|
||||
matching_test::initGModel(tg, cv::GIn(in1, in2, in3, in4, in5, in6), cv::GOut(out1, out2, er4, dil1));
|
||||
|
||||
// Pattern Matching
|
||||
cv::gimpl::GModel::Graph pgm(pg);
|
||||
cv::gimpl::GModel::Graph tgm(tg);
|
||||
cv::gimpl::SubgraphMatch match = cv::gimpl::findMatches(pg, tg);
|
||||
|
||||
// Inspecting results:
|
||||
EXPECT_TRUE(match.ok());
|
||||
|
||||
auto nodes = match.nodes();
|
||||
EXPECT_EQ(8u, nodes.size());
|
||||
|
||||
const auto in3_nh = cv::gimpl::GModel::dataNodeOf(tgm, in3);
|
||||
const auto in6_nh = cv::gimpl::GModel::dataNodeOf(tgm, in6);
|
||||
const auto er3_nh = cv::gimpl::GModel::dataNodeOf(tgm, er3);
|
||||
const auto dil2_nh = cv::gimpl::GModel::dataNodeOf(tgm, dil2);
|
||||
const auto out2_nh = cv::gimpl::GModel::dataNodeOf(tgm, out2);
|
||||
|
||||
const auto er_op_nh = cv::gimpl::GModel::producerOf(tgm, er3_nh);
|
||||
const auto dil_op_nh = cv::gimpl::GModel::producerOf(tgm, dil2_nh);
|
||||
const auto add_op_nh = cv::gimpl::GModel::producerOf(tgm, out2_nh);
|
||||
|
||||
EXPECT_EQ(matching_test::S({in3_nh, in6_nh, er3_nh, dil2_nh, out2_nh,
|
||||
er_op_nh, dil_op_nh, add_op_nh}),
|
||||
nodes);
|
||||
|
||||
EXPECT_EQ(cv::gapi::imgproc::GErode::id(), matching_test::opName(tgm, er_op_nh));
|
||||
EXPECT_EQ(cv::gapi::imgproc::GDilate::id(), matching_test::opName(tgm, dil_op_nh));
|
||||
EXPECT_EQ(cv::gapi::core::GAdd::id(), matching_test::opName(tgm, add_op_nh));
|
||||
|
||||
EXPECT_EQ(1u, er3_nh->outEdges().size());
|
||||
EXPECT_EQ(1u, dil2_nh->outEdges().size());
|
||||
EXPECT_TRUE(matching_test::isConsumedBy(tgm, in3_nh, er_op_nh));
|
||||
EXPECT_TRUE(matching_test::isConsumedBy(tgm, in6_nh, dil_op_nh));
|
||||
EXPECT_TRUE(matching_test::isConsumedBy(tgm, er3_nh, add_op_nh));
|
||||
EXPECT_TRUE(matching_test::isConsumedBy(tgm, dil2_nh, add_op_nh));
|
||||
|
||||
EXPECT_EQ(matching_test::S({ er_op_nh, dil_op_nh }), match.startOps());
|
||||
EXPECT_EQ(matching_test::S{ add_op_nh }, match.finishOps());
|
||||
EXPECT_EQ(matching_test::V({ in3_nh, in6_nh }), match.protoIns());
|
||||
EXPECT_EQ(matching_test::V{ out2_nh }, match.protoOuts());
|
||||
}
|
||||
|
||||
TEST(PatternMatching, TestMultipleStartOps2)
|
||||
{
|
||||
// Pattern
|
||||
ade::Graph pg;
|
||||
{
|
||||
GMat in1, in2;
|
||||
GMat er = cv::gapi::erode3x3(in1);
|
||||
GMat dil = cv::gapi::dilate3x3(in2);
|
||||
GMat out = cv::gapi::add(er, dil);
|
||||
matching_test::initGModel(pg, cv::GIn(in1, in2), cv::GOut(out));
|
||||
}
|
||||
|
||||
// Test
|
||||
ade::Graph tg;
|
||||
|
||||
GMat in1, in2;
|
||||
GMat er = cv::gapi::erode3x3(in1);
|
||||
GMat dil1 = cv::gapi::dilate3x3(in2);
|
||||
GMat dil2 = cv::gapi::dilate3x3(dil1);
|
||||
GMat out = cv::gapi::add(er, dil2);
|
||||
matching_test::initGModel(tg, cv::GIn(in1, in2), cv::GOut(out));
|
||||
|
||||
// Pattern Matching
|
||||
cv::gimpl::GModel::Graph pgm(pg);
|
||||
cv::gimpl::GModel::Graph tgm(tg);
|
||||
cv::gimpl::SubgraphMatch match = cv::gimpl::findMatches(pg, tg);
|
||||
|
||||
// Inspecting results:
|
||||
EXPECT_TRUE(match.ok());
|
||||
|
||||
auto nodes = match.nodes();
|
||||
EXPECT_EQ(8u, nodes.size());
|
||||
|
||||
const auto in1_nh = cv::gimpl::GModel::dataNodeOf(tgm, in1);
|
||||
const auto dil1_nh = cv::gimpl::GModel::dataNodeOf(tgm, dil1);
|
||||
const auto er_nh = cv::gimpl::GModel::dataNodeOf(tgm, er);
|
||||
const auto dil2_nh = cv::gimpl::GModel::dataNodeOf(tgm, dil2);
|
||||
const auto out_nh = cv::gimpl::GModel::dataNodeOf(tgm, out);
|
||||
|
||||
const auto er_op_nh = cv::gimpl::GModel::producerOf(tgm, er_nh);
|
||||
const auto dil_op_nh = cv::gimpl::GModel::producerOf(tgm, dil2_nh);
|
||||
const auto add_op_nh = cv::gimpl::GModel::producerOf(tgm, out_nh);
|
||||
|
||||
EXPECT_EQ(matching_test::S({in1_nh, dil1_nh, er_nh, dil2_nh, out_nh,
|
||||
er_op_nh, dil_op_nh, add_op_nh}),
|
||||
nodes);
|
||||
|
||||
EXPECT_EQ(cv::gapi::imgproc::GErode::id(), matching_test::opName(tgm, er_op_nh));
|
||||
EXPECT_EQ(cv::gapi::imgproc::GDilate::id(), matching_test::opName(tgm, dil_op_nh));
|
||||
EXPECT_EQ(cv::gapi::core::GAdd::id(), matching_test::opName(tgm, add_op_nh));
|
||||
|
||||
EXPECT_EQ(1u, er_nh->outEdges().size());
|
||||
EXPECT_EQ(1u, dil2_nh->outEdges().size());
|
||||
EXPECT_TRUE(matching_test::isConsumedBy(tgm, in1_nh, er_op_nh));
|
||||
EXPECT_TRUE(matching_test::isConsumedBy(tgm, dil1_nh, dil_op_nh));
|
||||
EXPECT_TRUE(matching_test::isConsumedBy(tgm, er_nh, add_op_nh));
|
||||
EXPECT_TRUE(matching_test::isConsumedBy(tgm, dil2_nh, add_op_nh));
|
||||
|
||||
EXPECT_EQ(matching_test::S({ er_op_nh, dil_op_nh }), match.startOps());
|
||||
EXPECT_EQ(matching_test::S{ add_op_nh }, match.finishOps());
|
||||
EXPECT_EQ(matching_test::V({ in1_nh, dil1_nh }), match.protoIns());
|
||||
EXPECT_EQ(matching_test::V{ out_nh }, match.protoOuts());
|
||||
}
|
||||
|
||||
TEST(PatternMatching, TestInexactMatchOfInOutData)
|
||||
{
|
||||
// Pattern
|
||||
ade::Graph pg;
|
||||
{
|
||||
GMat in;
|
||||
GMat out = cv::gapi::dilate3x3(in);
|
||||
matching_test::initGModel(pg, cv::GIn(in), cv::GOut(out));
|
||||
}
|
||||
|
||||
// Test
|
||||
ade::Graph tg;
|
||||
GMat in;
|
||||
GMat out1 = cv::gapi::erode3x3(in);
|
||||
GMat out2 = cv::gapi::boxFilter(in, -1, cv::Size(3, 3));
|
||||
GMat tmp = cv::gapi::dilate3x3(in);
|
||||
GScalar out3 = cv::gapi::sum(tmp);
|
||||
GScalar out4 = cv::gapi::mean(tmp);
|
||||
matching_test::initGModel(tg, cv::GIn(in), cv::GOut(out1, out2, out3, out4));
|
||||
|
||||
// Pattern Matching
|
||||
cv::gimpl::GModel::Graph pgm(pg);
|
||||
cv::gimpl::GModel::Graph tgm(tg);
|
||||
cv::gimpl::SubgraphMatch match = cv::gimpl::findMatches(pg, tg);
|
||||
|
||||
// Inspecting results:
|
||||
EXPECT_TRUE(match.ok());
|
||||
|
||||
auto nodes = match.nodes();
|
||||
EXPECT_EQ(3u, nodes.size());
|
||||
|
||||
const auto in_nh = cv::gimpl::GModel::dataNodeOf(tgm, in);
|
||||
const auto tmp_nh = cv::gimpl::GModel::dataNodeOf(tgm, tmp);
|
||||
|
||||
const auto op_nh = cv::gimpl::GModel::producerOf(tgm, tmp_nh); // dilate3x3
|
||||
|
||||
EXPECT_EQ(matching_test::S({in_nh, tmp_nh, op_nh}),
|
||||
nodes);
|
||||
|
||||
EXPECT_EQ(cv::gapi::imgproc::GDilate::id(), matching_test::opName(tgm, op_nh));
|
||||
|
||||
EXPECT_TRUE(matching_test::isConsumedBy(tgm, in_nh, op_nh));
|
||||
|
||||
|
||||
EXPECT_EQ(matching_test::S{ op_nh }, match.startOps());
|
||||
EXPECT_EQ(matching_test::S{ op_nh }, match.finishOps());
|
||||
EXPECT_EQ(matching_test::V{ in_nh }, match.protoIns());
|
||||
EXPECT_EQ(matching_test::V{ tmp_nh }, match.protoOuts());
|
||||
|
||||
EXPECT_GT(in_nh->outEdges().size(), 1u);
|
||||
EXPECT_GT(tmp_nh->outEdges().size(), 1u);
|
||||
}
|
||||
|
||||
//FIXME: The start ops matching shall be reworked to more smarter way.
|
||||
// Start ops matching shall get rid of non valid matchings sample,
|
||||
// where two identical start ops in the pattern refer to the only one in the test.
|
||||
TEST(PatternMatching, TestManySameStartOpsAndHinge)
|
||||
{
|
||||
// Pattern
|
||||
ade::Graph pg;
|
||||
{
|
||||
GMat in1, in2, in3;
|
||||
GMat er1 = cv::gapi::erode3x3(in1);
|
||||
GMat er2 = cv::gapi::erode3x3(in2);
|
||||
GMat er3 = cv::gapi::erode3x3(in3);
|
||||
GMat mrg = cv::gapi::merge3(er1, er2, er3);
|
||||
matching_test::initGModel(pg, cv::GIn(in1, in2, in3), cv::GOut(mrg));
|
||||
}
|
||||
|
||||
// Test
|
||||
ade::Graph tg;
|
||||
GMat in1, in2, in3;
|
||||
GMat er1 = cv::gapi::erode3x3(in1);
|
||||
GMat er2 = cv::gapi::erode3x3(in2);
|
||||
GMat er3 = cv::gapi::erode3x3(in3);
|
||||
GMat mrg = cv::gapi::merge3(er1, er2, er3);
|
||||
matching_test::initGModel(tg, cv::GIn(in1, in2, in3), cv::GOut(mrg));
|
||||
|
||||
// Pattern Matching
|
||||
cv::gimpl::GModel::Graph pgm(pg);
|
||||
cv::gimpl::GModel::Graph tgm(tg);
|
||||
cv::gimpl::SubgraphMatch match = cv::gimpl::findMatches(pg, tg);
|
||||
|
||||
// Inspecting results:
|
||||
EXPECT_TRUE(match.ok());
|
||||
|
||||
auto nodes = match.nodes();
|
||||
EXPECT_EQ(11u, nodes.size());
|
||||
EXPECT_EQ(matching_test::S(tgm.nodes().begin(), tgm.nodes().end()),
|
||||
nodes);
|
||||
}
|
||||
|
||||
//FIXME: The start ops matching shall be reworked to more smarter way.
|
||||
// Start ops matching shall get rid of non valid matchings sample,
|
||||
// where two identical start ops in the pattern refer to the only one in the test.
|
||||
TEST(PatternMatching, TestManySameStartOpsAndHinge2)
|
||||
{
|
||||
// Pattern
|
||||
ade::Graph pg;
|
||||
{
|
||||
GMat in1, in2, in3;
|
||||
GMat er1 = cv::gapi::erode3x3(in1);
|
||||
GMat er2 = cv::gapi::erode3x3(in2);
|
||||
GMat er3 = cv::gapi::erode3x3(in3);
|
||||
GMat dil1 = cv::gapi::dilate3x3(er1);
|
||||
GMat dil2 = cv::gapi::dilate3x3(er2);
|
||||
GMat dil3 = cv::gapi::dilate3x3(er3);
|
||||
GMat mrg = cv::gapi::merge3(dil1, dil2, dil3);
|
||||
matching_test::initGModel(pg, cv::GIn(in1, in2, in3), cv::GOut(mrg));
|
||||
}
|
||||
|
||||
// Test
|
||||
ade::Graph tg;
|
||||
GMat in1, in2, in3;
|
||||
GMat er1 = cv::gapi::erode3x3(in1);
|
||||
GMat er2 = cv::gapi::erode3x3(in2);
|
||||
GMat er3 = cv::gapi::erode3x3(in3);
|
||||
GMat dil1 = cv::gapi::dilate3x3(er1);
|
||||
GMat dil2 = cv::gapi::dilate3x3(er2);
|
||||
GMat dil3 = cv::gapi::dilate3x3(er3);
|
||||
GMat mrg = cv::gapi::merge3(dil1, dil2, dil3);
|
||||
matching_test::initGModel(tg, cv::GIn(in1, in2, in3), cv::GOut(mrg));
|
||||
|
||||
// Pattern Matching
|
||||
cv::gimpl::GModel::Graph pgm(pg);
|
||||
cv::gimpl::GModel::Graph tgm(tg);
|
||||
cv::gimpl::SubgraphMatch match = cv::gimpl::findMatches(pg, tg);
|
||||
|
||||
// Inspecting results:
|
||||
EXPECT_TRUE(match.ok());
|
||||
|
||||
auto nodes = match.nodes();
|
||||
EXPECT_EQ(17u, nodes.size());
|
||||
EXPECT_EQ(matching_test::S(tgm.nodes().begin(), tgm.nodes().end()),
|
||||
nodes);
|
||||
}
|
||||
|
||||
//FIXME: The start ops matching shall be reworked to more smarter way.
|
||||
// Start ops matching shall get rid of non valid matchings sample,
|
||||
// where two identical start ops in the pattern refer to the only one in the test.
|
||||
TEST(PatternMatching, TestTwoChainsOnTheHingeIsomorphism)
|
||||
{
|
||||
// Pattern
|
||||
ade::Graph pg;
|
||||
{
|
||||
GMat in1, in2;
|
||||
GMat er1 = cv::gapi::erode3x3(in1);
|
||||
GMat er2 = cv::gapi::erode3x3(in2);
|
||||
GMat mdb = cv::gapi::medianBlur(er1, 3);
|
||||
GMat gb = cv::gapi::gaussianBlur(er2, cv::Size(5, 5), 0.12);
|
||||
GMat conc = cv::gapi::concatVert(mdb, gb);
|
||||
matching_test::initGModel(pg, cv::GIn(in1, in2), cv::GOut(conc));
|
||||
}
|
||||
|
||||
// Test
|
||||
ade::Graph tg;
|
||||
GMat in1, in2;
|
||||
GMat er1 = cv::gapi::erode3x3(in1);
|
||||
GMat er2 = cv::gapi::erode3x3(in2);
|
||||
GMat gb = cv::gapi::gaussianBlur(er1, cv::Size(5, 5), 0.12);
|
||||
GMat mdb = cv::gapi::medianBlur(er2, 3);
|
||||
GMat conc = cv::gapi::concatVert(mdb, gb);
|
||||
matching_test::initGModel(tg, cv::GIn(in1, in2), cv::GOut(conc));
|
||||
|
||||
// Pattern Matching
|
||||
cv::gimpl::GModel::Graph pgm(pg);
|
||||
cv::gimpl::GModel::Graph tgm(tg);
|
||||
cv::gimpl::SubgraphMatch match = cv::gimpl::findMatches(pg, tg);
|
||||
|
||||
// Inspecting results:
|
||||
EXPECT_TRUE(match.ok());
|
||||
|
||||
auto nodes = match.nodes();
|
||||
EXPECT_EQ(12u, nodes.size());
|
||||
EXPECT_EQ(matching_test::S(tgm.nodes().begin(), tgm.nodes().end()),
|
||||
nodes);
|
||||
|
||||
const auto in1_nh = cv::gimpl::GModel::dataNodeOf(tgm, in1);
|
||||
const auto in2_nh = cv::gimpl::GModel::dataNodeOf(tgm, in2);
|
||||
|
||||
EXPECT_EQ(matching_test::V({ in2_nh, in1_nh }), match.protoIns());
|
||||
}
|
||||
|
||||
TEST(PatternMatching, TestPatternHasMoreInDataNodes)
|
||||
{
|
||||
// Pattern
|
||||
ade::Graph pg;
|
||||
{
|
||||
GMat in1, in2, in3;
|
||||
GMat out = cv::gapi::merge3(in1, in2, in3);
|
||||
matching_test::initGModel(pg, cv::GIn(in1, in2, in3), cv::GOut(out));
|
||||
}
|
||||
|
||||
// Test
|
||||
ade::Graph tg;
|
||||
GMat in;
|
||||
GMat out = cv::gapi::merge3(in, in, in);
|
||||
matching_test::initGModel(tg, cv::GIn(in), cv::GOut(out));
|
||||
|
||||
// Pattern Matching
|
||||
cv::gimpl::GModel::Graph pgm(pg);
|
||||
cv::gimpl::GModel::Graph tgm(tg);
|
||||
cv::gimpl::SubgraphMatch match = cv::gimpl::findMatches(pg, tg);
|
||||
|
||||
// Inspecting results:
|
||||
EXPECT_TRUE(match.ok());
|
||||
|
||||
auto nodes = match.nodes();
|
||||
EXPECT_EQ(3u, nodes.size());
|
||||
EXPECT_EQ(matching_test::S(tgm.nodes().begin(), tgm.nodes().end()),
|
||||
nodes);
|
||||
|
||||
const auto in_nh = cv::gimpl::GModel::dataNodeOf(tgm, in);
|
||||
|
||||
EXPECT_EQ(matching_test::V({ in_nh, in_nh, in_nh }), match.protoIns());
|
||||
}
|
||||
|
||||
TEST(PatternMatching, TestPatternHasFewerInDataNodes)
|
||||
{
|
||||
// Pattern
|
||||
ade::Graph pg;
|
||||
{
|
||||
GMat in;
|
||||
GMat out = cv::gapi::merge3(in, in, in);
|
||||
matching_test::initGModel(pg, cv::GIn(in), cv::GOut(out));
|
||||
}
|
||||
|
||||
// Test
|
||||
ade::Graph tg;
|
||||
GMat in1, in2, in3;
|
||||
GMat out = cv::gapi::merge3(in1, in2, in3);
|
||||
matching_test::initGModel(tg, cv::GIn(in1, in2, in3), cv::GOut(out));
|
||||
|
||||
// Pattern Matching
|
||||
cv::gimpl::GModel::Graph pgm(pg);
|
||||
cv::gimpl::GModel::Graph tgm(tg);
|
||||
cv::gimpl::SubgraphMatch match = cv::gimpl::findMatches(pg, tg);
|
||||
|
||||
// Inspecting results:
|
||||
EXPECT_FALSE(match.ok());
|
||||
}
|
||||
|
||||
TEST(PatternMatching, TestTwoMatchingsOneCorrect)
|
||||
{
|
||||
// Pattern
|
||||
ade::Graph pg;
|
||||
{
|
||||
GMat in1, in2;
|
||||
GMat n = cv::gapi::bitwise_not(in1);
|
||||
GMat e = cv::gapi::erode3x3(in1);
|
||||
GMat d = cv::gapi::dilate3x3(in2);
|
||||
GMat out = cv::gapi::merge3(n, e, d);
|
||||
matching_test::initGModel(pg, cv::GIn(in1, in2), cv::GOut(out));
|
||||
}
|
||||
|
||||
// Test
|
||||
ade::Graph tg;
|
||||
GMat in1, in2;
|
||||
GMat n = cv::gapi::bitwise_not(in1);
|
||||
GMat e = cv::gapi::erode3x3(in2);
|
||||
GMat d = cv::gapi::dilate3x3(in2);
|
||||
GMat mrg = cv::gapi::merge3(n, e, d);
|
||||
GMat i, sqi;
|
||||
std::tie(i, sqi) = cv::gapi::integral(mrg);
|
||||
GMat n1 = cv::gapi::bitwise_not(i);
|
||||
GMat e1 = cv::gapi::erode3x3(i);
|
||||
GMat d1 = cv::gapi::dilate3x3(sqi);
|
||||
GMat out = cv::gapi::merge3(n1, e1, d1);
|
||||
matching_test::initGModel(tg, cv::GIn(in1, in2), cv::GOut(out));
|
||||
|
||||
// Pattern Matching
|
||||
cv::gimpl::GModel::Graph pgm(pg);
|
||||
cv::gimpl::GModel::Graph tgm(tg);
|
||||
cv::gimpl::SubgraphMatch match = cv::gimpl::findMatches(pg, tg);
|
||||
|
||||
// Inspecting results:
|
||||
EXPECT_TRUE(match.ok());
|
||||
|
||||
auto nodes = match.nodes();
|
||||
EXPECT_EQ(10u, nodes.size());
|
||||
|
||||
const auto i_nh = cv::gimpl::GModel::dataNodeOf(tgm, i);
|
||||
const auto sqi_nh = cv::gimpl::GModel::dataNodeOf(tgm, sqi);
|
||||
const auto n1_nh = cv::gimpl::GModel::dataNodeOf(tgm, n1);
|
||||
const auto e1_nh = cv::gimpl::GModel::dataNodeOf(tgm, e1);
|
||||
const auto d1_nh = cv::gimpl::GModel::dataNodeOf(tgm, d1);
|
||||
const auto out_nh = cv::gimpl::GModel::dataNodeOf(tgm, out);
|
||||
|
||||
const auto n_op_nh = cv::gimpl::GModel::producerOf(tgm, n1_nh);
|
||||
const auto e_op_nh = cv::gimpl::GModel::producerOf(tgm, e1_nh);
|
||||
const auto d_op_nh = cv::gimpl::GModel::producerOf(tgm, d1_nh);
|
||||
const auto m_op_nh = cv::gimpl::GModel::producerOf(tgm, out_nh);
|
||||
|
||||
EXPECT_EQ(matching_test::S({i_nh, sqi_nh, n1_nh, e1_nh, d1_nh, out_nh,
|
||||
n_op_nh, e_op_nh, d_op_nh, m_op_nh}), nodes);
|
||||
|
||||
EXPECT_EQ(cv::gapi::core::GNot::id(), matching_test::opName(tgm, n_op_nh));
|
||||
EXPECT_EQ(cv::gapi::imgproc::GErode::id(), matching_test::opName(tgm, e_op_nh));
|
||||
EXPECT_EQ(cv::gapi::imgproc::GDilate::id(), matching_test::opName(tgm, d_op_nh));
|
||||
EXPECT_EQ(cv::gapi::core::GMerge3::id(), matching_test::opName(tgm, m_op_nh));
|
||||
|
||||
EXPECT_TRUE(matching_test::isConsumedBy(tgm, i_nh, n_op_nh));
|
||||
EXPECT_TRUE(matching_test::isConsumedBy(tgm, i_nh, e_op_nh));
|
||||
EXPECT_TRUE(matching_test::isConsumedBy(tgm, sqi_nh, d_op_nh));
|
||||
EXPECT_TRUE(matching_test::isConsumedBy(tgm, n1_nh, m_op_nh));
|
||||
EXPECT_TRUE(matching_test::isConsumedBy(tgm, e1_nh, m_op_nh));
|
||||
EXPECT_TRUE(matching_test::isConsumedBy(tgm, d1_nh, m_op_nh));
|
||||
EXPECT_EQ(1u, n1_nh->outEdges().size());
|
||||
EXPECT_EQ(1u, e1_nh->outEdges().size());
|
||||
EXPECT_EQ(1u, d1_nh->outEdges().size());
|
||||
|
||||
EXPECT_EQ(matching_test::S({n_op_nh, e_op_nh, d_op_nh}), match.startOps());
|
||||
EXPECT_EQ(matching_test::S{m_op_nh}, match.finishOps());
|
||||
EXPECT_EQ(matching_test::V({i_nh, sqi_nh}), match.protoIns());
|
||||
EXPECT_EQ(matching_test::V{out_nh}, match.protoOuts());}
|
||||
|
||||
TEST(PatternMatching, CheckNoMatch)
|
||||
{
|
||||
// Pattern
|
||||
ade::Graph pg;
|
||||
{
|
||||
GMat in;
|
||||
GMat tmp = cv::gapi::filter2D(in, -1, {});
|
||||
GMat out = cv::gapi::filter2D(tmp, -1, {});
|
||||
matching_test::initGModel(pg, cv::GIn(in), cv::GOut(out));
|
||||
}
|
||||
|
||||
// Test
|
||||
ade::Graph tg;
|
||||
{
|
||||
GMat in;
|
||||
GMat tmp1 = cv::gapi::erode3x3(in);
|
||||
GMat out = cv::gapi::dilate3x3(tmp1);
|
||||
matching_test::initGModel(tg, cv::GIn(in), cv::GOut(out));
|
||||
}
|
||||
|
||||
// Pattern Matching
|
||||
cv::gimpl::GModel::Graph pgm(pg);
|
||||
cv::gimpl::GModel::Graph tgm(tg);
|
||||
cv::gimpl::SubgraphMatch match = cv::gimpl::findMatches(pg, tg);
|
||||
|
||||
// Inspecting results:
|
||||
EXPECT_FALSE(match.ok());
|
||||
}
|
||||
|
||||
TEST(PatternMatching, adeSmokeTest)
|
||||
{
|
||||
ade::Graph g;
|
||||
ade::NodeHandle src = g.createNode();
|
||||
ade::NodeHandle dst = g.createNode();
|
||||
g.link(src, dst);
|
||||
g.link(src, dst);
|
||||
|
||||
EXPECT_EQ(2u, dst->inNodes().size());
|
||||
}
|
||||
|
||||
} // namespace opencv_test
|
649
3rdparty/opencv-4.5.4/modules/gapi/test/internal/gapi_int_perform_substitution_test.cpp
vendored
Normal file
649
3rdparty/opencv-4.5.4/modules/gapi/test/internal/gapi_int_perform_substitution_test.cpp
vendored
Normal file
@ -0,0 +1,649 @@
|
||||
// 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) 2019 Intel Corporation
|
||||
|
||||
|
||||
#include "../test_precomp.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <opencv2/gapi/gtransform.hpp>
|
||||
#include <opencv2/gapi/cpu/core.hpp>
|
||||
#include <opencv2/gapi/cpu/imgproc.hpp>
|
||||
|
||||
#include "compiler/gmodel.hpp"
|
||||
#include "compiler/gmodel_priv.hpp"
|
||||
|
||||
#include "api/gcomputation_priv.hpp"
|
||||
#include "compiler/gcompiler.hpp"
|
||||
#include "compiler/gmodelbuilder.hpp"
|
||||
#include "compiler/passes/passes.hpp"
|
||||
|
||||
#include "compiler/passes/pattern_matching.hpp"
|
||||
|
||||
#include "../common/gapi_tests_common.hpp"
|
||||
|
||||
#include "logger.hpp"
|
||||
|
||||
namespace opencv_test
|
||||
{
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Accuracy integration tests (GComputation-level)
|
||||
|
||||
namespace {
|
||||
// FIXME: replace listener with something better (e.g. check graph via GModel?)
|
||||
// custom "listener" to check what kernels are called within the test
|
||||
struct KernelListener { std::map<std::string, size_t> counts; };
|
||||
KernelListener& getListener() {
|
||||
static KernelListener l;
|
||||
return l;
|
||||
}
|
||||
|
||||
using CompCreator = std::function<cv::GComputation()>;
|
||||
using CompileArgsCreator = std::function<cv::GCompileArgs()>;
|
||||
using Verifier = std::function<void(KernelListener)>;
|
||||
} // anonymous namespace
|
||||
|
||||
// Custom kernels && transformations below:
|
||||
|
||||
G_TYPED_KERNEL(MyNV12toBGR, <GMat(GMat, GMat)>, "test.my_nv12_to_bgr") {
|
||||
static GMatDesc outMeta(GMatDesc in_y, GMatDesc in_uv) {
|
||||
return cv::gapi::imgproc::GNV12toBGR::outMeta(in_y, in_uv);
|
||||
}
|
||||
};
|
||||
GAPI_OCV_KERNEL(MyNV12toBGRImpl, MyNV12toBGR)
|
||||
{
|
||||
static void run(const cv::Mat& in_y, const cv::Mat& in_uv, cv::Mat &out)
|
||||
{
|
||||
getListener().counts[MyNV12toBGR::id()]++;
|
||||
cv::cvtColorTwoPlane(in_y, in_uv, out, cv::COLOR_YUV2BGR_NV12);
|
||||
}
|
||||
};
|
||||
G_TYPED_KERNEL(MyPlanarResize, <GMatP(GMatP, Size, int)>, "test.my_planar_resize") {
|
||||
static GMatDesc outMeta(GMatDesc in, Size sz, int interp) {
|
||||
return cv::gapi::core::GResizeP::outMeta(in, sz, interp);
|
||||
}
|
||||
};
|
||||
GAPI_OCV_KERNEL(MyPlanarResizeImpl, MyPlanarResize) {
|
||||
static void run(const cv::Mat& in, cv::Size out_sz, int interp, cv::Mat &out)
|
||||
{
|
||||
getListener().counts[MyPlanarResize::id()]++;
|
||||
int inH = in.rows / 3;
|
||||
int inW = in.cols;
|
||||
int outH = out.rows / 3;
|
||||
int outW = out.cols;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
auto in_plane = in(cv::Rect(0, i*inH, inW, inH));
|
||||
auto out_plane = out(cv::Rect(0, i*outH, outW, outH));
|
||||
cv::resize(in_plane, out_plane, out_sz, 0, 0, interp);
|
||||
}
|
||||
}
|
||||
};
|
||||
G_TYPED_KERNEL(MyInterleavedResize, <GMat(GMat, Size, int)>, "test.my_interleaved_resize") {
|
||||
static GMatDesc outMeta(GMatDesc in, Size sz, int interp) {
|
||||
return cv::gapi::core::GResize::outMeta(in, sz, 0.0, 0.0, interp);
|
||||
}
|
||||
};
|
||||
GAPI_OCV_KERNEL(MyInterleavedResizeImpl, MyInterleavedResize) {
|
||||
static void run(const cv::Mat& in, cv::Size out_sz, int interp, cv::Mat &out)
|
||||
{
|
||||
getListener().counts[MyInterleavedResize::id()]++;
|
||||
cv::resize(in, out, out_sz, 0.0, 0.0, interp);
|
||||
}
|
||||
};
|
||||
G_TYPED_KERNEL(MyToNCHW, <GMatP(GMat)>, "test.my_to_nchw") {
|
||||
static GMatDesc outMeta(GMatDesc in) {
|
||||
GAPI_Assert(in.depth == CV_8U);
|
||||
GAPI_Assert(in.chan == 3);
|
||||
GAPI_Assert(in.planar == false);
|
||||
return in.asPlanar();
|
||||
}
|
||||
};
|
||||
GAPI_OCV_KERNEL(MyToNCHWImpl, MyToNCHW) {
|
||||
static void run(const cv::Mat& in, cv::Mat& out)
|
||||
{
|
||||
getListener().counts[MyToNCHW::id()]++;
|
||||
auto sz = in.size();
|
||||
auto w = sz.width;
|
||||
auto h = sz.height;
|
||||
cv::Mat ins[3] = {};
|
||||
cv::split(in, ins);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
auto in_plane = ins[i];
|
||||
auto out_plane = out(cv::Rect(0, i*h, w, h));
|
||||
in_plane.copyTo(out_plane);
|
||||
}
|
||||
}
|
||||
};
|
||||
using GMat4 = std::tuple<GMat, GMat, GMat, GMat>;
|
||||
G_TYPED_KERNEL_M(MySplit4, <GMat4(GMat)>, "test.my_split4") {
|
||||
static std::tuple<GMatDesc, GMatDesc, GMatDesc, GMatDesc> outMeta(GMatDesc in) {
|
||||
const auto out_depth = in.depth;
|
||||
const auto out_desc = in.withType(out_depth, 1);
|
||||
return std::make_tuple(out_desc, out_desc, out_desc, out_desc);
|
||||
}
|
||||
};
|
||||
GAPI_OCV_KERNEL(MySplit4Impl, MySplit4) {
|
||||
static void run(const cv::Mat& in, cv::Mat& out1, cv::Mat& out2, cv::Mat& out3, cv::Mat& out4)
|
||||
{
|
||||
getListener().counts[MySplit4::id()]++;
|
||||
cv::Mat outs[] = { out1, out2, out3, out4 };
|
||||
cv::split(in, outs);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_TRANSFORM(NV12Transform, <cv::GMat(cv::GMat, cv::GMat)>, "test.nv12_transform")
|
||||
{
|
||||
static cv::GMat pattern(const cv::GMat& y, const cv::GMat& uv)
|
||||
{
|
||||
GMat out = cv::gapi::NV12toBGR(y, uv);
|
||||
return out;
|
||||
}
|
||||
|
||||
static cv::GMat substitute(const cv::GMat& y, const cv::GMat& uv)
|
||||
{
|
||||
GMat out = MyNV12toBGR::on(y, uv);
|
||||
return out;
|
||||
}
|
||||
};
|
||||
GAPI_TRANSFORM(ResizeTransform, <cv::GMat(cv::GMat)>, "3 x Resize -> Interleaved Resize")
|
||||
{
|
||||
static cv::GMat pattern(const cv::GMat& in)
|
||||
{
|
||||
GMat b, g, r;
|
||||
std::tie(b, g, r) = cv::gapi::split3(in);
|
||||
const auto resize = std::bind(&cv::gapi::resize, std::placeholders::_1,
|
||||
cv::Size(100, 100), 0, 0, cv::INTER_AREA);
|
||||
return cv::gapi::merge3(resize(b), resize(g), resize(r));
|
||||
}
|
||||
|
||||
static cv::GMat substitute(const cv::GMat& in)
|
||||
{
|
||||
return MyInterleavedResize::on(in, cv::Size(100, 100), cv::INTER_AREA);
|
||||
}
|
||||
};
|
||||
GAPI_TRANSFORM(ResizeTransformToCustom, <cv::GMat(cv::GMat)>, "Resize -> Custom Resize")
|
||||
{
|
||||
static cv::GMat pattern(const cv::GMat& in)
|
||||
{
|
||||
return cv::gapi::resize(in, cv::Size(100, 100), 0, 0, cv::INTER_AREA);
|
||||
}
|
||||
|
||||
static cv::GMat substitute(const cv::GMat& in)
|
||||
{
|
||||
return MyInterleavedResize::on(in, cv::Size(100, 100), cv::INTER_AREA);
|
||||
}
|
||||
};
|
||||
GAPI_TRANSFORM(ChainTransform1, <GMatP(GMat)>, "Resize + toNCHW -> toNCHW + PlanarResize")
|
||||
{
|
||||
static GMatP pattern(const cv::GMat& in)
|
||||
{
|
||||
return MyToNCHW::on(cv::gapi::resize(in, cv::Size(60, 60)));
|
||||
}
|
||||
|
||||
static GMatP substitute(const cv::GMat& in)
|
||||
{
|
||||
return MyPlanarResize::on(MyToNCHW::on(in), cv::Size(60, 60), cv::INTER_LINEAR);
|
||||
}
|
||||
};
|
||||
GAPI_TRANSFORM(ChainTransform2, <GMatP(GMat, GMat)>, "NV12toBGR + toNCHW -> NV12toBGRp")
|
||||
{
|
||||
static GMatP pattern(const GMat& y, const GMat& uv)
|
||||
{
|
||||
return MyToNCHW::on(MyNV12toBGR::on(y, uv));
|
||||
}
|
||||
|
||||
static GMatP substitute(const GMat& y, const GMat& uv)
|
||||
{
|
||||
return cv::gapi::NV12toBGRp(y, uv);
|
||||
}
|
||||
};
|
||||
GAPI_TRANSFORM(Split4Transform, <GMat4(GMat)>, "Split4 -> Custom Split4")
|
||||
{
|
||||
static GMat4 pattern(const GMat& in)
|
||||
{
|
||||
return cv::gapi::split4(in);
|
||||
}
|
||||
|
||||
static GMat4 substitute(const GMat& in)
|
||||
{
|
||||
return MySplit4::on(in);
|
||||
}
|
||||
};
|
||||
GAPI_TRANSFORM(Split4Merge3Transform, <GMat(GMat)>, "Split4 + Merge3 -> Custom Split4 + Merge3")
|
||||
{
|
||||
static GMat pattern(const GMat& in)
|
||||
{
|
||||
GMat tmp1, tmp2, tmp3, unused;
|
||||
std::tie(tmp1, tmp2, tmp3, unused) = cv::gapi::split4(in);
|
||||
return cv::gapi::merge3(tmp1, tmp2, tmp3);
|
||||
}
|
||||
|
||||
static GMat substitute(const GMat& in)
|
||||
{
|
||||
GMat tmp1, tmp2, tmp3, unused;
|
||||
std::tie(tmp1, tmp2, tmp3, unused) = MySplit4::on(in);
|
||||
return cv::gapi::merge3(tmp1, tmp2, tmp3);
|
||||
}
|
||||
};
|
||||
GAPI_TRANSFORM(Merge4Split4Transform, <GMat4(GMat, GMat, GMat, GMat)>,
|
||||
"Merge4 + Split4 -> Merge4 + Custom Split4")
|
||||
{
|
||||
static GMat4 pattern(const GMat& in1, const GMat& in2, const GMat& in3,
|
||||
const GMat& in4)
|
||||
{
|
||||
return cv::gapi::split4(cv::gapi::merge4(in1, in2, in3, in4));
|
||||
}
|
||||
|
||||
static GMat4 substitute(const GMat& in1, const GMat& in2, const GMat& in3,
|
||||
const GMat& in4)
|
||||
{
|
||||
return MySplit4::on(cv::gapi::merge4(in1, in2, in3, in4));
|
||||
}
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Integration tests
|
||||
|
||||
TEST(PatternMatchingIntegrationBasic, OneTransformationApplied)
|
||||
{
|
||||
cv::Size in_sz(640, 480);
|
||||
cv::Mat input(in_sz, CV_8UC3);
|
||||
cv::randu(input, cv::Scalar::all(0), cv::Scalar::all(100));
|
||||
cv::Mat orig_graph_output, transformed_graph_output;
|
||||
|
||||
auto orig_args = cv::compile_args();
|
||||
auto transform_args = cv::compile_args(
|
||||
cv::gapi::kernels<MyInterleavedResizeImpl, ResizeTransform>());
|
||||
|
||||
auto& listener = getListener();
|
||||
listener.counts.clear(); // clear counters before testing
|
||||
|
||||
const auto make_computation = [] () {
|
||||
GMat in;
|
||||
GMat b, g, r;
|
||||
std::tie(b, g, r) = cv::gapi::split3(in);
|
||||
const auto resize = std::bind(&cv::gapi::resize, std::placeholders::_1,
|
||||
cv::Size(100, 100), 0, 0, cv::INTER_AREA);
|
||||
GMat out = cv::gapi::merge3(resize(b), resize(g), resize(r));
|
||||
return cv::GComputation(cv::GIn(in), cv::GOut(out));
|
||||
};
|
||||
|
||||
{
|
||||
// Run original graph
|
||||
auto mainC = make_computation();
|
||||
mainC.apply(cv::gin(input), cv::gout(orig_graph_output), std::move(orig_args));
|
||||
}
|
||||
|
||||
// Generate transformed graph (passing transformations via compile args)
|
||||
auto mainC = make_computation(); // get new copy with new Priv
|
||||
mainC.apply(cv::gin(input), cv::gout(transformed_graph_output), std::move(transform_args));
|
||||
|
||||
// Compare
|
||||
ASSERT_TRUE(AbsExact()(orig_graph_output, transformed_graph_output));
|
||||
|
||||
// Custom verification via listener
|
||||
ASSERT_EQ(1u, listener.counts.size());
|
||||
// called in transformed graph:
|
||||
ASSERT_NE(listener.counts.cend(), listener.counts.find(MyInterleavedResize::id()));
|
||||
ASSERT_EQ(1u, listener.counts.at(MyInterleavedResize::id()));
|
||||
}
|
||||
|
||||
TEST(PatternMatchingIntegrationBasic, SameTransformationAppliedSeveralTimes)
|
||||
{
|
||||
cv::Size in_sz(640, 480);
|
||||
cv::Mat input(in_sz, CV_8UC3);
|
||||
cv::randu(input, cv::Scalar::all(0), cv::Scalar::all(100));
|
||||
cv::Mat orig_graph_output, transformed_graph_output;
|
||||
|
||||
auto orig_args = cv::compile_args();
|
||||
auto transform_args = cv::compile_args(
|
||||
cv::gapi::kernels<MyInterleavedResizeImpl, ResizeTransformToCustom>());
|
||||
|
||||
auto& listener = getListener();
|
||||
listener.counts.clear(); // clear counters before testing
|
||||
|
||||
const auto make_computation = [] () {
|
||||
GMat in;
|
||||
GMat b, g, r;
|
||||
std::tie(b, g, r) = cv::gapi::split3(in);
|
||||
const auto resize = std::bind(&cv::gapi::resize, std::placeholders::_1,
|
||||
cv::Size(100, 100), 0, 0, cv::INTER_AREA);
|
||||
GMat out = cv::gapi::merge3(resize(b), resize(g), resize(r));
|
||||
return cv::GComputation(cv::GIn(in), cv::GOut(out));
|
||||
};
|
||||
|
||||
{
|
||||
// Run original graph
|
||||
auto mainC = make_computation();
|
||||
mainC.apply(cv::gin(input), cv::gout(orig_graph_output), std::move(orig_args));
|
||||
}
|
||||
|
||||
// Generate transformed graph (passing transformations via compile args)
|
||||
auto mainC = make_computation(); // get new copy with new Priv
|
||||
mainC.apply(cv::gin(input), cv::gout(transformed_graph_output), std::move(transform_args));
|
||||
|
||||
// Compare
|
||||
ASSERT_TRUE(AbsExact()(orig_graph_output, transformed_graph_output));
|
||||
|
||||
// Custom verification via listener
|
||||
ASSERT_EQ(1u, listener.counts.size());
|
||||
// called in transformed graph:
|
||||
ASSERT_NE(listener.counts.cend(), listener.counts.find(MyInterleavedResize::id()));
|
||||
ASSERT_EQ(3u, listener.counts.at(MyInterleavedResize::id()));
|
||||
}
|
||||
|
||||
TEST(PatternMatchingIntegrationBasic, OneNV12toBGRTransformationApplied)
|
||||
{
|
||||
cv::Size in_sz(640, 480);
|
||||
cv::Mat y(in_sz, CV_8UC1), uv(cv::Size(in_sz.width / 2, in_sz.height / 2), CV_8UC2);
|
||||
cv::randu(y, cv::Scalar::all(0), cv::Scalar::all(100));
|
||||
cv::randu(uv, cv::Scalar::all(100), cv::Scalar::all(200));
|
||||
cv::Mat orig_graph_output, transformed_graph_output;
|
||||
|
||||
auto orig_args = cv::compile_args();
|
||||
auto transform_args = cv::compile_args(cv::gapi::kernels<MyNV12toBGRImpl, NV12Transform>());
|
||||
|
||||
auto& listener = getListener();
|
||||
listener.counts.clear(); // clear counters before testing
|
||||
|
||||
const auto make_computation = [] () {
|
||||
GMat in1, in2;
|
||||
GMat bgr = cv::gapi::NV12toBGR(in1, in2);
|
||||
GMat out = cv::gapi::resize(bgr, cv::Size(100, 100));
|
||||
return cv::GComputation(cv::GIn(in1, in2), cv::GOut(out));
|
||||
};
|
||||
|
||||
{
|
||||
// Run original graph
|
||||
auto mainC = make_computation();
|
||||
mainC.apply(cv::gin(y, uv), cv::gout(orig_graph_output), std::move(orig_args));
|
||||
}
|
||||
|
||||
// Generate transformed graph (passing transformations via compile args)
|
||||
auto mainC = make_computation(); // get new copy with new Priv
|
||||
mainC.apply(cv::gin(y, uv), cv::gout(transformed_graph_output), std::move(transform_args));
|
||||
|
||||
// Compare
|
||||
ASSERT_TRUE(AbsExact()(orig_graph_output, transformed_graph_output));
|
||||
|
||||
// Custom verification via listener
|
||||
ASSERT_EQ(1u, listener.counts.size());
|
||||
// called in transformed graph:
|
||||
ASSERT_NE(listener.counts.cend(), listener.counts.find(MyNV12toBGR::id()));
|
||||
ASSERT_EQ(1u, listener.counts.at(MyNV12toBGR::id()));
|
||||
}
|
||||
|
||||
TEST(PatternMatchingIntegrationBasic, TwoTransformationsApplied)
|
||||
{
|
||||
cv::Size in_sz(640, 480);
|
||||
cv::Mat y(in_sz, CV_8UC1), uv(cv::Size(in_sz.width / 2, in_sz.height / 2), CV_8UC2);
|
||||
cv::randu(y, cv::Scalar::all(0), cv::Scalar::all(100));
|
||||
cv::randu(uv, cv::Scalar::all(100), cv::Scalar::all(200));
|
||||
cv::Mat orig_graph_output, transformed_graph_output;
|
||||
|
||||
auto orig_args = cv::compile_args();
|
||||
auto transform_args = cv::compile_args(
|
||||
cv::gapi::kernels<MyNV12toBGRImpl, MyInterleavedResizeImpl, ResizeTransform,
|
||||
NV12Transform>()); // compile args with transformations
|
||||
|
||||
auto& listener = getListener();
|
||||
listener.counts.clear(); // clear counters before testing
|
||||
|
||||
const auto make_computation = [] () {
|
||||
GMat in1, in2;
|
||||
GMat bgr = cv::gapi::NV12toBGR(in1, in2);
|
||||
GMat b, g, r;
|
||||
std::tie(b, g, r) = cv::gapi::split3(bgr);
|
||||
const auto resize = std::bind(&cv::gapi::resize, std::placeholders::_1,
|
||||
cv::Size(100, 100), 0, 0, cv::INTER_AREA);
|
||||
GMat tmp1 = cv::gapi::resize(bgr, cv::Size(90, 90));
|
||||
GMat tmp2 = cv::gapi::bitwise_not(cv::gapi::merge3(resize(b), resize(g), resize(r)));
|
||||
GMat out = cv::gapi::resize(tmp1 + GScalar(10.0), cv::Size(100, 100)) + tmp2;
|
||||
return cv::GComputation(cv::GIn(in1, in2), cv::GOut(out));
|
||||
};
|
||||
|
||||
{
|
||||
// Run original graph
|
||||
auto mainC = make_computation();
|
||||
mainC.apply(cv::gin(y, uv), cv::gout(orig_graph_output), std::move(orig_args));
|
||||
}
|
||||
|
||||
// Generate transformed graph (passing transformations via compile args)
|
||||
auto mainC = make_computation(); // get new copy with new Priv
|
||||
mainC.apply(cv::gin(y, uv), cv::gout(transformed_graph_output), std::move(transform_args));
|
||||
|
||||
// Compare
|
||||
ASSERT_TRUE(AbsExact()(orig_graph_output, transformed_graph_output));
|
||||
|
||||
// Custom verification via listener
|
||||
ASSERT_EQ(2u, listener.counts.size());
|
||||
// called in transformed graph:
|
||||
ASSERT_NE(listener.counts.cend(), listener.counts.find(MyNV12toBGR::id()));
|
||||
ASSERT_EQ(1u, listener.counts.at(MyNV12toBGR::id()));
|
||||
ASSERT_NE(listener.counts.cend(), listener.counts.find(MyInterleavedResize::id()));
|
||||
ASSERT_EQ(1u, listener.counts.at(MyInterleavedResize::id()));
|
||||
}
|
||||
|
||||
struct PatternMatchingIntegrationE2E : testing::Test
|
||||
{
|
||||
cv::GComputation makeComputation() {
|
||||
GMat in1, in2;
|
||||
GMat bgr = MyNV12toBGR::on(in1, in2);
|
||||
GMat resized = cv::gapi::resize(bgr, cv::Size(60, 60));
|
||||
GMatP out = MyToNCHW::on(resized);
|
||||
return cv::GComputation(cv::GIn(in1, in2), cv::GOut(out));
|
||||
}
|
||||
|
||||
void runTest(cv::GCompileArgs&& transform_args) {
|
||||
cv::Size in_sz(640, 480);
|
||||
cv::Mat y(in_sz, CV_8UC1), uv(cv::Size(in_sz.width / 2, in_sz.height / 2), CV_8UC2);
|
||||
cv::randu(y, cv::Scalar::all(0), cv::Scalar::all(100));
|
||||
cv::randu(uv, cv::Scalar::all(100), cv::Scalar::all(200));
|
||||
cv::Mat orig_graph_output, transformed_graph_output;
|
||||
|
||||
auto& listener = getListener();
|
||||
listener.counts.clear(); // clear counters before testing
|
||||
{
|
||||
// Run original graph
|
||||
auto mainC = makeComputation();
|
||||
mainC.apply(cv::gin(y, uv), cv::gout(orig_graph_output),
|
||||
cv::compile_args(cv::gapi::kernels<MyNV12toBGRImpl, MyToNCHWImpl>()));
|
||||
}
|
||||
|
||||
// Generate transformed graph (passing transformations via compile args)
|
||||
auto mainC = makeComputation(); // get new copy with new Priv
|
||||
mainC.apply(cv::gin(y, uv), cv::gout(transformed_graph_output), std::move(transform_args));
|
||||
|
||||
// Compare
|
||||
ASSERT_TRUE(AbsExact()(orig_graph_output, transformed_graph_output));
|
||||
|
||||
// Custom verification via listener
|
||||
ASSERT_EQ(3u, listener.counts.size());
|
||||
// called in original graph:
|
||||
ASSERT_NE(listener.counts.cend(), listener.counts.find(MyNV12toBGR::id()));
|
||||
ASSERT_NE(listener.counts.cend(), listener.counts.find(MyToNCHW::id()));
|
||||
ASSERT_EQ(1u, listener.counts.at(MyNV12toBGR::id()));
|
||||
ASSERT_EQ(1u, listener.counts.at(MyToNCHW::id()));
|
||||
// called in transformed graph:
|
||||
ASSERT_NE(listener.counts.cend(), listener.counts.find(MyPlanarResize::id()));
|
||||
ASSERT_EQ(1u, listener.counts.at(MyPlanarResize::id()));
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(PatternMatchingIntegrationE2E, ChainTransformationsApplied)
|
||||
{
|
||||
runTest(cv::compile_args(
|
||||
cv::gapi::kernels<MyPlanarResizeImpl, ChainTransform1, ChainTransform2>()));
|
||||
}
|
||||
|
||||
TEST_F(PatternMatchingIntegrationE2E, ReversedChainTransformationsApplied)
|
||||
{
|
||||
runTest(cv::compile_args(
|
||||
cv::gapi::kernels<ChainTransform2, MyPlanarResizeImpl, ChainTransform1>()));
|
||||
}
|
||||
|
||||
struct PatternMatchingIntegrationUnusedNodes : testing::Test
|
||||
{
|
||||
cv::GComputation makeComputation() {
|
||||
GMat in1, in2;
|
||||
GMat bgr = cv::gapi::NV12toBGR(in1, in2);
|
||||
GMat b1, g1, r1;
|
||||
std::tie(b1, g1, r1) = cv::gapi::split3(bgr);
|
||||
// FIXME: easier way to call split4??
|
||||
GMat merged4 = cv::gapi::merge4(b1, g1, r1, b1);
|
||||
GMat b2, g2, r2, unused;
|
||||
std::tie(b2, g2, r2, unused) = cv::gapi::split4(merged4);
|
||||
GMat out = cv::gapi::merge3(b2, g2, r2);
|
||||
return cv::GComputation(cv::GIn(in1, in2), cv::GOut(out));
|
||||
}
|
||||
|
||||
void runTest(cv::GCompileArgs&& transform_args) {
|
||||
cv::Size in_sz(640, 480);
|
||||
cv::Mat y(in_sz, CV_8UC1), uv(cv::Size(in_sz.width / 2, in_sz.height / 2), CV_8UC2);
|
||||
cv::randu(y, cv::Scalar::all(0), cv::Scalar::all(100));
|
||||
cv::randu(uv, cv::Scalar::all(100), cv::Scalar::all(200));
|
||||
|
||||
cv::Mat orig_graph_output, transformed_graph_output;
|
||||
|
||||
auto& listener = getListener();
|
||||
listener.counts.clear(); // clear counters before testing
|
||||
{
|
||||
// Run original graph
|
||||
auto mainC = makeComputation();
|
||||
mainC.apply(cv::gin(y, uv), cv::gout(orig_graph_output),
|
||||
cv::compile_args(cv::gapi::kernels<MyNV12toBGRImpl, MyToNCHWImpl>()));
|
||||
}
|
||||
|
||||
// Generate transformed graph (passing transformations via compile args)
|
||||
auto mainC = makeComputation(); // get new copy with new Priv
|
||||
mainC.apply(cv::gin(y, uv), cv::gout(transformed_graph_output), std::move(transform_args));
|
||||
|
||||
// Compare
|
||||
ASSERT_TRUE(AbsExact()(orig_graph_output, transformed_graph_output));
|
||||
|
||||
// Custom verification via listener
|
||||
ASSERT_EQ(1u, listener.counts.size());
|
||||
// called in transformed graph:
|
||||
ASSERT_NE(listener.counts.cend(), listener.counts.find(MySplit4::id()));
|
||||
ASSERT_EQ(1u, listener.counts.at(MySplit4::id()));
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(PatternMatchingIntegrationUnusedNodes, SingleOpTransformApplied)
|
||||
{
|
||||
runTest(cv::compile_args(cv::gapi::kernels<MySplit4Impl, Split4Transform>()));
|
||||
}
|
||||
|
||||
// FIXME: enable once unused nodes are properly handled by Transformation API
|
||||
TEST_F(PatternMatchingIntegrationUnusedNodes, DISABLED_TransformWithInternalUnusedNodeApplied)
|
||||
{
|
||||
runTest(cv::compile_args(cv::gapi::kernels<MySplit4Impl, Split4Merge3Transform>()));
|
||||
}
|
||||
|
||||
TEST_F(PatternMatchingIntegrationUnusedNodes, TransformWithOutputUnusedNodeApplied)
|
||||
{
|
||||
runTest(cv::compile_args(cv::gapi::kernels<MySplit4Impl, Merge4Split4Transform>()));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Bad arg integration tests (GCompiler-level) - General
|
||||
|
||||
struct PatternMatchingIntegrationBadArgTests : testing::Test
|
||||
{
|
||||
cv::GComputation makeComputation() {
|
||||
GMat in;
|
||||
GMat a, b, c, d;
|
||||
std::tie(a, b, c, d) = MySplit4::on(in); // using custom Split4 to check if it's called
|
||||
GMat out = cv::gapi::merge3(a + b, cv::gapi::bitwise_not(c), d * cv::GScalar(2.0));
|
||||
return cv::GComputation(cv::GIn(in), cv::GOut(out));
|
||||
}
|
||||
|
||||
void runTest(cv::GCompileArgs&& transform_args) {
|
||||
cv::Size in_sz(640, 480);
|
||||
cv::Mat input(in_sz, CV_8UC4);
|
||||
cv::randu(input, cv::Scalar::all(70), cv::Scalar::all(140));
|
||||
|
||||
cv::Mat output;
|
||||
|
||||
// Generate transformed graph (passing transformations via compile args)
|
||||
auto mainC = makeComputation(); // get new copy with new Priv
|
||||
ASSERT_NO_THROW(mainC.apply(cv::gin(input), cv::gout(output), std::move(transform_args)));
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(PatternMatchingIntegrationBadArgTests, NoTransformations)
|
||||
{
|
||||
auto transform_args = cv::compile_args(cv::gapi::kernels<MySplit4Impl>());
|
||||
|
||||
auto& listener = getListener();
|
||||
listener.counts.clear(); // clear counters before testing
|
||||
|
||||
runTest(std::move(transform_args));
|
||||
|
||||
// Custom verification via listener
|
||||
ASSERT_EQ(1u, listener.counts.size());
|
||||
ASSERT_NE(listener.counts.cend(), listener.counts.find(MySplit4::id()));
|
||||
ASSERT_EQ(1u, listener.counts.at(MySplit4::id()));
|
||||
}
|
||||
|
||||
TEST_F(PatternMatchingIntegrationBadArgTests, WrongTransformation)
|
||||
{
|
||||
// Here Split4Transform::pattern is "looking for" cv::gapi::split4 but it's not used
|
||||
auto transform_args = cv::compile_args(cv::gapi::kernels<MySplit4Impl, Split4Transform>());
|
||||
|
||||
auto& listener = getListener();
|
||||
listener.counts.clear(); // clear counters before testing
|
||||
|
||||
runTest(std::move(transform_args));
|
||||
|
||||
// Custom verification via listener
|
||||
ASSERT_EQ(1u, listener.counts.size());
|
||||
ASSERT_NE(listener.counts.cend(), listener.counts.find(MySplit4::id()));
|
||||
ASSERT_EQ(1u, listener.counts.at(MySplit4::id()));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Bad arg integration tests (GCompiler-level) - Endless Loops
|
||||
|
||||
GAPI_TRANSFORM(EndlessLoopTransform, <cv::GMat(cv::GMat)>, "pattern in substitute")
|
||||
{
|
||||
static cv::GMat pattern(const cv::GMat& in)
|
||||
{
|
||||
return cv::gapi::resize(in, cv::Size(100, 100), 0, 0, cv::INTER_LINEAR);
|
||||
}
|
||||
|
||||
static cv::GMat substitute(const cv::GMat& in)
|
||||
{
|
||||
cv::GMat b, g, r;
|
||||
std::tie(b, g, r) = cv::gapi::split3(in);
|
||||
auto resize = std::bind(&cv::gapi::resize,
|
||||
std::placeholders::_1, cv::Size(100, 100), 0, 0, cv::INTER_LINEAR);
|
||||
cv::GMat out = cv::gapi::merge3(resize(b), resize(g), resize(r));
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
TEST(PatternMatchingIntegrationEndlessLoops, PatternInSubstituteInOneTransform)
|
||||
{
|
||||
cv::Size in_sz(640, 480);
|
||||
cv::Mat input(in_sz, CV_8UC3);
|
||||
cv::randu(input, cv::Scalar::all(0), cv::Scalar::all(100));
|
||||
|
||||
auto c = [] () {
|
||||
GMat in;
|
||||
GMat tmp = cv::gapi::resize(in, cv::Size(100, 100), 0, 0, cv::INTER_LINEAR);
|
||||
GMat out = cv::gapi::bitwise_not(tmp);
|
||||
return cv::GComputation(cv::GIn(in), cv::GOut(out));
|
||||
}();
|
||||
|
||||
EXPECT_THROW(
|
||||
cv::gimpl::GCompiler(c, cv::descr_of(cv::gin(input)),
|
||||
cv::compile_args(cv::gapi::kernels<EndlessLoopTransform>())),
|
||||
std::exception);
|
||||
}
|
||||
|
||||
|
||||
} // namespace opencv_test
|
35
3rdparty/opencv-4.5.4/modules/gapi/test/internal/gapi_int_proto_tests.cpp
vendored
Normal file
35
3rdparty/opencv-4.5.4/modules/gapi/test/internal/gapi_int_proto_tests.cpp
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
// 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
|
||||
|
||||
|
||||
#include "../test_precomp.hpp"
|
||||
#include "../src/api/gproto_priv.hpp"
|
||||
|
||||
namespace opencv_test {
|
||||
|
||||
template<typename T>
|
||||
struct ProtoPtrTest : public ::testing::Test { using Type = T; };
|
||||
|
||||
using ProtoPtrTestTypes = ::testing::Types< cv::Mat
|
||||
, cv::UMat
|
||||
, cv::gapi::own::Mat
|
||||
, cv::RMat
|
||||
, cv::Scalar
|
||||
, std::vector<int>
|
||||
, int
|
||||
>;
|
||||
|
||||
TYPED_TEST_CASE(ProtoPtrTest, ProtoPtrTestTypes);
|
||||
|
||||
TYPED_TEST(ProtoPtrTest, NonZero)
|
||||
{
|
||||
typename TestFixture::Type value;
|
||||
const auto arg = cv::gout(value).front();
|
||||
const auto ptr = cv::gimpl::proto::ptr(arg);
|
||||
EXPECT_EQ(ptr, &value);
|
||||
}
|
||||
|
||||
} // namespace opencv_test
|
232
3rdparty/opencv-4.5.4/modules/gapi/test/internal/gapi_int_recompilation_test.cpp
vendored
Normal file
232
3rdparty/opencv-4.5.4/modules/gapi/test/internal/gapi_int_recompilation_test.cpp
vendored
Normal file
@ -0,0 +1,232 @@
|
||||
// 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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#include "../test_precomp.hpp"
|
||||
#include "api/gcomputation_priv.hpp"
|
||||
|
||||
#include <opencv2/gapi/fluid/gfluidkernel.hpp>
|
||||
#include <opencv2/gapi/fluid/core.hpp>
|
||||
#include <opencv2/gapi/fluid/imgproc.hpp>
|
||||
|
||||
namespace opencv_test
|
||||
{
|
||||
|
||||
TEST(GComputationCompile, NoRecompileWithSameMeta)
|
||||
{
|
||||
cv::GMat in;
|
||||
cv::GComputation cc(in, in+in);
|
||||
|
||||
cv::Mat in_mat1 = cv::Mat::eye (32, 32, CV_8UC1);
|
||||
cv::Mat in_mat2 = cv::Mat::zeros(32, 32, CV_8UC1);
|
||||
cv::Mat out_mat;
|
||||
|
||||
cc.apply(in_mat1, out_mat);
|
||||
auto comp1 = cc.priv().m_lastCompiled;
|
||||
|
||||
cc.apply(in_mat2, out_mat);
|
||||
auto comp2 = cc.priv().m_lastCompiled;
|
||||
|
||||
// Both compiled objects are actually the same unique executable
|
||||
EXPECT_EQ(&comp1.priv(), &comp2.priv());
|
||||
}
|
||||
|
||||
TEST(GComputationCompile, NoRecompileWithWrongMeta)
|
||||
{
|
||||
cv::GMat in;
|
||||
cv::GComputation cc(in, in+in);
|
||||
|
||||
cv::Mat in_mat1 = cv::Mat::eye (32, 32, CV_8UC1);
|
||||
cv::Mat in_mat2 = cv::Mat::zeros(32, 32, CV_8UC1);
|
||||
cv::Mat out_mat;
|
||||
|
||||
cc.apply(in_mat1, out_mat);
|
||||
auto comp1 = cc.priv().m_lastCompiled;
|
||||
|
||||
EXPECT_THROW(cc.apply(cv::gin(cv::Scalar(128)), cv::gout(out_mat)), std::logic_error);
|
||||
auto comp2 = cc.priv().m_lastCompiled;
|
||||
|
||||
// Both compiled objects are actually the same unique executable
|
||||
EXPECT_EQ(&comp1.priv(), &comp2.priv());
|
||||
}
|
||||
|
||||
TEST(GComputationCompile, RecompileWithDifferentMeta)
|
||||
{
|
||||
cv::GMat in;
|
||||
cv::GComputation cc(in, in+in);
|
||||
|
||||
cv::Mat in_mat1 = cv::Mat::eye (32, 32, CV_8UC1);
|
||||
cv::Mat in_mat2 = cv::Mat::zeros(64, 64, CV_32F);
|
||||
cv::Mat out_mat;
|
||||
|
||||
cc.apply(in_mat1, out_mat);
|
||||
auto comp1 = cc.priv().m_lastCompiled;
|
||||
|
||||
cc.apply(in_mat2, out_mat);
|
||||
auto comp2 = cc.priv().m_lastCompiled;
|
||||
|
||||
// Both compiled objects are different
|
||||
EXPECT_NE(&comp1.priv(), &comp2.priv());
|
||||
}
|
||||
|
||||
TEST(GComputationCompile, FluidReshapeWithDifferentDims)
|
||||
{
|
||||
cv::GMat in;
|
||||
cv::GComputation cc(in, in+in);
|
||||
|
||||
cv::Mat in_mat1 = cv::Mat::eye (32, 32, CV_8UC1);
|
||||
cv::Mat in_mat2 = cv::Mat::zeros(64, 64, CV_8UC1);
|
||||
cv::Mat out_mat;
|
||||
|
||||
cc.apply(in_mat1, out_mat, cv::compile_args(cv::gapi::core::fluid::kernels()));
|
||||
auto comp1 = cc.priv().m_lastCompiled;
|
||||
|
||||
cc.apply(in_mat2, out_mat);
|
||||
auto comp2 = cc.priv().m_lastCompiled;
|
||||
|
||||
// Both compiled objects are actually the same unique executable
|
||||
EXPECT_EQ(&comp1.priv(), &comp2.priv());
|
||||
}
|
||||
|
||||
TEST(GComputationCompile, FluidReshapeResizeDownScale)
|
||||
{
|
||||
cv::Size szOut(4, 4);
|
||||
cv::GMat in;
|
||||
cv::GComputation cc(in, cv::gapi::resize(in, szOut));
|
||||
|
||||
cv::Mat in_mat1( 8, 8, CV_8UC3);
|
||||
cv::Mat in_mat2(16, 16, CV_8UC3);
|
||||
cv::randu(in_mat1, cv::Scalar::all(0), cv::Scalar::all(255));
|
||||
cv::randu(in_mat2, cv::Scalar::all(0), cv::Scalar::all(255));
|
||||
cv::Mat out_mat1, out_mat2;
|
||||
|
||||
cc.apply(in_mat1, out_mat1, cv::compile_args(cv::gapi::core::fluid::kernels()));
|
||||
auto comp1 = cc.priv().m_lastCompiled;
|
||||
|
||||
cc.apply(in_mat2, out_mat2);
|
||||
auto comp2 = cc.priv().m_lastCompiled;
|
||||
|
||||
// Both compiled objects are actually the same unique executable
|
||||
EXPECT_EQ(&comp1.priv(), &comp2.priv());
|
||||
|
||||
cv::Mat cv_out_mat1, cv_out_mat2;
|
||||
cv::resize(in_mat1, cv_out_mat1, szOut);
|
||||
cv::resize(in_mat2, cv_out_mat2, szOut);
|
||||
|
||||
EXPECT_EQ(0, cvtest::norm(out_mat1, cv_out_mat1, NORM_INF));
|
||||
EXPECT_EQ(0, cvtest::norm(out_mat2, cv_out_mat2, NORM_INF));
|
||||
}
|
||||
|
||||
TEST(GComputationCompile, FluidReshapeSwitchToUpscaleFromDownscale)
|
||||
{
|
||||
cv::Size szOut(4, 4);
|
||||
cv::GMat in;
|
||||
cv::GComputation cc(in, cv::gapi::resize(in, szOut));
|
||||
|
||||
cv::Mat in_mat1( 8, 8, CV_8UC3);
|
||||
cv::Mat in_mat2( 2, 2, CV_8UC3);
|
||||
cv::Mat in_mat3(16, 16, CV_8UC3);
|
||||
cv::randu(in_mat1, cv::Scalar::all(0), cv::Scalar::all(255));
|
||||
cv::randu(in_mat2, cv::Scalar::all(0), cv::Scalar::all(255));
|
||||
cv::randu(in_mat3, cv::Scalar::all(0), cv::Scalar::all(255));
|
||||
cv::Mat out_mat1, out_mat2, out_mat3;
|
||||
|
||||
cc.apply(in_mat1, out_mat1, cv::compile_args(cv::gapi::core::fluid::kernels()));
|
||||
auto comp1 = cc.priv().m_lastCompiled;
|
||||
|
||||
cc.apply(in_mat2, out_mat2);
|
||||
auto comp2 = cc.priv().m_lastCompiled;
|
||||
|
||||
cc.apply(in_mat3, out_mat3);
|
||||
auto comp3 = cc.priv().m_lastCompiled;
|
||||
|
||||
EXPECT_EQ(&comp1.priv(), &comp2.priv());
|
||||
EXPECT_EQ(&comp1.priv(), &comp3.priv());
|
||||
|
||||
cv::Mat cv_out_mat1, cv_out_mat2, cv_out_mat3;
|
||||
cv::resize(in_mat1, cv_out_mat1, szOut);
|
||||
cv::resize(in_mat2, cv_out_mat2, szOut);
|
||||
cv::resize(in_mat3, cv_out_mat3, szOut);
|
||||
|
||||
EXPECT_EQ(0, cvtest::norm(out_mat1, cv_out_mat1, NORM_INF));
|
||||
EXPECT_EQ(0, cvtest::norm(out_mat2, cv_out_mat2, NORM_INF));
|
||||
EXPECT_EQ(0, cvtest::norm(out_mat3, cv_out_mat3, NORM_INF));
|
||||
}
|
||||
|
||||
TEST(GComputationCompile, ReshapeBlur)
|
||||
{
|
||||
cv::Size kernelSize{3, 3};
|
||||
cv::GMat in;
|
||||
cv::GComputation cc(in, cv::gapi::blur(in, kernelSize));
|
||||
|
||||
cv::Mat in_mat1( 8, 8, CV_8UC1);
|
||||
cv::Mat in_mat2(16, 16, CV_8UC1);
|
||||
cv::randu(in_mat1, cv::Scalar::all(0), cv::Scalar::all(255));
|
||||
cv::randu(in_mat2, cv::Scalar::all(0), cv::Scalar::all(255));
|
||||
cv::Mat out_mat1, out_mat2;
|
||||
|
||||
cc.apply(in_mat1, out_mat1, cv::compile_args(cv::gapi::imgproc::fluid::kernels()));
|
||||
auto comp1 = cc.priv().m_lastCompiled;
|
||||
|
||||
cc.apply(in_mat2, out_mat2);
|
||||
auto comp2 = cc.priv().m_lastCompiled;
|
||||
|
||||
// Both compiled objects are actually the same unique executable
|
||||
EXPECT_EQ(&comp1.priv(), &comp2.priv());
|
||||
|
||||
cv::Mat cv_out_mat1, cv_out_mat2;
|
||||
cv::blur(in_mat1, cv_out_mat1, kernelSize);
|
||||
cv::blur(in_mat2, cv_out_mat2, kernelSize);
|
||||
|
||||
EXPECT_EQ(0, cvtest::norm(out_mat1, cv_out_mat1, NORM_INF));
|
||||
EXPECT_EQ(0, cvtest::norm(out_mat2, cv_out_mat2, NORM_INF));
|
||||
}
|
||||
|
||||
TEST(GComputationCompile, ReshapeRois)
|
||||
{
|
||||
cv::Size kernelSize{3, 3};
|
||||
cv::Size szOut(8, 8);
|
||||
cv::GMat in;
|
||||
auto blurred = cv::gapi::blur(in, kernelSize);
|
||||
cv::GComputation cc(in, cv::gapi::resize(blurred, szOut));
|
||||
|
||||
cv::Mat first_in_mat(8, 8, CV_8UC3);
|
||||
cv::randn(first_in_mat, cv::Scalar::all(127), cv::Scalar::all(40.f));
|
||||
cv::Mat first_out_mat;
|
||||
auto fluidKernels = cv::gapi::combine(gapi::imgproc::fluid::kernels(),
|
||||
gapi::core::fluid::kernels());
|
||||
cc.apply(first_in_mat, first_out_mat, cv::compile_args(fluidKernels));
|
||||
auto first_comp = cc.priv().m_lastCompiled;
|
||||
|
||||
constexpr int niter = 4;
|
||||
for (int i = 0; i < niter; i++)
|
||||
{
|
||||
int width = 4 + 2*i;
|
||||
int height = width;
|
||||
cv::Mat in_mat(width, height, CV_8UC3);
|
||||
cv::randn(in_mat, cv::Scalar::all(127), cv::Scalar::all(40.f));
|
||||
cv::Mat out_mat = cv::Mat::zeros(szOut, CV_8UC3);
|
||||
|
||||
int x = 0;
|
||||
int y = szOut.height * i / niter;
|
||||
int roiW = szOut.width;
|
||||
int roiH = szOut.height / niter;
|
||||
cv::Rect roi{x, y, roiW, roiH};
|
||||
|
||||
cc.apply(in_mat, out_mat, cv::compile_args(cv::GFluidOutputRois{{roi}}));
|
||||
auto comp = cc.priv().m_lastCompiled;
|
||||
|
||||
EXPECT_EQ(&first_comp.priv(), &comp.priv());
|
||||
|
||||
cv::Mat blur_mat, cv_out_mat;
|
||||
cv::blur(in_mat, blur_mat, kernelSize);
|
||||
cv::resize(blur_mat, cv_out_mat, szOut);
|
||||
|
||||
EXPECT_EQ(0, cvtest::norm(out_mat(roi), cv_out_mat(roi), NORM_INF));
|
||||
}
|
||||
}
|
||||
|
||||
} // opencv_test
|
207
3rdparty/opencv-4.5.4/modules/gapi/test/internal/gapi_int_vectorref_test.cpp
vendored
Normal file
207
3rdparty/opencv-4.5.4/modules/gapi/test/internal/gapi_int_vectorref_test.cpp
vendored
Normal file
@ -0,0 +1,207 @@
|
||||
// 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) 2018 Intel Corporation
|
||||
|
||||
|
||||
#include "../test_precomp.hpp"
|
||||
|
||||
namespace opencv_test
|
||||
{
|
||||
|
||||
typedef ::testing::Types<int, cv::Point, cv::Rect> VectorRef_Test_Types;
|
||||
|
||||
template<typename T> struct VectorRefT: public ::testing::Test { using Type = T; };
|
||||
|
||||
TYPED_TEST_CASE(VectorRefT, VectorRef_Test_Types);
|
||||
|
||||
TYPED_TEST(VectorRefT, Reset_Valid)
|
||||
{
|
||||
using T = typename TestFixture::Type;
|
||||
cv::detail::VectorRefT<T> ref; // vector ref created empty
|
||||
EXPECT_NO_THROW(ref.reset()); // 1st reset is OK (initializes)
|
||||
EXPECT_NO_THROW(ref.reset()); // 2nd reset is also OK (resets)
|
||||
}
|
||||
|
||||
TYPED_TEST(VectorRefT, Reset_Invalid)
|
||||
{
|
||||
using T = typename TestFixture::Type;
|
||||
std::vector<T> vec(42); // create a std::vector of 42 elements
|
||||
cv::detail::VectorRefT<T> ref(vec); // RO_EXT (since reference is const)
|
||||
EXPECT_ANY_THROW(ref.reset()); // data-bound vector ref can't be reset
|
||||
}
|
||||
|
||||
TYPED_TEST(VectorRefT, ReadRef_External)
|
||||
{
|
||||
using T = typename TestFixture::Type;
|
||||
const std::vector<T> vec(42); // create a std::vector of 42 elements
|
||||
cv::detail::VectorRefT<T> ref(vec); // RO_EXT (since reference is const)
|
||||
auto &vref = ref.rref();
|
||||
EXPECT_EQ(vec.data(), vref.data());
|
||||
EXPECT_EQ(vec.size(), vref.size());
|
||||
}
|
||||
|
||||
TYPED_TEST(VectorRefT, ReadRef_Internal)
|
||||
{
|
||||
using T = typename TestFixture::Type;
|
||||
cv::detail::VectorRefT<T> ref;
|
||||
ref.reset(); // RW_OWN (reset on empty ref)
|
||||
auto &vref = ref.rref(); // read access is valid for RW_OWN
|
||||
EXPECT_EQ(0u, vref.size()); // by default vector is empty
|
||||
}
|
||||
|
||||
TYPED_TEST(VectorRefT, WriteRef_External)
|
||||
{
|
||||
using T = typename TestFixture::Type;
|
||||
std::vector<T> vec(42); // create a std::vector of 42 elements
|
||||
cv::detail::VectorRefT<T> ref(vec); // RW_EXT (since reference is not const)
|
||||
auto &vref = ref.wref(); // write access is valid with RW_EXT
|
||||
EXPECT_EQ(vec.data(), vref.data());
|
||||
EXPECT_EQ(vec.size(), vref.size());
|
||||
}
|
||||
|
||||
TYPED_TEST(VectorRefT, WriteRef_Internal)
|
||||
{
|
||||
using T = typename TestFixture::Type;
|
||||
cv::detail::VectorRefT<T> ref;
|
||||
ref.reset(); // RW_OWN (reset on empty ref)
|
||||
auto &vref = ref.wref(); // write access is valid for RW_OWN
|
||||
EXPECT_EQ(0u, vref.size()); // empty vector by default
|
||||
}
|
||||
|
||||
TYPED_TEST(VectorRefT, WriteToRO)
|
||||
{
|
||||
using T = typename TestFixture::Type;
|
||||
const std::vector<T> vec(42); // create a std::vector of 42 elements
|
||||
cv::detail::VectorRefT<T> ref(vec); // RO_EXT (since reference is const)
|
||||
EXPECT_ANY_THROW(ref.wref());
|
||||
}
|
||||
|
||||
TYPED_TEST(VectorRefT, ReadAfterWrite)
|
||||
{
|
||||
using T = typename TestFixture::Type;
|
||||
std::vector<T> vec; // Initial data holder (empty vector)
|
||||
cv::detail::VectorRefT<T> writer(vec); // RW_EXT
|
||||
|
||||
const auto& ro_ref = vec;
|
||||
cv::detail::VectorRefT<T> reader(ro_ref); // RO_EXT
|
||||
|
||||
EXPECT_EQ(0u, writer.wref().size()); // Check the initial state
|
||||
EXPECT_EQ(0u, reader.rref().size());
|
||||
|
||||
writer.wref().emplace_back(); // Check that write is successful
|
||||
EXPECT_EQ(1u, writer.wref().size());
|
||||
|
||||
EXPECT_EQ(1u, vec.size()); // Check that changes are reflected to the original container
|
||||
EXPECT_EQ(1u, reader.rref().size()); // Check that changes are reflected to reader's view
|
||||
|
||||
EXPECT_EQ(T(), vec.at(0)); // Check the value (must be default-initialized)
|
||||
EXPECT_EQ(T(), reader.rref().at(0));
|
||||
EXPECT_EQ(T(), writer.wref().at(0));
|
||||
}
|
||||
|
||||
template<typename T> struct VectorRefU: public ::testing::Test { using Type = T; };
|
||||
|
||||
TYPED_TEST_CASE(VectorRefU, VectorRef_Test_Types);
|
||||
|
||||
template<class T> struct custom_struct { T a; T b; };
|
||||
|
||||
TYPED_TEST(VectorRefU, Reset_Valid)
|
||||
{
|
||||
using T = typename TestFixture::Type;
|
||||
cv::detail::VectorRef ref; // vector ref created empty
|
||||
EXPECT_NO_THROW(ref.reset<T>()); // 1st reset is OK (initializes)
|
||||
EXPECT_NO_THROW(ref.reset<T>()); // 2nd reset is also OK (resets)
|
||||
|
||||
EXPECT_ANY_THROW(ref.reset<custom_struct<T> >()); // type change is not allowed
|
||||
}
|
||||
|
||||
TYPED_TEST(VectorRefU, Reset_Invalid)
|
||||
{
|
||||
using T = typename TestFixture::Type;
|
||||
std::vector<T> vec(42); // create a std::vector of 42 elements
|
||||
cv::detail::VectorRef ref(vec); // RO_EXT (since reference is const)
|
||||
EXPECT_ANY_THROW(ref.reset<T>()); // data-bound vector ref can't be reset
|
||||
}
|
||||
|
||||
TYPED_TEST(VectorRefU, ReadRef_External)
|
||||
{
|
||||
using T = typename TestFixture::Type;
|
||||
const std::vector<T> vec(42); // create a std::vector of 42 elements
|
||||
cv::detail::VectorRef ref(vec); // RO_EXT (since reference is const)
|
||||
auto &vref = ref.rref<T>();
|
||||
EXPECT_EQ(vec.data(), vref.data());
|
||||
EXPECT_EQ(vec.size(), vref.size());
|
||||
}
|
||||
|
||||
TYPED_TEST(VectorRefU, ReadRef_Internal)
|
||||
{
|
||||
using T = typename TestFixture::Type;
|
||||
cv::detail::VectorRef ref;
|
||||
ref.reset<T>(); // RW_OWN (reset on empty ref)
|
||||
auto &vref = ref.rref<T>(); // read access is valid for RW_OWN
|
||||
EXPECT_EQ(0u, vref.size()); // by default vector is empty
|
||||
}
|
||||
|
||||
TYPED_TEST(VectorRefU, WriteRef_External)
|
||||
{
|
||||
using T = typename TestFixture::Type;
|
||||
std::vector<T> vec(42); // create a std::vector of 42 elements
|
||||
cv::detail::VectorRef ref(vec); // RW_EXT (since reference is not const)
|
||||
auto &vref = ref.wref<T>(); // write access is valid with RW_EXT
|
||||
EXPECT_EQ(vec.data(), vref.data());
|
||||
EXPECT_EQ(vec.size(), vref.size());
|
||||
}
|
||||
|
||||
TYPED_TEST(VectorRefU, WriteRef_Internal)
|
||||
{
|
||||
using T = typename TestFixture::Type;
|
||||
cv::detail::VectorRef ref;
|
||||
ref.reset<T>(); // RW_OWN (reset on empty ref)
|
||||
auto &vref = ref.wref<T>(); // write access is valid for RW_OWN
|
||||
EXPECT_EQ(0u, vref.size()); // empty vector by default
|
||||
}
|
||||
|
||||
TYPED_TEST(VectorRefU, WriteToRO)
|
||||
{
|
||||
using T = typename TestFixture::Type;
|
||||
const std::vector<T> vec(42); // create a std::vector of 42 elements
|
||||
cv::detail::VectorRef ref(vec); // RO_EXT (since reference is const)
|
||||
EXPECT_ANY_THROW(ref.wref<T>());
|
||||
}
|
||||
|
||||
TYPED_TEST(VectorRefU, ReadAfterWrite)
|
||||
{
|
||||
using T = typename TestFixture::Type;
|
||||
std::vector<T> vec; // Initial data holder (empty vector)
|
||||
cv::detail::VectorRef writer(vec); // RW_EXT
|
||||
|
||||
const auto& ro_ref = vec;
|
||||
cv::detail::VectorRef reader(ro_ref); // RO_EXT
|
||||
|
||||
EXPECT_EQ(0u, writer.wref<T>().size()); // Check the initial state
|
||||
EXPECT_EQ(0u, reader.rref<T>().size());
|
||||
|
||||
writer.wref<T>().emplace_back(); // Check that write is successful
|
||||
EXPECT_EQ(1u, writer.wref<T>().size());
|
||||
|
||||
EXPECT_EQ(1u, vec.size()); // Check that changes are reflected to the original container
|
||||
EXPECT_EQ(1u, reader.rref<T>().size()); // Check that changes are reflected to reader's view
|
||||
|
||||
EXPECT_EQ(T(), vec.at(0)); // Check the value (must be default-initialized)
|
||||
EXPECT_EQ(T(), reader.rref<T>().at(0));
|
||||
EXPECT_EQ(T(), writer.wref<T>().at(0));
|
||||
}
|
||||
|
||||
TEST(VectorRefU, TypeCheck)
|
||||
{
|
||||
cv::detail::VectorRef ref;
|
||||
ref.reset<int>(); // RW_OWN
|
||||
|
||||
EXPECT_ANY_THROW(ref.reset<char>());
|
||||
EXPECT_ANY_THROW(ref.rref<char>());
|
||||
EXPECT_ANY_THROW(ref.wref<char>());
|
||||
}
|
||||
|
||||
} // namespace opencv_test
|
369
3rdparty/opencv-4.5.4/modules/gapi/test/internal/gapi_transactions_test.cpp
vendored
Normal file
369
3rdparty/opencv-4.5.4/modules/gapi/test/internal/gapi_transactions_test.cpp
vendored
Normal file
@ -0,0 +1,369 @@
|
||||
// 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) 2018 - 2020 Intel Corporation
|
||||
|
||||
|
||||
#include "../test_precomp.hpp"
|
||||
|
||||
#include <ade/graph.hpp>
|
||||
#include <ade/typed_graph.hpp>
|
||||
|
||||
#include "compiler/transactions.hpp"
|
||||
|
||||
namespace opencv_test
|
||||
{
|
||||
namespace
|
||||
{
|
||||
|
||||
bool contains(const ade::Graph& graph, const ade::NodeHandle& node)
|
||||
{
|
||||
auto nodes = graph.nodes();
|
||||
return nodes.end() != std::find(nodes.begin(), nodes.end(), node);
|
||||
}
|
||||
|
||||
bool connected(const ade::NodeHandle& src_node, const ade::NodeHandle& dst_node)
|
||||
{
|
||||
auto nodes = src_node->outNodes();
|
||||
return nodes.end() != std::find(nodes.begin(), nodes.end(), dst_node);
|
||||
}
|
||||
|
||||
struct SimpleGraph
|
||||
{
|
||||
// ehs[0] ehs[1] ehs[2] ehs[3]
|
||||
// nhs[0] -- > nhs[1] --> nhs[2] --> nhs[3] --> nhs[4]
|
||||
|
||||
enum { node_nums = 5 };
|
||||
ade::Graph graph;
|
||||
ade::NodeHandle fused_nh; // For check that fusion node is connected to the
|
||||
// inputs of the prod and the outputs of the cons
|
||||
std::array<ade::NodeHandle, node_nums> nhs;
|
||||
std::array<ade::EdgeHandle, node_nums - 1> ehs;
|
||||
using Change = ChangeT<>;
|
||||
Change::List changes;
|
||||
|
||||
SimpleGraph()
|
||||
{
|
||||
nhs[0] = graph.createNode();
|
||||
for (int i = 1; i < node_nums; ++i)
|
||||
{
|
||||
nhs[i ] = graph.createNode();
|
||||
ehs[i - 1] = graph.link(nhs[i - 1], nhs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void fuse()
|
||||
{
|
||||
// nhs[0] --> fused_nh --> nhs[4]
|
||||
|
||||
fused_nh = graph.createNode();
|
||||
changes.enqueue<Change::NodeCreated>(fused_nh);
|
||||
changes.enqueue<Change::NewLink> (graph, nhs[0], fused_nh);
|
||||
changes.enqueue<Change::DropLink>(graph, nhs[1], ehs[0]);
|
||||
changes.enqueue<Change::NewLink> (graph, fused_nh, nhs[4]);
|
||||
changes.enqueue<Change::DropLink>(graph, nhs[3], ehs[3]);
|
||||
changes.enqueue<Change::DropLink>(graph, nhs[1], ehs[1]);
|
||||
changes.enqueue<Change::DropLink>(graph, nhs[2], ehs[2]);
|
||||
changes.enqueue<Change::DropNode>(nhs[1]);
|
||||
changes.enqueue<Change::DropNode>(nhs[2]);
|
||||
changes.enqueue<Change::DropNode>(nhs[3]);
|
||||
}
|
||||
|
||||
void commit() { changes.commit(graph); }
|
||||
void rollback() { changes.rollback(graph); }
|
||||
|
||||
};
|
||||
|
||||
struct Transactions: public ::testing::Test, public SimpleGraph {};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
TEST_F(Transactions, NodeCreated_Create)
|
||||
{
|
||||
auto new_nh = graph.createNode();
|
||||
Change::NodeCreated node_created(new_nh);
|
||||
|
||||
EXPECT_EQ(6u, static_cast<std::size_t>(graph.nodes().size()));
|
||||
EXPECT_TRUE(contains(graph, new_nh));
|
||||
}
|
||||
|
||||
TEST_F(Transactions, NodeCreated_RollBack)
|
||||
{
|
||||
auto new_nh = graph.createNode();
|
||||
Change::NodeCreated node_created(new_nh);
|
||||
|
||||
node_created.rollback(graph);
|
||||
|
||||
EXPECT_EQ(5u, static_cast<std::size_t>(graph.nodes().size()));
|
||||
EXPECT_FALSE(contains(graph, new_nh));
|
||||
}
|
||||
|
||||
TEST_F(Transactions, NodeCreated_Commit)
|
||||
{
|
||||
auto new_nh = graph.createNode();
|
||||
Change::NodeCreated node_created(new_nh);
|
||||
|
||||
node_created.commit(graph);
|
||||
|
||||
EXPECT_EQ(6u, static_cast<std::size_t>(graph.nodes().size()));
|
||||
EXPECT_TRUE(contains(graph, new_nh));
|
||||
}
|
||||
|
||||
TEST_F(Transactions, DropLink_Create)
|
||||
{
|
||||
Change::DropLink drop_link(graph, nhs[0], ehs[0]);
|
||||
|
||||
EXPECT_FALSE(connected(nhs[0], nhs[1]));
|
||||
}
|
||||
|
||||
TEST_F(Transactions, DropLink_RollBack)
|
||||
{
|
||||
Change::DropLink drop_link(graph, nhs[0], ehs[0]);
|
||||
|
||||
drop_link.rollback(graph);
|
||||
|
||||
EXPECT_TRUE(connected(nhs[0], nhs[1]));
|
||||
}
|
||||
|
||||
TEST_F(Transactions, DropLink_Commit)
|
||||
{
|
||||
Change::DropLink drop_link(graph, nhs[0], ehs[0]);
|
||||
|
||||
drop_link.commit(graph);
|
||||
|
||||
EXPECT_FALSE(connected(nhs[0], nhs[1]));
|
||||
}
|
||||
|
||||
TEST_F(Transactions, NewLink_Create)
|
||||
{
|
||||
auto new_nh = graph.createNode();
|
||||
Change::NewLink new_link(graph, new_nh, nhs[0]);
|
||||
|
||||
EXPECT_TRUE(connected(new_nh, nhs[0]));
|
||||
}
|
||||
|
||||
TEST_F(Transactions, NewLink_RollBack)
|
||||
{
|
||||
auto new_nh = graph.createNode();
|
||||
Change::NewLink new_link(graph, new_nh, nhs[0]);
|
||||
|
||||
new_link.rollback(graph);
|
||||
|
||||
EXPECT_FALSE(connected(new_nh, nhs[0]));
|
||||
}
|
||||
|
||||
TEST_F(Transactions, NewLink_Commit)
|
||||
{
|
||||
auto new_nh = graph.createNode();
|
||||
Change::NewLink new_link(graph, new_nh, nhs[0]);
|
||||
|
||||
new_link.commit(graph);
|
||||
|
||||
EXPECT_TRUE(connected(new_nh, nhs[0]));
|
||||
}
|
||||
|
||||
TEST_F(Transactions, DropNode_Create)
|
||||
{
|
||||
auto new_nh = graph.createNode();
|
||||
Change::DropNode drop_node(new_nh);
|
||||
|
||||
EXPECT_EQ(6u, static_cast<std::size_t>(graph.nodes().size()));
|
||||
EXPECT_TRUE(contains(graph, new_nh));
|
||||
}
|
||||
|
||||
TEST_F(Transactions, DropNode_RollBack)
|
||||
{
|
||||
auto new_nh = graph.createNode();
|
||||
Change::DropNode drop_node(new_nh);
|
||||
|
||||
drop_node.rollback(graph);
|
||||
|
||||
EXPECT_EQ(6u, static_cast<std::size_t>(graph.nodes().size()));
|
||||
EXPECT_TRUE(contains(graph, new_nh));
|
||||
}
|
||||
|
||||
TEST_F(Transactions, DropNode_Commit)
|
||||
{
|
||||
auto new_nh = graph.createNode();
|
||||
Change::DropNode drop_node(new_nh);
|
||||
|
||||
drop_node.commit(graph);
|
||||
|
||||
EXPECT_EQ(5u, static_cast<std::size_t>(graph.nodes().size()));
|
||||
EXPECT_FALSE(contains(graph, new_nh));
|
||||
}
|
||||
|
||||
TEST_F(Transactions, Fusion_Commit)
|
||||
{
|
||||
fuse();
|
||||
commit();
|
||||
|
||||
EXPECT_EQ(3u, static_cast<std::size_t>(graph.nodes().size()));
|
||||
EXPECT_TRUE(connected(nhs[0] , fused_nh));
|
||||
EXPECT_TRUE(connected(fused_nh, nhs[4]));
|
||||
}
|
||||
|
||||
TEST_F(Transactions, Fusion_RollBack)
|
||||
{
|
||||
fuse();
|
||||
rollback();
|
||||
|
||||
EXPECT_EQ(static_cast<std::size_t>(node_nums),
|
||||
static_cast<std::size_t>(graph.nodes().size()));
|
||||
EXPECT_FALSE(contains(graph, fused_nh));
|
||||
|
||||
for (int i = 0; i < static_cast<int>(node_nums) - 1; ++i)
|
||||
{
|
||||
EXPECT_TRUE(connected(nhs[i], nhs[i + 1]));
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
struct MetaInt {
|
||||
static const char *name() { return "int_meta"; }
|
||||
int x;
|
||||
};
|
||||
|
||||
struct MetaStr {
|
||||
static const char *name() { return "string_meta"; }
|
||||
std::string s;
|
||||
};
|
||||
}
|
||||
|
||||
TEST(PreservedMeta, TestMetaCopy_Full)
|
||||
{
|
||||
ade::Graph g;
|
||||
ade::TypedGraph<MetaInt, MetaStr> tg(g);
|
||||
|
||||
auto src_nh = tg.createNode();
|
||||
tg.metadata(src_nh).set(MetaInt{42});
|
||||
tg.metadata(src_nh).set(MetaStr{"hi"});
|
||||
|
||||
auto dst_nh = tg.createNode();
|
||||
|
||||
EXPECT_FALSE(tg.metadata(dst_nh).contains<MetaInt>());
|
||||
EXPECT_FALSE(tg.metadata(dst_nh).contains<MetaStr>());
|
||||
|
||||
// Here we specify all the meta types we know about the src node
|
||||
// Assume Preserved copies its all for us
|
||||
Preserved<ade::NodeHandle, MetaInt, MetaStr>(g, src_nh).copyTo(g, dst_nh);
|
||||
|
||||
ASSERT_TRUE(tg.metadata(dst_nh).contains<MetaInt>());
|
||||
ASSERT_TRUE(tg.metadata(dst_nh).contains<MetaStr>());
|
||||
|
||||
EXPECT_EQ(42, tg.metadata(dst_nh).get<MetaInt>().x);
|
||||
EXPECT_EQ("hi", tg.metadata(dst_nh).get<MetaStr>().s);
|
||||
}
|
||||
|
||||
|
||||
TEST(PreservedMeta, TestMetaCopy_Partial_Dst)
|
||||
{
|
||||
ade::Graph g;
|
||||
ade::TypedGraph<MetaInt, MetaStr> tg(g);
|
||||
|
||||
auto tmp_nh1 = tg.createNode();
|
||||
auto tmp_nh2 = tg.createNode();
|
||||
auto src_eh = tg.link(tmp_nh1, tmp_nh2);
|
||||
|
||||
tg.metadata(src_eh).set(MetaInt{42});
|
||||
tg.metadata(src_eh).set(MetaStr{"hi"});
|
||||
|
||||
auto tmp_nh3 = tg.createNode();
|
||||
auto tmp_nh4 = tg.createNode();
|
||||
auto dst_eh = tg.link(tmp_nh3, tmp_nh4);
|
||||
|
||||
EXPECT_FALSE(tg.metadata(dst_eh).contains<MetaInt>());
|
||||
EXPECT_FALSE(tg.metadata(dst_eh).contains<MetaStr>());
|
||||
|
||||
// Here we specify just a single meta type for the src node
|
||||
// Assume Preserved copies only this type and nothing else
|
||||
Preserved<ade::EdgeHandle, MetaStr>(g, src_eh).copyTo(g, dst_eh);
|
||||
|
||||
ASSERT_FALSE(tg.metadata(dst_eh).contains<MetaInt>());
|
||||
ASSERT_TRUE (tg.metadata(dst_eh).contains<MetaStr>());
|
||||
|
||||
EXPECT_EQ("hi", tg.metadata(dst_eh).get<MetaStr>().s);
|
||||
}
|
||||
|
||||
TEST(PreservedMeta, TestMetaCopy_Partial_Src)
|
||||
{
|
||||
ade::Graph g;
|
||||
ade::TypedGraph<MetaInt, MetaStr> tg(g);
|
||||
|
||||
auto src_nh = tg.createNode();
|
||||
tg.metadata(src_nh).set(MetaInt{42});
|
||||
|
||||
auto dst_nh = tg.createNode();
|
||||
|
||||
EXPECT_FALSE(tg.metadata(dst_nh).contains<MetaInt>());
|
||||
EXPECT_FALSE(tg.metadata(dst_nh).contains<MetaStr>());
|
||||
|
||||
// Here we specify all the meta types we know about the src node
|
||||
// but the src node has just one of them.
|
||||
// A valid situation, only MetaInt to be copied.
|
||||
Preserved<ade::NodeHandle, MetaInt, MetaStr>(g, src_nh).copyTo(g, dst_nh);
|
||||
|
||||
ASSERT_TRUE (tg.metadata(dst_nh).contains<MetaInt>());
|
||||
ASSERT_FALSE(tg.metadata(dst_nh).contains<MetaStr>());
|
||||
|
||||
EXPECT_EQ(42, tg.metadata(dst_nh).get<MetaInt>().x);
|
||||
}
|
||||
|
||||
TEST(PreservedMeta, TestMetaCopy_Nothing)
|
||||
{
|
||||
ade::Graph g;
|
||||
ade::TypedGraph<MetaInt, MetaStr> tg(g);
|
||||
|
||||
auto src_nh = tg.createNode();
|
||||
auto dst_nh = tg.createNode();
|
||||
|
||||
EXPECT_FALSE(tg.metadata(src_nh).contains<MetaInt>());
|
||||
EXPECT_FALSE(tg.metadata(src_nh).contains<MetaStr>());
|
||||
|
||||
EXPECT_FALSE(tg.metadata(dst_nh).contains<MetaInt>());
|
||||
EXPECT_FALSE(tg.metadata(dst_nh).contains<MetaStr>());
|
||||
|
||||
// Here we specify all the meta types we know about the src node
|
||||
// but the src node has none of those. See how it works now
|
||||
Preserved<ade::NodeHandle, MetaInt, MetaStr>(g, src_nh).copyTo(g, dst_nh);
|
||||
|
||||
ASSERT_FALSE(tg.metadata(dst_nh).contains<MetaInt>());
|
||||
ASSERT_FALSE(tg.metadata(dst_nh).contains<MetaStr>());
|
||||
}
|
||||
|
||||
TEST(PreservedMeta, DropEdge)
|
||||
{
|
||||
ade::Graph g;
|
||||
ade::TypedGraph<MetaInt, MetaStr> tg(g);
|
||||
|
||||
auto nh1 = tg.createNode();
|
||||
auto nh2 = tg.createNode();
|
||||
auto eh = tg.link(nh1, nh2);
|
||||
|
||||
tg.metadata(eh).set(MetaInt{42});
|
||||
tg.metadata(eh).set(MetaStr{"hi"});
|
||||
|
||||
// Drop an edge using the transaction API
|
||||
using Change = ChangeT<MetaInt, MetaStr>;
|
||||
Change::List changes;
|
||||
changes.enqueue<Change::DropLink>(g, nh1, eh);
|
||||
|
||||
EXPECT_EQ(0u, nh1->outNodes().size());
|
||||
EXPECT_EQ(nullptr, eh);
|
||||
|
||||
// Now restore the edge and check if it's meta was restored
|
||||
changes.rollback(g);
|
||||
|
||||
ASSERT_EQ(1u, nh1->outNodes().size());
|
||||
eh = *nh1->outEdges().begin();
|
||||
|
||||
ASSERT_TRUE(tg.metadata(eh).contains<MetaInt>());
|
||||
ASSERT_TRUE(tg.metadata(eh).contains<MetaStr>());
|
||||
|
||||
EXPECT_EQ(42, tg.metadata(eh).get<MetaInt>().x);
|
||||
EXPECT_EQ("hi", tg.metadata(eh).get<MetaStr>().s);
|
||||
}
|
||||
|
||||
} // opencv_test
|
Reference in New Issue
Block a user