Added auto-generated docs to all OpenCV functions

pull/1384/head
hbristow 12 years ago
parent faeb0aa92a
commit 3483bf14b9
  1. 16
      modules/matlab/CMakeLists.txt
  2. 9
      modules/matlab/generator/filters.py
  3. 56
      modules/matlab/generator/gen_matlab.py
  4. 37
      modules/matlab/generator/templates/template_doc_base.m

@ -95,7 +95,7 @@ set(MATLAB_DEPS ${OPENCV_MODULE_${the_module}_REQ_DEPS} ${OPENCV_MODULE_${the_mo
foreach(opencv_module ${MATLAB_DEPS}) foreach(opencv_module ${MATLAB_DEPS})
if (HAVE_${opencv_module}) if (HAVE_${opencv_module})
string(REPLACE "opencv_" "" module ${opencv_module}) string(REPLACE "opencv_" "" module ${opencv_module})
list(APPEND opencv_hdrs "${OPENCV_MODULE_${opencv_module}_LOCATION}/include/opencv2/${module}.hpp") list(APPEND opencv_modules ${module})
list(APPEND ${the_module}_ACTUAL_DEPS ${opencv_module}) list(APPEND ${the_module}_ACTUAL_DEPS ${opencv_module})
prepend("-I" MEX_INCLUDE_DIRS "${OPENCV_MODULE_${opencv_module}_LOCATION}/include") prepend("-I" MEX_INCLUDE_DIRS "${OPENCV_MODULE_${opencv_module}_LOCATION}/include")
prepend("-l" MEX_LIBS ${opencv_module}${OPENCV_DLLVERSION}) prepend("-l" MEX_LIBS ${opencv_module}${OPENCV_DLLVERSION})
@ -104,7 +104,7 @@ foreach(opencv_module ${MATLAB_DEPS})
endforeach() endforeach()
# add extra headers by hand # add extra headers by hand
list(APPEND opencv_hdrs "${OPENCV_MODULE_opencv_core_LOCATION}/include/opencv2/core/base.hpp") list(APPEND opencv_extra_hdrs "core:${OPENCV_MODULE_opencv_core_LOCATION}/include/opencv2/core/base.hpp")
# pass the OPENCV_CXX_EXTRA_FLAGS through to the mex compiler # pass the OPENCV_CXX_EXTRA_FLAGS through to the mex compiler
# remove the visibility modifiers, so the mex gateway is visible # remove the visibility modifiers, so the mex gateway is visible
@ -125,7 +125,7 @@ if (NOT MEX_WORKS)
${CMAKE_CURRENT_SOURCE_DIR}/generator/gen_matlab.py ${CMAKE_CURRENT_SOURCE_DIR}/generator/gen_matlab.py
--hdrparser ${HDR_PARSER_PATH} --hdrparser ${HDR_PARSER_PATH}
--rstparser ${RST_PARSER_PATH} --rstparser ${RST_PARSER_PATH}
--headers ${CMAKE_CURRENT_SOURCE_DIR}/test/test_generator.hpp --extra "test:${CMAKE_CURRENT_SOURCE_DIR}/test/test_generator.hpp"
--outdir ${CMAKE_BINARY_DIR}/junk --outdir ${CMAKE_BINARY_DIR}/junk
ERROR_VARIABLE GEN_ERROR ERROR_VARIABLE GEN_ERROR
OUTPUT_QUIET OUTPUT_QUIET
@ -183,10 +183,12 @@ add_custom_command(
OUTPUT ${GENERATE_PROXY} OUTPUT ${GENERATE_PROXY}
COMMAND ${PYTHON_EXECUTABLE} COMMAND ${PYTHON_EXECUTABLE}
${CMAKE_CURRENT_SOURCE_DIR}/generator/gen_matlab.py ${CMAKE_CURRENT_SOURCE_DIR}/generator/gen_matlab.py
--hdrparser ${HDR_PARSER_PATH} --hdrparser ${HDR_PARSER_PATH}
--rstparser ${RST_PARSER_PATH} --rstparser ${RST_PARSER_PATH}
--headers ${opencv_hdrs} --moduleroot ${CMAKE_SOURCE_DIR}/modules
--outdir ${CMAKE_CURRENT_BINARY_DIR} --modules ${opencv_modules}
--extra ${opencv_extra_hdrs}
--outdir ${CMAKE_CURRENT_BINARY_DIR}
COMMAND ${CMAKE_COMMAND} -E touch ${GENERATE_PROXY} COMMAND ${CMAKE_COMMAND} -E touch ${GENERATE_PROXY}
COMMENT "Generating Matlab source files" COMMENT "Generating Matlab source files"
) )

@ -84,6 +84,15 @@ def toUnderCase(text):
s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', text) s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', text)
return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower() return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
def stripTags(text):
upper = lambda pattern: pattern.group(1).upper()
text = re.sub('<code>(.*?)</code>', upper, text)
text = re.sub('<(.*?)>', '', text)
return text
def qualify(text, name):
return re.sub(name.upper(), 'CV.'+name.upper(), text)
def comment(text, wrap=80, escape='% ', escape_first='', escape_last=''): def comment(text, wrap=80, escape='% ', escape_first='', escape_last=''):
'''comment filter '''comment filter
Takes a string in text, and wraps it to wrap characters in length with Takes a string in text, and wraps it to wrap characters in length with

@ -2,24 +2,34 @@
class MatlabWrapperGenerator(object): class MatlabWrapperGenerator(object):
def gen(self, input_files, output_dir): def gen(self, module_root, modules, extras, output_dir):
# parse each of the files and store in a dictionary # parse each of the files and store in a dictionary
# as a separate "namespace" # as a separate "namespace"
parser = CppHeaderParser() parser = CppHeaderParser()
ns = {} rst = rst_parser.RstParser(parser)
for file in input_files: rst_parser.verbose = False
# get the file name rst_parser.show_warnings = False
# TODO: Is there a cleaner way to do this? rst_parser.show_errors = False
try: rst_parser.show_critical_errors = False
name = re.findall('include/opencv2/([^./]+)', file)[0]
except: ns = dict((key, []) for key in modules)
name = os.path.splitext(os.path.basename(file))[0] doc = dict((key, []) for key in modules)
path_template = Template('${module}/include/opencv2/${module}.hpp')
# add the file to the namespace
try: for module in modules:
ns[name] = ns[name] + parser.parse(file) # construct a header path from the module root and a path template
except KeyError: header = os.path.join(module_root, path_template.substitute(module=module))
ns[name] = parser.parse(file) # parse the definitions
ns[module] = parser.parse(header)
# parse the documentation
rst.parse(module, os.path.join(module_root, module))
doc[module] = rst.definitions
rst.definitions = {}
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 # cleanify the parser output
parse_tree = ParseTree() parse_tree = ParseTree()
@ -35,11 +45,13 @@ class MatlabWrapperGenerator(object):
jtemplate.filters['toUpperCamelCase'] = toUpperCamelCase jtemplate.filters['toUpperCamelCase'] = toUpperCamelCase
jtemplate.filters['toLowerCamelCase'] = toLowerCamelCase jtemplate.filters['toLowerCamelCase'] = toLowerCamelCase
jtemplate.filters['toUnderCase'] = toUnderCase jtemplate.filters['toUnderCase'] = toUnderCase
jtemplate.filters['stripTags'] = stripTags
jtemplate.filters['comment'] = comment jtemplate.filters['comment'] = comment
jtemplate.filters['inputs'] = inputs jtemplate.filters['inputs'] = inputs
jtemplate.filters['ninputs'] = ninputs jtemplate.filters['ninputs'] = ninputs
jtemplate.filters['outputs'] = outputs jtemplate.filters['outputs'] = outputs
jtemplate.filters['noutputs'] = noutputs jtemplate.filters['noutputs'] = noutputs
jtemplate.filters['qualify'] = qualify
jtemplate.filters['only'] = only jtemplate.filters['only'] = only
jtemplate.filters['void'] = void jtemplate.filters['void'] = void
jtemplate.filters['not'] = flip jtemplate.filters['not'] = flip
@ -72,9 +84,10 @@ class MatlabWrapperGenerator(object):
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: with open(output_source_dir+'/'+method.name+'.cpp', 'wb') as f:
f.write(populated) f.write(populated)
populated = tdoc.render(fun=method, time=time) if namespace.name in doc and method.name in doc[namespace.name]:
with open(output_class_dir+'/'+method.name+'.m', 'wb') as f: populated = tdoc.render(fun=method, doc=doc[namespace.name][method.name], time=time)
f.write(populated) with open(output_class_dir+'/'+method.name+'.m', 'wb') as f:
f.write(populated)
# classes # classes
for clss in namespace.classes: for clss in namespace.classes:
# cpp converter # cpp converter
@ -102,7 +115,9 @@ if __name__ == "__main__":
parser = ArgumentParser() parser = ArgumentParser()
parser.add_argument('--hdrparser') parser.add_argument('--hdrparser')
parser.add_argument('--rstparser') parser.add_argument('--rstparser')
parser.add_argument('--headers', nargs='+') parser.add_argument('--moduleroot', default='', required=False)
parser.add_argument('--modules', nargs='*', default=[], required=False)
parser.add_argument('--extra', nargs='*', default=[], required=False)
parser.add_argument('--outdir') parser.add_argument('--outdir')
args = parser.parse_args() args = parser.parse_args()
@ -112,10 +127,11 @@ if __name__ == "__main__":
from string import Template from string import Template
from hdr_parser import CppHeaderParser from hdr_parser import CppHeaderParser
import rst_parser
from parse_tree import ParseTree, todict, constants from parse_tree import ParseTree, todict, constants
from filters import * from filters import *
from jinja2 import Environment, FileSystemLoader from jinja2 import Environment, FileSystemLoader
# create the generator # create the generator
mwg = MatlabWrapperGenerator() mwg = MatlabWrapperGenerator()
mwg.gen(args.headers, args.outdir) mwg.gen(args.moduleroot, args.modules, args.extra, args.outdir)

@ -1,6 +1,10 @@
{% import 'functional.cpp' as functional %} {% import 'functional.cpp' as functional %}
%CV.{{ fun.name | upper }} {{ ('CV.' + fun.name | upper + ' ' + doc.brief | stripTags) | comment(75, '%') }}
%
% {{ functional.composeMatlab(fun) | upper }} % {{ functional.composeMatlab(fun) | upper }}
{% if doc.long %}
{{ doc.long | stripTags | qualify(fun.name) | comment(75, '% ') }}
{% endif %}
% %
{% if fun.rtp|void|not or fun.req|outputs|length or fun.opt|outputs|length %} {% if fun.rtp|void|not or fun.req|outputs|length or fun.opt|outputs|length %}
% Returns: % Returns:
@ -9,28 +13,45 @@
% LVALUE % LVALUE
{% endif %} {% endif %}
{% for arg in fun.req|outputs + fun.opt|outputs %} {% for arg in fun.req|outputs + fun.opt|outputs %}
% {{arg.name | upper}}{%- if arg.I -%}_OUT{% endif %} {% 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 %} {% endfor %}
% %
{% if fun.req|inputs|length %} {% if fun.req|inputs|length %}
% Required Inputs: % Required Inputs:
{% endif %} {% endif %}
{% for arg in fun.req|inputs %} {% for arg in fun.req|inputs %}
% {{arg.name | upper}}{%- if arg.O -%}_OUT{% endif %} {% 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 %}
{{ uname }}
{% endif %}
{% endfor %} {% endfor %}
% %
{% if fun.opt|inputs|length %} {% if fun.opt|inputs|length %}
% Optional Inputs: % Optional Inputs:
{% endif %} {% endif %}
{% for arg in fun.opt|inputs %} {% for arg in fun.opt|inputs %}
% {{arg.name | upper}}{%- if arg.O -%}_OUT{% endif %} {% 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 %} {% endfor %}
% %
% See also: {% if 'seealso' in doc %}
% See also: {% for item in doc['seealso'] %}
cv.{{ item }}{% if not loop.last %}, {% endif %}
{% endfor %}
% %
{% endif %}
% Official documentation: http://docs.opencv.org % Official documentation: http://docs.opencv.org
% Copyright {{ time.strftime("%Y", time.localtime()) }} The OpenCV Foundation % Copyright {{ time.strftime("%Y", time.localtime()) }} The OpenCV Foundation
% %

Loading…
Cancel
Save