mirror of
https://github.com/opencv/opencv.git
synced 2026-07-29 23:33:05 +04:00
Merge branch 4.x
This commit is contained in:
@@ -24,6 +24,12 @@ add_library(ade STATIC ${OPENCV_3RDPARTY_EXCLUDE_FROM_ALL}
|
||||
${ADE_include}
|
||||
${ADE_sources}
|
||||
)
|
||||
|
||||
# https://github.com/opencv/ade/issues/32
|
||||
if(CV_CLANG AND CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13.1)
|
||||
ocv_warnings_disable(CMAKE_CXX_FLAGS -Wdeprecated-copy)
|
||||
endif()
|
||||
|
||||
target_include_directories(ade PUBLIC $<BUILD_INTERFACE:${ADE_root}/include>)
|
||||
set_target_properties(ade PROPERTIES
|
||||
POSITION_INDEPENDENT_CODE True
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
namespace cv { namespace gapi { namespace imgproc { namespace fluid {
|
||||
|
||||
GAPI_EXPORTS GKernelPackage kernels();
|
||||
GAPI_EXPORTS_W GKernelPackage kernels();
|
||||
|
||||
}}}}
|
||||
|
||||
|
||||
@@ -414,8 +414,8 @@ namespace cv {
|
||||
class GAPI_EXPORTS_W_SIMPLE GKernelPackage;
|
||||
|
||||
namespace gapi {
|
||||
GAPI_EXPORTS cv::GKernelPackage combine(const cv::GKernelPackage &lhs,
|
||||
const cv::GKernelPackage &rhs);
|
||||
GAPI_EXPORTS_W cv::GKernelPackage combine(const cv::GKernelPackage &lhs,
|
||||
const cv::GKernelPackage &rhs);
|
||||
|
||||
/// @private
|
||||
class GFunctor
|
||||
@@ -513,7 +513,7 @@ namespace gapi {
|
||||
*
|
||||
* @return a number of kernels in the package
|
||||
*/
|
||||
std::size_t size() const;
|
||||
GAPI_WRAP std::size_t size() const;
|
||||
|
||||
/**
|
||||
* @brief Returns vector of transformations included in the package
|
||||
@@ -717,6 +717,8 @@ namespace gapi {
|
||||
{
|
||||
return combine(a, combine(b, rest...));
|
||||
}
|
||||
// NB(DM): Variadic-arg version in Python may require the same
|
||||
// approach as used in GComputation::compile/apply.
|
||||
|
||||
/** \addtogroup gapi_compile_args
|
||||
* @{
|
||||
|
||||
@@ -26,6 +26,13 @@ public:
|
||||
GAPI_WRAP
|
||||
PyParams(const std::string& tag, const std::string& model_path);
|
||||
|
||||
GAPI_WRAP
|
||||
PyParams& cfgMeanStd(const std::string &layer_name,
|
||||
const cv::Scalar &m,
|
||||
const cv::Scalar &s);
|
||||
GAPI_WRAP
|
||||
PyParams& cfgNormalize(const std::string &layer_name, bool flag);
|
||||
|
||||
GBackend backend() const;
|
||||
std::string tag() const;
|
||||
cv::util::any params() const;
|
||||
|
||||
@@ -242,7 +242,7 @@ public:
|
||||
@param cfg Map of pairs: (config parameter name, config parameter value).
|
||||
@return reference to this parameter structure.
|
||||
*/
|
||||
Params& pluginConfig(const IEConfig& cfg) {
|
||||
Params& pluginConfig(const IEConfig& cfg) {
|
||||
desc.config = cfg;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -70,6 +70,14 @@ struct ParamDesc {
|
||||
std::vector<std::string> names_to_remap; //!< Names of output layers that will be processed in PostProc function.
|
||||
|
||||
bool is_generic;
|
||||
|
||||
// TODO: Needs to modify the rest of ParamDesc accordingly to support
|
||||
// both generic and non-generic options without duplication
|
||||
// (as it was done for the OV IE backend)
|
||||
// These values are pushed into the respective vector<> fields above
|
||||
// when the generic infer parameters are unpacked (see GONNXBackendImpl::unpackKernel)
|
||||
std::unordered_map<std::string, std::pair<cv::Scalar, cv::Scalar> > generic_mstd;
|
||||
std::unordered_map<std::string, bool> generic_norm;
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
@@ -298,7 +306,17 @@ public:
|
||||
@param model_path path to model file (.onnx file).
|
||||
*/
|
||||
Params(const std::string& tag, const std::string& model_path)
|
||||
: desc{model_path, 0u, 0u, {}, {}, {}, {}, {}, {}, {}, {}, {}, true}, m_tag(tag) {}
|
||||
: desc{model_path, 0u, 0u, {}, {}, {}, {}, {}, {}, {}, {}, {}, true, {}, {} }, m_tag(tag) {}
|
||||
|
||||
void cfgMeanStdDev(const std::string &layer,
|
||||
const cv::Scalar &m,
|
||||
const cv::Scalar &s) {
|
||||
desc.generic_mstd[layer] = std::make_pair(m, s);
|
||||
}
|
||||
|
||||
void cfgNormalize(const std::string &layer, bool flag) {
|
||||
desc.generic_norm[layer] = flag;
|
||||
}
|
||||
|
||||
// BEGIN(G-API's network parametrization API)
|
||||
GBackend backend() const { return cv::gapi::onnx::backend(); }
|
||||
|
||||
@@ -31,6 +31,7 @@ namespace cv {
|
||||
using Size = gapi::own::Size;
|
||||
using Point = gapi::own::Point;
|
||||
using Point2f = gapi::own::Point2f;
|
||||
using Point3f = gapi::own::Point3f;
|
||||
using Scalar = gapi::own::Scalar;
|
||||
using Mat = gapi::own::Mat;
|
||||
} // namespace cv
|
||||
|
||||
@@ -43,6 +43,17 @@ public:
|
||||
float y = 0.f;
|
||||
};
|
||||
|
||||
class Point3f
|
||||
{
|
||||
public:
|
||||
Point3f() = default;
|
||||
Point3f(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {}
|
||||
|
||||
float x = 0.f;
|
||||
float y = 0.f;
|
||||
float z = 0.f;
|
||||
};
|
||||
|
||||
class Rect
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -664,7 +664,6 @@ static cv::GRunArgs run_py_kernel(cv::detail::PyObjectHolder kernel,
|
||||
cv::GRunArgs outs;
|
||||
try
|
||||
{
|
||||
int in_idx = 0;
|
||||
// NB: Doesn't increase reference counter (false),
|
||||
// because PyObject already have ownership.
|
||||
// In case exception decrement reference counter.
|
||||
@@ -697,7 +696,6 @@ static cv::GRunArgs run_py_kernel(cv::detail::PyObjectHolder kernel,
|
||||
util::throw_error(std::logic_error("GFrame isn't supported for custom operation"));
|
||||
break;
|
||||
}
|
||||
++in_idx;
|
||||
}
|
||||
|
||||
if (ctx.m_state.has_value())
|
||||
@@ -787,15 +785,14 @@ static void unpackMetasToTuple(const cv::GMetaArgs& meta,
|
||||
}
|
||||
}
|
||||
|
||||
static cv::GArg setup_py(cv::detail::PyObjectHolder setup,
|
||||
const cv::GMetaArgs& meta,
|
||||
const cv::GArgs& gargs)
|
||||
static cv::GArg run_py_setup(cv::detail::PyObjectHolder setup,
|
||||
const cv::GMetaArgs &meta,
|
||||
const cv::GArgs &gargs)
|
||||
{
|
||||
PyGILState_STATE gstate;
|
||||
gstate = PyGILState_Ensure();
|
||||
|
||||
cv::GArg out;
|
||||
|
||||
cv::GArg state;
|
||||
try
|
||||
{
|
||||
// NB: Doesn't increase reference counter (false),
|
||||
@@ -803,23 +800,20 @@ static cv::GArg setup_py(cv::detail::PyObjectHolder setup,
|
||||
// In case exception decrement reference counter.
|
||||
cv::detail::PyObjectHolder args(PyTuple_New(meta.size()), false);
|
||||
unpackMetasToTuple(meta, gargs, args);
|
||||
// NB: Take an onwership because this state is "Python" type so it will be wrapped as-is
|
||||
// into cv::GArg and stored in GPythonBackend. Object without ownership can't
|
||||
// be dealocated outside this function.
|
||||
cv::detail::PyObjectHolder result(PyObject_CallObject(setup.get(), args.get()), true);
|
||||
|
||||
PyObject *py_kernel_state = PyObject_CallObject(setup.get(), args.get());
|
||||
if (PyErr_Occurred())
|
||||
{
|
||||
PyErr_PrintEx(0);
|
||||
PyErr_Clear();
|
||||
throw std::logic_error("Python kernel failed with error!");
|
||||
throw std::logic_error("Python kernel setup failed with error!");
|
||||
}
|
||||
// NB: In fact it's impossible situation, because errors were handled above.
|
||||
GAPI_Assert(result.get() && "Python kernel returned NULL!");
|
||||
GAPI_Assert(py_kernel_state && "Python kernel setup returned NULL!");
|
||||
|
||||
if (!pyopencv_to(result.get(), out, ArgInfo("arg", false)))
|
||||
if (!pyopencv_to(py_kernel_state, state, ArgInfo("arg", false)))
|
||||
{
|
||||
util::throw_error(std::logic_error("Unsupported output meta type"));
|
||||
util::throw_error(std::logic_error("Failed to convert python state"));
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
@@ -828,7 +822,7 @@ static cv::GArg setup_py(cv::detail::PyObjectHolder setup,
|
||||
throw;
|
||||
}
|
||||
PyGILState_Release(gstate);
|
||||
return out;
|
||||
return state;
|
||||
}
|
||||
|
||||
static GMetaArg get_meta_arg(PyObject* obj)
|
||||
@@ -949,7 +943,7 @@ static PyObject* pyopencv_cv_gapi_kernels(PyObject* , PyObject* py_args, PyObjec
|
||||
gapi::python::GPythonFunctor f(
|
||||
id.c_str(), std::bind(run_py_meta, cv::detail::PyObjectHolder{out_meta}, _1, _2),
|
||||
std::bind(run_py_kernel, cv::detail::PyObjectHolder{run}, _1),
|
||||
std::bind(setup_py, cv::detail::PyObjectHolder{setup}, _1, _2));
|
||||
std::bind(run_py_setup, cv::detail::PyObjectHolder{setup}, _1, _2));
|
||||
pkg.include(f);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -14,21 +14,14 @@ try:
|
||||
if sys.version_info[:2] < (3, 0):
|
||||
raise unittest.SkipTest('Python 2.x is not supported')
|
||||
|
||||
CLASSIFICATION_MODEL_PATH = "onnx_models/vision/classification/squeezenet/model/squeezenet1.0-9.onnx"
|
||||
|
||||
testdata_required = bool(os.environ.get('OPENCV_DNN_TEST_REQUIRE_TESTDATA', False))
|
||||
CLASSIFICATION_MODEL_PATH = "vision/classification/squeezenet/model/squeezenet1.0-9.onnx"
|
||||
|
||||
class test_gapi_infer(NewOpenCVTests):
|
||||
def find_dnn_file(self, filename, required=None):
|
||||
if not required:
|
||||
required = testdata_required
|
||||
return self.find_file(filename, [os.environ.get('OPENCV_DNN_TEST_DATA_PATH', os.getcwd()),
|
||||
os.environ['OPENCV_TEST_DATA_PATH']],
|
||||
required=required)
|
||||
def find_dnn_file(self, filename):
|
||||
return self.find_file(filename, [os.environ.get('OPENCV_GAPI_ONNX_MODEL_PATH')], False)
|
||||
|
||||
def test_onnx_classification(self):
|
||||
model_path = self.find_dnn_file(CLASSIFICATION_MODEL_PATH)
|
||||
|
||||
if model_path is None:
|
||||
raise unittest.SkipTest("Missing DNN test file")
|
||||
|
||||
@@ -45,6 +38,7 @@ try:
|
||||
comp = cv.GComputation(cv.GIn(g_in), cv.GOut(g_out))
|
||||
|
||||
net = cv.gapi.onnx.params("squeeze-net", model_path)
|
||||
net.cfgNormalize("data_0", False)
|
||||
try:
|
||||
out_gapi = comp.apply(cv.gin(in_mat), cv.gapi.compile_args(cv.gapi.networks(net)))
|
||||
except cv.error as err:
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import numpy as np
|
||||
import cv2 as cv
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
from tests_common import NewOpenCVTests
|
||||
|
||||
|
||||
try:
|
||||
|
||||
if sys.version_info[:2] < (3, 0):
|
||||
raise unittest.SkipTest('Python 2.x is not supported')
|
||||
|
||||
class gapi_kernels_test(NewOpenCVTests):
|
||||
|
||||
def test_fluid_core_package(self):
|
||||
fluid_core = cv.gapi.core.fluid.kernels()
|
||||
self.assertLess(0, fluid_core.size())
|
||||
|
||||
def test_fluid_imgproc_package(self):
|
||||
fluid_imgproc = cv.gapi.imgproc.fluid.kernels()
|
||||
self.assertLess(0, fluid_imgproc.size())
|
||||
|
||||
def test_combine(self):
|
||||
fluid_core = cv.gapi.core.fluid.kernels()
|
||||
fluid_imgproc = cv.gapi.imgproc.fluid.kernels()
|
||||
fluid = cv.gapi.combine(fluid_core, fluid_imgproc)
|
||||
self.assertEqual(fluid_core.size() + fluid_imgproc.size(), fluid.size())
|
||||
|
||||
except unittest.SkipTest as e:
|
||||
|
||||
message = str(e)
|
||||
|
||||
class TestSkip(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.skipTest('Skip tests: ' + message)
|
||||
|
||||
def test_skip():
|
||||
pass
|
||||
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
NewOpenCVTests.bootstrap()
|
||||
@@ -24,7 +24,7 @@ try:
|
||||
in_types=[cv.GOpaque.Int],
|
||||
out_types=[cv.GOpaque.Int])
|
||||
class GStatefulCounter:
|
||||
"""Accumulate state counter on every call"""
|
||||
"""Accumulates state counter on every call"""
|
||||
|
||||
@staticmethod
|
||||
def outMeta(desc):
|
||||
@@ -45,6 +45,22 @@ try:
|
||||
return state.counter
|
||||
|
||||
|
||||
class SumState:
|
||||
def __init__(self):
|
||||
self.sum = 0
|
||||
|
||||
|
||||
@cv.gapi.op('stateful_sum',
|
||||
in_types=[cv.GOpaque.Int, cv.GOpaque.Int],
|
||||
out_types=[cv.GOpaque.Int])
|
||||
class GStatefulSum:
|
||||
"""Accumulates sum on every call"""
|
||||
|
||||
@staticmethod
|
||||
def outMeta(lhs_desc, rhs_desc):
|
||||
return cv.empty_gopaque_desc()
|
||||
|
||||
|
||||
class gapi_sample_pipelines(NewOpenCVTests):
|
||||
def test_stateful_kernel_single_instance(self):
|
||||
g_in = cv.GOpaque.Int()
|
||||
@@ -124,6 +140,64 @@ try:
|
||||
cc.stop()
|
||||
|
||||
|
||||
def test_stateful_multiple_inputs(self):
|
||||
@cv.gapi.kernel(GStatefulSum)
|
||||
class GStatefulSumImpl:
|
||||
"""Implementation for GStatefulCounter operation."""
|
||||
|
||||
@staticmethod
|
||||
def setup(lhs_desc, rhs_desc):
|
||||
return SumState()
|
||||
|
||||
@staticmethod
|
||||
def run(lhs, rhs, state):
|
||||
state.sum+= lhs + rhs
|
||||
return state.sum
|
||||
|
||||
|
||||
g_in1 = cv.GOpaque.Int()
|
||||
g_in2 = cv.GOpaque.Int()
|
||||
g_out = GStatefulSum.on(g_in1, g_in2)
|
||||
comp = cv.GComputation(cv.GIn(g_in1, g_in2), cv.GOut(g_out))
|
||||
pkg = cv.gapi.kernels(GStatefulSumImpl)
|
||||
|
||||
lhs_list = [1, 10, 15]
|
||||
rhs_list = [2, 14, 32]
|
||||
|
||||
ref_out = 0
|
||||
for lhs, rhs in zip(lhs_list, rhs_list):
|
||||
ref_out += lhs + rhs
|
||||
gapi_out = comp.apply(cv.gin(lhs, rhs), cv.gapi.compile_args(pkg))
|
||||
self.assertEqual(ref_out, gapi_out)
|
||||
|
||||
|
||||
def test_stateful_multiple_inputs_throw(self):
|
||||
@cv.gapi.kernel(GStatefulSum)
|
||||
class GStatefulSumImplIncorrect:
|
||||
"""Incorrect implementation for GStatefulCounter operation."""
|
||||
|
||||
# NB: setup methods is intentionally
|
||||
# incorrect - accepts one meta arg instead of two
|
||||
@staticmethod
|
||||
def setup(desc):
|
||||
return SumState()
|
||||
|
||||
@staticmethod
|
||||
def run(lhs, rhs, state):
|
||||
state.sum+= lhs + rhs
|
||||
return state.sum
|
||||
|
||||
|
||||
g_in1 = cv.GOpaque.Int()
|
||||
g_in2 = cv.GOpaque.Int()
|
||||
g_out = GStatefulSum.on(g_in1, g_in2)
|
||||
comp = cv.GComputation(cv.GIn(g_in1, g_in2), cv.GOut(g_out))
|
||||
pkg = cv.gapi.kernels(GStatefulSumImplIncorrect)
|
||||
|
||||
with self.assertRaises(Exception): comp.apply(cv.gin(42, 42),
|
||||
args=cv.gapi.compile_args(pkg))
|
||||
|
||||
|
||||
except unittest.SkipTest as e:
|
||||
|
||||
message = str(e)
|
||||
|
||||
@@ -17,7 +17,7 @@ try:
|
||||
|
||||
@cv.gapi.op('custom.delay', in_types=[cv.GMat], out_types=[cv.GMat])
|
||||
class GDelay:
|
||||
"""Delay for 10 ms."""
|
||||
"""Delay for 50 ms."""
|
||||
|
||||
@staticmethod
|
||||
def outMeta(desc):
|
||||
@@ -30,7 +30,7 @@ try:
|
||||
|
||||
@staticmethod
|
||||
def run(img):
|
||||
time.sleep(0.01)
|
||||
time.sleep(0.05)
|
||||
return img
|
||||
|
||||
|
||||
@@ -289,8 +289,7 @@ try:
|
||||
ccomp.start()
|
||||
|
||||
# Assert
|
||||
max_num_frames = 10
|
||||
proc_num_frames = 0
|
||||
max_num_frames = 50
|
||||
|
||||
out_counter = 0
|
||||
desync_out_counter = 0
|
||||
@@ -307,12 +306,11 @@ try:
|
||||
else:
|
||||
none_counter += 1
|
||||
|
||||
proc_num_frames += 1
|
||||
if proc_num_frames == max_num_frames:
|
||||
if out_counter == max_num_frames:
|
||||
ccomp.stop()
|
||||
break
|
||||
|
||||
self.assertLess(0, proc_num_frames)
|
||||
self.assertLess(0, out_counter)
|
||||
self.assertLess(desync_out_counter, out_counter)
|
||||
self.assertLess(0, none_counter)
|
||||
|
||||
|
||||
@@ -35,6 +35,22 @@ static AppMode strToAppMode(const std::string& mode_str) {
|
||||
}
|
||||
}
|
||||
|
||||
enum class WaitMode {
|
||||
BUSY,
|
||||
SLEEP
|
||||
};
|
||||
|
||||
static WaitMode strToWaitMode(const std::string& mode_str) {
|
||||
if (mode_str == "sleep") {
|
||||
return WaitMode::SLEEP;
|
||||
} else if (mode_str == "busy") {
|
||||
return WaitMode::BUSY;
|
||||
} else {
|
||||
throw std::logic_error("Unsupported wait mode: " + mode_str +
|
||||
"\nPlease chose between: busy (default) and sleep");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T read(const cv::FileNode& node) {
|
||||
return static_cast<T>(node);
|
||||
@@ -401,7 +417,12 @@ int main(int argc, char* argv[]) {
|
||||
if (app_mode == AppMode::BENCHMARK) {
|
||||
latency = 0.0;
|
||||
}
|
||||
auto src = std::make_shared<DummySource>(latency, output, drop_frames);
|
||||
|
||||
const auto wait_mode =
|
||||
strToWaitMode(readOpt<std::string>(src_fn["wait_mode"]).value_or("busy"));
|
||||
auto wait_strategy = (wait_mode == WaitMode::SLEEP) ? utils::sleep : utils::busyWait;
|
||||
auto src = std::make_shared<DummySource>(
|
||||
utils::double_ms_t{latency}, output, drop_frames, std::move(wait_strategy));
|
||||
builder.setSource(src_name, src);
|
||||
}
|
||||
|
||||
@@ -446,7 +467,7 @@ int main(int argc, char* argv[]) {
|
||||
// NB: Pipeline mode from config takes priority over cmd.
|
||||
auto pl_mode = cfg_pl_mode.has_value()
|
||||
? strToPLMode(cfg_pl_mode.value()) : cmd_pl_mode;
|
||||
// NB: Using drop_frames with streaming pipelines will follow to
|
||||
// NB: Using drop_frames with streaming pipelines will lead to
|
||||
// incorrect performance results.
|
||||
if (drop_frames && pl_mode == PLMode::STREAMING) {
|
||||
throw std::logic_error(
|
||||
|
||||
@@ -12,26 +12,36 @@
|
||||
|
||||
class DummySource final: public cv::gapi::wip::IStreamSource {
|
||||
public:
|
||||
using WaitStrategy = std::function<void(std::chrono::microseconds)>;
|
||||
using Ptr = std::shared_ptr<DummySource>;
|
||||
DummySource(const double latency,
|
||||
using ts_t = std::chrono::microseconds;
|
||||
|
||||
template <typename DurationT>
|
||||
DummySource(const DurationT latency,
|
||||
const OutputDescr& output,
|
||||
const bool drop_frames);
|
||||
const bool drop_frames,
|
||||
WaitStrategy&& wait);
|
||||
|
||||
bool pull(cv::gapi::wip::Data& data) override;
|
||||
cv::GMetaArg descr_of() const override;
|
||||
double latency() const { return m_latency; };
|
||||
|
||||
private:
|
||||
double m_latency;
|
||||
cv::Mat m_mat;
|
||||
bool m_drop_frames;
|
||||
double m_next_tick_ts = -1;
|
||||
int64_t m_curr_seq_id = 0;
|
||||
int64_t m_latency;
|
||||
cv::Mat m_mat;
|
||||
bool m_drop_frames;
|
||||
int64_t m_next_tick_ts = -1;
|
||||
int64_t m_curr_seq_id = 0;
|
||||
WaitStrategy m_wait;
|
||||
};
|
||||
|
||||
DummySource::DummySource(const double latency,
|
||||
template <typename DurationT>
|
||||
DummySource::DummySource(const DurationT latency,
|
||||
const OutputDescr& output,
|
||||
const bool drop_frames)
|
||||
: m_latency(latency), m_drop_frames(drop_frames) {
|
||||
const bool drop_frames,
|
||||
WaitStrategy&& wait)
|
||||
: m_latency(std::chrono::duration_cast<ts_t>(latency).count()),
|
||||
m_drop_frames(drop_frames),
|
||||
m_wait(std::move(wait)) {
|
||||
utils::createNDMat(m_mat, output.dims, output.precision);
|
||||
utils::generateRandom(m_mat);
|
||||
}
|
||||
@@ -42,10 +52,10 @@ bool DummySource::pull(cv::gapi::wip::Data& data) {
|
||||
|
||||
// NB: Wait m_latency before return the first frame.
|
||||
if (m_next_tick_ts == -1) {
|
||||
m_next_tick_ts = utils::timestamp<milliseconds>() + m_latency;
|
||||
m_next_tick_ts = utils::timestamp<ts_t>() + m_latency;
|
||||
}
|
||||
|
||||
int64_t curr_ts = utils::timestamp<milliseconds>();
|
||||
int64_t curr_ts = utils::timestamp<ts_t>();
|
||||
if (curr_ts < m_next_tick_ts) {
|
||||
/*
|
||||
* curr_ts
|
||||
@@ -57,8 +67,8 @@ bool DummySource::pull(cv::gapi::wip::Data& data) {
|
||||
*
|
||||
* NB: New frame will be produced at the m_next_tick_ts point.
|
||||
*/
|
||||
utils::sleep(m_next_tick_ts - curr_ts);
|
||||
} else {
|
||||
m_wait(ts_t{m_next_tick_ts - curr_ts});
|
||||
} else if (m_latency != 0) {
|
||||
/*
|
||||
* curr_ts
|
||||
* +1 +2 |
|
||||
@@ -66,29 +76,28 @@ bool DummySource::pull(cv::gapi::wip::Data& data) {
|
||||
* ^ ^
|
||||
* m_next_tick_ts ------------->
|
||||
*
|
||||
*
|
||||
* NB: Shift m_next_tick_ts to the nearest tick before curr_ts and
|
||||
* update current seq_id correspondingly.
|
||||
*
|
||||
* if drop_frames is enabled, wait for the next tick, otherwise
|
||||
* return last written frame (+2 at the picture above) immediately.
|
||||
*/
|
||||
|
||||
// NB: Count how many frames have been produced since last pull (m_next_tick_ts).
|
||||
int64_t num_frames =
|
||||
static_cast<int64_t>((curr_ts - m_next_tick_ts) / m_latency);
|
||||
m_curr_seq_id += num_frames;
|
||||
// NB: Shift m_next_tick_ts to the nearest tick before curr_ts.
|
||||
m_next_tick_ts += num_frames * m_latency;
|
||||
// NB: if drop_frames is enabled, update current seq_id and wait for the next tick, otherwise
|
||||
// return last written frame (+2 at the picture above) immediately.
|
||||
if (m_drop_frames) {
|
||||
// NB: Shift tick to the next frame.
|
||||
m_next_tick_ts += m_latency;
|
||||
++m_curr_seq_id;
|
||||
utils::sleep(m_next_tick_ts - curr_ts);
|
||||
// NB: Wait for the next frame.
|
||||
m_wait(ts_t{m_next_tick_ts - curr_ts});
|
||||
// NB: Drop already produced frames + update seq_id for the current.
|
||||
m_curr_seq_id += num_frames + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Just increase reference counter not to release mat memory
|
||||
// after assigning it to the data.
|
||||
cv::Mat mat = m_mat;
|
||||
|
||||
data.meta[meta_tag::timestamp] = utils::timestamp<milliseconds>();
|
||||
data.meta[meta_tag::timestamp] = utils::timestamp<ts_t>();
|
||||
data.meta[meta_tag::seq_id] = m_curr_seq_id++;
|
||||
data = mat;
|
||||
m_next_tick_ts += m_latency;
|
||||
|
||||
@@ -6,34 +6,39 @@
|
||||
struct PerfReport {
|
||||
std::string name;
|
||||
double avg_latency = 0.0;
|
||||
int64_t min_latency = 0;
|
||||
int64_t max_latency = 0;
|
||||
int64_t first_latency = 0;
|
||||
double min_latency = 0.0;
|
||||
double max_latency = 0.0;
|
||||
double first_latency = 0.0;
|
||||
double throughput = 0.0;
|
||||
int64_t elapsed = 0;
|
||||
int64_t warmup_time = 0;
|
||||
double elapsed = 0.0;
|
||||
double warmup_time = 0.0;
|
||||
int64_t num_late_frames = 0;
|
||||
std::vector<int64_t> latencies;
|
||||
std::vector<double> latencies;
|
||||
std::vector<int64_t> seq_ids;
|
||||
|
||||
std::string toStr(bool expanded = false) const;
|
||||
};
|
||||
|
||||
std::string PerfReport::toStr(bool expand) const {
|
||||
const auto to_double_str = [](double val) {
|
||||
std::stringstream ss;
|
||||
ss << std::fixed << std::setprecision(3) << val;
|
||||
return ss.str();
|
||||
};
|
||||
|
||||
std::stringstream ss;
|
||||
ss << name << ": \n"
|
||||
<< " Warm up time: " << warmup_time << " ms\n"
|
||||
<< " Execution time: " << elapsed << " ms\n"
|
||||
<< " Frames: " << num_late_frames << "/" << latencies.size() << " (late/all)\n"
|
||||
<< " Latency:\n"
|
||||
<< " first: " << first_latency << " ms\n"
|
||||
<< " min: " << min_latency << " ms\n"
|
||||
<< " max: " << max_latency << " ms\n"
|
||||
<< " avg: " << std::fixed << std::setprecision(3) << avg_latency << " ms\n"
|
||||
<< " Throughput: " << std::fixed << std::setprecision(3) << throughput << " FPS";
|
||||
ss << name << ": warm-up: " << to_double_str(warmup_time)
|
||||
<< " ms, execution time: " << to_double_str(elapsed)
|
||||
<< " ms, throughput: " << to_double_str(throughput)
|
||||
<< " FPS, latency: first: " << to_double_str(first_latency)
|
||||
<< " ms, min: " << to_double_str(min_latency)
|
||||
<< " ms, avg: " << to_double_str(avg_latency)
|
||||
<< " ms, max: " << to_double_str(max_latency)
|
||||
<< " ms, frames: " << num_late_frames << "/" << seq_ids.back()+1 << " (dropped/all)";
|
||||
if (expand) {
|
||||
for (size_t i = 0; i < latencies.size(); ++i) {
|
||||
ss << "\nFrame:" << i << "\nLatency: "
|
||||
<< latencies[i] << " ms";
|
||||
<< to_double_str(latencies[i]) << " ms";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,10 +75,12 @@ public:
|
||||
virtual ~Pipeline() = default;
|
||||
|
||||
protected:
|
||||
virtual void _compile() = 0;
|
||||
virtual int64_t run_iter() = 0;
|
||||
virtual void init() {};
|
||||
virtual void deinit() {};
|
||||
virtual void _compile() = 0;
|
||||
virtual void run_iter() = 0;
|
||||
virtual void init() {};
|
||||
virtual void deinit() {};
|
||||
|
||||
void prepareOutputs();
|
||||
|
||||
std::string m_name;
|
||||
cv::GComputation m_comp;
|
||||
@@ -82,6 +89,11 @@ protected:
|
||||
cv::GCompileArgs m_args;
|
||||
size_t m_num_outputs;
|
||||
PerfReport m_perf;
|
||||
|
||||
cv::GRunArgsP m_pipeline_outputs;
|
||||
std::vector<cv::Mat> m_out_mats;
|
||||
int64_t m_start_ts;
|
||||
int64_t m_seq_id;
|
||||
};
|
||||
|
||||
Pipeline::Pipeline(std::string&& name,
|
||||
@@ -101,42 +113,82 @@ Pipeline::Pipeline(std::string&& name,
|
||||
|
||||
void Pipeline::compile() {
|
||||
m_perf.warmup_time =
|
||||
utils::measure<std::chrono::milliseconds>([this]() {
|
||||
utils::measure<utils::double_ms_t>([this]() {
|
||||
_compile();
|
||||
});
|
||||
}
|
||||
|
||||
void Pipeline::prepareOutputs() {
|
||||
// NB: N-2 buffers + timestamp + seq_id.
|
||||
m_out_mats.resize(m_num_outputs - 2);
|
||||
for (auto& m : m_out_mats) {
|
||||
m_pipeline_outputs += cv::gout(m);
|
||||
}
|
||||
m_pipeline_outputs += cv::gout(m_start_ts);
|
||||
m_pipeline_outputs += cv::gout(m_seq_id);
|
||||
}
|
||||
|
||||
void Pipeline::run() {
|
||||
using namespace std::chrono;
|
||||
|
||||
// NB: Allocate outputs for execution
|
||||
prepareOutputs();
|
||||
|
||||
// NB: Warm-up iteration invalidates source state
|
||||
// so need to copy it
|
||||
auto orig_src = m_src;
|
||||
auto copy_src = std::make_shared<DummySource>(*m_src);
|
||||
|
||||
// NB: Use copy for warm-up iteration
|
||||
m_src = copy_src;
|
||||
|
||||
// NB: Warm-up iteration
|
||||
init();
|
||||
run_iter();
|
||||
deinit();
|
||||
|
||||
// NB: Calculate first latency
|
||||
m_perf.first_latency = utils::double_ms_t{
|
||||
microseconds{utils::timestamp<microseconds>() - m_start_ts}}.count();
|
||||
|
||||
// NB: Now use original source
|
||||
m_src = orig_src;
|
||||
|
||||
// NB: Start measuring execution
|
||||
init();
|
||||
auto start = high_resolution_clock::now();
|
||||
m_stop_criterion->start();
|
||||
|
||||
while (true) {
|
||||
m_perf.latencies.push_back(run_iter());
|
||||
m_perf.elapsed = duration_cast<milliseconds>(high_resolution_clock::now() - start).count();
|
||||
run_iter();
|
||||
const auto latency = utils::double_ms_t{
|
||||
microseconds{utils::timestamp<microseconds>() - m_start_ts}}.count();
|
||||
|
||||
m_perf.latencies.push_back(latency);
|
||||
m_perf.seq_ids.push_back(m_seq_id);
|
||||
|
||||
m_stop_criterion->iter();
|
||||
|
||||
if (m_stop_criterion->done()) {
|
||||
m_perf.elapsed = duration_cast<utils::double_ms_t>(
|
||||
high_resolution_clock::now() - start).count();
|
||||
deinit();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_perf.avg_latency = utils::avg(m_perf.latencies);
|
||||
m_perf.min_latency = utils::min(m_perf.latencies);
|
||||
m_perf.max_latency = utils::max(m_perf.latencies);
|
||||
m_perf.first_latency = m_perf.latencies[0];
|
||||
m_perf.avg_latency = utils::avg(m_perf.latencies);
|
||||
m_perf.min_latency = utils::min(m_perf.latencies);
|
||||
m_perf.max_latency = utils::max(m_perf.latencies);
|
||||
|
||||
// NB: Count how many executions don't fit into camera latency interval.
|
||||
m_perf.num_late_frames =
|
||||
std::count_if(m_perf.latencies.begin(), m_perf.latencies.end(),
|
||||
[this](int64_t latency) {
|
||||
return static_cast<double>(latency) > m_src->latency();
|
||||
});
|
||||
// NB: Count the number of dropped frames
|
||||
int64_t prev_seq_id = m_perf.seq_ids[0];
|
||||
for (size_t i = 1; i < m_perf.seq_ids.size(); ++i) {
|
||||
m_perf.num_late_frames += m_perf.seq_ids[i] - prev_seq_id - 1;
|
||||
prev_seq_id = m_perf.seq_ids[i];
|
||||
}
|
||||
|
||||
m_perf.throughput =
|
||||
(m_perf.latencies.size() / static_cast<double>(m_perf.elapsed)) * 1000;
|
||||
m_perf.throughput = (m_perf.latencies.size() / m_perf.elapsed) * 1000;
|
||||
}
|
||||
|
||||
const PerfReport& Pipeline::report() const {
|
||||
@@ -155,13 +207,6 @@ private:
|
||||
}
|
||||
|
||||
virtual void init() override {
|
||||
using namespace std::chrono;
|
||||
// NB: N-1 buffers + timestamp.
|
||||
m_out_mats.resize(m_num_outputs - 1);
|
||||
for (auto& m : m_out_mats) {
|
||||
m_pipeline_outputs += cv::gout(m);
|
||||
}
|
||||
m_pipeline_outputs += cv::gout(m_start_ts);
|
||||
m_compiled.setSource(m_src);
|
||||
m_compiled.start();
|
||||
}
|
||||
@@ -170,15 +215,11 @@ private:
|
||||
m_compiled.stop();
|
||||
}
|
||||
|
||||
virtual int64_t run_iter() override {
|
||||
virtual void run_iter() override {
|
||||
m_compiled.pull(cv::GRunArgsP{m_pipeline_outputs});
|
||||
return utils::timestamp<std::chrono::milliseconds>() - m_start_ts;
|
||||
}
|
||||
|
||||
cv::GStreamingCompiled m_compiled;
|
||||
cv::GRunArgsP m_pipeline_outputs;
|
||||
std::vector<cv::Mat> m_out_mats;
|
||||
int64_t m_start_ts;
|
||||
};
|
||||
|
||||
class RegularPipeline : public Pipeline {
|
||||
@@ -192,26 +233,13 @@ private:
|
||||
cv::GCompileArgs(m_args));
|
||||
}
|
||||
|
||||
virtual void init() override {
|
||||
m_out_mats.resize(m_num_outputs);
|
||||
for (auto& m : m_out_mats) {
|
||||
m_pipeline_outputs += cv::gout(m);
|
||||
}
|
||||
virtual void run_iter() override {
|
||||
cv::gapi::wip::Data data;
|
||||
m_src->pull(data);
|
||||
m_compiled({data}, cv::GRunArgsP{m_pipeline_outputs});
|
||||
}
|
||||
|
||||
virtual int64_t run_iter() override {
|
||||
using namespace std::chrono;
|
||||
cv::gapi::wip::Data d;
|
||||
m_src->pull(d);
|
||||
auto in_mat = cv::util::get<cv::Mat>(d);
|
||||
return utils::measure<milliseconds>([&]{
|
||||
m_compiled(cv::gin(in_mat), cv::GRunArgsP{m_pipeline_outputs});
|
||||
});
|
||||
}
|
||||
|
||||
cv::GCompiled m_compiled;
|
||||
cv::GRunArgsP m_pipeline_outputs;
|
||||
std::vector<cv::Mat> m_out_mats;
|
||||
cv::GCompiled m_compiled;
|
||||
};
|
||||
|
||||
enum class PLMode {
|
||||
|
||||
@@ -163,13 +163,10 @@ struct DummyCall {
|
||||
cv::Mat& out_mat,
|
||||
DummyState& state) {
|
||||
using namespace std::chrono;
|
||||
double total = 0;
|
||||
auto start = high_resolution_clock::now();
|
||||
auto start_ts = utils::timestamp<utils::double_ms_t>();
|
||||
state.mat.copyTo(out_mat);
|
||||
while (total < time) {
|
||||
total = duration_cast<duration<double, std::milli>>(
|
||||
high_resolution_clock::now() - start).count();
|
||||
}
|
||||
auto elapsed = utils::timestamp<utils::double_ms_t>() - start_ts;
|
||||
utils::busyWait(duration_cast<microseconds>(utils::double_ms_t{time-elapsed}));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -656,16 +653,16 @@ Pipeline::Ptr PipelineBuilder::construct() {
|
||||
}
|
||||
|
||||
GAPI_Assert(m_state->stop_criterion);
|
||||
if (m_state->mode == PLMode::STREAMING) {
|
||||
GAPI_Assert(graph_inputs.size() == 1);
|
||||
GAPI_Assert(cv::util::holds_alternative<cv::GMat>(graph_inputs[0]));
|
||||
// FIXME: Handle GFrame when NV12 comes.
|
||||
const auto& graph_input = cv::util::get<cv::GMat>(graph_inputs[0]);
|
||||
// NB: In case streaming mode need to expose timestamp in order to
|
||||
// calculate performance metrics.
|
||||
graph_outputs.emplace_back(
|
||||
cv::gapi::streaming::timestamp(graph_input).strip());
|
||||
GAPI_Assert(graph_inputs.size() == 1);
|
||||
GAPI_Assert(cv::util::holds_alternative<cv::GMat>(graph_inputs[0]));
|
||||
// FIXME: Handle GFrame when NV12 comes.
|
||||
const auto& graph_input = cv::util::get<cv::GMat>(graph_inputs[0]);
|
||||
graph_outputs.emplace_back(
|
||||
cv::gapi::streaming::timestamp(graph_input).strip());
|
||||
graph_outputs.emplace_back(
|
||||
cv::gapi::streaming::seq_id(graph_input).strip());
|
||||
|
||||
if (m_state->mode == PLMode::STREAMING) {
|
||||
return std::make_shared<StreamingPipeline>(std::move(m_state->name),
|
||||
cv::GComputation(
|
||||
cv::GProtoInputArgs{graph_inputs},
|
||||
|
||||
@@ -17,6 +17,8 @@ struct OutputDescr {
|
||||
|
||||
namespace utils {
|
||||
|
||||
using double_ms_t = std::chrono::duration<double, std::milli>;
|
||||
|
||||
inline void createNDMat(cv::Mat& mat, const std::vector<int>& dims, int depth) {
|
||||
GAPI_Assert(!dims.empty());
|
||||
mat.create(dims, depth);
|
||||
@@ -50,10 +52,8 @@ inline void generateRandom(cv::Mat& out) {
|
||||
}
|
||||
}
|
||||
|
||||
inline void sleep(double ms) {
|
||||
inline void sleep(std::chrono::microseconds delay) {
|
||||
#if defined(_WIN32)
|
||||
// NB: It takes portions of 100 nanoseconds.
|
||||
int64_t ns_units = static_cast<int64_t>(ms * 1e4);
|
||||
// FIXME: Wrap it to RAII and instance only once.
|
||||
HANDLE timer = CreateWaitableTimer(NULL, true, NULL);
|
||||
if (!timer) {
|
||||
@@ -61,7 +61,12 @@ inline void sleep(double ms) {
|
||||
}
|
||||
|
||||
LARGE_INTEGER li;
|
||||
li.QuadPart = -ns_units;
|
||||
using ns_t = std::chrono::nanoseconds;
|
||||
using ns_100_t = std::chrono::duration<ns_t::rep,
|
||||
std::ratio_multiply<std::ratio<100>, ns_t::period>>;
|
||||
// NB: QuadPart takes portions of 100 nanoseconds.
|
||||
li.QuadPart = -std::chrono::duration_cast<ns_100_t>(delay).count();
|
||||
|
||||
if(!SetWaitableTimer(timer, &li, 0, NULL, NULL, false)){
|
||||
CloseHandle(timer);
|
||||
throw std::logic_error("Failed to set timer");
|
||||
@@ -72,8 +77,7 @@ inline void sleep(double ms) {
|
||||
}
|
||||
CloseHandle(timer);
|
||||
#else
|
||||
using namespace std::chrono;
|
||||
std::this_thread::sleep_for(duration<double, std::milli>(ms));
|
||||
std::this_thread::sleep_for(delay);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -93,6 +97,16 @@ typename duration_t::rep timestamp() {
|
||||
return duration_cast<duration_t>(now.time_since_epoch()).count();
|
||||
}
|
||||
|
||||
inline void busyWait(std::chrono::microseconds delay) {
|
||||
auto start_ts = timestamp<std::chrono::microseconds>();
|
||||
auto end_ts = start_ts;
|
||||
auto time_to_wait = delay.count();
|
||||
|
||||
while (end_ts - start_ts < time_to_wait) {
|
||||
end_ts = timestamp<std::chrono::microseconds>();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename K, typename V>
|
||||
void mergeMapWith(std::map<K, V>& target, const std::map<K, V>& second) {
|
||||
for (auto&& item : second) {
|
||||
|
||||
@@ -456,6 +456,7 @@ public:
|
||||
cv::gimpl::GIslandExecutable::IOutput & output,
|
||||
const cv::GArgs & args,
|
||||
const std::vector<cv::gimpl::RcDesc> & outs,
|
||||
cv::GRunArg::Meta && meta,
|
||||
std::vector<cv::gimpl::GIslandExecutable::InObj> && input_objs,
|
||||
std::vector<cv::gimpl::GIslandExecutable::OutObj> && output_objs);
|
||||
|
||||
@@ -477,9 +478,8 @@ public:
|
||||
const cv::Mat& inMat (std::size_t input) const;
|
||||
const cv::MediaFrame& inFrame(std::size_t input) const;
|
||||
|
||||
const cv::GRunArg& input (std::size_t idx) const;
|
||||
cv::GRunArgP output (std::size_t idx);
|
||||
cv::Mat& outMatR(std::size_t idx);
|
||||
cv::GRunArgP output (std::size_t idx);
|
||||
cv::Mat& outMatR(std::size_t idx);
|
||||
|
||||
const IEUnit &uu;
|
||||
cv::gimpl::GIslandExecutable::IOutput &out;
|
||||
@@ -491,6 +491,8 @@ public:
|
||||
// To store exception appeared in callback.
|
||||
std::exception_ptr eptr;
|
||||
|
||||
const cv::GRunArg::Meta& getMeta() { return m_meta; };
|
||||
|
||||
using req_key_t = void*;
|
||||
cv::MediaFrame* prepareKeepAliveFrameSlot(req_key_t key);
|
||||
size_t releaseKeepAliveFrame(req_key_t key);
|
||||
@@ -499,6 +501,9 @@ private:
|
||||
|
||||
cv::GArg packArg(const cv::GArg &arg);
|
||||
|
||||
// To propagate accumulated meta from all inputs to output.
|
||||
cv::GRunArg::Meta m_meta;
|
||||
|
||||
// To store input/output data from frames
|
||||
std::vector<cv::gimpl::GIslandExecutable::InObj> m_input_objs;
|
||||
std::vector<cv::gimpl::GIslandExecutable::OutObj> m_output_objs;
|
||||
@@ -525,9 +530,11 @@ IECallContext::IECallContext(const IEUnit &
|
||||
cv::gimpl::GIslandExecutable::IOutput & output,
|
||||
const cv::GArgs & args,
|
||||
const std::vector<cv::gimpl::RcDesc> & outs,
|
||||
cv::GRunArg::Meta && meta,
|
||||
std::vector<cv::gimpl::GIslandExecutable::InObj> && input_objs,
|
||||
std::vector<cv::gimpl::GIslandExecutable::OutObj> && output_objs)
|
||||
: uu(unit), out(output), m_input_objs(std::move(input_objs)), m_output_objs(std::move(output_objs))
|
||||
: uu(unit), out(output), m_meta(std::move(meta)),
|
||||
m_input_objs(std::move(input_objs)), m_output_objs(std::move(output_objs))
|
||||
{
|
||||
for (auto& it : m_input_objs) cv::gimpl::magazine::bindInArg (m_res, it.first, it.second);
|
||||
for (auto& it : m_output_objs) cv::gimpl::magazine::bindOutArg(m_res, it.first, it.second);
|
||||
@@ -575,10 +582,6 @@ cv::GRunArgP IECallContext::output(std::size_t idx) {
|
||||
return m_output_objs[idx].second;
|
||||
};
|
||||
|
||||
const cv::GRunArg& IECallContext::input(std::size_t idx) const {
|
||||
return m_input_objs[idx].second;
|
||||
}
|
||||
|
||||
cv::detail::VectorRef& IECallContext::outVecRef(std::size_t idx) {
|
||||
return cv::util::get<cv::detail::VectorRef>(m_results.at(idx));
|
||||
}
|
||||
@@ -1062,6 +1065,12 @@ void cv::gimpl::ie::GIEExecutable::run(cv::gimpl::GIslandExecutable::IInput &in
|
||||
|
||||
GAPI_Assert(cv::util::holds_alternative<cv::GRunArgs>(in_msg));
|
||||
const auto in_vector = cv::util::get<cv::GRunArgs>(in_msg);
|
||||
// NB: Collect meta from all inputs.
|
||||
cv::GRunArg::Meta stub_meta;
|
||||
for (auto &&in_arg : in_vector)
|
||||
{
|
||||
stub_meta.insert(in_arg.meta.begin(), in_arg.meta.end());
|
||||
}
|
||||
|
||||
// (1) Collect island inputs/outputs
|
||||
input_objs.reserve(in_desc.size());
|
||||
@@ -1084,7 +1093,7 @@ void cv::gimpl::ie::GIEExecutable::run(cv::gimpl::GIslandExecutable::IInput &in
|
||||
const auto &op = m_gm.metadata(this_nh).get<Op>();
|
||||
// (2) Create kernel context
|
||||
auto ctx = std::make_shared<IECallContext>(uu, out, op.args, op.outs,
|
||||
std::move(input_objs), std::move(output_objs));
|
||||
std::move(stub_meta), std::move(input_objs), std::move(output_objs));
|
||||
|
||||
const auto &kk = giem.metadata(this_nh).get<IECallable>();
|
||||
|
||||
@@ -1096,6 +1105,7 @@ void cv::gimpl::ie::GIEExecutable::run(cv::gimpl::GIslandExecutable::IInput &in
|
||||
for (auto i : ade::util::iota(ctx->uu.params.num_out))
|
||||
{
|
||||
auto output = ctx->output(i);
|
||||
ctx->out.meta(output, ctx->getMeta());
|
||||
ctx->out.post(std::move(output), eptr);
|
||||
}
|
||||
return;
|
||||
@@ -1247,7 +1257,7 @@ static void PostOutputs(InferenceEngine::InferRequest &request,
|
||||
IE::Blob::Ptr this_blob = request.GetBlob(ctx->uu.params.output_names[i]);
|
||||
copyFromIE(this_blob, out_mat);
|
||||
auto output = ctx->output(i);
|
||||
ctx->out.meta(output, ctx->input(0).meta);
|
||||
ctx->out.meta(output, ctx->getMeta());
|
||||
ctx->out.post(std::move(output), ctx->eptr);
|
||||
}
|
||||
|
||||
@@ -1314,7 +1324,7 @@ void PostOutputsList::operator()(InferenceEngine::InferRequest &req,
|
||||
if (finished == size) {
|
||||
for (auto i : ade::util::iota(ctx->uu.params.num_out)) {
|
||||
auto output = ctx->output(i);
|
||||
ctx->out.meta(output, ctx->input(0).meta);
|
||||
ctx->out.meta(output, ctx->getMeta());
|
||||
ctx->out.post(std::move(output), ctx->eptr);
|
||||
}
|
||||
}
|
||||
@@ -1374,6 +1384,11 @@ struct Infer: public cv::detail::KernelTag {
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &&p : uu.params.const_inputs) {
|
||||
const auto ii = inputs.at(p.first);
|
||||
ii->setPrecision(toIE(p.second.first.depth()));
|
||||
}
|
||||
|
||||
// FIXME: This isn't the best place to call reshape function.
|
||||
// Сorrect solution would be to do this in compile() method of network,
|
||||
// but now input meta isn't passed to compile() method.
|
||||
@@ -1474,7 +1489,8 @@ struct InferROI: public cv::detail::KernelTag {
|
||||
// only in the loadNetwork case.
|
||||
if (uu.params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Load) {
|
||||
// 0th is ROI, 1st is input image
|
||||
auto ii = uu.net.getInputsInfo().at(input_name);
|
||||
auto inputs = uu.net.getInputsInfo();
|
||||
auto ii = inputs.at(input_name);
|
||||
configureInputInfo(ii, mm);
|
||||
if (uu.params.layer_names_to_reshape.find(input_name) !=
|
||||
uu.params.layer_names_to_reshape.end()) {
|
||||
@@ -1496,6 +1512,11 @@ struct InferROI: public cv::detail::KernelTag {
|
||||
const_cast<IEUnit::InputFramesDesc &>(uu.net_input_params)
|
||||
.set_param(input_name, ii->getTensorDesc());
|
||||
}
|
||||
|
||||
for (auto &&p : uu.params.const_inputs) {
|
||||
inputs.at(p.first)->setPrecision(toIE(p.second.first.depth()));
|
||||
}
|
||||
|
||||
configureOutputPrecision(uu.net.getOutputsInfo(), uu.params.output_precision);
|
||||
} else {
|
||||
GAPI_Assert(uu.params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Import);
|
||||
@@ -1614,6 +1635,12 @@ struct InferList: public cv::detail::KernelTag {
|
||||
if (!input_reshape_table.empty()) {
|
||||
const_cast<IE::CNNNetwork *>(&uu.net)->reshape(input_reshape_table);
|
||||
}
|
||||
|
||||
for (auto &&p : uu.params.const_inputs) {
|
||||
const auto ii = inputs.at(p.first);
|
||||
ii->setPrecision(toIE(p.second.first.depth()));
|
||||
}
|
||||
|
||||
configureOutputPrecision(uu.net.getOutputsInfo(), uu.params.output_precision);
|
||||
} else {
|
||||
GAPI_Assert(uu.params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Import);
|
||||
@@ -1642,7 +1669,7 @@ struct InferList: public cv::detail::KernelTag {
|
||||
if (in_roi_vec.empty()) {
|
||||
for (auto i : ade::util::iota(ctx->uu.params.num_out)) {
|
||||
auto output = ctx->output(i);
|
||||
ctx->out.meta(output, ctx->input(0).meta);
|
||||
ctx->out.meta(output, ctx->getMeta());
|
||||
ctx->out.post(std::move(output));
|
||||
}
|
||||
return;
|
||||
@@ -1751,8 +1778,9 @@ struct InferList2: 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) {
|
||||
auto inputs = uu.net.getInputsInfo();
|
||||
// This is a cv::Rect -- configure the IE preprocessing
|
||||
auto ii = uu.net.getInputsInfo().at(input_name);
|
||||
auto ii = inputs.at(input_name);
|
||||
configureInputInfo(ii, mm_0);
|
||||
if (uu.params.layer_names_to_reshape.find(input_name) !=
|
||||
uu.params.layer_names_to_reshape.end()) {
|
||||
@@ -1762,6 +1790,10 @@ struct InferList2: public cv::detail::KernelTag {
|
||||
ii->getPreProcess().setResizeAlgorithm(IE::RESIZE_BILINEAR);
|
||||
}
|
||||
|
||||
for (auto &&p : uu.params.const_inputs) {
|
||||
inputs.at(p.first)->setPrecision(toIE(p.second.first.depth()));
|
||||
}
|
||||
|
||||
// FIXME: This isn't the best place to call reshape function.
|
||||
// Сorrect solution would be to do this in compile() method of network,
|
||||
// but now input meta isn't passed to compile() method.
|
||||
@@ -1806,7 +1838,7 @@ struct InferList2: public cv::detail::KernelTag {
|
||||
if (list_size == 0u) {
|
||||
for (auto i : ade::util::iota(ctx->uu.params.num_out)) {
|
||||
auto output = ctx->output(i);
|
||||
ctx->out.meta(output, ctx->input(0).meta);
|
||||
ctx->out.meta(output, ctx->getMeta());
|
||||
ctx->out.post(std::move(output));
|
||||
}
|
||||
return;
|
||||
|
||||
@@ -8,6 +8,19 @@ cv::gapi::onnx::PyParams::PyParams(const std::string& tag,
|
||||
const std::string& model_path)
|
||||
: m_priv(std::make_shared<Params<cv::gapi::Generic>>(tag, model_path)) {}
|
||||
|
||||
cv::gapi::onnx::PyParams& cv::gapi::onnx::PyParams::cfgMeanStd(const std::string &layer_name,
|
||||
const cv::Scalar &m,
|
||||
const cv::Scalar &s) {
|
||||
m_priv->cfgMeanStdDev(layer_name, m, s);
|
||||
return *this;
|
||||
}
|
||||
|
||||
cv::gapi::onnx::PyParams& cv::gapi::onnx::PyParams::cfgNormalize(const std::string &layer_name,
|
||||
bool flag) {
|
||||
m_priv->cfgNormalize(layer_name, flag);
|
||||
return *this;
|
||||
}
|
||||
|
||||
cv::gapi::GBackend cv::gapi::onnx::PyParams::backend() const {
|
||||
return m_priv->backend();
|
||||
}
|
||||
|
||||
@@ -44,7 +44,8 @@ static std::string pdims(const std::vector<int64_t> &dims) {
|
||||
|
||||
struct TensorInfo {
|
||||
TensorInfo() = default;
|
||||
explicit TensorInfo(const Ort::TensorTypeAndShapeInfo& info)
|
||||
|
||||
explicit TensorInfo(const Ort::ConstTensorTypeAndShapeInfo &info)
|
||||
: dims(info.GetShape())
|
||||
, type(info.GetElementType())
|
||||
, is_dynamic(ade::util::find(dims, -1) != dims.end()) {
|
||||
@@ -283,6 +284,7 @@ inline void preprocess(const cv::Mat& src,
|
||||
cv::resize(csc, rsz, cv::Size(new_w, new_h));
|
||||
if (src.depth() == CV_8U && type == CV_32F) {
|
||||
rsz.convertTo(pp, type, ti.normalize ? 1.f / 255 : 1.f);
|
||||
|
||||
if (ti.mstd.has_value()) {
|
||||
pp -= ti.mstd->mean;
|
||||
pp /= ti.mstd->stdev;
|
||||
@@ -688,11 +690,10 @@ std::vector<TensorInfo> ONNXCompiled::getTensorInfo(TensorPosition pos) {
|
||||
: this_session.GetOutputTypeInfo(i);
|
||||
tensor_info.emplace_back(info.GetTensorTypeAndShapeInfo());
|
||||
|
||||
char *name_p = pos == INPUT
|
||||
? this_session.GetInputName(i, allocator)
|
||||
: this_session.GetOutputName(i, allocator);
|
||||
tensor_info.back().name = name_p;
|
||||
allocator.Free(name_p);
|
||||
Ort::AllocatedStringPtr name_p = pos == INPUT
|
||||
? this_session.GetInputNameAllocated(i, allocator)
|
||||
: this_session.GetOutputNameAllocated(i, allocator);
|
||||
tensor_info.back().name = std::string(name_p.get());
|
||||
}
|
||||
|
||||
return tensor_info;
|
||||
@@ -1143,24 +1144,31 @@ namespace {
|
||||
if (pp.is_generic) {
|
||||
auto& info = cv::util::any_cast<cv::detail::InOutInfo>(op.params);
|
||||
|
||||
for (const auto& a : info.in_names)
|
||||
for (const auto& layer_name : info.in_names)
|
||||
{
|
||||
pp.input_names.push_back(a);
|
||||
}
|
||||
// Adding const input is necessary because the definition of input_names
|
||||
// includes const input.
|
||||
for (const auto& a : pp.const_inputs)
|
||||
{
|
||||
pp.input_names.push_back(a.first);
|
||||
pp.input_names.push_back(layer_name);
|
||||
if (!pp.generic_mstd.empty()) {
|
||||
const auto &ms = pp.generic_mstd.at(layer_name);
|
||||
pp.mean.push_back(ms.first);
|
||||
pp.stdev.push_back(ms.second);
|
||||
}
|
||||
if (!pp.generic_norm.empty()) {
|
||||
pp.normalize.push_back(pp.generic_norm.at(layer_name));
|
||||
}
|
||||
}
|
||||
pp.num_in = info.in_names.size();
|
||||
|
||||
// Incorporate extra parameters associated with input layer names
|
||||
// FIXME(DM): The current form assumes ALL input layers require
|
||||
// this information, this is obviously not correct
|
||||
|
||||
for (const auto& a : info.out_names)
|
||||
{
|
||||
pp.output_names.push_back(a);
|
||||
}
|
||||
pp.num_out = info.out_names.size();
|
||||
}
|
||||
} // if(is_generic) -- note, the structure is already filled at the user
|
||||
// end when a non-generic Params are used
|
||||
|
||||
gm.metadata(nh).set(ONNXUnit{pp});
|
||||
gm.metadata(nh).set(ONNXCallable{ki.run});
|
||||
|
||||
@@ -829,7 +829,11 @@ TEST_P(Preproc4lpiTest, Test)
|
||||
cv::cvtColor(in_mat, rgb_mat, cv::COLOR_YUV2RGB_NV12);
|
||||
cv::resize(rgb_mat, out_mat_ocv, out_sz, 0, 0, interp);
|
||||
|
||||
#if defined(__arm__) || defined(__aarch64__)
|
||||
EXPECT_GE(2, cvtest::norm(out_mat(roi), out_mat_ocv(roi), NORM_INF));
|
||||
#else
|
||||
EXPECT_EQ(0, cvtest::norm(out_mat(roi), out_mat_ocv(roi), NORM_INF));
|
||||
#endif
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(Fluid, Preproc4lpiTest,
|
||||
|
||||
@@ -332,9 +332,8 @@ public:
|
||||
// Inputs Run params
|
||||
std::vector<Ort::Value> in_tensors;
|
||||
for(size_t i = 0; i < num_in; ++i) {
|
||||
char* in_node_name_p = session.GetInputName(i, allocator);
|
||||
in_node_names.emplace_back(in_node_name_p);
|
||||
allocator.Free(in_node_name_p);
|
||||
auto in_node_name_p = session.GetInputNameAllocated(i, allocator);
|
||||
in_node_names.emplace_back(in_node_name_p.get());
|
||||
in_node_dims = toORT(ins[i].size);
|
||||
in_tensors.emplace_back(Ort::Value::CreateTensor<T>(memory_info,
|
||||
const_cast<T*>(ins[i].ptr<T>()),
|
||||
@@ -345,9 +344,8 @@ public:
|
||||
// Outputs Run params
|
||||
if (custom_out_names.empty()) {
|
||||
for(size_t i = 0; i < num_out; ++i) {
|
||||
char* out_node_name_p = session.GetOutputName(i, allocator);
|
||||
out_node_names.emplace_back(out_node_name_p);
|
||||
allocator.Free(out_node_name_p);
|
||||
auto out_node_name_p = session.GetOutputNameAllocated(i, allocator);
|
||||
out_node_names.emplace_back(out_node_name_p.get());
|
||||
}
|
||||
} else {
|
||||
out_node_names = std::move(custom_out_names);
|
||||
@@ -425,13 +423,17 @@ public:
|
||||
cv::Rect(cv::Point{50, 100}, cv::Size{250, 360})
|
||||
};
|
||||
|
||||
void preprocess(const cv::Mat& src, cv::Mat& dst) {
|
||||
// FIXME(dm): There's too much "preprocess" routines in this file
|
||||
// Only one must stay but better design it wisely (and later)
|
||||
void preprocess(const cv::Mat& src, cv::Mat& dst, bool norm = true) {
|
||||
const int new_h = 224;
|
||||
const int new_w = 224;
|
||||
cv::Mat tmp, cvt, rsz;
|
||||
cv::resize(src, rsz, cv::Size(new_w, new_h));
|
||||
rsz.convertTo(cvt, CV_32F, 1.f / 255);
|
||||
tmp = (cvt - mean) / std;
|
||||
rsz.convertTo(cvt, CV_32F, norm ? 1.f / 255 : 1.f);
|
||||
tmp = norm
|
||||
? (cvt - mean) / std
|
||||
: cvt;
|
||||
toCHW(tmp, dst);
|
||||
dst = dst.reshape(1, {1, 3, new_h, new_w});
|
||||
}
|
||||
@@ -552,16 +554,16 @@ TEST_F(ONNXClassification, Infer)
|
||||
in_mat = cv::imread(findDataFile("cv/dpm/cat.png", false));
|
||||
// ONNX_API code
|
||||
cv::Mat processed_mat;
|
||||
preprocess(in_mat, processed_mat);
|
||||
preprocess(in_mat, processed_mat, false); // NO normalization for 1.0-9, see #23597
|
||||
infer<float>(processed_mat, out_onnx);
|
||||
// G_API code
|
||||
G_API_NET(SqueezNet, <cv::GMat(cv::GMat)>, "squeeznet");
|
||||
cv::GMat in;
|
||||
cv::GMat out = cv::gapi::infer<SqueezNet>(in);
|
||||
cv::GComputation comp(cv::GIn(in), cv::GOut(out));
|
||||
// NOTE: We have to normalize U8 tensor
|
||||
// so cfgMeanStd() is here
|
||||
auto net = cv::gapi::onnx::Params<SqueezNet> { model_path }.cfgMeanStd({ mean }, { std });
|
||||
auto net = cv::gapi::onnx::Params<SqueezNet> {
|
||||
model_path
|
||||
}.cfgNormalize({false});
|
||||
comp.apply(cv::gin(in_mat),
|
||||
cv::gout(out_gapi.front()),
|
||||
cv::compile_args(cv::gapi::networks(net)));
|
||||
@@ -575,7 +577,7 @@ TEST_F(ONNXClassification, InferTensor)
|
||||
in_mat = cv::imread(findDataFile("cv/dpm/cat.png", false));
|
||||
// Create tensor
|
||||
cv::Mat tensor;
|
||||
preprocess(in_mat, tensor);
|
||||
preprocess(in_mat, tensor, false); // NO normalization for 1.0-9, see #23597
|
||||
// ONNX_API code
|
||||
infer<float>(tensor, out_onnx);
|
||||
// G_API code
|
||||
@@ -583,7 +585,9 @@ TEST_F(ONNXClassification, InferTensor)
|
||||
cv::GMat in;
|
||||
cv::GMat out = cv::gapi::infer<SqueezNet>(in);
|
||||
cv::GComputation comp(cv::GIn(in), cv::GOut(out));
|
||||
auto net = cv::gapi::onnx::Params<SqueezNet> { model_path };
|
||||
auto net = cv::gapi::onnx::Params<SqueezNet> {
|
||||
model_path
|
||||
}.cfgNormalize({false});
|
||||
comp.apply(cv::gin(tensor),
|
||||
cv::gout(out_gapi.front()),
|
||||
cv::compile_args(cv::gapi::networks(net)));
|
||||
@@ -598,7 +602,7 @@ TEST_F(ONNXClassification, InferROI)
|
||||
const auto ROI = rois.at(0);
|
||||
// ONNX_API code
|
||||
cv::Mat roi_mat;
|
||||
preprocess(in_mat(ROI), roi_mat);
|
||||
preprocess(in_mat(ROI), roi_mat, false); // NO normalization for 1.0-9, see #23597
|
||||
infer<float>(roi_mat, out_onnx);
|
||||
// G_API code
|
||||
G_API_NET(SqueezNet, <cv::GMat(cv::GMat)>, "squeeznet");
|
||||
@@ -606,9 +610,9 @@ TEST_F(ONNXClassification, InferROI)
|
||||
cv::GOpaque<cv::Rect> rect;
|
||||
cv::GMat out = cv::gapi::infer<SqueezNet>(rect, in);
|
||||
cv::GComputation comp(cv::GIn(in, rect), cv::GOut(out));
|
||||
// NOTE: We have to normalize U8 tensor
|
||||
// so cfgMeanStd() is here
|
||||
auto net = cv::gapi::onnx::Params<SqueezNet> { model_path }.cfgMeanStd({ mean }, { std });
|
||||
auto net = cv::gapi::onnx::Params<SqueezNet> {
|
||||
model_path
|
||||
}.cfgNormalize({false});
|
||||
comp.apply(cv::gin(in_mat, ROI),
|
||||
cv::gout(out_gapi.front()),
|
||||
cv::compile_args(cv::gapi::networks(net)));
|
||||
@@ -623,7 +627,7 @@ TEST_F(ONNXClassification, InferROIList)
|
||||
// ONNX_API code
|
||||
for (size_t i = 0; i < rois.size(); ++i) {
|
||||
cv::Mat roi_mat;
|
||||
preprocess(in_mat(rois[i]), roi_mat);
|
||||
preprocess(in_mat(rois[i]), roi_mat, false); // NO normalization for 1.0-9, see #23597
|
||||
infer<float>(roi_mat, out_onnx);
|
||||
}
|
||||
// G_API code
|
||||
@@ -634,7 +638,9 @@ TEST_F(ONNXClassification, InferROIList)
|
||||
cv::GComputation comp(cv::GIn(in, rr), cv::GOut(out));
|
||||
// NOTE: We have to normalize U8 tensor
|
||||
// so cfgMeanStd() is here
|
||||
auto net = cv::gapi::onnx::Params<SqueezNet> { model_path }.cfgMeanStd({ mean }, { std });
|
||||
auto net = cv::gapi::onnx::Params<SqueezNet> {
|
||||
model_path
|
||||
}.cfgNormalize({false});
|
||||
comp.apply(cv::gin(in_mat, rois),
|
||||
cv::gout(out_gapi),
|
||||
cv::compile_args(cv::gapi::networks(net)));
|
||||
@@ -649,7 +655,7 @@ TEST_F(ONNXClassification, Infer2ROIList)
|
||||
// ONNX_API code
|
||||
for (size_t i = 0; i < rois.size(); ++i) {
|
||||
cv::Mat roi_mat;
|
||||
preprocess(in_mat(rois[i]), roi_mat);
|
||||
preprocess(in_mat(rois[i]), roi_mat, false); // NO normalization for 1.0-9, see #23597
|
||||
infer<float>(roi_mat, out_onnx);
|
||||
}
|
||||
// G_API code
|
||||
@@ -660,7 +666,9 @@ TEST_F(ONNXClassification, Infer2ROIList)
|
||||
cv::GComputation comp(cv::GIn(in, rr), cv::GOut(out));
|
||||
// NOTE: We have to normalize U8 tensor
|
||||
// so cfgMeanStd() is here
|
||||
auto net = cv::gapi::onnx::Params<SqueezNet> { model_path }.cfgMeanStd({ mean }, { std });
|
||||
auto net = cv::gapi::onnx::Params<SqueezNet> {
|
||||
model_path
|
||||
}.cfgNormalize({false});
|
||||
comp.apply(cv::gin(in_mat, rois),
|
||||
cv::gout(out_gapi),
|
||||
cv::compile_args(cv::gapi::networks(net)));
|
||||
@@ -749,7 +757,7 @@ TEST_F(ONNXMediaFrame, InferBGR)
|
||||
in_mat = cv::imread(findDataFile("cv/dpm/cat.png", false));
|
||||
// ONNX_API code
|
||||
cv::Mat processed_mat;
|
||||
preprocess(in_mat, processed_mat);
|
||||
preprocess(in_mat, processed_mat, false); // NO normalization for 1.0-9, see #23597
|
||||
infer<float>(processed_mat, out_onnx);
|
||||
// G_API code
|
||||
auto frame = MediaFrame::Create<TestMediaBGR>(in_mat);
|
||||
@@ -759,7 +767,9 @@ TEST_F(ONNXMediaFrame, InferBGR)
|
||||
cv::GComputation comp(cv::GIn(in), cv::GOut(out));
|
||||
// NOTE: We have to normalize U8 tensor
|
||||
// so cfgMeanStd() is here
|
||||
auto net = cv::gapi::onnx::Params<SqueezNet> { model_path }.cfgMeanStd({ mean }, { std });
|
||||
auto net = cv::gapi::onnx::Params<SqueezNet> {
|
||||
model_path
|
||||
}.cfgNormalize({false});
|
||||
comp.apply(cv::gin(frame),
|
||||
cv::gout(out_gapi.front()),
|
||||
cv::compile_args(cv::gapi::networks(net)));
|
||||
@@ -776,7 +786,7 @@ TEST_F(ONNXMediaFrame, InferYUV)
|
||||
cv::Mat pp;
|
||||
cvtColorTwoPlane(m_in_y, m_in_uv, pp, cv::COLOR_YUV2BGR_NV12);
|
||||
cv::Mat processed_mat;
|
||||
preprocess(pp, processed_mat);
|
||||
preprocess(pp, processed_mat, false); // NO normalization for 1.0-9, see #23597
|
||||
infer<float>(processed_mat, out_onnx);
|
||||
// G_API code
|
||||
G_API_NET(SqueezNet, <cv::GMat(cv::GMat)>, "squeeznet");
|
||||
@@ -785,7 +795,9 @@ TEST_F(ONNXMediaFrame, InferYUV)
|
||||
cv::GComputation comp(cv::GIn(in), cv::GOut(out));
|
||||
// NOTE: We have to normalize U8 tensor
|
||||
// so cfgMeanStd() is here
|
||||
auto net = cv::gapi::onnx::Params<SqueezNet> { model_path }.cfgMeanStd({ mean }, { std });
|
||||
auto net = cv::gapi::onnx::Params<SqueezNet> {
|
||||
model_path
|
||||
}.cfgNormalize({false});
|
||||
comp.apply(cv::gin(frame),
|
||||
cv::gout(out_gapi.front()),
|
||||
cv::compile_args(cv::gapi::networks(net)));
|
||||
@@ -800,7 +812,7 @@ TEST_F(ONNXMediaFrame, InferROIBGR)
|
||||
auto frame = MediaFrame::Create<TestMediaBGR>(in_mat);
|
||||
// ONNX_API code
|
||||
cv::Mat roi_mat;
|
||||
preprocess(in_mat(rois.front()), roi_mat);
|
||||
preprocess(in_mat(rois.front()), roi_mat, false); // NO normalization for 1.0-9, see #23597
|
||||
infer<float>(roi_mat, out_onnx);
|
||||
// G_API code
|
||||
G_API_NET(SqueezNet, <cv::GMat(cv::GMat)>, "squeeznet");
|
||||
@@ -810,7 +822,9 @@ TEST_F(ONNXMediaFrame, InferROIBGR)
|
||||
cv::GComputation comp(cv::GIn(in, rect), cv::GOut(out));
|
||||
// NOTE: We have to normalize U8 tensor
|
||||
// so cfgMeanStd() is here
|
||||
auto net = cv::gapi::onnx::Params<SqueezNet> { model_path }.cfgMeanStd({ mean }, { std });
|
||||
auto net = cv::gapi::onnx::Params<SqueezNet> {
|
||||
model_path
|
||||
}.cfgNormalize({false});
|
||||
comp.apply(cv::gin(frame, rois.front()),
|
||||
cv::gout(out_gapi.front()),
|
||||
cv::compile_args(cv::gapi::networks(net)));
|
||||
@@ -827,7 +841,7 @@ TEST_F(ONNXMediaFrame, InferROIYUV)
|
||||
cv::Mat pp;
|
||||
cvtColorTwoPlane(m_in_y, m_in_uv, pp, cv::COLOR_YUV2BGR_NV12);
|
||||
cv::Mat roi_mat;
|
||||
preprocess(pp(rois.front()), roi_mat);
|
||||
preprocess(pp(rois.front()), roi_mat, false); // NO normalization for 1.0-9, see #23597
|
||||
infer<float>(roi_mat, out_onnx);
|
||||
// G_API code
|
||||
G_API_NET(SqueezNet, <cv::GMat(cv::GMat)>, "squeeznet");
|
||||
@@ -837,7 +851,9 @@ TEST_F(ONNXMediaFrame, InferROIYUV)
|
||||
cv::GComputation comp(cv::GIn(in, rect), cv::GOut(out));
|
||||
// NOTE: We have to normalize U8 tensor
|
||||
// so cfgMeanStd() is here
|
||||
auto net = cv::gapi::onnx::Params<SqueezNet> { model_path }.cfgMeanStd({ mean }, { std });
|
||||
auto net = cv::gapi::onnx::Params<SqueezNet> {
|
||||
model_path
|
||||
}.cfgNormalize({false});
|
||||
comp.apply(cv::gin(frame, rois.front()),
|
||||
cv::gout(out_gapi.front()),
|
||||
cv::compile_args(cv::gapi::networks(net)));
|
||||
@@ -853,7 +869,7 @@ TEST_F(ONNXMediaFrame, InferListBGR)
|
||||
// ONNX_API code
|
||||
for (size_t i = 0; i < rois.size(); ++i) {
|
||||
cv::Mat roi_mat;
|
||||
preprocess(in_mat(rois[i]), roi_mat);
|
||||
preprocess(in_mat(rois[i]), roi_mat, false); // NO normalization for 1.0-9, see #23597
|
||||
infer<float>(roi_mat, out_onnx);
|
||||
}
|
||||
// G_API code
|
||||
@@ -864,7 +880,9 @@ TEST_F(ONNXMediaFrame, InferListBGR)
|
||||
cv::GComputation comp(cv::GIn(in, rr), cv::GOut(out));
|
||||
// NOTE: We have to normalize U8 tensor
|
||||
// so cfgMeanStd() is here
|
||||
auto net = cv::gapi::onnx::Params<SqueezNet> { model_path }.cfgMeanStd({ mean }, { std });
|
||||
auto net = cv::gapi::onnx::Params<SqueezNet> {
|
||||
model_path
|
||||
}.cfgNormalize({false});
|
||||
comp.apply(cv::gin(frame, rois),
|
||||
cv::gout(out_gapi),
|
||||
cv::compile_args(cv::gapi::networks(net)));
|
||||
@@ -882,7 +900,7 @@ TEST_F(ONNXMediaFrame, InferListYUV)
|
||||
cvtColorTwoPlane(m_in_y, m_in_uv, pp, cv::COLOR_YUV2BGR_NV12);
|
||||
for (size_t i = 0; i < rois.size(); ++i) {
|
||||
cv::Mat roi_mat;
|
||||
preprocess(pp(rois[i]), roi_mat);
|
||||
preprocess(pp(rois[i]), roi_mat, false); // NO normalization for 1.0-9, see #23597
|
||||
infer<float>(roi_mat, out_onnx);
|
||||
}
|
||||
// G_API code
|
||||
@@ -893,7 +911,9 @@ TEST_F(ONNXMediaFrame, InferListYUV)
|
||||
cv::GComputation comp(cv::GIn(in, rr), cv::GOut(out));
|
||||
// NOTE: We have to normalize U8 tensor
|
||||
// so cfgMeanStd() is here
|
||||
auto net = cv::gapi::onnx::Params<SqueezNet> { model_path }.cfgMeanStd({ mean }, { std });
|
||||
auto net = cv::gapi::onnx::Params<SqueezNet> {
|
||||
model_path
|
||||
}.cfgNormalize({false});
|
||||
comp.apply(cv::gin(frame, rois),
|
||||
cv::gout(out_gapi),
|
||||
cv::compile_args(cv::gapi::networks(net)));
|
||||
@@ -935,7 +955,7 @@ TEST_F(ONNXMediaFrame, InferList2BGR)
|
||||
// ONNX_API code
|
||||
for (size_t i = 0; i < rois.size(); ++i) {
|
||||
cv::Mat roi_mat;
|
||||
preprocess(in_mat(rois[i]), roi_mat);
|
||||
preprocess(in_mat(rois[i]), roi_mat, false); // NO normalization for 1.0-9, see #23597
|
||||
infer<float>(roi_mat, out_onnx);
|
||||
}
|
||||
// G_API code
|
||||
@@ -946,7 +966,9 @@ TEST_F(ONNXMediaFrame, InferList2BGR)
|
||||
cv::GComputation comp(cv::GIn(in, rr), cv::GOut(out));
|
||||
// NOTE: We have to normalize U8 tensor
|
||||
// so cfgMeanStd() is here
|
||||
auto net = cv::gapi::onnx::Params<SqueezNet> { model_path }.cfgMeanStd({ mean }, { std });
|
||||
auto net = cv::gapi::onnx::Params<SqueezNet> {
|
||||
model_path
|
||||
}.cfgNormalize({false});
|
||||
comp.apply(cv::gin(frame, rois),
|
||||
cv::gout(out_gapi),
|
||||
cv::compile_args(cv::gapi::networks(net)));
|
||||
|
||||
@@ -27,7 +27,7 @@ class GMockExecutable final: public cv::gimpl::GIslandExecutable
|
||||
m_priv->m_reshape_counter++;
|
||||
}
|
||||
virtual void handleNewStream() override { }
|
||||
virtual void run(std::vector<InObj>&&, std::vector<OutObj>&&) { }
|
||||
virtual void run(std::vector<InObj>&&, std::vector<OutObj>&&) override { }
|
||||
virtual bool allocatesOutputs() const override
|
||||
{
|
||||
return true;
|
||||
|
||||
@@ -190,7 +190,7 @@ public:
|
||||
: cv::gapi::wip::GCaptureSource(pipeline) {
|
||||
}
|
||||
|
||||
bool pull(cv::gapi::wip::Data& data) {
|
||||
bool pull(cv::gapi::wip::Data& data) override {
|
||||
if (cv::gapi::wip::GCaptureSource::pull(data)) {
|
||||
data = cv::MediaFrame::Create<TestMediaBGR>(cv::util::get<cv::Mat>(data));
|
||||
return true;
|
||||
@@ -232,7 +232,7 @@ public:
|
||||
: cv::gapi::wip::GCaptureSource(pipeline) {
|
||||
}
|
||||
|
||||
bool pull(cv::gapi::wip::Data& data) {
|
||||
bool pull(cv::gapi::wip::Data& data) override {
|
||||
if (cv::gapi::wip::GCaptureSource::pull(data)) {
|
||||
cv::Mat bgr = cv::util::get<cv::Mat>(data);
|
||||
cv::Mat y, uv;
|
||||
@@ -256,7 +256,7 @@ public:
|
||||
: cv::gapi::wip::GCaptureSource(pipeline) {
|
||||
}
|
||||
|
||||
bool pull(cv::gapi::wip::Data& data) {
|
||||
bool pull(cv::gapi::wip::Data& data) override {
|
||||
if (cv::gapi::wip::GCaptureSource::pull(data)) {
|
||||
cv::Mat bgr = cv::util::get<cv::Mat>(data);
|
||||
cv::Mat gray;
|
||||
@@ -319,7 +319,7 @@ public:
|
||||
return "InvalidSource sucessfuly failed!";
|
||||
}
|
||||
|
||||
bool pull(cv::gapi::wip::Data& d) {
|
||||
bool pull(cv::gapi::wip::Data& d) override {
|
||||
++m_curr_frame_id;
|
||||
if (m_curr_frame_id > m_num_frames) {
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user