Merge pull request #18292 from smirnov-alexey:as/osd_serialization

[G-API]: Support render primitives serialization

* Add GOpaque and GArray serialization support

* Address review comments

* Remove holds() method

* Add serialization mechanism for render primitives

* Fix standalone mode

* Fix wchar_t error on win64

* Fix assert on windows

* Address review comments

* Fix GArray and GOpaque reset() method to store proper kind

* Reset wchar before deserializing it

* Fix wchar_t cross-platform issue

* Address review comments

* Fix wchar_t serialization and tests

* Remove FText serialization
pull/18384/head
Alexey Smirnov 4 years ago committed by GitHub
parent f52a2cf5e1
commit f6aa9ac304
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      modules/gapi/include/opencv2/gapi/garray.hpp
  2. 8
      modules/gapi/include/opencv2/gapi/gcommon.hpp
  3. 2
      modules/gapi/include/opencv2/gapi/gopaque.hpp
  4. 311
      modules/gapi/include/opencv2/gapi/render/render.hpp
  5. 347
      modules/gapi/include/opencv2/gapi/render/render_types.hpp
  6. 56
      modules/gapi/src/backends/common/serialization.cpp
  7. 23
      modules/gapi/src/backends/common/serialization.hpp
  8. 9
      modules/gapi/test/gapi_array_tests.cpp
  9. 9
      modules/gapi/test/gapi_opaque_tests.cpp
  10. 1
      modules/gapi/test/s11n/gapi_s11n_tests.cpp
  11. 225
      modules/gapi/test/s11n/gapi_sample_pipelines_s11n.cpp

@ -261,8 +261,8 @@ namespace detail
template<typename T> void reset() template<typename T> void reset()
{ {
if (!m_ref) m_ref.reset(new VectorRefT<T>()); if (!m_ref) m_ref.reset(new VectorRefT<T>());
check<T>(); check<T>();
storeKind<T>();
static_cast<VectorRefT<T>&>(*m_ref).reset(); static_cast<VectorRefT<T>&>(*m_ref).reset();
} }

@ -18,6 +18,7 @@
#include <opencv2/gapi/util/optional.hpp> #include <opencv2/gapi/util/optional.hpp>
#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>
namespace cv { namespace cv {
@ -48,6 +49,7 @@ namespace detail
CV_RECT, // cv::Rect user G-API data CV_RECT, // cv::Rect user G-API data
CV_SCALAR, // cv::Scalar user G-API data CV_SCALAR, // cv::Scalar user G-API data
CV_MAT, // cv::Mat user G-API data CV_MAT, // cv::Mat user G-API data
CV_PRIM, // cv::gapi::wip::draw::Prim user G-API data
}; };
// Type traits helper which simplifies the extraction of kind from type // Type traits helper which simplifies the extraction of kind from type
@ -62,10 +64,12 @@ namespace detail
template<> struct GOpaqueTraits<cv::Mat> { static constexpr const OpaqueKind kind = OpaqueKind::CV_MAT; }; template<> struct GOpaqueTraits<cv::Mat> { static constexpr const OpaqueKind kind = OpaqueKind::CV_MAT; };
template<> struct GOpaqueTraits<cv::Rect> { static constexpr const OpaqueKind kind = OpaqueKind::CV_RECT; }; template<> struct GOpaqueTraits<cv::Rect> { static constexpr const OpaqueKind kind = OpaqueKind::CV_RECT; };
template<> struct GOpaqueTraits<cv::GMat> { static constexpr const OpaqueKind kind = OpaqueKind::CV_MAT; }; template<> struct GOpaqueTraits<cv::GMat> { static constexpr const OpaqueKind kind = OpaqueKind::CV_MAT; };
template<> struct GOpaqueTraits<cv::gapi::wip::draw::Prim>
{ static constexpr const OpaqueKind kind = OpaqueKind::CV_PRIM; };
// GArray is not supporting bool type for now due to difference in std::vector<bool> implementation // GArray is not supporting bool type for now due to difference in std::vector<bool> implementation
using GOpaqueTraitsArrayTypes = std::tuple<int, double, cv::Size, cv::Scalar, cv::Point, cv::Mat, cv::Rect>; using GOpaqueTraitsArrayTypes = std::tuple<int, double, cv::Size, cv::Scalar, cv::Point, cv::Mat, cv::Rect, cv::gapi::wip::draw::Prim>;
// GOpaque is not supporting cv::Mat and cv::Scalar since there are GScalar and GMat types // GOpaque is not supporting cv::Mat and cv::Scalar since there are GScalar and GMat types
using GOpaqueTraitsOpaqueTypes = std::tuple<bool, int, double, cv::Size, cv::Point, cv::Rect>; using GOpaqueTraitsOpaqueTypes = std::tuple<bool, int, double, cv::Size, cv::Point, cv::Rect, cv::gapi::wip::draw::Prim>;
} // namespace detail } // namespace detail
// This definition is here because it is reused by both public(?) and internal // This definition is here because it is reused by both public(?) and internal

