# define GAPI_EXPORTS CV_EXPORTS
/* special informative macros for wrapper generators */
# define GAPI_PROP CV_PROP
+# define GAPI_PROP_RW CV_PROP_RW
# define GAPI_WRAP CV_WRAP
# define GAPI_EXPORTS_W_SIMPLE CV_EXPORTS_W_SIMPLE
# define GAPI_EXPORTS_W CV_EXPORTS_W
# else
# define GAPI_PROP
+# define GAPI_PROP_RW
# define GAPI_WRAP
# define GAPI_EXPORTS
# define GAPI_EXPORTS_W_SIMPLE
@param prims vector of drawing primitivies
@param args graph compile time parameters
*/
-void GAPI_EXPORTS render(cv::Mat& bgr,
- const Prims& prims,
- cv::GCompileArgs&& args = {});
+void GAPI_EXPORTS_W render(cv::Mat& bgr,
+ const Prims& prims,
+ cv::GCompileArgs&& args = {});
/** @brief The function renders on two NV12 planes passed drawing primitivies
@param prims vector of drawing primitivies
@param args graph compile time parameters
*/
-void GAPI_EXPORTS render(cv::Mat& y_plane,
- cv::Mat& uv_plane,
- const Prims& prims,
- cv::GCompileArgs&& args = {});
+void GAPI_EXPORTS_W render(cv::Mat& y_plane,
+ cv::Mat& uv_plane,
+ const Prims& prims,
+ cv::GCompileArgs&& args = {});
/** @brief The function renders on the input media frame passed drawing primitivies
@param src input image: 8-bit unsigned 3-channel image @ref CV_8UC3
@param prims draw primitives
*/
-GAPI_EXPORTS GMat render3ch(const GMat& src, const GArray<Prim>& prims);
+GAPI_EXPORTS_W GMat render3ch(const GMat& src, const GArray<Prim>& prims);
/** @brief Renders on two planes
@param uv input image: 8-bit unsigned 2-channel image @ref CV_8UC2
@param prims draw primitives
*/
-GAPI_EXPORTS GMat2 renderNV12(const GMat& y,
- const GMat& uv,
- const GArray<Prim>& prims);
+GAPI_EXPORTS_W GMat2 renderNV12(const GMat& y,
+ const GMat& uv,
+ const GArray<Prim>& prims);
/** @brief Renders Media Frame
{
namespace ocv
{
- GAPI_EXPORTS cv::gapi::GKernelPackage kernels();
+ GAPI_EXPORTS_W cv::gapi::GKernelPackage kernels();
} // namespace ocv
} // namespace render
*
* Parameters match cv::putText().
*/
-struct Text
+struct GAPI_EXPORTS_W_SIMPLE Text
{
/**
* @brief Text constructor
* @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
*/
+ GAPI_WRAP
Text(const std::string& text_,
const cv::Point& org_,
int ff_,
{
}
+ GAPI_WRAP
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
+ GAPI_PROP_RW std::string text; //!< The text string to be drawn
+ GAPI_PROP_RW cv::Point org; //!< The bottom-left corner of the text string in the image
+ GAPI_PROP_RW int ff; //!< The font type, see #HersheyFonts
+ GAPI_PROP_RW double fs; //!< The font scale factor that is multiplied by the font-specific base size
+ GAPI_PROP_RW cv::Scalar color; //!< The text color
+ GAPI_PROP_RW int thick; //!< The thickness of the lines used to draw a text
+ GAPI_PROP_RW int lt; //!< The line type. See #LineTypes
+ GAPI_PROP_RW bool bottom_left_origin; //!< When true, the image data origin is at the bottom-left corner. Otherwise, it is at the top-left corner
/*@{*/
};
*
* Parameters match cv::rectangle().
*/
-struct Rect
+struct GAPI_EXPORTS_W_SIMPLE Rect
{
/**
* @brief Rect constructor
{
}
+ GAPI_WRAP
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
+ GAPI_PROP_RW cv::Rect rect; //!< Coordinates of the rectangle
+ GAPI_PROP_RW cv::Scalar color; //!< The rectangle color or brightness (grayscale image)
+ GAPI_PROP_RW 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
+ GAPI_PROP_RW int lt; //!< The type of the line. See #LineTypes
+ GAPI_PROP_RW int shift; //!< The number of fractional bits in the point coordinates
/*@{*/
};
*
* Parameters match cv::circle().
*/
-struct Circle
+struct GAPI_EXPORTS_W_SIMPLE Circle
{
/**
* @brief Circle constructor
* @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
*/
+ GAPI_WRAP
Circle(const cv::Point& center_,
int radius_,
const cv::Scalar& color_,
{
}
+ GAPI_WRAP
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
+ GAPI_PROP_RW cv::Point center; //!< The center of the circle
+ GAPI_PROP_RW int radius; //!< The radius of the circle
+ GAPI_PROP_RW cv::Scalar color; //!< The color of the circle
+ GAPI_PROP_RW int thick; //!< The thickness of the circle outline, if positive. Negative values, like #FILLED, mean that a filled circle is to be drawn
+ GAPI_PROP_RW int lt; //!< The Type of the circle boundary. See #LineTypes
+ GAPI_PROP_RW int shift; //!< The Number of fractional bits in the coordinates of the center and in the radius value
/*@{*/
};
*
* Parameters match cv::line().
*/
-struct Line
+struct GAPI_EXPORTS_W_SIMPLE Line
{
/**
* @brief Line constructor
* @param lt_ The Type of the line. See #LineTypes
* @param shift_ The number of fractional bits in the point coordinates
*/
+ GAPI_WRAP
Line(const cv::Point& pt1_,
const cv::Point& pt2_,
const cv::Scalar& color_,
{
}
+ GAPI_WRAP
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
+ GAPI_PROP_RW cv::Point pt1; //!< The first point of the line segment
+ GAPI_PROP_RW cv::Point pt2; //!< The second point of the line segment
+ GAPI_PROP_RW cv::Scalar color; //!< The line color
+ GAPI_PROP_RW int thick; //!< The thickness of line
+ GAPI_PROP_RW int lt; //!< The Type of the line. See #LineTypes
+ GAPI_PROP_RW int shift; //!< The number of fractional bits in the point coordinates
/*@{*/
};
*
* Mosaicing is a very basic method to obfuscate regions in the image.
*/
-struct Mosaic
+struct GAPI_EXPORTS_W_SIMPLE Mosaic
{
/**
* @brief Mosaic constructor
{
}
+ GAPI_WRAP
Mosaic() : cellSz(0), decim(0) {}
/*@{*/
- cv::Rect mos; //!< Coordinates of the mosaic
- int cellSz; //!< Cell size (same for X, Y)
- int decim; //!< Decimation (0 stands for no decimation)
+ GAPI_PROP_RW cv::Rect mos; //!< Coordinates of the mosaic
+ GAPI_PROP_RW int cellSz; //!< Cell size (same for X, Y)
+ GAPI_PROP_RW int decim; //!< Decimation (0 stands for no decimation)
/*@{*/
};
*
* Image is blended on a frame using the specified mask.
*/
-struct Image
+struct GAPI_EXPORTS_W_SIMPLE Image
{
/**
* @brief Mosaic constructor
* @param img_ Image to draw
* @param alpha_ Alpha channel for image to draw (same size and number of channels)
*/
+ GAPI_WRAP
Image(const cv::Point& org_,
const cv::Mat& img_,
const cv::Mat& alpha_) :
{
}
+ GAPI_WRAP
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)
+ GAPI_PROP_RW cv::Point org; //!< The bottom-left corner of the image
+ GAPI_PROP_RW cv::Mat img; //!< Image to draw
+ GAPI_PROP_RW 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
+struct GAPI_EXPORTS_W_SIMPLE Poly
{
/**
* @brief Mosaic constructor
* @param lt_ The Type of the line. See #LineTypes
* @param shift_ The number of fractional bits in the point coordinate
*/
+ GAPI_WRAP
Poly(const std::vector<cv::Point>& points_,
const cv::Scalar& color_,
int thick_ = 1,
{
}
+ GAPI_WRAP
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
+ GAPI_PROP_RW std::vector<cv::Point> points; //!< Points to connect
+ GAPI_PROP_RW cv::Scalar color; //!< The line color
+ GAPI_PROP_RW int thick; //!< The thickness of line
+ GAPI_PROP_RW int lt; //!< The Type of the line. See #LineTypes
+ GAPI_PROP_RW int shift; //!< The number of fractional bits in the point coordinate
/*@{*/
};
, Poly
>;
-using Prims = std::vector<Prim>;
+using Prims = std::vector<Prim>;
//! @} gapi_draw_prims
} // namespace draw
def __new__(self):
return cv.GOpaqueT(cv.gapi.CV_RECT)
+ class Prim():
+ def __new__(self):
+ return cv.GOpaqueT(cv.gapi.CV_DRAW_PRIM)
+
class Any():
def __new__(self):
return cv.GOpaqueT(cv.gapi.CV_ANY)
def __new__(self):
return cv.GArrayT(cv.gapi.CV_GMAT)
+ class Prim():
+ def __new__(self):
+ return cv.GArray(cv.gapi.CV_DRAW_PRIM)
+
class Any():
def __new__(self):
return cv.GArray(cv.gapi.CV_ANY)
cv.GArray.Scalar: cv.gapi.CV_SCALAR,
cv.GArray.Mat: cv.gapi.CV_MAT,
cv.GArray.GMat: cv.gapi.CV_GMAT,
+ cv.GArray.Prim: cv.gapi.CV_DRAW_PRIM,
cv.GArray.Any: cv.gapi.CV_ANY
}
cv.GOpaque.Point2f: cv.gapi.CV_POINT2F,
cv.GOpaque.Size: cv.gapi.CV_SIZE,
cv.GOpaque.Rect: cv.gapi.CV_RECT,
+ cv.GOpaque.Prim: cv.gapi.CV_DRAW_PRIM,
cv.GOpaque.Any: cv.gapi.CV_ANY
}
type2str = {
- cv.gapi.CV_BOOL: 'cv.gapi.CV_BOOL' ,
- cv.gapi.CV_INT: 'cv.gapi.CV_INT' ,
- cv.gapi.CV_DOUBLE: 'cv.gapi.CV_DOUBLE' ,
- cv.gapi.CV_FLOAT: 'cv.gapi.CV_FLOAT' ,
- cv.gapi.CV_STRING: 'cv.gapi.CV_STRING' ,
- cv.gapi.CV_POINT: 'cv.gapi.CV_POINT' ,
- cv.gapi.CV_POINT2F: 'cv.gapi.CV_POINT2F' ,
- cv.gapi.CV_SIZE: 'cv.gapi.CV_SIZE',
- cv.gapi.CV_RECT: 'cv.gapi.CV_RECT',
- cv.gapi.CV_SCALAR: 'cv.gapi.CV_SCALAR',
- cv.gapi.CV_MAT: 'cv.gapi.CV_MAT',
- cv.gapi.CV_GMAT: 'cv.gapi.CV_GMAT'
+ cv.gapi.CV_BOOL: 'cv.gapi.CV_BOOL' ,
+ cv.gapi.CV_INT: 'cv.gapi.CV_INT' ,
+ cv.gapi.CV_DOUBLE: 'cv.gapi.CV_DOUBLE' ,
+ cv.gapi.CV_FLOAT: 'cv.gapi.CV_FLOAT' ,
+ cv.gapi.CV_STRING: 'cv.gapi.CV_STRING' ,
+ cv.gapi.CV_POINT: 'cv.gapi.CV_POINT' ,
+ cv.gapi.CV_POINT2F: 'cv.gapi.CV_POINT2F' ,
+ cv.gapi.CV_SIZE: 'cv.gapi.CV_SIZE',
+ cv.gapi.CV_RECT: 'cv.gapi.CV_RECT',
+ cv.gapi.CV_SCALAR: 'cv.gapi.CV_SCALAR',
+ cv.gapi.CV_MAT: 'cv.gapi.CV_MAT',
+ cv.gapi.CV_GMAT: 'cv.gapi.CV_GMAT',
+ cv.gapi.CV_DRAW_PRIM: 'cv.gapi.CV_DRAW_PRIM'
}
# NB: Second lvl decorator takes class to decorate
return cls
return kernel_with_params
+
+
+# FIXME: On the c++ side every class is placed in cv2 module.
+cv.gapi.wip.draw.Rect = cv.gapi_wip_draw_Rect
+cv.gapi.wip.draw.Text = cv.gapi_wip_draw_Text
+cv.gapi.wip.draw.Circle = cv.gapi_wip_draw_Circle
+cv.gapi.wip.draw.Line = cv.gapi_wip_draw_Line
+cv.gapi.wip.draw.Mosaic = cv.gapi_wip_draw_Mosaic
+cv.gapi.wip.draw.Image = cv.gapi_wip_draw_Image
+cv.gapi.wip.draw.Poly = cv.gapi_wip_draw_Poly
using GArray_Scalar = cv::GArray<cv::Scalar>;
using GArray_Mat = cv::GArray<cv::Mat>;
using GArray_GMat = cv::GArray<cv::GMat>;
+using GArray_Prim = cv::GArray<cv::gapi::wip::draw::Prim>;
// FIXME: Python wrapper generate code without namespace std,
// so it cause error: "string wasn't declared"
return o;
}
+// #FIXME: Is it possible to implement pyopencv_from/pyopencv_to for generic
+// cv::variant<Types...> ?
+template <>
+PyObject* pyopencv_from(const cv::gapi::wip::draw::Prim& prim)
+{
+ switch (prim.index()) {
+ case cv::gapi::wip::draw::Prim::index_of<cv::gapi::wip::draw::Rect>():
+ return pyopencv_from(cv::util::get<cv::gapi::wip::draw::Rect>(prim));
+ case cv::gapi::wip::draw::Prim::index_of<cv::gapi::wip::draw::Text>():
+ return pyopencv_from(cv::util::get<cv::gapi::wip::draw::Text>(prim));
+ case cv::gapi::wip::draw::Prim::index_of<cv::gapi::wip::draw::Circle>():
+ return pyopencv_from(cv::util::get<cv::gapi::wip::draw::Circle>(prim));
+ case cv::gapi::wip::draw::Prim::index_of<cv::gapi::wip::draw::Line>():
+ return pyopencv_from(cv::util::get<cv::gapi::wip::draw::Line>(prim));
+ case cv::gapi::wip::draw::Prim::index_of<cv::gapi::wip::draw::Poly>():
+ return pyopencv_from(cv::util::get<cv::gapi::wip::draw::Poly>(prim));
+ case cv::gapi::wip::draw::Prim::index_of<cv::gapi::wip::draw::Mosaic>():
+ return pyopencv_from(cv::util::get<cv::gapi::wip::draw::Mosaic>(prim));
+ case cv::gapi::wip::draw::Prim::index_of<cv::gapi::wip::draw::Image>():
+ return pyopencv_from(cv::util::get<cv::gapi::wip::draw::Image>(prim));
+ }
+
+ util::throw_error(std::logic_error("Unsupported draw primitive type"));
+}
+
+template <>
+PyObject* pyopencv_from(const cv::gapi::wip::draw::Prims& value)
+{
+ return pyopencv_from_generic_vec(value);
+}
+
+template<>
+bool pyopencv_to(PyObject* obj, cv::gapi::wip::draw::Prim& value, const ArgInfo& info)
+{
+#define TRY_EXTRACT(Prim) \
+ if (PyObject_TypeCheck(obj, reinterpret_cast<PyTypeObject*>(pyopencv_gapi_wip_draw_##Prim##_TypePtr))) \
+ { \
+ value = reinterpret_cast<pyopencv_gapi_wip_draw_##Prim##_t*>(obj)->v; \
+ return true; \
+ } \
+
+ TRY_EXTRACT(Rect)
+ TRY_EXTRACT(Text)
+ TRY_EXTRACT(Circle)
+ TRY_EXTRACT(Line)
+ TRY_EXTRACT(Mosaic)
+ TRY_EXTRACT(Image)
+ TRY_EXTRACT(Poly)
+
+ failmsg("Unsupported primitive type");
+ return false;
+}
+
+template <>
+bool pyopencv_to(PyObject* obj, cv::gapi::wip::draw::Prims& value, const ArgInfo& info)
+{
+ return pyopencv_to_generic_vec(obj, value, info);
+}
+
template<>
PyObject* pyopencv_from(const cv::GArg& value)
{
#define UNSUPPORTED(T) case cv::detail::OpaqueKind::CV_##T: break
switch (value.opaque_kind)
{
- HANDLE_CASE(BOOL, bool);
- HANDLE_CASE(INT, int);
+ HANDLE_CASE(BOOL, bool);
+ HANDLE_CASE(INT, int);
HANDLE_CASE(INT64, int64_t);
- HANDLE_CASE(DOUBLE, double);
- HANDLE_CASE(FLOAT, float);
- HANDLE_CASE(STRING, std::string);
- HANDLE_CASE(POINT, cv::Point);
- HANDLE_CASE(POINT2F, cv::Point2f);
- HANDLE_CASE(SIZE, cv::Size);
- HANDLE_CASE(RECT, cv::Rect);
- HANDLE_CASE(SCALAR, cv::Scalar);
- HANDLE_CASE(MAT, cv::Mat);
- HANDLE_CASE(UNKNOWN, cv::detail::PyObjectHolder);
+ HANDLE_CASE(DOUBLE, double);
+ HANDLE_CASE(FLOAT, float);
+ HANDLE_CASE(STRING, std::string);
+ HANDLE_CASE(POINT, cv::Point);
+ HANDLE_CASE(POINT2F, cv::Point2f);
+ HANDLE_CASE(SIZE, cv::Size);
+ HANDLE_CASE(RECT, cv::Rect);
+ HANDLE_CASE(SCALAR, cv::Scalar);
+ HANDLE_CASE(MAT, cv::Mat);
+ HANDLE_CASE(UNKNOWN, cv::detail::PyObjectHolder);
+ HANDLE_CASE(DRAW_PRIM, cv::gapi::wip::draw::Prim);
UNSUPPORTED(UINT64);
- UNSUPPORTED(DRAW_PRIM);
#undef HANDLE_CASE
#undef UNSUPPORTED
}
case cv::detail::OpaqueKind::CV_SIZE : return pyopencv_from(o.rref<cv::Size>());
case cv::detail::OpaqueKind::CV_RECT : return pyopencv_from(o.rref<cv::Rect>());
case cv::detail::OpaqueKind::CV_UNKNOWN : return pyopencv_from(o.rref<cv::GArg>());
+ case cv::detail::OpaqueKind::CV_DRAW_PRIM : return pyopencv_from(o.rref<cv::gapi::wip::draw::Prim>());
case cv::detail::OpaqueKind::CV_UINT64 : break;
case cv::detail::OpaqueKind::CV_SCALAR : break;
case cv::detail::OpaqueKind::CV_MAT : break;
- case cv::detail::OpaqueKind::CV_DRAW_PRIM : break;
}
PyErr_SetString(PyExc_TypeError, "Unsupported GOpaque type");
case cv::detail::OpaqueKind::CV_SCALAR : return pyopencv_from_generic_vec(v.rref<cv::Scalar>());
case cv::detail::OpaqueKind::CV_MAT : return pyopencv_from_generic_vec(v.rref<cv::Mat>());
case cv::detail::OpaqueKind::CV_UNKNOWN : return pyopencv_from_generic_vec(v.rref<cv::GArg>());
+ case cv::detail::OpaqueKind::CV_DRAW_PRIM : return pyopencv_from_generic_vec(v.rref<cv::gapi::wip::draw::Prim>());
case cv::detail::OpaqueKind::CV_UINT64 : break;
- case cv::detail::OpaqueKind::CV_DRAW_PRIM : break;
}
PyErr_SetString(PyExc_TypeError, "Unsupported GArray type");
#define UNSUPPORTED(T) case cv::detail::OpaqueKind::CV_##T: break
switch (kind)
{
- HANDLE_CASE(BOOL, bool);
- HANDLE_CASE(INT, int);
- HANDLE_CASE(DOUBLE, double);
- HANDLE_CASE(FLOAT, float);
- HANDLE_CASE(STRING, std::string);
- HANDLE_CASE(POINT, cv::Point);
- HANDLE_CASE(POINT2F, cv::Point2f);
- HANDLE_CASE(SIZE, cv::Size);
- HANDLE_CASE(RECT, cv::Rect);
- HANDLE_CASE(SCALAR, cv::Scalar);
- HANDLE_CASE(MAT, cv::Mat);
- HANDLE_CASE(UNKNOWN, cv::GArg);
+ HANDLE_CASE(BOOL, bool);
+ HANDLE_CASE(INT, int);
+ HANDLE_CASE(DOUBLE, double);
+ HANDLE_CASE(FLOAT, float);
+ HANDLE_CASE(STRING, std::string);
+ HANDLE_CASE(POINT, cv::Point);
+ HANDLE_CASE(POINT2F, cv::Point2f);
+ HANDLE_CASE(SIZE, cv::Size);
+ HANDLE_CASE(RECT, cv::Rect);
+ HANDLE_CASE(SCALAR, cv::Scalar);
+ HANDLE_CASE(MAT, cv::Mat);
+ HANDLE_CASE(UNKNOWN, cv::GArg);
+ HANDLE_CASE(DRAW_PRIM, cv::gapi::wip::draw::Prim);
UNSUPPORTED(UINT64);
UNSUPPORTED(INT64);
- UNSUPPORTED(DRAW_PRIM);
#undef HANDLE_CASE
#undef UNSUPPORTED
}
#include <opencv2/gapi.hpp>
#include <opencv2/gapi/garg.hpp>
#include <opencv2/gapi/gopaque.hpp>
+#include <opencv2/gapi/render/render_types.hpp> // Prim
#define ID(T, E) T
#define ID_(T, E) ID(T, E),
GAPI_Assert(false && "Unsupported type"); \
}
+using cv::gapi::wip::draw::Prim;
+
#define GARRAY_TYPE_LIST_G(G, G2) \
-WRAP_ARGS(bool , cv::gapi::ArgType::CV_BOOL, G) \
-WRAP_ARGS(int , cv::gapi::ArgType::CV_INT, G) \
-WRAP_ARGS(int64_t , cv::gapi::ArgType::CV_INT64, G) \
-WRAP_ARGS(double , cv::gapi::ArgType::CV_DOUBLE, G) \
-WRAP_ARGS(float , cv::gapi::ArgType::CV_FLOAT, G) \
-WRAP_ARGS(std::string , cv::gapi::ArgType::CV_STRING, G) \
-WRAP_ARGS(cv::Point , cv::gapi::ArgType::CV_POINT, G) \
-WRAP_ARGS(cv::Point2f , cv::gapi::ArgType::CV_POINT2F, G) \
-WRAP_ARGS(cv::Size , cv::gapi::ArgType::CV_SIZE, G) \
-WRAP_ARGS(cv::Rect , cv::gapi::ArgType::CV_RECT, G) \
-WRAP_ARGS(cv::Scalar , cv::gapi::ArgType::CV_SCALAR, G) \
-WRAP_ARGS(cv::Mat , cv::gapi::ArgType::CV_MAT, G) \
-WRAP_ARGS(cv::GArg , cv::gapi::ArgType::CV_ANY, G) \
-WRAP_ARGS(cv::GMat , cv::gapi::ArgType::CV_GMAT, G2) \
+WRAP_ARGS(bool , cv::gapi::ArgType::CV_BOOL, G) \
+WRAP_ARGS(int , cv::gapi::ArgType::CV_INT, G) \
+WRAP_ARGS(int64_t , cv::gapi::ArgType::CV_INT64, G) \
+WRAP_ARGS(double , cv::gapi::ArgType::CV_DOUBLE, G) \
+WRAP_ARGS(float , cv::gapi::ArgType::CV_FLOAT, G) \
+WRAP_ARGS(std::string , cv::gapi::ArgType::CV_STRING, G) \
+WRAP_ARGS(cv::Point , cv::gapi::ArgType::CV_POINT, G) \
+WRAP_ARGS(cv::Point2f , cv::gapi::ArgType::CV_POINT2F, G) \
+WRAP_ARGS(cv::Size , cv::gapi::ArgType::CV_SIZE, G) \
+WRAP_ARGS(cv::Rect , cv::gapi::ArgType::CV_RECT, G) \
+WRAP_ARGS(cv::Scalar , cv::gapi::ArgType::CV_SCALAR, G) \
+WRAP_ARGS(cv::Mat , cv::gapi::ArgType::CV_MAT, G) \
+WRAP_ARGS(Prim , cv::gapi::ArgType::CV_DRAW_PRIM, G) \
+WRAP_ARGS(cv::GArg , cv::gapi::ArgType::CV_ANY, G) \
+WRAP_ARGS(cv::GMat , cv::gapi::ArgType::CV_GMAT, G2) \
#define GOPAQUE_TYPE_LIST_G(G, G2) \
WRAP_ARGS(bool , cv::gapi::ArgType::CV_BOOL, G) \
CV_SCALAR,
CV_MAT,
CV_GMAT,
+ CV_DRAW_PRIM,
CV_ANY,
};
namespace cv
{
- struct GAPI_EXPORTS_W_SIMPLE GCompileArg {
- GAPI_WRAP GCompileArg(gapi::GKernelPackage pkg);
- GAPI_WRAP GCompileArg(gapi::GNetPackage pkg);
- };
-
- class GAPI_EXPORTS_W_SIMPLE GInferInputs
- {
- public:
- GAPI_WRAP GInferInputs();
- GAPI_WRAP GInferInputs& setInput(const std::string& name, const cv::GMat& value);
- GAPI_WRAP GInferInputs& setInput(const std::string& name, const cv::GFrame& value);
- };
-
- class GAPI_EXPORTS_W_SIMPLE GInferListInputs
- {
- public:
- GAPI_WRAP GInferListInputs();
- GAPI_WRAP GInferListInputs setInput(const std::string& name, const cv::GArray<cv::GMat>& value);
- GAPI_WRAP GInferListInputs setInput(const std::string& name, const cv::GArray<cv::Rect>& value);
- };
-
- class GAPI_EXPORTS_W_SIMPLE GInferOutputs
- {
- public:
- GAPI_WRAP GInferOutputs();
- GAPI_WRAP cv::GMat at(const std::string& name);
- };
-
- class GAPI_EXPORTS_W_SIMPLE GInferListOutputs
- {
- public:
- GAPI_WRAP GInferListOutputs();
- GAPI_WRAP cv::GArray<cv::GMat> at(const std::string& name);
- };
-
- namespace detail
- {
- gapi::GNetParam GAPI_EXPORTS_W strip(gapi::ie::PyParams params);
- } // namespace detail
-
- namespace gapi
- {
- namespace streaming
- {
- // FIXME: Extend to work with an arbitrary G-type.
- cv::GOpaque<int64_t> GAPI_EXPORTS_W timestamp(cv::GMat);
- cv::GOpaque<int64_t> GAPI_EXPORTS_W seqNo(cv::GMat);
- cv::GOpaque<int64_t> GAPI_EXPORTS_W seq_id(cv::GMat);
- } // namespace streaming
- namespace wip
- {
- class GAPI_EXPORTS_W IStreamSource { };
- } // namespace wip
- } // namespace gapi
+struct GAPI_EXPORTS_W_SIMPLE GCompileArg {
+ GAPI_WRAP GCompileArg(gapi::GKernelPackage pkg);
+ GAPI_WRAP GCompileArg(gapi::GNetPackage pkg);
+};
+
+class GAPI_EXPORTS_W_SIMPLE GInferInputs
+{
+public:
+ GAPI_WRAP GInferInputs();
+ GAPI_WRAP GInferInputs& setInput(const std::string& name, const cv::GMat& value);
+ GAPI_WRAP GInferInputs& setInput(const std::string& name, const cv::GFrame& value);
+};
+
+class GAPI_EXPORTS_W_SIMPLE GInferListInputs
+{
+public:
+ GAPI_WRAP GInferListInputs();
+ GAPI_WRAP GInferListInputs setInput(const std::string& name, const cv::GArray<cv::GMat>& value);
+ GAPI_WRAP GInferListInputs setInput(const std::string& name, const cv::GArray<cv::Rect>& value);
+};
+
+class GAPI_EXPORTS_W_SIMPLE GInferOutputs
+{
+public:
+ GAPI_WRAP GInferOutputs();
+ GAPI_WRAP cv::GMat at(const std::string& name);
+};
+
+class GAPI_EXPORTS_W_SIMPLE GInferListOutputs
+{
+public:
+ GAPI_WRAP GInferListOutputs();
+ GAPI_WRAP cv::GArray<cv::GMat> at(const std::string& name);
+};
+
+namespace gapi
+{
+namespace wip
+{
+class GAPI_EXPORTS_W IStreamSource { };
+namespace draw
+{
+ // NB: These render primitives are partially wrapped in shadow file
+ // because cv::Rect conflicts with cv::gapi::wip::draw::Rect in python generator
+ // and cv::Rect2i breaks standalone mode.
+ struct Rect
+ {
+ GAPI_WRAP Rect(const cv::Rect2i& rect_,
+ const cv::Scalar& color_,
+ int thick_ = 1,
+ int lt_ = 8,
+ int shift_ = 0);
+ };
+
+ struct Mosaic
+ {
+ GAPI_WRAP Mosaic(const cv::Rect2i& mos_, int cellSz_, int decim_);
+ };
+} // namespace draw
+} // namespace wip
+namespace streaming
+{
+ // FIXME: Extend to work with an arbitrary G-type.
+ cv::GOpaque<int64_t> GAPI_EXPORTS_W timestamp(cv::GMat);
+ cv::GOpaque<int64_t> GAPI_EXPORTS_W seqNo(cv::GMat);
+ cv::GOpaque<int64_t> GAPI_EXPORTS_W seq_id(cv::GMat);
+} // namespace streaming
+} // namespace gapi
+
+namespace detail
+{
+ gapi::GNetParam GAPI_EXPORTS_W strip(gapi::ie::PyParams params);
+} // namespace detail
} // namespace cv
--- /dev/null
+#!/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')
+
+ # FIXME: FText isn't supported yet.
+ class gapi_render_test(NewOpenCVTests):
+ def __init__(self, *args):
+ super().__init__(*args)
+
+ self.size = (300, 300, 3)
+
+ # Rect
+ self.rect = (30, 30, 50, 50)
+ self.rcolor = (0, 255, 0)
+ self.rlt = cv.LINE_4
+ self.rthick = 2
+ self.rshift = 3
+
+ # Text
+ self.text = 'Hello, world!'
+ self.org = (100, 100)
+ self.ff = cv.FONT_HERSHEY_SIMPLEX
+ self.fs = 1.0
+ self.tthick = 2
+ self.tlt = cv.LINE_8
+ self.tcolor = (255, 255, 255)
+ self.blo = False
+
+ # Circle
+ self.center = (200, 200)
+ self.radius = 200
+ self.ccolor = (255, 255, 0)
+ self.cthick = 2
+ self.clt = cv.LINE_4
+ self.cshift = 1
+
+ # Line
+ self.pt1 = (50, 50)
+ self.pt2 = (200, 200)
+ self.lcolor = (0, 255, 128)
+ self.lthick = 5
+ self.llt = cv.LINE_8
+ self.lshift = 2
+
+ # Poly
+ self.pts = [(50, 100), (100, 200), (25, 250)]
+ self.pcolor = (0, 0, 255)
+ self.pthick = 3
+ self.plt = cv.LINE_4
+ self.pshift = 1
+
+ # Image
+ self.iorg = (150, 150)
+ img_path = self.find_file('cv/face/david2.jpg', [os.environ.get('OPENCV_TEST_DATA_PATH')])
+ self.img = cv.resize(cv.imread(img_path), (50, 50))
+ self.alpha = np.full(self.img.shape[:2], 0.8, dtype=np.float32)
+
+ # Mosaic
+ self.mos = (100, 100, 100, 100)
+ self.cell_sz = 25
+ self.decim = 0
+
+ # Render primitives
+ self.prims = [cv.gapi.wip.draw.Rect(self.rect, self.rcolor, self.rthick, self.rlt, self.rshift),
+ cv.gapi.wip.draw.Text(self.text, self.org, self.ff, self.fs, self.tcolor, self.tthick, self.tlt, self.blo),
+ cv.gapi.wip.draw.Circle(self.center, self.radius, self.ccolor, self.cthick, self.clt, self.cshift),
+ cv.gapi.wip.draw.Line(self.pt1, self.pt2, self.lcolor, self.lthick, self.llt, self.lshift),
+ cv.gapi.wip.draw.Mosaic(self.mos, self.cell_sz, self.decim),
+ cv.gapi.wip.draw.Image(self.iorg, self.img, self.alpha),
+ cv.gapi.wip.draw.Poly(self.pts, self.pcolor, self.pthick, self.plt, self.pshift)]
+
+ def cvt_nv12_to_yuv(self, y, uv):
+ h,w,_ = uv.shape
+ upsample_uv = cv.resize(uv, (h * 2, w * 2))
+ return cv.merge([y, upsample_uv])
+
+ def cvt_yuv_to_nv12(self, yuv, y_out, uv_out):
+ chs = cv.split(yuv, [y_out, None, None])
+ uv = cv.merge([chs[1], chs[2]])
+ uv_out = cv.resize(uv, (uv.shape[0] // 2, uv.shape[1] // 2), dst=uv_out)
+ return y_out, uv_out
+
+ def cvt_bgr_to_yuv_color(self, bgr):
+ y = bgr[2] * 0.299000 + bgr[1] * 0.587000 + bgr[0] * 0.114000;
+ u = bgr[2] * -0.168736 + bgr[1] * -0.331264 + bgr[0] * 0.500000 + 128;
+ v = bgr[2] * 0.500000 + bgr[1] * -0.418688 + bgr[0] * -0.081312 + 128;
+ return (y, u, v)
+
+ def blend_img(self, background, org, img, alpha):
+ x, y = org
+ h, w, _ = img.shape
+ roi_img = background[x:x+w, y:y+h, :]
+ img32f_w = cv.merge([alpha] * 3).astype(np.float32)
+ roi32f_w = np.full(roi_img.shape, 1.0, dtype=np.float32)
+ roi32f_w -= img32f_w
+ img32f = (img / 255).astype(np.float32)
+ roi32f = (roi_img / 255).astype(np.float32)
+ cv.multiply(img32f, img32f_w, dst=img32f)
+ cv.multiply(roi32f, roi32f_w, dst=roi32f)
+ roi32f += img32f
+ roi_img[...] = np.round(roi32f * 255)
+
+ # This is quite naive implementations used as a simple reference
+ # doesn't consider corner cases.
+ def draw_mosaic(self, img, mos, cell_sz, decim):
+ x,y,w,h = mos
+ mosaic_area = img[x:x+w, y:y+h, :]
+ for i in range(0, mosaic_area.shape[0], cell_sz):
+ for j in range(0, mosaic_area.shape[1], cell_sz):
+ cell_roi = mosaic_area[j:j+cell_sz, i:i+cell_sz, :]
+ s0, s1, s2 = cv.mean(cell_roi)[:3]
+ mosaic_area[j:j+cell_sz, i:i+cell_sz] = (round(s0), round(s1), round(s2))
+
+ def render_primitives_bgr_ref(self, img):
+ cv.rectangle(img, self.rect, self.rcolor, self.rthick, self.rlt, self.rshift)
+ cv.putText(img, self.text, self.org, self.ff, self.fs, self.tcolor, self.tthick, self.tlt, self.blo)
+ cv.circle(img, self.center, self.radius, self.ccolor, self.cthick, self.clt, self.cshift)
+ cv.line(img, self.pt1, self.pt2, self.lcolor, self.lthick, self.llt, self.lshift)
+ cv.fillPoly(img, np.expand_dims(np.array([self.pts]), axis=0), self.pcolor, self.plt, self.pshift)
+ self.draw_mosaic(img, self.mos, self.cell_sz, self.decim)
+ self.blend_img(img, self.iorg, self.img, self.alpha)
+
+ def render_primitives_nv12_ref(self, y_plane, uv_plane):
+ yuv = self.cvt_nv12_to_yuv(y_plane, uv_plane)
+ cv.rectangle(yuv, self.rect, self.cvt_bgr_to_yuv_color(self.rcolor), self.rthick, self.rlt, self.rshift)
+ cv.putText(yuv, self.text, self.org, self.ff, self.fs, self.cvt_bgr_to_yuv_color(self.tcolor), self.tthick, self.tlt, self.blo)
+ cv.circle(yuv, self.center, self.radius, self.cvt_bgr_to_yuv_color(self.ccolor), self.cthick, self.clt, self.cshift)
+ cv.line(yuv, self.pt1, self.pt2, self.cvt_bgr_to_yuv_color(self.lcolor), self.lthick, self.llt, self.lshift)
+ cv.fillPoly(yuv, np.expand_dims(np.array([self.pts]), axis=0), self.cvt_bgr_to_yuv_color(self.pcolor), self.plt, self.pshift)
+ self.draw_mosaic(yuv, self.mos, self.cell_sz, self.decim)
+ self.blend_img(yuv, self.iorg, cv.cvtColor(self.img, cv.COLOR_BGR2YUV), self.alpha)
+ self.cvt_yuv_to_nv12(yuv, y_plane, uv_plane)
+
+ def test_render_primitives_on_bgr_graph(self):
+ expected = np.zeros(self.size, dtype=np.uint8)
+ actual = np.array(expected, copy=True)
+
+ # OpenCV
+ self.render_primitives_bgr_ref(expected)
+
+ # G-API
+ g_in = cv.GMat()
+ g_prims = cv.GArray.Prim()
+ g_out = cv.gapi.wip.draw.render3ch(g_in, g_prims)
+
+
+ comp = cv.GComputation(cv.GIn(g_in, g_prims), cv.GOut(g_out))
+ actual = comp.apply(cv.gin(actual, self.prims))
+
+ self.assertEqual(0.0, cv.norm(expected, actual, cv.NORM_INF))
+
+ def test_render_primitives_on_bgr_function(self):
+ expected = np.zeros(self.size, dtype=np.uint8)
+ actual = np.array(expected, copy=True)
+
+ # OpenCV
+ self.render_primitives_bgr_ref(expected)
+
+ # G-API
+ cv.gapi.wip.draw.render(actual, self.prims)
+ self.assertEqual(0.0, cv.norm(expected, actual, cv.NORM_INF))
+
+ def test_render_primitives_on_nv12_graph(self):
+ y_expected = np.zeros((self.size[0], self.size[1], 1), dtype=np.uint8)
+ uv_expected = np.zeros((self.size[0] // 2, self.size[1] // 2, 2), dtype=np.uint8)
+
+ y_actual = np.array(y_expected, copy=True)
+ uv_actual = np.array(uv_expected, copy=True)
+
+ # OpenCV
+ self.render_primitives_nv12_ref(y_expected, uv_expected)
+
+ # G-API
+ g_y = cv.GMat()
+ g_uv = cv.GMat()
+ g_prims = cv.GArray.Prim()
+ g_out_y, g_out_uv = cv.gapi.wip.draw.renderNV12(g_y, g_uv, g_prims)
+
+ comp = cv.GComputation(cv.GIn(g_y, g_uv, g_prims), cv.GOut(g_out_y, g_out_uv))
+ y_actual, uv_actual = comp.apply(cv.gin(y_actual, uv_actual, self.prims))
+
+ self.assertEqual(0.0, cv.norm(y_expected, y_actual, cv.NORM_INF))
+ self.assertEqual(0.0, cv.norm(uv_expected, uv_actual, cv.NORM_INF))
+
+ def test_render_primitives_on_nv12_function(self):
+ y_expected = np.zeros((self.size[0], self.size[1], 1), dtype=np.uint8)
+ uv_expected = np.zeros((self.size[0] // 2, self.size[1] // 2, 2), dtype=np.uint8)
+
+ y_actual = np.array(y_expected, copy=True)
+ uv_actual = np.array(uv_expected, copy=True)
+
+ # OpenCV
+ self.render_primitives_nv12_ref(y_expected, uv_expected)
+
+ # G-API
+ cv.gapi.wip.draw.render(y_actual, uv_actual, self.prims)
+
+ self.assertEqual(0.0, cv.norm(y_expected, y_actual, cv.NORM_INF))
+ self.assertEqual(0.0, cv.norm(uv_expected, uv_actual, cv.NORM_INF))
+
+
+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()
{
const auto& rp = cv::util::get<Rect>(p);
const auto color = converter.cvtColor(rp.color);
- cv::rectangle(in, rp.rect, color , rp.thick);
+ cv::rectangle(in, rp.rect, color, rp.thick, rp.lt, rp.shift);
break;
}
{
const auto& cp = cv::util::get<Circle>(p);
const auto color = converter.cvtColor(cp.color);
- cv::circle(in, cp.center, cp.radius, color, cp.thick);
+ cv::circle(in, cp.center, cp.radius, color, cp.thick, cp.lt, cp.shift);
break;
}
{
const auto& lp = cv::util::get<Line>(p);
const auto color = converter.cvtColor(lp.color);
- cv::line(in, lp.pt1, lp.pt2, color, lp.thick);
+ cv::line(in, lp.pt1, lp.pt2, color, lp.thick, lp.lt, lp.shift);
break;
}
Values(cv::Rect(100, 100, 200, 200)),
Values(cv::Scalar(100, 50, 150)),
Values(2),
- Values(LINE_8),
- Values(0)));
+ Values(LINE_8, LINE_4),
+ Values(0, 1)));
INSTANTIATE_TEST_CASE_P(RenderNV12OCVTestRectsImpl, RenderNV12OCVTestRects,
Combine(Values(cv::Size(1280, 720)),
Values(10),
Values(cv::Scalar(100, 50, 150)),
Values(2),
- Values(LINE_8),
- Values(0)));
+ Values(LINE_8, LINE_4),
+ Values(0, 1)));
INSTANTIATE_TEST_CASE_P(RenderMFrameOCVTestCirclesImpl, RenderMFrameOCVTestCircles,
Combine(Values(cv::Size(1280, 720)),
("GAPI_EXPORTS_W_SIMPLE","CV_EXPORTS_W_SIMPLE"),
("GAPI_WRAP", "CV_WRAP"),
("GAPI_PROP", "CV_PROP"),
+ ("GAPI_PROP_RW", "CV_PROP_RW"),
('defined(GAPI_STANDALONE)', '0'),
])