mirror of
https://github.com/opencv/opencv.git
synced 2024-11-24 11:10:21 +08:00
bindings: backport generator from OpenCV 4.x
- better handling of enum arguments - less merge conflicts
This commit is contained in:
parent
d034ef6f27
commit
f5b58e5fc9
36
modules/core/misc/python/pyopencv_umat.hpp
Normal file
36
modules/core/misc/python/pyopencv_umat.hpp
Normal file
@ -0,0 +1,36 @@
|
||||
#ifdef HAVE_OPENCV_CORE
|
||||
|
||||
#include "opencv2/core/mat.hpp"
|
||||
|
||||
typedef std::vector<Range> vector_Range;
|
||||
|
||||
CV_PY_TO_CLASS(UMat);
|
||||
CV_PY_FROM_CLASS(UMat);
|
||||
|
||||
static bool cv_mappable_to(const Ptr<Mat>& src, Ptr<UMat>& dst)
|
||||
{
|
||||
//dst.reset(new UMat(src->getUMat(ACCESS_RW)));
|
||||
dst.reset(new UMat());
|
||||
src->copyTo(*dst);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void* cv_UMat_queue()
|
||||
{
|
||||
return cv::ocl::Queue::getDefault().ptr();
|
||||
}
|
||||
|
||||
static void* cv_UMat_context()
|
||||
{
|
||||
return cv::ocl::Context::getDefault().ptr();
|
||||
}
|
||||
|
||||
static Mat cv_UMat_get(const UMat* _self)
|
||||
{
|
||||
Mat m;
|
||||
m.allocator = &g_numpyAllocator;
|
||||
_self->copyTo(m);
|
||||
return m;
|
||||
}
|
||||
|
||||
#endif
|
59
modules/core/misc/python/shadow_umat.hpp
Normal file
59
modules/core/misc/python/shadow_umat.hpp
Normal file
@ -0,0 +1,59 @@
|
||||
#error This is a shadow header file, which is not intended for processing by any compiler. \
|
||||
Only bindings parser should handle this file.
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
class CV_EXPORTS_W UMat
|
||||
{
|
||||
public:
|
||||
//! default constructor
|
||||
CV_WRAP UMat(UMatUsageFlags usageFlags = USAGE_DEFAULT);
|
||||
//! constructs 2D matrix of the specified size and type
|
||||
// (_type is CV_8UC1, CV_64FC3, CV_32SC(12) etc.)
|
||||
CV_WRAP UMat(int rows, int cols, int type, UMatUsageFlags usageFlags = USAGE_DEFAULT);
|
||||
CV_WRAP UMat(Size size, int type, UMatUsageFlags usageFlags = USAGE_DEFAULT);
|
||||
//! constucts 2D matrix and fills it with the specified value _s.
|
||||
CV_WRAP UMat(int rows, int cols, int type, const Scalar& s, UMatUsageFlags usageFlags = USAGE_DEFAULT);
|
||||
CV_WRAP UMat(Size size, int type, const Scalar& s, UMatUsageFlags usageFlags = USAGE_DEFAULT);
|
||||
|
||||
//! Mat is mappable to UMat
|
||||
CV_WRAP_MAPPABLE(Ptr<Mat>);
|
||||
|
||||
//! returns the OpenCL queue used by OpenCV UMat
|
||||
CV_WRAP_PHANTOM(static void* queue());
|
||||
|
||||
//! returns the OpenCL context used by OpenCV UMat
|
||||
CV_WRAP_PHANTOM(static void* context());
|
||||
|
||||
//! copy constructor
|
||||
CV_WRAP UMat(const UMat& m);
|
||||
|
||||
//! creates a matrix header for a part of the bigger matrix
|
||||
CV_WRAP UMat(const UMat& m, const Range& rowRange, const Range& colRange = Range::all());
|
||||
CV_WRAP UMat(const UMat& m, const Rect& roi);
|
||||
CV_WRAP UMat(const UMat& m, const std::vector<Range>& ranges);
|
||||
|
||||
//CV_WRAP_AS(get) Mat getMat(int flags CV_WRAP_DEFAULT(ACCESS_RW)) const;
|
||||
//! returns a numpy matrix
|
||||
CV_WRAP_PHANTOM(Mat get() const);
|
||||
|
||||
//! returns true iff the matrix data is continuous
|
||||
// (i.e. when there are no gaps between successive rows).
|
||||
// similar to CV_IS_MAT_CONT(cvmat->type)
|
||||
CV_WRAP bool isContinuous() const;
|
||||
|
||||
//! returns true if the matrix is a submatrix of another matrix
|
||||
CV_WRAP bool isSubmatrix() const;
|
||||
|
||||
/*! Returns the OpenCL buffer handle on which UMat operates on.
|
||||
The UMat instance should be kept alive during the use of the handle to prevent the buffer to be
|
||||
returned to the OpenCV buffer pool.
|
||||
*/
|
||||
CV_WRAP void* handle(int/*AccessFlag*/ accessFlags) const;
|
||||
|
||||
// offset of the submatrix (or 0)
|
||||
CV_PROP_RW size_t offset;
|
||||
};
|
||||
|
||||
} // namespace cv
|
@ -140,17 +140,18 @@ class GeneralInfo():
|
||||
|
||||
def fullName(self, isCPP=False):
|
||||
result = ".".join([self.fullClass(), self.name])
|
||||
return result if not isCPP else result.replace(".", "::")
|
||||
return result if not isCPP else get_cname(result)
|
||||
|
||||
def fullClass(self, isCPP=False):
|
||||
result = ".".join([f for f in [self.namespace] + self.classpath.split(".") if len(f)>0])
|
||||
return result if not isCPP else result.replace(".", "::")
|
||||
return result if not isCPP else get_cname(result)
|
||||
|
||||
class ConstInfo(GeneralInfo):
|
||||
def __init__(self, decl, addedManually=False, namespaces=[]):
|
||||
def __init__(self, decl, addedManually=False, namespaces=[], enumType=None):
|
||||
GeneralInfo.__init__(self, "const", decl, namespaces)
|
||||
self.cname = self.name.replace(".", "::")
|
||||
self.cname = get_cname(self.name)
|
||||
self.value = decl[1]
|
||||
self.enumType = enumType
|
||||
self.addedManually = addedManually
|
||||
if self.namespace in namespaces_dict:
|
||||
self.name = '%s_%s' % (namespaces_dict[self.namespace], self.name)
|
||||
@ -166,6 +167,25 @@ class ConstInfo(GeneralInfo):
|
||||
return True
|
||||
return False
|
||||
|
||||
def normalize_field_name(name):
|
||||
return name.replace(".","_").replace("[","").replace("]","").replace("_getNativeObjAddr()","_nativeObj")
|
||||
|
||||
def normalize_class_name(name):
|
||||
return re.sub(r"^cv\.", "", name).replace(".", "_")
|
||||
|
||||
def get_cname(name):
|
||||
return name.replace(".", "::")
|
||||
|
||||
def cast_from(t):
|
||||
if t in type_dict and "cast_from" in type_dict[t]:
|
||||
return type_dict[t]["cast_from"]
|
||||
return t
|
||||
|
||||
def cast_to(t):
|
||||
if t in type_dict and "cast_to" in type_dict[t]:
|
||||
return type_dict[t]["cast_to"]
|
||||
return t
|
||||
|
||||
class ClassPropInfo():
|
||||
def __init__(self, decl): # [f_ctype, f_name, '', '/RW']
|
||||
self.ctype = decl[0]
|
||||
@ -178,7 +198,7 @@ class ClassPropInfo():
|
||||
class ClassInfo(GeneralInfo):
|
||||
def __init__(self, decl, namespaces=[]): # [ 'class/struct cname', ': base', [modlist] ]
|
||||
GeneralInfo.__init__(self, "class", decl, namespaces)
|
||||
self.cname = self.name.replace(".", "::")
|
||||
self.cname = get_cname(self.name)
|
||||
self.methods = []
|
||||
self.methods_suffixes = {}
|
||||
self.consts = [] # using a list to save the occurrence order
|
||||
@ -303,7 +323,7 @@ class ArgInfo():
|
||||
class FuncInfo(GeneralInfo):
|
||||
def __init__(self, decl, namespaces=[]): # [ funcname, return_ctype, [modifiers], [args] ]
|
||||
GeneralInfo.__init__(self, "func", decl, namespaces)
|
||||
self.cname = decl[0].replace(".", "::")
|
||||
self.cname = get_cname(decl[0])
|
||||
self.jname = self.name
|
||||
self.isconstructor = self.name == self.classname
|
||||
if "[" in self.name:
|
||||
@ -403,13 +423,16 @@ class JavaWrapperGenerator(object):
|
||||
)
|
||||
logging.info('ok: class %s, name: %s, base: %s', classinfo, name, classinfo.base)
|
||||
|
||||
def add_const(self, decl): # [ "const cname", val, [], [] ]
|
||||
constinfo = ConstInfo(decl, namespaces=self.namespaces)
|
||||
def add_const(self, decl, enumType=None): # [ "const cname", val, [], [] ]
|
||||
constinfo = ConstInfo(decl, namespaces=self.namespaces, enumType=enumType)
|
||||
if constinfo.isIgnored():
|
||||
logging.info('ignored: %s', constinfo)
|
||||
elif not self.isWrapped(constinfo.classname):
|
||||
logging.info('class not found: %s', constinfo)
|
||||
else:
|
||||
if not self.isWrapped(constinfo.classname):
|
||||
logging.info('class not found: %s', constinfo)
|
||||
constinfo.name = constinfo.classname + '_' + constinfo.name
|
||||
constinfo.classname = ''
|
||||
|
||||
ci = self.getClass(constinfo.classname)
|
||||
duplicate = ci.getConst(constinfo.name)
|
||||
if duplicate:
|
||||
@ -421,6 +444,18 @@ class JavaWrapperGenerator(object):
|
||||
ci.addConst(constinfo)
|
||||
logging.info('ok: %s', constinfo)
|
||||
|
||||
def add_enum(self, decl): # [ "enum cname", "", [], [] ]
|
||||
enumType = decl[0].rsplit(" ", 1)[1]
|
||||
if enumType.endswith("<unnamed>"):
|
||||
enumType = None
|
||||
else:
|
||||
ctype = normalize_class_name(enumType)
|
||||
type_dict[ctype] = { "cast_from" : "int", "cast_to" : get_cname(enumType), "j_type" : "int", "jn_type" : "int", "jni_type" : "jint", "suffix" : "I" }
|
||||
const_decls = decl[3]
|
||||
|
||||
for decl in const_decls:
|
||||
self.add_const(decl, enumType)
|
||||
|
||||
def add_func(self, decl):
|
||||
fi = FuncInfo(decl, namespaces=self.namespaces)
|
||||
classname = fi.classname or self.Module
|
||||
@ -479,6 +514,9 @@ class JavaWrapperGenerator(object):
|
||||
self.add_class(decl)
|
||||
elif name.startswith("const"):
|
||||
self.add_const(decl)
|
||||
elif name.startswith("enum"):
|
||||
# enum
|
||||
self.add_enum(decl)
|
||||
else: # function
|
||||
self.add_func(decl)
|
||||
|
||||
@ -518,7 +556,7 @@ class JavaWrapperGenerator(object):
|
||||
if self.isWrapped(t):
|
||||
return self.getClass(t).fullName(isCPP=True)
|
||||
else:
|
||||
return t
|
||||
return cast_from(t)
|
||||
|
||||
def gen_func(self, ci, fi, prop_name=''):
|
||||
logging.info("%s", fi)
|
||||
@ -551,7 +589,7 @@ class JavaWrapperGenerator(object):
|
||||
msg = "// Return type '%s' is not supported, skipping the function\n\n" % fi.ctype
|
||||
self.skipped_func_list.append(c_decl + "\n" + msg)
|
||||
j_code.write( " "*4 + msg )
|
||||
logging.warning("SKIP:" + c_decl.strip() + "\t due to RET type" + fi.ctype)
|
||||
logging.warning("SKIP:" + c_decl.strip() + "\t due to RET type " + fi.ctype)
|
||||
return
|
||||
for a in fi.args:
|
||||
if a.ctype not in type_dict:
|
||||
@ -563,7 +601,7 @@ class JavaWrapperGenerator(object):
|
||||
msg = "// Unknown type '%s' (%s), skipping the function\n\n" % (a.ctype, a.out or "I")
|
||||
self.skipped_func_list.append(c_decl + "\n" + msg)
|
||||
j_code.write( " "*4 + msg )
|
||||
logging.warning("SKIP:" + c_decl.strip() + "\t due to ARG type" + a.ctype + "/" + (a.out or "I"))
|
||||
logging.warning("SKIP:" + c_decl.strip() + "\t due to ARG type " + a.ctype + "/" + (a.out or "I"))
|
||||
return
|
||||
|
||||
self.ported_func_list.append(c_decl)
|
||||
@ -642,7 +680,7 @@ class JavaWrapperGenerator(object):
|
||||
if "I" in a.out or not a.out or self.isWrapped(a.ctype): # input arg, pass by primitive fields
|
||||
for f in fields:
|
||||
jn_args.append ( ArgInfo([ f[0], a.name + f[1], "", [], "" ]) )
|
||||
jni_args.append( ArgInfo([ f[0], a.name + f[1].replace(".","_").replace("[","").replace("]","").replace("_getNativeObjAddr()","_nativeObj"), "", [], "" ]) )
|
||||
jni_args.append( ArgInfo([ f[0], a.name + normalize_field_name(f[1]), "", [], "" ]) )
|
||||
if "O" in a.out and not self.isWrapped(a.ctype): # out arg, pass as double[]
|
||||
jn_args.append ( ArgInfo([ "double[]", "%s_out" % a.name, "", [], "" ]) )
|
||||
jni_args.append ( ArgInfo([ "double[]", "%s_out" % a.name, "", [], "" ]) )
|
||||
@ -690,7 +728,7 @@ class JavaWrapperGenerator(object):
|
||||
" private static native $type $name($args);\n").substitute(\
|
||||
type = type_dict[fi.ctype].get("jn_type", "double[]"), \
|
||||
name = fi.jname + '_' + str(suffix_counter), \
|
||||
args = ", ".join(["%s %s" % (type_dict[a.ctype]["jn_type"], a.name.replace(".","_").replace("[","").replace("]","").replace("_getNativeObjAddr()","_nativeObj")) for a in jn_args])
|
||||
args = ", ".join(["%s %s" % (type_dict[a.ctype]["jn_type"], normalize_field_name(a.name)) for a in jn_args])
|
||||
) );
|
||||
|
||||
# java part:
|
||||
@ -848,7 +886,7 @@ class JavaWrapperGenerator(object):
|
||||
if not a.out and not "jni_var" in type_dict[a.ctype]:
|
||||
# explicit cast to C type to avoid ambiguous call error on platforms (mingw)
|
||||
# where jni types are different from native types (e.g. jint is not the same as int)
|
||||
jni_name = "(%s)%s" % (a.ctype, jni_name)
|
||||
jni_name = "(%s)%s" % (cast_to(a.ctype), jni_name)
|
||||
if not a.ctype: # hidden
|
||||
jni_name = a.defval
|
||||
cvargs.append( type_dict[a.ctype].get("jni_name", jni_name) % {"n" : a.name})
|
||||
@ -922,11 +960,35 @@ JNIEXPORT $rtype JNICALL Java_org_opencv_${module}_${clazz}_$fname
|
||||
%s;\n\n""" % (",\n"+" "*12).join(["%s = %s" % (c.name, c.value) for c in ci.private_consts])
|
||||
)
|
||||
if ci.consts:
|
||||
logging.info("%s", ci.consts)
|
||||
ci.j_code.write("""
|
||||
enumTypes = set(map(lambda c: c.enumType, ci.consts))
|
||||
grouped_consts = {enumType: [c for c in ci.consts if c.enumType == enumType] for enumType in enumTypes}
|
||||
for typeName, consts in grouped_consts.items():
|
||||
logging.info("%s", consts)
|
||||
if typeName:
|
||||
typeName = typeName.rsplit(".", 1)[-1]
|
||||
###################### Utilize Java enums ######################
|
||||
# ci.j_code.write("""
|
||||
# public enum {1} {{
|
||||
# {0};
|
||||
#
|
||||
# private final int id;
|
||||
# {1}(int id) {{ this.id = id; }}
|
||||
# {1}({1} _this) {{ this.id = _this.id; }}
|
||||
# public int getValue() {{ return id; }}
|
||||
# }}\n\n""".format((",\n"+" "*8).join(["%s(%s)" % (c.name, c.value) for c in consts]), typeName)
|
||||
# )
|
||||
################################################################
|
||||
ci.j_code.write("""
|
||||
// C++: enum {1}
|
||||
public static final int
|
||||
%s;\n\n""" % (",\n"+" "*12).join(["%s = %s" % (c.name, c.value) for c in ci.consts])
|
||||
)
|
||||
{0};\n\n""".format((",\n"+" "*12).join(["%s = %s" % (c.name, c.value) for c in consts]), typeName)
|
||||
)
|
||||
else:
|
||||
ci.j_code.write("""
|
||||
// C++: enum <unnamed>
|
||||
public static final int
|
||||
{0};\n\n""".format((",\n"+" "*12).join(["%s = %s" % (c.name, c.value) for c in consts]))
|
||||
)
|
||||
# methods
|
||||
for fi in ci.getAllMethods():
|
||||
self.gen_func(ci, fi)
|
||||
@ -1123,7 +1185,7 @@ if __name__ == "__main__":
|
||||
with open(srcfiles_fname) as f:
|
||||
srcfiles = [os.path.join(module_location, str(l).strip()) for l in f.readlines() if str(l).strip()]
|
||||
else:
|
||||
re_bad = re.compile(r'(private|.inl.hpp$|_inl.hpp$|.details.hpp$|_winrt.hpp$|/cuda/)')
|
||||
re_bad = re.compile(r'(private|.inl.hpp$|_inl.hpp$|.details.hpp$|_winrt.hpp$|/cuda/|/legacy/)')
|
||||
# .h files before .hpp
|
||||
h_files = []
|
||||
hpp_files = []
|
||||
|
@ -26,15 +26,15 @@ foreach(m ${OPENCV_PYTHON_MODULES})
|
||||
list(APPEND opencv_hdrs "${hdr}")
|
||||
endif()
|
||||
endforeach()
|
||||
file(GLOB hdr ${OPENCV_MODULE_${m}_LOCATION}/misc/python/shadow*.hpp)
|
||||
list(APPEND opencv_hdrs ${hdr})
|
||||
file(GLOB userdef_hdrs ${OPENCV_MODULE_${m}_LOCATION}/misc/python/pyopencv*.hpp)
|
||||
list(APPEND opencv_userdef_hdrs ${userdef_hdrs})
|
||||
endforeach(m)
|
||||
|
||||
# header blacklist
|
||||
ocv_list_filterout(opencv_hdrs "modules/.*\\\\.h$")
|
||||
ocv_list_filterout(opencv_hdrs "modules/core/.*/cuda")
|
||||
ocv_list_filterout(opencv_hdrs "modules/cuda.*")
|
||||
ocv_list_filterout(opencv_hdrs "modules/cudev")
|
||||
ocv_list_filterout(opencv_hdrs "modules/core/.*/cuda/")
|
||||
ocv_list_filterout(opencv_hdrs "modules/core/.*/hal/")
|
||||
ocv_list_filterout(opencv_hdrs "modules/core/.*/opencl/")
|
||||
ocv_list_filterout(opencv_hdrs "modules/.+/utils/.*")
|
||||
@ -43,7 +43,12 @@ ocv_list_filterout(opencv_hdrs "modules/.*_inl\\\\.h*")
|
||||
ocv_list_filterout(opencv_hdrs "modules/.*\\\\.details\\\\.h*")
|
||||
ocv_list_filterout(opencv_hdrs "modules/.*\\\\.private\\\\.h*")
|
||||
ocv_list_filterout(opencv_hdrs "modules/.*/private\\\\.h*")
|
||||
ocv_list_filterout(opencv_hdrs "modules/.*/legacy/.*")
|
||||
ocv_list_filterout(opencv_hdrs "modules/.*/detection_based_tracker\\\\.hpp") # Conditional compilation
|
||||
if(NOT HAVE_CUDA)
|
||||
ocv_list_filterout(opencv_hdrs "modules/cuda.*")
|
||||
ocv_list_filterout(opencv_hdrs "modules/cudev")
|
||||
endif()
|
||||
|
||||
set(cv2_generated_files
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/pyopencv_generated_include.h"
|
||||
|
@ -11,6 +11,20 @@
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
template<typename T, class TEnable = void> // TEnable is used for SFINAE checks
|
||||
struct PyOpenCV_Converter
|
||||
{
|
||||
//static inline bool to(PyObject* obj, T& p, const char* name);
|
||||
//static inline PyObject* from(const T& src);
|
||||
};
|
||||
|
||||
template<typename T> static
|
||||
bool pyopencv_to(PyObject* obj, T& p, const char* name = "<unknown>") { return PyOpenCV_Converter<T>::to(obj, p, name); }
|
||||
|
||||
template<typename T> static
|
||||
PyObject* pyopencv_from(const T& src) { return PyOpenCV_Converter<T>::from(src); }
|
||||
|
||||
|
||||
#define CV_PY_FN_WITH_KW_(fn, flags) (PyCFunction)(void*)(PyCFunctionWithKeywords)(fn), (flags) | METH_VARARGS | METH_KEYWORDS
|
||||
#define CV_PY_FN_NOARGS_(fn, flags) (PyCFunction)(fn), (flags) | METH_NOARGS
|
||||
|
||||
@ -28,6 +42,68 @@
|
||||
# define CV_PYTHON_TYPE_HEAD_INIT() PyObject_HEAD_INIT(&PyType_Type) 0,
|
||||
#endif
|
||||
|
||||
#define CV_PY_TO_CLASS(TYPE) \
|
||||
template<> \
|
||||
bool pyopencv_to(PyObject* dst, TYPE& src, const char* name) \
|
||||
{ \
|
||||
if (!dst || dst == Py_None) \
|
||||
return true; \
|
||||
Ptr<TYPE> ptr; \
|
||||
\
|
||||
if (!pyopencv_to(dst, ptr, name)) return false; \
|
||||
src = *ptr; \
|
||||
return true; \
|
||||
}
|
||||
|
||||
#define CV_PY_FROM_CLASS(TYPE) \
|
||||
template<> \
|
||||
PyObject* pyopencv_from(const TYPE& src) \
|
||||
{ \
|
||||
Ptr<TYPE> ptr(new TYPE()); \
|
||||
\
|
||||
*ptr = src; \
|
||||
return pyopencv_from(ptr); \
|
||||
}
|
||||
|
||||
#define CV_PY_TO_CLASS_PTR(TYPE) \
|
||||
template<> \
|
||||
bool pyopencv_to(PyObject* dst, TYPE*& src, const char* name) \
|
||||
{ \
|
||||
if (!dst || dst == Py_None) \
|
||||
return true; \
|
||||
Ptr<TYPE> ptr; \
|
||||
\
|
||||
if (!pyopencv_to(dst, ptr, name)) return false; \
|
||||
src = ptr; \
|
||||
return true; \
|
||||
}
|
||||
|
||||
#define CV_PY_FROM_CLASS_PTR(TYPE) \
|
||||
static PyObject* pyopencv_from(TYPE*& src) \
|
||||
{ \
|
||||
return pyopencv_from(Ptr<TYPE>(src)); \
|
||||
}
|
||||
|
||||
#define CV_PY_TO_ENUM(TYPE) \
|
||||
template<> \
|
||||
bool pyopencv_to(PyObject* dst, TYPE& src, const char* name) \
|
||||
{ \
|
||||
if (!dst || dst == Py_None) \
|
||||
return true; \
|
||||
int underlying = 0; \
|
||||
\
|
||||
if (!pyopencv_to(dst, underlying, name)) return false; \
|
||||
src = static_cast<TYPE>(underlying); \
|
||||
return true; \
|
||||
}
|
||||
|
||||
#define CV_PY_FROM_ENUM(TYPE) \
|
||||
template<> \
|
||||
PyObject* pyopencv_from(const TYPE& src) \
|
||||
{ \
|
||||
return pyopencv_from(static_cast<int>(src)); \
|
||||
}
|
||||
|
||||
#include "pyopencv_generated_include.h"
|
||||
#include "opencv2/core/types_c.h"
|
||||
|
||||
@ -37,7 +113,7 @@
|
||||
|
||||
#include <map>
|
||||
|
||||
static PyObject* opencv_error = 0;
|
||||
static PyObject* opencv_error = NULL;
|
||||
|
||||
static int failmsg(const char *fmt, ...)
|
||||
{
|
||||
@ -98,6 +174,12 @@ try \
|
||||
} \
|
||||
catch (const cv::Exception &e) \
|
||||
{ \
|
||||
PyObject_SetAttrString(opencv_error, "file", PyString_FromString(e.file.c_str())); \
|
||||
PyObject_SetAttrString(opencv_error, "func", PyString_FromString(e.func.c_str())); \
|
||||
PyObject_SetAttrString(opencv_error, "line", PyInt_FromLong(e.line)); \
|
||||
PyObject_SetAttrString(opencv_error, "code", PyInt_FromLong(e.code)); \
|
||||
PyObject_SetAttrString(opencv_error, "msg", PyString_FromString(e.msg.c_str())); \
|
||||
PyObject_SetAttrString(opencv_error, "err", PyString_FromString(e.err.c_str())); \
|
||||
PyErr_SetString(opencv_error, e.what()); \
|
||||
return 0; \
|
||||
}
|
||||
@ -113,6 +195,7 @@ typedef std::vector<size_t> vector_size_t;
|
||||
typedef std::vector<Point> vector_Point;
|
||||
typedef std::vector<Point2f> vector_Point2f;
|
||||
typedef std::vector<Point3f> vector_Point3f;
|
||||
typedef std::vector<Size> vector_Size;
|
||||
typedef std::vector<Vec2f> vector_Vec2f;
|
||||
typedef std::vector<Vec3f> vector_Vec3f;
|
||||
typedef std::vector<Vec4f> vector_Vec4f;
|
||||
@ -223,12 +306,6 @@ public:
|
||||
NumpyAllocator g_numpyAllocator;
|
||||
|
||||
|
||||
template<typename T> static
|
||||
bool pyopencv_to(PyObject* obj, T& p, const char* name = "<unknown>");
|
||||
|
||||
template<typename T> static
|
||||
PyObject* pyopencv_from(const T& src);
|
||||
|
||||
enum { ARG_NONE = 0, ARG_MAT = 1, ARG_SCALAR = 2 };
|
||||
|
||||
// special case, when the converter needs full ArgInfo structure
|
||||
@ -435,15 +512,6 @@ bool pyopencv_to(PyObject* o, Matx<_Tp, m, n>& mx, const char* name)
|
||||
return pyopencv_to(o, mx, ArgInfo(name, 0));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool pyopencv_to(PyObject *o, Ptr<T>& p, const char *name)
|
||||
{
|
||||
if (!o || o == Py_None)
|
||||
return true;
|
||||
p = makePtr<T>();
|
||||
return pyopencv_to(o, *p, name);
|
||||
}
|
||||
|
||||
template<>
|
||||
PyObject* pyopencv_from(const Mat& m)
|
||||
{
|
||||
@ -468,279 +536,39 @@ PyObject* pyopencv_from(const Matx<_Tp, m, n>& matx)
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
PyObject* pyopencv_from(const cv::Ptr<T>& p)
|
||||
struct PyOpenCV_Converter< cv::Ptr<T> >
|
||||
{
|
||||
if (!p)
|
||||
Py_RETURN_NONE;
|
||||
return pyopencv_from(*p);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
UMat* um;
|
||||
} cv2_UMatWrapperObject;
|
||||
|
||||
static bool PyObject_IsUMat(PyObject *o);
|
||||
|
||||
// UMatWrapper init - try to map arguments from python to UMat constructors
|
||||
static int UMatWrapper_init(PyObject* self_, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
cv2_UMatWrapperObject* self = (cv2_UMatWrapperObject*)self_;
|
||||
if (self == NULL)
|
||||
static PyObject* from(const cv::Ptr<T>& p)
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, "Internal error");
|
||||
return -1;
|
||||
if (!p)
|
||||
Py_RETURN_NONE;
|
||||
return pyopencv_from(*p);
|
||||
}
|
||||
self->um = NULL;
|
||||
static bool to(PyObject *o, Ptr<T>& p, const char *name)
|
||||
{
|
||||
// constructor ()
|
||||
const char *kwlist[] = {NULL};
|
||||
if (PyArg_ParseTupleAndKeywords(args, kwds, "", (char**) kwlist)) {
|
||||
self->um = new UMat();
|
||||
return 0;
|
||||
}
|
||||
PyErr_Clear();
|
||||
if (!o || o == Py_None)
|
||||
return true;
|
||||
p = makePtr<T>();
|
||||
return pyopencv_to(o, *p, name);
|
||||
}
|
||||
{
|
||||
// constructor (rows, cols, type)
|
||||
const char *kwlist[] = {"rows", "cols", "type", NULL};
|
||||
int rows, cols, type;
|
||||
if (PyArg_ParseTupleAndKeywords(args, kwds, "iii", (char**) kwlist, &rows, &cols, &type)) {
|
||||
self->um = new UMat(rows, cols, type);
|
||||
return 0;
|
||||
}
|
||||
PyErr_Clear();
|
||||
}
|
||||
{
|
||||
// constructor (m, rowRange, colRange)
|
||||
const char *kwlist[] = {"m", "rowRange", "colRange", NULL};
|
||||
PyObject *obj = NULL;
|
||||
int y0 = -1, y1 = -1, x0 = -1, x1 = -1;
|
||||
if (PyArg_ParseTupleAndKeywords(args, kwds, "O(ii)|(ii)", (char**) kwlist, &obj, &y0, &y1, &x0, &x1) && PyObject_IsUMat(obj)) {
|
||||
UMat *um_other = ((cv2_UMatWrapperObject *) obj)->um;
|
||||
Range rowRange(y0, y1);
|
||||
Range colRange = (x0 >= 0 && x1 >= 0) ? Range(x0, x1) : Range::all();
|
||||
self->um = new UMat(*um_other, rowRange, colRange);
|
||||
return 0;
|
||||
}
|
||||
PyErr_Clear();
|
||||
}
|
||||
{
|
||||
// constructor (m)
|
||||
const char *kwlist[] = {"m", NULL};
|
||||
PyObject *obj = NULL;
|
||||
if (PyArg_ParseTupleAndKeywords(args, kwds, "O", (char**) kwlist, &obj)) {
|
||||
// constructor (UMat m)
|
||||
if (PyObject_IsUMat(obj)) {
|
||||
UMat *um_other = ((cv2_UMatWrapperObject *) obj)->um;
|
||||
self->um = new UMat(*um_other);
|
||||
return 0;
|
||||
}
|
||||
// python specific constructor from array like object
|
||||
Mat m;
|
||||
if (pyopencv_to(obj, m, ArgInfo("UMatWrapper.np_mat", 0))) {
|
||||
self->um = new UMat();
|
||||
m.copyTo(*self->um);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
PyErr_Clear();
|
||||
}
|
||||
PyErr_SetString(PyExc_TypeError, "no matching UMat constructor found/supported");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void UMatWrapper_dealloc(cv2_UMatWrapperObject* self)
|
||||
{
|
||||
if (self->um)
|
||||
delete self->um;
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
Py_TYPE(self)->tp_free((PyObject*)self);
|
||||
#else
|
||||
self->ob_type->tp_free((PyObject*)self);
|
||||
#endif
|
||||
}
|
||||
|
||||
// UMatWrapper.get() - returns numpy array by transferring UMat data to Mat and than wrapping it to numpy array
|
||||
// (using numpy allocator - and so without unnecessary copy)
|
||||
static PyObject * UMatWrapper_get(PyObject* self_, PyObject * /*args*/)
|
||||
{
|
||||
cv2_UMatWrapperObject* self = (cv2_UMatWrapperObject*)self_;
|
||||
if (self == NULL)
|
||||
return failmsgp("Incorrect type of self (must be 'cv2_UMatWrapperObject')");
|
||||
Mat m;
|
||||
m.allocator = &g_numpyAllocator;
|
||||
self->um->copyTo(m);
|
||||
|
||||
return pyopencv_from(m);
|
||||
}
|
||||
|
||||
// UMatWrapper.handle() - returns the OpenCL handle of the UMat object
|
||||
static PyObject * UMatWrapper_handle(PyObject* self_, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
cv2_UMatWrapperObject* self = (cv2_UMatWrapperObject*)self_;
|
||||
if (self == NULL)
|
||||
return failmsgp("Incorrect type of self (must be 'cv2_UMatWrapperObject')");
|
||||
const char *kwlist[] = {"accessFlags", NULL};
|
||||
int accessFlags;
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", (char**) kwlist, &accessFlags))
|
||||
return 0;
|
||||
return PyLong_FromVoidPtr(self->um->handle(accessFlags));
|
||||
}
|
||||
|
||||
// UMatWrapper.isContinuous() - returns true if the matrix data is continuous
|
||||
static PyObject * UMatWrapper_isContinuous(PyObject* self_, PyObject * /*args*/)
|
||||
{
|
||||
cv2_UMatWrapperObject* self = (cv2_UMatWrapperObject*)self_;
|
||||
if (self == NULL)
|
||||
return failmsgp("Incorrect type of self (must be 'cv2_UMatWrapperObject')");
|
||||
return PyBool_FromLong(self->um->isContinuous());
|
||||
}
|
||||
|
||||
// UMatWrapper.isContinuous() - returns true if the matrix is a submatrix of another matrix
|
||||
static PyObject * UMatWrapper_isSubmatrix(PyObject* self_, PyObject * /*args*/)
|
||||
{
|
||||
cv2_UMatWrapperObject* self = (cv2_UMatWrapperObject*)self_;
|
||||
if (self == NULL)
|
||||
return failmsgp("Incorrect type of self (must be 'cv2_UMatWrapperObject')");
|
||||
return PyBool_FromLong(self->um->isSubmatrix());
|
||||
}
|
||||
|
||||
// UMatWrapper.context() - returns the OpenCL context used by OpenCV UMat
|
||||
static PyObject * UMatWrapper_context(PyObject* /*self_*/, PyObject * /*args*/)
|
||||
{
|
||||
return PyLong_FromVoidPtr(cv::ocl::Context::getDefault().ptr());
|
||||
}
|
||||
|
||||
// UMatWrapper.context() - returns the OpenCL queue used by OpenCV UMat
|
||||
static PyObject * UMatWrapper_queue(PyObject* /*self_*/, PyObject * /*args*/)
|
||||
{
|
||||
return PyLong_FromVoidPtr(cv::ocl::Queue::getDefault().ptr());
|
||||
}
|
||||
|
||||
static PyObject * UMatWrapper_offset_getter(PyObject* self_, void*)
|
||||
{
|
||||
cv2_UMatWrapperObject* self = (cv2_UMatWrapperObject*)self_;
|
||||
if (self == NULL)
|
||||
return failmsgp("Incorrect type of self (must be 'cv2_UMatWrapperObject')");
|
||||
return PyLong_FromSsize_t(self->um->offset);
|
||||
}
|
||||
|
||||
static PyMethodDef UMatWrapper_methods[] = {
|
||||
{"get", CV_PY_FN_NOARGS(UMatWrapper_get),
|
||||
"Returns numpy array"
|
||||
},
|
||||
{"handle", CV_PY_FN_WITH_KW(UMatWrapper_handle),
|
||||
"Returns UMat native handle"
|
||||
},
|
||||
{"isContinuous", CV_PY_FN_NOARGS(UMatWrapper_isContinuous),
|
||||
"Returns true if the matrix data is continuous"
|
||||
},
|
||||
{"isSubmatrix", CV_PY_FN_NOARGS(UMatWrapper_isSubmatrix),
|
||||
"Returns true if the matrix is a submatrix of another matrix"
|
||||
},
|
||||
{"context", CV_PY_FN_NOARGS_(UMatWrapper_context, METH_STATIC),
|
||||
"Returns OpenCL context handle"
|
||||
},
|
||||
{"queue", CV_PY_FN_NOARGS_(UMatWrapper_queue, METH_STATIC),
|
||||
"Returns OpenCL queue handle"
|
||||
},
|
||||
{NULL, NULL, 0, NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
static PyGetSetDef UMatWrapper_getset[] = {
|
||||
{(char*) "offset", (getter) UMatWrapper_offset_getter, NULL, NULL, NULL},
|
||||
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
static PyTypeObject cv2_UMatWrapperType = {
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
#else
|
||||
PyObject_HEAD_INIT(NULL)
|
||||
0, /*ob_size*/
|
||||
#endif
|
||||
"cv2.UMat", /* tp_name */
|
||||
sizeof(cv2_UMatWrapperObject), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
(destructor)UMatWrapper_dealloc, /* tp_dealloc */
|
||||
0, /* tp_print */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
0, /* tp_reserved */
|
||||
0, /* tp_repr */
|
||||
0, /* tp_as_number */
|
||||
0, /* tp_as_sequence */
|
||||
0, /* tp_as_mapping */
|
||||
0, /* tp_hash */
|
||||
0, /* tp_call */
|
||||
0, /* tp_str */
|
||||
0, /* tp_getattro */
|
||||
0, /* tp_setattro */
|
||||
0, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT, /* tp_flags */
|
||||
"OpenCV 3 UMat wrapper. Used for T-API support.", /* tp_doc */
|
||||
0, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
0, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
UMatWrapper_methods, /* tp_methods */
|
||||
0, /* tp_members */
|
||||
UMatWrapper_getset, /* tp_getset */
|
||||
0, /* tp_base */
|
||||
0, /* tp_dict */
|
||||
0, /* tp_descr_get */
|
||||
0, /* tp_descr_set */
|
||||
0, /* tp_dictoffset */
|
||||
(initproc)UMatWrapper_init, /* tp_init */
|
||||
0, /* tp_alloc */
|
||||
PyType_GenericNew, /* tp_new */
|
||||
0, /* tp_free */
|
||||
0, /* tp_is_gc */
|
||||
0, /* tp_bases */
|
||||
0, /* tp_mro */
|
||||
0, /* tp_cache */
|
||||
0, /* tp_subclasses */
|
||||
0, /* tp_weaklist */
|
||||
0, /* tp_del */
|
||||
0, /* tp_version_tag */
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
0, /* tp_finalize */
|
||||
#endif
|
||||
};
|
||||
|
||||
static bool PyObject_IsUMat(PyObject *o) {
|
||||
return (o != NULL) && PyObject_TypeCheck(o, &cv2_UMatWrapperType);
|
||||
}
|
||||
|
||||
static bool pyopencv_to(PyObject* o, UMat& um, const ArgInfo info) {
|
||||
if (PyObject_IsUMat(o)) {
|
||||
um = *((cv2_UMatWrapperObject *) o)->um;
|
||||
template<>
|
||||
bool pyopencv_to(PyObject* obj, void*& ptr, const char* name)
|
||||
{
|
||||
CV_UNUSED(name);
|
||||
if (!obj || obj == Py_None)
|
||||
return true;
|
||||
}
|
||||
|
||||
Mat m;
|
||||
if (!pyopencv_to(o, m, info)) {
|
||||
if (!PyLong_Check(obj))
|
||||
return false;
|
||||
}
|
||||
|
||||
m.copyTo(um);
|
||||
return true;
|
||||
ptr = PyLong_AsVoidPtr(obj);
|
||||
return ptr != NULL && !PyErr_Occurred();
|
||||
}
|
||||
|
||||
template<>
|
||||
bool pyopencv_to(PyObject* o, UMat& um, const char* name)
|
||||
static PyObject* pyopencv_from(void*& ptr)
|
||||
{
|
||||
return pyopencv_to(o, um, ArgInfo(name, 0));
|
||||
}
|
||||
|
||||
template<>
|
||||
PyObject* pyopencv_from(const UMat& m) {
|
||||
PyObject *o = PyObject_CallObject((PyObject *) &cv2_UMatWrapperType, NULL);
|
||||
*((cv2_UMatWrapperObject *) o)->um = m;
|
||||
return o;
|
||||
return PyLong_FromVoidPtr(ptr);
|
||||
}
|
||||
|
||||
static bool pyopencv_to(PyObject *o, Scalar& s, const ArgInfo info)
|
||||
@ -1483,6 +1311,19 @@ template<> struct pyopencvVecConverter<Mat>
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct pyopencvVecConverter<UMat>
|
||||
{
|
||||
static bool to(PyObject* obj, std::vector<UMat>& value, const ArgInfo info)
|
||||
{
|
||||
return pyopencv_to_generic_vec(obj, value, info);
|
||||
}
|
||||
|
||||
static PyObject* from(const std::vector<UMat>& value)
|
||||
{
|
||||
return pyopencv_from_generic_vec(value);
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct pyopencvVecConverter<KeyPoint>
|
||||
{
|
||||
static bool to(PyObject* obj, std::vector<KeyPoint>& value, const ArgInfo info)
|
||||
@ -1814,6 +1655,7 @@ static int convert_to_char(PyObject *o, char *dst, const char *name = "no_name")
|
||||
# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
|
||||
#endif
|
||||
|
||||
#include "pyopencv_generated_enums.h"
|
||||
#include "pyopencv_custom_headers.h"
|
||||
#include "pyopencv_generated_types.h"
|
||||
#include "pyopencv_generated_funcs.h"
|
||||
@ -1927,18 +1769,17 @@ void initcv2()
|
||||
|
||||
PyDict_SetItemString(d, "__version__", PyString_FromString(CV_VERSION));
|
||||
|
||||
opencv_error = PyErr_NewException((char*)MODULESTR".error", NULL, NULL);
|
||||
PyObject *opencv_error_dict = PyDict_New();
|
||||
PyDict_SetItemString(opencv_error_dict, "file", Py_None);
|
||||
PyDict_SetItemString(opencv_error_dict, "func", Py_None);
|
||||
PyDict_SetItemString(opencv_error_dict, "line", Py_None);
|
||||
PyDict_SetItemString(opencv_error_dict, "code", Py_None);
|
||||
PyDict_SetItemString(opencv_error_dict, "msg", Py_None);
|
||||
PyDict_SetItemString(opencv_error_dict, "err", Py_None);
|
||||
opencv_error = PyErr_NewException((char*)MODULESTR".error", NULL, opencv_error_dict);
|
||||
Py_DECREF(opencv_error_dict);
|
||||
PyDict_SetItemString(d, "error", opencv_error);
|
||||
|
||||
//Registering UMatWrapper python class in cv2 module:
|
||||
if (PyType_Ready(&cv2_UMatWrapperType) < 0)
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
return NULL;
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
#define PUBLISH_OBJECT(name, type) Py_INCREF(&type);\
|
||||
PyModule_AddObject(m, name, (PyObject *)&type);
|
||||
@ -1949,8 +1790,6 @@ void initcv2()
|
||||
PyModule_AddObject(m, name, (PyObject *)&type);
|
||||
#endif
|
||||
|
||||
PUBLISH_OBJECT("UMat", cv2_UMatWrapperType);
|
||||
|
||||
#include "pyopencv_generated_type_publish.h"
|
||||
|
||||
#define PUBLISH(I) PyDict_SetItemString(d, #I, PyInt_FromLong(I))
|
||||
|
@ -10,19 +10,23 @@ if sys.version_info[0] >= 3:
|
||||
else:
|
||||
from cStringIO import StringIO
|
||||
|
||||
forbidden_arg_types = ["void*"]
|
||||
|
||||
ignored_arg_types = ["RNG*"]
|
||||
|
||||
pass_by_val_types = ["Point*", "Point2f*", "Rect*", "String*", "double*", "float*", "int*"]
|
||||
|
||||
gen_template_check_self = Template(""" $cname* _self_ = NULL;
|
||||
if(PyObject_TypeCheck(self, &pyopencv_${name}_Type))
|
||||
_self_ = ${amp}((pyopencv_${name}_t*)self)->v${get};
|
||||
if (_self_ == NULL)
|
||||
if (!_self_)
|
||||
return failmsgp("Incorrect type of self (must be '${name}' or its derivative)");
|
||||
""")
|
||||
|
||||
gen_template_check_self_algo = Template(""" $cname* _self_ = NULL;
|
||||
if(PyObject_TypeCheck(self, &pyopencv_${name}_Type))
|
||||
_self_ = dynamic_cast<$cname*>(${amp}((pyopencv_${name}_t*)self)->v.get());
|
||||
if (_self_ == NULL)
|
||||
if (!_self_)
|
||||
return failmsgp("Incorrect type of self (must be '${name}' or its derivative)");
|
||||
""")
|
||||
|
||||
@ -68,27 +72,40 @@ static void pyopencv_${name}_dealloc(PyObject* self)
|
||||
PyObject_Del(self);
|
||||
}
|
||||
|
||||
template<> PyObject* pyopencv_from(const ${cname}& r)
|
||||
template<>
|
||||
struct PyOpenCV_Converter< ${cname} >
|
||||
{
|
||||
pyopencv_${name}_t *m = PyObject_NEW(pyopencv_${name}_t, &pyopencv_${name}_Type);
|
||||
new (&m->v) ${cname}(r); //Copy constructor
|
||||
return (PyObject*)m;
|
||||
}
|
||||
|
||||
template<> bool pyopencv_to(PyObject* src, ${cname}& dst, const char* name)
|
||||
{
|
||||
if( src == NULL || src == Py_None )
|
||||
return true;
|
||||
if(!PyObject_TypeCheck(src, &pyopencv_${name}_Type))
|
||||
static PyObject* from(const ${cname}& r)
|
||||
{
|
||||
pyopencv_${name}_t *m = PyObject_NEW(pyopencv_${name}_t, &pyopencv_${name}_Type);
|
||||
new (&m->v) ${cname}(r); //Copy constructor
|
||||
return (PyObject*)m;
|
||||
}
|
||||
|
||||
static bool to(PyObject* src, ${cname}& dst, const char* name)
|
||||
{
|
||||
if(!src || src == Py_None)
|
||||
return true;
|
||||
if(PyObject_TypeCheck(src, &pyopencv_${name}_Type))
|
||||
{
|
||||
dst = ((pyopencv_${name}_t*)src)->v;
|
||||
return true;
|
||||
}
|
||||
failmsg("Expected ${cname} for argument '%%s'", name);
|
||||
return false;
|
||||
}
|
||||
dst = ((pyopencv_${name}_t*)src)->v;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
""" % head_init_str)
|
||||
|
||||
gen_template_mappable = Template("""
|
||||
{
|
||||
${mappable} _src;
|
||||
if (pyopencv_to(src, _src, name))
|
||||
{
|
||||
return cv_mappable_to(_src, dst);
|
||||
}
|
||||
}
|
||||
""")
|
||||
|
||||
gen_template_type_decl = Template("""
|
||||
struct pyopencv_${name}_t
|
||||
@ -110,26 +127,31 @@ static void pyopencv_${name}_dealloc(PyObject* self)
|
||||
PyObject_Del(self);
|
||||
}
|
||||
|
||||
template<> PyObject* pyopencv_from(const Ptr<${cname}>& r)
|
||||
template<>
|
||||
struct PyOpenCV_Converter< Ptr<${cname}> >
|
||||
{
|
||||
pyopencv_${name}_t *m = PyObject_NEW(pyopencv_${name}_t, &pyopencv_${name}_Type);
|
||||
new (&(m->v)) Ptr<$cname1>(); // init Ptr with placement new
|
||||
m->v = r;
|
||||
return (PyObject*)m;
|
||||
}
|
||||
|
||||
template<> bool pyopencv_to(PyObject* src, Ptr<${cname}>& dst, const char* name)
|
||||
{
|
||||
if( src == NULL || src == Py_None )
|
||||
return true;
|
||||
if(!PyObject_TypeCheck(src, &pyopencv_${name}_Type))
|
||||
static PyObject* from(const Ptr<${cname}>& r)
|
||||
{
|
||||
pyopencv_${name}_t *m = PyObject_NEW(pyopencv_${name}_t, &pyopencv_${name}_Type);
|
||||
new (&(m->v)) Ptr<$cname1>(); // init Ptr with placement new
|
||||
m->v = r;
|
||||
return (PyObject*)m;
|
||||
}
|
||||
|
||||
static bool to(PyObject* src, Ptr<${cname}>& dst, const char* name)
|
||||
{
|
||||
if(!src || src == Py_None)
|
||||
return true;
|
||||
if(PyObject_TypeCheck(src, &pyopencv_${name}_Type))
|
||||
{
|
||||
dst = ((pyopencv_${name}_t*)src)->v.dynamicCast<${cname}>();
|
||||
return true;
|
||||
}
|
||||
${mappable_code}
|
||||
failmsg("Expected ${cname} for argument '%%s'", name);
|
||||
return false;
|
||||
}
|
||||
dst = ((pyopencv_${name}_t*)src)->v.dynamicCast<${cname}>();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
""" % head_init_str)
|
||||
|
||||
@ -192,7 +214,7 @@ gen_template_get_prop_algo = Template("""
|
||||
static PyObject* pyopencv_${name}_get_${member}(pyopencv_${name}_t* p, void *closure)
|
||||
{
|
||||
$cname* _self_ = dynamic_cast<$cname*>(p->v.get());
|
||||
if (_self_ == NULL)
|
||||
if (!_self_)
|
||||
return failmsgp("Incorrect type of object (must be '${name}' or its derivative)");
|
||||
return pyopencv_from(_self_${access}${member});
|
||||
}
|
||||
@ -201,7 +223,7 @@ static PyObject* pyopencv_${name}_get_${member}(pyopencv_${name}_t* p, void *clo
|
||||
gen_template_set_prop = Template("""
|
||||
static int pyopencv_${name}_set_${member}(pyopencv_${name}_t* p, PyObject *value, void *closure)
|
||||
{
|
||||
if (value == NULL)
|
||||
if (!value)
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, "Cannot delete the ${member} attribute");
|
||||
return -1;
|
||||
@ -213,13 +235,13 @@ static int pyopencv_${name}_set_${member}(pyopencv_${name}_t* p, PyObject *value
|
||||
gen_template_set_prop_algo = Template("""
|
||||
static int pyopencv_${name}_set_${member}(pyopencv_${name}_t* p, PyObject *value, void *closure)
|
||||
{
|
||||
if (value == NULL)
|
||||
if (!value)
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, "Cannot delete the ${member} attribute");
|
||||
return -1;
|
||||
}
|
||||
$cname* _self_ = dynamic_cast<$cname*>(p->v.get());
|
||||
if (_self_ == NULL)
|
||||
if (!_self_)
|
||||
{
|
||||
failmsgp("Incorrect type of object (must be '${name}' or its derivative)");
|
||||
return -1;
|
||||
@ -265,6 +287,7 @@ class ClassInfo(object):
|
||||
self.isalgorithm = False
|
||||
self.methods = {}
|
||||
self.props = []
|
||||
self.mappables = []
|
||||
self.consts = {}
|
||||
self.base = None
|
||||
self.constructor = None
|
||||
@ -402,7 +425,7 @@ class ArgInfo(object):
|
||||
self.py_outputarg = False
|
||||
|
||||
def isbig(self):
|
||||
return self.tp == "Mat" or self.tp == "vector_Mat"\
|
||||
return self.tp == "Mat" or self.tp == "vector_Mat" or self.tp == "cuda::GpuMat"\
|
||||
or self.tp == "UMat" or self.tp == "vector_UMat" # or self.tp.startswith("vector")
|
||||
|
||||
def crepr(self):
|
||||
@ -410,10 +433,11 @@ class ArgInfo(object):
|
||||
|
||||
|
||||
class FuncVariant(object):
|
||||
def __init__(self, classname, name, decl, isconstructor):
|
||||
def __init__(self, classname, name, decl, isconstructor, isphantom=False):
|
||||
self.classname = classname
|
||||
self.name = self.wname = name
|
||||
self.isconstructor = isconstructor
|
||||
self.isphantom = isphantom
|
||||
|
||||
self.docstring = decl[5]
|
||||
|
||||
@ -461,6 +485,7 @@ class FuncVariant(object):
|
||||
argno += 1
|
||||
if a.name in self.array_counters:
|
||||
continue
|
||||
assert not a.tp in forbidden_arg_types, 'Forbidden type "{}" for argument "{}" in "{}" ("{}")'.format(a.tp, a.name, self.name, self.classname)
|
||||
if a.tp in ignored_arg_types:
|
||||
continue
|
||||
if a.returnarg:
|
||||
@ -520,17 +545,17 @@ class FuncVariant(object):
|
||||
|
||||
|
||||
class FuncInfo(object):
|
||||
def __init__(self, classname, name, cname, isconstructor, namespace, isclassmethod):
|
||||
def __init__(self, classname, name, cname, isconstructor, namespace, is_static):
|
||||
self.classname = classname
|
||||
self.name = name
|
||||
self.cname = cname
|
||||
self.isconstructor = isconstructor
|
||||
self.namespace = namespace
|
||||
self.isclassmethod = isclassmethod
|
||||
self.is_static = is_static
|
||||
self.variants = []
|
||||
|
||||
def add_variant(self, decl):
|
||||
self.variants.append(FuncVariant(self.classname, self.name, decl, self.isconstructor))
|
||||
def add_variant(self, decl, isphantom=False):
|
||||
self.variants.append(FuncVariant(self.classname, self.name, decl, self.isconstructor, isphantom))
|
||||
|
||||
def get_wrapper_name(self):
|
||||
name = self.name
|
||||
@ -541,8 +566,8 @@ class FuncInfo(object):
|
||||
else:
|
||||
classname = ""
|
||||
|
||||
if self.isclassmethod:
|
||||
name += "_cls"
|
||||
if self.is_static:
|
||||
name += "_static"
|
||||
|
||||
return "pyopencv_" + self.namespace.replace('.','_') + '_' + classname + name
|
||||
|
||||
@ -601,7 +626,7 @@ class FuncInfo(object):
|
||||
|
||||
return Template(' {"$py_funcname", CV_PY_FN_WITH_KW_($wrap_funcname, $flags), "$py_docstring"},\n'
|
||||
).substitute(py_funcname = self.variants[0].wname, wrap_funcname=self.get_wrapper_name(),
|
||||
flags = 'METH_CLASS' if self.isclassmethod else '0', py_docstring = full_docstring)
|
||||
flags = 'METH_STATIC' if self.is_static else '0', py_docstring = full_docstring)
|
||||
|
||||
def gen_code(self, codegen):
|
||||
all_classes = codegen.classes
|
||||
@ -618,7 +643,7 @@ class FuncInfo(object):
|
||||
selfinfo = all_classes[self.classname]
|
||||
if not self.isconstructor:
|
||||
amp = "&" if selfinfo.issimple else ""
|
||||
if self.isclassmethod:
|
||||
if self.is_static:
|
||||
pass
|
||||
elif selfinfo.isalgorithm:
|
||||
code += gen_template_check_self_algo.substitute(name=selfinfo.name, cname=selfinfo.cname, amp=amp)
|
||||
@ -638,6 +663,9 @@ class FuncInfo(object):
|
||||
all_cargs = []
|
||||
parse_arglist = []
|
||||
|
||||
if v.isphantom and ismethod and not self.is_static:
|
||||
code_args += "_self_"
|
||||
|
||||
# declare all the C function arguments,
|
||||
# add necessary conversions from Python objects to code_cvt_list,
|
||||
# form the function/method call,
|
||||
@ -646,7 +674,7 @@ class FuncInfo(object):
|
||||
if a.tp in ignored_arg_types:
|
||||
defval = a.defval
|
||||
if not defval and a.tp.endswith("*"):
|
||||
defval = 0
|
||||
defval = "0"
|
||||
assert defval
|
||||
if not code_args.endswith("("):
|
||||
code_args += ", "
|
||||
@ -656,15 +684,15 @@ class FuncInfo(object):
|
||||
tp1 = tp = a.tp
|
||||
amp = ""
|
||||
defval0 = ""
|
||||
if tp.endswith("*"):
|
||||
if tp in pass_by_val_types:
|
||||
tp = tp1 = tp[:-1]
|
||||
amp = "&"
|
||||
if tp.endswith("*"):
|
||||
defval0 = "0"
|
||||
tp1 = tp.replace("*", "_ptr")
|
||||
if tp1.endswith("*"):
|
||||
print("Error: type with star: a.tp=%s, tp=%s, tp1=%s" % (a.tp, tp, tp1))
|
||||
sys.exit(-1)
|
||||
tp_candidates = [a.tp, normalize_class_name(self.namespace + "." + a.tp)]
|
||||
if any(tp in codegen.enums.keys() for tp in tp_candidates):
|
||||
defval0 = "static_cast<%s>(%d)" % (a.tp, 0)
|
||||
|
||||
amapping = simple_argtype_mapping.get(tp, (tp, "O", defval0))
|
||||
parse_name = a.name
|
||||
@ -686,6 +714,9 @@ class FuncInfo(object):
|
||||
if "UMat" in tp:
|
||||
if "Mat" in defval and "UMat" not in defval:
|
||||
defval = defval.replace("Mat", "UMat")
|
||||
if "cuda::GpuMat" in tp:
|
||||
if "Mat" in defval and "GpuMat" not in defval:
|
||||
defval = defval.replace("Mat", "cuda::GpuMat")
|
||||
# "tp arg = tp();" is equivalent to "tp arg;" in the case of complex types
|
||||
if defval == tp + "()" and amapping[1] == "O":
|
||||
defval = ""
|
||||
@ -712,13 +743,15 @@ class FuncInfo(object):
|
||||
|
||||
code_prelude = templ_prelude.substitute(name=selfinfo.name, cname=selfinfo.cname)
|
||||
code_fcall = templ.substitute(name=selfinfo.name, cname=selfinfo.cname, args=code_args)
|
||||
if v.isphantom:
|
||||
code_fcall = code_fcall.replace("new " + selfinfo.cname, self.cname.replace("::", "_"))
|
||||
else:
|
||||
code_prelude = ""
|
||||
code_fcall = ""
|
||||
if v.rettype:
|
||||
code_decl += " " + v.rettype + " retval;\n"
|
||||
code_fcall += "retval = "
|
||||
if ismethod and not self.isclassmethod:
|
||||
if not v.isphantom and ismethod and not self.is_static:
|
||||
code_fcall += "_self_->" + self.cname
|
||||
else:
|
||||
code_fcall += self.cname
|
||||
@ -754,7 +787,7 @@ class FuncInfo(object):
|
||||
parse_arglist = ", ".join(["&" + all_cargs[argno][1] for aname, argno in v.py_arglist]),
|
||||
code_cvt = " &&\n ".join(code_cvt_list))
|
||||
else:
|
||||
code_parse = "if(PyObject_Size(args) == 0 && (kw == NULL || PyObject_Size(kw) == 0))"
|
||||
code_parse = "if(PyObject_Size(args) == 0 && (!kw || PyObject_Size(kw) == 0))"
|
||||
|
||||
if len(v.py_outlist) == 0:
|
||||
code_ret = "Py_RETURN_NONE"
|
||||
@ -799,7 +832,7 @@ class FuncInfo(object):
|
||||
#if dump: pprint(vars(classinfo))
|
||||
if self.isconstructor:
|
||||
py_name = 'cv.' + classinfo.wname
|
||||
elif self.isclassmethod:
|
||||
elif self.is_static:
|
||||
py_name = '.'.join([self.namespace, classinfo.sname + '_' + self.variants[0].wname])
|
||||
else:
|
||||
cname = classinfo.cname + '::' + cname
|
||||
@ -833,7 +866,9 @@ class PythonWrapperGenerator(object):
|
||||
self.classes = {}
|
||||
self.namespaces = {}
|
||||
self.consts = {}
|
||||
self.enums = {}
|
||||
self.code_include = StringIO()
|
||||
self.code_enums = StringIO()
|
||||
self.code_types = StringIO()
|
||||
self.code_funcs = StringIO()
|
||||
self.code_type_reg = StringIO()
|
||||
@ -890,6 +925,18 @@ class PythonWrapperGenerator(object):
|
||||
py_signatures.append(dict(name=py_name, value=value))
|
||||
#print(cname + ' => ' + str(py_name) + ' (value=' + value + ')')
|
||||
|
||||
def add_enum(self, name, decl):
|
||||
wname = normalize_class_name(name)
|
||||
if wname.endswith("<unnamed>"):
|
||||
wname = None
|
||||
else:
|
||||
self.enums[wname] = name
|
||||
const_decls = decl[3]
|
||||
|
||||
for decl in const_decls:
|
||||
name = decl[0]
|
||||
self.add_const(name.replace("const ", "").strip(), decl)
|
||||
|
||||
def add_func(self, decl):
|
||||
namespace, classes, barename = self.split_decl_name(decl[0])
|
||||
cname = "::".join(namespace+classes+[barename])
|
||||
@ -902,35 +949,46 @@ class PythonWrapperGenerator(object):
|
||||
namespace = '.'.join(namespace)
|
||||
|
||||
isconstructor = name == bareclassname
|
||||
isclassmethod = False
|
||||
is_static = False
|
||||
isphantom = False
|
||||
mappable = None
|
||||
for m in decl[2]:
|
||||
if m == "/S":
|
||||
isclassmethod = True
|
||||
is_static = True
|
||||
elif m == "/phantom":
|
||||
isphantom = True
|
||||
cname = cname.replace("::", "_")
|
||||
elif m.startswith("="):
|
||||
name = m[1:]
|
||||
elif m.startswith("/mappable="):
|
||||
mappable = m[10:]
|
||||
self.classes[classname].mappables.append(mappable)
|
||||
return
|
||||
|
||||
if isconstructor:
|
||||
name = "_".join(classes[:-1]+[name])
|
||||
|
||||
if isclassmethod:
|
||||
if is_static:
|
||||
# Add it as a method to the class
|
||||
func_map = self.classes[classname].methods
|
||||
func = func_map.setdefault(name, FuncInfo(classname, name, cname, isconstructor, namespace, isclassmethod))
|
||||
func.add_variant(decl)
|
||||
func = func_map.setdefault(name, FuncInfo(classname, name, cname, isconstructor, namespace, is_static))
|
||||
func.add_variant(decl, isphantom)
|
||||
|
||||
# Add it as global function
|
||||
g_name = "_".join(classes+[name])
|
||||
func_map = self.namespaces.setdefault(namespace, Namespace()).funcs
|
||||
func = func_map.setdefault(g_name, FuncInfo("", g_name, cname, isconstructor, namespace, False))
|
||||
func.add_variant(decl)
|
||||
func.add_variant(decl, isphantom)
|
||||
else:
|
||||
if classname and not isconstructor:
|
||||
cname = barename
|
||||
if not isphantom:
|
||||
cname = barename
|
||||
func_map = self.classes[classname].methods
|
||||
else:
|
||||
func_map = self.namespaces.setdefault(namespace, Namespace()).funcs
|
||||
|
||||
func = func_map.setdefault(name, FuncInfo(classname, name, cname, isconstructor, namespace, isclassmethod))
|
||||
func.add_variant(decl)
|
||||
func = func_map.setdefault(name, FuncInfo(classname, name, cname, isconstructor, namespace, is_static))
|
||||
func.add_variant(decl, isphantom)
|
||||
|
||||
if classname and isconstructor:
|
||||
self.classes[classname].constructor = func
|
||||
@ -949,10 +1007,10 @@ class PythonWrapperGenerator(object):
|
||||
|
||||
self.code_ns_reg.write('static ConstDef consts_%s[] = {\n'%wname)
|
||||
for name, cname in sorted(ns.consts.items()):
|
||||
self.code_ns_reg.write(' {"%s", %s},\n'%(name, cname))
|
||||
self.code_ns_reg.write(' {"%s", static_cast<long>(%s)},\n'%(name, cname))
|
||||
compat_name = re.sub(r"([a-z])([A-Z])", r"\1_\2", name).upper()
|
||||
if name != compat_name:
|
||||
self.code_ns_reg.write(' {"%s", %s},\n'%(compat_name, cname))
|
||||
self.code_ns_reg.write(' {"%s", static_cast<long>(%s)},\n'%(compat_name, cname))
|
||||
self.code_ns_reg.write(' {NULL, 0}\n};\n\n')
|
||||
|
||||
def gen_namespaces_reg(self):
|
||||
@ -963,6 +1021,21 @@ class PythonWrapperGenerator(object):
|
||||
self.code_ns_reg.write(' init_submodule(root, MODULESTR"%s", methods_%s, consts_%s);\n' % (ns_name[2:], wname, wname))
|
||||
self.code_ns_reg.write('};\n')
|
||||
|
||||
def gen_enum_reg(self, enum_name):
|
||||
name_seg = enum_name.split(".")
|
||||
is_enum_class = False
|
||||
if len(name_seg) >= 2 and name_seg[-1] == name_seg[-2]:
|
||||
enum_name = ".".join(name_seg[:-1])
|
||||
is_enum_class = True
|
||||
|
||||
wname = normalize_class_name(enum_name)
|
||||
cname = enum_name.replace(".", "::")
|
||||
|
||||
code = ""
|
||||
if re.sub(r"^cv\.", "", enum_name) != wname:
|
||||
code += "typedef enum {0} {1};\n".format(cname, wname)
|
||||
code += "CV_PY_FROM_ENUM({0});\nCV_PY_TO_ENUM({0});\n\n".format(wname)
|
||||
self.code_enums.write(code)
|
||||
|
||||
def save(self, path, name, buf):
|
||||
with open(path + "/" + name, "wt") as f:
|
||||
@ -975,14 +1048,15 @@ class PythonWrapperGenerator(object):
|
||||
|
||||
def gen(self, srcfiles, output_path):
|
||||
self.clear()
|
||||
self.parser = hdr_parser.CppHeaderParser(generate_umat_decls=True)
|
||||
self.parser = hdr_parser.CppHeaderParser(generate_umat_decls=True, generate_gpumat_decls=False)
|
||||
|
||||
# step 1: scan the headers and build more descriptive maps of classes, consts, functions
|
||||
for hdr in srcfiles:
|
||||
decls = self.parser.parse(hdr)
|
||||
if len(decls) == 0:
|
||||
continue
|
||||
self.code_include.write( '#include "{0}"\n'.format(hdr[hdr.rindex('opencv2/'):]) )
|
||||
if hdr.find('opencv2/') >= 0: #Avoid including the shadow files
|
||||
self.code_include.write( '#include "{0}"\n'.format(hdr[hdr.rindex('opencv2/'):]) )
|
||||
for decl in decls:
|
||||
name = decl[0]
|
||||
if name.startswith("struct") or name.startswith("class"):
|
||||
@ -994,6 +1068,9 @@ class PythonWrapperGenerator(object):
|
||||
elif name.startswith("const"):
|
||||
# constant
|
||||
self.add_const(name.replace("const ", "").strip(), decl)
|
||||
elif name.startswith("enum"):
|
||||
# enum
|
||||
self.add_enum(name.rsplit(" ", 1)[1], decl)
|
||||
else:
|
||||
# function
|
||||
self.add_func(decl)
|
||||
@ -1043,8 +1120,11 @@ class PythonWrapperGenerator(object):
|
||||
templ = gen_template_simple_type_decl
|
||||
else:
|
||||
templ = gen_template_type_decl
|
||||
mappable_code = "\n".join([
|
||||
gen_template_mappable.substitute(cname=classinfo.cname, mappable=mappable)
|
||||
for mappable in classinfo.mappables])
|
||||
self.code_types.write(templ.substitute(name=name, wname=classinfo.wname, cname=classinfo.cname, sname=classinfo.sname,
|
||||
cname1=("cv::Algorithm" if classinfo.isalgorithm else classinfo.cname)))
|
||||
cname1=("cv::Algorithm" if classinfo.isalgorithm else classinfo.cname), mappable_code=mappable_code))
|
||||
|
||||
# register classes in the same order as they have been declared.
|
||||
# this way, base classes will be registered in Python before their derivatives.
|
||||
@ -1070,7 +1150,13 @@ class PythonWrapperGenerator(object):
|
||||
self.gen_namespace(ns_name)
|
||||
self.gen_namespaces_reg()
|
||||
|
||||
# step 4: generate the code for constants
|
||||
# step 4: generate the code for enum types
|
||||
enumlist = list(self.enums.values())
|
||||
enumlist.sort()
|
||||
for name in enumlist:
|
||||
self.gen_enum_reg(name)
|
||||
|
||||
# step 5: generate the code for constants
|
||||
constlist = list(self.consts.items())
|
||||
constlist.sort()
|
||||
for name, constinfo in constlist:
|
||||
@ -1079,6 +1165,7 @@ class PythonWrapperGenerator(object):
|
||||
# That's it. Now save all the files
|
||||
self.save(output_path, "pyopencv_generated_include.h", self.code_include)
|
||||
self.save(output_path, "pyopencv_generated_funcs.h", self.code_funcs)
|
||||
self.save(output_path, "pyopencv_generated_enums.h", self.code_enums)
|
||||
self.save(output_path, "pyopencv_generated_types.h", self.code_types)
|
||||
self.save(output_path, "pyopencv_generated_type_reg.h", self.code_type_reg)
|
||||
self.save(output_path, "pyopencv_generated_ns_reg.h", self.code_ns_reg)
|
||||
|
@ -6,6 +6,7 @@ import os, sys, re, string, io
|
||||
# the list only for debugging. The real list, used in the real OpenCV build, is specified in CMakeLists.txt
|
||||
opencv_hdr_list = [
|
||||
"../../core/include/opencv2/core.hpp",
|
||||
"../../core/include/opencv2/core/mat.hpp",
|
||||
"../../core/include/opencv2/core/ocl.hpp",
|
||||
"../../flann/include/opencv2/flann/miniflann.hpp",
|
||||
"../../ml/include/opencv2/ml.hpp",
|
||||
@ -32,8 +33,9 @@ original_return_type is None if the original_return_type is the same as return_v
|
||||
|
||||
class CppHeaderParser(object):
|
||||
|
||||
def __init__(self, generate_umat_decls=False):
|
||||
def __init__(self, generate_umat_decls=False, generate_gpumat_decls=False):
|
||||
self._generate_umat_decls = generate_umat_decls
|
||||
self._generate_gpumat_decls = generate_gpumat_decls
|
||||
|
||||
self.BLOCK_TYPE = 0
|
||||
self.BLOCK_NAME = 1
|
||||
@ -375,11 +377,9 @@ class CppHeaderParser(object):
|
||||
decl[2].append("/A")
|
||||
if bool(re.match(r".*\)\s*const(\s*=\s*0)?", decl_str)):
|
||||
decl[2].append("/C")
|
||||
if "virtual" in decl_str:
|
||||
print(decl_str)
|
||||
return decl
|
||||
|
||||
def parse_func_decl(self, decl_str, use_umat=False, docstring=""):
|
||||
def parse_func_decl(self, decl_str, mat="Mat", docstring=""):
|
||||
"""
|
||||
Parses the function or method declaration in the form:
|
||||
[([CV_EXPORTS] <rettype>) | CVAPI(rettype)]
|
||||
@ -392,8 +392,7 @@ class CppHeaderParser(object):
|
||||
"""
|
||||
|
||||
if self.wrap_mode:
|
||||
if not (("CV_EXPORTS_AS" in decl_str) or ("CV_EXPORTS_W" in decl_str) or \
|
||||
("CV_WRAP" in decl_str) or ("CV_WRAP_AS" in decl_str)):
|
||||
if not (("CV_EXPORTS_AS" in decl_str) or ("CV_EXPORTS_W" in decl_str) or ("CV_WRAP" in decl_str)):
|
||||
return []
|
||||
|
||||
# ignore old API in the documentation check (for now)
|
||||
@ -413,6 +412,16 @@ class CppHeaderParser(object):
|
||||
arg, npos3 = self.get_macro_arg(decl_str, npos)
|
||||
func_modlist.append("="+arg)
|
||||
decl_str = decl_str[:npos] + decl_str[npos3+1:]
|
||||
npos = decl_str.find("CV_WRAP_PHANTOM")
|
||||
if npos >= 0:
|
||||
decl_str, _ = self.get_macro_arg(decl_str, npos)
|
||||
func_modlist.append("/phantom")
|
||||
npos = decl_str.find("CV_WRAP_MAPPABLE")
|
||||
if npos >= 0:
|
||||
mappable, npos3 = self.get_macro_arg(decl_str, npos)
|
||||
func_modlist.append("/mappable="+mappable)
|
||||
classname = top[1]
|
||||
return ['.'.join([classname, classname]), None, func_modlist, [], None, None]
|
||||
|
||||
virtual_method = False
|
||||
pure_virtual_method = False
|
||||
@ -526,8 +535,6 @@ class CppHeaderParser(object):
|
||||
t, npos = self.find_next_token(decl_str, ["(", ")", ",", "<", ">"], npos)
|
||||
if not t:
|
||||
print("Error: no closing ')' at %d" % (self.lineno,))
|
||||
print(decl_str)
|
||||
print(decl_str[arg_start:])
|
||||
sys.exit(-1)
|
||||
if t == "<":
|
||||
angle_balance += 1
|
||||
@ -563,8 +570,6 @@ class CppHeaderParser(object):
|
||||
a = a[:eqpos].strip()
|
||||
arg_type, arg_name, modlist, argno = self.parse_arg(a, argno)
|
||||
if self.wrap_mode:
|
||||
mat = "UMat" if use_umat else "Mat"
|
||||
|
||||
# TODO: Vectors should contain UMat, but this is not very easy to support and not very needed
|
||||
vector_mat = "vector_{}".format("Mat")
|
||||
vector_mat_template = "vector<{}>".format("Mat")
|
||||
@ -629,8 +634,10 @@ class CppHeaderParser(object):
|
||||
block_type, block_name = b[self.BLOCK_TYPE], b[self.BLOCK_NAME]
|
||||
if block_type in ["file", "enum"]:
|
||||
continue
|
||||
if block_type not in ["struct", "class", "namespace"]:
|
||||
print("Error at %d: there are non-valid entries in the current block stack " % (self.lineno, self.block_stack))
|
||||
if block_type in ["enum struct", "enum class"] and block_name == name:
|
||||
continue
|
||||
if block_type not in ["struct", "class", "namespace", "enum struct", "enum class"]:
|
||||
print("Error at %d: there are non-valid entries in the current block stack %s" % (self.lineno, self.block_stack))
|
||||
sys.exit(-1)
|
||||
if block_name and (block_type == "namespace" or not qualified_name):
|
||||
n += block_name + "."
|
||||
@ -639,7 +646,7 @@ class CppHeaderParser(object):
|
||||
n = "cv.Algorithm"
|
||||
return n
|
||||
|
||||
def parse_stmt(self, stmt, end_token, use_umat=False, docstring=""):
|
||||
def parse_stmt(self, stmt, end_token, mat="Mat", docstring=""):
|
||||
"""
|
||||
parses the statement (ending with ';' or '}') or a block head (ending with '{')
|
||||
|
||||
@ -706,20 +713,19 @@ class CppHeaderParser(object):
|
||||
decl[1] = ": " + ", ".join([self.get_dotted_name(b).replace(".","::") for b in bases])
|
||||
return stmt_type, classname, True, decl
|
||||
|
||||
if stmt.startswith("enum"):
|
||||
return "enum", "", True, None
|
||||
|
||||
if stmt.startswith("namespace"):
|
||||
stmt_list = stmt.split()
|
||||
if stmt.startswith("enum") or stmt.startswith("namespace"):
|
||||
stmt_list = stmt.rsplit(" ", 1)
|
||||
if len(stmt_list) < 2:
|
||||
stmt_list.append("<unnamed>")
|
||||
return stmt_list[0], stmt_list[1], True, None
|
||||
|
||||
if stmt.startswith("extern") and "\"C\"" in stmt:
|
||||
return "namespace", "", True, None
|
||||
|
||||
if end_token == "}" and context == "enum":
|
||||
if end_token == "}" and context.startswith("enum"):
|
||||
decl = self.parse_enum(stmt)
|
||||
return "enum", "", False, decl
|
||||
name = stack_top[self.BLOCK_NAME]
|
||||
return context, name, False, decl
|
||||
|
||||
if end_token == ";" and stmt.startswith("typedef"):
|
||||
# TODO: handle typedef's more intelligently
|
||||
@ -731,7 +737,7 @@ class CppHeaderParser(object):
|
||||
# since we filtered off the other places where '(' can normally occur:
|
||||
# - code blocks
|
||||
# - function pointer typedef's
|
||||
decl = self.parse_func_decl(stmt, use_umat=use_umat, docstring=docstring)
|
||||
decl = self.parse_func_decl(stmt, mat=mat, docstring=docstring)
|
||||
# we return parse_flag == False to prevent the parser to look inside function/method bodies
|
||||
# (except for tracking the nested blocks)
|
||||
return stmt_type, "", False, decl
|
||||
@ -827,7 +833,7 @@ class CppHeaderParser(object):
|
||||
l = l[pos+2:]
|
||||
state = SCAN
|
||||
|
||||
if l.startswith('CV__'): # just ignore this lines
|
||||
if l.startswith('CV__') or l.startswith('__CV_'): # just ignore these lines
|
||||
#print('IGNORE: ' + l)
|
||||
state = SCAN
|
||||
continue
|
||||
@ -841,11 +847,17 @@ class CppHeaderParser(object):
|
||||
|
||||
if not token:
|
||||
block_head += " " + l
|
||||
break
|
||||
block_head = block_head.strip()
|
||||
if len(block_head) > 0 and block_head[-1] == ')' and block_head.startswith('CV_ENUM_FLAGS('):
|
||||
l = ''
|
||||
token = ';'
|
||||
else:
|
||||
break
|
||||
|
||||
if token == "//":
|
||||
block_head += " " + l[:pos]
|
||||
break
|
||||
l = ''
|
||||
continue
|
||||
|
||||
if token == "/*":
|
||||
block_head += " " + l[:pos]
|
||||
@ -896,20 +908,29 @@ class CppHeaderParser(object):
|
||||
docstring = docstring.strip()
|
||||
stmt_type, name, parse_flag, decl = self.parse_stmt(stmt, token, docstring=docstring)
|
||||
if decl:
|
||||
if stmt_type == "enum":
|
||||
for d in decl:
|
||||
decls.append(d)
|
||||
if stmt_type.startswith("enum"):
|
||||
decls.append([stmt_type + " " + self.get_dotted_name(name), "", [], decl, None, ""])
|
||||
else:
|
||||
decls.append(decl)
|
||||
|
||||
if self._generate_gpumat_decls and "cv.cuda." in decl[0]:
|
||||
# If function takes as one of arguments Mat or vector<Mat> - we want to create the
|
||||
# same declaration working with GpuMat (this is important for T-Api access)
|
||||
args = decl[3]
|
||||
has_mat = len(list(filter(lambda x: x[0] in {"Mat", "vector_Mat"}, args))) > 0
|
||||
if has_mat:
|
||||
_, _, _, gpumat_decl = self.parse_stmt(stmt, token, mat="cuda::GpuMat", docstring=docstring)
|
||||
decls.append(gpumat_decl)
|
||||
|
||||
if self._generate_umat_decls:
|
||||
# If function takes as one of arguments Mat or vector<Mat> - we want to create the
|
||||
# same declaration working with UMat (this is important for T-Api access)
|
||||
args = decl[3]
|
||||
has_mat = len(list(filter(lambda x: x[0] in {"Mat", "vector_Mat"}, args))) > 0
|
||||
if has_mat:
|
||||
_, _, _, umat_decl = self.parse_stmt(stmt, token, use_umat=True, docstring=docstring)
|
||||
_, _, _, umat_decl = self.parse_stmt(stmt, token, mat="UMat", docstring=docstring)
|
||||
decls.append(umat_decl)
|
||||
|
||||
docstring = ""
|
||||
if stmt_type == "namespace":
|
||||
chunks = [block[1] for block in self.block_stack if block[0] == 'namespace'] + [name]
|
||||
@ -952,7 +973,7 @@ class CppHeaderParser(object):
|
||||
print()
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = CppHeaderParser(generate_umat_decls=True)
|
||||
parser = CppHeaderParser(generate_umat_decls=True, generate_gpumat_decls=False)
|
||||
decls = []
|
||||
for hname in opencv_hdr_list:
|
||||
decls += parser.parse(hname)
|
||||
|
@ -1,9 +1,3 @@
|
||||
#ifdef HAVE_OPENCV_STITCHING
|
||||
typedef Stitcher::Status Status;
|
||||
|
||||
template<>
|
||||
PyObject* pyopencv_from(const Status& value)
|
||||
{
|
||||
return PyInt_FromLong(value);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
@ -1,33 +1,6 @@
|
||||
#ifdef HAVE_OPENCV_VIDEOIO
|
||||
typedef std::vector<VideoCaptureAPIs> vector_VideoCaptureAPIs;
|
||||
|
||||
template<>
|
||||
bool pyopencv_to(PyObject *o, cv::VideoCaptureAPIs &v, const char *name)
|
||||
{
|
||||
(void)name;
|
||||
v = CAP_ANY;
|
||||
if (!o || o == Py_None)
|
||||
return false;
|
||||
else if (PyLong_Check(o))
|
||||
{
|
||||
v = VideoCaptureAPIs((int64)PyLong_AsLongLong(o));
|
||||
return true;
|
||||
}
|
||||
else if (PyInt_Check(o))
|
||||
{
|
||||
v = VideoCaptureAPIs((int64)PyInt_AS_LONG(o));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
template<>
|
||||
PyObject* pyopencv_from(const cv::VideoCaptureAPIs &v)
|
||||
{
|
||||
return pyopencv_from((int)(v));
|
||||
}
|
||||
|
||||
template<> struct pyopencvVecConverter<cv::VideoCaptureAPIs>
|
||||
{
|
||||
static bool to(PyObject* obj, std::vector<cv::VideoCaptureAPIs>& value, const ArgInfo info)
|
||||
|
Loading…
Reference in New Issue
Block a user