@ -250,8 +250,8 @@ namespace detail
template<typename T> void reset() template<typename T> void reset()
{ {
if (!m_ref) m_ref.reset(new OpaqueRefT<T>()); if (!m_ref) m_ref.reset(new OpaqueRefT<T>());
check<T>(); check<T>();
storeKind<T>();
static_cast<OpaqueRefT<T>&>(*m_ref).reset(); static_cast<OpaqueRefT<T>&>(*m_ref).reset();
} }

@ -2,23 +2,16 @@
// It is subject to the license terms in the LICENSE file found in the top-level directory // 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. // of this distribution and at http://opencv.org/license.html.
// //
// Copyright (C) 2018-2019 Intel Corporation // Copyright (C) 2018-2020 Intel Corporation
#ifndef OPENCV_GAPI_RENDER_HPP #ifndef OPENCV_GAPI_RENDER_HPP
#define OPENCV_GAPI_RENDER_HPP #define OPENCV_GAPI_RENDER_HPP
#include <string> #include <opencv2/gapi/render/render_types.hpp>
#include <vector>
#include <opencv2/imgproc.hpp>
#include <opencv2/gapi.hpp> #include <opencv2/gapi.hpp>
#include <opencv2/gapi/opencv_includes.hpp>
#include <opencv2/gapi/util/variant.hpp>
#include <opencv2/gapi/own/exports.hpp>
/** \defgroup gapi_draw G-API Drawing and composition functionality /** \defgroup gapi_draw G-API Drawing and composition functionality
* @{ * @{
* *
@ -77,309 +70,9 @@ namespace wip
namespace draw namespace draw
{ {
/**
* @brief This structure specifies which FreeType font to use by FText primitives.
*/
struct freetype_font
{
/*@{*/
std::string path; //!< The path to the font file (.ttf)
/*@{*/
};
//! @addtogroup gapi_draw_prims
//! @{
/**
* @brief This structure represents a text string to draw.
*
* Parameters match cv::putText().
*/
struct Text
{
/**
* @brief Text constructor
*
* @param text_ The text string to be drawn
* @param org_ The bottom-left corner of the text string in the image
* @param ff_ The font type, see #HersheyFonts
* @param fs_ The font scale factor that is multiplied by the font-specific base size
* @param color_ The text color
* @param thick_ The thickness of the lines used to draw a text
* @param lt_ The line type. See #LineTypes
* @param bottom_left_origin_ When true, the image data origin is at the bottom-left corner. Otherwise, it is at the top-left corner
*/
Text(const std::string& text_,
const cv::Point& org_,
int ff_,
double fs_,
const cv::Scalar& color_,
int thick_ = 1,
int lt_ = cv::LINE_8,
bool bottom_left_origin_ = false) :
text(text_), org(org_), ff(ff_), fs(fs_),
color(color_), thick(thick_), lt(lt_), bottom_left_origin(bottom_left_origin_)
{
}
/*@{*/
std::string text; //!< The text string to be drawn
cv::Point org; //!< The bottom-left corner of the text string in the image
int ff; //!< The font type, see #HersheyFonts
double fs; //!< The font scale factor that is multiplied by the font-specific base size
cv::Scalar color; //!< The text color
int thick; //!< The thickness of the lines used to draw a text
int lt; //!< The line type. See #LineTypes
bool bottom_left_origin; //!< When true, the image data origin is at the bottom-left corner. Otherwise, it is at the top-left corner
/*@{*/
};
/**
* @brief This structure represents a text string to draw using
* FreeType renderer.
*
* If OpenCV is built without FreeType support, this primitive will
* fail at the execution stage.
*/
struct FText
{
/**
* @brief FText constructor
*
* @param text_ The text string to be drawn
* @param org_ The bottom-left corner of the text string in the image
* @param fh_ The height of text
* @param color_ The text color
*/
FText(const std::wstring& text_,
const cv::Point& org_,
int fh_,
const cv::Scalar& color_) :
text(text_), org(org_), fh(fh_), color(color_)
{
}
/*@{*/
std::wstring text; //!< The text string to be drawn
cv::Point org; //!< The bottom-left corner of the text string in the image
int fh; //!< The height of text
cv::Scalar color; //!< The text color
/*@{*/
};
/**
* @brief This structure represents a rectangle to draw.
*
* Parameters match cv::rectangle().
*/
struct Rect
{
/**
* @brief Rect constructor
*
* @param rect_ Coordinates of the rectangle
* @param color_ The bottom-left corner of the text string in the image
* @param thick_ The thickness of lines that make up the rectangle. Negative values, like #FILLED, mean that the function has to draw a filled rectangle
* @param lt_ The type of the line. See #LineTypes
* @param shift_ The number of fractional bits in the point coordinates
*/
Rect(const cv::Rect& rect_,
const cv::Scalar& color_,
int thick_ = 1,
int lt_ = cv::LINE_8,
int shift_ = 0) :
rect(rect_), color(color_), thick(thick_), lt(lt_), shift(shift_)
{
}
/*@{*/
cv::Rect rect; //!< Coordinates of the rectangle
cv::Scalar color; //!< The rectangle color or brightness (grayscale image)
int thick; //!< The thickness of lines that make up the rectangle. Negative values, like #FILLED, mean that the function has to draw a filled rectangle
int lt; //!< The type of the line. See #LineTypes
int shift; //!< The number of fractional bits in the point coordinates
/*@{*/
};
/**
* @brief This structure represents a circle to draw.
*
* Parameters match cv::circle().
*/
struct Circle
{
/**
* @brief Circle constructor
*
* @param center_ The center of the circle
* @param radius_ The radius of the circle
* @param color_ The color of the circle
* @param thick_ The thickness of the circle outline, if positive. Negative values, like #FILLED, mean that a filled circle is to be drawn
* @param lt_ The Type of the circle boundary. See #LineTypes
* @param shift_ The Number of fractional bits in the coordinates of the center and in the radius value
*/
Circle(const cv::Point& center_,
int radius_,
const cv::Scalar& color_,
int thick_ = 1,
int lt_ = cv::LINE_8,
int shift_ = 0) :
center(center_), radius(radius_), color(color_), thick(thick_), lt(lt_), shift(shift_)
{
}
/*@{*/
cv::Point center; //!< The center of the circle
int radius; //!< The radius of the circle
cv::Scalar color; //!< The color of the circle
int thick; //!< The thickness of the circle outline, if positive. Negative values, like #FILLED, mean that a filled circle is to be drawn
int lt; //!< The Type of the circle boundary. See #LineTypes
int shift; //!< The Number of fractional bits in the coordinates of the center and in the radius value
/*@{*/
};
/**
* @brief This structure represents a line to draw.
*
* Parameters match cv::line().
*/
struct Line
{
/**
* @brief Line constructor
*
* @param pt1_ The first point of the line segment
* @param pt2_ The second point of the line segment
* @param color_ The line color
* @param thick_ The thickness of line
* @param lt_ The Type of the line. See #LineTypes
* @param shift_ The number of fractional bits in the point coordinates
*/
Line(const cv::Point& pt1_,
const cv::Point& pt2_,
const cv::Scalar& color_,
int thick_ = 1,
int lt_ = cv::LINE_8,
int shift_ = 0) :
pt1(pt1_), pt2(pt2_), color(color_), thick(thick_), lt(lt_), shift(shift_)
{
}
/*@{*/
cv::Point pt1; //!< The first point of the line segment
cv::Point pt2; //!< The second point of the line segment
cv::Scalar color; //!< The line color
int thick; //!< The thickness of line
int lt; //!< The Type of the line. See #LineTypes
int shift; //!< The number of fractional bits in the point coordinates
/*@{*/
};
/**
* @brief This structure represents a mosaicing operation.
*
* Mosaicing is a very basic method to obfuscate regions in the image.
*/
struct Mosaic
{
/**
* @brief Mosaic constructor
*
* @param mos_ Coordinates of the mosaic
* @param cellSz_ Cell size (same for X, Y)
* @param decim_ Decimation (0 stands for no decimation)
*/
Mosaic(const cv::Rect& mos_,
int cellSz_,
int decim_) :
mos(mos_), cellSz(cellSz_), decim(decim_)
{
}
/*@{*/
cv::Rect mos; //!< Coordinates of the mosaic
int cellSz; //!< Cell size (same for X, Y)
int decim; //!< Decimation (0 stands for no decimation)
/*@{*/
};
/**
* @brief This structure represents an image to draw.
*
* Image is blended on a frame using the specified mask.
*/
struct Image
{
/**
* @brief Mosaic constructor
*
* @param org_ The bottom-left corner of the image
* @param img_ Image to draw
* @param alpha_ Alpha channel for image to draw (same size and number of channels)
*/
Image(const cv::Point& org_,
const cv::Mat& img_,
const cv::Mat& alpha_) :
org(org_), img(img_), alpha(alpha_)
{
}
/*@{*/
cv::Point org; //!< The bottom-left corner of the image
cv::Mat img; //!< Image to draw
cv::Mat alpha; //!< Alpha channel for image to draw (same size and number of channels)
/*@{*/
};
/**
* @brief This structure represents a polygon to draw.
*/
struct Poly
{
/**
* @brief Mosaic constructor
*
* @param points_ Points to connect
* @param color_ The line color
* @param thick_ The thickness of line
* @param lt_ The Type of the line. See #LineTypes
* @param shift_ The number of fractional bits in the point coordinate
*/
Poly(const std::vector<cv::Point>& points_,
const cv::Scalar& color_,
int thick_ = 1,
int lt_ = cv::LINE_8,
int shift_ = 0) :
points(points_), color(color_), thick(thick_), lt(lt_), shift(shift_)
{
}
/*@{*/
std::vector<cv::Point> points; //!< Points to connect
cv::Scalar color; //!< The line color
int thick; //!< The thickness of line
int lt; //!< The Type of the line. See #LineTypes
int shift; //!< The number of fractional bits in the point coordinate
/*@{*/
};
using Prim = util::variant
< Text
, FText
, Rect
, Circle
, Line
, Mosaic
, Image
, Poly
>;
using Prims = std::vector<Prim>;
//! @} gapi_draw_prims
using GMat2 = std::tuple<cv::GMat,cv::GMat>; using GMat2 = std::tuple<cv::GMat,cv::GMat>;
using GMatDesc2 = std::tuple<cv::GMatDesc,cv::GMatDesc>; using GMatDesc2 = std::tuple<cv::GMatDesc,cv::GMatDesc>;
//! @addtogroup gapi_draw_api //! @addtogroup gapi_draw_api
//! @{ //! @{
/** @brief The function renders on the input image passed drawing primitivies /** @brief The function renders on the input image passed drawing primitivies

@ -0,0 +1,347 @@
// 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_RENDER_TYPES_HPP
#define OPENCV_GAPI_RENDER_TYPES_HPP
#include <string>
#include <vector>
#include <opencv2/gapi/opencv_includes.hpp>
#include <opencv2/gapi/util/variant.hpp>
#include <opencv2/gapi/own/exports.hpp>
namespace cv
{
namespace gapi
{
namespace wip
{
namespace draw
{
/**
* @brief This structure specifies which FreeType font to use by FText primitives.
*/
struct freetype_font
{
/*@{*/
std::string path; //!< The path to the font file (.ttf)
/*@{*/
};
//! @addtogroup gapi_draw_prims
//! @{
/**
* @brief This structure represents a text string to draw.
*
* Parameters match cv::putText().
*/
struct Text
{
/**
* @brief Text constructor
*
* @param text_ The text string to be drawn
* @param org_ The bottom-left corner of the text string in the image
* @param ff_ The font type, see #HersheyFonts
* @param fs_ The font scale factor that is multiplied by the font-specific base size
* @param color_ The text color
* @param thick_ The thickness of the lines used to draw a text
* @param lt_ The line type. See #LineTypes
* @param bottom_left_origin_ When true, the image data origin is at the bottom-left corner. Otherwise, it is at the top-left corner
*/
Text(const std::string& text_,
const cv::Point& org_,
int ff_,
double fs_,
const cv::Scalar& color_,
int thick_ = 1,
int lt_ = 8,
bool bottom_left_origin_ = false) :
text(text_), org(org_), ff(ff_), fs(fs_),
color(color_), thick(thick_), lt(lt_), bottom_left_origin(bottom_left_origin_)
{
}
Text() = default;
/*@{*/
std::string text; //!< The text string to be drawn
cv::Point org; //!< The bottom-left corner of the text string in the image
int ff; //!< The font type, see #HersheyFonts
double fs; //!< The font scale factor that is multiplied by the font-specific base size
cv::Scalar color; //!< The text color
int thick; //!< The thickness of the lines used to draw a text
int lt; //!< The line type. See #LineTypes
bool bottom_left_origin; //!< When true, the image data origin is at the bottom-left corner. Otherwise, it is at the top-left corner
/*@{*/
};
/**
* @brief This structure represents a text string to draw using
* FreeType renderer.
*
* If OpenCV is built without FreeType support, this primitive will
* fail at the execution stage.
*/
struct FText
{
/**
* @brief FText constructor
*
* @param text_ The text string to be drawn
* @param org_ The bottom-left corner of the text string in the image
* @param fh_ The height of text
* @param color_ The text color
*/
FText(const std::wstring& text_,
const cv::Point& org_,
int fh_,
const cv::Scalar& color_) :
text(text_), org(org_), fh(fh_), color(color_)
{
}
FText() = default;
/*@{*/
std::wstring text; //!< The text string to be drawn
cv::Point org; //!< The bottom-left corner of the text string in the image
int fh; //!< The height of text
cv::Scalar color; //!< The text color
/*@{*/
};
/**
* @brief This structure represents a rectangle to draw.
*
* Parameters match cv::rectangle().
*/
struct Rect
{
/**
* @brief Rect constructor
*
* @param rect_ Coordinates of the rectangle
* @param color_ The bottom-left corner of the text string in the image
* @param thick_ The thickness of lines that make up the rectangle. Negative values, like #FILLED, mean that the function has to draw a filled rectangle
* @param lt_ The type of the line. See #LineTypes
* @param shift_ The number of fractional bits in the point coordinates
*/
Rect(const cv::Rect& rect_,
const cv::Scalar& color_,
int thick_ = 1,
int lt_ = 8,
int shift_ = 0) :
rect(rect_), color(color_), thick(thick_), lt(lt_), shift(shift_)
{
}
Rect() = default;
/*@{*/
cv::Rect rect; //!< Coordinates of the rectangle
cv::Scalar color; //!< The rectangle color or brightness (grayscale image)
int thick; //!< The thickness of lines that make up the rectangle. Negative values, like #FILLED, mean that the function has to draw a filled rectangle
int lt; //!< The type of the line. See #LineTypes
int shift; //!< The number of fractional bits in the point coordinates
/*@{*/
};
/**
* @brief This structure represents a circle to draw.
*
* Parameters match cv::circle().
*/
struct Circle
{
/**
* @brief Circle constructor
*
* @param center_ The center of the circle
* @param radius_ The radius of the circle
* @param color_ The color of the circle
* @param thick_ The thickness of the circle outline, if positive. Negative values, like #FILLED, mean that a filled circle is to be drawn
* @param lt_ The Type of the circle boundary. See #LineTypes
* @param shift_ The Number of fractional bits in the coordinates of the center and in the radius value
*/
Circle(const cv::Point& center_,
int radius_,
const cv::Scalar& color_,
int thick_ = 1,
int lt_ = 8,
int shift_ = 0) :
center(center_), radius(radius_), color(color_), thick(thick_), lt(lt_), shift(shift_)
{
}
Circle() = default;
/*@{*/
cv::Point center; //!< The center of the circle
int radius; //!< The radius of the circle
cv::Scalar color; //!< The color of the circle
int thick; //!< The thickness of the circle outline, if positive. Negative values, like #FILLED, mean that a filled circle is to be drawn
int lt; //!< The Type of the circle boundary. See #LineTypes
int shift; //!< The Number of fractional bits in the coordinates of the center and in the radius value
/*@{*/
};
/**
* @brief This structure represents a line to draw.
*
* Parameters match cv::line().
*/
struct Line
{
/**
* @brief Line constructor
*
* @param pt1_ The first point of the line segment
* @param pt2_ The second point of the line segment
* @param color_ The line color
* @param thick_ The thickness of line
* @param lt_ The Type of the line. See #LineTypes
* @param shift_ The number of fractional bits in the point coordinates
*/
Line(const cv::Point& pt1_,
const cv::Point& pt2_,
const cv::Scalar& color_,
int thick_ = 1,
int lt_ = 8,
int shift_ = 0) :
pt1(pt1_), pt2(pt2_), color(color_), thick(thick_), lt(lt_), shift(shift_)
{
}
Line() = default;
/*@{*/
cv::Point pt1; //!< The first point of the line segment
cv::Point pt2; //!< The second point of the line segment
cv::Scalar color; //!< The line color
int thick; //!< The thickness of line
int lt; //!< The Type of the line. See #LineTypes
int shift; //!< The number of fractional bits in the point coordinates
/*@{*/
};
/**
* @brief This structure represents a mosaicing operation.
*
* Mosaicing is a very basic method to obfuscate regions in the image.
*/
struct Mosaic
{
/**
* @brief Mosaic constructor
*
* @param mos_ Coordinates of the mosaic
* @param cellSz_ Cell size (same for X, Y)
* @param decim_ Decimation (0 stands for no decimation)
*/
Mosaic(const cv::Rect& mos_,
int cellSz_,
int decim_) :
mos(mos_), cellSz(cellSz_), decim(decim_)
{
}
Mosaic() = default;
/*@{*/
cv::Rect mos; //!< Coordinates of the mosaic
int cellSz; //!< Cell size (same for X, Y)
int decim; //!< Decimation (0 stands for no decimation)
/*@{*/
};
/**
* @brief This structure represents an image to draw.
*
* Image is blended on a frame using the specified mask.
*/
struct Image
{
/**
* @brief Mosaic constructor
*
* @param org_ The bottom-left corner of the image
* @param img_ Image to draw
* @param alpha_ Alpha channel for image to draw (same size and number of channels)
*/
Image(const cv::Point& org_,
const cv::Mat& img_,
const cv::Mat& alpha_) :
org(org_), img(img_), alpha(alpha_)
{
}
Image() = default;
/*@{*/
cv::Point org; //!< The bottom-left corner of the image
cv::Mat img; //!< Image to draw
cv::Mat alpha; //!< Alpha channel for image to draw (same size and number of channels)
/*@{*/
};
/**
* @brief This structure represents a polygon to draw.
*/
struct Poly
{
/**
* @brief Mosaic constructor
*
* @param points_ Points to connect
* @param color_ The line color
* @param thick_ The thickness of line
* @param lt_ The Type of the line. See #LineTypes
* @param shift_ The number of fractional bits in the point coordinate
*/
Poly(const std::vector<cv::Point>& points_,
const cv::Scalar& color_,
int thick_ = 1,
int lt_ = 8,
int shift_ = 0) :
points(points_), color(color_), thick(thick_), lt(lt_), shift(shift_)
{
}
Poly() = default;
/*@{*/
std::vector<cv::Point> points; //!< Points to connect
cv::Scalar color; //!< The line color
int thick; //!< The thickness of line
int lt; //!< The Type of the line. See #LineTypes
int shift; //!< The number of fractional bits in the point coordinate
/*@{*/
};
using Prim = util::variant
< Text
, FText
, Rect
, Circle
, Line
, Mosaic
, Image
, Poly
>;
using Prims = std::vector<Prim>;
//! @} gapi_draw_prims
} // namespace draw
} // namespace wip
} // namespace gapi
} // namespace cv
#endif // OPENCV_GAPI_RENDER_TYPES_HPP

