vendor: OpenCV 5.0.0 snapshot at 755e50675d97db9b7d449d8bd6b09888646f6c6e
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
def substitute(build, output_dir):
|
||||
|
||||
# setup the template engine
|
||||
template_dir = os.path.join(os.path.dirname(__file__), 'templates')
|
||||
jtemplate = Environment(loader=FileSystemLoader(template_dir), trim_blocks=True, lstrip_blocks=True)
|
||||
|
||||
# add the filters
|
||||
jtemplate.filters['csv'] = csv
|
||||
jtemplate.filters['stripExtraSpaces'] = stripExtraSpaces
|
||||
|
||||
# load the template
|
||||
template = jtemplate.get_template('template_build_info.m')
|
||||
|
||||
# create the build directory
|
||||
output_dir = output_dir+'/+cv'
|
||||
if not os.path.isdir(output_dir):
|
||||
os.mkdir(output_dir)
|
||||
|
||||
# populate template
|
||||
populated = template.render(build=build, time=time)
|
||||
with open(os.path.join(output_dir, 'buildInformation.m'), 'wb') as f:
|
||||
f.write(populated.encode('utf-8'))
|
||||
|
||||
if __name__ == "__main__":
|
||||
"""
|
||||
Usage: python build_info.py
|
||||
--os os_version_string
|
||||
--arch [bitness processor]
|
||||
--compiler [id version]
|
||||
--mex_arch arch_string
|
||||
--mex_script /path/to/mex/script
|
||||
--cxx_flags [-list -of -flags -to -passthrough]
|
||||
--opencv_version version_string
|
||||
--commit commit_hash_if_using_git
|
||||
--modules [core imgproc highgui etc]
|
||||
--configuration Debug/Release
|
||||
--outdir /path/to/write/build/info
|
||||
|
||||
build_info.py generates a Matlab function that can be invoked with a call to
|
||||
>> cv.buildInformation();
|
||||
|
||||
This function prints a summary of the user's OS, OpenCV and Matlab build
|
||||
given the information passed to this module. build_info.py invokes Jinja2
|
||||
on the template_build_info.m template.
|
||||
"""
|
||||
|
||||
# parse the input options
|
||||
import sys, re, os, time
|
||||
from argparse import ArgumentParser
|
||||
parser = ArgumentParser()
|
||||
parser.add_argument('--os')
|
||||
parser.add_argument('--arch', nargs=2)
|
||||
parser.add_argument('--compiler', nargs='+')
|
||||
parser.add_argument('--mex_arch')
|
||||
parser.add_argument('--mex_script')
|
||||
parser.add_argument('--mex_opts', default=['-largeArrayDims'], nargs='*')
|
||||
parser.add_argument('--cxx_flags', default=[], nargs='*')
|
||||
parser.add_argument('--opencv_version', default='', nargs='?')
|
||||
parser.add_argument('--commit', default='Not in working git tree', nargs='?')
|
||||
parser.add_argument('--modules', nargs='+')
|
||||
parser.add_argument('--configuration')
|
||||
parser.add_argument('--outdir')
|
||||
build = parser.parse_args()
|
||||
|
||||
from filters import *
|
||||
from jinja2 import Environment, FileSystemLoader
|
||||
|
||||
# populate the build info template
|
||||
substitute(build, build.outdir)
|
||||
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
def substitute(cv, output_dir):
|
||||
|
||||
# setup the template engine
|
||||
template_dir = os.path.join(os.path.dirname(__file__), 'templates')
|
||||
jtemplate = Environment(loader=FileSystemLoader(template_dir), trim_blocks=True, lstrip_blocks=True)
|
||||
|
||||
# add the filters
|
||||
jtemplate.filters['cellarray'] = cellarray
|
||||
jtemplate.filters['split'] = split
|
||||
jtemplate.filters['csv'] = csv
|
||||
|
||||
# load the template
|
||||
template = jtemplate.get_template('template_cvmex_base.m')
|
||||
|
||||
# create the build directory
|
||||
output_dir = output_dir+'/+cv'
|
||||
if not os.path.isdir(output_dir):
|
||||
os.mkdir(output_dir)
|
||||
|
||||
# populate template
|
||||
populated = template.render(cv=cv, time=time)
|
||||
with open(os.path.join(output_dir, 'mex.m'), 'wb') as f:
|
||||
f.write(populated.encode('utf-8'))
|
||||
|
||||
if __name__ == "__main__":
|
||||
"""
|
||||
Usage: python cvmex.py
|
||||
--opts [-list -of -opts]
|
||||
--include_dirs [-list -of -opencv_include_directories]
|
||||
--lib_dir opencv_lib_directory
|
||||
--libs [-lopencv_core -lopencv_imgproc ...]
|
||||
--flags [-Wall -opencv_build_flags ...]
|
||||
--outdir /path/to/generated/output
|
||||
|
||||
cvmex.py generates a custom mex compiler that automatically links OpenCV
|
||||
libraries to built sources where appropriate. The calling syntax is the
|
||||
same as the builtin mex compiler, with added cv qualification:
|
||||
>> cv.mex(..., ...);
|
||||
"""
|
||||
|
||||
# parse the input options
|
||||
import sys, re, os, time
|
||||
from argparse import ArgumentParser
|
||||
parser = ArgumentParser()
|
||||
parser.add_argument('--opts')
|
||||
parser.add_argument('--include_dirs')
|
||||
parser.add_argument('--lib_dir')
|
||||
parser.add_argument('--libs')
|
||||
parser.add_argument('--flags')
|
||||
parser.add_argument('--outdir')
|
||||
cv = parser.parse_args()
|
||||
|
||||
from filters import *
|
||||
from jinja2 import Environment, FileSystemLoader
|
||||
|
||||
# populate the mex base template
|
||||
substitute(cv, cv.outdir)
|
||||
@@ -0,0 +1,177 @@
|
||||
from textwrap import TextWrapper
|
||||
import re, os
|
||||
# precompile a URL matching regular expression
|
||||
urlexpr = re.compile(r"((https?):((//)|(\\\\))+[\w\d:#@%/;$()~_?\+-=\\\.&]*)", re.MULTILINE|re.UNICODE)
|
||||
|
||||
def inputs(args):
|
||||
'''Keeps only the input arguments in a list of elements.
|
||||
'''
|
||||
try:
|
||||
return [arg for arg in args['only'] if arg.I and not arg.O]
|
||||
except:
|
||||
return [arg for arg in args if arg.I]
|
||||
|
||||
def ninputs(fun):
|
||||
'''Counts the number of input arguments in the input list'''
|
||||
return len(inputs(fun.req)) + len(inputs(fun.opt))
|
||||
|
||||
def outputs(args):
|
||||
'''Determines whether any of the given arguments is an output
|
||||
reference, and returns a list of only those elements.
|
||||
In OpenCV, output references are preceded by CV_OUT or has *OutputArray* type
|
||||
'''
|
||||
try:
|
||||
return [arg for arg in args['only'] if arg.O and not arg.I]
|
||||
except:
|
||||
return [arg for arg in args if arg.O]
|
||||
|
||||
def only(args):
|
||||
'''Returns exclusively the arguments which are only inputs
|
||||
or only outputs'''
|
||||
d = {};
|
||||
d['only'] = args
|
||||
return d
|
||||
|
||||
def void(arg):
|
||||
'''Is the input 'void' '''
|
||||
return arg == 'void'
|
||||
|
||||
def flip(arg):
|
||||
'''flip the sign of the input'''
|
||||
return not arg
|
||||
|
||||
def noutputs(fun):
|
||||
'''Counts the number of output arguments in the input list'''
|
||||
return int(not void(fun.rtp)) + len(outputs(fun.req)) + len(outputs(fun.opt))
|
||||
|
||||
def convertibleToInt(string):
|
||||
'''Can the input string be evaluated to an integer?'''
|
||||
salt = '1+'
|
||||
try:
|
||||
exec(salt+string)
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
|
||||
def binaryToDecimal(string):
|
||||
'''Attempt to convert the input string to floating point representation'''
|
||||
try:
|
||||
return str(eval(string))
|
||||
except:
|
||||
return string
|
||||
|
||||
def formatMatlabConstant(string, table):
|
||||
'''
|
||||
Given a string representing a Constant, and a table of all Constants,
|
||||
attempt to resolve the Constant into a valid Matlab expression
|
||||
For example, the input
|
||||
DEPENDENT_VALUE = 1 << FIXED_VALUE
|
||||
needs to be converted to
|
||||
DEPENDENT_VALUE = bitshift(1, cv.FIXED_VALUE);
|
||||
'''
|
||||
# split the string into expressions
|
||||
words = re.split('(\W+)', string)
|
||||
# add a 'cv' prefix if an expression is also a key in the lookup table
|
||||
words = ''.join([('cv.'+word if word in table else word) for word in words])
|
||||
# attempt to convert arithmetic expressions and binary/hex to decimal
|
||||
words = binaryToDecimal(words)
|
||||
# convert any remaining bitshifts to Matlab 'bitshift' methods
|
||||
shift = re.sub('[\(\) ]', '', words).split('<<')
|
||||
words = 'bitshift('+shift[0]+', '+shift[1]+')' if len(shift) == 2 else words
|
||||
return words
|
||||
|
||||
def matlabURL(string):
|
||||
"""This filter is used to construct a Matlab specific URL that calls the
|
||||
system browser instead of the (insanely bad) builtin Matlab browser"""
|
||||
return re.sub(urlexpr, '<a href="matlab: web(\'\\1\', \'-browser\')">\\1</a>', string)
|
||||
|
||||
def capitalizeFirst(text):
|
||||
'''Capitalize only the first character of the text string'''
|
||||
return text[0].upper() + text[1:]
|
||||
|
||||
def toUpperCamelCase(text):
|
||||
'''variable_name --> VariableName'''
|
||||
return ''.join([capitalizeFirst(word) for word in text.split('_')])
|
||||
|
||||
def toLowerCamelCase(text):
|
||||
'''variable_name --> variableName'''
|
||||
upper_camel = toUpperCamelCase(test)
|
||||
return upper_camel[0].lower() + upper_camel[1:]
|
||||
|
||||
def toUnderCase(text):
|
||||
'''VariableName --> variable_name'''
|
||||
s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', text)
|
||||
return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
|
||||
|
||||
def stripTags(text):
|
||||
'''
|
||||
strip or convert html tags from a text string
|
||||
<code>content</code> --> content
|
||||
<anything> --> ''
|
||||
< --> <
|
||||
> --> >
|
||||
&le --> <=
|
||||
&ge --> >=
|
||||
'''
|
||||
upper = lambda pattern: pattern.group(1).upper()
|
||||
text = re.sub('<code>(.*?)</code>', upper, text)
|
||||
text = re.sub('<([^=\s].*?)>', '', text)
|
||||
text = re.sub('<', '<', text)
|
||||
text = re.sub('>', '>', text)
|
||||
text = re.sub('&le', '<=', text)
|
||||
text = re.sub('&ge', '>=', text)
|
||||
return text
|
||||
|
||||
def qualify(text, name):
|
||||
'''Adds uppercase 'CV.' qualification to any occurrences of name in text'''
|
||||
return re.sub(name.upper(), 'CV.'+name.upper(), text)
|
||||
|
||||
def slugify(text):
|
||||
'''A_Function_name --> a-function-name'''
|
||||
return text.lower().replace('_', '-')
|
||||
|
||||
def filename(fullpath):
|
||||
'''Returns only the filename without an extension from a file path
|
||||
eg. /path/to/file.txt --> file
|
||||
'''
|
||||
return os.path.splitext(os.path.basename(fullpath))[0]
|
||||
|
||||
def split(text, delimiter=' '):
|
||||
'''Split a text string into a list using the specified delimiter'''
|
||||
return text.split(delimiter)
|
||||
|
||||
def csv(items, sep=', '):
|
||||
'''format a list with a separator (comma if not specified)'''
|
||||
return sep.join(item for item in items)
|
||||
|
||||
def cellarray(items, escape='\''):
|
||||
'''format a list of items as a matlab cell array'''
|
||||
return '{' + ', '.join(escape+item+escape for item in items) + '}'
|
||||
|
||||
def stripExtraSpaces(text):
|
||||
'''Removes superfluous whitespace from a string, including the removal
|
||||
of all leading and trailing whitespace'''
|
||||
return ' '.join(text.split())
|
||||
|
||||
def comment(text, wrap=80, escape='% ', escape_first='', escape_last=''):
|
||||
'''comment filter
|
||||
Takes a string in text, and wraps it to wrap characters in length with
|
||||
preceding comment escape sequence on each line. escape_first and
|
||||
escape_last can be used for languages which define block comments.
|
||||
Examples:
|
||||
C++ inline comment comment(80, '// ')
|
||||
C block comment: comment(80, ' * ', '/*', ' */')
|
||||
Matlab comment: comment(80, '% ')
|
||||
Matlab block comment: comment(80, '', '%{', '%}')
|
||||
Python docstrings: comment(80, '', '\'\'\'', '\'\'\'')
|
||||
'''
|
||||
|
||||
tw = TextWrapper(width=wrap-len(escape))
|
||||
if escape_first:
|
||||
escape_first = escape_first+'\n'
|
||||
if escape_last:
|
||||
escape_last = '\n'+escape_last
|
||||
escapn = '\n'+escape
|
||||
lines = text.split('\n')
|
||||
wlines = (tw.wrap(line) for line in lines)
|
||||
return escape_first+escape+escapn.join(escapn.join(line) for line in wlines)+escape_last
|
||||
@@ -0,0 +1,194 @@
|
||||
#!/usr/bin/env python
|
||||
import sys, re, os, time
|
||||
from string import Template
|
||||
from parse_tree import ParseTree, todict, constants
|
||||
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):
|
||||
"""
|
||||
MatlabWrapperGenerator is a class for generating Matlab mex sources from
|
||||
a set of C++ headers. MatlabWrapperGenerator objects can be default
|
||||
constructed. Given an instance, the gen() method performs the translation.
|
||||
"""
|
||||
|
||||
def gen(self, module_roots, modules, extras, output_dir):
|
||||
"""
|
||||
Generate a set of Matlab mex source files by parsing exported symbols
|
||||
in a set of C++ headers. The headers can be input in one (or both) of
|
||||
two methods:
|
||||
1. specify module_root and modules
|
||||
Given a path to the OpenCV module root and a list of module names,
|
||||
the headers to parse are implicitly constructed.
|
||||
2. specifiy header locations explicitly in extras
|
||||
Each element in the list of extras must be of the form:
|
||||
'namespace=/full/path/to/extra/header.hpp' where 'namespace' is
|
||||
the namespace in which the definitions should be added.
|
||||
The output_dir specifies the directory to write the generated sources
|
||||
to.
|
||||
"""
|
||||
# dynamically import the parsers
|
||||
from jinja2 import Environment, FileSystemLoader
|
||||
import hdr_parser
|
||||
|
||||
# parse each of the files and store in a dictionary
|
||||
# as a separate "namespace"
|
||||
parser = hdr_parser.CppHeaderParser()
|
||||
|
||||
ns = dict((key, []) for key in modules)
|
||||
path_template = Template('${module}/include/opencv2/${module}.hpp')
|
||||
|
||||
for module in modules:
|
||||
for module_root in module_roots:
|
||||
# construct a header path from the module root and a path template
|
||||
header = os.path.join(module_root, path_template.substitute(module=module))
|
||||
if os.path.isfile(header):
|
||||
break
|
||||
else:
|
||||
raise Exception('no header found for module %s!' % module)
|
||||
|
||||
# parse the definitions
|
||||
ns[module] = parser.parse(header)
|
||||
|
||||
for extra in extras:
|
||||
module = extra.split("=")[0]
|
||||
header = extra.split("=")[1]
|
||||
ns[module] = ns[module] + parser.parse(header) if module in ns else parser.parse(header)
|
||||
|
||||
# cleanify the parser output
|
||||
parse_tree = ParseTree()
|
||||
parse_tree.build(ns)
|
||||
|
||||
# setup the template engine
|
||||
template_dir = os.path.join(os.path.dirname(__file__), 'templates')
|
||||
jtemplate = Environment(loader=FileSystemLoader(template_dir), trim_blocks=True, lstrip_blocks=True)
|
||||
|
||||
# add the custom filters
|
||||
jtemplate.filters['formatMatlabConstant'] = formatMatlabConstant
|
||||
jtemplate.filters['convertibleToInt'] = convertibleToInt
|
||||
jtemplate.filters['toUpperCamelCase'] = toUpperCamelCase
|
||||
jtemplate.filters['toLowerCamelCase'] = toLowerCamelCase
|
||||
jtemplate.filters['toUnderCase'] = toUnderCase
|
||||
jtemplate.filters['matlabURL'] = matlabURL
|
||||
jtemplate.filters['stripTags'] = stripTags
|
||||
jtemplate.filters['filename'] = filename
|
||||
jtemplate.filters['comment'] = comment
|
||||
jtemplate.filters['inputs'] = inputs
|
||||
jtemplate.filters['ninputs'] = ninputs
|
||||
jtemplate.filters['outputs'] = outputs
|
||||
jtemplate.filters['noutputs'] = noutputs
|
||||
jtemplate.filters['qualify'] = qualify
|
||||
jtemplate.filters['slugify'] = slugify
|
||||
jtemplate.filters['only'] = only
|
||||
jtemplate.filters['void'] = void
|
||||
jtemplate.filters['not'] = flip
|
||||
|
||||
# load the templates
|
||||
tfunction = jtemplate.get_template('template_function_base.cpp')
|
||||
tclassm = jtemplate.get_template('template_class_base.m')
|
||||
tclassc = jtemplate.get_template('template_class_base.cpp')
|
||||
tconst = jtemplate.get_template('template_map_base.m')
|
||||
|
||||
# create the build directory
|
||||
output_source_dir = output_dir+'/src'
|
||||
output_private_dir = output_source_dir+'/private'
|
||||
output_class_dir = output_dir+'/+cv'
|
||||
output_map_dir = output_dir+'/map'
|
||||
if not os.path.isdir(output_source_dir):
|
||||
os.makedirs(output_source_dir)
|
||||
if not os.path.isdir(output_private_dir):
|
||||
os.makedirs(output_private_dir)
|
||||
if not os.path.isdir(output_class_dir):
|
||||
os.makedirs(output_class_dir)
|
||||
if not os.path.isdir(output_map_dir):
|
||||
os.makedirs(output_map_dir)
|
||||
|
||||
# populate templates
|
||||
for namespace in parse_tree.namespaces:
|
||||
# functions
|
||||
for method in namespace.methods:
|
||||
populated = tfunction.render(fun=method, time=time, includes=namespace.name)
|
||||
update_file(output_source_dir+'/'+method.name+'.cpp', populated.encode('utf-8'))
|
||||
# classes
|
||||
for clss in namespace.classes:
|
||||
# cpp converter
|
||||
populated = tclassc.render(clss=clss, time=time)
|
||||
update_file(output_private_dir+'/'+clss.name+'Bridge.cpp', populated.encode('utf-8'))
|
||||
# matlab classdef
|
||||
populated = tclassm.render(clss=clss, time=time)
|
||||
update_file(output_class_dir+'/'+clss.name+'.m', populated.encode('utf-8'))
|
||||
|
||||
# create a global constants lookup table
|
||||
const = dict(constants(todict(parse_tree.namespaces)))
|
||||
populated = tconst.render(constants=const, time=time)
|
||||
update_file(output_dir+'/cv.m', populated.encode('utf-8'))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
"""
|
||||
Usage: python gen_matlab.py
|
||||
--hdrparser /path/to/hdr_parser/dir
|
||||
--moduleroot [ /path/to/opencv/modules /path/to/opencv_contrib/modules etc ]
|
||||
--modules [core imgproc objdetect etc]
|
||||
--extra namespace=/path/to/extra/header.hpp
|
||||
--outdir /path/to/output/generated/srcs
|
||||
|
||||
gen_matlab.py is the main control script for generating matlab source
|
||||
files from given set of headers. Internally, gen_matlab:
|
||||
1. constructs the headers to parse from the module root and list of modules
|
||||
2. parses the headers using CppHeaderParser
|
||||
3. refactors the definitions using ParseTree
|
||||
4. populates the templates for classes, function, enums from the
|
||||
definitions
|
||||
|
||||
gen_matlab.py requires the following inputs:
|
||||
--hdrparser the path to the header parser directory
|
||||
(opencv/modules/python/src2)
|
||||
--moduleroot (optional) paths to the opencv directories containing the modules
|
||||
--modules (optional - required if --moduleroot specified) the modules
|
||||
to produce bindings for. The path to the include directories
|
||||
as well as the namespaces are constructed from the modules
|
||||
and the moduleroot
|
||||
--extra extra headers explicitly defined to parse. This must be in
|
||||
the format "namepsace=/path/to/extra/header.hpp". For example,
|
||||
the core module requires the extra header:
|
||||
"core=/opencv/modules/core/include/opencv2/core/core/base.hpp"
|
||||
--outdir the output directory to put the generated matlab sources. In
|
||||
the OpenCV build this is "${CMAKE_CURRENT_BUILD_DIR}/src"
|
||||
"""
|
||||
|
||||
# parse the input options
|
||||
from argparse import ArgumentParser
|
||||
parser = ArgumentParser()
|
||||
parser.add_argument('--hdrparser')
|
||||
parser.add_argument('--moduleroot', nargs='*', default=[], required=False)
|
||||
parser.add_argument('--modules', nargs='*', default=[], required=False)
|
||||
parser.add_argument('--extra', nargs='*', default=[], required=False)
|
||||
parser.add_argument('--outdir')
|
||||
args = parser.parse_args()
|
||||
|
||||
# add the hdr_parser module to the path
|
||||
sys.path.append(args.hdrparser)
|
||||
|
||||
# create the generator
|
||||
mwg = MatlabWrapperGenerator()
|
||||
mwg.gen(args.moduleroot, args.modules, args.extra, args.outdir)
|
||||
@@ -0,0 +1,386 @@
|
||||
import sys
|
||||
if sys.version_info >= (3, 10):
|
||||
import collections.abc
|
||||
IterableType = collections.abc.Iterable
|
||||
else:
|
||||
import collections
|
||||
IterableType = collections.Iterable
|
||||
from textwrap import fill
|
||||
from filters import *
|
||||
try:
|
||||
# Python 2.7+
|
||||
basestring
|
||||
except NameError:
|
||||
# Python 3.3+
|
||||
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):
|
||||
"""
|
||||
The ParseTree class produces a semantic tree of C++ definitions given
|
||||
the output of the CppHeaderParser (from opencv/modules/python/src2/hdr_parser.py)
|
||||
|
||||
The full hierarchy is as follows:
|
||||
|
||||
Namespaces
|
||||
|
|
||||
|- name
|
||||
|- Classes
|
||||
|
|
||||
|- name
|
||||
|- Methods
|
||||
|- Constants
|
||||
|- Methods
|
||||
|
|
||||
|- name
|
||||
|- static (T/F)
|
||||
|- return type
|
||||
|- required Arguments
|
||||
|
|
||||
|- name
|
||||
|- const (T/F)
|
||||
|- reference ('&'/'*')
|
||||
|- type
|
||||
|- input
|
||||
|- output (pass return by reference)
|
||||
|- default value
|
||||
|- optional Arguments
|
||||
|- Constants
|
||||
|
|
||||
|- name
|
||||
|- const (T/F)
|
||||
|- reference ('&'/'*')
|
||||
|- type
|
||||
|- value
|
||||
|
||||
The semantic tree contains substantial information for easily introspecting
|
||||
information about objects. How many methods does the 'core' namespace have?
|
||||
Does the 'randn' method have any return by reference (output) arguments?
|
||||
How many required and optional arguments does the 'add' method have? Is the
|
||||
variable passed by reference or raw pointer?
|
||||
|
||||
Individual definitions from the parse tree (Classes, Functions, Constants)
|
||||
are passed to the Jinja2 template engine where they are manipulated to
|
||||
produce Matlab mex sources.
|
||||
|
||||
A common call tree for constructing and using a ParseTree object is:
|
||||
|
||||
# parse a set of definitions into a dictionary of namespaces
|
||||
parser = CppHeaderParser()
|
||||
ns['core'] = parser.parse('path/to/opencv/core.hpp')
|
||||
|
||||
# refactor into a semantic tree
|
||||
parse_tree = ParseTree()
|
||||
parse_tree.build(ns)
|
||||
|
||||
# iterate over the tree
|
||||
for namespace in parse_tree.namespaces:
|
||||
for clss in namespace.classes:
|
||||
# do stuff
|
||||
for method in namespace.methods:
|
||||
# do stuff
|
||||
|
||||
Calling 'print' on a ParseTree object will reconstruct the definitions
|
||||
to produce an output resembling the original C++ code.
|
||||
"""
|
||||
def __init__(self, namespaces=None):
|
||||
self.namespaces = namespaces if namespaces else []
|
||||
|
||||
def __str__(self):
|
||||
return '\n\n\n'.join(ns.__str__() for ns in self.namespaces)
|
||||
|
||||
def build(self, namespaces):
|
||||
babel = Translator()
|
||||
for name, definitions in namespaces.items():
|
||||
class_tree = {}
|
||||
methods = []
|
||||
constants = []
|
||||
for defn in definitions:
|
||||
try:
|
||||
obj = babel.translate(defn)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
obj = None
|
||||
if obj is None:
|
||||
continue
|
||||
if type(obj) is Class or obj.clss:
|
||||
self.insertIntoClassTree(obj, class_tree)
|
||||
elif type(obj) is Method:
|
||||
methods.append(obj)
|
||||
elif type(obj) is Constant:
|
||||
constants.append(obj)
|
||||
else:
|
||||
raise TypeError('Unexpected object type: '+str(type(obj)))
|
||||
self.namespaces.append(Namespace(name, constants, list(class_tree.values()), methods))
|
||||
|
||||
def insertIntoClassTree(self, obj, class_tree):
|
||||
cname = obj.name if type(obj) is Class else obj.clss
|
||||
if not cname:
|
||||
return
|
||||
if not cname in class_tree:
|
||||
# add a new class to the tree
|
||||
class_tree[cname] = Class(cname)
|
||||
# insert the definition into the class
|
||||
val = class_tree[cname]
|
||||
if type(obj) is Method:
|
||||
val.methods.append(obj)
|
||||
elif type(obj) is Constant:
|
||||
val.constants.append(obj)
|
||||
else:
|
||||
raise TypeError('Unexpected object type: '+str(type(obj)))
|
||||
|
||||
|
||||
|
||||
class Translator(object):
|
||||
"""
|
||||
The Translator class does the heavy lifting of translating the nested
|
||||
list representation of the hdr_parser into individual definitions that
|
||||
are inserted into the ParseTree.
|
||||
Translator consists of a top-level method: translate()
|
||||
along with a number of helper methods: translateClass(), translateMethod(),
|
||||
translateArgument(), translateConstant(), translateName(), and
|
||||
translateClassName()
|
||||
"""
|
||||
def translate(self, defn):
|
||||
# --- class ---
|
||||
# classes have 'class' prefixed on their name
|
||||
if 'class' in defn[0].split(' ') or 'struct' in defn[0].split(' '):
|
||||
return self.translateClass(defn)
|
||||
# --- operators! ---
|
||||
#TODO: implement operators: http://www.mathworks.com.au/help/matlab/matlab_oop/implementing-operators-for-your-class.html
|
||||
if 'operator' in defn[0]:
|
||||
return
|
||||
# --- constant ---
|
||||
elif convertibleToInt(defn[1]):
|
||||
return self.translateConstant(defn)
|
||||
# --- function ---
|
||||
# functions either need to have input arguments, or not uppercase names
|
||||
elif defn[3] or not self.translateName(defn[0]).split('_')[0].isupper():
|
||||
return self.translateMethod(defn)
|
||||
# --- constant ---
|
||||
else:
|
||||
return self.translateConstant(defn)
|
||||
|
||||
def translateClass(self, defn):
|
||||
return Class()
|
||||
|
||||
def translateMethod(self, defn, class_tree=None):
|
||||
name = self.translateName(defn[0])
|
||||
clss = self.translateClassName(defn[0])
|
||||
rtp = defn[1]
|
||||
static = True if 'S' in ''.join(defn[2]) else False
|
||||
args = defn[3]
|
||||
req = []
|
||||
opt = []
|
||||
for arg in args:
|
||||
if arg:
|
||||
a = self.translateArgument(arg)
|
||||
opt.append(a) if a.default else req.append(a)
|
||||
return Method(name, clss, static, '', rtp, False, req, opt)
|
||||
|
||||
def translateConstant(self, defn):
|
||||
const = True if 'const' in defn[0] else False
|
||||
name = self.translateName(defn[0])
|
||||
clss = self.translateClassName(defn[0])
|
||||
tp = 'int'
|
||||
val = defn[1]
|
||||
return Constant(name, clss, tp, const, '', val)
|
||||
|
||||
def translateArgument(self, defn):
|
||||
modifiers = defn[3]
|
||||
ref = '*' if '*' in defn[0] else ''
|
||||
ref = '&' if '&' in defn[0] or '/Ref' in modifiers else ref
|
||||
const = '/C' in modifiers
|
||||
tp = " ".join([word for word in defn[0].replace(ref, '').split() if not ' const ' in ' '+word+' '])
|
||||
name = defn[1]
|
||||
default = defn[2] if defn[2] else ''
|
||||
I = True if '/I' in modifiers or not '/O' in modifiers else False
|
||||
O = True if '/O' in modifiers else False
|
||||
return Argument(name, tp, const, I, O, ref, default)
|
||||
|
||||
def translateName(self, name):
|
||||
return name.split(' ')[-1].split('.')[-1]
|
||||
|
||||
def translateClassName(self, name):
|
||||
name = name.split(' ')[-1]
|
||||
parts = name.split('.')
|
||||
return parts[-2] if len(parts) > 1 and not parts[-2] == 'cv' else ''
|
||||
|
||||
|
||||
|
||||
class Namespace(object):
|
||||
"""
|
||||
Namespace
|
||||
|
|
||||
|- name
|
||||
|- Constants
|
||||
|- Methods
|
||||
|- Constants
|
||||
"""
|
||||
def __init__(self, name='', constants=None, classes=None, methods=None):
|
||||
self.name = name
|
||||
self.constants = constants if constants else []
|
||||
self.classes = classes if classes else []
|
||||
self.methods = methods if methods else []
|
||||
|
||||
def __str__(self):
|
||||
return 'namespace '+self.name+' {\n\n'+\
|
||||
('\n'.join(c.__str__() for c in self.constants)+'\n\n' if self.constants else '')+\
|
||||
('\n'.join(f.__str__() for f in self.methods)+'\n\n' if self.methods else '')+\
|
||||
('\n\n'.join(o.__str__() for o in self.classes) if self.classes else '')+'\n};'
|
||||
|
||||
class Class(object):
|
||||
"""
|
||||
Class
|
||||
|
|
||||
|- name
|
||||
|- Methods
|
||||
|- Constants
|
||||
"""
|
||||
def __init__(self, name='', namespace='', constants=None, methods=None):
|
||||
self.name = name
|
||||
self.namespace = namespace
|
||||
self.constants = constants if constants else []
|
||||
self.methods = methods if methods else []
|
||||
|
||||
def __str__(self):
|
||||
return 'class '+self.name+' {\n\t'+\
|
||||
('\n\t'.join(c.__str__() for c in self.constants)+'\n\n\t' if self.constants else '')+\
|
||||
('\n\t'.join(f.__str__() for f in self.methods) if self.methods else '')+'\n};'
|
||||
|
||||
class Method(object):
|
||||
"""
|
||||
Method
|
||||
int VideoWriter::read( cv::Mat& frame, const cv::Mat& mask=cv::Mat() );
|
||||
--- ----- ---- -------- ----------------
|
||||
rtp class name required optional
|
||||
|
||||
name the method name
|
||||
clss the class the method belongs to ('' if free)
|
||||
static static?
|
||||
namespace the namespace the method belongs to ('' if free)
|
||||
rtp the return type
|
||||
const const?
|
||||
req list of required arguments
|
||||
opt list of optional arguments
|
||||
"""
|
||||
def __init__(self, name='', clss='', static=False, namespace='', rtp='', const=False, req=None, opt=None):
|
||||
self.name = name
|
||||
self.clss = clss
|
||||
self.constructor = True if name == clss else False
|
||||
self.static = static
|
||||
self.const = const
|
||||
self.namespace = namespace
|
||||
self.rtp = rtp
|
||||
self.req = req if req else []
|
||||
self.opt = opt if opt else []
|
||||
|
||||
def __str__(self):
|
||||
return (self.rtp+' ' if self.rtp else '')+self.name+'('+\
|
||||
', '.join(arg.__str__() for arg in self.req+self.opt)+\
|
||||
')'+(' const' if self.const else '')+';'
|
||||
|
||||
class Argument(object):
|
||||
"""
|
||||
Argument
|
||||
const cv::Mat& mask=cv::Mat()
|
||||
----- ---- --- ---- -------
|
||||
const tp ref name default
|
||||
|
||||
name the argument name
|
||||
tp the argument type
|
||||
const const?
|
||||
I is the argument treated as an input?
|
||||
O is the argument treated as an output (return by reference)
|
||||
ref is the argument passed by reference? ('*'/'&')
|
||||
default the default value of the argument ('' if required)
|
||||
"""
|
||||
def __init__(self, name='', tp='', const=False, I=True, O=False, ref='', default=''):
|
||||
self.name = name
|
||||
self.tp = tp
|
||||
self.ref = ref
|
||||
self.I = I
|
||||
self.O = O
|
||||
self.const = const
|
||||
self.default = default
|
||||
if not tp in valid_types:
|
||||
raise Exception("Non-supported argument type: {} (name: {})".format(tp, name))
|
||||
|
||||
def __str__(self):
|
||||
return ('const ' if self.const else '')+self.tp+self.ref+\
|
||||
' '+self.name+('='+self.default if self.default else '')
|
||||
|
||||
class Constant(object):
|
||||
"""
|
||||
Constant
|
||||
DFT_COMPLEX_OUTPUT = 12;
|
||||
---- -------
|
||||
name default
|
||||
|
||||
name the name of the constant
|
||||
clss the class that the constant belongs to ('' if free)
|
||||
tp the type of the constant ('' if int)
|
||||
const const?
|
||||
ref is the constant a reference? ('*'/'&')
|
||||
default default value, required for constants
|
||||
"""
|
||||
def __init__(self, name='', clss='', tp='', const=False, ref='', default=''):
|
||||
self.name = name
|
||||
self.clss = clss
|
||||
self.tp = tp
|
||||
self.ref = ref
|
||||
self.const = const
|
||||
self.default = default
|
||||
|
||||
def __str__(self):
|
||||
return ('const ' if self.const else '')+self.tp+self.ref+\
|
||||
' '+self.name+('='+self.default if self.default else '')+';'
|
||||
|
||||
def constants(tree):
|
||||
"""
|
||||
recursive generator to strip all Constant objects from the ParseTree
|
||||
and place them into a flat dictionary of { name, value (default) }
|
||||
"""
|
||||
if isinstance(tree, dict) and 'constants' in tree and isinstance(tree['constants'], list):
|
||||
for node in tree['constants']:
|
||||
yield (node['name'], node['default'])
|
||||
if isinstance(tree, dict):
|
||||
for key, val in tree.items():
|
||||
for gen in constants(val):
|
||||
yield gen
|
||||
if isinstance(tree, list):
|
||||
for val in tree:
|
||||
for gen in constants(val):
|
||||
yield gen
|
||||
|
||||
|
||||
def todict(obj):
|
||||
"""
|
||||
Recursively convert a Python object graph to sequences (lists)
|
||||
and mappings (dicts) of primitives (bool, int, float, string, ...)
|
||||
"""
|
||||
if isinstance(obj, basestring):
|
||||
return obj
|
||||
elif isinstance(obj, dict):
|
||||
return dict((key, todict(val)) for key, val in obj.items())
|
||||
elif isinstance(obj, IterableType):
|
||||
return [todict(val) for val in obj]
|
||||
elif hasattr(obj, '__dict__'):
|
||||
return todict(vars(obj))
|
||||
elif hasattr(obj, '__slots__'):
|
||||
return todict(dict((name, getattr(obj, name)) for name in getattr(obj, '__slots__')))
|
||||
return obj
|
||||
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* compose
|
||||
* compose a function call
|
||||
* This macro takes as input a Method object and composes
|
||||
* a function call by inspecting the types and argument names
|
||||
*/
|
||||
{% macro compose(fun) %}
|
||||
{# ----------- Return type ------------- #}
|
||||
{%- if not fun.rtp|void and not fun.constructor -%} retval = {% endif -%}
|
||||
{%- if fun.constructor -%}{{fun.clss}} obj = {% endif -%}
|
||||
{%- if fun.clss and not fun.constructor -%}inst.{%- else -%} cv:: {%- endif -%}
|
||||
{{fun.name}}(
|
||||
{#- ----------- Required ------------- -#}
|
||||
{%- for arg in fun.req -%}
|
||||
{%- if arg.ref == '*' -%}&{%- endif -%}
|
||||
{{arg.name}}
|
||||
{%- if not loop.last %}, {% endif %}
|
||||
{% endfor %}
|
||||
{#- ----------- Optional ------------- -#}
|
||||
{% if fun.req and fun.opt %}, {% endif %}
|
||||
{%- for opt in fun.opt -%}
|
||||
{%- if opt.ref == '*' -%}&{%- endif -%}
|
||||
{{opt.name}}
|
||||
{%- if not loop.last -%}, {% endif %}
|
||||
{%- endfor -%}
|
||||
);
|
||||
{%- endmacro %}
|
||||
|
||||
|
||||
/*
|
||||
* composeMatlab
|
||||
* compose a Matlab function call
|
||||
* This macro takes as input a Method object and composes
|
||||
* a Matlab function call by inspecting the types and argument names
|
||||
*/
|
||||
{% macro composeMatlab(fun) %}
|
||||
{# ----------- Return type ------------- #}
|
||||
{%- if fun|noutputs > 1 -%}[{% endif -%}
|
||||
{%- if not fun.rtp|void -%}LVALUE{% endif -%}
|
||||
{%- if not fun.rtp|void and fun|noutputs > 1 -%},{% endif -%}
|
||||
{# ------------- Outputs ------------- -#}
|
||||
{%- for arg in fun.req|outputs + fun.opt|outputs -%}
|
||||
{{arg.name}}
|
||||
{%- if arg.I -%}_out{%- endif -%}
|
||||
{%- if not loop.last %}, {% endif %}
|
||||
{% endfor %}
|
||||
{%- if fun|noutputs > 1 -%}]{% endif -%}
|
||||
{%- if fun|noutputs %} = {% endif -%}
|
||||
cv.{{fun.name}}(
|
||||
{#- ------------ Inputs -------------- -#}
|
||||
{%- for arg in fun.req|inputs + fun.opt|inputs -%}
|
||||
{{arg.name}}
|
||||
{%- if arg.O -%}_in{%- endif -%}
|
||||
{%- if not loop.last %}, {% endif -%}
|
||||
{% endfor -%}
|
||||
);
|
||||
{%- endmacro %}
|
||||
|
||||
|
||||
/*
|
||||
* composeVariant
|
||||
* compose a variant call for the ArgumentParser
|
||||
*/
|
||||
{% macro composeVariant(fun) %}
|
||||
addVariant("{{ fun.name }}", {{ fun.req|inputs|length }}, {{ fun.opt|inputs|length }}
|
||||
{%- if fun.opt|inputs|length %}, {% endif -%}
|
||||
{%- for arg in fun.opt|inputs -%}
|
||||
"{{arg.name}}"
|
||||
{%- if not loop.last %}, {% endif -%}
|
||||
{% endfor -%}
|
||||
)
|
||||
{%- endmacro %}
|
||||
|
||||
|
||||
/*
|
||||
* composeWithExceptionHandler
|
||||
* compose a function call wrapped in exception traps
|
||||
* This macro takes an input a Method object and composes a function
|
||||
* call through the compose() macro, then wraps the return in traps
|
||||
* for cv::Exceptions, std::exceptions, and all generic exceptions
|
||||
* and returns a useful error message to the Matlab interpreter
|
||||
*/
|
||||
{%- macro composeWithExceptionHandler(fun) -%}
|
||||
// call the opencv function
|
||||
// [out =] namespace.fun(src1, ..., srcn, dst1, ..., dstn, opt1, ..., optn);
|
||||
try {
|
||||
{{ compose(fun) }}
|
||||
} catch(const cv::Exception& e) {
|
||||
error(std::string("cv::exception caught: ").append(e.what()).c_str());
|
||||
} catch(const std::exception& e) {
|
||||
error(std::string("std::exception caught: ").append(e.what()).c_str());
|
||||
} catch(...) {
|
||||
error("Uncaught exception occurred in {{fun.name}}");
|
||||
}
|
||||
{%- endmacro %}
|
||||
|
||||
|
||||
/*
|
||||
* handleInputs
|
||||
* unpack input arguments from the Bridge
|
||||
* Given an input Bridge object, this unpacks the object from the Bridge and
|
||||
* casts them into the correct type
|
||||
*/
|
||||
{%- macro handleInputs(fun) %}
|
||||
|
||||
{% if fun|ninputs or (fun|noutputs and not fun.constructor) %}
|
||||
// - inputs
|
||||
{% for arg in fun.req|inputs %}
|
||||
{{arg.tp}} {{arg.name}} = inputs[{{ loop.index0 }}].to{{arg.tp|toUpperCamelCase}}();
|
||||
{% endfor %}
|
||||
// - inputs (opt)
|
||||
{% 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}}();
|
||||
{% endfor %}
|
||||
// - outputs
|
||||
{% for arg in fun.req|only|outputs %}
|
||||
{{arg.tp}} {{arg.name}};
|
||||
{% endfor %}
|
||||
// - outputs (opt)
|
||||
{% for opt in fun.opt|only|outputs %}
|
||||
{{opt.tp}} {{opt.name}};
|
||||
{% endfor %}
|
||||
// - return
|
||||
{% if not fun.rtp|void and not fun.constructor %}
|
||||
{{fun.rtp}} retval;
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{%- endmacro %}
|
||||
|
||||
/*
|
||||
* handleOutputs
|
||||
* pack outputs into the bridge
|
||||
* Given a set of outputs, this methods assigns them into the bridge for
|
||||
* return to the calling method
|
||||
*/
|
||||
{%- macro handleOutputs(fun) %}
|
||||
|
||||
{% if fun|noutputs %}
|
||||
// assign the outputs into the bridge
|
||||
{% if not fun.rtp|void and not fun.constructor %}
|
||||
outputs[0] = retval;
|
||||
{% endif %}
|
||||
{% for arg in fun.req|outputs %}
|
||||
outputs[{{loop.index0 + fun.rtp|void|not}}] = {{arg.name}};
|
||||
{% endfor %}
|
||||
{% for opt in fun.opt|outputs %}
|
||||
outputs[{{loop.index0 + fun.rtp|void|not + fun.req|outputs|length}}] = {{opt.name}};
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{%- endmacro %}
|
||||
@@ -0,0 +1,41 @@
|
||||
function buildInformation()
|
||||
%CV.BUILDINFORMATION display OpenCV Toolbox build information
|
||||
%
|
||||
% Call CV.BUILDINFORMATION() to get a printout of diagonstic information
|
||||
% pertaining to your particular build of the OpenCV Toolbox. If you ever
|
||||
% run into issues with the Toolbox, it is useful to submit this
|
||||
% information alongside a bug report to the OpenCV team.
|
||||
%
|
||||
% Copyright {{ time.strftime("%Y", time.localtime()) }} The OpenCV Foundation
|
||||
%
|
||||
info = {
|
||||
' ------------------------------------------------------------------------'
|
||||
' <strong>OpenCV Toolbox</strong>'
|
||||
' Build and diagnostic information'
|
||||
' ------------------------------------------------------------------------'
|
||||
''
|
||||
' <strong>Platform</strong>'
|
||||
' OS: {{ build.os }}'
|
||||
' Architecture: {{ build.arch[0] }}-bit {{ build.arch[1] }}'
|
||||
' Compiler: {{ build.compiler | csv(' ') }}'
|
||||
''
|
||||
' <strong>Matlab</strong>'
|
||||
[' Version: ' version()]
|
||||
[' Mex extension: ' mexext()]
|
||||
' Architecture: {{ build.mex_arch }}'
|
||||
' Mex path: {{ build.mex_script }}'
|
||||
' Mex flags: {{ build.mex_opts | csv(' ') }}'
|
||||
' CXX flags: {{ build.cxx_flags | csv(' ') | stripExtraSpaces | wordwrap(60, True, '\'\n\' ') }}'
|
||||
''
|
||||
' <strong>OpenCV</strong>'
|
||||
' Version: {{ build.opencv_version }}'
|
||||
' Commit: {{ build.commit }}'
|
||||
' Configuration: {{ build.configuration }}'
|
||||
' Modules: {{ build.modules | csv | wordwrap(60, True, '\'\n\' ') }}'
|
||||
''
|
||||
};
|
||||
|
||||
info = cellfun(@(x) [x '\n'], info, 'UniformOutput', false);
|
||||
info = horzcat(info{:});
|
||||
fprintf(info);
|
||||
end
|
||||
@@ -0,0 +1,97 @@
|
||||
{% import 'functional.cpp' as functional %}
|
||||
/*
|
||||
* file: {{clss.name}}Bridge.cpp
|
||||
* author: A trusty code generator
|
||||
*
|
||||
* This file was autogenerated, do not modify.
|
||||
* See LICENSE for full modification and redistribution details.
|
||||
* Copyright 2018 The OpenCV Foundation
|
||||
*/
|
||||
#include <mex.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <opencv2/matlab/map.hpp>
|
||||
#include <opencv2/matlab/bridge.hpp>
|
||||
#include <opencv2/core.hpp>
|
||||
using namespace cv;
|
||||
using namespace matlab;
|
||||
using namespace bridge;
|
||||
|
||||
namespace {
|
||||
|
||||
typedef std::vector<Bridge> (*)({{clss.name}}&, const std::vector<Bridge>&) MethodSignature;
|
||||
|
||||
{% for function in clss.methods %}
|
||||
|
||||
{% if function.constructor %}
|
||||
// wrapper for {{function.name}}() constructor
|
||||
{{ function.clss }} {{function.name}}(const std::vector<Bridge>& inputs) {
|
||||
{{ functional.handleInputs(function) }}
|
||||
{{ functional.compose(function) }}
|
||||
return obj;
|
||||
}
|
||||
{% else %}
|
||||
// wrapper for {{function.name}}() method
|
||||
std::vector<Bridge> {{function.name}}({{clss.name}}& inst, const std::vector<Bridge>& inputs) {
|
||||
std::vector<Bridge> outputs{% if function|noutputs %}({{function|noutputs}}){% endif %};
|
||||
{{ functional.handleInputs(function) }}
|
||||
{{ functional.composeWithExceptionHandler(function) }}
|
||||
{{ functional.handleOutputs(function) }}
|
||||
return outputs;
|
||||
}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
Map<std::string, MethodSignature> createMethodMap() {
|
||||
Map<std::string, MethodSignature> m;
|
||||
{% for function in clss.methods %}
|
||||
m["{{function.name}}"] = &{{function.name}};
|
||||
{% endfor %}
|
||||
|
||||
return m;
|
||||
}
|
||||
static const Map<std::string, MethodSignature> methods = createMethodMap();
|
||||
|
||||
// map of created {{clss.name}} instances. Don't trust the user to keep them safe...
|
||||
static Map<void *, {{clss.name}}> instances;
|
||||
|
||||
/*
|
||||
* {{ clss.name }}
|
||||
* Gateway routine
|
||||
* nlhs - number of return arguments
|
||||
* plhs - pointers to return arguments
|
||||
* nrhs - number of input arguments
|
||||
* prhs - pointers to input arguments
|
||||
*/
|
||||
void mexFunction(int nlhs, mxArray* plhs[],
|
||||
int nrhs, const mxArray* prhs[]) {
|
||||
|
||||
// parse the inputs
|
||||
Bridge method_name(prhs[0]);
|
||||
|
||||
Bridge handle(prhs[1]);
|
||||
std::vector<Bridge> brhs(prhs+2, prhs+nrhs);
|
||||
|
||||
// retrieve the instance of interest
|
||||
try {
|
||||
{{clss.name}}& inst = instances.at(handle.address());
|
||||
} catch (const std::out_of_range& e) {
|
||||
mexErrMsgTxt("Invalid object instance provided");
|
||||
}
|
||||
|
||||
// invoke the correct method on the data
|
||||
try {
|
||||
std::vector<Bridge> blhs = (*methods.at(method_name))(inst, brhs);
|
||||
} catch (const std::out_of_range& e) {
|
||||
mexErrMsgTxt("Unknown method specified");
|
||||
}
|
||||
|
||||
{% block postfun %}
|
||||
{% endblock %}
|
||||
|
||||
{% block cleanup %}
|
||||
{% endblock %}
|
||||
|
||||
}
|
||||
|
||||
} // end namespace
|
||||
@@ -0,0 +1,31 @@
|
||||
% {{clss.name | upper}}
|
||||
% Matlab handle class for OpenCV object classes
|
||||
%
|
||||
% This file was autogenerated, do not modify.
|
||||
% See LICENSE for full modification and redistribution details.
|
||||
% Copyright {{time.strftime("%Y", time.localtime())}} The OpenCV Foundation
|
||||
classdef {{clss.name}} < handle
|
||||
properties (SetAccess = private, Hidden = true)
|
||||
ptr_ = 0; % handle to the underlying c++ clss instance
|
||||
end
|
||||
|
||||
methods
|
||||
% constructor
|
||||
function this = {{clss.name}}(varargin)
|
||||
this.ptr_ = {{clss.name}}Bridge('new', varargin{:});
|
||||
end
|
||||
|
||||
% destructor
|
||||
function delete(this)
|
||||
{{clss.name}}Bridge(this.ptr_, 'delete');
|
||||
end
|
||||
|
||||
{% for function in clss.functions %}
|
||||
% {{function.__str__()}}
|
||||
function varargout = {{function.name}}(this, varargin)
|
||||
[varargout{1:nargout}] = {{clss.name}}Bridge('{{function.name}}', this.ptr_, varargin{:});
|
||||
end
|
||||
|
||||
{% endfor %}
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,46 @@
|
||||
function mex(varargin)
|
||||
%CV.MEX compile MEX-function with OpenCV linkages
|
||||
%
|
||||
% Usage:
|
||||
% CV.MEX [options ...] file [file file ...]
|
||||
%
|
||||
% Description:
|
||||
% CV.MEX compiles one or more C/C++ source files into a shared-library
|
||||
% called a mex-file. This function is equivalent to the builtin MEX
|
||||
% routine, with the notable exception that it automatically resolves
|
||||
% OpenCV includes, and links in the OpenCV libraries where appropriate.
|
||||
% It also forwards the flags used to build OpenCV, so architecture-
|
||||
% specific optimizations can be used.
|
||||
%
|
||||
% CV.MEX is designed to be used in situations where the source(s) you
|
||||
% are compiling contain OpenCV definitions. In such cases, it streamlines
|
||||
% the finding and including of appropriate OpenCV libraries.
|
||||
%
|
||||
% See also: mex
|
||||
%
|
||||
% Copyright {{ time.strftime("%Y", time.localtime()) }} The OpenCV Foundation
|
||||
%
|
||||
|
||||
% forward the OpenCV build flags (C++ only)
|
||||
EXTRA_FLAGS = ['"CXXFLAGS="\$CXXFLAGS '...
|
||||
'{{ cv.flags | trim | wordwrap(60, false, '\'...\n \'') }}""'];
|
||||
|
||||
% add the OpenCV include dirs
|
||||
INCLUDE_DIRS = {{ cv.include_dirs | split | cellarray | wordwrap(60, false, '...\n ') }};
|
||||
|
||||
% add the lib dir (singular in both build tree and install tree)
|
||||
LIB_DIR = '{{ cv.lib_dir }}';
|
||||
|
||||
% add the OpenCV libs. Only the used libs will actually be linked
|
||||
LIBS = {{ cv.libs | split | cellarray | wordwrap(60, false, '...\n ') }};
|
||||
|
||||
% add the mex opts (usually at least -largeArrayDims)
|
||||
OPTS = {{ cv.opts | split | cellarray | wordwrap(60, false, '...\n ') }};
|
||||
|
||||
% merge all of the default options (EXTRA_FLAGS, LIBS, etc) and the options
|
||||
% and files passed by the user (varargin) into a single cell array
|
||||
merged = [ {EXTRA_FLAGS}, INCLUDE_DIRS, {LIB_DIR}, LIBS, OPTS, varargin ];
|
||||
|
||||
% expand the merged argument list into the builtin mex utility
|
||||
mex(merged{:});
|
||||
end
|
||||
@@ -0,0 +1,62 @@
|
||||
{% import 'functional.cpp' as functional %}
|
||||
{{ ('CV.' + fun.name | upper + ' ' + doc.brief | stripTags) | comment(75, '%') | matlabURL }}
|
||||
%
|
||||
% {{ functional.composeMatlab(fun) | upper }}
|
||||
{% if doc.long %}
|
||||
{{ doc.long | stripTags | qualify(fun.name) | comment(75, '% ') | matlabURL }}
|
||||
{% endif %}
|
||||
%
|
||||
{# ----------------------- Returns --------------------- #}
|
||||
{% if fun.rtp|void|not or fun.req|outputs|length or fun.opt|outputs|length %}
|
||||
% Returns:
|
||||
{% if fun.rtp|void|not %}
|
||||
% LVALUE
|
||||
{% endif %}
|
||||
{% for arg in fun.req|outputs + fun.opt|outputs %}
|
||||
{% set uname = arg.name | upper + ('_OUT' if arg.I else '') %}
|
||||
{% if arg.name in doc.params %}
|
||||
{{ (uname + ' ' + doc.params[arg.name]) | stripTags | comment(75, '% ') }}
|
||||
{% else %}
|
||||
{{ uname }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
%
|
||||
{% endif %}
|
||||
{# ----------------- Required Inputs ------------------- #}
|
||||
{% if fun.req|inputs|length %}
|
||||
% Required Inputs:
|
||||
{% for arg in fun.req|inputs %}
|
||||
{% set uname = arg.name | upper + ('_IN' if arg.O else '') %}
|
||||
{% if arg.name in doc.params %}
|
||||
{{ (uname + ' ' + doc.params[arg.name]) | stripTags | comment(75, '% ') }}
|
||||
{% else %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
%
|
||||
{% endif %}
|
||||
{# ------------------ Optional Inputs ------------------- #}
|
||||
{% if fun.opt|inputs|length %}
|
||||
% Optional Inputs:
|
||||
{% for arg in fun.opt|inputs %}
|
||||
{% set uname = arg.name | upper + ('_IN' if arg.O else '') + ' (default: ' + arg.default + ')' %}
|
||||
{% if arg.name in doc.params %}
|
||||
{{ (uname + ' ' + doc.params[arg.name]) | stripTags | comment(75, '% ') }}
|
||||
{% else %}
|
||||
{{ uname }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
%
|
||||
{% endif %}
|
||||
{# ---------------------- See also --------------------- #}
|
||||
{% if 'seealso' in doc %}
|
||||
% See also: {% for item in doc['seealso'] %}
|
||||
cv.{{ item }}{% if not loop.last %}, {% endif %}
|
||||
{% endfor %}
|
||||
|
||||
%
|
||||
{% endif %}
|
||||
{# ----------------------- Online ---------------------- #}
|
||||
{% set url = 'http://docs.opencv.org/modules/' + doc.module + '/doc/' + (doc.file|filename) + '.html#' + (fun.name|slugify) %}
|
||||
% Online docs: {{ url | matlabURL }}
|
||||
% Copyright {{ time.strftime("%Y", time.localtime()) }} The OpenCV Foundation
|
||||
%
|
||||
@@ -0,0 +1,59 @@
|
||||
{% import 'functional.cpp' as functional %}
|
||||
/*
|
||||
* file: {{fun.name}}.cpp
|
||||
* author: A trusty code generator
|
||||
*
|
||||
* This file was autogenerated, do not modify.
|
||||
* See LICENSE for full modification and redistribution details.
|
||||
* Copyright 2018 The OpenCV Foundation
|
||||
*/
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
#include <exception>
|
||||
#include <opencv2/matlab/bridge.hpp>
|
||||
#include <opencv2/{{includes}}.hpp>
|
||||
using namespace cv;
|
||||
using namespace matlab;
|
||||
using namespace bridge;
|
||||
|
||||
/*
|
||||
* {{ fun.name }}
|
||||
* {{ fun }}
|
||||
* Gateway routine
|
||||
* nlhs - number of return arguments
|
||||
* plhs - pointers to return arguments
|
||||
* nrhs - number of input arguments
|
||||
* prhs - pointers to input arguments
|
||||
*/
|
||||
void mexFunction(int nlhs, mxArray*{% if fun|noutputs %} plhs[]{% else %}*{% endif %},
|
||||
int nrhs, const mxArray*{% if fun|ninputs %} prhs[]{% else %}*{% endif %}) {
|
||||
|
||||
{% if fun|ninputs %}
|
||||
// parse the inputs
|
||||
ArgumentParser parser("{{fun.name}}");
|
||||
parser.{{ functional.composeVariant(fun) }};
|
||||
MxArrayVector sorted = parser.parse(MxArrayVector(prhs, prhs+nrhs));
|
||||
{% endif %}
|
||||
|
||||
{% if fun|ninputs or fun|noutputs %}
|
||||
// setup
|
||||
{% if fun|ninputs %}
|
||||
BridgeVector inputs(sorted.begin(), sorted.end());
|
||||
{% endif -%}
|
||||
{%- if fun|noutputs %}
|
||||
BridgeVector outputs({{fun|noutputs}});
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{{ functional.handleInputs(fun) }}
|
||||
{{ functional.composeWithExceptionHandler(fun) }}
|
||||
{{ functional.handleOutputs(fun) }}
|
||||
|
||||
{% if fun|noutputs %}
|
||||
// push the outputs back to matlab
|
||||
for (size_t n = 0; n < static_cast<size_t>(std::max(nlhs,1)); ++n) {
|
||||
plhs[n] = outputs[n].toMxArray().releaseOwnership();
|
||||
}
|
||||
{% endif %}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
% ------------------------------------------------------------------------
|
||||
% <strong>OpenCV Toolbox</strong>
|
||||
% Matlab bindings for the OpenCV library
|
||||
% ------------------------------------------------------------------------
|
||||
%
|
||||
% The OpenCV Toolbox allows you to make calls to native OpenCV methods
|
||||
% and classes directly from within Matlab.
|
||||
%
|
||||
% <strong>PATHS</strong>
|
||||
% To call OpenCV methods from anywhere in your workspace, add the
|
||||
% directory containing this file to the path:
|
||||
%
|
||||
% addpath(fileparts(which('cv')));
|
||||
%
|
||||
% The OpenCV Toolbox contains two important locations:
|
||||
% cv.m - This file, containing OpenCV enums
|
||||
% +cv/ - The directory containing the OpenCV methods and classes
|
||||
%
|
||||
% <strong>CALLING SYNTAX</strong>
|
||||
% To call an OpenCV method, class or enum, it must be prefixed with the
|
||||
% 'cv' qualifier. For example:
|
||||
%
|
||||
% % perform a Fourier transform
|
||||
% Xf = cv.dft(X, cv.DFT_COMPLEX_OUTPUT);
|
||||
%
|
||||
% % create a VideoCapture object, and open a file
|
||||
% camera = cv.VideoCapture();
|
||||
% camera.open('/path/to/file');
|
||||
%
|
||||
% You can specify optional arguments by name, similar to how python
|
||||
% and many builtin Matlab functions work. For example, the cv.dft
|
||||
% method used above has an optional 'nonzeroRows' argument. If
|
||||
% you want to specify that, but keep the default 'flags' behaviour,
|
||||
% simply call the method as:
|
||||
%
|
||||
% Xf = cv.dft(X, 'nonzeroRows', 7);
|
||||
%
|
||||
% <strong>HELP</strong>
|
||||
% Each method has its own help file containing information about the
|
||||
% arguments, return values, and what operation the method performs.
|
||||
% You can access this help information by typing:
|
||||
%
|
||||
% help cv.methodName
|
||||
%
|
||||
% The full list of methods can be found by inspecting the +cv/
|
||||
% directory. Note that the methods available to you will depend
|
||||
% on which modules you configured OpenCV to build.
|
||||
%
|
||||
% <strong>DIAGNOSTICS</strong>
|
||||
% If you are having problems with the OpenCV Toolbox and need to send a
|
||||
% bug report to the OpenCV team, you can get a printout of diagnostic
|
||||
% information to submit along with your report by typing:
|
||||
%
|
||||
% <a href="matlab: cv.buildInformation()">cv.buildInformation();</a>
|
||||
%
|
||||
% <strong>OTHER RESOURCES</strong>
|
||||
% OpenCV documentation online: <a href="matlab: web('http://docs.opencv.org', '-browser')">http://docs.opencv.org</a>
|
||||
% OpenCV issue tracker: <a href="matlab: web('http://code.opencv.org', '-browser')">http://code.opencv.org</a>
|
||||
% OpenCV Q&A: <a href="matlab: web('http://answers.opencv.org', '-browser')">http://answers.opencv.org</a>
|
||||
%
|
||||
% See also: cv.help, <a href="matlab: cv.buildInformation()">cv.buildInformation</a>
|
||||
%
|
||||
% Copyright {{ time.strftime("%Y", time.localtime()) }} The OpenCV Foundation
|
||||
%
|
||||
classdef cv
|
||||
properties (Constant = true)
|
||||
{% for key, val in constants.items() %}
|
||||
{{key}} = {{val|formatMatlabConstant(constants)}};
|
||||
{% endfor %}
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user