Path: blob/master/modules/gapi/test/internal/gapi_int_gmodel_builder_test.cpp
16344 views
// This file is part of OpenCV project.1// It is subject to the license terms in the LICENSE file found in the top-level directory2// of this distribution and at http://opencv.org/license.html.3//4// Copyright (C) 2018 Intel Corporation567#include "test_precomp.hpp"89#include <ade/util/zip_range.hpp> // util::indexed1011#include "opencv2/gapi/gkernel.hpp"12#include "compiler/gmodelbuilder.hpp"13#include "compiler/gmodel.hpp" // RcDesc, GModel::init1415namespace opencv_test16{1718namespace test19{2021namespace22{23cv::GMat unaryOp(cv::GMat m)24{25return cv::GCall(cv::GKernel{"gapi.test.unaryop", nullptr, { GShape::GMAT } }).pass(m).yield(0);26}2728cv::GMat binaryOp(cv::GMat m1, cv::GMat m2)29{30return cv::GCall(cv::GKernel{"gapi.test.binaryOp", nullptr, { GShape::GMAT } }).pass(m1, m2).yield(0);31}3233std::vector<ade::NodeHandle> collectOperations(const cv::gimpl::GModel::Graph& gr)34{35std::vector<ade::NodeHandle> ops;36for (const auto& nh : gr.nodes())37{38if (gr.metadata(nh).get<cv::gimpl::NodeType>().t == cv::gimpl::NodeType::OP)39ops.push_back(nh);40}41return ops;42}4344ade::NodeHandle inputOf(cv::gimpl::GModel::Graph& gm, ade::NodeHandle nh, std::size_t port)45{46for (const auto& eh : nh->inEdges())47{48if (gm.metadata(eh).get<cv::gimpl::Input>().port == port)49{50return eh->srcNode();51}52}53util::throw_error(std::logic_error("port " + std::to_string(port) + " not found"));54}55}56}// namespace opencv_test::test5758TEST(GModelBuilder, Unroll_TestUnary)59{60cv::GMat in;61cv::GMat out = test::unaryOp(in);6263auto unrolled = cv::gimpl::unrollExpr(cv::GIn(in).m_args, cv::GOut(out).m_args);6465EXPECT_EQ(1u, unrolled.all_ops.size()); // There is one operation66EXPECT_EQ(2u, unrolled.all_data.size()); // And two data objects (in, out)6768// TODO check what the operation is, and so on, and so on69}7071TEST(GModelBuilder, Unroll_TestUnaryOfUnary)72{73cv::GMat in;74cv::GMat out = test::unaryOp(test::unaryOp(in));7576auto unrolled = cv::gimpl::unrollExpr(cv::GIn(in).m_args, cv::GOut(out).m_args);7778EXPECT_EQ(2u, unrolled.all_ops.size()); // There're two operations79EXPECT_EQ(3u, unrolled.all_data.size()); // And three data objects (in, out)8081// TODO check what the operation is, and so on, and so on82}8384TEST(GModelBuilder, Unroll_Not_All_Protocol_Inputs_Are_Reached)85{86cv::GMat in1, in2; // in1 -> unaryOp() -> u_op1 -> unaryOp() -> out87auto u_op1 = test::unaryOp(in1); // in2 -> unaryOp() -> u_op288auto u_op2 = test::unaryOp(in2);89auto out = test::unaryOp(u_op1);9091EXPECT_THROW(cv::gimpl::unrollExpr(cv::GIn(in1, in2).m_args, cv::GOut(out).m_args), std::logic_error);92}9394TEST(GModelBuilder, Unroll_Parallel_Path)95{96cv::GMat in1, in2; // in1 -> unaryOp() -> out197auto out1 = test::unaryOp(in1); // in2 -> unaryOp() -> out298auto out2 = test::unaryOp(in2);99100auto unrolled = cv::gimpl::unrollExpr(cv::GIn(in1, in2).m_args, cv::GOut(out1, out2).m_args);101102EXPECT_EQ(unrolled.all_ops.size(), 2u);103EXPECT_EQ(unrolled.all_data.size(), 4u);104}105106TEST(GModelBuilder, Unroll_WithBranch)107{108// in -> unaryOp() -> tmp -->unaryOp() -> out1109// `---->unaryOp() -> out2110111GMat in;112auto tmp = test::unaryOp(in);113auto out1 = test::unaryOp(tmp);114auto out2 = test::unaryOp(tmp);115116auto unrolled = cv::gimpl::unrollExpr(cv::GIn(in).m_args, cv::GOut(out1, out2).m_args);117118EXPECT_EQ(unrolled.all_ops.size(), 3u);119EXPECT_EQ(unrolled.all_data.size(), 4u);120}121122TEST(GModelBuilder, Build_Unary)123{124cv::GMat in;125cv::GMat out = test::unaryOp(in);126127ade::Graph g;128cv::gimpl::GModel::Graph gm(g);129cv::gimpl::GModel::init(gm);130cv::gimpl::GModelBuilder(g).put(cv::GIn(in).m_args, cv::GOut(out).m_args);131132EXPECT_EQ(3u, static_cast<std::size_t>(g.nodes().size())); // Generated graph should have three nodes133134// TODO: Check what the nodes are135}136137TEST(GModelBuilder, Constant_GScalar)138{139// in -> addC()-----(GMat)---->mulC()-----(GMat)---->unaryOp()----out140// ^ ^141// | |142// 3-------` c_s-------'143144cv::GMat in;145cv::GScalar c_s = 5;146auto out = test::unaryOp((in + 3) * c_s); // 3 converted to GScalar147148ade::Graph g;149cv::gimpl::GModel::Graph gm(g);150cv::gimpl::GModel::init(gm);151auto proto_slots = cv::gimpl::GModelBuilder(g).put(cv::GIn(in).m_args, cv::GOut(out).m_args);152cv::gimpl::Protocol p;153std::tie(p.inputs, p.outputs, p.in_nhs, p.out_nhs) = proto_slots;154155auto in_nh = p.in_nhs.front();156auto addC_nh = in_nh->outNodes().front();157auto mulC_nh = addC_nh->outNodes().front()->outNodes().front();158159ASSERT_TRUE(gm.metadata(addC_nh).get<cv::gimpl::NodeType>().t == cv::gimpl::NodeType::OP);160ASSERT_TRUE(gm.metadata(mulC_nh).get<cv::gimpl::NodeType>().t == cv::gimpl::NodeType::OP);161162auto s_3 = test::inputOf(gm, addC_nh, 1);163auto s_5 = test::inputOf(gm, mulC_nh, 1);164165EXPECT_EQ(9u, static_cast<std::size_t>(g.nodes().size())); // 6 data nodes (1 -input, 1 output, 2 constant, 2 temp) and 3 op nodes166EXPECT_EQ(2u, static_cast<std::size_t>(addC_nh->inNodes().size())); // in and 3167EXPECT_EQ(2u, static_cast<std::size_t>(mulC_nh->inNodes().size())); // addC output and c_s168EXPECT_EQ(3, (util::get<cv::gapi::own::Scalar>(gm.metadata(s_3).get<cv::gimpl::ConstValue>().arg))[0]);169EXPECT_EQ(5, (util::get<cv::gapi::own::Scalar>(gm.metadata(s_5).get<cv::gimpl::ConstValue>().arg))[0]);170}171172TEST(GModelBuilder, Check_Multiple_Outputs)173{174// ------------------------------> r175// '176// ' -----------> i_out1177// ' '178// in ----> split3() ---> g ---> integral()179// ' '180// ' -----------> i_out2181// '182// '---------> b ---> unaryOp() ---> u_out183184cv::GMat in, r, g, b, i_out1, i_out2, u_out;185std::tie(r, g, b) = cv::gapi::split3(in);186std::tie(i_out1, i_out2) = cv::gapi::integral(g, 1, 1);187u_out = test::unaryOp(b);188189ade::Graph gr;190cv::gimpl::GModel::Graph gm(gr);191cv::gimpl::GModel::init(gm);192auto proto_slots = cv::gimpl::GModelBuilder(gr).put(cv::GIn(in).m_args, cv::GOut(r, i_out1, i_out2, u_out).m_args);193cv::gimpl::Protocol p;194std::tie(p.inputs, p.outputs, p.in_nhs, p.out_nhs) = proto_slots;195196EXPECT_EQ(4u, static_cast<std::size_t>(p.out_nhs.size()));197EXPECT_EQ(0u, gm.metadata(p.out_nhs[0]->inEdges().front()).get<cv::gimpl::Output>().port);198EXPECT_EQ(0u, gm.metadata(p.out_nhs[1]->inEdges().front()).get<cv::gimpl::Output>().port);199EXPECT_EQ(1u, gm.metadata(p.out_nhs[2]->inEdges().front()).get<cv::gimpl::Output>().port);200EXPECT_EQ(0u, gm.metadata(p.out_nhs[3]->inEdges().front()).get<cv::gimpl::Output>().port);201for (const auto& it : ade::util::indexed(p.out_nhs))202{203const auto& out_nh = ade::util::value(it);204205EXPECT_EQ(cv::gimpl::NodeType::DATA, gm.metadata(out_nh).get<cv::gimpl::NodeType>().t);206EXPECT_EQ(GShape::GMAT, gm.metadata(out_nh).get<cv::gimpl::Data>().shape);207}208}209210TEST(GModelBuilder, Unused_Outputs)211{212cv::GMat in;213auto yuv_p = cv::gapi::split3(in);214215ade::Graph g;216cv::gimpl::GModel::Graph gm(g);217cv::gimpl::GModel::init(gm);218cv::gimpl::GModelBuilder(g).put(cv::GIn(in).m_args, cv::GOut(std::get<0>(yuv_p)).m_args);219220EXPECT_EQ(5u, static_cast<std::size_t>(g.nodes().size())); // 1 input, 1 operation, 3 outputs221}222223TEST(GModelBuilder, Work_With_One_Channel_From_Split3)224{225cv::GMat in, y, u, v;226std::tie(y, u, v) = cv::gapi::split3(in);227auto y_blur = cv::gapi::gaussianBlur(y, cv::Size(3, 3), 1);228229ade::Graph g;230cv::gimpl::GModel::Graph gm(g);231cv::gimpl::GModel::init(gm);232cv::gimpl::GModelBuilder(g).put(cv::GIn(in).m_args, cv::GOut(y_blur).m_args);233234EXPECT_EQ(7u, static_cast<std::size_t>(g.nodes().size())); // 1 input, 2 operation, 3 nodes from split3, 1 output235}236237TEST(GModelBuilder, Add_Nodes_To_Unused_Nodes)238{239cv::GMat in, y, u, v;240std::tie(y, u, v) = cv::gapi::split3(in);241auto y_blur = cv::gapi::gaussianBlur(y, cv::Size(3, 3), 1);242// unused nodes243auto u_blur = cv::gapi::gaussianBlur(y, cv::Size(3, 3), 1);244auto v_blur = cv::gapi::gaussianBlur(y, cv::Size(3, 3), 1);245246ade::Graph g;247cv::gimpl::GModel::Graph gm(g);248cv::gimpl::GModel::init(gm);249cv::gimpl::GModelBuilder(g).put(cv::GIn(in).m_args, cv::GOut(y_blur).m_args);250251EXPECT_EQ(7u, static_cast<std::size_t>(g.nodes().size())); // 1 input, 2 operation, 3 nodes from split3, 1 output252}253254TEST(GModelBuilder, Unlisted_Inputs)255{256// in1 -> binaryOp() -> out257// ^258// |259// in2 ----'260261cv::GMat in1, in2;262auto out = test::binaryOp(in1, in2);263264ade::Graph g;265cv::gimpl::GModel::Graph gm(g);266cv::gimpl::GModel::init(gm);267// add required 2 inputs but pass 1268EXPECT_THROW(cv::gimpl::GModelBuilder(g).put(cv::GIn(in1).m_args, cv::GOut(out).m_args), std::logic_error);269}270271TEST(GModelBuilder, Unroll_No_Link_Between_In_And_Out)272{273// in -> unaryOp() -> u_op274// other -> unaryOp() -> out275276cv::GMat in, other;277auto u_op = test::unaryOp(in);278auto out = test::unaryOp(other);279280EXPECT_THROW(cv::gimpl::unrollExpr(cv::GIn(in).m_args, cv::GOut(out).m_args), std::logic_error);281}282283284TEST(GModel_builder, Check_Binary_Op)285{286// in1 -> binaryOp() -> out287// ^288// |289// in2 -----'290291cv::GMat in1, in2;292auto out = test::binaryOp(in1, in2);293294ade::Graph g;295cv::gimpl::GModel::Graph gm(g);296cv::gimpl::GModel::init(gm);297auto proto_slots = cv::gimpl::GModelBuilder(g).put(cv::GIn(in1, in2).m_args, cv::GOut(out).m_args);298299cv::gimpl::Protocol p;300std::tie(p.inputs, p.outputs, p.in_nhs, p.out_nhs) = proto_slots;301auto ops = test::collectOperations(g);302303EXPECT_EQ(1u, ops.size());304EXPECT_EQ("gapi.test.binaryOp", gm.metadata(ops.front()).get<cv::gimpl::Op>().k.name);305EXPECT_EQ(2u, static_cast<std::size_t>(ops.front()->inEdges().size()));306EXPECT_EQ(1u, static_cast<std::size_t>(ops.front()->outEdges().size()));307EXPECT_EQ(1u, static_cast<std::size_t>(ops.front()->outNodes().size()));308}309310TEST(GModelBuilder, Add_Operation_With_Two_Out_One_Time)311{312// in -> integral() --> out_b1 -> unaryOp() -> out1313// |314// '-------> out_b2 -> unaryOp() -> out2315316cv::GMat in, out_b1, out_b2;317std::tie(out_b1, out_b2) = cv::gapi::integral(in, 1, 1);318auto out1 = test::unaryOp(out_b1);319auto out2 = test::unaryOp(out_b1);320321ade::Graph g;322cv::gimpl::GModel::Graph gm(g);323cv::gimpl::GModel::init(gm);324auto proto_slots = cv::gimpl::GModelBuilder(g).put(cv::GIn(in).m_args, cv::GOut(out1, out2).m_args);325326auto ops = test::collectOperations(gm);327328cv::gimpl::Protocol p;329std::tie(p.inputs, p.outputs, p.in_nhs, p.out_nhs) = proto_slots;330auto integral_nh = p.in_nhs.front()->outNodes().front();331332EXPECT_EQ(3u, ops.size());333EXPECT_EQ("org.opencv.core.matrixop.integral", gm.metadata(integral_nh).get<cv::gimpl::Op>().k.name);334EXPECT_EQ(1u, static_cast<std::size_t>(integral_nh->inEdges().size()));335EXPECT_EQ(2u, static_cast<std::size_t>(integral_nh->outEdges().size()));336EXPECT_EQ(2u, static_cast<std::size_t>(integral_nh->outNodes().size()));337}338TEST(GModelBuilder, Add_Operation_With_One_Out_One_Time)339{340// in1 -> binaryOp() -> b_out -> unaryOp() -> out1341// ^ |342// | |343// in2 ------- '----> unaryOp() -> out2344345cv::GMat in1, in2;346auto b_out = test::binaryOp(in1, in2);347auto out1 = test::unaryOp(b_out);348auto out2 = test::unaryOp(b_out);349350ade::Graph g;351cv::gimpl::GModel::Graph gm(g);352cv::gimpl::GModel::init(gm);353auto proto_slots = cv::gimpl::GModelBuilder(g).put(cv::GIn(in1, in2).m_args, cv::GOut(out1, out2).m_args);354cv::gimpl::Protocol p;355std::tie(p.inputs, p.outputs, p.in_nhs, p.out_nhs) = proto_slots;356cv::gimpl::GModel::Graph gr(g);357auto binaryOp_nh = p.in_nhs.front()->outNodes().front();358359EXPECT_EQ(2u, static_cast<std::size_t>(binaryOp_nh->inEdges().size()));360EXPECT_EQ(1u, static_cast<std::size_t>(binaryOp_nh->outEdges().size()));361EXPECT_EQ(8u, static_cast<std::size_t>(g.nodes().size()));362}363} // namespace opencv_test364365366