提交 f5b58e5f 编写于 作者: A Alexander Alekhin 提交者: Alexander Alekhin

bindings: backport generator from OpenCV 4.x

- better handling of enum arguments
- less merge conflicts
上级 d034ef6f
#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
#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,10 +960,34 @@ 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)
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
{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
%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]))
)
# methods
for fi in ci.getAllMethods():
......@@ -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"
......
此差异已折叠。
此差异已折叠。
......@@ -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
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)
......
#ifdef HAVE_OPENCV_STITCHING
typedef Stitcher::Status Status;
template<>
PyObject* pyopencv_from(const Status& value)
{
return PyInt_FromLong(value);
}
#endif
#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)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册