mirror of
https://github.com/opencv/opencv.git
synced 2025-06-17 23:51:16 +08:00
Merge pull request #18496 from AsyaPronina:comp_args_serialization
Serialization && deserialization for compile arguments * Initial stub * Add test on serialization of a custom type * Namespaces rework * Fix isSupported in test struct * Fix clang lookup issue * Initial implementation * Drop the isSupported flag * Initial implementation * Removed internal header inclusion * Switched to public API * Implemented serialization * Adding desirialize: WIP * Fixed merge errors * Implemented * Final polishing * Addressed review comments and added debug throw * Added FluidROI test * Polishing * Polishing * Polishing * Polishing * Polishing * Updated CMakeLists.txt * Fixed comments * Addressed review comments * Removed decay from deserialize_arg * Addressed review comments * Removed extra inclusion * Fixed Win64 warning * Update gcommon.hpp * Update serialization.cpp * Update gcommon.hpp * gapi: drop GAPI_EXPORTS_W_SIMPLE from GCompileArg Co-authored-by: Smirnov Alexey <alexey.smirnov@intel.com> Co-authored-by: AsyaPronina <155jj@mail.ru>
This commit is contained in:
parent
46ccde82cf
commit
af2f8c69f0
@ -49,6 +49,7 @@ file(GLOB gapi_ext_hdrs
|
|||||||
"${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/ocl/*.hpp"
|
"${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/ocl/*.hpp"
|
||||||
"${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/own/*.hpp"
|
"${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/own/*.hpp"
|
||||||
"${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/render/*.hpp"
|
"${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/render/*.hpp"
|
||||||
|
"${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/s11n/*.hpp"
|
||||||
"${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/streaming/*.hpp"
|
"${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/streaming/*.hpp"
|
||||||
"${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/plaidml/*.hpp"
|
"${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/plaidml/*.hpp"
|
||||||
"${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/util/*.hpp"
|
"${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/util/*.hpp"
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include <opencv2/gapi/own/exports.hpp>
|
#include <opencv2/gapi/own/exports.hpp>
|
||||||
#include <opencv2/gapi/own/assert.hpp>
|
#include <opencv2/gapi/own/assert.hpp>
|
||||||
#include <opencv2/gapi/render/render_types.hpp>
|
#include <opencv2/gapi/render/render_types.hpp>
|
||||||
|
#include <opencv2/gapi/s11n/base.hpp>
|
||||||
|
|
||||||
namespace cv {
|
namespace cv {
|
||||||
|
|
||||||
@ -94,6 +95,15 @@ enum class GShape: int
|
|||||||
GFRAME,
|
GFRAME,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace gapi {
|
||||||
|
namespace s11n {
|
||||||
|
namespace detail {
|
||||||
|
template<typename T> struct wrap_serialize;
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace s11n
|
||||||
|
} // namespace gapi
|
||||||
|
|
||||||
|
|
||||||
struct GCompileArg;
|
struct GCompileArg;
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
@ -139,7 +149,7 @@ namespace detail {
|
|||||||
* passed in (a variadic template parameter pack) into a vector of
|
* passed in (a variadic template parameter pack) into a vector of
|
||||||
* cv::GCompileArg objects.
|
* cv::GCompileArg objects.
|
||||||
*/
|
*/
|
||||||
struct GAPI_EXPORTS_W_SIMPLE GCompileArg
|
struct GCompileArg
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// NB: Required for pythnon bindings
|
// NB: Required for pythnon bindings
|
||||||
@ -151,6 +161,7 @@ public:
|
|||||||
template<typename T, typename std::enable_if<!detail::is_compile_arg<T>::value, int>::type = 0>
|
template<typename T, typename std::enable_if<!detail::is_compile_arg<T>::value, int>::type = 0>
|
||||||
explicit GCompileArg(T &&t)
|
explicit GCompileArg(T &&t)
|
||||||
: tag(detail::CompileArgTag<typename std::decay<T>::type>::tag())
|
: tag(detail::CompileArgTag<typename std::decay<T>::type>::tag())
|
||||||
|
, serializeF(&cv::gapi::s11n::detail::wrap_serialize<T>::serialize)
|
||||||
, arg(t)
|
, arg(t)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -165,7 +176,13 @@ public:
|
|||||||
return util::any_cast<T>(arg);
|
return util::any_cast<T>(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void serialize(cv::gapi::s11n::IOStream& os) const
|
||||||
|
{
|
||||||
|
serializeF(os, *this);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
std::function<void(cv::gapi::s11n::IOStream&, const GCompileArg&)> serializeF;
|
||||||
util::any arg;
|
util::any arg;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -198,6 +215,19 @@ inline cv::util::optional<T> getCompileArg(const cv::GCompileArgs &args)
|
|||||||
}
|
}
|
||||||
return cv::util::optional<T>();
|
return cv::util::optional<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace s11n {
|
||||||
|
namespace detail {
|
||||||
|
template<typename T> struct wrap_serialize
|
||||||
|
{
|
||||||
|
static void serialize(IOStream& os, const GCompileArg& arg)
|
||||||
|
{
|
||||||
|
using decayed_type = typename std::decay<T>::type;
|
||||||
|
S11N<decayed_type>::serialize(os, arg.get<decayed_type>());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace s11n
|
||||||
} // namespace gapi
|
} // namespace gapi
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <opencv2/gapi/s11n/base.hpp>
|
||||||
#include <opencv2/gapi/gcomputation.hpp>
|
#include <opencv2/gapi/gcomputation.hpp>
|
||||||
|
|
||||||
namespace cv {
|
namespace cv {
|
||||||
@ -17,14 +18,13 @@ namespace gapi {
|
|||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
GAPI_EXPORTS cv::GComputation getGraph(const std::vector<char> &p);
|
GAPI_EXPORTS cv::GComputation getGraph(const std::vector<char> &p);
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
GAPI_EXPORTS cv::GMetaArgs getMetaArgs(const std::vector<char> &p);
|
GAPI_EXPORTS cv::GMetaArgs getMetaArgs(const std::vector<char> &p);
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
GAPI_EXPORTS cv::GRunArgs getRunArgs(const std::vector<char> &p);
|
GAPI_EXPORTS cv::GRunArgs getRunArgs(const std::vector<char> &p);
|
||||||
|
|
||||||
|
template<typename... Types>
|
||||||
|
cv::GCompileArgs getCompileArgs(const std::vector<char> &p);
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
GAPI_EXPORTS std::vector<char> serialize(const cv::GComputation &c);
|
GAPI_EXPORTS std::vector<char> serialize(const cv::GComputation &c);
|
||||||
@ -35,6 +35,7 @@ T deserialize(const std::vector<char> &p);
|
|||||||
|
|
||||||
//} //ananymous namespace
|
//} //ananymous namespace
|
||||||
|
|
||||||
|
GAPI_EXPORTS std::vector<char> serialize(const cv::GCompileArgs&);
|
||||||
GAPI_EXPORTS std::vector<char> serialize(const cv::GMetaArgs&);
|
GAPI_EXPORTS std::vector<char> serialize(const cv::GMetaArgs&);
|
||||||
GAPI_EXPORTS std::vector<char> serialize(const cv::GRunArgs&);
|
GAPI_EXPORTS std::vector<char> serialize(const cv::GRunArgs&);
|
||||||
|
|
||||||
@ -53,6 +54,11 @@ cv::GRunArgs deserialize(const std::vector<char> &p) {
|
|||||||
return detail::getRunArgs(p);
|
return detail::getRunArgs(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T, typename... Types> inline
|
||||||
|
typename std::enable_if<std::is_same<T, GCompileArgs>::value, GCompileArgs>::
|
||||||
|
type deserialize(const std::vector<char> &p) {
|
||||||
|
return detail::getCompileArgs<Types...>(p);
|
||||||
|
}
|
||||||
} // namespace gapi
|
} // namespace gapi
|
||||||
} // namespace cv
|
} // namespace cv
|
||||||
|
|
||||||
@ -91,6 +97,10 @@ struct GAPI_EXPORTS IIStream {
|
|||||||
virtual IIStream& operator>> (std::string &) = 0;
|
virtual IIStream& operator>> (std::string &) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
GAPI_EXPORTS std::unique_ptr<IIStream> getInStream(const std::vector<char> &p);
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// S11N operators
|
// S11N operators
|
||||||
@ -174,17 +184,48 @@ IIStream& operator>> (IIStream& is, std::vector<T> &ts) {
|
|||||||
}
|
}
|
||||||
return is;
|
return is;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
// Will be used along with default types if possible in specific cases (compile args, etc)
|
|
||||||
// Note: actual implementation is defined by user
|
|
||||||
template<typename T>
|
|
||||||
struct GAPI_EXPORTS S11N {
|
|
||||||
static void serialize(IOStream &, const T &) {}
|
|
||||||
static T deserialize(IIStream &) { T t; return t; }
|
|
||||||
};
|
|
||||||
} // namespace detail
|
|
||||||
} // namespace s11n
|
} // namespace s11n
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
template<typename T> struct deserialize_arg;
|
||||||
|
|
||||||
|
template<> struct deserialize_arg<std::tuple<>> {
|
||||||
|
static GCompileArg exec(cv::gapi::s11n::IIStream&, const std::string&) {
|
||||||
|
throw std::logic_error("Passed arg can't be deserialized!");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename... Types>
|
||||||
|
struct deserialize_arg<std::tuple<T, Types...>> {
|
||||||
|
static GCompileArg exec(cv::gapi::s11n::IIStream& is, const std::string& tag) {
|
||||||
|
if (tag == cv::detail::CompileArgTag<T>::tag()) {
|
||||||
|
return GCompileArg {
|
||||||
|
cv::gapi::s11n::detail::S11N<T>::deserialize(is)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return deserialize_arg<std::tuple<Types...>>::exec(is, tag);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename... Types>
|
||||||
|
cv::GCompileArgs getCompileArgs(const std::vector<char> &p) {
|
||||||
|
std::unique_ptr<cv::gapi::s11n::IIStream> pIs = cv::gapi::s11n::detail::getInStream(p);
|
||||||
|
cv::gapi::s11n::IIStream& is = *pIs;
|
||||||
|
cv::GCompileArgs args;
|
||||||
|
|
||||||
|
uint32_t sz = 0;
|
||||||
|
is >> sz;
|
||||||
|
for (uint32_t i = 0; i < sz; ++i) {
|
||||||
|
std::string tag;
|
||||||
|
is >> tag;
|
||||||
|
args.push_back(cv::gapi::detail::deserialize_arg<std::tuple<Types...>>::exec(is, tag));
|
||||||
|
}
|
||||||
|
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
} // namespace detail
|
||||||
} // namespace gapi
|
} // namespace gapi
|
||||||
} // namespace cv
|
} // namespace cv
|
||||||
|
|
||||||
|
36
modules/gapi/include/opencv2/gapi/s11n/base.hpp
Normal file
36
modules/gapi/include/opencv2/gapi/s11n/base.hpp
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
// This file is part of OpenCV project.
|
||||||
|
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||||
|
// of this distribution and at http://opencv.org/license.html.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2020 Intel Corporation
|
||||||
|
|
||||||
|
#ifndef OPENCV_GAPI_S11N_BASE_HPP
|
||||||
|
#define OPENCV_GAPI_S11N_BASE_HPP
|
||||||
|
|
||||||
|
#include <opencv2/gapi/own/assert.hpp>
|
||||||
|
|
||||||
|
namespace cv {
|
||||||
|
namespace gapi {
|
||||||
|
namespace s11n {
|
||||||
|
struct IOStream;
|
||||||
|
struct IIStream;
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
// Will be used along with default types if possible in specific cases (compile args, etc)
|
||||||
|
// Note: actual implementation is defined by user
|
||||||
|
template<typename T>
|
||||||
|
struct S11N {
|
||||||
|
static void serialize(IOStream &, const T &) {
|
||||||
|
GAPI_Assert(false && "No serialization routine is provided!");
|
||||||
|
}
|
||||||
|
static T deserialize(IIStream &) {
|
||||||
|
GAPI_Assert(false && "No deserialization routine is provided!");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace s11n
|
||||||
|
} // namespace gapi
|
||||||
|
} // namespace cv
|
||||||
|
|
||||||
|
#endif // OPENCV_GAPI_S11N_BASE_HPP
|
@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
namespace cv
|
namespace cv
|
||||||
{
|
{
|
||||||
|
struct GAPI_EXPORTS_W_SIMPLE GCompileArg { };
|
||||||
|
|
||||||
GAPI_EXPORTS_W GCompileArgs compile_args(gapi::GKernelPackage pkg);
|
GAPI_EXPORTS_W GCompileArgs compile_args(gapi::GKernelPackage pkg);
|
||||||
|
|
||||||
class GAPI_EXPORTS_W_SIMPLE GProtoArg { };
|
class GAPI_EXPORTS_W_SIMPLE GProtoArg { };
|
||||||
|
@ -44,6 +44,13 @@ std::vector<char> cv::gapi::serialize(const cv::GRunArgs& ra)
|
|||||||
return os.data();
|
return os.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<char> cv::gapi::serialize(const cv::GCompileArgs& ca)
|
||||||
|
{
|
||||||
|
cv::gapi::s11n::ByteMemoryOutStream os;
|
||||||
|
serialize(os, ca);
|
||||||
|
return os.data();
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: This function should move from S11N to GRunArg-related entities.
|
// FIXME: This function should move from S11N to GRunArg-related entities.
|
||||||
// it has nothing to do with the S11N as it is
|
// it has nothing to do with the S11N as it is
|
||||||
cv::GRunArgsP cv::gapi::bind(cv::GRunArgs &results)
|
cv::GRunArgsP cv::gapi::bind(cv::GRunArgs &results)
|
||||||
|
@ -329,6 +329,13 @@ IIStream& operator>> (IIStream& is, cv::gapi::wip::draw::Line &l) {
|
|||||||
|
|
||||||
// G-API types /////////////////////////////////////////////////////////////////
|
// G-API types /////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
IOStream& operator<< (IOStream& os, const cv::GCompileArg& arg)
|
||||||
|
{
|
||||||
|
os << arg.tag;
|
||||||
|
arg.serialize(os);
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
// Stubs (empty types)
|
// Stubs (empty types)
|
||||||
|
|
||||||
IOStream& operator<< (IOStream& os, cv::util::monostate ) {return os;}
|
IOStream& operator<< (IOStream& os, cv::util::monostate ) {return os;}
|
||||||
@ -865,6 +872,14 @@ IIStream& ByteMemoryInStream::operator>> (std::string& str) {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GAPI_EXPORTS std::unique_ptr<IIStream> detail::getInStream(const std::vector<char> &p) {
|
||||||
|
return std::unique_ptr<ByteMemoryInStream>(new ByteMemoryInStream(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
GAPI_EXPORTS void serialize(IOStream& os, const cv::GCompileArgs &ca) {
|
||||||
|
os << ca;
|
||||||
|
}
|
||||||
|
|
||||||
GAPI_EXPORTS void serialize(IOStream& os, const cv::GMetaArgs &ma) {
|
GAPI_EXPORTS void serialize(IOStream& os, const cv::GMetaArgs &ma) {
|
||||||
os << ma;
|
os << ma;
|
||||||
}
|
}
|
||||||
@ -882,7 +897,6 @@ GAPI_EXPORTS GRunArgs run_args_deserialize(IIStream& is) {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace s11n
|
} // namespace s11n
|
||||||
} // namespace gapi
|
} // namespace gapi
|
||||||
} // namespace cv
|
} // namespace cv
|
||||||
|
@ -40,6 +40,8 @@ struct GSerialized {
|
|||||||
|
|
||||||
// G-API types /////////////////////////////////////////////////////////////////
|
// G-API types /////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
GAPI_EXPORTS IOStream& operator<< (IOStream& os, const cv::GCompileArg& arg);
|
||||||
|
|
||||||
GAPI_EXPORTS IOStream& operator<< (IOStream& os, cv::util::monostate );
|
GAPI_EXPORTS IOStream& operator<< (IOStream& os, cv::util::monostate );
|
||||||
GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::util::monostate &);
|
GAPI_EXPORTS IIStream& operator>> (IIStream& is, cv::util::monostate &);
|
||||||
|
|
||||||
@ -268,6 +270,11 @@ public:
|
|||||||
virtual IIStream& operator>> (std::string &) override;
|
virtual IIStream& operator>> (std::string &) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
GAPI_EXPORTS std::unique_ptr<IIStream> getInStream(const std::vector<char> &p);
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
GAPI_EXPORTS void serialize(IOStream& os, const cv::GCompileArgs &ca);
|
||||||
GAPI_EXPORTS void serialize(IOStream& os, const cv::GMetaArgs &ma);
|
GAPI_EXPORTS void serialize(IOStream& os, const cv::GMetaArgs &ma);
|
||||||
GAPI_EXPORTS void serialize(IOStream& os, const cv::GRunArgs &ra);
|
GAPI_EXPORTS void serialize(IOStream& os, const cv::GRunArgs &ra);
|
||||||
GAPI_EXPORTS GMetaArgs meta_args_deserialize(IIStream& is);
|
GAPI_EXPORTS GMetaArgs meta_args_deserialize(IIStream& is);
|
||||||
|
@ -21,7 +21,7 @@ namespace opencv_test
|
|||||||
{
|
{
|
||||||
std::string method;
|
std::string method;
|
||||||
};
|
};
|
||||||
}
|
} // namespace opencv_test
|
||||||
|
|
||||||
namespace cv
|
namespace cv
|
||||||
{
|
{
|
||||||
@ -31,11 +31,11 @@ namespace cv
|
|||||||
{
|
{
|
||||||
static const char* tag()
|
static const char* tag()
|
||||||
{
|
{
|
||||||
return "org.opencv.test..background_substractor_state_params";
|
return "org.opencv.test.background_substractor_state_params";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
} // namespace detail
|
||||||
}
|
} // namespace cv
|
||||||
|
|
||||||
namespace opencv_test
|
namespace opencv_test
|
||||||
{
|
{
|
||||||
|
@ -34,6 +34,17 @@ namespace detail {
|
|||||||
} // namespace gapi
|
} // namespace gapi
|
||||||
} // namespace cv
|
} // namespace cv
|
||||||
|
|
||||||
|
|
||||||
|
namespace cv {
|
||||||
|
namespace detail {
|
||||||
|
template<> struct CompileArgTag<MyCustomType> {
|
||||||
|
static const char* tag() {
|
||||||
|
return "org.opencv.test.mycustomtype";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace cv
|
||||||
|
|
||||||
namespace opencv_test {
|
namespace opencv_test {
|
||||||
|
|
||||||
struct S11N_Basic: public ::testing::Test {
|
struct S11N_Basic: public ::testing::Test {
|
||||||
@ -511,4 +522,15 @@ TEST_F(S11N_Basic, Test_Custom_Type) {
|
|||||||
MyCustomType new_var = cv::gapi::s11n::detail::S11N<MyCustomType>::deserialize(is);
|
MyCustomType new_var = cv::gapi::s11n::detail::S11N<MyCustomType>::deserialize(is);
|
||||||
EXPECT_EQ(var, new_var);
|
EXPECT_EQ(var, new_var);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(S11N_Basic, Test_Custom_CompileArg) {
|
||||||
|
MyCustomType customVar{1248, "World", {1280, 720, 640, 480}, {{5, 32434142342}, {7, 34242432}}};
|
||||||
|
|
||||||
|
std::vector<char> sArgs = cv::gapi::serialize(cv::compile_args(customVar));
|
||||||
|
|
||||||
|
GCompileArgs dArgs = cv::gapi::deserialize<GCompileArgs, MyCustomType>(sArgs);
|
||||||
|
|
||||||
|
MyCustomType dCustomVar = cv::gapi::getCompileArg<MyCustomType>(dArgs).value();
|
||||||
|
EXPECT_EQ(customVar, dCustomVar);
|
||||||
|
}
|
||||||
} // namespace opencv_test
|
} // namespace opencv_test
|
||||||
|
Loading…
Reference in New Issue
Block a user