Merge pull request #20284 from TolyaTalamanov:at/wrap-render
G-API: Wrap render functionality to python * Wrap render Rect prim * Add all primitives and tests * Cover mosaic and image * Handle error in pyopencv_to(Prim) * Move Mosaic and Rect ctors wrappers to shadow file * Use GAPI_PROP_RW * Fix indent
This commit is contained in:
committed by
GitHub
parent
bf489feef1
commit
9fe49497bb
@@ -84,6 +84,10 @@ class GOpaque():
|
||||
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)
|
||||
@@ -143,6 +147,10 @@ class GArray():
|
||||
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)
|
||||
@@ -164,6 +172,7 @@ def op(op_id, in_types, out_types):
|
||||
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
|
||||
}
|
||||
|
||||
@@ -179,22 +188,24 @@ def op(op_id, in_types, out_types):
|
||||
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
|
||||
@@ -274,3 +285,13 @@ def kernel(op_cls):
|
||||
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
|
||||
|
||||
@@ -43,6 +43,7 @@ using GArray_Rect = cv::GArray<cv::Rect>;
|
||||
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"
|
||||
@@ -125,6 +126,65 @@ PyObject* pyopencv_from(const cv::detail::PyObjectHolder& v)
|
||||
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)
|
||||
{
|
||||
@@ -137,21 +197,21 @@ 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
|
||||
}
|
||||
@@ -205,10 +265,10 @@ PyObject* pyopencv_from(const cv::detail::OpaqueRef& o)
|
||||
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");
|
||||
@@ -233,8 +293,8 @@ PyObject* pyopencv_from(const cv::detail::VectorRef& v)
|
||||
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");
|
||||
@@ -394,21 +454,21 @@ static cv::detail::VectorRef extract_vector_ref(PyObject* from, cv::detail::Opaq
|
||||
#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
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#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),
|
||||
@@ -24,21 +25,24 @@
|
||||
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) \
|
||||
@@ -71,6 +75,7 @@ enum ArgType {
|
||||
CV_SCALAR,
|
||||
CV_MAT,
|
||||
CV_GMAT,
|
||||
CV_DRAW_PRIM,
|
||||
CV_ANY,
|
||||
};
|
||||
|
||||
|
||||
@@ -3,58 +3,77 @@
|
||||
|
||||
namespace cv
|
||||
{
|
||||
struct GAPI_EXPORTS_W_SIMPLE GCompileArg {
|
||||
GAPI_WRAP GCompileArg(gapi::GKernelPackage pkg);
|
||||
GAPI_WRAP GCompileArg(gapi::GNetPackage pkg);
|
||||
};
|
||||
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 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 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 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);
|
||||
};
|
||||
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 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);
|
||||
};
|
||||
|
||||
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 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
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
#!/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()
|
||||
Reference in New Issue
Block a user