Merge pull request #20918 from TolyaTalamanov:at/fix-empty-map-importNetwork

[G-API] Fix bugs in GIEBackend

* Remove inputs/outputs map from IEUnit

* Add test

* Add NV12 test

* Reorganize setBlob function

* Check that backend don't overwrite blob precision

* Stop setting config to global IE::Core

* Replace mutable to const_cast

* Update modules/gapi/test/infer/gapi_infer_ie_test.cpp

* Update modules/gapi/test/infer/gapi_infer_ie_test.cpp

* Make blob parameter as const ref

* Cosmetic fixes

* Fix failed test on inferROI

* Removed double ref for ii

* Disable tests

* Skip tests if device not available

* Use Sync prim under shared_ptr to avoid issue on MAC

* Apply WA for IE::Core

* Apply WA for MAC build

* Try to apply another WA

* Not release IE::Core for apple

* Put comment

* Support PreprocInfo for

* InferROI
* InferList
* InferList2

* Remove empty line

* Fix alignment

Co-authored-by: Maxim Pashchenkov <maxim.pashchenkov@intel.com>
pull/21024/head
Anatoliy Talamanov 3 years ago committed by GitHub
parent 394e640909
commit 2b2e515a30
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 165
      modules/gapi/src/backends/ie/giebackend.cpp
  2. 31
      modules/gapi/src/backends/ie/giebackend/giewrapper.cpp
  3. 17
      modules/gapi/src/backends/ie/giebackend/giewrapper.hpp
  4. 673
      modules/gapi/test/infer/gapi_infer_ie_test.cpp

