mirror of
https://github.com/opencv/opencv_contrib.git
synced 2025-10-17 07:04:18 +08:00
matlab: fix bindings generator
This commit is contained in:
@@ -259,6 +259,13 @@ add_custom_command(
|
|||||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/test/help.m ${CMAKE_CURRENT_BINARY_DIR}/+cv
|
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/test/help.m ${CMAKE_CURRENT_BINARY_DIR}/+cv
|
||||||
COMMAND ${CMAKE_COMMAND} -E touch ${GENERATE_PROXY}
|
COMMAND ${CMAKE_COMMAND} -E touch ${GENERATE_PROXY}
|
||||||
COMMENT "Generating Matlab source files"
|
COMMENT "Generating Matlab source files"
|
||||||
|
DEPENDS "${CMAKE_CURRENT_LIST_DIR}/generator/build_info.py"
|
||||||
|
DEPENDS "${CMAKE_CURRENT_LIST_DIR}/generator/cvmex.py"
|
||||||
|
DEPENDS "${CMAKE_CURRENT_LIST_DIR}/generator/filters.py"
|
||||||
|
DEPENDS "${CMAKE_CURRENT_LIST_DIR}/generator/gen_matlab.py"
|
||||||
|
DEPENDS "${CMAKE_CURRENT_LIST_DIR}/generator/parse_tree.py"
|
||||||
|
DEPENDS "${CMAKE_CURRENT_LIST_DIR}/generator/templates/functional.cpp"
|
||||||
|
DEPENDS "${CMAKE_CURRENT_LIST_DIR}/generator/templates/template_function_base.cpp"
|
||||||
)
|
)
|
||||||
|
|
||||||
# compile
|
# compile
|
||||||
|
@@ -28,11 +28,18 @@ endif()
|
|||||||
# 2. attempt compile if required
|
# 2. attempt compile if required
|
||||||
# 3. if the compile fails, throw an error and cancel compilation
|
# 3. if the compile fails, throw an error and cancel compilation
|
||||||
file(GLOB SOURCE_FILES "${CMAKE_CURRENT_BINARY_DIR}/src/*.cpp")
|
file(GLOB SOURCE_FILES "${CMAKE_CURRENT_BINARY_DIR}/src/*.cpp")
|
||||||
|
list(LENGTH SOURCE_FILES __size)
|
||||||
|
message("Matlab: compiling ${__size} files")
|
||||||
|
set(__index 0)
|
||||||
foreach(SOURCE_FILE ${SOURCE_FILES})
|
foreach(SOURCE_FILE ${SOURCE_FILES})
|
||||||
|
MATH(EXPR __index "${__index}+1")
|
||||||
# strip out the filename
|
# strip out the filename
|
||||||
get_filename_component(FILENAME ${SOURCE_FILE} NAME_WE)
|
get_filename_component(FILENAME ${SOURCE_FILE} NAME_WE)
|
||||||
|
message("[${__index}/${__size}] Compiling: ${FILENAME}")
|
||||||
# compile the source file using mex
|
# compile the source file using mex
|
||||||
if (NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/+cv/${FILENAME}.${MATLAB_MEXEXT})
|
if (NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}/+cv/${FILENAME}.${MATLAB_MEXEXT}" OR
|
||||||
|
"${SOURCE_FILE}" IS_NEWER_THAN "${CMAKE_CURRENT_BINARY_DIR}/+cv/${FILENAME}.${MATLAB_MEXEXT}"
|
||||||
|
)
|
||||||
execute_process(
|
execute_process(
|
||||||
COMMAND ${MATLAB_MEX_SCRIPT} ${MEX_OPTS} "CXXFLAGS=\$CXXFLAGS ${MEX_CXXFLAGS}" ${MEX_INCLUDE_DIRS_LIST}
|
COMMAND ${MATLAB_MEX_SCRIPT} ${MEX_OPTS} "CXXFLAGS=\$CXXFLAGS ${MEX_CXXFLAGS}" ${MEX_INCLUDE_DIRS_LIST}
|
||||||
${MEX_LIB_DIR} ${MEX_LIBS_LIST} ${SOURCE_FILE}
|
${MEX_LIB_DIR} ${MEX_LIBS_LIST} ${SOURCE_FILE}
|
||||||
|
@@ -5,8 +5,6 @@ urlexpr = re.compile(r"((https?):((//)|(\\\\))+[\w\d:#@%/;$()~_?\+-=\\\.&]*)", r
|
|||||||
|
|
||||||
def inputs(args):
|
def inputs(args):
|
||||||
'''Keeps only the input arguments in a list of elements.
|
'''Keeps only the input arguments in a list of elements.
|
||||||
In OpenCV input arguments are all arguments with names
|
|
||||||
not beginning with 'dst'
|
|
||||||
'''
|
'''
|
||||||
try:
|
try:
|
||||||
return [arg for arg in args['only'] if arg.I and not arg.O]
|
return [arg for arg in args['only'] if arg.I and not arg.O]
|
||||||
@@ -20,7 +18,7 @@ def ninputs(fun):
|
|||||||
def outputs(args):
|
def outputs(args):
|
||||||
'''Determines whether any of the given arguments is an output
|
'''Determines whether any of the given arguments is an output
|
||||||
reference, and returns a list of only those elements.
|
reference, and returns a list of only those elements.
|
||||||
In OpenCV, output references are preceeded by 'dst'
|
In OpenCV, output references are preceeded by CV_OUT or has *OutputArray* type
|
||||||
'''
|
'''
|
||||||
try:
|
try:
|
||||||
return [arg for arg in args['only'] if arg.O and not arg.I]
|
return [arg for arg in args['only'] if arg.O and not arg.I]
|
||||||
|
@@ -4,6 +4,26 @@ from string import Template
|
|||||||
from parse_tree import ParseTree, todict, constants
|
from parse_tree import ParseTree, todict, constants
|
||||||
from filters import *
|
from filters import *
|
||||||
|
|
||||||
|
updated_files = []
|
||||||
|
|
||||||
|
def update_file(fname, content):
|
||||||
|
if fname in updated_files:
|
||||||
|
print('ERROR(gen_matlab.py): attemption to write file multiple times: {}'.format(fname))
|
||||||
|
return
|
||||||
|
updated_files.append(fname)
|
||||||
|
if os.path.exists(fname):
|
||||||
|
with open(fname, 'rb') as f:
|
||||||
|
old_content = f.read()
|
||||||
|
if old_content == content:
|
||||||
|
#print('Up-to-date: {}'.format(fname))
|
||||||
|
return
|
||||||
|
print('Updating: {}'.format(fname))
|
||||||
|
else:
|
||||||
|
print('Writing: {}'.format(fname))
|
||||||
|
with open(fname, 'wb') as f:
|
||||||
|
f.write(content)
|
||||||
|
|
||||||
|
|
||||||
class MatlabWrapperGenerator(object):
|
class MatlabWrapperGenerator(object):
|
||||||
"""
|
"""
|
||||||
MatlabWrapperGenerator is a class for generating Matlab mex sources from
|
MatlabWrapperGenerator is a class for generating Matlab mex sources from
|
||||||
@@ -107,24 +127,20 @@ class MatlabWrapperGenerator(object):
|
|||||||
# functions
|
# functions
|
||||||
for method in namespace.methods:
|
for method in namespace.methods:
|
||||||
populated = tfunction.render(fun=method, time=time, includes=namespace.name)
|
populated = tfunction.render(fun=method, time=time, includes=namespace.name)
|
||||||
with open(output_source_dir+'/'+method.name+'.cpp', 'wb') as f:
|
update_file(output_source_dir+'/'+method.name+'.cpp', populated.encode('utf-8'))
|
||||||
f.write(populated.encode('utf-8'))
|
|
||||||
# classes
|
# classes
|
||||||
for clss in namespace.classes:
|
for clss in namespace.classes:
|
||||||
# cpp converter
|
# cpp converter
|
||||||
populated = tclassc.render(clss=clss, time=time)
|
populated = tclassc.render(clss=clss, time=time)
|
||||||
with open(output_private_dir+'/'+clss.name+'Bridge.cpp', 'wb') as f:
|
update_file(output_private_dir+'/'+clss.name+'Bridge.cpp', populated.encode('utf-8'))
|
||||||
f.write(populated.encode('utf-8'))
|
|
||||||
# matlab classdef
|
# matlab classdef
|
||||||
populated = tclassm.render(clss=clss, time=time)
|
populated = tclassm.render(clss=clss, time=time)
|
||||||
with open(output_class_dir+'/'+clss.name+'.m', 'wb') as f:
|
update_file(output_class_dir+'/'+clss.name+'.m', populated.encode('utf-8'))
|
||||||
f.write(populated.encode('utf-8'))
|
|
||||||
|
|
||||||
# create a global constants lookup table
|
# create a global constants lookup table
|
||||||
const = dict(constants(todict(parse_tree.namespaces)))
|
const = dict(constants(todict(parse_tree.namespaces)))
|
||||||
populated = tconst.render(constants=const, time=time)
|
populated = tconst.render(constants=const, time=time)
|
||||||
with open(output_dir+'/cv.m', 'wb') as f:
|
update_file(output_dir+'/cv.m', populated.encode('utf-8'))
|
||||||
f.write(populated.encode('utf-8'))
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
@@ -8,6 +8,21 @@ except NameError:
|
|||||||
# Python 3.3+
|
# Python 3.3+
|
||||||
basestring = str
|
basestring = str
|
||||||
|
|
||||||
|
|
||||||
|
valid_types = (
|
||||||
|
'int', 'bool', 'float', 'double', 'size_t', 'char',
|
||||||
|
'Mat', 'Scalar', 'String',
|
||||||
|
'TermCriteria', 'Size', 'Point', 'Point2f', 'Point2d', 'Rect', 'RotatedRect',
|
||||||
|
'RNG', 'DMatch', 'Moments',
|
||||||
|
'vector_Mat', 'vector_Point', 'vector_int', 'vector_float', 'vector_double', 'vector_String', 'vector_uchar', 'vector_Rect', 'vector_DMatch', 'vector_KeyPoint',
|
||||||
|
'vector_Point2f', 'vector_vector_char', 'vector_vector_DMatch', 'vector_vector_KeyPoint',
|
||||||
|
'Ptr_StereoBM', 'Ptr_StereoSGBM', 'Ptr_FeatureDetector', 'Ptr_CLAHE', 'Ptr_LineSegmentDetector', 'Ptr_AlignMTB', 'Ptr_CalibrateDebevec',
|
||||||
|
'Ptr_CalibrateRobertson', 'Ptr_DenseOpticalFlow', 'Ptr_DualTVL1OpticalFlow', 'Ptr_MergeDebevec', 'Ptr_MergeMertens', 'Ptr_MergeRobertson',
|
||||||
|
'Ptr_Stitcher', 'Ptr_Tonemap', 'Ptr_TonemapDrago', 'Ptr_TonemapDurand', 'Ptr_TonemapMantiuk', 'Ptr_TonemapReinhard', 'Ptr_float',
|
||||||
|
# Not supported:
|
||||||
|
#vector_vector_KeyPoint
|
||||||
|
)
|
||||||
|
|
||||||
class ParseTree(object):
|
class ParseTree(object):
|
||||||
"""
|
"""
|
||||||
The ParseTree class produces a semantic tree of C++ definitions given
|
The ParseTree class produces a semantic tree of C++ definitions given
|
||||||
@@ -89,7 +104,11 @@ class ParseTree(object):
|
|||||||
methods = []
|
methods = []
|
||||||
constants = []
|
constants = []
|
||||||
for defn in definitions:
|
for defn in definitions:
|
||||||
obj = babel.translate(defn)
|
try:
|
||||||
|
obj = babel.translate(defn)
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
obj = None
|
||||||
if obj is None:
|
if obj is None:
|
||||||
continue
|
continue
|
||||||
if type(obj) is Class or obj.clss:
|
if type(obj) is Class or obj.clss:
|
||||||
@@ -176,15 +195,15 @@ class Translator(object):
|
|||||||
return Constant(name, clss, tp, const, '', val)
|
return Constant(name, clss, tp, const, '', val)
|
||||||
|
|
||||||
def translateArgument(self, defn):
|
def translateArgument(self, defn):
|
||||||
|
modifiers = defn[3]
|
||||||
ref = '*' if '*' in defn[0] else ''
|
ref = '*' if '*' in defn[0] else ''
|
||||||
ref = '&' if '&' in defn[0] else ref
|
ref = '&' if '&' in defn[0] or '/Ref' in modifiers else ref
|
||||||
const = ' const ' in ' '+defn[0]+' '
|
const = '/C' in modifiers
|
||||||
tp = " ".join([word for word in defn[0].replace(ref, '').split() if not ' const ' in ' '+word+' '])
|
tp = " ".join([word for word in defn[0].replace(ref, '').split() if not ' const ' in ' '+word+' '])
|
||||||
name = defn[1]
|
name = defn[1]
|
||||||
default = defn[2] if defn[2] else ''
|
default = defn[2] if defn[2] else ''
|
||||||
modifiers = ''.join(defn[3])
|
I = True if '/I' in modifiers or not '/O' in modifiers else False
|
||||||
I = True if not modifiers or 'I' in modifiers else False
|
O = True if '/O' in modifiers else False
|
||||||
O = True if 'O' in modifiers else False
|
|
||||||
return Argument(name, tp, const, I, O, ref, default)
|
return Argument(name, tp, const, I, O, ref, default)
|
||||||
|
|
||||||
def translateName(self, name):
|
def translateName(self, name):
|
||||||
@@ -292,6 +311,8 @@ class Argument(object):
|
|||||||
self.O = O
|
self.O = O
|
||||||
self.const = const
|
self.const = const
|
||||||
self.default = default
|
self.default = default
|
||||||
|
if not tp in valid_types:
|
||||||
|
raise Exception("Non-supported argument type: {} (name: {})".format(tp, name))
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return ('const ' if self.const else '')+self.tp+self.ref+\
|
return ('const ' if self.const else '')+self.tp+self.ref+\
|
||||||
|
@@ -104,21 +104,23 @@ addVariant("{{ fun.name }}", {{ fun.req|inputs|length }}, {{ fun.opt|inputs|leng
|
|||||||
{%- macro handleInputs(fun) %}
|
{%- macro handleInputs(fun) %}
|
||||||
|
|
||||||
{% if fun|ninputs or (fun|noutputs and not fun.constructor) %}
|
{% if fun|ninputs or (fun|noutputs and not fun.constructor) %}
|
||||||
// unpack the arguments
|
// - inputs
|
||||||
{# ----------- Inputs ------------- #}
|
|
||||||
{% for arg in fun.req|inputs %}
|
{% for arg in fun.req|inputs %}
|
||||||
{{arg.tp}} {{arg.name}} = inputs[{{ loop.index0 }}].to{{arg.tp|toUpperCamelCase}}();
|
{{arg.tp}} {{arg.name}} = inputs[{{ loop.index0 }}].to{{arg.tp|toUpperCamelCase}}();
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
// - inputs (opt)
|
||||||
{% for opt in fun.opt|inputs %}
|
{% for opt in fun.opt|inputs %}
|
||||||
{{opt.tp}} {{opt.name}} = inputs[{{loop.index0 + fun.req|inputs|length}}].empty() ? ({{opt.tp}}) {% if opt.ref == '*' -%} {{opt.tp}}() {%- else -%} {{opt.default}} {%- endif %} : inputs[{{loop.index0 + fun.req|inputs|length}}].to{{opt.tp|toUpperCamelCase}}();
|
{{opt.tp}} {{opt.name}} = inputs[{{loop.index0 + fun.req|inputs|length}}].empty() ? ({{opt.tp}}) {% if opt.ref == '*' -%} {{opt.tp}}() {%- else -%} {{opt.default}} {%- endif %} : inputs[{{loop.index0 + fun.req|inputs|length}}].to{{opt.tp|toUpperCamelCase}}();
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{# ----------- Outputs ------------ #}
|
// - outputs
|
||||||
{% for arg in fun.req|only|outputs %}
|
{% for arg in fun.req|only|outputs %}
|
||||||
{{arg.tp}} {{arg.name}};
|
{{arg.tp}} {{arg.name}};
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
// - outputs (opt)
|
||||||
{% for opt in fun.opt|only|outputs %}
|
{% for opt in fun.opt|only|outputs %}
|
||||||
{{opt.tp}} {{opt.name}};
|
{{opt.tp}} {{opt.name}};
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
// - return
|
||||||
{% if not fun.rtp|void and not fun.constructor %}
|
{% if not fun.rtp|void and not fun.constructor %}
|
||||||
{{fun.rtp}} retval;
|
{{fun.rtp}} retval;
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@@ -2,11 +2,10 @@
|
|||||||
/*
|
/*
|
||||||
* file: {{clss.name}}Bridge.cpp
|
* file: {{clss.name}}Bridge.cpp
|
||||||
* author: A trusty code generator
|
* author: A trusty code generator
|
||||||
* date: {{time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime())}}
|
|
||||||
*
|
*
|
||||||
* This file was autogenerated, do not modify.
|
* This file was autogenerated, do not modify.
|
||||||
* See LICENSE for full modification and redistribution details.
|
* See LICENSE for full modification and redistribution details.
|
||||||
* Copyright {{time.strftime("%Y", time.localtime())}} The OpenCV Foundation
|
* Copyright 2018 The OpenCV Foundation
|
||||||
*/
|
*/
|
||||||
#include <mex.h>
|
#include <mex.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@@ -2,11 +2,10 @@
|
|||||||
/*
|
/*
|
||||||
* file: {{fun.name}}.cpp
|
* file: {{fun.name}}.cpp
|
||||||
* author: A trusty code generator
|
* author: A trusty code generator
|
||||||
* date: {{time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime())}}
|
|
||||||
*
|
*
|
||||||
* This file was autogenerated, do not modify.
|
* This file was autogenerated, do not modify.
|
||||||
* See LICENSE for full modification and redistribution details.
|
* See LICENSE for full modification and redistribution details.
|
||||||
* Copyright {{time.strftime("%Y", time.localtime())}} The OpenCV Foundation
|
* Copyright 2018 The OpenCV Foundation
|
||||||
*/
|
*/
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
Reference in New Issue
Block a user