@ -252,6 +252,62 @@ I::IStream& operator>> (I::IStream& is, cv::Mat& m) {
return is; return is;
} }
I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Text &t) {
return os << t.bottom_left_origin << t.color << t.ff << t.fs << t.lt << t.org << t.text << t.thick;
}
I::IStream& operator>> (I::IStream& is, cv::gapi::wip::draw::Text &t) {
return is >> t.bottom_left_origin >> t.color >> t.ff >> t.fs >> t.lt >> t.org >> t.text >> t.thick;
}
I::OStream& operator<< (I::OStream&, const cv::gapi::wip::draw::FText &) {
GAPI_Assert(false && "Serialization: Unsupported << for FText");
}
I::IStream& operator>> (I::IStream&, cv::gapi::wip::draw::FText &) {
GAPI_Assert(false && "Serialization: Unsupported >> for FText");
}
I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Circle &c) {
return os << c.center << c.color << c.lt << c.radius << c.shift << c.thick;
}
I::IStream& operator>> (I::IStream& is, cv::gapi::wip::draw::Circle &c) {
return is >> c.center >> c.color >> c.lt >> c.radius >> c.shift >> c.thick;
}
I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Rect &r) {
return os << r.color << r.lt << r.rect << r.shift << r.thick;
}
I::IStream& operator>> (I::IStream& is, cv::gapi::wip::draw::Rect &r) {
return is >> r.color >> r.lt >> r.rect >> r.shift >> r.thick;
}
I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Image &i) {
return os << i.org << i.alpha << i.img;
}
I::IStream& operator>> (I::IStream& is, cv::gapi::wip::draw::Image &i) {
return is >> i.org >> i.alpha >> i.img;
}
I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Mosaic &m) {
return os << m.cellSz << m.decim << m.mos;
}
I::IStream& operator>> (I::IStream& is, cv::gapi::wip::draw::Mosaic &m) {
return is >> m.cellSz >> m.decim >> m.mos;
}
I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Poly &p) {
return os << p.color << p.lt << p.points << p.shift << p.thick;
}
I::IStream& operator>> (I::IStream& is, cv::gapi::wip::draw::Poly &p) {
return is >> p.color >> p.lt >> p.points >> p.shift >> p.thick;
}
I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Line &l) {
return os << l.color << l.lt << l.pt1 << l.pt2 << l.shift << l.thick;
}
I::IStream& operator>> (I::IStream& is, cv::gapi::wip::draw::Line &l) {
return is >> l.color >> l.lt >> l.pt1 >> l.pt2 >> l.shift >> l.thick;
}
// G-API types ///////////////////////////////////////////////////////////////// // G-API types /////////////////////////////////////////////////////////////////
// Stubs (empty types) // Stubs (empty types)

@ -14,6 +14,7 @@
#include <ade/util/iota_range.hpp> // used in the vector<</>> #include <ade/util/iota_range.hpp> // used in the vector<</>>
#include "compiler/gmodel.hpp" #include "compiler/gmodel.hpp"
#include "opencv2/gapi/render/render_types.hpp"
#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER #if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
#pragma warning(disable: 4702) #pragma warning(disable: 4702)
@ -89,7 +90,29 @@ GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::Scalar &s);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::Mat &m); GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::Mat &m);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::Mat &m); GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::Mat &m);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Text &t);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::gapi::wip::draw::Text &t);
GAPI_EXPORTS I::OStream& operator<< (I::OStream&, const cv::gapi::wip::draw::FText &);
GAPI_EXPORTS I::IStream& operator>> (I::IStream&, cv::gapi::wip::draw::FText &);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Circle &c);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::gapi::wip::draw::Circle &c);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Rect &r);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::gapi::wip::draw::Rect &r);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Image &i);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::gapi::wip::draw::Image &i);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Mosaic &m);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::gapi::wip::draw::Mosaic &m);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Poly &p);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::gapi::wip::draw::Poly &p);
GAPI_EXPORTS I::OStream& operator<< (I::OStream& os, const cv::gapi::wip::draw::Line &l);
GAPI_EXPORTS I::IStream& operator>> (I::IStream& is, cv::gapi::wip::draw::Line &l);
// G-API types ///////////////////////////////////////////////////////////////// // G-API types /////////////////////////////////////////////////////////////////

