mirror of https://github.com/opencv/opencv.git
parent
052d2dc23a
commit
81a5988015
120 changed files with 5422 additions and 4710 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,497 @@ |
||||
import os, sys, glob, re |
||||
|
||||
sys.path.append("../modules/python/src2/") |
||||
sys.path.append("../modules/java/") |
||||
|
||||
import hdr_parser as hp |
||||
import rst_parser as rp |
||||
|
||||
rp.show_warnings = False |
||||
rp.show_errors = False |
||||
|
||||
allmodules = rp.allmodules |
||||
DOCUMENTED_MARKER = "verified" |
||||
|
||||
ERROR_001_NOTACLASS = 1 |
||||
ERROR_002_NOTASTRUCT = 2 |
||||
ERROR_003_INCORRECTBASE = 3 |
||||
ERROR_004_MISSEDNAMESPACE = 4 |
||||
ERROR_005_MISSINGPYFUNC = 5 |
||||
ERROR_006_INVALIDPYOLDDOC = 6 |
||||
ERROR_007_INVALIDPYDOC = 7 |
||||
ERROR_008_CFUNCISNOTGLOBAL = 8 |
||||
ERROR_009_OVERLOADNOTFOUND = 9 |
||||
ERROR_010_UNKNOWNCLASS = 10 |
||||
ERROR_011_UNKNOWNFUNC = 11 |
||||
|
||||
do_python_crosscheck = True |
||||
errors_disabled = [ERROR_004_MISSEDNAMESPACE] |
||||
|
||||
doc_signatures_whitelist = [ |
||||
# templates |
||||
"Matx", "Vec", "SparseMat_", "Scalar_", "Mat_", "Ptr", "Size_", "Point_", "Rect_", "Point3_", |
||||
"DataType", "detail::RotationWarperBase", "flann::Index_", "CalonderDescriptorExtractor", |
||||
"gpu::DevMem2D_", "gpu::PtrStep_", "gpu::PtrElemStep_", |
||||
# black boxes |
||||
"CvArr", "CvFileStorage", |
||||
# other |
||||
"InputArray", "OutputArray", |
||||
] |
||||
|
||||
defines = ["cvGraphEdgeIdx", "cvFree", "CV_Assert", "cvSqrt", "cvGetGraphVtx", "cvGraphVtxIdx", |
||||
"cvCaptureFromFile", "cvCaptureFromCAM", "cvCalcBackProjectPatch", "cvCalcBackProject", |
||||
"cvGetHistValue_1D", "cvGetHistValue_2D", "cvGetHistValue_3D", "cvGetHistValue_nD", |
||||
"cvQueryHistValue_1D", "cvQueryHistValue_2D", "cvQueryHistValue_3D", "cvQueryHistValue_nD", |
||||
# not a real function but behaves as function |
||||
"Mat::size", |
||||
# ugly "virtual" functions from ml module |
||||
"CvStatModel::train", "CvStatModel::predict", |
||||
# TODO: |
||||
"cvExtractSURF" |
||||
] |
||||
|
||||
synonims = { |
||||
"StarDetector" : ["StarFeatureDetector"], |
||||
"MSER" : ["MserFeatureDetector"], |
||||
"GFTTDetector" : ["GoodFeaturesToTrackDetector"], |
||||
"cvCaptureFromFile" : ["cvCreateFileCapture"], |
||||
"cvCaptureFromCAM" : ["cvCreateCameraCapture"], |
||||
"cvCalcArrBackProjectPatch" : ["cvCalcBackProjectPatch"], |
||||
"cvCalcArrBackProject" : ["cvCalcBackProject"], |
||||
"InputArray" : ["_InputArray"], |
||||
"OutputArray" : ["_OutputArray"], |
||||
} |
||||
|
||||
if do_python_crosscheck: |
||||
try: |
||||
import cv2 |
||||
except ImportError: |
||||
print "Could not load cv2" |
||||
do_python_crosscheck = False |
||||
|
||||
def get_cv2_object(name): |
||||
if name.startswith("cv2."): |
||||
name = name[4:] |
||||
if name.startswith("cv."): |
||||
name = name[3:] |
||||
if name == "Algorithm": |
||||
return cv2.Algorithm__create("Feature2D.ORB"), name |
||||
elif name == "FeatureDetector": |
||||
return cv2.FeatureDetector_create("ORB"), name |
||||
elif name == "DescriptorExtractor": |
||||
return cv2.DescriptorExtractor_create("ORB"), name |
||||
elif name == "BackgroundSubtractor": |
||||
return cv2.BackgroundSubtractorMOG(), name |
||||
elif name == "StatModel": |
||||
return cv2.KNearest(), name |
||||
else: |
||||
return getattr(cv2, name)(), name |
||||
|
||||
def compareSignatures(f, s): |
||||
# function names |
||||
if f[0] != s[0]: |
||||
return False, "name mismatch" |
||||
# return type |
||||
stype = (s[1] or "void") |
||||
ftype = f[1] |
||||
stype = re.sub(r"\b(cv|std)::", "", stype) |
||||
if ftype: |
||||
ftype = re.sub(r"\b(cv|std)::", "", ftype) |
||||
if ftype and ftype != stype: |
||||
return False, "return type mismatch" |
||||
if ("\C" in f[2]) ^ ("\C" in s[2]): |
||||
return False, "const qualifier mismatch" |
||||
if ("\S" in f[2]) ^ ("\S" in s[2]): |
||||
return False, "static qualifier mismatch" |
||||
if ("\V" in f[2]) ^ ("\V" in s[2]): |
||||
return False, "virtual qualifier mismatch" |
||||
if ("\A" in f[2]) ^ ("\A" in s[2]): |
||||
return False, "abstract qualifier mismatch" |
||||
if len(f[3]) != len(s[3]): |
||||
return False, "different number of arguments" |
||||
for idx, arg in enumerate(zip(f[3], s[3])): |
||||
farg = arg[0] |
||||
sarg = arg[1] |
||||
ftype = re.sub(r"\b(cv|std)::", "", (farg[0] or "")) |
||||
stype = re.sub(r"\b(cv|std)::", "", (sarg[0] or "")) |
||||
if ftype != stype: |
||||
return False, "type of argument #" + str(idx+1) + " mismatch" |
||||
fname = farg[1] or "arg" + str(idx) |
||||
sname = sarg[1] or "arg" + str(idx) |
||||
if fname != sname: |
||||
return False, "name of argument #" + str(idx+1) + " mismatch" |
||||
fdef = re.sub(r"\b(cv|std)::", "", (farg[2] or "")) |
||||
sdef = re.sub(r"\b(cv|std)::", "", (sarg[2] or "")) |
||||
if fdef != sdef: |
||||
return False, "default value of argument #" + str(idx+1) + " mismatch" |
||||
return True, "match" |
||||
|
||||
def formatSignature(s): |
||||
_str = "" |
||||
if "/V" in s[2]: |
||||
_str += "virtual " |
||||
if "/S" in s[2]: |
||||
_str += "static " |
||||
if s[1]: |
||||
_str += s[1] + " " |
||||
else: |
||||
if not bool(re.match(r"(\w+\.)*(?P<cls>\w+)\.(?P=cls)", s[0])): |
||||
_str += "void " |
||||
if s[0].startswith("cv."): |
||||
_str += s[0][3:].replace(".", "::") |
||||
else: |
||||
_str += s[0].replace(".", "::") |
||||
if len(s[3]) == 0: |
||||
_str += "()" |
||||
else: |
||||
_str += "( " |
||||
for idx, arg in enumerate(s[3]): |
||||
if idx > 0: |
||||
_str += ", " |
||||
argtype = re.sub(r"\bcv::", "", arg[0]) |
||||
bidx = argtype.find('[') |
||||
if bidx < 0: |
||||
_str += argtype + " " |
||||
else: |
||||
_srt += argtype[:bidx] |
||||
if arg[1]: |
||||
_str += arg[1] |
||||
else: |
||||
_str += "arg" + str(idx) |
||||
if bidx >= 0: |
||||
_str += argtype[bidx:] |
||||
if arg[2]: |
||||
_str += "=" + re.sub(r"\bcv::", "", arg[2]) |
||||
_str += " )" |
||||
if "/C" in s[2]: |
||||
_str += " const" |
||||
if "/A" in s[2]: |
||||
_str += " = 0" |
||||
return _str |
||||
|
||||
|
||||
def logerror(code, message, doc = None): |
||||
if code in errors_disabled: |
||||
return |
||||
if doc: |
||||
print doc["file"] + ":" + str(doc["line"]), |
||||
print "error %03d: %s" % (code, message) |
||||
#print |
||||
|
||||
def process_module(module, path): |
||||
hppparser = hp.CppHeaderParser() |
||||
rstparser = rp.RstParser(hppparser) |
||||
|
||||
rstparser.parse(module, path) |
||||
rst = rstparser.definitions |
||||
|
||||
hdrlist = glob.glob(os.path.join(path, "include", "opencv2", module, "*.h*")) |
||||
hdrlist.extend(glob.glob(os.path.join(path, "include", "opencv2", module, "detail", "*.h*"))) |
||||
|
||||
if module == "gpu": |
||||
hdrlist.append(os.path.join(path, "..", "core", "include", "opencv2", "core", "devmem2d.hpp")) |
||||
hdrlist.append(os.path.join(path, "..", "core", "include", "opencv2", "core", "gpumat.hpp")) |
||||
|
||||
decls = [] |
||||
for hname in hdrlist: |
||||
if not "ts_gtest.h" in hname: |
||||
decls += hppparser.parse(hname, wmode=False) |
||||
|
||||
funcs = [] |
||||
# not really needed to hardcode all the namespaces. Normally all they are collected automatically |
||||
namespaces = ['cv', 'cv.gpu', 'cvflann', 'cvflann.anyimpl', 'cvflann.lsh', 'cv.flann', 'cv.linemod', 'cv.detail', 'cvtest', 'perf', 'cv.videostab'] |
||||
classes = [] |
||||
structs = [] |
||||
|
||||
# collect namespaces and classes/structs |
||||
for decl in decls: |
||||
if decl[0].startswith("const"): |
||||
pass |
||||
elif decl[0].startswith("class") or decl[0].startswith("struct"): |
||||
if decl[0][0] == 'c': |
||||
classes.append(decl) |
||||
else: |
||||
structs.append(decl) |
||||
dotIdx = decl[0].rfind('.') |
||||
if dotIdx > 0: |
||||
namespace = decl[0][decl[0].find(' ')+1:dotIdx] |
||||
if not [c for c in classes if c[0].endswith(namespace)] and not [s for s in structs if s[0].endswith(namespace)]: |
||||
if namespace not in namespaces: |
||||
namespaces.append(namespace) |
||||
else: |
||||
funcs.append(decl) |
||||
|
||||
clsnamespaces = [] |
||||
# process classes |
||||
for cl in classes: |
||||
name = cl[0][cl[0].find(' ')+1:] |
||||
if name.find('.') < 0 and not name.startswith("Cv"): |
||||
logerror(ERROR_004_MISSEDNAMESPACE, "class " + name + " from opencv_" + module + " is placed in global namespace but violates C-style naming convention") |
||||
clsnamespaces.append(name) |
||||
if do_python_crosscheck and not name.startswith("cv.") and name.startswith("Cv"): |
||||
clsnamespaces.append("cv." + name[2:]) |
||||
if name.startswith("cv."): |
||||
name = name[3:] |
||||
name = name.replace(".", "::") |
||||
sns = synonims.get(name, []) |
||||
sns.append(name) |
||||
for name in sns: |
||||
doc = rst.get(name) |
||||
if not doc: |
||||
#TODO: class is not documented |
||||
continue |
||||
doc[DOCUMENTED_MARKER] = True |
||||
# verify class marker |
||||
if not doc.get("isclass"): |
||||
logerror(ERROR_001_NOTACLASS, "class " + name + " is not marked as \"class\" in documentation", doc) |
||||
else: |
||||
# verify base |
||||
signature = doc.get("class", "") |
||||
signature = signature.replace(" public ", " ") |
||||
namespaceIdx = signature.rfind("::") |
||||
|
||||
signature = ("class " + signature).strip() |
||||
hdrsignature = ("class " + name + " " + cl[1]).replace(".", "::").replace("cv::","").strip() |
||||
if signature != hdrsignature: |
||||
logerror(ERROR_003_INCORRECTBASE, "invalid base class documentation\ndocumented: " + signature + "\nactual: " + hdrsignature, doc) |
||||
|
||||
# process structs |
||||
for st in structs: |
||||
name = st[0][st[0].find(' ')+1:] |
||||
if name.find('.') < 0 and not name.startswith("Cv"): |
||||
logerror(ERROR_004_MISSEDNAMESPACE, "struct " + name + " from opencv_" + module + " is placed in global namespace but violates C-style naming convention") |
||||
clsnamespaces.append(name) |
||||
if name.startswith("cv."): |
||||
name = name[3:] |
||||
name = name.replace(".", "::") |
||||
doc = rst.get(name) |
||||
if not doc: |
||||
#TODO: struct is not documented |
||||
continue |
||||
doc[DOCUMENTED_MARKER] = True |
||||
# verify struct marker |
||||
if not doc.get("isstruct"): |
||||
logerror(ERROR_002_NOTASTRUCT, "struct " + name + " is not marked as \"struct\" in documentation", doc) |
||||
else: |
||||
# verify base |
||||
signature = doc.get("class", "") |
||||
signature = signature.replace(", public ", " ").replace(" public ", " ") |
||||
signature = signature.replace(", protected ", " ").replace(" protected ", " ") |
||||
signature = signature.replace(", private ", " ").replace(" private ", " ") |
||||
signature = ("struct " + signature).strip() |
||||
hdrsignature = (st[0] + " " + st[1]).replace("struct cv.", "struct ").replace(".", "::").strip() |
||||
if signature != hdrsignature: |
||||
logerror(ERROR_003_INCORRECTBASE, "invalid base struct documentation\ndocumented: " + signature + "\nactual: " + hdrsignature, doc) |
||||
print st, doc |
||||
|
||||
# process functions and methods |
||||
flookup = {} |
||||
for fn in funcs: |
||||
name = fn[0] |
||||
parent = None |
||||
namespace = None |
||||
for cl in clsnamespaces: |
||||
if name.startswith(cl + "."): |
||||
if cl.startswith(parent or ""): |
||||
parent = cl |
||||
if parent: |
||||
name = name[len(parent) + 1:] |
||||
for nm in namespaces: |
||||
if parent.startswith(nm + "."): |
||||
if nm.startswith(namespace or ""): |
||||
namespace = nm |
||||
if namespace: |
||||
parent = parent[len(namespace) + 1:] |
||||
else: |
||||
for nm in namespaces: |
||||
if name.startswith(nm + "."): |
||||
if nm.startswith(namespace or ""): |
||||
namespace = nm |
||||
if namespace: |
||||
name = name[len(namespace) + 1:] |
||||
#print namespace, parent, name, fn[0] |
||||
if not namespace and not parent and not name.startswith("cv") and not name.startswith("CV_"): |
||||
logerror(ERROR_004_MISSEDNAMESPACE, "function " + name + " from opencv_" + module + " is placed in global namespace but violates C-style naming convention") |
||||
else: |
||||
fdescr = (namespace, parent, name, fn) |
||||
flookup_entry = flookup.get(fn[0], []) |
||||
flookup_entry.append(fdescr) |
||||
flookup[fn[0]] = flookup_entry |
||||
|
||||
if do_python_crosscheck: |
||||
for name, doc in rst.iteritems(): |
||||
decls = doc.get("decls") |
||||
if not decls: |
||||
continue |
||||
for signature in decls: |
||||
if signature[0] == "Python1": |
||||
pname = signature[1][:signature[1].find('(')] |
||||
try: |
||||
fn = getattr(cv2.cv, pname[3:]) |
||||
docstr = "cv." + fn.__doc__ |
||||
except AttributeError: |
||||
logerror(ERROR_005_MISSINGPYFUNC, "could not load documented function: cv2." + pname, doc) |
||||
continue |
||||
docstring = docstr |
||||
sign = signature[1] |
||||
signature.append(DOCUMENTED_MARKER) |
||||
# convert old signature to pydoc style |
||||
if docstring.endswith("*"): |
||||
docstring = docstring[:-1] |
||||
s = None |
||||
while s != sign: |
||||
s = sign |
||||
sign = re.sub(r"^(.*\(.*)\(.*?\)(.*\) *->)", "\\1_\\2", sign) |
||||
s = None |
||||
while s != sign: |
||||
s = sign |
||||
sign = re.sub(r"\s*,\s*([^,]+)\s*=\s*[^,]+\s*(( \[.*\])?)\)", " [, \\1\\2])", sign) |
||||
sign = re.sub(r"\(\s*([^,]+)\s*=\s*[^,]+\s*(( \[.*\])?)\)", "([\\1\\2])", sign) |
||||
|
||||
sign = re.sub(r"\)\s*->\s*", ") -> ", sign) |
||||
sign = sign.replace("-> convexHull", "-> CvSeq") |
||||
sign = sign.replace("-> lines", "-> CvSeq") |
||||
sign = sign.replace("-> boundingRects", "-> CvSeq") |
||||
sign = sign.replace("-> contours", "-> CvSeq") |
||||
sign = sign.replace("-> retval", "-> int") |
||||
sign = sign.replace("-> detectedObjects", "-> CvSeqOfCvAvgComp") |
||||
|
||||
def retvalRplace(match): |
||||
m = match.group(1) |
||||
m = m.replace("CvScalar", "scalar") |
||||
m = m.replace("CvMemStorage", "memstorage") |
||||
m = m.replace("ROIplImage", "image") |
||||
m = m.replace("IplImage", "image") |
||||
m = m.replace("ROCvMat", "mat") |
||||
m = m.replace("CvMat", "mat") |
||||
m = m.replace("double", "float") |
||||
m = m.replace("CvSubdiv2DPoint", "point") |
||||
m = m.replace("CvBox2D", "Box2D") |
||||
m = m.replace("IplConvKernel", "kernel") |
||||
m = m.replace("CvHistogram", "hist") |
||||
m = m.replace("CvSize", "width,height") |
||||
m = m.replace("cvmatnd", "matND") |
||||
m = m.replace("CvSeqOfCvConvexityDefect", "convexityDefects") |
||||
mm = m.split(',') |
||||
if len(mm) > 1: |
||||
return "(" + ", ".join(mm) + ")" |
||||
else: |
||||
return m |
||||
|
||||
docstring = re.sub(r"(?<=-> )(.*)$", retvalRplace, docstring) |
||||
docstring = docstring.replace("( [, ", "([") |
||||
|
||||
if sign != docstring: |
||||
logerror(ERROR_006_INVALIDPYOLDDOC, "old-style documentation differs from pydoc\npydoc: " + docstring + "\nfixup: " + sign + "\ncvdoc: " + signature[1], doc) |
||||
elif signature[0] == "Python2": |
||||
pname = signature[1][4:signature[1].find('(')] |
||||
cvname = "cv." + pname |
||||
parent = None |
||||
for cl in clsnamespaces: |
||||
if cvname.startswith(cl + "."): |
||||
if cl.startswith(parent or ""): |
||||
parent = cl |
||||
try: |
||||
if parent: |
||||
instance, clsname = get_cv2_object(parent) |
||||
fn = getattr(instance, cvname[len(parent)+1:]) |
||||
docstr = fn.__doc__ |
||||
docprefix = "cv2." + clsname + "." |
||||
else: |
||||
fn = getattr(cv2, pname) |
||||
docstr = fn.__doc__ |
||||
docprefix = "cv2." |
||||
except AttributeError: |
||||
if parent: |
||||
logerror(ERROR_005_MISSINGPYFUNC, "could not load documented member of " + parent + " class: cv2." + pname, doc) |
||||
else: |
||||
logerror(ERROR_005_MISSINGPYFUNC, "could not load documented function cv2." + pname, doc) |
||||
signature.append(DOCUMENTED_MARKER) # stop subsequent errors |
||||
continue |
||||
docstrings = [docprefix + s.replace("([, ", "([") for s in docstr.split(" or ")] |
||||
if not signature[1] in docstrings: |
||||
pydocs = "\npydoc: ".join(docstrings) |
||||
logerror(ERROR_007_INVALIDPYDOC, "documentation differs from pydoc\npydoc: " + pydocs + "\ncvdoc: " + signature[1], doc) |
||||
signature.append(DOCUMENTED_MARKER) |
||||
|
||||
# verify C/C++ signatures |
||||
for name, doc in rst.iteritems(): |
||||
decls = doc.get("decls") |
||||
if not decls: |
||||
continue |
||||
for signature in decls: |
||||
if signature[0] == "C" or signature[0] == "C++": |
||||
if "template" in (signature[2][1] or ""): |
||||
# TODO find a way to validate templates |
||||
signature.append(DOCUMENTED_MARKER) |
||||
continue |
||||
fd = flookup.get(signature[2][0]) |
||||
if not fd: |
||||
if signature[2][0].startswith("cv."): |
||||
fd = flookup.get(signature[2][0][3:]) |
||||
if not fd: |
||||
continue |
||||
else: |
||||
signature[2][0] = signature[2][0][3:] |
||||
if signature[0] == "C": |
||||
ffd = [f for f in fd if not f[0] and not f[1]] # filter out C++ stuff |
||||
if not ffd: |
||||
if fd[0][1]: |
||||
logerror(ERROR_008_CFUNCISNOTGLOBAL, "function " + fd[0][2] + " is documented as C function but is actually member of " + fd[0][1] + " class", doc) |
||||
elif fd[0][0]: |
||||
logerror(ERROR_008_CFUNCISNOTGLOBAL, "function " + fd[0][2] + " is documented as C function but is actually placed in " + fd[0][0] + " namespace", doc) |
||||
fd = ffd |
||||
error = None |
||||
for f in fd: |
||||
match, error = compareSignatures(signature[2], f[3]) |
||||
if match: |
||||
signature.append(DOCUMENTED_MARKER) |
||||
break |
||||
if signature[-1] != DOCUMENTED_MARKER: |
||||
candidates = "\n\t".join([formatSignature(f[3]) for f in fd]) |
||||
logerror(ERROR_009_OVERLOADNOTFOUND, signature[0] + " function " + signature[2][0].replace(".","::") + " is documented but misses in headers (" + error + ").\nDocumented as:\n\t" + signature[1] + "\nCandidates are:\n\t" + candidates, doc) |
||||
signature.append(DOCUMENTED_MARKER) # to stop subsequent error on this function |
||||
|
||||
# verify that all signatures was found in the library headers |
||||
for name, doc in rst.iteritems(): |
||||
# if doc.get(DOCUMENTED_MARKER, False): |
||||
# continue # this class/struct was found |
||||
if not doc.get(DOCUMENTED_MARKER, False) and (doc.get("isclass", False) or doc.get("isstruct", False)): |
||||
if name in doc_signatures_whitelist: |
||||
continue |
||||
logerror(ERROR_010_UNKNOWNCLASS, "class/struct " + name + " is mentioned in documentation but is not found in OpenCV headers", doc) |
||||
for d in doc.get("decls", []): |
||||
if d[-1] != DOCUMENTED_MARKER: |
||||
if d[0] == "C" or d[0] =="C++" or (do_python_crosscheck and d[0].startswith("Python")): |
||||
if d[0][0] == 'C': |
||||
sname = d[2][0][3:].replace(".", "::") |
||||
if sname in defines: |
||||
#TODO: need to find a way to verify #define's |
||||
continue |
||||
else: |
||||
sname = d[1][:d[1].find("(")] |
||||
prefixes = [x for x in doc_signatures_whitelist if sname.startswith(x)] |
||||
if prefixes: |
||||
# TODO: member of template class |
||||
continue |
||||
logerror(ERROR_011_UNKNOWNFUNC, d[0] + " function " + sname + " is documented but is not found in OpenCV headers. It is documented as:\n\t" + d[1], doc) |
||||
# end of process_module |
||||
|
||||
if __name__ == "__main__": |
||||
if len(sys.argv) < 2: |
||||
print "Usage:\n", os.path.basename(sys.argv[0]), " <module path>" |
||||
exit(0) |
||||
|
||||
modules = sys.argv[1:] |
||||
if modules[0] == "all": |
||||
modules = allmodules |
||||
|
||||
for module in modules: |
||||
selfpath = os.path.dirname(os.path.abspath(sys.argv[0])) |
||||
module_path = os.path.join(selfpath, "..", "modules", module) |
||||
|
||||
if not os.path.isdir(module_path): |
||||
print "Module \"" + module + "\" could not be found." |
||||
exit(1) |
||||
|
||||
process_module(module, module_path) |
@ -0,0 +1,117 @@ |
||||
Stereo Correspondence |
||||
======================================== |
||||
|
||||
.. highlight:: cpp |
||||
|
||||
StereoVar |
||||
---------- |
||||
|
||||
.. ocv:class:: StereoVar |
||||
|
||||
Class for computing stereo correspondence using the variational matching algorithm :: |
||||
|
||||
class StereoVar |
||||
{ |
||||
StereoVar(); |
||||
StereoVar( int levels, double pyrScale, |
||||
int nIt, int minDisp, int maxDisp, |
||||
int poly_n, double poly_sigma, float fi, |
||||
float lambda, int penalization, int cycle, |
||||
int flags); |
||||
virtual ~StereoVar(); |
||||
|
||||
virtual void operator()(InputArray left, InputArray right, OutputArray disp); |
||||
|
||||
int levels; |
||||
double pyrScale; |
||||
int nIt; |
||||
int minDisp; |
||||
int maxDisp; |
||||
int poly_n; |
||||
double poly_sigma; |
||||
float fi; |
||||
float lambda; |
||||
int penalization; |
||||
int cycle; |
||||
int flags; |
||||
|
||||
... |
||||
}; |
||||
|
||||
The class implements the modified S. G. Kosov algorithm [Publication] that differs from the original one as follows: |
||||
|
||||
* The automatic initialization of method's parameters is added. |
||||
|
||||
* The method of Smart Iteration Distribution (SID) is implemented. |
||||
|
||||
* The support of Multi-Level Adaptation Technique (MLAT) is not included. |
||||
|
||||
* The method of dynamic adaptation of method's parameters is not included. |
||||
|
||||
StereoVar::StereoVar |
||||
-------------------------- |
||||
|
||||
.. ocv:function:: StereoVar::StereoVar() |
||||
|
||||
.. ocv:function:: StereoVar::StereoVar( int levels, double pyrScale, int nIt, int minDisp, int maxDisp, int poly_n, double poly_sigma, float fi, float lambda, int penalization, int cycle, int flags ) |
||||
|
||||
The constructor |
||||
|
||||
:param levels: The number of pyramid layers, including the initial image. levels=1 means that no extra layers are created and only the original images are used. This parameter is ignored if flag USE_AUTO_PARAMS is set. |
||||
|
||||
:param pyrScale: Specifies the image scale (<1) to build the pyramids for each image. pyrScale=0.5 means the classical pyramid, where each next layer is twice smaller than the previous. (This parameter is ignored if flag USE_AUTO_PARAMS is set). |
||||
|
||||
:param nIt: The number of iterations the algorithm does at each pyramid level. (If the flag USE_SMART_ID is set, the number of iterations will be redistributed in such a way, that more iterations will be done on more coarser levels.) |
||||
|
||||
:param minDisp: Minimum possible disparity value. Could be negative in case the left and right input images change places. |
||||
|
||||
:param maxDisp: Maximum possible disparity value. |
||||
|
||||
:param poly_n: Size of the pixel neighbourhood used to find polynomial expansion in each pixel. The larger values mean that the image will be approximated with smoother surfaces, yielding more robust algorithm and more blurred motion field. Typically, poly_n = 3, 5 or 7 |
||||
|
||||
:param poly_sigma: Standard deviation of the Gaussian that is used to smooth derivatives that are used as a basis for the polynomial expansion. For poly_n=5 you can set poly_sigma=1.1 , for poly_n=7 a good value would be poly_sigma=1.5 |
||||
|
||||
:param fi: The smoothness parameter, ot the weight coefficient for the smoothness term. |
||||
|
||||
:param lambda: The threshold parameter for edge-preserving smoothness. (This parameter is ignored if PENALIZATION_CHARBONNIER or PENALIZATION_PERONA_MALIK is used.) |
||||
|
||||
:param penalization: Possible values: PENALIZATION_TICHONOV - linear smoothness; PENALIZATION_CHARBONNIER - non-linear edge preserving smoothness; PENALIZATION_PERONA_MALIK - non-linear edge-enhancing smoothness. (This parameter is ignored if flag USE_AUTO_PARAMS is set). |
||||
|
||||
:param cycle: Type of the multigrid cycle. Possible values: CYCLE_O and CYCLE_V for null- and v-cycles respectively. (This parameter is ignored if flag USE_AUTO_PARAMS is set). |
||||
|
||||
:param flags: The operation flags; can be a combination of the following: |
||||
|
||||
* USE_INITIAL_DISPARITY: Use the input flow as the initial flow approximation. |
||||
|
||||
* USE_EQUALIZE_HIST: Use the histogram equalization in the pre-processing phase. |
||||
|
||||
* USE_SMART_ID: Use the smart iteration distribution (SID). |
||||
|
||||
* USE_AUTO_PARAMS: Allow the method to initialize the main parameters. |
||||
|
||||
* USE_MEDIAN_FILTERING: Use the median filer of the solution in the post processing phase. |
||||
|
||||
The first constructor initializes ``StereoVar`` with all the default parameters. So, you only have to set ``StereoVar::maxDisp`` and / or ``StereoVar::minDisp`` at minimum. The second constructor enables you to set each parameter to a custom value. |
||||
|
||||
|
||||
|
||||
StereoVar::operator () |
||||
----------------------- |
||||
|
||||
.. ocv:function:: void StereoVar::operator()( const Mat& left, const Mat& right, Mat& disp ) |
||||
|
||||
Computes disparity using the variational algorithm for a rectified stereo pair. |
||||
|
||||
:param left: Left 8-bit single-channel or 3-channel image. |
||||
|
||||
:param right: Right image of the same size and the same type as the left one. |
||||
|
||||
:param disp: Output disparity map. It is a 8-bit signed single-channel image of the same size as the input image. |
||||
|
||||
The method executes the variational algorithm on a rectified stereo pair. See ``stereo_match.cpp`` OpenCV sample on how to prepare images and call the method. |
||||
|
||||
**Note**: |
||||
|
||||
The method is not constant, so you should not use the same ``StereoVar`` instance from different threads simultaneously. |
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,95 @@ |
||||
Histograms |
||||
========== |
||||
|
||||
.. highlight:: cpp |
||||
|
||||
|
||||
|
||||
CalcPGH |
||||
------- |
||||
Calculates a pair-wise geometrical histogram for a contour. |
||||
|
||||
.. ocv:cfunction:: void cvCalcPGH( const CvSeq* contour, CvHistogram* hist ) |
||||
|
||||
:param contour: Input contour. Currently, only integer point coordinates are allowed. |
||||
|
||||
:param hist: Calculated histogram. It must be two-dimensional. |
||||
|
||||
The function calculates a 2D pair-wise geometrical histogram (PGH), described in [Iivarinen97]_ for the contour. The algorithm considers every pair of contour |
||||
edges. The angle between the edges and the minimum/maximum distances |
||||
are determined for every pair. To do this, each of the edges in turn |
||||
is taken as the base, while the function loops through all the other |
||||
edges. When the base edge and any other edge are considered, the minimum |
||||
and maximum distances from the points on the non-base edge and line of |
||||
the base edge are selected. The angle between the edges defines the row |
||||
of the histogram in which all the bins that correspond to the distance |
||||
between the calculated minimum and maximum distances are incremented |
||||
(that is, the histogram is transposed relatively to the definition in the original paper). The histogram can be used for contour matching. |
||||
|
||||
|
||||
.. [Iivarinen97] Jukka Iivarinen, Markus Peura, Jaakko Srel, and Ari Visa. *Comparison of Combined Shape Descriptors for Irregular Objects*, 8th British Machine Vision Conference, BMVC'97. http://www.cis.hut.fi/research/IA/paper/publications/bmvc97/bmvc97.html |
||||
|
||||
|
||||
QueryHistValue*D |
||||
---------------- |
||||
Queries the value of the histogram bin. |
||||
|
||||
.. ocv:cfunction:: float cvQueryHistValue_1D(CvHistogram hist, int idx0) |
||||
.. ocv:cfunction:: float cvQueryHistValue_2D(CvHistogram hist, int idx0, int idx1) |
||||
.. ocv:cfunction:: float cvQueryHistValue_3D(CvHistogram hist, int idx0, int idx1, int idx2) |
||||
.. ocv:cfunction:: float cvQueryHistValue_nD(CvHistogram hist, const int* idx) |
||||
|
||||
.. ocv:pyoldfunction:: cv.QueryHistValue_1D(hist, idx0) -> float |
||||
.. ocv:pyoldfunction:: cv.QueryHistValue_2D(hist, idx0, idx1) -> float |
||||
.. ocv:pyoldfunction:: cv.QueryHistValue_3D(hist, idx0, idx1, idx2) -> float |
||||
.. ocv:pyoldfunction:: cv.QueryHistValue_nD(hist, idx) -> float |
||||
|
||||
:param hist: Histogram. |
||||
|
||||
:param idx0: 0-th index. |
||||
|
||||
:param idx1: 1-st index. |
||||
|
||||
:param idx2: 2-nd index. |
||||
|
||||
:param idx: Array of indices. |
||||
|
||||
The macros return the value of the specified bin of the 1D, 2D, 3D, or N-D histogram. In case of a sparse histogram, the function returns 0. If the bin is not present in the histogram, no new bin is created. |
||||
|
||||
GetHistValue\_?D |
||||
---------------- |
||||
Returns a pointer to the histogram bin. |
||||
|
||||
.. ocv:cfunction:: float cvGetHistValue_1D(CvHistogram hist, int idx0) |
||||
|
||||
.. ocv:cfunction:: float cvGetHistValue_2D(CvHistogram hist, int idx0, int idx1) |
||||
|
||||
.. ocv:cfunction:: float cvGetHistValue_3D(CvHistogram hist, int idx0, int idx1, int idx2) |
||||
|
||||
.. ocv:cfunction:: float cvGetHistValue_nD(CvHistogram hist, int idx) |
||||
|
||||
:param hist: Histogram. |
||||
|
||||
:param idx0: 0-th index. |
||||
|
||||
:param idx1: 1-st index. |
||||
|
||||
:param idx2: 2-nd index. |
||||
|
||||
:param idx: Array of indices. |
||||
|
||||
:: |
||||
|
||||
#define cvGetHistValue_1D( hist, idx0 ) |
||||
((float*)(cvPtr1D( (hist)->bins, (idx0), 0 )) |
||||
#define cvGetHistValue_2D( hist, idx0, idx1 ) |
||||
((float*)(cvPtr2D( (hist)->bins, (idx0), (idx1), 0 ))) |
||||
#define cvGetHistValue_3D( hist, idx0, idx1, idx2 ) |
||||
((float*)(cvPtr3D( (hist)->bins, (idx0), (idx1), (idx2), 0 ))) |
||||
#define cvGetHistValue_nD( hist, idx ) |
||||
((float*)(cvPtrND( (hist)->bins, (idx), 0 ))) |
||||
|
||||
.. |
||||
|
||||
The macros ``GetHistValue`` return a pointer to the specified bin of the 1D, 2D, 3D, or N-D histogram. In case of a sparse histogram, the function creates a new bin and sets it to 0, unless it exists already. |
||||
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue