initial commit

This commit is contained in:
Joachim
2020-03-23 11:48:41 +01:00
commit fce6dc35b4
6434 changed files with 2823345 additions and 0 deletions

View 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