@ -274,4 +274,13 @@ TEST(GArray_VectorRef, TestRvalue)
auto v = std::vector<int>{3, 5, -4}; auto v = std::vector<int>{3, 5, -4};
EXPECT_EQ(vref.rref<int>(), v); EXPECT_EQ(vref.rref<int>(), v);
} }
TEST(GArray_VectorRef, TestReset)
{
// Warning: this test is testing some not-very-public APIs
cv::detail::VectorRef vref(std::vector<int>{3, 5, -4});
EXPECT_EQ(cv::detail::OpaqueKind::CV_INT, vref.getKind());
vref.reset<int>();
EXPECT_EQ(cv::detail::OpaqueKind::CV_INT, vref.getKind());
}
} // namespace opencv_test } // namespace opencv_test

@ -235,4 +235,13 @@ TEST(GOpaque_OpaqueRef, Kind)
cv::detail::OpaqueRef v8(std::string{}); cv::detail::OpaqueRef v8(std::string{});
EXPECT_EQ(cv::detail::OpaqueKind::CV_UNKNOWN, v8.getKind()); EXPECT_EQ(cv::detail::OpaqueKind::CV_UNKNOWN, v8.getKind());
} }
TEST(GOpaque_OpaqueRef, TestReset)
{
// Warning: this test is testing some not-very-public APIs
cv::detail::OpaqueRef opref(int{42});
EXPECT_EQ(cv::detail::OpaqueKind::CV_INT, opref.getKind());
opref.reset<int>();
EXPECT_EQ(cv::detail::OpaqueKind::CV_INT, opref.getKind());
}
} // namespace opencv_test } // namespace opencv_test

