-
-
Rapid Object Detection With A Cascade of Boosted
-Classifiers Based on Haar-like Features
-
-
Introduction
-
-
This document describes how to train and
-use a cascade of boosted classifiers for rapid object detection. A large set of
-over-complete haar-like features provide the basis for the simple individual
-classifiers. Examples of object detection tasks are face, eye and nose
-detection, as well as logo detection.
-
-
-
-
The sample detection task in this document
-is logo detection, since logo detection does not require the collection of
-large set of registered and carefully marked object samples. Instead we assume
-that from one prototype image, a very large set of derived object examples can
-be derived (createsamples utility, see below).
-
-
-
-
A detailed description of the training/evaluation
-algorithm can be found in [1] and [2].
-
-
Samples Creation
-
-
For training a training samples must be
-collected. There are two sample types: negative samples and positive samples.
-Negative samples correspond to non-object images. Positive samples correspond
-to object images.
-
-
Negative Samples
-
-
Negative samples are taken from arbitrary
-images. These images must not contain object representations. Negative samples
-are passed through background description file. It is a text file in which each
-text line contains the filename (relative to the directory of the description
-file) of negative sample image. This file must be created manually. Note that
-the negative samples and sample images are also called background samples or
-background samples images, and are used interchangeably in this document
-
-
-
-
Example of negative description file:
-
-
-
-
Directory structure:
-
-
/img
-
-
img1.jpg
-
-
img2.jpg
-
-
bg.txt
-
-
-
-
File bg.txt:
-
-
img/img1.jpg
-
-
img/img2.jpg
-
-
Positive Samples
-
-
Positive samples are created by createsamples
-utility. They may be created from single object image or from collection of
-previously marked up images.
-
-
-
-
The single object image may for instance
-contain a company logo. Then are large set of positive samples are created from
-the given object image by randomly rotating, changing the logo color as well as
-placing the logo on arbitrary background.
-
-
The amount and range of randomness can be
-controlled by command line arguments.
-
-
Command line arguments:
-
-
- vec <vec_file_name>
-
-
name of the
-output file containing the positive samples for training
-
-
- img <image_file_name>
-
-
source object
-image (e.g., a company logo)
-
-
- bg <background_file_name>
-
-
background
-description file; contains a list of images into which randomly distorted
-versions of the object are pasted for positive sample generation
-
-
- num <number_of_samples>
-
-
number of
-positive samples to generate
-
-
- bgcolor <background_color>
-
-
background color (currently grayscale images are assumed); the
-background color denotes the transparent color. Since there might be
-compression artifacts, the amount of color tolerance can be specified by –bgthresh. All pixels between bgcolor-bgthresh and bgcolor+bgthresh are regarded as transparent.
-
-
- bgthresh <background_color_threshold>
-
-
- inv
-
-
if specified, the colors will be inverted
-
-
- randinv
-
-
if specified, the colors will be inverted randomly
-
-
- maxidev <max_intensity_deviation>
-
-
maximal
-intensity deviation of foreground samples pixels
-
-
- maxxangle <max_x_rotation_angle>,
-
-
- maxyangle <max_y_rotation_angle>,
-
-
- maxzangle <max_z_rotation_angle>
-
-
maximum rotation angles in radians
-
-
-show
-
-
if specified, each sample will be shown. Pressing ‘Esc’ will
-continue creation process without samples showing. Useful debugging option.
-
-
- w <sample_width>
-
-
width (in
-pixels) of the output samples
-
-
- h <sample_height>
-
-
height (in
-pixels) of the output samples
-
-
-
-
For following procedure is used to create a
-sample object instance:
-
-
The source image is rotated random around
-all three axes. The chosen angle is limited my -max?angle. Next pixels of
-intensities in the range of [bg_color-bg_color_threshold;
-bg_color+bg_color_threshold] are regarded as
-transparent. White noise is added to the intensities of the foreground. If –inv key is
-specified then foreground pixel intensities are inverted. If –randinv key is
-specified then it is randomly selected whether for this sample inversion will
-be applied. Finally, the obtained image is placed onto arbitrary background
-from the background description file, resized to the pixel size specified by –w and –h and stored
-into the file specified by the –vec command line parameter.
-
-
-
-
Positive samples also may be obtained from
-a collection of previously marked up images. This collection is described by
-text file similar to background description file. Each line of this file
-corresponds to collection image. The first element of the line is image file
-name. It is followed by number of object instances. The following numbers are
-the coordinates of bounding rectangles (x, y, width, height).
-
-
-
-
Example of description file:
-
-
-
-
Directory structure:
-
-
/img
-
-
img1.jpg
-
-
img2.jpg
-
-
info.dat
-
-
-
-
File info.dat:
-
-
img/img1.jpg 1 140
-100 45 45
-
-
img/img2.jpg 2 100
-200 50 50 50 30 25 25
-
-
-
-
Image img1.jpg contains single object
-instance with bounding rectangle (140, 100, 45, 45). Image img2.jpg contains
-two object instances.
-
-
-
-
In order to create positive samples from
-such collection –info argument should be specified instead of –img:
-
-
- info <collection_file_name>
-
-
description file
-of marked up images collection
-
-
-
-
The scheme of sample creation in this case
-is as follows. The object instances are taken from images. Then they are
-resized to samples size and stored in output file. No distortion is applied, so
-the only affecting arguments are –w, -h, -show and –num.
-
-
-
-
createsamples utility may be used for examining samples stored in positive samples
-file. In order to do this only –vec, –w and –h parameters
-should be specified.
-
-
-
-
Note that for training, it does not matter
-how positive samples files are generated. So the createsamples utility is only one way
-to collect/create a vector file of positive samples.
-
-
Training
-
-
The next step after samples creation is
-training of classifier. It is performed by the haartraining utility.
-
-
-
-
Command line arguments:
-
-
- data <dir_name>
-
-
directory name in which the trained classifier is stored
-
-
- vec <vec_file_name>
-
-
file name of positive sample file (created by trainingsamples utility or by any other means)
-
-
- bg <background_file_name>
-
-
background description file
-
-
- npos <number_of_positive_samples>,
-
-
- nneg <number_of_negative_samples>
-
-
number of positive/negative samples used in training of each
-classifier stage. Reasonable values are npos = 7000 and nneg = 3000.
-
-
- nstages <number_of_stages>
-
-
number of
-stages to be trained
-
-
- nsplits <number_of_splits>
-
-
determines the weak classifier used in stage classifiers. If 1, then a simple stump classifier is used, if 2 and more, then CART classifier with number_of_splits internal (split)
-nodes is used
-
-
- mem <memory_in_MB>
-
-
Available memory in MB for precalculation. The more memory you
-have the faster the training process
-
-
- sym (default),
-
-
- nonsym
-
-
specifies whether the object class under training has vertical
-symmetry or not. Vertical symmetry speeds up training process. For instance,
-frontal faces show off vertical symmetry
-
-
- minhitrate <min_hit_rate>
-
-
minimal desired hit rate for each stage classifier. Overall hit
-rate may be estimated as (min_hit_rate^number_of_stages)
-
-
- maxfalsealarm <max_false_alarm_rate>
-
-
maximal desired false alarm rate for each stage classifier. Overall
-false alarm rate may be estimated as (max_false_alarm_rate^number_of_stages)
-
-
- weighttrimming <weight_trimming>
-
-
Specifies
-whether and how much weight trimming should be used. A decent choice is 0.90.
-
-
- eqw
-
-
- mode <BASIC (default) | CORE | ALL>
-
-
selects the type of haar features set used in training. BASIC use
-only upright features, while ALL uses the full set of upright and 45 degree
-rotated feature set. See [1] for more details.
-
-
- w <sample_width>,
-
-
- h <sample_height>
-
-
Size of training samples (in pixels). Must have exactly the same
-values as used during training samples creation (utility trainingsamples)
-
-
-
-
Note: in order to use multiprocessor
-advantage a compiler that supports OpenMP 1.0 standard should be used.
-
-
Application
-
-
OpenCV cvHaarDetectObjects() function (in
-particular haarFaceDetect demo) is used for detection.
-
-
Test Samples
-
-
In order to evaluate the performance of
-trained classifier a collection of marked up images is needed. When such
-collection is not available test samples may be created from single object
-image by createsamples utility. The scheme of test samples creation in this case is
-similar to training samples creation since each test sample is a background
-image into which a randomly distorted and randomly scaled instance of the
-object picture is pasted at a random position.
-
-
-
-
If both –img and –info arguments are specified then
-test samples will be created by createsamples utility. The sample image is arbitrary distorted as it was
-described below, then it is placed at random location to background image and
-stored. The corresponding description line is added to the file specified by –info argument.
-
-
-
-
The –w and –h keys determine the minimal size of
-placed object picture.
-
-
-
-
The test image file name format is as
-follows:
-
-
imageOrderNumber_x_y_width_height.jpg, where x, y, width and height are the coordinates of placed object bounding rectangle.
-
-
Note that you should use a background
-images set different from the background image set used during training.
-
-
Performance
-Evaluation
-
-
In order to evaluate the performance of the
-classifier performance utility may be used. It takes a collection of marked up images,
-applies the classifier and outputs the performance, i.e. number of found
-objects, number of missed objects, number of false alarms and other
-information.
-
-
-
-
Command line arguments:
-
-
- data <dir_name>
-
-
directory name in which the trained classifier is stored
-
-
- info <collection_file_name>
-
-
file with test samples description
-
-
- maxSizeDiff <max_size_difference>,
-
-
- maxPosDiff <max_position_difference>
-
-
determine the criterion of reference and detected rectangles
-coincidence. Default values are 1.5 and 0.3 respectively.
-
-
- sf <scale_factor>,
-
-
detection parameter. Default value is 1.2.
-
-
- w <sample_width>,
-
-
- h <sample_height>
-
-
Size of training samples (in pixels). Must have exactly the same
-values as used during training (utility haartraining)
-
-
References
-
-
[1] Rainer Lienhart and Jochen Maydt. An
-Extended Set of Haar-like Features for Rapid Object Detection. Submitted to
-ICIP2002.
-
-
[2] Alexander Kuranov, Rainer Lienhart, and
-Vadim Pisarevsky. An Empirical Analysis of Boosting Algorithms for Rapid
-Objects With an Extended Set of Haar-like Features. Intel Technical Report
-MRL-TR-July02-01, 2002.
-
-
-
-
-
-
diff --git a/doc/ocv.py b/doc/ocv.py
deleted file mode 100755
index a22d3daa56b077f51a1a6c6ab021cef11ca29e28..0000000000000000000000000000000000000000
--- a/doc/ocv.py
+++ /dev/null
@@ -1,1616 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-"""
- ocv domain, a modified copy of sphinx.domains.cpp + shpinx.domains.python.
- The original copyright is below
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- The OpenCV C/C++/Python/Java/... language domain.
-
- :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
- :license: BSD, see LICENSE for details.
-"""
-
-import re
-from copy import deepcopy
-
-from docutils import nodes
-from docutils.parsers.rst import directives
-
-from sphinx import addnodes
-from sphinx.roles import XRefRole
-from sphinx.locale import l_, _
-from sphinx.domains import Domain, ObjType
-from sphinx.directives import ObjectDescription
-from sphinx.util.nodes import make_refnode
-from sphinx.util.compat import Directive
-from sphinx.util.docfields import Field, GroupedField, TypedField
-
-########################### Python Part ###########################
-
-# REs for Python signatures
-py_sig_re = re.compile(
- r'''^ ([\w.]*\.)? # class name(s)
- (\w+) \s* # thing name
- (?: \((.*)\) # optional: arguments
- (?:\s* -> \s* (.*))? # return annotation
- )? $ # and nothing more
- ''', re.VERBOSE)
-
-
-def _pseudo_parse_arglist(signode, arglist):
- """"Parse" a list of arguments separated by commas.
-
- Arguments can have "optional" annotations given by enclosing them in
- brackets. Currently, this will split at any comma, even if it's inside a
- string literal (e.g. default argument value).
- """
- paramlist = addnodes.desc_parameterlist()
- stack = [paramlist]
- try:
- for argument in arglist.split(','):
- argument = argument.strip()
- ends_open = ends_close = 0
- while argument.startswith('['):
- stack.append(addnodes.desc_optional())
- stack[-2] += stack[-1]
- argument = argument[1:].strip()
- while argument.startswith(']'):
- stack.pop()
- argument = argument[1:].strip()
- while argument.endswith(']'):
- ends_close += 1
- argument = argument[:-1].strip()
- while argument.endswith('['):
- ends_open += 1
- argument = argument[:-1].strip()
- if argument:
- stack[-1] += addnodes.desc_parameter(argument, argument, noemph=True)
- while ends_open:
- stack.append(addnodes.desc_optional())
- stack[-2] += stack[-1]
- ends_open -= 1
- while ends_close:
- stack.pop()
- ends_close -= 1
- if len(stack) != 1:
- raise IndexError
- except IndexError:
- # if there are too few or too many elements on the stack, just give up
- # and treat the whole argument list as one argument, discarding the
- # already partially populated paramlist node
- signode += addnodes.desc_parameterlist()
- signode[-1] += addnodes.desc_parameter(arglist, arglist)
- else:
- signode += paramlist
-
-
-class OCVPyObject(ObjectDescription):
- """
- Description of a general Python object.
- """
- option_spec = {
- 'noindex': directives.flag,
- 'module': directives.unchanged,
- }
-
- doc_field_types = [
- TypedField('parameter', label=l_('Parameters'),
- names=('param', 'parameter', 'arg', 'argument',
- 'keyword', 'kwarg', 'kwparam'),
- typerolename='obj', typenames=('paramtype', 'type'),
- can_collapse=True),
- TypedField('variable', label=l_('Variables'), rolename='obj',
- names=('var', 'ivar', 'cvar'),
- typerolename='obj', typenames=('vartype',),
- can_collapse=True),
- GroupedField('exceptions', label=l_('Raises'), rolename='exc',
- names=('raises', 'raise', 'exception', 'except'),
- can_collapse=True),
- Field('returnvalue', label=l_('Returns'), has_arg=False,
- names=('returns', 'return')),
- Field('returntype', label=l_('Return type'), has_arg=False,
- names=('rtype',)),
- ]
-
- def get_signature_prefix(self, sig):
- """
- May return a prefix to put before the object name in the signature.
- """
- return ''
-
- def needs_arglist(self):
- """
- May return true if an empty argument list is to be generated even if
- the document contains none.
- """
- return False
-
- def handle_signature(self, sig, signode):
- """
- Transform a Python signature into RST nodes.
- Returns (fully qualified name of the thing, classname if any).
-
- If inside a class, the current class name is handled intelligently:
- * it is stripped from the displayed name if present
- * it is added to the full name (return value) if not present
- """
- signode += nodes.strong("Python:", "Python:")
- signode += addnodes.desc_name(" ", " ")
- m = py_sig_re.match(sig)
- if m is None:
- raise ValueError
- name_prefix, name, arglist, retann = m.groups()
-
- # determine module and class name (if applicable), as well as full name
- modname = self.options.get(
- 'module', self.env.temp_data.get('py:module'))
- classname = self.env.temp_data.get('py:class')
- if classname:
- add_module = False
- if name_prefix and name_prefix.startswith(classname):
- fullname = name_prefix + name
- # class name is given again in the signature
- name_prefix = name_prefix[len(classname):].lstrip('.')
- elif name_prefix:
- # class name is given in the signature, but different
- # (shouldn't happen)
- fullname = classname + '.' + name_prefix + name
- else:
- # class name is not given in the signature
- fullname = classname + '.' + name
- else:
- add_module = True
- if name_prefix:
- classname = name_prefix.rstrip('.')
- fullname = name_prefix + name
- else:
- classname = ''
- fullname = name
-
- signode['module'] = modname
- signode['class'] = classname
- signode['fullname'] = fullname
-
- sig_prefix = self.get_signature_prefix(sig)
- if sig_prefix:
- signode += addnodes.desc_annotation(sig_prefix, sig_prefix)
-
- if name_prefix:
- signode += addnodes.desc_addname(name_prefix, name_prefix)
- # exceptions are a special case, since they are documented in the
- # 'exceptions' module.
- elif add_module and self.env.config.add_module_names:
- modname = self.options.get(
- 'module', self.env.temp_data.get('py:module'))
- if modname and modname != 'exceptions':
- nodetext = modname + '.'
- signode += addnodes.desc_addname(nodetext, nodetext)
-
- signode += addnodes.desc_name(name, name)
- if not arglist:
- if self.needs_arglist():
- # for callables, add an empty parameter list
- signode += addnodes.desc_parameterlist()
- if retann:
- signode += addnodes.desc_returns(retann, retann)
- return fullname, name_prefix
- _pseudo_parse_arglist(signode, arglist)
- if retann:
- signode += addnodes.desc_returns(retann, retann)
- return fullname, name_prefix
-
- def get_index_text(self, modname, name):
- """
- Return the text for the index entry of the object.
- """
- raise NotImplementedError('must be implemented in subclasses')
-
- def add_target_and_index(self, name_cls, sig, signode):
- modname = self.options.get(
- 'module', self.env.temp_data.get('py:module'))
- fullname = (modname and modname + '.' or '') + name_cls[0]
- # note target
- if fullname not in self.state.document.ids:
- signode['names'].append(fullname)
- signode['ids'].append(fullname)
- signode['first'] = (not self.names)
- self.state.document.note_explicit_target(signode)
- objects = self.env.domaindata['ocv']['objects']
- if fullname in objects:
- self.env.warn(
- self.env.docname,
- 'duplicate object description of %s, ' % fullname +
- 'other instance in ' +
- self.env.doc2path(objects[fullname][0]) +
- ', use :noindex: for one of them',
- self.lineno)
- objects.setdefault(fullname, (self.env.docname, self.objtype, name_cls[0]))
-
- indextext = self.get_index_text(modname, name_cls)
- if indextext:
- self.indexnode['entries'].append(('single', indextext,
- fullname, fullname))
-
- def before_content(self):
- # needed for automatic qualification of members (reset in subclasses)
- self.clsname_set = False
-
- def after_content(self):
- if self.clsname_set:
- self.env.temp_data['py:class'] = None
-
-class OCVPyModulelevel(OCVPyObject):
- """
- Description of an object on module level (functions, data).
- """
- directive_prefix = 'py'
-
- def needs_arglist(self):
- return self.objtype == self.__class__.directive_prefix + 'function'
-
- def get_index_text(self, modname, name_cls):
- if self.objtype == self.__class__.directive_prefix + 'function':
- if not modname:
- fname = name_cls[0]
- if not fname.startswith("cv") and not fname.startswith("cv2"):
- return _('%s() (Python function)') % fname
- pos = fname.find(".")
- modname = fname[:pos]
- fname = fname[pos+1:]
- return _('%s() (Python function in %s)') % (fname, modname)
- return _('%s() (Python function in %s)') % (name_cls[0], modname)
- elif self.objtype == 'pydata':
- if not modname:
- return _('%s (Python variable)') % name_cls[0]
- return _('%s (in module %s)') % (name_cls[0], modname)
- else:
- return ''
-
-class OCVPyXRefRole(XRefRole):
- def process_link(self, env, refnode, has_explicit_title, title, target):
- refnode['ocv:module'] = env.temp_data.get('ocv:module')
- refnode['ocv:class'] = env.temp_data.get('ocv:class')
- if not has_explicit_title:
- title = title.lstrip('.') # only has a meaning for the target
- target = target.lstrip('~') # only has a meaning for the title
- # if the first character is a tilde, don't display the module/class
- # parts of the contents
- if title[0:1] == '~':
- title = title[1:]
- dot = title.rfind('.')
- if dot != -1:
- title = title[dot+1:]
- # if the first character is a dot, search more specific namespaces first
- # else search builtins first
- if target[0:1] == '.':
- target = target[1:]
- refnode['refspecific'] = True
- return title, target
-
-
-########################### C/C++/Java Part ###########################
-
-_identifier_re = re.compile(r'(~?\b[a-zA-Z_][a-zA-Z0-9_]*\b)')
-_argument_name_re = re.compile(r'(~?\b[a-zA-Z_][a-zA-Z0-9_]*\b(?:\[\d*\])?|\.\.\.)')
-_whitespace_re = re.compile(r'\s+(?u)')
-_string_re = re.compile(r"[LuU8]?('([^'\\]*(?:\\.[^'\\]*)*)'"
- r'|"([^"\\]*(?:\\.[^"\\]*)*)")', re.S)
-_visibility_re = re.compile(r'\b(public|private|protected)\b')
-_operator_re = re.compile(r'''(?x)
- \[\s*\]
- | \(\s*\)
- | (<<|>>)=?
- | \+\+ | -- | ->\*?
- | [!<>=/*%+|&^-]=?
- | ~ | && | \| | \|\|
- | \,
-''')
-
-_id_shortwords = {
- 'char': 'c',
- 'signed char': 'c',
- 'unsigned char': 'C',
- 'int': 'i',
- 'signed int': 'i',
- 'unsigned int': 'U',
- 'long': 'l',
- 'signed long': 'l',
- 'unsigned long': 'L',
- 'bool': 'b',
- 'size_t': 's',
- 'std::string': 'ss',
- 'std::ostream': 'os',
- 'std::istream': 'is',
- 'std::iostream': 'ios',
- 'std::vector': 'v',
- 'std::map': 'm',
- 'operator[]': 'subscript-operator',
- 'operator()': 'call-operator',
- 'operator!': 'not-operator',
- 'operator<': 'lt-operator',
- 'operator<=': 'lte-operator',
- 'operator>': 'gt-operator',
- 'operator>=': 'gte-operator',
- 'operator=': 'assign-operator',
- 'operator/': 'div-operator',
- 'operator*': 'mul-operator',
- 'operator%': 'mod-operator',
- 'operator+': 'add-operator',
- 'operator-': 'sub-operator',
- 'operator|': 'or-operator',
- 'operator&': 'and-operator',
- 'operator^': 'xor-operator',
- 'operator&&': 'sand-operator',
- 'operator||': 'sor-operator',
- 'operator==': 'eq-operator',
- 'operator!=': 'neq-operator',
- 'operator<<': 'lshift-operator',
- 'operator>>': 'rshift-operator',
- 'operator-=': 'sub-assign-operator',
- 'operator+=': 'add-assign-operator',
- 'operator*-': 'mul-assign-operator',
- 'operator/=': 'div-assign-operator',
- 'operator%=': 'mod-assign-operator',
- 'operator&=': 'and-assign-operator',
- 'operator|=': 'or-assign-operator',
- 'operator<<=': 'lshift-assign-operator',
- 'operator>>=': 'rshift-assign-operator',
- 'operator^=': 'xor-assign-operator',
- 'operator,': 'comma-operator',
- 'operator->': 'pointer-operator',
- 'operator->*': 'pointer-by-pointer-operator',
- 'operator~': 'inv-operator',
- 'operator++': 'inc-operator',
- 'operator--': 'dec-operator',
- 'operator new': 'new-operator',
- 'operator new[]': 'new-array-operator',
- 'operator delete': 'delete-operator',
- 'operator delete[]': 'delete-array-operator'
-}
-
-
-class DefinitionError(Exception):
-
- def __init__(self, description):
- self.description = description
-
- def __unicode__(self):
- return self.description
-
- def __str__(self):
- return unicode(self.encode('utf-8'))
-
-
-class DefExpr(object):
-
- def __unicode__(self):
- raise NotImplementedError()
-
- def __eq__(self, other):
- if type(self) is not type(other):
- return False
- try:
- for key, value in self.__dict__.iteritems():
- if value != getattr(other, value):
- return False
- except AttributeError:
- return False
- return True
-
- def __ne__(self, other):
- return not self.__eq__(other)
-
- def clone(self):
- """Close a definition expression node"""
- return deepcopy(self)
-
- def get_id(self):
- """Returns the id for the node"""
- return u''
-
- def get_name(self):
- """Returns the name. Returns either `None` or a node with
- a name you might call :meth:`split_owner` on.
- """
- return None
-
- def split_owner(self):
- """Nodes returned by :meth:`get_name` can split off their
- owning parent. This function returns the owner and the
- name as a tuple of two items. If a node does not support
- it, it returns None as owner and self as name.
- """
- return None, self
-
- def prefix(self, prefix):
- """Prefixes a name node (a node returned by :meth:`get_name`)."""
- raise NotImplementedError()
-
- def __str__(self):
- return unicode(self).encode('utf-8')
-
- def __repr__(self):
- return '<%s %s>' % (self.__class__.__name__, self)
-
-
-class PrimaryDefExpr(DefExpr):
-
- def get_name(self):
- return self
-
- def prefix(self, prefix):
- if isinstance(prefix, PathDefExpr):
- prefix = prefix.clone()
- prefix.path.append(self)
- return prefix
- return PathDefExpr([prefix, self])
-
-
-class NameDefExpr(PrimaryDefExpr):
-
- def __init__(self, name):
- self.name = name
-
- def get_id(self):
- name = _id_shortwords.get(self.name)
- if name is not None:
- return name
- return self.name.replace(u' ', u'-')
-
- def __unicode__(self):
- return unicode(self.name)
-
-
-class PathDefExpr(PrimaryDefExpr):
-
- def __init__(self, parts):
- self.path = parts
-
- def get_id(self):
- rv = u'::'.join(x.get_id() for x in self.path)
- return _id_shortwords.get(rv, rv)
-
- def split_owner(self):
- if len(self.path) > 1:
- return PathDefExpr(self.path[:-1]), self.path[-1]
- return None, self
-
- def prefix(self, prefix):
- if isinstance(prefix, PathDefExpr):
- prefix = prefix.clone()
- prefix.path.extend(self.path)
- return prefix
- return PathDefExpr([prefix] + self.path)
-
- def __unicode__(self):
- return u'::'.join(map(unicode, self.path))
-
-
-class TemplateDefExpr(PrimaryDefExpr):
-
- def __init__(self, typename, args):
- self.typename = typename
- self.args = args
-
- def split_owner(self):
- owner, typename = self.typename.split_owner()
- return owner, TemplateDefExpr(typename, self.args)
-
- def get_id(self):
- return u'%s:%s:' % (self.typename.get_id(),
- u'.'.join(x.get_id() for x in self.args))
-
- def __unicode__(self):
- return u'%s<%s>' % (self.typename, u', '.join(map(unicode, self.args)))
-
-
-class WrappingDefExpr(DefExpr):
-
- def __init__(self, typename):
- self.typename = typename
-
- def get_name(self):
- return self.typename.get_name()
-
-
-class ModifierDefExpr(WrappingDefExpr):
-
- def __init__(self, typename, modifiers):
- WrappingDefExpr.__init__(self, typename)
- self.modifiers = modifiers
-
- def get_id(self):
- pieces = [_id_shortwords.get(unicode(x), unicode(x))
- for x in self.modifiers]
- pieces.append(self.typename.get_id())
- return u'-'.join(pieces)
-
- def __unicode__(self):
- return u' '.join(map(unicode, list(self.modifiers) + [self.typename]))
-
-
-class PtrDefExpr(WrappingDefExpr):
-
- def get_id(self):
- return self.typename.get_id() + u'P'
-
- def __unicode__(self):
- return u'%s*' % self.typename
-
-
-class RefDefExpr(WrappingDefExpr):
-
- def get_id(self):
- return self.typename.get_id() + u'R'
-
- def __unicode__(self):
- return u'%s&' % self.typename
-
-
-class ConstDefExpr(WrappingDefExpr):
-
- def __init__(self, typename, prefix=False):
- WrappingDefExpr.__init__(self, typename)
- self.prefix = prefix
-
- def get_id(self):
- return self.typename.get_id() + u'C'
-
- def __unicode__(self):
- return (self.prefix and u'const %s' or u'%s const') % self.typename
-
-class ConstTemplateDefExpr(WrappingDefExpr):
-
- def __init__(self, typename, prefix=False):
- WrappingDefExpr.__init__(self, typename)
- self.prefix = prefix
-
- def get_id(self):
- return self.typename.get_id() + u'C'
-
- def __unicode__(self):
- return (self.prefix and u'const %s' or u'%s const') % self.typename
-
-
-class CastOpDefExpr(PrimaryDefExpr):
-
- def __init__(self, typename):
- self.typename = typename
-
- def get_id(self):
- return u'castto-%s-operator' % self.typename.get_id()
-
- def __unicode__(self):
- return u'operator %s' % self.typename
-
-
-class ArgumentDefExpr(DefExpr):
-
- def __init__(self, type, name, default=None):
- self.name = name
- self.type = type
- self.default = default
-
- def get_name(self):
- return self.name.get_name()
-
- def get_id(self):
- if self.type is None:
- return 'X'
- return self.type.get_id()
-
- def __unicode__(self):
- return (u'%s %s' % (self.type or u'', self.name or u'')).strip() + \
- (self.default is not None and u'=%s' % self.default or u'')
-
-
-class NamedDefExpr(DefExpr):
-
- def __init__(self, name, visibility, static):
- self.name = name
- self.visibility = visibility
- self.static = static
-
- def get_name(self):
- return self.name.get_name()
-
- def get_modifiers(self):
- rv = []
- if self.visibility != 'public':
- rv.append(self.visibility)
- if self.static:
- rv.append(u'static')
- return rv
-
-
-class TypeObjDefExpr(NamedDefExpr):
-
- def __init__(self, name, visibility, static, typename):
- NamedDefExpr.__init__(self, name, visibility, static)
- self.typename = typename
-
- def get_id(self):
- if self.typename is None:
- return self.name.get_id()
- return u'%s__%s' % (self.name.get_id(), self.typename.get_id())
-
- def __unicode__(self):
- buf = self.get_modifiers()
- if self.typename is None:
- buf.append(unicode(self.name))
- else:
- buf.extend(map(unicode, (self.typename, self.name)))
- return u' '.join(buf)
-
-
-class MemberObjDefExpr(NamedDefExpr):
-
- def __init__(self, name, visibility, static, typename, value):
- NamedDefExpr.__init__(self, name, visibility, static)
- self.typename = typename
- self.value = value
-
- def get_id(self):
- return u'%s__%s' % (self.name.get_id(), self.typename.get_id())
-
- def __unicode__(self):
- buf = self.get_modifiers()
- buf.append(u'%s %s' % (self.typename, self.name))
- if self.value is not None:
- buf.append(u'= %s' % self.value)
- return u' '.join(buf)
-
-
-class FuncDefExpr(NamedDefExpr):
-
- def __init__(self, name, visibility, static, explicit, rv,
- signature, const, pure_virtual, virtual):
- NamedDefExpr.__init__(self, name, visibility, static)
- self.rv = rv
- self.signature = signature
- self.explicit = explicit
- self.const = const
- self.pure_virtual = pure_virtual
- self.virtual = virtual
-
- def get_id(self):
- return u'%s%s%s' % (
- self.name.get_id(),
- self.signature and u'__' +
- u'.'.join(x.get_id() for x in self.signature) or u'',
- self.const and u'C' or u''
- )
-
- def __unicode__(self):
- buf = self.get_modifiers()
- if self.explicit:
- buf.append(u'explicit')
- if self.virtual:
- buf.append(u'virtual')
- if self.rv is not None:
- buf.append(unicode(self.rv))
- buf.append(u'%s(%s)' % (self.name, u', '.join(
- map(unicode, self.signature))))
- if self.const:
- buf.append(u'const')
- if self.pure_virtual:
- buf.append(u'= 0')
- return u' '.join(buf)
-
-
-class ClassDefExpr(NamedDefExpr):
-
- def __init__(self, name, visibility, static, parents = None):
- NamedDefExpr.__init__(self, name, visibility, static)
- self.parents = parents
-
- def get_id(self):
- return self.name.get_id()
-
- def __unicode__(self):
- buf = self.get_modifiers()
- buf.append(unicode(self.name))
- return u' '.join(buf)
-
-
-class DefinitionParser(object):
-
- # mapping of valid type modifiers. if the set is None it means
- # the modifier can prefix all types, otherwise only the types
- # (actually more keywords) in the set. Also check
- # _guess_typename when changing this.
- _modifiers = {
- 'volatile': None,
- 'register': None,
- 'mutable': None,
- 'const': None,
- 'typename': None,
- 'unsigned': set(('char', 'short', 'int', 'long')),
- 'signed': set(('char', 'short', 'int', 'long')),
- 'short': set(('int',)),
- 'long': set(('int', 'long', 'double'))
- }
-
- def __init__(self, definition):
- self.definition = definition.strip()
- self.pos = 0
- self.end = len(self.definition)
- self.last_match = None
- self._previous_state = (0, None)
-
- def fail(self, msg):
- raise DefinitionError('Invalid definition: %s [error at %d]\n %s' %
- (msg, self.pos, self.definition))
-
- def match(self, regex):
- match = regex.match(self.definition, self.pos)
- if match is not None:
- self._previous_state = (self.pos, self.last_match)
- self.pos = match.end()
- self.last_match = match
- return True
- return False
-
- def backout(self):
- self.pos, self.last_match = self._previous_state
-
- def skip_string(self, string):
- strlen = len(string)
- if self.definition[self.pos:self.pos + strlen] == string:
- self.pos += strlen
- return True
- return False
-
- def skip_word(self, word):
- return self.match(re.compile(r'\b%s\b' % re.escape(word)))
-
- def skip_ws(self):
- return self.match(_whitespace_re)
-
- @property
- def eof(self):
- return self.pos >= self.end
-
- @property
- def current_char(self):
- try:
- return self.definition[self.pos]
- except IndexError:
- return 'EOF'
-
- @property
- def matched_text(self):
- if self.last_match is not None:
- return self.last_match.group()
-
- def _parse_operator(self):
- self.skip_ws()
- # thank god, a regular operator definition
- if self.match(_operator_re):
- return NameDefExpr('operator' +
- _whitespace_re.sub('', self.matched_text))
- # new/delete operator?
- for allocop in 'new', 'delete':
- if not self.skip_word(allocop):
- continue
- self.skip_ws()
- if self.skip_string('['):
- self.skip_ws()
- if not self.skip_string(']'):
- self.fail('expected "]" for ' + allocop)
- allocop += '[]'
- return NameDefExpr('operator ' + allocop)
-
- # oh well, looks like a cast operator definition.
- # In that case, eat another type.
- type = self._parse_type()
- return CastOpDefExpr(type)
-
- def _parse_name(self):
- if not self.match(_argument_name_re):
- self.fail('expected name')
- identifier = self.matched_text
-
- # strictly speaking, operators are not regular identifiers
- # but because operator is a keyword, it might not be used
- # for variable names anyways, so we can safely parse the
- # operator here as identifier
- if identifier == 'operator':
- return self._parse_operator()
-
- return NameDefExpr(identifier)
-
- def _guess_typename(self, path):
- if not path:
- return [], 'int'
- # for the long type, we don't want the int in there
- if 'long' in path:
- path = [x for x in path if x != 'int']
- # remove one long
- path.remove('long')
- return path, 'long'
- if path[-1] in ('int', 'char'):
- return path[:-1], path[-1]
- return path, 'int'
-
- def _attach_crefptr(self, expr, is_const=False):
- if is_const:
- expr = ConstDefExpr(expr, prefix=True)
- while 1:
- self.skip_ws()
- if self.skip_word('const'):
- expr = ConstDefExpr(expr)
- elif self.skip_string('*'):
- expr = PtrDefExpr(expr)
- elif self.skip_string('&'):
- expr = RefDefExpr(expr)
- else:
- return expr
-
- def _peek_const(self, path):
- try:
- path.remove('const')
- return True
- except ValueError:
- return False
-
- def _parse_builtin(self, modifier):
- path = [modifier]
- following = self._modifiers[modifier]
- while 1:
- self.skip_ws()
- if not self.match(_identifier_re):
- break
- identifier = self.matched_text
- if identifier in following:
- path.append(identifier)
- following = self._modifiers[modifier]
- assert following
- else:
- self.backout()
- break
-
- is_const = self._peek_const(path)
- modifiers, typename = self._guess_typename(path)
- rv = ModifierDefExpr(NameDefExpr(typename), modifiers)
- return self._attach_crefptr(rv, is_const)
-
- def _parse_type_expr(self):
- typename = self._parse_name()
- if typename and self.skip_string('['):
- typename.name += '['
- if self.match(re.compile(r'\d*')):
- typename.name += self.last_match.group(0)
- typename.name += ']'
- if not self.skip_string(']'):
- self.fail('expected type')
- self.skip_ws()
- if not self.skip_string('<'):
- return typename
-
- args = []
- while 1:
- self.skip_ws()
- if self.skip_string('>'):
- break
- if args:
- if not self.skip_string(','):
- self.fail('"," or ">" in template expected')
- self.skip_ws()
- args.append(self._parse_type(True))
- return TemplateDefExpr(typename, args)
-
- def _parse_type(self, in_template=False):
- self.skip_ws()
- result = []
- modifiers = []
-
- if self.match(re.compile(r'template\w*<([^>]*)>')):
- args = self.last_match.group(1).split(',')
- args = [a.strip() for a in args]
- modifiers.append(TemplateDefExpr('template', args))
-
- # if there is a leading :: or not, we don't care because we
- # treat them exactly the same. Buf *if* there is one, we
- # don't have to check for type modifiers
- if not self.skip_string('::'):
- self.skip_ws()
- while self.match(_identifier_re):
- modifier = self.matched_text
- if modifier in self._modifiers:
- following = self._modifiers[modifier]
- # if the set is not none, there is a limited set
- # of types that might follow. It is technically
- # impossible for a template to follow, so what
- # we do is go to a different function that just
- # eats types
- if following is not None:
- return self._parse_builtin(modifier)
- modifiers.append(modifier)
- else:
- self.backout()
- break
-
- while 1:
- self.skip_ws()
- if (in_template and self.current_char in ',>') or \
- (result and not self.skip_string('::')) or \
- self.eof:
- break
- result.append(self._parse_type_expr())
-
- if not result:
- self.fail('expected type')
- if len(result) == 1:
- rv = result[0]
- else:
- rv = PathDefExpr(result)
- is_const = self._peek_const(modifiers)
- if is_const:
- rv = ConstDefExpr(rv, prefix=True)
- if modifiers:
- rv = ModifierDefExpr(rv, modifiers)
- return self._attach_crefptr(rv, False)
-
- def _parse_default_expr(self):
- self.skip_ws()
- if self.match(_string_re):
- return self.matched_text
- paren_stack_depth = 0
- max_pos = len(self.definition)
- rv_start = self.pos
- while 1:
- idx0 = self.definition.find('(', self.pos)
- idx1 = self.definition.find(',', self.pos)
- idx2 = self.definition.find(')', self.pos)
- if idx0 < 0:
- idx0 = max_pos
- if idx1 < 0:
- idx1 = max_pos
- if idx2 < 0:
- idx2 = max_pos
- idx = min(idx0, idx1, idx2)
- if idx >= max_pos:
- self.fail('unexpected end in default expression')
- if idx == idx0:
- paren_stack_depth += 1
- elif idx == idx2:
- paren_stack_depth -= 1
- if paren_stack_depth < 0:
- break
- elif paren_stack_depth == 0:
- break
- self.pos = idx+1
-
- rv = self.definition[rv_start:idx]
- self.pos = idx
- return rv
-
- def _parse_signature(self):
- if r'CvStatModel::train' in self.definition:
- # hack to skip parsing of problematic definition
- self.pos = self.end
- return [ArgumentDefExpr("const Mat&", "train_data", None), ArgumentDefExpr(None, self.definition[self.definition.find("["):-1], None)], False, True
-
- self.skip_ws()
- if not self.skip_string('('):
- self.fail('expected parentheses for function')
-
- args = []
- while 1:
- self.skip_ws()
- if self.eof:
- self.fail('missing closing parentheses')
- if self.skip_string(')'):
- break
- if args:
- if not self.skip_string(','):
- self.fail('expected comma between arguments')
- self.skip_ws()
-
- argtype = self._parse_type()
- self.skip_ws()
- if unicode(argtype) == u"...":
- if not self.skip_string(')'):
- self.fail("var arg must be the last argument")
- args.append(ArgumentDefExpr(None, argtype, None))
- break
- argname = default = None
- if self.skip_string('='):
- self.pos += 1
- default = self._parse_default_expr()
- elif self.current_char not in ',)':
- argname = self._parse_name()
- self.skip_ws()
- if self.skip_string('='):
- default = self._parse_default_expr()
-
- args.append(ArgumentDefExpr(argtype, argname, default))
- self.skip_ws()
- const = self.skip_word('const')
- if const:
- self.skip_ws()
- if self.skip_string('='):
- self.skip_ws()
- if not (self.skip_string('0') or \
- self.skip_word('NULL') or \
- self.skip_word('nullptr')):
- self.fail('pure virtual functions must be defined with '
- 'either 0, NULL or nullptr, other macros are '
- 'not allowed')
- pure_virtual = True
- else:
- pure_virtual = False
- return args, const, pure_virtual
-
- def _parse_visibility_static(self):
- visibility = 'public'
- if self.match(_visibility_re):
- visibility = self.matched_text
- static = self.skip_word('static')
- return visibility, static
-
- def parse_type(self):
- return self._parse_type()
-
- def parse_type_object(self):
- visibility, static = self._parse_visibility_static()
- typename = self._parse_type()
- self.skip_ws()
- if not self.eof:
- name = self._parse_type()
- else:
- name = typename
- typename = None
- return TypeObjDefExpr(name, visibility, static, typename)
-
- def parse_member_object(self):
- visibility, static = self._parse_visibility_static()
- typename = self._parse_type()
- name = self._parse_type()
- self.skip_ws()
- if self.skip_string('='):
- value = self.read_rest().strip()
- else:
- value = None
- return MemberObjDefExpr(name, visibility, static, typename, value)
-
- def parse_enum_member_object(self):
- visibility, static = self._parse_visibility_static()
- typename = None
- name = self._parse_type()
- self.skip_ws()
- if self.skip_string('='):
- value = self.read_rest().strip()
- else:
- value = None
- return MemberObjDefExpr(name, visibility, static, typename, value)
-
- def parse_function(self):
- visibility, static = self._parse_visibility_static()
- if self.skip_word('explicit'):
- explicit = True
- self.skip_ws()
- else:
- explicit = False
- if self.skip_word('virtual'):
- virtual = True
- self.skip_ws()
- else:
- virtual = False
- rv = self._parse_type()
- self.skip_ws()
- # some things just don't have return values
- if self.current_char == '(':
- name = rv
- rv = None
- else:
- name = self._parse_type()
- return FuncDefExpr(name, visibility, static, explicit, rv,
- *self._parse_signature(), virtual = virtual)
-
- def parse_class(self):
- visibility, static = self._parse_visibility_static()
- typename = self._parse_type()
- parent = None
- self.skip_ws()
- parents = []
- if self.skip_string(':'):
- while not self.eof:
- self.skip_ws()
- classname_pos = self.pos
- pvisibility, pstatic = self._parse_visibility_static()
- if pstatic:
- self.fail('unsepected static keyword, got %r' %
- self.definition[self.classname_pos:])
- parents.append(ClassDefExpr(self._parse_type(), pvisibility, pstatic))
- if not self.skip_string(','):
- break
- return ClassDefExpr(typename, visibility, static, parents)
-
- def read_rest(self):
- rv = self.definition[self.pos:]
- self.pos = self.end
- return rv
-
- def assert_end(self):
- self.skip_ws()
- if not self.eof:
- self.fail('expected end of definition, got %r' %
- self.definition[self.pos:])
-
-
-class OCVObject(ObjectDescription):
- """Description of a C++ language object."""
-
- langname = "C++"
- ismember = False
-
- doc_field_types = [
- TypedField('parameter', label=l_('Parameters'),
- names=('param', 'parameter', 'arg', 'argument'),
- typerolename='type', typenames=('type',)),
- Field('returnvalue', label=l_('Returns'), has_arg=False,
- names=('returns', 'return')),
- Field('returntype', label=l_('Return type'), has_arg=False,
- names=('rtype',)),
- ]
-
- def attach_name(self, node, name):
- owner, name = name.split_owner()
- varname = unicode(name)
- if owner is not None:
- owner = unicode(owner) + '::'
- node += addnodes.desc_addname(owner, owner)
- node += addnodes.desc_name(varname, varname)
-
- def attach_type(self, node, type):
- # XXX: link to c?
- text = unicode(type)
- pnode = addnodes.pending_xref(
- '', refdomain='ocv', reftype='type',
- reftarget=text, modname=None, classname=None)
- pnode['ocv:parent'] = self.env.temp_data.get('ocv:parent')
- pnode += nodes.Text(text)
- node += pnode
-
- def attach_modifiers(self, node, obj):
- if not self.__class__.ismember:
- lname = self.__class__.langname
- node += nodes.strong(lname + ":", lname + ":")
- node += addnodes.desc_name(" ", " ")
-
- if obj.visibility != 'public':
- node += addnodes.desc_annotation(obj.visibility,
- obj.visibility)
- node += nodes.Text(' ')
- if obj.static:
- node += addnodes.desc_annotation('static', 'static')
- node += nodes.Text(' ')
-
- def add_target_and_index(self, sigobj, sig, signode):
- theid = sig#obj.get_id()
- theid = re.sub(r" +", " ", theid)
- if self.objtype == 'emember':
- theid = re.sub(r" ?=.*", "", theid)
- theid = re.sub(r"=[^,()]+\([^)]*?\)[^,)]*(,|\))", "\\1", theid)
- theid = re.sub(r"=\w*[^,)(]+(,|\))", "\\1", theid)
- theid = theid.replace("( ", "(").replace(" )", ")")
- name = unicode(sigobj.name)
- if theid not in self.state.document.ids:
- signode['names'].append(theid)
- signode['ids'].append(theid)
- signode['first'] = (not self.names)
- self.state.document.note_explicit_target(signode)
-
- #self.env.domaindata['ocv']['objects'].setdefault(name,
- #(self.env.docname, self.objtype, theid))
- self.env.domaindata['ocv']['objects'].setdefault(theid,
- (self.env.docname, self.objtype, theid))
- self.env.domaindata['ocv']['objects2'].setdefault(name,
- (self.env.docname, self.objtype, theid))
-
- indextext = self.get_index_text(name)
- if indextext:
- self.indexnode['entries'].append(('single', indextext, theid, name))
-
- def before_content(self):
- lastname = self.names and self.names[-1]
- if lastname and not self.env.temp_data.get('ocv:parent'):
- assert isinstance(lastname, NamedDefExpr)
- self.env.temp_data['ocv:parent'] = lastname.name
- self.parentname_set = True
- else:
- self.parentname_set = False
-
- def after_content(self):
- if self.parentname_set:
- self.env.temp_data['ocv:parent'] = None
-
- def parse_definition(self, parser):
- raise NotImplementedError()
-
- def describe_signature(self, signode, arg):
- raise NotImplementedError()
-
- def handle_signature(self, sig, signode):
- parser = DefinitionParser(sig)
- try:
- rv = self.parse_definition(parser)
- parser.assert_end()
- except DefinitionError, e:
- self.env.warn(self.env.docname,
- e.description, self.lineno)
- raise ValueError
- self.describe_signature(signode, rv)
-
- parent = self.env.temp_data.get('ocv:parent')
- if parent is not None:
- rv = rv.clone()
- rv.name = rv.name.prefix(parent)
- return rv
-
-
-class OCVClassObject(OCVObject):
- object_annotation = "class "
- object_long_name = "class"
-
- def attach_modifiers(self, node, obj, skip_visibility = 'public'):
- if obj.visibility != skip_visibility:
- node += addnodes.desc_annotation(obj.visibility,
- obj.visibility)
- node += nodes.Text(' ')
- if obj.static:
- node += addnodes.desc_annotation('static', 'static')
- node += nodes.Text(' ')
-
- def get_index_text(self, name):
- return _('%s (C++ %s)') % (name, self.__class__.object_long_name)
-
- def parse_definition(self, parser):
- return parser.parse_class()
-
- def describe_signature(self, signode, cls):
- self.attach_modifiers(signode, cls)
- signode += addnodes.desc_annotation(self.__class__.object_annotation, self.__class__.object_annotation)
- self.attach_name(signode, cls.name)
- first_parent = True
- for p in cls.parents:
- if first_parent:
- signode += nodes.Text(' : ')
- first_parent = False
- else:
- signode += nodes.Text(', ')
- self.attach_modifiers(signode, p, None)
- self.attach_name(signode, p.name)
-
-class OCVStructObject(OCVClassObject):
- object_annotation = "struct "
- object_long_name = "structure"
-
-class OCVTypeObject(OCVObject):
-
- def get_index_text(self, name):
- if self.objtype == 'type':
- return _('%s (C++ type)') % name
- return ''
-
- def parse_definition(self, parser):
- return parser.parse_type_object()
-
- def describe_signature(self, signode, obj):
- self.attach_modifiers(signode, obj)
- signode += addnodes.desc_annotation('type ', 'type ')
- if obj.typename is not None:
- self.attach_type(signode, obj.typename)
- signode += nodes.Text(' ')
- self.attach_name(signode, obj.name)
-
-class OCVEnumObject(OCVObject):
-
- def get_index_text(self, name):
- if self.objtype == 'enum':
- return _('%s (enum)') % name
- return ''
-
- def parse_definition(self, parser):
- return parser.parse_type_object()
-
- def describe_signature(self, signode, obj):
- self.attach_modifiers(signode, obj)
- signode += addnodes.desc_annotation('enum ', 'enum ')
- if obj.typename is not None:
- self.attach_type(signode, obj.typename)
- signode += nodes.Text(' ')
- self.attach_name(signode, obj.name)
-
-
-class OCVMemberObject(OCVObject):
- ismember = True
-
- def get_index_text(self, name):
- if self.objtype == 'member':
- return _('%s (C++ member)') % name
- return ''
-
- def parse_definition(self, parser):
- parent_class = self.env.temp_data.get('ocv:parent')
- if parent_class is None:
- parser.fail("missing parent structure/class")
- return parser.parse_member_object()
-
- def describe_signature(self, signode, obj):
- self.attach_modifiers(signode, obj)
- if obj.typename:
- self.attach_type(signode, obj.typename)
- signode += nodes.Text(' ')
- self.attach_name(signode, obj.name)
- if obj.value is not None:
- signode += nodes.Text(u' = ' + obj.value)
-
-class OCVEnumMemberObject(OCVMemberObject):
- def parse_definition(self, parser):
- # parent_class = self.env.temp_data.get('ocv:parent')
- # if parent_class is None:
- # parser.fail("missing parent structure/class")
- return parser.parse_enum_member_object()
-
-class OCVFunctionObject(OCVObject):
-
- def attach_function(self, node, func):
- owner, name = func.name.split_owner()
- if owner is not None:
- owner = unicode(owner) + '::'
- node += addnodes.desc_addname(owner, owner)
-
- # cast operator is special. in this case the return value
- # is reversed.
- if isinstance(name, CastOpDefExpr):
- node += addnodes.desc_name('operator', 'operator')
- node += nodes.Text(u' ')
- self.attach_type(node, name.typename)
- else:
- funcname = unicode(name)
- node += addnodes.desc_name(funcname, funcname)
-
- paramlist = addnodes.desc_parameterlist()
- for arg in func.signature:
- param = addnodes.desc_parameter('', '', noemph=True)
- if arg.type is not None:
- self.attach_type(param, arg.type)
- param += nodes.Text(u' ')
- #param += nodes.emphasis(unicode(arg.name), unicode(arg.name))
- sbrIdx = unicode(arg.name).find("[")
- if sbrIdx < 0:
- param += nodes.strong(unicode(arg.name), unicode(arg.name))
- else:
- param += nodes.strong(unicode(arg.name)[:sbrIdx], unicode(arg.name)[:sbrIdx])
- param += nodes.Text(unicode(arg.name)[sbrIdx:])
- if arg.default is not None:
- def_ = u'=' + unicode(arg.default)
- #param += nodes.emphasis(def_, def_)
- param += nodes.Text(def_)
- paramlist += param
-
- node += paramlist
- if func.const:
- node += addnodes.desc_addname(' const', ' const')
- if func.pure_virtual:
- node += addnodes.desc_addname(' = 0', ' = 0')
-
- def get_index_text(self, name):
- lname = self.__class__.langname
- if lname == "C" and name.startswith("cv"):
- name = name[2:]
- return _('%s (%s function)') % (name, lname)
-
- def parse_definition(self, parser):
- return parser.parse_function()
-
- def describe_signature(self, signode, func):
- self.attach_modifiers(signode, func)
- if func.explicit:
- signode += addnodes.desc_annotation('explicit', 'explicit')
- signode += nodes.Text(' ')
- if func.virtual:
- signode += addnodes.desc_annotation('virtual', 'virtual')
- signode += nodes.Text(' ')
- # return value is None for things with a reverse return value
- # such as casting operator definitions or constructors
- # and destructors.
- if func.rv is not None:
- self.attach_type(signode, func.rv)
- signode += nodes.Text(u' ')
- self.attach_function(signode, func)
-
-
-class OCVCurrentNamespace(Directive):
- """This directive is just to tell Sphinx that we're documenting
- stuff in namespace foo.
- """
-
- has_content = False
- required_arguments = 1
- optional_arguments = 0
- final_argument_whitespace = True
- option_spec = {}
-
- def run(self):
- env = self.state.document.settings.env
- if self.arguments[0].strip() in ('NULL', '0', 'nullptr'):
- env.temp_data['ocv:prefix'] = None
- else:
- parser = DefinitionParser(self.arguments[0])
- try:
- prefix = parser.parse_type()
- parser.assert_end()
- except DefinitionError, e:
- self.env.warn(self.env.docname,
- e.description, self.lineno)
- else:
- env.temp_data['ocv:prefix'] = prefix
- return []
-
-
-class OCVXRefRole(XRefRole):
-
- def process_link(self, env, refnode, has_explicit_title, title, target):
- refnode['ocv:parent'] = env.temp_data.get('ocv:parent')
- if not has_explicit_title:
- target = target.lstrip('~') # only has a meaning for the title
- # if the first character is a tilde, don't display the module/class
- # parts of the contents
- if title[:1] == '~':
- title = title[1:]
- dcolon = title.rfind('::')
- if dcolon != -1:
- title = title[dcolon + 2:]
- return title, target
-
-
-class OCVCFunctionObject(OCVFunctionObject):
- langname = "C"
-
-class OCVJavaFunctionObject(OCVFunctionObject):
- langname = "Java"
-
-
-class OCVDomain(Domain):
- """OpenCV C++ language domain."""
- name = 'ocv'
- label = 'C++'
- object_types = {
- 'class': ObjType(l_('class'), 'class'),
- 'struct': ObjType(l_('struct'), 'struct'),
- 'function': ObjType(l_('function'), 'func', 'funcx'),
- 'cfunction': ObjType(l_('cfunction'), 'cfunc', 'cfuncx'),
- 'jfunction': ObjType(l_('jfunction'), 'jfunc', 'jfuncx'),
- 'pyfunction': ObjType(l_('pyfunction'), 'pyfunc'),
- 'member': ObjType(l_('member'), 'member'),
- 'emember': ObjType(l_('emember'), 'emember'),
- 'type': ObjType(l_('type'), 'type'),
- 'enum': ObjType(l_('enum'), 'enum')
- }
-
- directives = {
- 'class': OCVClassObject,
- 'struct': OCVStructObject,
- 'function': OCVFunctionObject,
- 'cfunction': OCVCFunctionObject,
- 'jfunction': OCVJavaFunctionObject,
- 'pyfunction': OCVPyModulelevel,
- 'member': OCVMemberObject,
- 'emember': OCVEnumMemberObject,
- 'type': OCVTypeObject,
- 'enum': OCVEnumObject,
- 'namespace': OCVCurrentNamespace
- }
- roles = {
- 'class': OCVXRefRole(),
- 'struct': OCVXRefRole(),
- 'func' : OCVXRefRole(fix_parens=True),
- 'funcx' : OCVXRefRole(),
- 'cfunc' : OCVXRefRole(fix_parens=True),
- 'cfuncx' : OCVXRefRole(),
- 'jfunc' : OCVXRefRole(fix_parens=True),
- 'jfuncx' : OCVXRefRole(),
- 'pyfunc' : OCVPyXRefRole(),
- 'member': OCVXRefRole(),
- 'emember': OCVXRefRole(),
- 'type': OCVXRefRole(),
- 'enum': OCVXRefRole()
- }
- initial_data = {
- 'objects': {}, # fullname -> docname, objtype
- }
-
- def __init__(self, env):
- Domain.__init__(self, env)
- self.data['objects2'] = {}
-
- def clear_doc(self, docname):
- for fullname, (fn, _, _) in self.data['objects'].items():
- if fn == docname:
- del self.data['objects'][fullname]
-
- def resolve_xref(self, env, fromdocname, builder,
- typ, target, node, contnode):
- def _create_refnode(expr):
- name = unicode(expr)
- if "type" in self.objtypes_for_role(typ):
- return None
- if "cfunction" in self.objtypes_for_role(typ):
- if not name.startswith(u'cv'):
- name = u'cv' + name
- dict = self.data['objects']
- if name not in dict:
- dict = self.data['objects2']
- if name not in dict:
- refdoc = node.get('refdoc', fromdocname)
- env.warn(refdoc, 'unresolved reference: %r - %r' % (target, typ), node.line)
- return None
- obj = dict[name]
- if obj[1] not in self.objtypes_for_role(typ):
- return None
- title = obj[2]
- if "class" in self.objtypes_for_role(typ):
- title = u"class " + title
- elif "struct" in self.objtypes_for_role(typ):
- title = u"struct " + title
- return make_refnode(builder, fromdocname, obj[0], obj[2],
- contnode, title)
-
- parser = DefinitionParser(target)
- try:
- expr = parser.parse_type().get_name()
- parser.skip_ws()
- if not parser.eof or expr is None:
- raise DefinitionError('')
- except DefinitionError:
- refdoc = node.get('refdoc', fromdocname)
- env.warn(refdoc, 'unparseable C++ definition: %r' % target,
- node.line)
- return None
-
- parent = node['ocv:parent']
-
- rv = _create_refnode(expr)
- if rv is not None or parent is None:
- return rv
- parent = parent.get_name()
-
- rv = _create_refnode(expr.prefix(parent))
- if rv is not None:
- return rv
-
- parent, name = parent.split_owner()
- return _create_refnode(expr.prefix(parent))
-
- def get_objects(self):
- for refname, (docname, type, theid) in self.data['objects'].iteritems():
- yield (refname, refname, type, docname, refname, 1)
-
- def get_type_name(self, type, primary=False):
- """
- Return full name for given ObjType.
- """
- if primary:
- return type.lname
-
- return {
- 'class': _('C++ class'),
- 'struct': _('C/C++ struct'),
- 'function': _('C++ function'),
- 'cfunction': _('C function'),
- 'jfunction': _('Java method'),
- 'pyfunction': _('Python function'),
- 'member': _('C++ member'),
- 'emember': _('enum member'),
- 'type': _('C/C++ type'),
- 'enum': _('C/C++ enum'),
- 'namespace': _('C++ namespace'),
- }.get(type.lname, _('%s %s') % (self.label, type.lname))
-
-def setup(app):
- app.add_domain(OCVDomain)
diff --git a/doc/opencv_cheatsheet.tex b/doc/opencv_cheatsheet.tex
deleted file mode 100644
index 01d5c275d9d53d2be70ecf8f9d3154f957785225..0000000000000000000000000000000000000000
--- a/doc/opencv_cheatsheet.tex
+++ /dev/null
@@ -1,620 +0,0 @@
-%
-% The OpenCV cheatsheet structure:
-%
-% opencv data structures
-% point, rect
-% matrix
-%
-% creating matrices
-% from scratch
-% from previously allocated data: plain arrays, vectors
-% converting to/from old-style structures
-%
-% element access, iteration through matrix elements
-%
-% copying & shuffling matrix data
-% copying & converting the whole matrices
-% extracting matrix parts & copying them
-% split, merge & mixchannels
-% flip, transpose, repeat
-%
-% matrix & image operations:
-% arithmetics & logic
-% matrix multiplication, inversion, determinant, trace, SVD
-% statistical functions
-%
-% basic image processing:
-% image filtering with predefined & custom filters
-% example: finding local maxima
-% geometrical transformations, resize, warpaffine, perspective & remap.
-% color space transformations
-% histograms & back projections
-% contours
-%
-% i/o:
-% displaying images
-% saving/loading to/from file (XML/YAML & image file formats)
-% reading videos & camera feed, writing videos
-%
-% operations on point sets:
-% findcontours, bounding box, convex hull, min area rect,
-% transformations, to/from homogeneous coordinates
-% matching point sets: homography, fundamental matrix, rigid transforms
-%
-% 3d:
-% camera calibration, pose estimation.
-% uncalibrated case
-% stereo: rectification, running stereo correspondence, obtaining the depth.
-%
-% feature detection:
-% features2d toolbox
-%
-% object detection:
-% using a classifier running on a sliding window: cascadeclassifier + hog.
-% using salient point features: features2d -> matching
-%
-% statistical data processing:
-% clustering (k-means),
-% classification + regression (SVM, boosting, k-nearest),
-% compressing data (PCA)
-%
-
-\documentclass[10pt,landscape]{article}
-\usepackage[usenames,dvips,pdftex]{color}
-\usepackage{multicol}
-\usepackage{calc}
-\usepackage{ifthen}
-\usepackage[pdftex]{color,graphicx}
-\usepackage[landscape]{geometry}
-\usepackage{hyperref}
-\usepackage[T1]{fontenc}
-\hypersetup{colorlinks=true, filecolor=black, linkcolor=black, urlcolor=blue, citecolor=black}
-\graphicspath{{./images/}}
-
-% This sets page margins to .5 inch if using letter paper, and to 1cm
-% if using A4 paper. (This probably isn't strictly necessary.)
-% If using another size paper, use default 1cm margins.
-\ifthenelse{\lengthtest { \paperwidth = 11in}}
- { \geometry{top=.5in,left=.5in,right=.5in,bottom=.5in} }
- {\ifthenelse{ \lengthtest{ \paperwidth = 297mm}}
- {\geometry{top=1cm,left=1cm,right=1cm,bottom=1cm} }
- {\geometry{top=1cm,left=1cm,right=1cm,bottom=1cm} }
- }
-
-% Turn off header and footer
-% \pagestyle{empty}
-
-% Redefine section commands to use less space
-\makeatletter
-\renewcommand{\section}{\@startsection{section}{1}{0mm}%
- {-1ex plus -.5ex minus -.2ex}%
- {0.5ex plus .2ex}%x
- {\normalfont\large\bfseries}}
-\renewcommand{\subsection}{\@startsection{subsection}{2}{0mm}%
- {-1explus -.5ex minus -.2ex}%
- {0.5ex plus .2ex}%
- {\normalfont\normalsize\bfseries}}
-\renewcommand{\subsubsection}{\@startsection{subsubsection}{3}{0mm}%
- {-1ex plus -.5ex minus -.2ex}%
- {1ex plus .2ex}%
- {\normalfont\small\bfseries}}
-\makeatother
-
-% Define BibTeX command
-\def\BibTeX{{\rm B\kern-.05em{\sc i\kern-.025em b}\kern-.08em
- T\kern-.1667em\lower.7ex\hbox{E}\kern-.125emX}}
-
-% Don't print section numbers
-\setcounter{secnumdepth}{0}
-
-
-%\setlength{\parindent}{0pt}
-%\setlength{\parskip}{0pt plus 0.5ex}
-
-\newcommand{\ccode}[1]{
-\begin{alltt}
-#1
-\end{alltt}
-}
-
-% -----------------------------------------------------------------------
-
-\begin{document}
-
-\raggedright
-\footnotesize
-\begin{multicols}{3}
-
-
-% multicol parameters
-% These lengths are set only within the two main columns
-%\setlength{\columnseprule}{0.25pt}
-\setlength{\premulticols}{1pt}
-\setlength{\postmulticols}{1pt}
-\setlength{\multicolsep}{1pt}
-\setlength{\columnsep}{2pt}
-
-\begin{center}
- \Large{\textbf{OpenCV 2.4 Cheat Sheet (C++)}} \\
-\end{center}
-\newlength{\MyLen}
-\settowidth{\MyLen}{\texttt{letterpaper}/\texttt{a4paper} \ }
-
-%\section{Filesystem Concepts}
-%\begin{tabular}{@{}p{\the\MyLen}%
- % @{}p{\linewidth-\the\MyLen}@{}}
-%\texttt{\href{http://www.ros.org/wiki/Packages}{package}} & The lowest level of ROS software organization. \\
-%\texttt{\href{http://www.ros.org/wiki/Manifest}{manifest}} & Description of a ROS package. \\
-%\texttt{\href{http://www.ros.org/wiki/Stack}{stack}} & Collections of ROS packages that form a higher-level library. \\
-%\texttt{\href{http://www.ros.org/wiki/Stack Manifest}{stack manifest}} & Description of a ROS stack.
-%\end{tabular}
-
-\emph{The OpenCV C++ reference manual is here: \url{http://docs.opencv.org}. Use \textbf{Quick Search} to find descriptions of the particular functions and classes}
-
-\section{Key OpenCV Classes}
-\begin{tabular}{@{}p{\the\MyLen}%
- @{}p{\linewidth-\the\MyLen}@{}}
-\texttt{\href{http://docs.opencv.org/modules/core/doc/basic_structures.html\#Point_}{Point\_}} & Template 2D point class \\
-\texttt{\href{http://docs.opencv.org/modules/core/doc/basic_structures.html\#Point3_}{Point3\_}} & Template 3D point class \\
-\texttt{\href{http://docs.opencv.org/modules/core/doc/basic_structures.html\#Size_}{Size\_}} & Template size (width, height) class \\
-\texttt{\href{http://docs.opencv.org/modules/core/doc/basic_structures.html\#Vec}{Vec}} & Template short vector class \\
-\texttt{\href{http://docs.opencv.org/modules/core/doc/basic_structures.html\#Matx}{Matx}} & Template small matrix class \\
-\texttt{\href{http://docs.opencv.org/modules/core/doc/basic_structures.html\#Scalar_}{Scalar}} & 4-element vector \\
-\texttt{\href{http://docs.opencv.org/modules/core/doc/basic_structures.html\#Rect_}{Rect}} & Rectangle \\
-\texttt{\href{http://docs.opencv.org/modules/core/doc/basic_structures.html\#Range}{Range}} & Integer value range \\
-\texttt{\href{http://docs.opencv.org/modules/core/doc/basic_structures.html\#Mat}{Mat}} & 2D or multi-dimensional dense array (can be used to store matrices, images, histograms, feature descriptors, voxel volumes etc.)\\
-\texttt{\href{http://docs.opencv.org/modules/core/doc/basic_structures.html\#sparsemat}{SparseMat}} & Multi-dimensional sparse array \\
-\texttt{\href{http://docs.opencv.org/modules/core/doc/basic_structures.html\#Ptr}{Ptr}} & Template smart pointer class
-\end{tabular}
-
-\section{Matrix Basics}
-\begin{tabbing}
-
-\textbf{Cr}\=\textbf{ea}\=\textbf{te}\={} \textbf{a matrix} \\
-\> \texttt{Mat image(240, 320, CV\_8UC3);} \\
-
-\textbf{[Re]allocate a pre-declared matrix}\\
-\> \texttt{image.\href{http://docs.opencv.org/modules/core/doc/basic_structures.html\#mat-create}{create}(480, 640, CV\_8UC3);}\\
-
-\textbf{Create a matrix initialized with a constant}\\
-\> \texttt{Mat A33(3, 3, CV\_32F, Scalar(5));} \\
-\> \texttt{Mat B33(3, 3, CV\_32F); B33 = Scalar(5);} \\
-\> \texttt{Mat C33 = Mat::ones(3, 3, CV\_32F)*5.;} \\
-\> \texttt{Mat D33 = Mat::zeros(3, 3, CV\_32F) + 5.;} \\
-
-\textbf{Create a matrix initialized with specified values}\\
-\> \texttt{double a = CV\_PI/3;} \\
-\> \texttt{Mat A22 = (Mat\_