diff --git a/modules/js/generator/CMakeLists.txt b/modules/js/generator/CMakeLists.txt index 7a53429651..3d66df154f 100644 --- a/modules/js/generator/CMakeLists.txt +++ b/modules/js/generator/CMakeLists.txt @@ -60,6 +60,7 @@ add_custom_command( ${JS_SOURCE_DIR}/src/core_bindings.cpp ${CMAKE_CURRENT_SOURCE_DIR}/embindgen.py ${CMAKE_CURRENT_SOURCE_DIR}/templates.py + "${OPENCV_JS_WHITELIST_FILE}" ${scripts_hdr_parser} #(not needed - generated by CMake) ${CMAKE_CURRENT_BINARY_DIR}/headers.txt ${opencv_hdrs} diff --git a/modules/js/generator/embindgen.py b/modules/js/generator/embindgen.py index dc7a001df1..7eb20c9861 100644 --- a/modules/js/generator/embindgen.py +++ b/modules/js/generator/embindgen.py @@ -104,6 +104,9 @@ def makeWhiteList(module_list): return wl white_list = None +namespace_prefix_override = { + 'dnn' : '' +} # Features to be exported export_enums = False @@ -271,6 +274,8 @@ class FuncVariant(object): class FuncInfo(object): def __init__(self, class_name, name, cname, namespace, isconstructor): + self.name_id = '_'.join([namespace] + ([class_name] if class_name else []) + [name]) # unique id for dict key + self.class_name = class_name self.name = name self.cname = cname @@ -295,9 +300,9 @@ class JSWrapperGenerator(object): self.bindings = [] self.wrapper_funcs = [] - self.classes = {} + self.classes = {} # FIXIT 'classes' should belong to 'namespaces' self.namespaces = {} - self.enums = {} + self.enums = {} # FIXIT 'enums' should belong to 'namespaces' self.parser = hdr_parser.CppHeaderParser() self.class_idx = 0 @@ -419,7 +424,8 @@ class JSWrapperGenerator(object): else: func_map = self.namespaces.setdefault(namespace, Namespace()).funcs - func = func_map.setdefault(name, FuncInfo(class_name, name, cpp_name, namespace, is_constructor)) + fi = FuncInfo(class_name, name, cpp_name, namespace, is_constructor) + func = func_map.setdefault(fi.name_id, fi) variant = FuncVariant(class_name, name, decl, is_constructor, is_class_method, is_const_method, is_virtual_method, is_pure_virtual_method, ref_return, const_return) @@ -430,7 +436,7 @@ class JSWrapperGenerator(object): f.write(buf.getvalue()) f.close() - def gen_function_binding_with_wrapper(self, func, class_info): + def gen_function_binding_with_wrapper(self, func, ns_name, class_info): binding_text = None wrapper_func_text = None @@ -488,8 +494,23 @@ class JSWrapperGenerator(object): # Wrapper function - wrap_func_name = (func.class_name+"_" if class_info != None else "") + func.name.split("::")[-1] + "_wrapper" - js_func_name = func.name + if ns_name != None and ns_name != "cv": + ns_parts = ns_name.split(".") + if ns_parts[0] == "cv": + ns_parts = ns_parts[1:] + ns_part = "_".join(ns_parts) + "_" + ns_id = '_'.join(ns_parts) + ns_prefix = namespace_prefix_override.get(ns_id, ns_id) + if ns_prefix: + ns_prefix = ns_prefix + '_' + else: + ns_prefix = '' + if class_info == None: + js_func_name = ns_prefix + func.name + wrap_func_name = js_func_name + "_wrapper" + else: + wrap_func_name = ns_prefix + func.class_name + "_" + func.name + "_wrapper" + js_func_name = func.name # TODO: Name functions based wrap directives or based on arguments list if index > 0: @@ -740,12 +761,22 @@ class JSWrapperGenerator(object): # step 2: generate bindings # Global functions for ns_name, ns in sorted(self.namespaces.items()): - if ns_name.split('.')[0] != 'cv': + ns_parts = ns_name.split('.') + if ns_parts[0] != 'cv': + print('Ignore namespace: {}'.format(ns_name)) continue - for name, func in sorted(ns.funcs.items()): + else: + ns_parts = ns_parts[1:] + ns_id = '_'.join(ns_parts) + ns_prefix = namespace_prefix_override.get(ns_id, ns_id) + for name_id, func in sorted(ns.funcs.items()): + name = func.name + if ns_prefix: + name = ns_prefix + '_' + name if name in ignore_list: continue if not name in white_list['']: + #print('Not in whitelist: "{}" from ns={}'.format(name, ns_name)) continue ext_cnst = False @@ -769,7 +800,7 @@ class JSWrapperGenerator(object): continue if with_wrapped_functions: - binding, wrapper = self.gen_function_binding_with_wrapper(func, class_info=None) + binding, wrapper = self.gen_function_binding_with_wrapper(func, ns_name, class_info=None) self.bindings += binding self.wrapper_funcs += wrapper else: @@ -802,7 +833,7 @@ class JSWrapperGenerator(object): class_bindings.append(constructor_template.substitute(signature=', '.join(args))) else: if with_wrapped_functions and (len(method.variants) > 1 or len(method.variants[0].args)>0 or "String" in method.variants[0].rettype): - binding, wrapper = self.gen_function_binding_with_wrapper(method, class_info=class_info) + binding, wrapper = self.gen_function_binding_with_wrapper(method, None, class_info=class_info) self.wrapper_funcs = self.wrapper_funcs + wrapper class_bindings = class_bindings + binding else: diff --git a/platforms/js/opencv_js.config.py b/platforms/js/opencv_js.config.py index 3e09805cd3..05d2883b78 100644 --- a/platforms/js/opencv_js.config.py +++ b/platforms/js/opencv_js.config.py @@ -55,8 +55,26 @@ features2d = {'Feature2D': ['detect', 'compute', 'detectAndCompute', 'descriptor 'BFMatcher': ['isMaskSupported', 'create'], '': ['drawKeypoints', 'drawMatches', 'drawMatchesKnn']} -calib3d = {'': ['findHomography', 'calibrateCameraExtended', 'drawFrameAxes', 'estimateAffine2D', \ - 'getDefaultNewCameraMatrix', 'initUndistortRectifyMap', 'Rodrigues', \ - 'solvePnP', 'solvePnPRansac', 'solvePnPRefineLM']} +calib3d = { + '': [ + 'findHomography', + 'calibrateCameraExtended', + 'drawFrameAxes', + 'estimateAffine2D', + 'getDefaultNewCameraMatrix', + 'initUndistortRectifyMap', + 'Rodrigues', + 'solvePnP', + 'solvePnPRansac', + 'solvePnPRefineLM', + 'projectPoints', + + # cv::fisheye namespace + 'fisheye_initUndistortRectifyMap', + 'fisheye_projectPoints', + ], +} white_list = makeWhiteList([core, imgproc, objdetect, video, dnn, features2d, calib3d]) + +# namespace_prefix_override['dnn'] = '' # compatibility stuff (enabled by default)