@ -218,14 +218,18 @@ struct IEUnit {
cv::gapi::ie::detail::ParamDesc params;
IE::CNNNetwork net;
IE::InputsDataMap inputs;
IE::OutputsDataMap outputs;
IE::ExecutableNetwork this_network;
cv::gimpl::ie::wrap::Plugin this_plugin;
InferenceEngine::RemoteContext::Ptr rctx = nullptr;
// FIXME: Unlike loadNetwork case, importNetwork requires that preprocessing
// should be passed as ExecutableNetwork::SetBlob method, so need to collect
// and store this information at the graph compilation stage (outMeta) and use in runtime.
using PreProcMap = std::unordered_map<std::string, IE::PreProcessInfo>;
PreProcMap preproc_map;
explicit IEUnit(const cv::gapi::ie::detail::ParamDesc &pp)
: params(pp) {
InferenceEngine::ParamMap* ctx_params =
@ -238,11 +242,8 @@ struct IEUnit {
if (params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Load) {
net = cv::gimpl::ie::wrap::readNetwork(params);
net.setBatchSize(params.batch_size);
inputs = net.getInputsInfo();
outputs = net.getOutputsInfo();
} else if (params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Import) {
this_plugin = cv::gimpl::ie::wrap::getPlugin(params);
this_plugin.SetConfig(params.config);
this_network = cv::gimpl::ie::wrap::importNetwork(this_plugin, params, rctx);
if (!params.reshape_table.empty() || !params.layer_names_to_reshape.empty()) {
GAPI_LOG_WARNING(NULL, "Reshape isn't supported for imported network");
@ -268,14 +269,14 @@ struct IEUnit {
}
if (params.num_in == 1u && params.input_names.empty()) {
if (params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Load) {
params.input_names = { inputs.begin()->first };
params.input_names = { net.getInputsInfo().begin()->first };
} else {
params.input_names = { this_network.GetInputsInfo().begin()->first };
}
}
if (params.num_out == 1u && params.output_names.empty()) {
if (params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Load) {
params.output_names = { outputs.begin()->first };
params.output_names = { net.getOutputsInfo().begin()->first };
} else {
params.output_names = { this_network.GetOutputsInfo().begin()->first };
}
@ -290,11 +291,11 @@ struct IEUnit {
// This method is [supposed to be] called at Island compilation stage
cv::gimpl::ie::IECompiled compile() const {
IEUnit* non_const_this = const_cast<IEUnit*>(this);
// FIXME: LoadNetwork must be called only after all necessary model
// inputs information is set, since it's done in outMeta and compile called after that,
// this place seems to be suitable, but consider another place not to break const agreements.
if (params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Load) {
// FIXME: In case importNetwork for fill inputs/outputs need to obtain ExecutableNetwork, but
// for loadNetwork they can be obtained by using readNetwork
non_const_this->this_plugin = cv::gimpl::ie::wrap::getPlugin(params);
non_const_this->this_plugin.SetConfig(params.config);
non_const_this->this_network = cv::gimpl::ie::wrap::loadNetwork(non_const_this->this_plugin,
net, params, rctx);
}
@ -540,19 +541,16 @@ inline IE::Blob::Ptr extractBlob(IECallContext& ctx, std::size_t i) {
}
static void setBlob(InferenceEngine::InferRequest& req,
cv::gapi::ie::detail::ParamDesc::Kind kind,
const std::string& layer_name,
IE::Blob::Ptr blob) {
// NB: In case importNetwork preprocessing must be
// passed as SetBlob argument.
if (kind == cv::gapi::ie::detail::ParamDesc::Kind::Load) {
static void setBlob(InferenceEngine::InferRequest& req,
const std::string& layer_name,
const IE::Blob::Ptr& blob,
const IECallContext& ctx) {
using namespace cv::gapi::ie::detail;
if (ctx.uu.params.kind == ParamDesc::Kind::Load) {
req.SetBlob(layer_name, blob);
} else {
GAPI_Assert(kind == cv::gapi::ie::detail::ParamDesc::Kind::Import);
IE::PreProcessInfo info;
info.setResizeAlgorithm(IE::RESIZE_BILINEAR);
req.SetBlob(layer_name, blob, info);
GAPI_Assert(ctx.uu.params.kind == ParamDesc::Kind::Import);
req.SetBlob(layer_name, blob, ctx.uu.preproc_map.at(layer_name));
}
}
@ -822,6 +820,23 @@ static void configureInputInfo(const IE::InputInfo::Ptr& ii, const cv::GMetaArg
}
}
static IE::PreProcessInfo configurePreProcInfo(const IE::InputInfo::CPtr& ii,
const cv::GMetaArg& mm) {
IE::PreProcessInfo info;
if (cv::util::holds_alternative<cv::GFrameDesc>(mm)) {
auto desc = cv::util::get<cv::GFrameDesc>(mm);
if (desc.fmt == cv::MediaFormat::NV12) {
info.setColorFormat(IE::ColorFormat::NV12);
}
}
const auto layout = ii->getTensorDesc().getLayout();
if (layout == IE::Layout::NCHW ||
layout == IE::Layout::NHWC) {
info.setResizeAlgorithm(IE::RESIZE_BILINEAR);
}
return info;
}
// NB: This is a callback used by async infer
// to post outputs blobs (cv::GMat's).
static void PostOutputs(InferenceEngine::InferRequest &request,
@ -921,11 +936,13 @@ struct Infer: public cv::detail::KernelTag {
// NB: Configuring input precision and network reshape must be done
// only in the loadNetwork case.
if (uu.params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Load) {
using namespace cv::gapi::ie::detail;
if (uu.params.kind == ParamDesc::Kind::Load) {
auto inputs = uu.net.getInputsInfo();
for (auto &&it : ade::util::zip(ade::util::toRange(uu.params.input_names),
ade::util::toRange(in_metas))) {
const auto &input_name = std::get<0>(it);
auto &&ii = uu.inputs.at(input_name);
auto ii = inputs.at(input_name);
const auto & mm = std::get<1>(it);
configureInputInfo(ii, mm);
@ -942,6 +959,18 @@ struct Infer: public cv::detail::KernelTag {
if (!input_reshape_table.empty()) {
const_cast<IE::CNNNetwork *>(&uu.net)->reshape(input_reshape_table);
}
} else {
GAPI_Assert(uu.params.kind == ParamDesc::Kind::Import);
auto inputs = uu.this_network.GetInputsInfo();
// FIXME: This isn't the best place to collect PreProcMap.
auto* non_const_prepm = const_cast<IEUnit::PreProcMap*>(&uu.preproc_map);
for (auto &&it : ade::util::zip(ade::util::toRange(uu.params.input_names),
ade::util::toRange(in_metas))) {
const auto &input_name = std::get<0>(it);
auto ii = inputs.at(input_name);
const auto & mm = std::get<1>(it);
non_const_prepm->emplace(input_name, configurePreProcInfo(ii, mm));
}
}
// FIXME: It would be nice here to have an exact number of network's
@ -950,11 +979,13 @@ struct Infer: public cv::detail::KernelTag {
for (const auto &out_name : uu.params.output_names) {
// NOTE: our output_names vector follows the API order
// of this operation's outputs
const IE::DataPtr& ie_out = uu.outputs.at(out_name);
const IE::SizeVector dims = ie_out->getTensorDesc().getDims();
const auto& desc =
uu.params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Load
? uu.net.getOutputsInfo().at(out_name)->getTensorDesc()
: uu.this_network.GetOutputsInfo().at(out_name)->getTensorDesc();
cv::GMatDesc outm(toCV(ie_out->getPrecision()),
toCV(ie_out->getTensorDesc().getDims()));
cv::GMatDesc outm(toCV(desc.getPrecision()),
toCV(desc.getDims()));
result.emplace_back(outm);
}
return result;
@ -973,10 +1004,7 @@ struct Infer: public cv::detail::KernelTag {
// and redirect our data producers to this memory
// (A memory dialog comes to the picture again)
IE::Blob::Ptr this_blob = extractBlob(*ctx, i);
setBlob(req,
ctx->uu.params.kind,
ctx->uu.params.input_names[i],
this_blob);
setBlob(req, ctx->uu.params.input_names[i], this_blob, *ctx);
}
// FIXME: Should it be done by kernel ?
// What about to do that in RequestPool ?
@ -1008,13 +1036,13 @@ struct InferROI: public cv::detail::KernelTag {
GAPI_Assert(1u == uu.params.input_names.size());
GAPI_Assert(2u == in_metas.size());
const auto &input_name = uu.params.input_names.at(0);
auto &&mm = in_metas.at(1u);
// NB: Configuring input precision and network reshape must be done
// only in the loadNetwork case.
if (uu.params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Load) {
// 0th is ROI, 1st is input image
const auto &input_name = uu.params.input_names.at(0);
auto &&ii = uu.inputs.at(input_name);
auto &&mm = in_metas.at(1u);
auto ii = uu.net.getInputsInfo().at(input_name);
configureInputInfo(ii, mm);
if (uu.params.layer_names_to_reshape.find(input_name) !=
uu.params.layer_names_to_reshape.end()) {
@ -1028,6 +1056,13 @@ struct InferROI: public cv::detail::KernelTag {
if (!input_reshape_table.empty()) {
const_cast<IE::CNNNetwork *>(&uu.net)->reshape(input_reshape_table);
}
} else {
GAPI_Assert(uu.params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Import);
auto inputs = uu.this_network.GetInputsInfo();
// FIXME: This isn't the best place to collect PreProcMap.
auto* non_const_prepm = const_cast<IEUnit::PreProcMap*>(&uu.preproc_map);
auto ii = inputs.at(input_name);
non_const_prepm->emplace(input_name, configurePreProcInfo(ii, mm));
}
// FIXME: It would be nice here to have an exact number of network's
@ -1036,11 +1071,13 @@ struct InferROI: public cv::detail::KernelTag {
for (const auto &out_name : uu.params.output_names) {
// NOTE: our output_names vector follows the API order
// of this operation's outputs
const IE::DataPtr& ie_out = uu.outputs.at(out_name);
const IE::SizeVector dims = ie_out->getTensorDesc().getDims();
const auto& desc =
uu.params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Load
? uu.net.getOutputsInfo().at(out_name)->getTensorDesc()
: uu.this_network.GetOutputsInfo().at(out_name)->getTensorDesc();
cv::GMatDesc outm(toCV(ie_out->getPrecision()),
toCV(ie_out->getTensorDesc().getDims()));
cv::GMatDesc outm(toCV(desc.getPrecision()),
toCV(desc.getDims()));
result.emplace_back(outm);
}
return result;
@ -1057,10 +1094,9 @@ struct InferROI: public cv::detail::KernelTag {
IE::Blob::Ptr this_blob = extractBlob(*ctx, 1);
setBlob(req,
ctx->uu.params.kind,
*(ctx->uu.params.input_names.begin()),
IE::make_shared_blob(this_blob,
toIE(this_roi)));
IE::make_shared_blob(this_blob, toIE(this_roi)),
*ctx);
// FIXME: Should it be done by kernel ?
// What about to do that in RequestPool ?
req.StartAsync();
@ -1099,8 +1135,9 @@ struct InferList: public cv::detail::KernelTag {
// only in the loadNetwork case.
if (uu.params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Load) {
std::size_t idx = 1u;
auto inputs = uu.net.getInputsInfo();
for (auto &&input_name : uu.params.input_names) {
auto &&ii = uu.inputs.at(input_name);
auto ii = inputs.at(input_name);
const auto & mm = in_metas[idx++];
configureInputInfo(ii, mm);
if (uu.params.layer_names_to_reshape.find(input_name) !=
@ -1116,6 +1153,16 @@ struct InferList: public cv::detail::KernelTag {
if (!input_reshape_table.empty()) {
const_cast<IE::CNNNetwork *>(&uu.net)->reshape(input_reshape_table);
}
} else {
GAPI_Assert(uu.params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Import);
std::size_t idx = 1u;
auto inputs = uu.this_network.GetInputsInfo();
auto* non_const_prepm = const_cast<IEUnit::PreProcMap*>(&uu.preproc_map);
for (auto &&input_name : uu.params.input_names) {
auto ii = inputs.at(input_name);
const auto & mm = in_metas[idx++];
non_const_prepm->emplace(input_name, configurePreProcInfo(ii, mm));
}
}
// roi-list version is much easier at the moment.
@ -1144,8 +1191,12 @@ struct InferList: public cv::detail::KernelTag {
std::vector<std::vector<int>> cached_dims(ctx->uu.params.num_out);
for (auto i : ade::util::iota(ctx->uu.params.num_out)) {
const IE::DataPtr& ie_out = ctx->uu.outputs.at(ctx->uu.params.output_names[i]);
cached_dims[i] = toCV(ie_out->getTensorDesc().getDims());
const auto& out_name = ctx->uu.params.output_names[i];
const auto& desc =
ctx->uu.params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Load
? ctx->uu.net.getOutputsInfo().at(out_name)->getTensorDesc()
: ctx->uu.this_network.GetOutputsInfo().at(out_name)->getTensorDesc();
cached_dims[i] = toCV(desc.getDims());
// FIXME: Isn't this should be done automatically
// by some resetInternalData(), etc? (Probably at the GExecutor level)
auto& out_vec = ctx->outVecR<cv::Mat>(i);
@ -1161,10 +1212,7 @@ struct InferList: public cv::detail::KernelTag {
cv::gimpl::ie::RequestPool::Task {
[ctx, rc, this_blob](InferenceEngine::InferRequest &req) {
IE::Blob::Ptr roi_blob = IE::make_shared_blob(this_blob, toIE(rc));
setBlob(req,
ctx->uu.params.kind,
ctx->uu.params.input_names[0u],
roi_blob);
setBlob(req, ctx->uu.params.input_names[0u], roi_blob, *ctx);
req.StartAsync();
},
std::bind(callback, std::placeholders::_1, pos)
@ -1232,7 +1280,6 @@ struct InferList2: public cv::detail::KernelTag {
std::size_t idx = 1u;
for (auto &&input_name : uu.params.input_names) {
auto &ii = uu.inputs.at(input_name);
const auto &mm = in_metas[idx];
GAPI_Assert(util::holds_alternative<cv::GArrayDesc>(mm)
&& "Non-array inputs are not supported");
@ -1242,6 +1289,7 @@ struct InferList2: public cv::detail::KernelTag {
// only in the loadNetwork case.
if (uu.params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Load) {
// This is a cv::Rect -- configure the IE preprocessing
auto ii = uu.net.getInputsInfo().at(input_name);
configureInputInfo(ii, mm_0);
if (uu.params.layer_names_to_reshape.find(input_name) !=
uu.params.layer_names_to_reshape.end()) {
@ -1255,6 +1303,12 @@ struct InferList2: public cv::detail::KernelTag {
if (!input_reshape_table.empty()) {
const_cast<IE::CNNNetwork *>(&uu.net)->reshape(input_reshape_table);
}
} else {
GAPI_Assert(uu.params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Import);
auto inputs = uu.this_network.GetInputsInfo();
auto* non_const_prepm = const_cast<IEUnit::PreProcMap*>(&uu.preproc_map);
auto ii = inputs.at(input_name);
non_const_prepm->emplace(input_name, configurePreProcInfo(ii, mm_0));
}
} else {
// This is a cv::GMat (equals to: cv::Mat)
@ -1290,8 +1344,12 @@ struct InferList2: public cv::detail::KernelTag {
// FIXME: This could be done ONCE at graph compile stage!
std::vector< std::vector<int> > cached_dims(ctx->uu.params.num_out);
for (auto i : ade::util::iota(ctx->uu.params.num_out)) {
const IE::DataPtr& ie_out = ctx->uu.outputs.at(ctx->uu.params.output_names[i]);
cached_dims[i] = toCV(ie_out->getTensorDesc().getDims());
const auto& out_name = ctx->uu.params.output_names[i];
const auto& desc =
ctx->uu.params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Load
? ctx->uu.net.getOutputsInfo().at(out_name)->getTensorDesc()
: ctx->uu.this_network.GetOutputsInfo().at(out_name)->getTensorDesc();
cached_dims[i] = toCV(desc.getDims());
// FIXME: Isn't this should be done automatically
// by some resetInternalData(), etc? (Probably at the GExecutor level)
auto& out_vec = ctx->outVecR<cv::Mat>(i);
@ -1319,10 +1377,7 @@ struct InferList2: public cv::detail::KernelTag {
GAPI_Assert(false &&
"Only Rect and Mat types are supported for infer list 2!");
}
setBlob(req,
ctx->uu.params.kind,
ctx->uu.params.input_names[in_idx],
this_blob);
setBlob(req, ctx->uu.params.input_names[in_idx], this_blob, *ctx);
}
req.StartAsync();
},

@ -18,6 +18,8 @@
#include <opencv2/core/utility.hpp>
#include <opencv2/core/utils/logger.hpp>
#include <opencv2/core/utils/configuration.private.hpp>
namespace IE = InferenceEngine;
namespace giewrap = cv::gimpl::ie::wrap;
using GIEParam = cv::gapi::ie::detail::ParamDesc;
@ -93,11 +95,38 @@ IE::InferencePlugin giewrap::getPlugin(const GIEParam& params) {
return plugin;
}
#else // >= 2019.R2
IE::Core giewrap::getCore() {
// NB: Some of IE plugins fail during IE::Core destroying in specific cases.
// Solution is allocate IE::Core in heap and doesn't destroy it, which cause
// leak, but fixes tests on CI. This behaviour is configurable by using
// OPENCV_GAPI_INFERENCE_ENGINE_CORE_LIFETIME_WORKAROUND=0
static IE::Core create_IE_Core_pointer() {
// NB: 'delete' is never called
static IE::Core* core = new IE::Core();
return *core;
}
static IE::Core create_IE_Core_instance() {
static IE::Core core;
return core;
}
IE::Core giewrap::getCore() {
// NB: to make happy memory leak tools use:
// - OPENCV_GAPI_INFERENCE_ENGINE_CORE_LIFETIME_WORKAROUND=0
static bool param_GAPI_INFERENCE_ENGINE_CORE_LIFETIME_WORKAROUND =
utils::getConfigurationParameterBool(
"OPENCV_GAPI_INFERENCE_ENGINE_CORE_LIFETIME_WORKAROUND",
#if defined(_WIN32) || defined(__APPLE__)
true
#else
false
#endif
);
return param_GAPI_INFERENCE_ENGINE_CORE_LIFETIME_WORKAROUND
? create_IE_Core_pointer() : create_IE_Core_instance();
}
IE::Core giewrap::getPlugin(const GIEParam& params) {
auto plugin = giewrap::getCore();
if (params.device_id == "CPU" || params.device_id == "FPGA")

@ -34,13 +34,12 @@ using Plugin = IE::InferencePlugin;
GAPI_EXPORTS IE::InferencePlugin getPlugin(const GIEParam& params);
GAPI_EXPORTS inline IE::ExecutableNetwork loadNetwork( IE::InferencePlugin& plugin,
const IE::CNNNetwork& net,
const GIEParam&) {
return plugin.LoadNetwork(net, {}); // FIXME: 2nd parameter to be
// configurable via the API
const GIEParam& params) {
return plugin.LoadNetwork(net, params.config);
}
GAPI_EXPORTS inline IE::ExecutableNetwork importNetwork( IE::CNNNetwork& plugin,
const GIEParam& param) {
return plugin.ImportNetwork(param.model_path, param.device_id, {});
const GIEParam& params) {
return plugin.ImportNetwork(param.model_path, param.device_id, params.config);
}
#else // >= 2019.R2
using Plugin = IE::Core;
@ -51,9 +50,9 @@ GAPI_EXPORTS inline IE::ExecutableNetwork loadNetwork( IE::Core& core
const GIEParam& params,
IE::RemoteContext::Ptr rctx = nullptr) {
if (rctx != nullptr) {
return core.LoadNetwork(net, rctx);
return core.LoadNetwork(net, rctx, params.config);
} else {
return core.LoadNetwork(net, params.device_id);
return core.LoadNetwork(net, params.device_id, params.config);
}
}
GAPI_EXPORTS inline IE::ExecutableNetwork importNetwork( IE::Core& core,
@ -67,9 +66,9 @@ GAPI_EXPORTS inline IE::ExecutableNetwork importNetwork( IE::Core& core,
throw std::runtime_error("Could not open file");
}
std::istream graphBlob(&blobFile);
return core.ImportNetwork(graphBlob, rctx);
return core.ImportNetwork(graphBlob, rctx, params.config);
} else {
return core.ImportNetwork(params.model_path, params.device_id, {});
return core.ImportNetwork(params.model_path, params.device_id, params.config);
}
}
#endif // INF_ENGINE_RELEASE < 2019020000

@ -139,6 +139,48 @@ void setNetParameters(IE::CNNNetwork& net, bool is_nv12 = false) {
}
}
bool checkDeviceIsAvailable(const std::string& device) {
const static auto available_devices = [&](){
auto devices = cv::gimpl::ie::wrap::getCore().GetAvailableDevices();
return std::unordered_set<std::string>{devices.begin(), devices.end()};
}();
return available_devices.find(device) != available_devices.end();
}
void skipIfDeviceNotAvailable(const std::string& device) {
if (!checkDeviceIsAvailable(device)) {
throw SkipTestException("Device: " + device + " isn't available!");
}
}
void compileBlob(const cv::gapi::ie::detail::ParamDesc& params,
const std::string& output,
const IE::Precision& ip) {
auto plugin = cv::gimpl::ie::wrap::getPlugin(params);
auto net = cv::gimpl::ie::wrap::readNetwork(params);
for (auto&& ii : net.getInputsInfo()) {
ii.second->setPrecision(ip);
}
auto this_network = cv::gimpl::ie::wrap::loadNetwork(plugin, net, params);
std::ofstream out_file{output, std::ios::out | std::ios::binary};
GAPI_Assert(out_file.is_open());
this_network.Export(out_file);
}
std::string compileAgeGenderBlob(const std::string& device) {
const static std::string blob_path = [&](){
cv::gapi::ie::detail::ParamDesc params;
const std::string model_name = "age-gender-recognition-retail-0013";
const std::string output = model_name + ".blob";
params.model_path = findDataFile(SUBDIR + model_name + ".xml");
params.weights_path = findDataFile(SUBDIR + model_name + ".bin");
params.device_id = device;
compileBlob(params, output, IE::Precision::U8);
return output;
}();
return blob_path;
}
} // anonymous namespace
// TODO: Probably DNN/IE part can be further parametrized with a template
@ -471,10 +513,10 @@ struct ROIListNV12: public ::testing::Test {
for (auto &&rc : m_roi_list) {
const auto ie_rc = IE::ROI {
0u
, static_cast<std::size_t>(rc.x)
, static_cast<std::size_t>(rc.y)
, static_cast<std::size_t>(rc.width)
, static_cast<std::size_t>(rc.height)
, static_cast<std::size_t>(rc.x)
, static_cast<std::size_t>(rc.y)
, static_cast<std::size_t>(rc.width)
, static_cast<std::size_t>(rc.height)
};
infer_request.SetBlob("data", IE::make_shared_blob(frame_blob, ie_rc));
infer_request.Infer();
@ -534,11 +576,11 @@ struct SingleROI: public ::testing::Test {
auto infer_request = this_network.CreateInferRequest();
const auto ie_rc = IE::ROI {
0u
, static_cast<std::size_t>(m_roi.x)
, static_cast<std::size_t>(m_roi.y)
, static_cast<std::size_t>(m_roi.width)
, static_cast<std::size_t>(m_roi.height)
0u
, static_cast<std::size_t>(m_roi.x)
, static_cast<std::size_t>(m_roi.y)
, static_cast<std::size_t>(m_roi.width)
, static_cast<std::size_t>(m_roi.height)
};
IE::Blob::Ptr roi_blob = IE::make_shared_blob(cv::gapi::ie::util::to_ie(m_in_mat), ie_rc);
@ -596,11 +638,11 @@ struct SingleROINV12: public ::testing::Test {
auto blob = cv::gapi::ie::util::to_ie(m_in_y, m_in_uv);
const auto ie_rc = IE::ROI {
0u
, static_cast<std::size_t>(m_roi.x)
, static_cast<std::size_t>(m_roi.y)
, static_cast<std::size_t>(m_roi.width)
, static_cast<std::size_t>(m_roi.height)
0u
, static_cast<std::size_t>(m_roi.x)
, static_cast<std::size_t>(m_roi.y)
, static_cast<std::size_t>(m_roi.width)
, static_cast<std::size_t>(m_roi.height)
};
IE::Blob::Ptr roi_blob = IE::make_shared_blob(blob, ie_rc);
@ -2065,7 +2107,7 @@ struct Sync {
class GMockMediaAdapter final: public cv::MediaFrame::IAdapter {
public:
explicit GMockMediaAdapter(cv::Mat m, Sync& sync)
explicit GMockMediaAdapter(cv::Mat m, std::shared_ptr<Sync> sync)
: m_mat(m), m_sync(sync) {
}
@ -2081,15 +2123,15 @@ public:
~GMockMediaAdapter() {
{
std::lock_guard<std::mutex> lk{m_sync.m};
m_sync.counter--;
std::lock_guard<std::mutex> lk{m_sync->m};
m_sync->counter--;
}
m_sync.cv.notify_one();
m_sync->cv.notify_one();
}
private:
cv::Mat m_mat;
Sync& m_sync;
cv::Mat m_mat;
std::shared_ptr<Sync> m_sync;
};
// NB: This source is needed to simulate real
@ -2099,15 +2141,16 @@ private:
class GMockSource : public cv::gapi::wip::IStreamSource {
public:
explicit GMockSource(int limit)
: m_limit(limit), m_mat(cv::Size(1920, 1080), CV_8UC3) {
: m_limit(limit), m_mat(cv::Size(1920, 1080), CV_8UC3),
m_sync(new Sync{}) {
cv::randu(m_mat, cv::Scalar::all(0), cv::Scalar::all(255));
}
bool pull(cv::gapi::wip::Data& data) {
std::unique_lock<std::mutex> lk(m_sync.m);
m_sync.counter++;
std::unique_lock<std::mutex> lk(m_sync->m);
m_sync->counter++;
// NB: Can't produce new frames until old ones are released.
m_sync.cv.wait(lk, [this]{return m_sync.counter <= m_limit;});
m_sync->cv.wait(lk, [this]{return m_sync->counter <= m_limit;});
data = cv::MediaFrame::Create<GMockMediaAdapter>(m_mat, m_sync);
return true;
@ -2118,9 +2161,9 @@ public:
}
private:
int m_limit;
cv::Mat m_mat;
Sync m_sync;
int m_limit;
cv::Mat m_mat;
std::shared_ptr<Sync> m_sync;
};
struct LimitedSourceInfer: public ::testing::Test {
@ -2239,6 +2282,582 @@ TEST(TestAgeGenderIE, InferWithBatch)
normAssert(cv::gapi::ie::util::to_ocv(ie_gender), gapi_gender, "Test gender output");
}
TEST(ImportNetwork, Infer)
{
const std::string device = "MYRIAD";
skipIfDeviceNotAvailable(device);
initDLDTDataPath();
cv::gapi::ie::detail::ParamDesc params;
params.model_path = compileAgeGenderBlob(device);
params.device_id = device;
cv::Mat in_mat(320, 240, CV_8UC3);
cv::randu(in_mat, 0, 255);
cv::Mat gapi_age, gapi_gender;
// Load & run IE network
IE::Blob::Ptr ie_age, ie_gender;
{
auto plugin = cv::gimpl::ie::wrap::getPlugin(params);
auto this_network = cv::gimpl::ie::wrap::importNetwork(plugin, params);
auto infer_request = this_network.CreateInferRequest();
IE::PreProcessInfo info;
info.setResizeAlgorithm(IE::RESIZE_BILINEAR);
infer_request.SetBlob("data", cv::gapi::ie::util::to_ie(in_mat), info);
infer_request.Infer();
ie_age = infer_request.GetBlob("age_conv3");
ie_gender = infer_request.GetBlob("prob");
}
// Configure & run G-API
using AGInfo = std::tuple<cv::GMat, cv::GMat>;
G_API_NET(AgeGender, <AGInfo(cv::GMat)>, "test-age-gender");
cv::GMat in;
cv::GMat age, gender;
std::tie(age, gender) = cv::gapi::infer<AgeGender>(in);
cv::GComputation comp(cv::GIn(in), cv::GOut(age, gender));
auto pp = cv::gapi::ie::Params<AgeGender> {
params.model_path, params.device_id
}.cfgOutputLayers({ "age_conv3", "prob" });
comp.apply(cv::gin(in_mat), cv::gout(gapi_age, gapi_gender),
cv::compile_args(cv::gapi::networks(pp)));
// Validate with IE itself (avoid DNN module dependency here)
normAssert(cv::gapi::ie::util::to_ocv(ie_age), gapi_age, "Test age output" );
normAssert(cv::gapi::ie::util::to_ocv(ie_gender), gapi_gender, "Test gender output");
}
TEST(ImportNetwork, InferNV12)
{
const std::string device = "MYRIAD";
skipIfDeviceNotAvailable(device);
initDLDTDataPath();
cv::gapi::ie::detail::ParamDesc params;
params.model_path= compileAgeGenderBlob(device);
params.device_id = device;
cv::Size sz{320, 240};
cv::Mat in_y_mat(sz, CV_8UC1);
cv::randu(in_y_mat, 0, 255);
cv::Mat in_uv_mat(sz / 2, CV_8UC2);
cv::randu(in_uv_mat, 0, 255);
cv::Mat gapi_age, gapi_gender;
// Load & run IE network
IE::Blob::Ptr ie_age, ie_gender;
{
auto plugin = cv::gimpl::ie::wrap::getPlugin(params);
auto this_network = cv::gimpl::ie::wrap::importNetwork(plugin, params);
auto infer_request = this_network.CreateInferRequest();
IE::PreProcessInfo info;
info.setResizeAlgorithm(IE::RESIZE_BILINEAR);
info.setColorFormat(IE::ColorFormat::NV12);
infer_request.SetBlob("data", cv::gapi::ie::util::to_ie(in_y_mat, in_uv_mat), info);
infer_request.Infer();
ie_age = infer_request.GetBlob("age_conv3");
ie_gender = infer_request.GetBlob("prob");
}
// Configure & run G-API
using AGInfo = std::tuple<cv::GMat, cv::GMat>;
G_API_NET(AgeGender, <AGInfo(cv::GMat)>, "test-age-gender");
cv::GFrame in;
cv::GMat age, gender;
std::tie(age, gender) = cv::gapi::infer<AgeGender>(in);
cv::GComputation comp(cv::GIn(in), cv::GOut(age, gender));
auto frame = MediaFrame::Create<TestMediaNV12>(in_y_mat, in_uv_mat);
auto pp = cv::gapi::ie::Params<AgeGender> {
params.model_path, params.device_id
}.cfgOutputLayers({ "age_conv3", "prob" });
comp.apply(cv::gin(frame), cv::gout(gapi_age, gapi_gender),
cv::compile_args(cv::gapi::networks(pp)));
// Validate with IE itself (avoid DNN module dependency here)
normAssert(cv::gapi::ie::util::to_ocv(ie_age), gapi_age, "Test age output" );
normAssert(cv::gapi::ie::util::to_ocv(ie_gender), gapi_gender, "Test gender output");
}
TEST(ImportNetwork, InferROI)
{
const std::string device = "MYRIAD";
skipIfDeviceNotAvailable(device);
initDLDTDataPath();
cv::gapi::ie::detail::ParamDesc params;
params.model_path = compileAgeGenderBlob(device);
params.device_id = device;
cv::Mat in_mat(320, 240, CV_8UC3);
cv::randu(in_mat, 0, 255);
cv::Mat gapi_age, gapi_gender;
cv::Rect rect(cv::Point{64, 60}, cv::Size{96, 96});
// Load & run IE network
IE::Blob::Ptr ie_age, ie_gender;
{
auto plugin = cv::gimpl::ie::wrap::getPlugin(params);
auto this_network = cv::gimpl::ie::wrap::importNetwork(plugin, params);
auto infer_request = this_network.CreateInferRequest();
const auto ie_rc = IE::ROI {
0u
, static_cast<std::size_t>(rect.x)
, static_cast<std::size_t>(rect.y)
, static_cast<std::size_t>(rect.width)
, static_cast<std::size_t>(rect.height)
};
IE::Blob::Ptr roi_blob = IE::make_shared_blob(cv::gapi::ie::util::to_ie(in_mat), ie_rc);
IE::PreProcessInfo info;
info.setResizeAlgorithm(IE::RESIZE_BILINEAR);
infer_request.SetBlob("data", roi_blob, info);
infer_request.Infer();
ie_age = infer_request.GetBlob("age_conv3");
ie_gender = infer_request.GetBlob("prob");
}
using AGInfo = std::tuple<cv::GMat, cv::GMat>;
G_API_NET(AgeGender, <AGInfo(cv::GMat)>, "test-age-gender");
cv::GMat in;
cv::GOpaque<cv::Rect> roi;
cv::GMat age, gender;
std::tie(age, gender) = cv::gapi::infer<AgeGender>(roi, in);
cv::GComputation comp(cv::GIn(in, roi), cv::GOut(age, gender));
auto pp = cv::gapi::ie::Params<AgeGender> {
params.model_path, params.device_id
}.cfgOutputLayers({ "age_conv3", "prob" });
comp.apply(cv::gin(in_mat, rect), cv::gout(gapi_age, gapi_gender),
cv::compile_args(cv::gapi::networks(pp)));
// Validate with IE itself (avoid DNN module dependency here)
normAssert(cv::gapi::ie::util::to_ocv(ie_age), gapi_age, "Test age output" );
normAssert(cv::gapi::ie::util::to_ocv(ie_gender), gapi_gender, "Test gender output");
}
TEST(ImportNetwork, InferROINV12)
{
const std::string device = "MYRIAD";
skipIfDeviceNotAvailable(device);
initDLDTDataPath();
cv::gapi::ie::detail::ParamDesc params;
params.model_path = compileAgeGenderBlob(device);
params.device_id = device;
cv::Size sz{320, 240};
cv::Mat in_y_mat(sz, CV_8UC1);
cv::randu(in_y_mat, 0, 255);
cv::Mat in_uv_mat(sz / 2, CV_8UC2);
cv::randu(in_uv_mat, 0, 255);
cv::Rect rect(cv::Point{64, 60}, cv::Size{96, 96});
cv::Mat gapi_age, gapi_gender;
// Load & run IE network
IE::Blob::Ptr ie_age, ie_gender;
{
auto plugin = cv::gimpl::ie::wrap::getPlugin(params);
auto this_network = cv::gimpl::ie::wrap::importNetwork(plugin, params);
auto infer_request = this_network.CreateInferRequest();
const auto ie_rc = IE::ROI {
0u
, static_cast<std::size_t>(rect.x)
, static_cast<std::size_t>(rect.y)
, static_cast<std::size_t>(rect.width)
, static_cast<std::size_t>(rect.height)
};
IE::Blob::Ptr roi_blob =
IE::make_shared_blob(cv::gapi::ie::util::to_ie(in_y_mat, in_uv_mat), ie_rc);
IE::PreProcessInfo info;
info.setResizeAlgorithm(IE::RESIZE_BILINEAR);
info.setColorFormat(IE::ColorFormat::NV12);
infer_request.SetBlob("data", roi_blob, info);
infer_request.Infer();
ie_age = infer_request.GetBlob("age_conv3");
ie_gender = infer_request.GetBlob("prob");
}
using AGInfo = std::tuple<cv::GMat, cv::GMat>;
G_API_NET(AgeGender, <AGInfo(cv::GMat)>, "test-age-gender");
cv::GFrame in;
cv::GOpaque<cv::Rect> roi;
cv::GMat age, gender;
std::tie(age, gender) = cv::gapi::infer<AgeGender>(roi, in);
cv::GComputation comp(cv::GIn(in, roi), cv::GOut(age, gender));
auto frame = MediaFrame::Create<TestMediaNV12>(in_y_mat, in_uv_mat);
auto pp = cv::gapi::ie::Params<AgeGender> {
params.model_path, params.device_id
}.cfgOutputLayers({ "age_conv3", "prob" });
comp.apply(cv::gin(frame, rect), cv::gout(gapi_age, gapi_gender),
cv::compile_args(cv::gapi::networks(pp)));
// Validate with IE itself (avoid DNN module dependency here)
normAssert(cv::gapi::ie::util::to_ocv(ie_age), gapi_age, "Test age output" );
normAssert(cv::gapi::ie::util::to_ocv(ie_gender), gapi_gender, "Test gender output");
}
TEST(ImportNetwork, InferList)
{
const std::string device = "MYRIAD";
skipIfDeviceNotAvailable(device);
initDLDTDataPath();
cv::gapi::ie::detail::ParamDesc params;
params.model_path = compileAgeGenderBlob(device);
params.device_id = device;
cv::Mat in_mat(320, 240, CV_8UC3);
cv::randu(in_mat, 0, 255);
std::vector<cv::Rect> roi_list = {
cv::Rect(cv::Point{64, 60}, cv::Size{ 96, 96}),
cv::Rect(cv::Point{50, 32}, cv::Size{128, 160}),
};
std::vector<cv::Mat> out_ie_ages, out_ie_genders, out_gapi_ages, out_gapi_genders;
// Load & run IE network
{
auto plugin = cv::gimpl::ie::wrap::getPlugin(params);
auto this_network = cv::gimpl::ie::wrap::importNetwork(plugin, params);
auto infer_request = this_network.CreateInferRequest();
for (auto &&rc : roi_list) {
const auto ie_rc = IE::ROI {
0u
, static_cast<std::size_t>(rc.x)
, static_cast<std::size_t>(rc.y)
, static_cast<std::size_t>(rc.width)
, static_cast<std::size_t>(rc.height)
};
IE::Blob::Ptr roi_blob =
IE::make_shared_blob(cv::gapi::ie::util::to_ie(in_mat), ie_rc);
IE::PreProcessInfo info;
info.setResizeAlgorithm(IE::RESIZE_BILINEAR);
infer_request.SetBlob("data", roi_blob, info);
infer_request.Infer();
using namespace cv::gapi::ie::util;
out_ie_ages.push_back(to_ocv(infer_request.GetBlob("age_conv3")).clone());
out_ie_genders.push_back(to_ocv(infer_request.GetBlob("prob")).clone());
}
}
// Configure & run G-API
using AGInfo = std::tuple<cv::GMat, cv::GMat>;
G_API_NET(AgeGender, <AGInfo(cv::GMat)>, "test-age-gender");
cv::GArray<cv::Rect> rr;
cv::GMat in;
cv::GArray<cv::GMat> age, gender;
std::tie(age, gender) = cv::gapi::infer<AgeGender>(rr, in);
cv::GComputation comp(cv::GIn(in, rr), cv::GOut(age, gender));
auto pp = cv::gapi::ie::Params<AgeGender> {
params.model_path, params.device_id
}.cfgOutputLayers({ "age_conv3", "prob" });
comp.apply(cv::gin(in_mat, roi_list), cv::gout(out_gapi_ages, out_gapi_genders),
cv::compile_args(cv::gapi::networks(pp)));
// Validate with IE itself (avoid DNN module dependency here)
GAPI_Assert(!out_gapi_ages.empty());
ASSERT_EQ(out_gapi_genders.size(), out_gapi_ages.size());
ASSERT_EQ(out_gapi_ages.size(), out_ie_ages.size());
ASSERT_EQ(out_gapi_genders.size(), out_ie_genders.size());
const size_t size = out_gapi_ages.size();
for (size_t i = 0; i < size; ++i) {
normAssert(out_ie_ages [i], out_gapi_ages [i], "Test age output");
normAssert(out_ie_genders[i], out_gapi_genders[i], "Test gender output");
}
}
TEST(ImportNetwork, InferListNV12)
{
const std::string device = "MYRIAD";
skipIfDeviceNotAvailable(device);
initDLDTDataPath();
cv::gapi::ie::detail::ParamDesc params;
params.model_path = compileAgeGenderBlob(device);
params.device_id = device;
cv::Size sz{320, 240};
cv::Mat in_y_mat(sz, CV_8UC1);
cv::randu(in_y_mat, 0, 255);
cv::Mat in_uv_mat(sz / 2, CV_8UC2);
cv::randu(in_uv_mat, 0, 255);
std::vector<cv::Rect> roi_list = {
cv::Rect(cv::Point{64, 60}, cv::Size{ 96, 96}),
cv::Rect(cv::Point{50, 32}, cv::Size{128, 160}),
};
std::vector<cv::Mat> out_ie_ages, out_ie_genders, out_gapi_ages, out_gapi_genders;
// Load & run IE network
{
auto plugin = cv::gimpl::ie::wrap::getPlugin(params);
auto this_network = cv::gimpl::ie::wrap::importNetwork(plugin, params);
auto infer_request = this_network.CreateInferRequest();
for (auto &&rc : roi_list) {
const auto ie_rc = IE::ROI {
0u
, static_cast<std::size_t>(rc.x)
, static_cast<std::size_t>(rc.y)
, static_cast<std::size_t>(rc.width)
, static_cast<std::size_t>(rc.height)
};
IE::Blob::Ptr roi_blob =
IE::make_shared_blob(cv::gapi::ie::util::to_ie(in_y_mat, in_uv_mat), ie_rc);
IE::PreProcessInfo info;
info.setResizeAlgorithm(IE::RESIZE_BILINEAR);
info.setColorFormat(IE::ColorFormat::NV12);
infer_request.SetBlob("data", roi_blob, info);
infer_request.Infer();
using namespace cv::gapi::ie::util;
out_ie_ages.push_back(to_ocv(infer_request.GetBlob("age_conv3")).clone());
out_ie_genders.push_back(to_ocv(infer_request.GetBlob("prob")).clone());
}
}
// Configure & run G-API
using AGInfo = std::tuple<cv::GMat, cv::GMat>;
G_API_NET(AgeGender, <AGInfo(cv::GMat)>, "test-age-gender");
cv::GArray<cv::Rect> rr;
cv::GFrame in;
cv::GArray<cv::GMat> age, gender;
std::tie(age, gender) = cv::gapi::infer<AgeGender>(rr, in);
cv::GComputation comp(cv::GIn(in, rr), cv::GOut(age, gender));
auto pp = cv::gapi::ie::Params<AgeGender> {
params.model_path, params.device_id
}.cfgOutputLayers({ "age_conv3", "prob" });
auto frame = MediaFrame::Create<TestMediaNV12>(in_y_mat, in_uv_mat);
comp.apply(cv::gin(frame, roi_list), cv::gout(out_gapi_ages, out_gapi_genders),
cv::compile_args(cv::gapi::networks(pp)));
// Validate with IE itself (avoid DNN module dependency here)
GAPI_Assert(!out_gapi_ages.empty());
ASSERT_EQ(out_gapi_genders.size(), out_gapi_ages.size());
ASSERT_EQ(out_gapi_ages.size(), out_ie_ages.size());
ASSERT_EQ(out_gapi_genders.size(), out_ie_genders.size());
const size_t size = out_gapi_ages.size();
for (size_t i = 0; i < size; ++i) {
normAssert(out_ie_ages [i], out_gapi_ages [i], "Test age output");
normAssert(out_ie_genders[i], out_gapi_genders[i], "Test gender output");
}
}
TEST(ImportNetwork, InferList2)
{
const std::string device = "MYRIAD";
skipIfDeviceNotAvailable(device);
initDLDTDataPath();
cv::gapi::ie::detail::ParamDesc params;
params.model_path = compileAgeGenderBlob(device);
params.device_id = device;
cv::Mat in_mat(320, 240, CV_8UC3);
cv::randu(in_mat, 0, 255);
std::vector<cv::Rect> roi_list = {
cv::Rect(cv::Point{64, 60}, cv::Size{ 96, 96}),
cv::Rect(cv::Point{50, 32}, cv::Size{128, 160}),
};
std::vector<cv::Mat> out_ie_ages, out_ie_genders, out_gapi_ages, out_gapi_genders;
// Load & run IE network
{
auto plugin = cv::gimpl::ie::wrap::getPlugin(params);
auto this_network = cv::gimpl::ie::wrap::importNetwork(plugin, params);
auto infer_request = this_network.CreateInferRequest();
for (auto &&rc : roi_list) {
const auto ie_rc = IE::ROI {
0u
, static_cast<std::size_t>(rc.x)
, static_cast<std::size_t>(rc.y)
, static_cast<std::size_t>(rc.width)
, static_cast<std::size_t>(rc.height)
};
IE::Blob::Ptr roi_blob =
IE::make_shared_blob(cv::gapi::ie::util::to_ie(in_mat), ie_rc);
IE::PreProcessInfo info;
info.setResizeAlgorithm(IE::RESIZE_BILINEAR);
infer_request.SetBlob("data", roi_blob, info);
infer_request.Infer();
using namespace cv::gapi::ie::util;
out_ie_ages.push_back(to_ocv(infer_request.GetBlob("age_conv3")).clone());
out_ie_genders.push_back(to_ocv(infer_request.GetBlob("prob")).clone());
}
}
// Configure & run G-API
using AGInfo = std::tuple<cv::GMat, cv::GMat>;
G_API_NET(AgeGender, <AGInfo(cv::GMat)>, "test-age-gender");
cv::GArray<cv::Rect> rr;
cv::GMat in;
cv::GArray<cv::GMat> age, gender;
std::tie(age, gender) = cv::gapi::infer2<AgeGender>(in, rr);
cv::GComputation comp(cv::GIn(in, rr), cv::GOut(age, gender));
auto pp = cv::gapi::ie::Params<AgeGender> {
params.model_path, params.device_id
}.cfgOutputLayers({ "age_conv3", "prob" });
comp.apply(cv::gin(in_mat, roi_list), cv::gout(out_gapi_ages, out_gapi_genders),
cv::compile_args(cv::gapi::networks(pp)));
// Validate with IE itself (avoid DNN module dependency here)
GAPI_Assert(!out_gapi_ages.empty());
ASSERT_EQ(out_gapi_genders.size(), out_gapi_ages.size());
ASSERT_EQ(out_gapi_ages.size(), out_ie_ages.size());
ASSERT_EQ(out_gapi_genders.size(), out_ie_genders.size());
const size_t size = out_gapi_ages.size();
for (size_t i = 0; i < size; ++i) {
normAssert(out_ie_ages [i], out_gapi_ages [i], "Test age output");
normAssert(out_ie_genders[i], out_gapi_genders[i], "Test gender output");
}
}
TEST(ImportNetwork, InferList2NV12)
{
const std::string device = "MYRIAD";
skipIfDeviceNotAvailable(device);
initDLDTDataPath();
cv::gapi::ie::detail::ParamDesc params;
params.model_path = compileAgeGenderBlob(device);
params.device_id = device;
cv::Size sz{320, 240};
cv::Mat in_y_mat(sz, CV_8UC1);
cv::randu(in_y_mat, 0, 255);
cv::Mat in_uv_mat(sz / 2, CV_8UC2);
cv::randu(in_uv_mat, 0, 255);
std::vector<cv::Rect> roi_list = {
cv::Rect(cv::Point{64, 60}, cv::Size{ 96, 96}),
cv::Rect(cv::Point{50, 32}, cv::Size{128, 160}),
};
std::vector<cv::Mat> out_ie_ages, out_ie_genders, out_gapi_ages, out_gapi_genders;
// Load & run IE network
{
auto plugin = cv::gimpl::ie::wrap::getPlugin(params);
auto this_network = cv::gimpl::ie::wrap::importNetwork(plugin, params);
auto infer_request = this_network.CreateInferRequest();
for (auto &&rc : roi_list) {
const auto ie_rc = IE::ROI {
0u
, static_cast<std::size_t>(rc.x)
, static_cast<std::size_t>(rc.y)
, static_cast<std::size_t>(rc.width)
, static_cast<std::size_t>(rc.height)
};
IE::Blob::Ptr roi_blob =
IE::make_shared_blob(cv::gapi::ie::util::to_ie(in_y_mat, in_uv_mat), ie_rc);
IE::PreProcessInfo info;
info.setResizeAlgorithm(IE::RESIZE_BILINEAR);
info.setColorFormat(IE::ColorFormat::NV12);
infer_request.SetBlob("data", roi_blob, info);
infer_request.Infer();
using namespace cv::gapi::ie::util;
out_ie_ages.push_back(to_ocv(infer_request.GetBlob("age_conv3")).clone());
out_ie_genders.push_back(to_ocv(infer_request.GetBlob("prob")).clone());
}
}
// Configure & run G-API
using AGInfo = std::tuple<cv::GMat, cv::GMat>;
G_API_NET(AgeGender, <AGInfo(cv::GMat)>, "test-age-gender");
cv::GArray<cv::Rect> rr;
cv::GFrame in;
cv::GArray<cv::GMat> age, gender;
std::tie(age, gender) = cv::gapi::infer2<AgeGender>(in, rr);
cv::GComputation comp(cv::GIn(in, rr), cv::GOut(age, gender));
auto pp = cv::gapi::ie::Params<AgeGender> {
params.model_path, params.device_id
}.cfgOutputLayers({ "age_conv3", "prob" });
auto frame = MediaFrame::Create<TestMediaNV12>(in_y_mat, in_uv_mat);
comp.apply(cv::gin(frame, roi_list), cv::gout(out_gapi_ages, out_gapi_genders),
cv::compile_args(cv::gapi::networks(pp)));
// Validate with IE itself (avoid DNN module dependency here)
GAPI_Assert(!out_gapi_ages.empty());
ASSERT_EQ(out_gapi_genders.size(), out_gapi_ages.size());
ASSERT_EQ(out_gapi_ages.size(), out_ie_ages.size());
ASSERT_EQ(out_gapi_genders.size(), out_ie_genders.size());
const size_t size = out_gapi_ages.size();
for (size_t i = 0; i < size; ++i) {
normAssert(out_ie_ages [i], out_gapi_ages [i], "Test age output");
normAssert(out_ie_genders[i], out_gapi_genders[i], "Test gender output");
}
}
TEST(TestAgeGender, ThrowBlobAndInputPrecisionMismatch)
{
const std::string device = "MYRIAD";
skipIfDeviceNotAvailable(device);
initDLDTDataPath();
cv::gapi::ie::detail::ParamDesc params;
// NB: Precision for inputs is U8.
params.model_path = compileAgeGenderBlob(device);
params.device_id = device;
// Configure & run G-API
using AGInfo = std::tuple<cv::GMat, cv::GMat>;
G_API_NET(AgeGender, <AGInfo(cv::GMat)>, "test-age-gender");
cv::GMat in, age, gender;
std::tie(age, gender) = cv::gapi::infer<AgeGender>(in);
cv::GComputation comp(cv::GIn(in), cv::GOut(age, gender));
auto pp = cv::gapi::ie::Params<AgeGender> {
params.model_path, params.device_id
}.cfgOutputLayers({ "age_conv3", "prob" });
cv::Mat in_mat(320, 240, CV_32FC3);
cv::randu(in_mat, 0, 1);
cv::Mat gapi_age, gapi_gender;
// NB: Blob precision is U8, but user pass FP32 data, so exception will be thrown.
// Now exception comes directly from IE, but since G-API has information
// about data precision at the compile stage, consider the possibility of
// throwing exception from there.
EXPECT_ANY_THROW(comp.apply(cv::gin(in_mat), cv::gout(gapi_age, gapi_gender),
cv::compile_args(cv::gapi::networks(pp))));
}
} // namespace opencv_test
#endif // HAVE_INF_ENGINE

Loading…
Cancel
Save