diff --git a/modules/gapi/include/opencv2/gapi/gcommon.hpp b/modules/gapi/include/opencv2/gapi/gcommon.hpp index dc2c8b9bd7..e008fe4bf1 100644 --- a/modules/gapi/include/opencv2/gapi/gcommon.hpp +++ b/modules/gapi/include/opencv2/gapi/gcommon.hpp @@ -44,12 +44,15 @@ namespace detail CV_BOOL, // bool user G-API data CV_INT, // int user G-API data CV_DOUBLE, // double user G-API data + CV_FLOAT, // float user G-API data + CV_UINT64, // uint64_t user G-API data + CV_STRING, // std::string user G-API data CV_POINT, // cv::Point user G-API data CV_SIZE, // cv::Size user G-API data CV_RECT, // cv::Rect user G-API data CV_SCALAR, // cv::Scalar user G-API data CV_MAT, // cv::Mat user G-API data - CV_PRIM, // cv::gapi::wip::draw::Prim user G-API data + CV_DRAW_PRIM, // cv::gapi::wip::draw::Prim user G-API data }; // Type traits helper which simplifies the extraction of kind from type @@ -57,19 +60,23 @@ namespace detail template struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_UNKNOWN; }; template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_INT; }; template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_DOUBLE; }; - template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_SIZE; }; + template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_FLOAT; }; + template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_UINT64; }; template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_BOOL; }; + template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_STRING; }; + template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_SIZE; }; template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_SCALAR; }; template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_POINT; }; template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_MAT; }; template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_RECT; }; template<> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_MAT; }; template<> struct GOpaqueTraits - { static constexpr const OpaqueKind kind = OpaqueKind::CV_PRIM; }; - // GArray is not supporting bool type for now due to difference in std::vector implementation - using GOpaqueTraitsArrayTypes = std::tuple; + { static constexpr const OpaqueKind kind = OpaqueKind::CV_DRAW_PRIM; }; + using GOpaqueTraitsArrayTypes = std::tuple; // GOpaque is not supporting cv::Mat and cv::Scalar since there are GScalar and GMat types - using GOpaqueTraitsOpaqueTypes = std::tuple; + using GOpaqueTraitsOpaqueTypes = std::tuple; } // namespace detail // This definition is here because it is reused by both public(?) and internal diff --git a/modules/gapi/include/opencv2/gapi/gopaque.hpp b/modules/gapi/include/opencv2/gapi/gopaque.hpp index 1c45d4683e..3d1394473b 100644 --- a/modules/gapi/include/opencv2/gapi/gopaque.hpp +++ b/modules/gapi/include/opencv2/gapi/gopaque.hpp @@ -240,7 +240,7 @@ namespace detail // FIXME: probably won't work with const object explicit OpaqueRef(T&& obj) : m_ref(new OpaqueRefT>(std::forward(obj))), - m_kind(GOpaqueTraits::kind) {} + m_kind(GOpaqueTraits>::kind) {} cv::detail::OpaqueKind getKind() const { diff --git a/modules/gapi/src/backends/common/serialization.cpp b/modules/gapi/src/backends/common/serialization.cpp index ab7626d43d..76618d6acd 100644 --- a/modules/gapi/src/backends/common/serialization.cpp +++ b/modules/gapi/src/backends/common/serialization.cpp @@ -478,14 +478,17 @@ I::OStream& operator<< (I::OStream& os, const cv::GArg &arg) { GAPI_Assert(arg.kind == cv::detail::ArgKind::OPAQUE_VAL); GAPI_Assert(arg.opaque_kind != cv::detail::OpaqueKind::CV_UNKNOWN); switch (arg.opaque_kind) { - case cv::detail::OpaqueKind::CV_BOOL: os << arg.get(); break; - case cv::detail::OpaqueKind::CV_INT: os << arg.get(); break; - case cv::detail::OpaqueKind::CV_DOUBLE: os << arg.get(); break; - case cv::detail::OpaqueKind::CV_POINT: os << arg.get(); break; - case cv::detail::OpaqueKind::CV_SIZE: os << arg.get(); break; - case cv::detail::OpaqueKind::CV_RECT: os << arg.get(); break; - case cv::detail::OpaqueKind::CV_SCALAR: os << arg.get(); break; - case cv::detail::OpaqueKind::CV_MAT: os << arg.get(); break; + case cv::detail::OpaqueKind::CV_BOOL: os << arg.get(); break; + case cv::detail::OpaqueKind::CV_INT: os << arg.get(); break; + case cv::detail::OpaqueKind::CV_UINT64: os << arg.get(); break; + case cv::detail::OpaqueKind::CV_DOUBLE: os << arg.get(); break; + case cv::detail::OpaqueKind::CV_FLOAT: os << arg.get(); break; + case cv::detail::OpaqueKind::CV_STRING: os << arg.get(); break; + case cv::detail::OpaqueKind::CV_POINT: os << arg.get(); break; + case cv::detail::OpaqueKind::CV_SIZE: os << arg.get(); break; + case cv::detail::OpaqueKind::CV_RECT: os << arg.get(); break; + case cv::detail::OpaqueKind::CV_SCALAR: os << arg.get(); break; + case cv::detail::OpaqueKind::CV_MAT: os << arg.get(); break; default: GAPI_Assert(false && "GArg: Unsupported (unknown?) opaque value type"); } } @@ -511,7 +514,10 @@ I::IStream& operator>> (I::IStream& is, cv::GArg &arg) { { T t{}; is >> t; arg = (cv::GArg(t)); } break HANDLE_CASE(BOOL , bool); HANDLE_CASE(INT , int); + HANDLE_CASE(UINT64 , uint64_t); HANDLE_CASE(DOUBLE , double); + HANDLE_CASE(FLOAT , float); + HANDLE_CASE(STRING , std::string); HANDLE_CASE(POINT , cv::Point); HANDLE_CASE(SIZE , cv::Size); HANDLE_CASE(RECT , cv::Rect); @@ -686,6 +692,12 @@ I::OStream& ByteMemoryOutStream::operator<< (uint32_t atom) { m_storage.push_back(0xFF & (atom >> 24)); return *this; } +I::OStream& ByteMemoryOutStream::operator<< (uint64_t atom) { + for (int i = 0; i < 8; ++i) { + m_storage.push_back(0xFF & (atom >> (i * 8)));; + } + return *this; +} I::OStream& ByteMemoryOutStream::operator<< (bool atom) { m_storage.push_back(atom ? 1 : 0); return *this; @@ -734,7 +746,6 @@ I::OStream& ByteMemoryOutStream::operator<< (const std::string &str) { for (auto c : str) *this << c; return *this; } - ByteMemoryInStream::ByteMemoryInStream(const std::vector &data) : m_storage(data) { } @@ -753,11 +764,26 @@ I::IStream& ByteMemoryInStream::operator>> (bool& atom) { atom = (m_storage[m_idx++] == 0) ? false : true; return *this; } +I::IStream& ByteMemoryInStream::operator>> (std::vector::reference atom) { + check(sizeof(char)); + atom = (m_storage[m_idx++] == 0) ? false : true; + return *this; +} I::IStream& ByteMemoryInStream::operator>> (char &atom) { check(sizeof(char)); atom = m_storage[m_idx++]; return *this; } +I::IStream& ByteMemoryInStream::operator>> (uint64_t &atom) { + check(sizeof(uint64_t)); + uint8_t x[8]; + atom = 0; + for (int i = 0; i < 8; ++i) { + x[i] = static_cast(m_storage[m_idx++]); + atom |= (static_cast(x[i]) << (i * 8)); + } + return *this; +} I::IStream& ByteMemoryInStream::operator>> (unsigned char &atom) { char c{}; *this >> c; diff --git a/modules/gapi/src/backends/common/serialization.hpp b/modules/gapi/src/backends/common/serialization.hpp index 9286bc4391..7a2952a134 100644 --- a/modules/gapi/src/backends/common/serialization.hpp +++ b/modules/gapi/src/backends/common/serialization.hpp @@ -9,7 +9,8 @@ #include #include -#include +#include +#include #include // used in the vector<> @@ -46,6 +47,7 @@ namespace I { virtual OStream& operator<< (int) = 0; //virtual OStream& operator<< (std::size_t) = 0; virtual OStream& operator<< (uint32_t) = 0; + virtual OStream& operator<< (uint64_t) = 0; virtual OStream& operator<< (float) = 0; virtual OStream& operator<< (double) = 0; virtual OStream& operator<< (const std::string&) = 0; @@ -55,6 +57,7 @@ namespace I { virtual ~IStream() = default; virtual IStream& operator>> (bool &) = 0; + virtual IStream& operator>> (std::vector::reference) = 0; virtual IStream& operator>> (char &) = 0; virtual IStream& operator>> (unsigned char &) = 0; virtual IStream& operator>> (short &) = 0; @@ -64,6 +67,7 @@ namespace I { virtual IStream& operator>> (double &) = 0; //virtual IStream& operator>> (std::size_t &) = 0; virtual IStream& operator >> (uint32_t &) = 0; + virtual IStream& operator >> (uint64_t &) = 0; virtual IStream& operator>> (std::string &) = 0; }; } // namespace I @@ -217,6 +221,28 @@ GAPI_EXPORTS void serialize( I::OStream& os GAPI_EXPORTS GSerialized deserialize(I::IStream& is); GAPI_EXPORTS void reconstruct(const GSerialized &s, ade::Graph &g); +// Generic: map serialization //////////////////////////////////////// +template +I::OStream& operator<< (I::OStream& os, const std::map &m) { + const uint32_t sz = static_cast(m.size()); // explicitly specify type + os << sz; + for (const auto& it : m) os << it.first << it.second; + return os; +} +template +I::IStream& operator>> (I::IStream& is, std::map &m) { + m.clear(); + uint32_t sz = 0u; + is >> sz; + for (std::size_t i = 0; i < sz; ++i) { + K k{}; + V v{}; + is >> k >> v; + m[k] = v; + } + return is; +} + // Legacy ////////////////////////////////////////////////////////////////////// // Generic: unordered_map serialization //////////////////////////////////////// template @@ -334,6 +360,7 @@ public: virtual I::OStream& operator<< (double) override; virtual I::OStream& operator<< (const std::string&) override; virtual I::OStream& operator<< (uint32_t) override; + virtual I::OStream& operator<< (uint64_t) override; }; class GAPI_EXPORTS ByteMemoryInStream final: public I::IStream { @@ -349,6 +376,7 @@ public: explicit ByteMemoryInStream(const std::vector &data); virtual I::IStream& operator>> (bool &) override; + virtual I::IStream& operator>> (std::vector::reference) override; virtual I::IStream& operator>> (char &) override; virtual I::IStream& operator>> (unsigned char &) override; virtual I::IStream& operator>> (short &) override; @@ -358,6 +386,7 @@ public: virtual I::IStream& operator>> (double &) override; //virtual I::IStream& operator>> (std::size_t &) override; virtual I::IStream& operator >> (uint32_t &) override; + virtual I::IStream& operator >> (uint64_t &) override; virtual I::IStream& operator>> (std::string &) override; }; diff --git a/modules/gapi/test/gapi_array_tests.cpp b/modules/gapi/test/gapi_array_tests.cpp index 2faf538ae9..de8b4f27d2 100644 --- a/modules/gapi/test/gapi_array_tests.cpp +++ b/modules/gapi/test/gapi_array_tests.cpp @@ -240,6 +240,14 @@ TEST(GArray_VectorRef, TestMov) EXPECT_EQ(V{}, vtest); } +namespace { + struct MyTestStruct { + int i; + float f; + std::string name; + }; +} + TEST(GArray_VectorRef, Kind) { cv::detail::VectorRef v1(std::vector{}); @@ -264,7 +272,10 @@ TEST(GArray_VectorRef, Kind) EXPECT_EQ(cv::detail::OpaqueKind::CV_SIZE, v7.getKind()); cv::detail::VectorRef v8(std::vector{}); - EXPECT_EQ(cv::detail::OpaqueKind::CV_UNKNOWN, v8.getKind()); + EXPECT_EQ(cv::detail::OpaqueKind::CV_STRING, v8.getKind()); + + cv::detail::VectorRef v9(std::vector{}); + EXPECT_EQ(cv::detail::OpaqueKind::CV_UNKNOWN, v9.getKind()); } TEST(GArray_VectorRef, TestRvalue) diff --git a/modules/gapi/test/gapi_opaque_tests.cpp b/modules/gapi/test/gapi_opaque_tests.cpp index c76c97ad01..9bbb431052 100644 --- a/modules/gapi/test/gapi_opaque_tests.cpp +++ b/modules/gapi/test/gapi_opaque_tests.cpp @@ -215,6 +215,14 @@ TEST(GOpaque_OpaqueRef, TestMov) EXPECT_NE(test, mov.rref()); // ref lost the data } +namespace { + struct MyTestStruct { + int i; + float f; + std::string name; + }; +} + TEST(GOpaque_OpaqueRef, Kind) { cv::detail::OpaqueRef v1(cv::Rect{}); @@ -233,7 +241,10 @@ TEST(GOpaque_OpaqueRef, Kind) EXPECT_EQ(cv::detail::OpaqueKind::CV_SIZE, v7.getKind()); cv::detail::OpaqueRef v8(std::string{}); - EXPECT_EQ(cv::detail::OpaqueKind::CV_UNKNOWN, v8.getKind()); + EXPECT_EQ(cv::detail::OpaqueKind::CV_STRING, v8.getKind()); + + cv::detail::OpaqueRef v9(MyTestStruct{}); + EXPECT_EQ(cv::detail::OpaqueKind::CV_UNKNOWN, v9.getKind()); } TEST(GOpaque_OpaqueRef, TestReset) diff --git a/modules/gapi/test/s11n/gapi_s11n_tests.cpp b/modules/gapi/test/s11n/gapi_s11n_tests.cpp index 5b5be997b9..5042a346b4 100644 --- a/modules/gapi/test/s11n/gapi_s11n_tests.cpp +++ b/modules/gapi/test/s11n/gapi_s11n_tests.cpp @@ -62,10 +62,78 @@ TEST_F(S11N_Basic, Test_fp64) { EXPECT_EQ(x, get()); } +TEST_F(S11N_Basic, Test_uint64) { + uint64_t x = 2147483647374; + put(x); + EXPECT_EQ(x, get()); +} + +TEST_F(S11N_Basic, Test_int32_pos) { + int32_t x = 2147483647; + put(x); + EXPECT_EQ(x, get()); +} + +TEST_F(S11N_Basic, Test_int32_neg) { + int32_t x = -2147483646; + put(x); + EXPECT_EQ(x, get()); +} + +TEST_F(S11N_Basic, Test_vector_bool) { + std::vector v = {false, true, false}; + put(v); + EXPECT_EQ(v, get>()); +} + +TEST_F(S11N_Basic, Test_map_string2string) { + using T = std::map; + T v; + v["gapi"] = "cool"; + v["42"] = "answer"; + v["hi"] = "hello there"; + put(v); + EXPECT_EQ(v, get()); +} + +TEST_F(S11N_Basic, Test_map_int2int) { + using T = std::map; + T v; + v[1] = 23; + v[-100] = 0; + v[435346] = -12346; + put(v); + EXPECT_EQ(v, get()); +} + +TEST_F(S11N_Basic, Test_map_float2cvsize) { + using T = std::map; + T v; + v[0.4f] = cv::Size(4, 5); + v[234.43f] = cv::Size(3421, 321); + v[2223.f] = cv::Size(1920, 1080); + put(v); + EXPECT_EQ(v, get()); +} + +TEST_F(S11N_Basic, Test_map_uint642cvmat) { + using T = std::map; + T v; + v[21304805324] = cv::Mat(3, 3, CV_8UC1, cv::Scalar::all(3)); + v[4353245222] = cv::Mat(5, 5, CV_8UC3, cv::Scalar::all(7)); + v[0] = cv::Mat(10, 10, CV_32FC2, cv::Scalar::all(-128.f)); + put(v); + auto out_v = get(); + for (const auto& el : out_v) { + EXPECT_NE(v.end(), v.find(el.first)); + EXPECT_EQ(0, cv::norm(el.second, v[el.first])); + } +} + TEST_F(S11N_Basic, Test_vector_int) { std::vector v = {1,2,3}; put(v); - EXPECT_EQ(v, get >()); + EXPECT_EQ(v, get>()); } TEST_F(S11N_Basic, Test_vector_cvSize) { @@ -74,7 +142,7 @@ TEST_F(S11N_Basic, Test_vector_cvSize) { cv::Size(1280, 1024), }; put(v); - EXPECT_EQ(v, get >()); + EXPECT_EQ(v, get>()); } TEST_F(S11N_Basic, Test_vector_string) { @@ -84,13 +152,13 @@ TEST_F(S11N_Basic, Test_vector_string) { "ok!" }; put(v); - EXPECT_EQ(v, get >()); + EXPECT_EQ(v, get>()); } TEST_F(S11N_Basic, Test_vector_empty) { std::vector v; put(v); - EXPECT_EQ(v, get >()); + EXPECT_EQ(v, get>()); } TEST_F(S11N_Basic, Test_variant) { @@ -348,4 +416,58 @@ TEST_F(S11N_Basic, Test_Bind_RunArgs_MatScalar) { i++; } } + +namespace { + template + bool verifyOpaqueKind(T&& in) { + auto inObjs = cv::gin(in); + auto in_o_ref = cv::util::get(inObjs[0]); + return K == in_o_ref.getKind(); + } + + template + bool verifyArrayKind(T&& in) { + auto inObjs = cv::gin(in); + auto in_o_ref = cv::util::get(inObjs[0]); + return K == in_o_ref.getKind(); + } +} + +TEST_F(S11N_Basic, Test_Gin_GOpaque) { + int i; float f; double d; + std::uint64_t ui; bool b; + std::string s; + cv::Rect r; cv::Size sz; + cv::Point p; + EXPECT_TRUE(verifyOpaqueKind(i)); + EXPECT_TRUE(verifyOpaqueKind(f)); + EXPECT_TRUE(verifyOpaqueKind(d)); + EXPECT_TRUE(verifyOpaqueKind(ui)); + EXPECT_TRUE(verifyOpaqueKind(b)); + EXPECT_TRUE(verifyOpaqueKind(s)); + EXPECT_TRUE(verifyOpaqueKind(r)); + EXPECT_TRUE(verifyOpaqueKind(sz)); + EXPECT_TRUE(verifyOpaqueKind(p)); +} + +TEST_F(S11N_Basic, Test_Gin_GArray) { + std::vector i; std::vector f; std::vector d; + std::vector ui; std::vector b; + std::vector s; + std::vector r; std::vector sz; + std::vector p; + std::vector mat; + std::vector sc; + EXPECT_TRUE(verifyArrayKind(i)); + EXPECT_TRUE(verifyArrayKind(f)); + EXPECT_TRUE(verifyArrayKind(d)); + EXPECT_TRUE(verifyArrayKind(ui)); + EXPECT_TRUE(verifyArrayKind(b)); + EXPECT_TRUE(verifyArrayKind(s)); + EXPECT_TRUE(verifyArrayKind(r)); + EXPECT_TRUE(verifyArrayKind(sz)); + EXPECT_TRUE(verifyArrayKind(p)); + EXPECT_TRUE(verifyArrayKind(mat)); + EXPECT_TRUE(verifyArrayKind(sc)); +} } // namespace opencv_test diff --git a/modules/gapi/test/s11n/gapi_sample_pipelines_s11n.cpp b/modules/gapi/test/s11n/gapi_sample_pipelines_s11n.cpp index 1d8f7514ea..885457cd90 100644 --- a/modules/gapi/test/s11n/gapi_sample_pipelines_s11n.cpp +++ b/modules/gapi/test/s11n/gapi_sample_pipelines_s11n.cpp @@ -391,6 +391,52 @@ namespace ThisTest vp[idx] = cv::Point(vi[idx], vi[idx]); } }; + + using GK3Out = std::tuple, cv::GArray>; + G_TYPED_KERNEL_M(OpArrK3, , cv::GArray, cv::GOpaque)>, "test.s11n.oparrk3") + { + static std::tuple outMeta(const GArrayDesc&, const GArrayDesc&, const GOpaqueDesc&) { + return std::make_tuple(empty_array_desc(), empty_array_desc()); + } + }; + + GAPI_OCV_KERNEL(OCVOpArrK3, OpArrK3) + { + static void run(const std::vector& vb, const std::vector& vi_in, const float& f, + std::vector& vui, std::vector& vi) + { + vui.clear(); vui.resize(vi_in.size()); + vi.clear(); vi.resize(vi_in.size()); + + for (std::size_t idx = 0; idx < vi_in.size(); ++ idx) + { + vi[idx] = vb[idx] ? vi_in[idx] : -vi_in[idx]; + vui[idx] = vb[idx] ? static_cast(vi_in[idx] * f) : + static_cast(vi_in[idx] / f); + } + } + }; + + using GK4Out = std::tuple, cv::GArray>; + G_TYPED_KERNEL_M(OpArrK4, , cv::GOpaque)>, "test.s11n.oparrk4") + { + static std::tuple outMeta(const GOpaqueDesc&, const GOpaqueDesc&) { + return std::make_tuple(empty_gopaque_desc(), empty_array_desc()); + } + }; + + GAPI_OCV_KERNEL(OCVOpArrK4, OpArrK4) + { + static void run(const bool& b, const std::string& s, + int& i, std::vector& vs) + { + vs.clear(); + vs.resize(2); + i = b ? 42 : 24; + auto s_copy = s + " world"; + vs = std::vector{s_copy, s_copy}; + } + }; } // namespace ThisTest TEST(S11N, Pipeline_GOpaque) @@ -485,6 +531,59 @@ TEST(S11N, Pipeline_GArray_GOpaque_Multinode) } } +TEST(S11N, Pipeline_GArray_GOpaque_2) +{ + using namespace ThisTest; + + cv::GArray in1; + cv::GArray in2; + cv::GOpaque in3; + auto out = OpArrK3::on(in1, in2, in3); + cv::GComputation c(cv::GIn(in1, in2, in3), + cv::GOut(std::get<0>(out), std::get<1>(out))); + + auto p = cv::gapi::serialize(c); + auto dc = cv::gapi::deserialize(p); + + std::vector b {true, false, false}; + std::vector i {234324, -234252, 999}; + float f = 0.85f; + std::vector out_i; + std::vector out_ui; + dc.apply(cv::gin(b, i, f), cv::gout(out_ui, out_i), cv::compile_args(cv::gapi::kernels())); + + for (std::size_t idx = 0; idx < b.size(); ++idx) + { + EXPECT_EQ(out_i[idx], b[idx] ? i[idx] : -i[idx]); + EXPECT_EQ(out_ui[idx], b[idx] ? static_cast(i[idx] * f) : + static_cast(i[idx] / f)); + } +} + +TEST(S11N, Pipeline_GArray_GOpaque_3) +{ + using namespace ThisTest; + + cv::GOpaque in1; + cv::GOpaque in2; + auto out = OpArrK4::on(in1, in2); + cv::GComputation c(cv::GIn(in1, in2), + cv::GOut(std::get<0>(out), std::get<1>(out))); + + auto p = cv::gapi::serialize(c); + auto dc = cv::gapi::deserialize(p); + + bool b = false; + std::string s("hello"); + int i = 0; + std::vector vs{}; + dc.apply(cv::gin(b, s), cv::gout(i, vs), cv::compile_args(cv::gapi::kernels())); + + EXPECT_EQ(24, i); + std::vector vs_ref{"hello world", "hello world"}; + EXPECT_EQ(vs_ref, vs); +} + TEST(S11N, Pipeline_Render_NV12) { cv::Size sz (100, 200);