mirror of
https://github.com/opencv/opencv.git
synced 2024-11-28 13:10:12 +08:00
Commenting spree no.2
This commit is contained in:
parent
bfa88384c7
commit
fb41d7bf4e
@ -1,4 +1,4 @@
|
||||
#/usr/bin/env python
|
||||
#!/usr/bin/env python
|
||||
|
||||
def substitute(build, output_dir):
|
||||
|
||||
@ -18,12 +18,32 @@ def substitute(build, output_dir):
|
||||
if not os.path.isdir(output_dir):
|
||||
os.mkdir(output_dir)
|
||||
|
||||
# populate templates
|
||||
# populate template
|
||||
populated = template.render(build=build)
|
||||
with open(os.path.join(output_dir, 'buildInformation.m'), 'wb') as f:
|
||||
f.write(populated)
|
||||
|
||||
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
|
||||
|
@ -1,6 +1,7 @@
|
||||
from textwrap import TextWrapper
|
||||
from string import split, join
|
||||
import re, os
|
||||
# precompile a URL matching regular expression
|
||||
urlexpr = re.compile(r"((https?):((//)|(\\\\))+[\w\d:#@%/;$()~_?\+-=\\\.&]*)", re.MULTILINE|re.UNICODE)
|
||||
|
||||
def inputs(args):
|
||||
@ -35,9 +36,11 @@ def 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):
|
||||
@ -45,6 +48,7 @@ def noutputs(fun):
|
||||
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)
|
||||
@ -53,12 +57,21 @@ def convertibleToInt(string):
|
||||
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
|
||||
@ -76,20 +89,33 @@ def matlabURL(string):
|
||||
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)
|
||||
@ -100,18 +126,26 @@ def stripTags(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 csv(items, sep=', '):
|
||||
'''format a list with a separator (comma if not specified)'''
|
||||
return sep.join(item 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=''):
|
||||
|
@ -1,8 +1,27 @@
|
||||
#/usr/bin/env python
|
||||
#!/usr/bin/env python
|
||||
|
||||
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_root, 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.
|
||||
"""
|
||||
# parse each of the files and store in a dictionary
|
||||
# as a separate "namespace"
|
||||
parser = CppHeaderParser()
|
||||
@ -109,8 +128,41 @@ class MatlabWrapperGenerator(object):
|
||||
f.write(populated)
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
"""
|
||||
Usage: python gen_matlab.py --hdrparser /path/to/hdr_parser/dir
|
||||
--rstparser /path/to/rst_parser/dir
|
||||
--moduleroot /path/to/opencv/modules
|
||||
--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. parses .rst docs using RstParser
|
||||
5. populates the templates for classes, function, enums and docs from the
|
||||
definitions
|
||||
|
||||
gen_matlab.py requires the following inputs:
|
||||
--hdrparser the path to the header parser directory
|
||||
(opencv/modules/python/src2)
|
||||
--rstparser the path to the rst parser directory
|
||||
(opencv/modules/java/generator)
|
||||
--moduleroot (optional) path to the opencv directory 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
|
||||
import sys, re, os, time
|
||||
|
@ -3,6 +3,73 @@ from textwrap import fill
|
||||
from filters import *
|
||||
|
||||
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 []
|
||||
|
||||
@ -48,6 +115,15 @@ class ParseTree(object):
|
||||
|
||||
|
||||
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
|
||||
@ -116,6 +192,14 @@ class Translator(object):
|
||||
|
||||
|
||||
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 []
|
||||
@ -129,6 +213,13 @@ class Namespace(object):
|
||||
(join((o.__str__() for o in self.classes), '\n\n') 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
|
||||
@ -141,6 +232,21 @@ class Class(object):
|
||||
(join((f.__str__() for f in self.methods), '\n\t') 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
|
||||
@ -158,6 +264,20 @@ class Method(object):
|
||||
')'+(' 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
|
||||
@ -172,6 +292,19 @@ class Argument(object):
|
||||
' '+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
|
||||
@ -185,6 +318,10 @@ class Constant(object):
|
||||
' '+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'])
|
||||
@ -198,6 +335,10 @@ def constants(tree):
|
||||
yield gen
|
||||
|
||||
def todict(obj, classkey=None):
|
||||
"""
|
||||
Convert the ParseTree to a dictionary, stripping all objects of their
|
||||
methods and converting class names to strings
|
||||
"""
|
||||
if isinstance(obj, dict):
|
||||
for k in obj.keys():
|
||||
obj[k] = todict(obj[k], classkey)
|
||||
|
Loading…
Reference in New Issue
Block a user