diff --git a/modules/gapi/include/opencv2/gapi/infer/bindings_ie.hpp b/modules/gapi/include/opencv2/gapi/infer/bindings_ie.hpp index 92ef2101a1..94272dea55 100644 --- a/modules/gapi/include/opencv2/gapi/infer/bindings_ie.hpp +++ b/modules/gapi/include/opencv2/gapi/infer/bindings_ie.hpp @@ -44,6 +44,9 @@ public: GAPI_WRAP PyParams& cfgNumRequests(size_t nireq); + GAPI_WRAP + PyParams& cfgBatchSize(const size_t size); + GBackend backend() const; std::string tag() const; cv::util::any params() const; diff --git a/modules/gapi/include/opencv2/gapi/infer/ie.hpp b/modules/gapi/include/opencv2/gapi/infer/ie.hpp index 2be739e518..0e9c127fa1 100644 --- a/modules/gapi/include/opencv2/gapi/infer/ie.hpp +++ b/modules/gapi/include/opencv2/gapi/infer/ie.hpp @@ -79,6 +79,8 @@ struct ParamDesc { // NB: An optional config to setup RemoteContext for IE cv::util::any context_config; + + size_t batch_size; }; } // namespace detail @@ -120,7 +122,8 @@ public: , {} , {} , 1u - , {}} { + , {} + , 1u} { }; /** @overload @@ -141,7 +144,8 @@ public: , {} , {} , 1u - , {}} { + , {} + , 1u} { }; /** @brief Specifies sequence of network input layers names for inference. @@ -316,6 +320,19 @@ public: return *this; } + /** @brief Specifies the inference batch size. + + The function is used to specify inference batch size. + Follow https://docs.openvinotoolkit.org/latest/classInferenceEngine_1_1CNNNetwork.html#a8e9d19270a48aab50cb5b1c43eecb8e9 for additional information + + @param size batch size which will be used. + @return reference to this parameter structure. + */ + Params& cfgBatchSize(const size_t size) { + desc.batch_size = size; + return *this; + } + // BEGIN(G-API's network parametrization API) GBackend backend() const { return cv::gapi::ie::backend(); } std::string tag() const { return Net::tag(); } @@ -350,7 +367,7 @@ public: const std::string &device) : desc{ model, weights, device, {}, {}, {}, 0u, 0u, detail::ParamDesc::Kind::Load, true, {}, {}, {}, 1u, - {}}, + {}, 1u}, m_tag(tag) { }; @@ -368,7 +385,7 @@ public: const std::string &device) : desc{ model, {}, device, {}, {}, {}, 0u, 0u, detail::ParamDesc::Kind::Import, true, {}, {}, {}, 1u, - {}}, + {}, 1u}, m_tag(tag) { }; @@ -435,6 +452,12 @@ public: return *this; } + /** @see ie::Params::cfgBatchSize */ + Params& cfgBatchSize(const size_t size) { + desc.batch_size = size; + return *this; + } + // BEGIN(G-API's network parametrization API) GBackend backend() const { return cv::gapi::ie::backend(); } std::string tag() const { return m_tag; } diff --git a/modules/gapi/src/backends/ie/bindings_ie.cpp b/modules/gapi/src/backends/ie/bindings_ie.cpp index 5874fe1378..39f07d28e5 100644 --- a/modules/gapi/src/backends/ie/bindings_ie.cpp +++ b/modules/gapi/src/backends/ie/bindings_ie.cpp @@ -49,3 +49,9 @@ cv::gapi::ie::PyParams& cv::gapi::ie::PyParams::cfgNumRequests(size_t nireq) { m_priv->cfgNumRequests(nireq); return *this; } + +cv::gapi::ie::PyParams& +cv::gapi::ie::PyParams::cfgBatchSize(const size_t size) { + m_priv->cfgBatchSize(size); + return *this; +} diff --git a/modules/gapi/src/backends/ie/giebackend.cpp b/modules/gapi/src/backends/ie/giebackend.cpp index 03584c9561..c69302baca 100644 --- a/modules/gapi/src/backends/ie/giebackend.cpp +++ b/modules/gapi/src/backends/ie/giebackend.cpp @@ -237,6 +237,7 @@ 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) { @@ -1412,11 +1413,11 @@ std::vector cv::gapi::ie::util::to_ocv(const IE::SizeVector &dims) { return toCV(dims); } -IE::Blob::Ptr cv::gapi::ie::util::to_ie(cv::Mat &blob) { +IE::Blob::Ptr cv::gapi::ie::util::to_ie(const cv::Mat &blob) { return wrapIE(blob, cv::gapi::ie::TraitAs::IMAGE); } -IE::Blob::Ptr cv::gapi::ie::util::to_ie(cv::Mat &y_plane, cv::Mat &uv_plane) { +IE::Blob::Ptr cv::gapi::ie::util::to_ie(const cv::Mat &y_plane, const cv::Mat &uv_plane) { auto y_blob = wrapIE(y_plane, cv::gapi::ie::TraitAs::IMAGE); auto uv_blob = wrapIE(uv_plane, cv::gapi::ie::TraitAs::IMAGE); #if INF_ENGINE_RELEASE >= 2021010000 diff --git a/modules/gapi/src/backends/ie/util.hpp b/modules/gapi/src/backends/ie/util.hpp index 080c88498f..e2f1f44140 100644 --- a/modules/gapi/src/backends/ie/util.hpp +++ b/modules/gapi/src/backends/ie/util.hpp @@ -27,8 +27,8 @@ namespace util { // test suite only. GAPI_EXPORTS std::vector to_ocv(const InferenceEngine::SizeVector &dims); GAPI_EXPORTS cv::Mat to_ocv(InferenceEngine::Blob::Ptr blob); -GAPI_EXPORTS InferenceEngine::Blob::Ptr to_ie(cv::Mat &blob); -GAPI_EXPORTS InferenceEngine::Blob::Ptr to_ie(cv::Mat &y_plane, cv::Mat &uv_plane); +GAPI_EXPORTS InferenceEngine::Blob::Ptr to_ie(const cv::Mat &blob); +GAPI_EXPORTS InferenceEngine::Blob::Ptr to_ie(const cv::Mat &y_plane, const cv::Mat &uv_plane); }}}} diff --git a/modules/gapi/test/infer/gapi_infer_ie_test.cpp b/modules/gapi/test/infer/gapi_infer_ie_test.cpp index b7ea891b81..49cf47048e 100644 --- a/modules/gapi/test/infer/gapi_infer_ie_test.cpp +++ b/modules/gapi/test/infer/gapi_infer_ie_test.cpp @@ -2,7 +2,7 @@ // It is subject to the license terms in the LICENSE file found in the top-level directory // of this distribution and at http://opencv.org/license.html. // -// Copyright (C) 2019-2020 Intel Corporation +// Copyright (C) 2019-2021 Intel Corporation #include "../test_precomp.hpp" @@ -2187,6 +2187,58 @@ TEST_F(LimitedSourceInfer, ReleaseFrameAsync) run(max_frames, resources_limit, nireq); } +TEST(TestAgeGenderIE, InferWithBatch) +{ + initDLDTDataPath(); + + constexpr int batch_size = 4; + cv::gapi::ie::detail::ParamDesc params; + params.model_path = findDataFile(SUBDIR + "age-gender-recognition-retail-0013.xml"); + params.weights_path = findDataFile(SUBDIR + "age-gender-recognition-retail-0013.bin"); + params.device_id = "CPU"; + + cv::Mat in_mat({batch_size, 3, 320, 240}, CV_8U); + 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 net = cv::gimpl::ie::wrap::readNetwork(params); + setNetParameters(net); + net.setBatchSize(batch_size); + auto this_network = cv::gimpl::ie::wrap::loadNetwork(plugin, net, params); + auto infer_request = this_network.CreateInferRequest(); + infer_request.SetBlob("data", cv::gapi::ie::util::to_ie(in_mat)); + infer_request.Infer(); + ie_age = infer_request.GetBlob("age_conv3"); + ie_gender = infer_request.GetBlob("prob"); + } + + // Configure & run G-API + using AGInfo = std::tuple; + G_API_NET(AgeGender, , "test-age-gender"); + + cv::GMat in; + cv::GMat age, gender; + std::tie(age, gender) = cv::gapi::infer(in); + cv::GComputation comp(cv::GIn(in), cv::GOut(age, gender)); + + auto pp = cv::gapi::ie::Params { + params.model_path, params.weights_path, params.device_id + }.cfgOutputLayers({ "age_conv3", "prob" }) + .cfgBatchSize(batch_size); + + 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"); +} + } // namespace opencv_test #endif // HAVE_INF_ENGINE