@ -348,5 +348,4 @@ TEST_F(S11N_Basic, Test_Bind_RunArgs_MatScalar) {
i++; i++;
} }
} }
} // namespace opencv_test } // namespace opencv_test

@ -8,8 +8,9 @@
#include "../test_precomp.hpp" #include "../test_precomp.hpp"
#include <ade/util/iota_range.hpp> #include <ade/util/iota_range.hpp>
#include <opencv2/gapi/s11n.hpp> #include <opencv2/gapi/s11n.hpp>
#include "api/render_priv.hpp"
#include "../common/gapi_render_tests.hpp"
namespace opencv_test namespace opencv_test
{ {
@ -484,4 +485,226 @@ TEST(S11N, Pipeline_GArray_GOpaque_Multinode)
} }
} }
TEST(S11N, Pipeline_Render_NV12)
{
cv::Size sz (100, 200);
int rects_num = 10;
int text_num = 10;
int image_num = 10;
int thick = 2;
int lt = LINE_8;
cv::Scalar color(111, 222, 77);
// G-API code //////////////////////////////////////////////////////////////
cv::gapi::wip::draw::Prims prims;
// Rects
int shift = 0;
for (int i = 0; i < rects_num; ++i) {
cv::Rect rect(200 + i, 200 + i, 200, 200);
prims.emplace_back(cv::gapi::wip::draw::Rect(rect, color, thick, lt, shift));
}
// Mosaic
int cellsz = 50;
int decim = 0;
for (int i = 0; i < rects_num; ++i) {
cv::Rect mos(200 + i, 200 + i, 200, 200);
prims.emplace_back(cv::gapi::wip::draw::Mosaic(mos, cellsz, decim));
}
// Text
std::string text = "Some text";
int ff = FONT_HERSHEY_SIMPLEX;
double fs = 2.0;
bool blo = false;
for (int i = 0; i < text_num; ++i) {
cv::Point org(200 + i, 200 + i);
prims.emplace_back(cv::gapi::wip::draw::Text(text, org, ff, fs, color, thick, lt, blo));
}
// Image
double transparency = 1.0;
cv::Rect rect_img(0 ,0 , 50, 50);
cv::Mat img(rect_img.size(), CV_8UC3, color);
cv::Mat alpha(rect_img.size(), CV_32FC1, transparency);
auto tl = rect_img.tl();
for (int i = 0; i < image_num; ++i) {
cv::Point org_img = {tl.x + i, tl.y + rect_img.size().height + i};
prims.emplace_back(cv::gapi::wip::draw::Image({org_img, img, alpha}));
}
// Circle
cv::Point center(300, 400);
int rad = 25;
prims.emplace_back(cv::gapi::wip::draw::Circle({center, rad, color, thick, lt, shift}));
// Line
cv::Point point_next(300, 425);
prims.emplace_back(cv::gapi::wip::draw::Line({center, point_next, color, thick, lt, shift}));
// Poly
std::vector<cv::Point> points = {{300, 400}, {290, 450}, {348, 410}, {300, 400}};
prims.emplace_back(cv::gapi::wip::draw::Poly({points, color, thick, lt, shift}));
cv::GMat y_in, uv_in, y_out, uv_out;
cv::GArray<cv::gapi::wip::draw::Prim> arr;
std::tie(y_out, uv_out) = cv::gapi::wip::draw::renderNV12(y_in, uv_in, arr);
cv::GComputation comp(cv::GIn(y_in, uv_in, arr), cv::GOut(y_out, uv_out));
auto serialized = cv::gapi::serialize(comp);
auto dc = cv::gapi::deserialize<cv::GComputation>(serialized);
cv::Mat y(1920, 1080, CV_8UC1);
cv::Mat uv(960, 540, CV_8UC2);
cv::randu(y, cv::Scalar(0), cv::Scalar(255));
cv::randu(uv, cv::Scalar::all(0), cv::Scalar::all(255));
cv::Mat y_ref_mat = y.clone(), uv_ref_mat = uv.clone();
dc.apply(cv::gin(y, uv, prims), cv::gout(y, uv));
// OpenCV code //////////////////////////////////////////////////////////////
cv::Mat yuv;
cv::gapi::wip::draw::cvtNV12ToYUV(y_ref_mat, uv_ref_mat, yuv);
for (int i = 0; i < rects_num; ++i) {
cv::Rect rect(200 + i, 200 + i, 200, 200);
cv::rectangle(yuv, rect, cvtBGRToYUVC(color), thick, lt, shift);
}
for (int i = 0; i < rects_num; ++i) {
cv::Rect mos(200 + i, 200 + i, 200, 200);
drawMosaicRef(yuv, mos, cellsz);
}
for (int i = 0; i < text_num; ++i) {
cv::Point org(200 + i, 200 + i);
cv::putText(yuv, text, org, ff, fs, cvtBGRToYUVC(color), thick, lt, blo);
}
for (int i = 0; i < image_num; ++i) {
cv::Point org_img = {tl.x + i, tl.y + rect_img.size().height + i};
cv::Mat yuv_img;
cv::cvtColor(img, yuv_img, cv::COLOR_BGR2YUV);
blendImageRef(yuv, org_img, yuv_img, alpha);
}
cv::circle(yuv, center, rad, cvtBGRToYUVC(color), thick, lt, shift);
cv::line(yuv, center, point_next, cvtBGRToYUVC(color), thick, lt, shift);
std::vector<std::vector<cv::Point>> pp{points};
cv::fillPoly(yuv, pp, cvtBGRToYUVC(color), lt, shift);
// YUV -> NV12
cv::gapi::wip::draw::cvtYUVToNV12(yuv, y_ref_mat, uv_ref_mat);
EXPECT_EQ(cv::norm( y, y_ref_mat), 0);
EXPECT_EQ(cv::norm(uv, uv_ref_mat), 0);
}
TEST(S11N, Pipeline_Render_RGB)
{
cv::Size sz (100, 200);
int rects_num = 10;
int text_num = 10;
int image_num = 10;
int thick = 2;
int lt = LINE_8;
cv::Scalar color(111, 222, 77);
// G-API code //////////////////////////////////////////////////////////////
cv::gapi::wip::draw::Prims prims;
// Rects
int shift = 0;
for (int i = 0; i < rects_num; ++i) {
cv::Rect rect(200 + i, 200 + i, 200, 200);
prims.emplace_back(cv::gapi::wip::draw::Rect(rect, color, thick, lt, shift));
}
// Mosaic
int cellsz = 50;
int decim = 0;
for (int i = 0; i < rects_num; ++i) {
cv::Rect mos(200 + i, 200 + i, 200, 200);
prims.emplace_back(cv::gapi::wip::draw::Mosaic(mos, cellsz, decim));
}
// Text
std::string text = "Some text";
int ff = FONT_HERSHEY_SIMPLEX;
double fs = 2.0;
bool blo = false;
for (int i = 0; i < text_num; ++i) {
cv::Point org(200 + i, 200 + i);
prims.emplace_back(cv::gapi::wip::draw::Text(text, org, ff, fs, color, thick, lt, blo));
}
// Image
double transparency = 1.0;
cv::Rect rect_img(0 ,0 , 50, 50);
cv::Mat img(rect_img.size(), CV_8UC3, color);
cv::Mat alpha(rect_img.size(), CV_32FC1, transparency);
auto tl = rect_img.tl();
for (int i = 0; i < image_num; ++i) {
cv::Point org_img = {tl.x + i, tl.y + rect_img.size().height + i};
prims.emplace_back(cv::gapi::wip::draw::Image({org_img, img, alpha}));
}
// Circle
cv::Point center(300, 400);
int rad = 25;
prims.emplace_back(cv::gapi::wip::draw::Circle({center, rad, color, thick, lt, shift}));
// Line
cv::Point point_next(300, 425);
prims.emplace_back(cv::gapi::wip::draw::Line({center, point_next, color, thick, lt, shift}));
// Poly
std::vector<cv::Point> points = {{300, 400}, {290, 450}, {348, 410}, {300, 400}};
prims.emplace_back(cv::gapi::wip::draw::Poly({points, color, thick, lt, shift}));
cv::GMat in, out;
cv::GArray<cv::gapi::wip::draw::Prim> arr;
out = cv::gapi::wip::draw::render3ch(in, arr);
cv::GComputation comp(cv::GIn(in, arr), cv::GOut(out));
auto serialized = cv::gapi::serialize(comp);
auto dc = cv::gapi::deserialize<cv::GComputation>(serialized);
cv::Mat input(1920, 1080, CV_8UC3);
cv::randu(input, cv::Scalar::all(0), cv::Scalar::all(255));
cv::Mat ref_mat = input.clone();
dc.apply(cv::gin(input, prims), cv::gout(input));
// OpenCV code //////////////////////////////////////////////////////////////
for (int i = 0; i < rects_num; ++i) {
cv::Rect rect(200 + i, 200 + i, 200, 200);
cv::rectangle(ref_mat, rect, color, thick, lt, shift);
}
for (int i = 0; i < rects_num; ++i) {
cv::Rect mos(200 + i, 200 + i, 200, 200);
drawMosaicRef(ref_mat, mos, cellsz);
}
for (int i = 0; i < text_num; ++i) {
cv::Point org(200 + i, 200 + i);
cv::putText(ref_mat, text, org, ff, fs, color, thick, lt, blo);
}
for (int i = 0; i < image_num; ++i) {
cv::Point org_img = {tl.x + i, tl.y + rect_img.size().height + i};
blendImageRef(ref_mat, org_img, img, alpha);
}
cv::circle(ref_mat, center, rad, color, thick, lt, shift);
cv::line(ref_mat, center, point_next, color, thick, lt, shift);
std::vector<std::vector<cv::Point>> pp{points};
cv::fillPoly(ref_mat, pp, color, lt, shift);
EXPECT_EQ(cv::norm(input, ref_mat), 0);
}
} // namespace opencv_test } // namespace opencv_test

Loading…
Cancel
Save