]> rtime.felk.cvut.cz Git - opencv.git/commitdiff
added planar object detector (based on cvlab papers)
authorvp153 <vp153@73c94f0f-984f-4a5f-82bc-2d8db8d8ee08>
Tue, 14 Jul 2009 16:11:54 +0000 (16:11 +0000)
committervp153 <vp153@73c94f0f-984f-4a5f-82bc-2d8db8d8ee08>
Tue, 14 Jul 2009 16:11:54 +0000 (16:11 +0000)
git-svn-id: https://code.ros.org/svn/opencv/trunk@1929 73c94f0f-984f-4a5f-82bc-2d8db8d8ee08

opencv/include/opencv/cv.hpp
opencv/include/opencv/cvaux.hpp
opencv/include/opencv/cxcore.hpp
opencv/include/opencv/cxoperations.hpp
opencv/src/cv/cvfeatureselect.cpp
opencv/src/cv/cvfundam.cpp
opencv/src/cv/cvimgwarp.cpp
opencv/src/cvaux/cvplanardetect.cpp [new file with mode: 0644]
opencv/src/cxcore/cxpersistence.cpp

index 532cbc0fd77d114e80d2987fb302f627b8ce8554..2b4863e114a1b47b062f25fb2fe2f53ffdff7226 100644 (file)
-/*M///////////////////////////////////////////////////////////////////////////////////////\r
-//\r
-//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.\r
-//\r
-//  By downloading, copying, installing or using the software you agree to this license.\r
-//  If you do not agree to this license, do not download, install,\r
-//  copy or use the software.\r
-//\r
-//\r
-//                           License Agreement\r
-//                For Open Source Computer Vision Library\r
-//\r
-// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.\r
-// Copyright (C) 2009, Willow Garage Inc., all rights reserved.\r
-// Third party copyrights are property of their respective owners.\r
-//\r
-// Redistribution and use in source and binary forms, with or without modification,\r
-// are permitted provided that the following conditions are met:\r
-//\r
-//   * Redistribution's of source code must retain the above copyright notice,\r
-//     this list of conditions and the following disclaimer.\r
-//\r
-//   * Redistribution's in binary form must reproduce the above copyright notice,\r
-//     this list of conditions and the following disclaimer in the documentation\r
-//     and/or other materials provided with the distribution.\r
-//\r
-//   * The name of the copyright holders may not be used to endorse or promote products\r
-//     derived from this software without specific prior written permission.\r
-//\r
-// This software is provided by the copyright holders and contributors "as is" and\r
-// any express or implied warranties, including, but not limited to, the implied\r
-// warranties of merchantability and fitness for a particular purpose are disclaimed.\r
-// In no event shall the Intel Corporation or contributors be liable for any direct,\r
-// indirect, incidental, special, exemplary, or consequential damages\r
-// (including, but not limited to, procurement of substitute goods or services;\r
-// loss of use, data, or profits; or business interruption) however caused\r
-// and on any theory of liability, whether in contract, strict liability,\r
-// or tort (including negligence or otherwise) arising in any way out of\r
-// the use of this software, even if advised of the possibility of such damage.\r
-//\r
-//M*/\r
-\r
-#ifndef _CV_HPP_\r
-#define _CV_HPP_\r
-\r
-#ifdef __cplusplus\r
-\r
-namespace cv\r
-{\r
-\r
-enum { BORDER_REPLICATE=IPL_BORDER_REPLICATE, BORDER_CONSTANT=IPL_BORDER_CONSTANT,\r
-       BORDER_REFLECT=IPL_BORDER_REFLECT, BORDER_REFLECT_101=IPL_BORDER_REFLECT_101,\r
-       BORDER_REFLECT101=BORDER_REFLECT_101, BORDER_WRAP=IPL_BORDER_WRAP,\r
-       BORDER_TRANSPARENT, BORDER_DEFAULT=BORDER_REFLECT_101, BORDER_ISOLATED=16 };\r
-\r
-CV_EXPORTS int borderInterpolate( int p, int len, int borderType );\r
-\r
-class CV_EXPORTS BaseRowFilter\r
-{\r
-public:\r
-    BaseRowFilter();\r
-    virtual ~BaseRowFilter();\r
-    virtual void operator()(const uchar* src, uchar* dst,\r
-                            int width, int cn) = 0;\r
-    int ksize, anchor;\r
-};\r
-\r
-\r
-class CV_EXPORTS BaseColumnFilter\r
-{\r
-public:\r
-    BaseColumnFilter();\r
-    virtual ~BaseColumnFilter();\r
-    virtual void operator()(const uchar** src, uchar* dst, int dststep,\r
-                            int dstcount, int width) = 0;\r
-    virtual void reset();\r
-    int ksize, anchor;\r
-};\r
-\r
-\r
-class CV_EXPORTS BaseFilter\r
-{\r
-public:\r
-    BaseFilter();\r
-    virtual ~BaseFilter();\r
-    virtual void operator()(const uchar** src, uchar* dst, int dststep,\r
-                            int dstcount, int width, int cn) = 0;\r
-    virtual void reset();\r
-    Size ksize;\r
-    Point anchor;\r
-};\r
-\r
-\r
-class CV_EXPORTS FilterEngine\r
-{\r
-public:\r
-    FilterEngine();\r
-    FilterEngine(const Ptr<BaseFilter>& _filter2D,\r
-                 const Ptr<BaseRowFilter>& _rowFilter,\r
-                 const Ptr<BaseColumnFilter>& _columnFilter,\r
-                 int srcType, int dstType, int bufType,\r
-                 int _rowBorderType=BORDER_REPLICATE,\r
-                 int _columnBorderType=-1,\r
-                 const Scalar& _borderValue=Scalar());\r
-    virtual ~FilterEngine();\r
-    void init(const Ptr<BaseFilter>& _filter2D,\r
-              const Ptr<BaseRowFilter>& _rowFilter,\r
-              const Ptr<BaseColumnFilter>& _columnFilter,\r
-              int srcType, int dstType, int bufType,\r
-              int _rowBorderType=BORDER_REPLICATE, int _columnBorderType=-1,\r
-              const Scalar& _borderValue=Scalar());\r
-    virtual int start(Size wholeSize, Rect roi, int maxBufRows=-1);\r
-    virtual int start(const Mat& src, const Rect& srcRoi=Rect(0,0,-1,-1),\r
-                      bool isolated=false, int maxBufRows=-1);\r
-    virtual int proceed(const uchar* src, int srcStep, int srcCount,\r
-                        uchar* dst, int dstStep);\r
-    virtual void apply( const Mat& src, Mat& dst,\r
-                        const Rect& srcRoi=Rect(0,0,-1,-1),\r
-                        Point dstOfs=Point(0,0),\r
-                        bool isolated=false);\r
-    bool isSeparable() const { return (const BaseFilter*)filter2D == 0; }\r
-    int remainingInputRows() const;\r
-    int remainingOutputRows() const;\r
-    \r
-    int srcType, dstType, bufType;\r
-    Size ksize;\r
-    Point anchor;\r
-    int maxWidth;\r
-    Size wholeSize;\r
-    Rect roi;\r
-    int dx1, dx2;\r
-    int rowBorderType, columnBorderType;\r
-    Vector<int> borderTab;\r
-    int borderElemSize;\r
-    Vector<uchar> ringBuf;\r
-    Vector<uchar> srcRow;\r
-    Vector<uchar> constBorderValue;\r
-    Vector<uchar> constBorderRow;\r
-    int bufStep, startY, startY0, endY, rowCount, dstY;\r
-    Vector<uchar*> rows;\r
-    \r
-    Ptr<BaseFilter> filter2D;\r
-    Ptr<BaseRowFilter> rowFilter;\r
-    Ptr<BaseColumnFilter> columnFilter;\r
-};\r
-\r
-enum { KERNEL_GENERAL=0, KERNEL_SYMMETRICAL=1, KERNEL_ASYMMETRICAL=2,\r
-       KERNEL_SMOOTH=4, KERNEL_INTEGER=8 };\r
-\r
-CV_EXPORTS int getKernelType(const Mat& kernel, Point anchor);\r
-\r
-CV_EXPORTS Ptr<BaseRowFilter> getLinearRowFilter(int srcType, int bufType,\r
-                                            const Mat& kernel, int anchor,\r
-                                            int symmetryType);\r
-\r
-CV_EXPORTS Ptr<BaseColumnFilter> getLinearColumnFilter(int bufType, int dstType,\r
-                                            const Mat& kernel, int anchor,\r
-                                            int symmetryType, double delta=0,\r
-                                            int bits=0);\r
-\r
-CV_EXPORTS Ptr<BaseFilter> getLinearFilter(int srcType, int dstType,\r
-                                           const Mat& kernel,\r
-                                           Point anchor=Point(-1,-1),\r
-                                           double delta=0, int bits=0);\r
-\r
-CV_EXPORTS Ptr<FilterEngine> createSeparableLinearFilter(int srcType, int dstType,\r
-                          const Mat& rowKernel, const Mat& columnKernel,\r
-                          Point _anchor=Point(-1,-1), double delta=0,\r
-                          int _rowBorderType=BORDER_DEFAULT,\r
-                          int _columnBorderType=-1,\r
-                          const Scalar& _borderValue=Scalar());\r
-\r
-CV_EXPORTS Ptr<FilterEngine> createLinearFilter(int srcType, int dstType,\r
-                 const Mat& kernel, Point _anchor=Point(-1,-1),\r
-                 double delta=0, int _rowBorderType=BORDER_DEFAULT,\r
-                 int _columnBorderType=-1, const Scalar& _borderValue=Scalar());\r
-\r
-CV_EXPORTS Mat getGaussianKernel( int ksize, double sigma, int ktype=CV_64F );\r
-\r
-CV_EXPORTS Ptr<FilterEngine> createGaussianFilter( int type, Size ksize,\r
-                                    double sigma1, double sigma2=0,\r
-                                    int borderType=BORDER_DEFAULT);\r
-\r
-CV_EXPORTS void getDerivKernels( Mat& kx, Mat& ky, int dx, int dy, int ksize,\r
-                                 bool normalize=false, int ktype=CV_32F );\r
-\r
-CV_EXPORTS Ptr<FilterEngine> createDerivFilter( int srcType, int dstType,\r
-                                        int dx, int dy, int ksize,\r
-                                        int borderType=BORDER_DEFAULT );\r
-\r
-CV_EXPORTS Ptr<BaseRowFilter> getRowSumFilter(int srcType, int sumType,\r
-                                                 int ksize, int anchor=-1);\r
-CV_EXPORTS Ptr<BaseColumnFilter> getColumnSumFilter(int sumType, int dstType,\r
-                                                       int ksize, int anchor=-1,\r
-                                                       double scale=1);\r
-CV_EXPORTS Ptr<FilterEngine> createBoxFilter( int srcType, int dstType, Size ksize,\r
-                                                 Point anchor=Point(-1,-1),\r
-                                                 bool normalize=true,\r
-                                                 int borderType=BORDER_DEFAULT);\r
-\r
-enum { MORPH_ERODE=0, MORPH_DILATE=1, MORPH_OPEN=2, MORPH_CLOSE=3,\r
-       MORPH_GRADIENT=4, MORPH_TOPHAT=5, MORPH_BLACKHAT=6 };\r
-\r
-CV_EXPORTS Ptr<BaseRowFilter> getMorphologyRowFilter(int op, int type, int ksize, int anchor=-1);\r
-CV_EXPORTS Ptr<BaseColumnFilter> getMorphologyColumnFilter(int op, int type, int ksize, int anchor=-1);\r
-CV_EXPORTS Ptr<BaseFilter> getMorphologyFilter(int op, int type, const Mat& kernel,\r
-                                               Point anchor=Point(-1,-1));\r
-\r
-static inline Scalar morphologyDefaultBorderValue() { return Scalar::all(DBL_MAX); }\r
-\r
-CV_EXPORTS Ptr<FilterEngine> createMorphologyFilter(int op, int type, const Mat& kernel,\r
-                    Point anchor=Point(-1,-1), int _rowBorderType=BORDER_CONSTANT,\r
-                    int _columnBorderType=-1,\r
-                    const Scalar& _borderValue=morphologyDefaultBorderValue());\r
-\r
-enum { MORPH_RECT=0, MORPH_CROSS=1, MORPH_ELLIPSE=2 };\r
-CV_EXPORTS Mat getStructuringElement(int shape, Size ksize, Point anchor=Point(-1,-1));\r
-\r
-CV_EXPORTS void copyMakeBorder( const Mat& src, Mat& dst,\r
-                                int top, int bottom, int left, int right,\r
-                                int borderType );\r
-\r
-CV_EXPORTS void medianBlur( const Mat& src, Mat& dst, int ksize );\r
-CV_EXPORTS void GaussianBlur( const Mat& src, Mat& dst, Size ksize,\r
-                              double sigma1, double sigma2=0,\r
-                              int borderType=BORDER_DEFAULT );\r
-CV_EXPORTS void bilateralFilter( const Mat& src, Mat& dst, int d,\r
-                                 double sigmaColor, double sigmaSpace,\r
-                                 int borderType=BORDER_DEFAULT );\r
-CV_EXPORTS void boxFilter( const Mat& src, Mat& dst, int ddepth,\r
-                           Size ksize, Point anchor=Point(-1,-1),\r
-                           bool normalize=true,\r
-                           int borderType=BORDER_DEFAULT );\r
-static inline void blur( const Mat& src, Mat& dst,\r
-                         Size ksize, Point anchor=Point(-1,-1),\r
-                         int borderType=BORDER_DEFAULT )\r
-{\r
-    boxFilter( src, dst, -1, ksize, anchor, true, borderType );\r
-}\r
-\r
-CV_EXPORTS void filter2D( const Mat& src, Mat& dst, int ddepth,\r
-                          const Mat& kernel, Point anchor=Point(-1,-1),\r
-                          double delta=0, int borderType=BORDER_DEFAULT );\r
-\r
-CV_EXPORTS void sepFilter2D( const Mat& src, Mat& dst, int ddepth,\r
-                             const Mat& kernelX, const Mat& kernelY,\r
-                             Point anchor=Point(-1,-1),\r
-                             double delta=0, int borderType=BORDER_DEFAULT );\r
-\r
-CV_EXPORTS void Sobel( const Mat& src, Mat& dst, int ddepth,\r
-                       int dx, int dy, int ksize=3,\r
-                       double scale=1, double delta=0,\r
-                       int borderType=BORDER_DEFAULT );\r
-\r
-CV_EXPORTS void Scharr( const Mat& src, Mat& dst, int ddepth,\r
-                        int dx, int dy, double scale=1, double delta=0,\r
-                        int borderType=BORDER_DEFAULT );\r
-\r
-CV_EXPORTS void Laplacian( const Mat& src, Mat& dst, int ddepth,\r
-                           int ksize=1, double scale=1, double delta=0,\r
-                           int borderType=BORDER_DEFAULT );\r
-\r
-CV_EXPORTS void Canny( const Mat& image, Mat& edges,\r
-                       double threshold1, double threshold2,\r
-                       int apertureSize=3, bool L2gradient=false );\r
-\r
-CV_EXPORTS void cornerMinEigenVal( const Mat& src, Mat& dst,\r
-                                   int blockSize, int ksize=3,\r
-                                   int borderType=BORDER_DEFAULT );\r
-\r
-CV_EXPORTS void cornerHarris( const Mat& src, Mat& dst, int blockSize,\r
-                              int ksize, double k,\r
-                              int borderType=BORDER_DEFAULT );\r
-\r
-CV_EXPORTS void cornerEigenValsAndVecs( const Mat& src, Mat& dst,\r
-                                        int blockSize, int ksize,\r
-                                        int borderType=BORDER_DEFAULT );\r
-\r
-CV_EXPORTS void preCornerDetect( const Mat& src, Mat& dst, int ksize,\r
-                                 int borderType=BORDER_DEFAULT );\r
-\r
-CV_EXPORTS void cornerSubPix( const Mat& image, Vector<Point2f>& corners,\r
-                              Size winSize, Size zeroZone,\r
-                              TermCriteria criteria );\r
-\r
-CV_EXPORTS void goodFeaturesToTrack( const Mat& image, Vector<Point2f>& corners,\r
-                                     int maxCorners, double qualityLevel, double minDistance,\r
-                                     const Mat& mask=Mat(), int blockSize=3,\r
-                                     bool useHarrisDetector=false, double k=0.04 );\r
-\r
-CV_EXPORTS void HoughLines( Mat& image, Vector<Vec2f>& lines,\r
-                            double rho, double theta, int threshold,\r
-                            double srn=0, double stn=0 );\r
-\r
-CV_EXPORTS void HoughLinesP( Mat& image, Vector<Vec4i>& lines,\r
-                             double rho, double theta, int threshold,\r
-                             double minLineLength=0, double maxLineGap=0 );\r
-\r
-CV_EXPORTS void HoughCircles( Mat& image, Vector<Vec3f>& circles,\r
-                              int method, double dp, double minDist,\r
-                              double param1=100, double param2=100,\r
-                              int minRadius=0, int maxRadius=0 );\r
-\r
-CV_EXPORTS void erode( const Mat& src, Mat& dst, const Mat& kernel,\r
-                       Point anchor=Point(-1,-1), int iterations=1,\r
-                       int borderType=BORDER_CONSTANT,\r
-                       const Scalar& borderValue=morphologyDefaultBorderValue() );\r
-CV_EXPORTS void dilate( const Mat& src, Mat& dst, const Mat& kernel,\r
-                        Point anchor=Point(-1,-1), int iterations=1,\r
-                        int borderType=BORDER_CONSTANT,\r
-                        const Scalar& borderValue=morphologyDefaultBorderValue() );\r
-CV_EXPORTS void morphologyEx( const Mat& src, Mat& dst, int op, const Mat& kernel,\r
-                              Point anchor=Point(-1,-1), int iterations=1,\r
-                              int borderType=BORDER_CONSTANT,\r
-                              const Scalar& borderValue=morphologyDefaultBorderValue() );\r
-\r
-enum { INTER_NEAREST=0, INTER_LINEAR=1, INTER_CUBIC=2, INTER_AREA=3,\r
-       INTER_LANCZOS4=4, INTER_MAX=7, WARP_INVERSE_MAP=16 };\r
-\r
-CV_EXPORTS void resize( const Mat& src, Mat& dst,\r
-                        Size dsize=Size(), double fx=0, double fy=0,\r
-                        int interpolation=INTER_LINEAR );\r
-\r
-CV_EXPORTS void warpAffine( const Mat& src, Mat& dst,\r
-                            const Mat& M, Size dsize,\r
-                            int flags=INTER_LINEAR,\r
-                            int borderMode=BORDER_CONSTANT,\r
-                            const Scalar& borderValue=Scalar());\r
-CV_EXPORTS void warpPerspective( const Mat& src, Mat& dst,\r
-                                 const Mat& M, Size dsize,\r
-                                 int flags=INTER_LINEAR,\r
-                                 int borderMode=BORDER_CONSTANT,\r
-                                 const Scalar& borderValue=Scalar());\r
-\r
-CV_EXPORTS void remap( const Mat& src, Mat& dst, const Mat& map1, const Mat& map2,\r
-                       int interpolation, int borderMode=BORDER_CONSTANT,\r
-                       const Scalar& borderValue=Scalar());\r
-\r
-CV_EXPORTS void convertMaps( const Mat& map1, const Mat& map2, Mat& dstmap1, Mat& dstmap2,\r
-                             int dstmap1type, bool nninterpolation=false );\r
-\r
-CV_EXPORTS Mat getRotationMatrix2D( Point2f center, double angle, double scale );\r
-CV_EXPORTS Mat getPerspectiveTransform( const Point2f src[], const Point2f dst[] );\r
-CV_EXPORTS Mat getAffineTransform( const Point2f src[], const Point2f dst[] );\r
-\r
-CV_EXPORTS void getRectSubPix( const Mat& image, Size patchSize,\r
-                               Point2f center, Mat& patch, int patchType=-1 );\r
-\r
-CV_EXPORTS void integral( const Mat& src, Mat& sum, int sdepth=-1 );\r
-CV_EXPORTS void integral( const Mat& src, Mat& sum, Mat& sqsum, int sdepth=-1 );\r
-CV_EXPORTS void integral( const Mat& src, Mat& sum, Mat& sqsum, Mat& tilted, int sdepth=-1 );\r
-\r
-CV_EXPORTS void accumulate( const Mat& src, Mat& dst, const Mat& mask=Mat() );\r
-CV_EXPORTS void accumulateSquare( const Mat& src, Mat& dst, const Mat& mask=Mat() );\r
-CV_EXPORTS void accumulateProduct( const Mat& src1, const Mat& src2,\r
-                                   Mat& dst, const Mat& mask=Mat() );\r
-CV_EXPORTS void accumulateWeighted( const Mat& src, Mat& dst,\r
-                                    double alpha, const Mat& mask=Mat() );\r
-\r
-enum { THRESH_BINARY=0, THRESH_BINARY_INV=1, THRESH_TRUNC=2, THRESH_TOZERO=3,\r
-       THRESH_TOZERO_INV=4, THRESH_MASK=7, THRESH_OTSU=8 };\r
-\r
-CV_EXPORTS double threshold( const Mat& src, Mat& dst, double thresh, double maxval, int type );\r
-\r
-enum { ADAPTIVE_THRESH_MEAN_C=0, ADAPTIVE_THRESH_GAUSSIAN_C=1 };\r
-\r
-CV_EXPORTS void adaptiveThreshold( const Mat& src, Mat& dst, double maxValue,\r
-                                   int adaptiveMethod, int thresholdType,\r
-                                   int blockSize, double C );\r
-\r
-CV_EXPORTS void pyrDown( const Mat& src, Mat& dst, const Size& dstsize=Size());\r
-CV_EXPORTS void pyrUp( const Mat& src, Mat& dst, const Size& dstsize=Size());\r
-CV_EXPORTS void buildPyramid( const Mat& src, Vector<Mat>& dst, int maxlevel );\r
-\r
-\r
-CV_EXPORTS void undistort( const Mat& src, Mat& dst, const Mat& cameraMatrix,\r
-                           const Mat& distCoeffs, const Mat& newCameraMatrix=Mat() );\r
-CV_EXPORTS void initUndistortRectifyMap( const Mat& cameraMatrix, const Mat& distCoeffs,\r
-                           const Mat& R, const Mat& newCameraMatrix,\r
-                           Size size, int m1type, Mat& map1, Mat& map2 );\r
-CV_EXPORTS Mat getDefaultNewCameraMatrix( const Mat& cameraMatrix, Size imgsize=Size(),\r
-                                          bool centerPrincipalPoint=false );\r
-\r
-enum { OPTFLOW_USE_INITIAL_FLOW=4, OPTFLOW_FARNEBACK_GAUSSIAN=256 };\r
-\r
-CV_EXPORTS void calcOpticalFlowPyrLK( const Mat& prevImg, const Mat& nextImg,\r
-                           const Vector<Point2f>& prevPts,\r
-                           Vector<Point2f>& nextPts,\r
-                           Vector<bool>& status, Vector<float>& err,\r
-                           Size winSize=Size(15,15), int maxLevel=3,\r
-                           TermCriteria criteria=TermCriteria(\r
-                            TermCriteria::COUNT+TermCriteria::EPS,\r
-                            30, 0.01),\r
-                           double derivLambda=0.5,\r
-                           int flags=0 );\r
-\r
-CV_EXPORTS void calcOpticalFlowFarneback( const Mat& prev0, const Mat& next0,\r
-                               Mat& flow0, double pyr_scale, int levels, int winsize,\r
-                               int iterations, int poly_n, double poly_sigma, int flags );\r
-    \r
-    \r
-CV_EXPORTS void calcHist( const Vector<Mat>& images, const Vector<int>& channels,\r
-                          const Mat& mask, MatND& hist, const Vector<int>& histSize,\r
-                          const Vector<Vector<float> >& ranges,\r
-                          bool uniform=true, bool accumulate=false );\r
-\r
-CV_EXPORTS void calcHist( const Vector<Mat>& images, const Vector<int>& channels,\r
-                          const Mat& mask, SparseMat& hist, const Vector<int>& histSize,\r
-                          const Vector<Vector<float> >& ranges,\r
-                          bool uniform=true, bool accumulate=false );\r
-    \r
-CV_EXPORTS void calcBackProject( const Vector<Mat>& images, const Vector<int>& channels,\r
-                                 const MatND& hist, Mat& backProject,\r
-                                 const Vector<Vector<float> >& ranges,\r
-                                 double scale=1, bool uniform=true );\r
-    \r
-CV_EXPORTS void calcBackProject( const Vector<Mat>& images, const Vector<int>& channels,\r
-                                 const SparseMat& hist, Mat& backProject,\r
-                                 const Vector<Vector<float> >& ranges,\r
-                                 double scale=1, bool uniform=true );\r
-\r
-CV_EXPORTS double compareHist( const MatND& H1, const MatND& H2, int method );\r
-\r
-CV_EXPORTS double compareHist( const SparseMat& H1, const SparseMat& H2, int method );\r
-\r
-CV_EXPORTS void equalizeHist( const Mat& src, Mat& dst );\r
-\r
-CV_EXPORTS void watershed( const Mat& image, Mat& markers );\r
-\r
-enum { INPAINT_NS=CV_INPAINT_NS, INPAINT_TELEA=CV_INPAINT_TELEA };\r
-\r
-CV_EXPORTS void inpaint( const Mat& src, const Mat& inpaintMask,\r
-                         Mat& dst, double inpaintRange, int flags );\r
-\r
-CV_EXPORTS void distanceTransform( const Mat& src, Mat& dst, Mat& labels,\r
-                                   int distanceType, int maskSize );\r
-\r
-CV_EXPORTS void distanceTransform( const Mat& src, Mat& dst,\r
-                                   int distanceType, int maskSize );\r
-\r
-enum { FLOODFILL_FIXED_RANGE = 1 << 16,\r
-       FLOODFILL_MASK_ONLY = 1 << 17 };\r
-\r
-CV_EXPORTS int floodFill( Mat& image,\r
-                          Point seedPoint, Scalar newVal, Rect* rect=0,\r
-                          Scalar loDiff=Scalar(), Scalar upDiff=Scalar(),\r
-                          int flags=4 );\r
-\r
-CV_EXPORTS int floodFill( Mat& image, Mat& mask,\r
-                          Point seedPoint, Scalar newVal, Rect* rect=0,\r
-                          Scalar loDiff=Scalar(), Scalar upDiff=Scalar(),\r
-                          int flags=4 );\r
-\r
-CV_EXPORTS void cvtColor( const Mat& src, Mat& dst, int code, int dstCn=0 );\r
-\r
-class CV_EXPORTS Moments\r
-{\r
-public:\r
-    Moments();\r
-    Moments(double m00, double m10, double m01, double m20, double m11,\r
-            double m02, double m30, double m21, double m12, double m03 );\r
-    Moments( const CvMoments& moments );\r
-    operator CvMoments() const;\r
-    \r
-    double  m00, m10, m01, m20, m11, m02, m30, m21, m12, m03; // spatial moments\r
-    double  mu20, mu11, mu02, mu30, mu21, mu12, mu03; // central moments\r
-    double  nu20, nu11, nu02, nu30, nu21, nu12, nu03; // central normalized moments\r
-};\r
-\r
-CV_EXPORTS Moments moments( const Mat& image, bool binaryImage=false );\r
-\r
-CV_EXPORTS void HuMoments( const Moments& moments, double hu[7] );\r
-\r
-enum { TM_SQDIFF=CV_TM_SQDIFF, TM_SQDIFF_NORMED=CV_TM_SQDIFF_NORMED,\r
-       TM_CCORR=CV_TM_CCORR, TM_CCORR_NORMED=CV_TM_CCORR_NORMED,\r
-       TM_CCOEFF=CV_TM_CCOEFF, TM_CCOEFF_NORMED=CV_TM_CCOEFF_NORMED };\r
-\r
-CV_EXPORTS void matchTemplate( const Mat& image, const Mat& templ, Mat& result, int method );\r
-\r
-enum { RETR_EXTERNAL=CV_RETR_EXTERNAL, RETR_LIST=CV_RETR_LIST,\r
-       RETR_CCOMP=CV_RETR_CCOMP, RETR_TREE=CV_RETR_TREE };\r
-\r
-enum { CHAIN_APPROX_NONE=CV_CHAIN_APPROX_NONE,\r
-       CHAIN_APPROX_SIMPLE=CV_CHAIN_APPROX_SIMPLE,\r
-       CHAIN_APPROX_TC89_L1=CV_CHAIN_APPROX_TC89_L1,\r
-       CHAIN_APPROX_TC89_KCOS=CV_CHAIN_APPROX_TC89_KCOS };\r
-\r
-CV_EXPORTS Vector<Vector<Point> >\r
-    findContours( const Mat& image, Vector<Vec4i>& hierarchy,\r
-                  int mode, int method, Point offset=Point());\r
-\r
-CV_EXPORTS Vector<Vector<Point> >\r
-    findContours( const Mat& image, int mode, int method, Point offset=Point());\r
-\r
-CV_EXPORTS void\r
-    drawContours( Mat& image, const Vector<Vector<Point> >& contours,\r
-                  const Scalar& color, int thickness=1,\r
-                  int lineType=8, const Vector<Vec4i>& hierarchy=Vector<Vec4i>(),\r
-                  int maxLevel=1, Point offset=Point() );\r
-\r
-CV_EXPORTS void approxPolyDP( const Vector<Point>& curve,\r
-                              Vector<Point>& approxCurve,\r
-                              double epsilon, bool closed );\r
-CV_EXPORTS void approxPolyDP( const Vector<Point2f>& curve,\r
-                              Vector<Point2f>& approxCurve,\r
-                              double epsilon, bool closed );\r
-\r
-CV_EXPORTS double arcLength( const Vector<Point>& curve, bool closed );\r
-CV_EXPORTS double arcLength( const Vector<Point2f>& curve, bool closed );\r
-\r
-CV_EXPORTS Rect boundingRect( const Vector<Point>& points );\r
-CV_EXPORTS Rect boundingRect( const Vector<Point2f>& points );\r
-\r
-CV_EXPORTS double contourArea( const Vector<Point>& contour );\r
-CV_EXPORTS double contourArea( const Vector<Point2f>& contour );\r
-\r
-CV_EXPORTS RotatedRect minAreaRect( const Vector<Point>& points );\r
-CV_EXPORTS RotatedRect minAreaRect( const Vector<Point2f>& points );\r
-\r
-CV_EXPORTS void minEnclosingCircle( const Vector<Point>& points,\r
-                                    Point2f center, float& radius );\r
-CV_EXPORTS void minEnclosingCircle( const Vector<Point2f>& points,\r
-                                    Point2f center, float& radius );\r
-\r
-CV_EXPORTS Moments moments( const Vector<Point>& points );\r
-CV_EXPORTS Moments moments( const Vector<Point2f>& points );\r
-\r
-CV_EXPORTS double matchShapes( const Vector<Point2f>& contour1,\r
-                               const Vector<Point2f>& contour2,\r
-                               int method, double parameter );\r
-CV_EXPORTS double matchShapes( const Vector<Point>& contour1,\r
-                               const Vector<Point>& contour2,\r
-                               int method, double parameter );\r
-\r
-CV_EXPORTS void convexHull( const Vector<Point>& points,\r
-                            Vector<int>& hull, bool clockwise=false );\r
-CV_EXPORTS void convexHull( const Vector<Point>& points,\r
-                            Vector<Point>& hull, bool clockwise=false );\r
-CV_EXPORTS void convexHull( const Vector<Point2f>& points,\r
-                            Vector<int>& hull, bool clockwise=false );\r
-CV_EXPORTS void convexHull( const Vector<Point2f>& points,\r
-                            Vector<Point2f>& hull, bool clockwise=false );\r
-\r
-CV_EXPORTS bool isContourConvex( const Vector<Point>& contour );\r
-CV_EXPORTS bool isContourConvex( const Vector<Point2f>& contour );\r
-\r
-CV_EXPORTS RotatedRect fitEllipse( const Vector<Point>& points );\r
-CV_EXPORTS RotatedRect fitEllipse( const Vector<Point2f>& points );\r
-\r
-CV_EXPORTS Vec4f fitLine( const Vector<Point> points, int distType,\r
-                          double param, double reps, double aeps );\r
-CV_EXPORTS Vec4f fitLine( const Vector<Point2f> points, int distType,\r
-                          double param, double reps, double aeps );\r
-CV_EXPORTS Vec6f fitLine( const Vector<Point3f> points, int distType,\r
-                          double param, double reps, double aeps );\r
-\r
-CV_EXPORTS double pointPolygonTest( const Vector<Point>& contour,\r
-                                    Point2f pt, bool measureDist );\r
-CV_EXPORTS double pointPolygonTest( const Vector<Point2f>& contour,\r
-                                    Point2f pt, bool measureDist );\r
-\r
-CV_EXPORTS Mat estimateRigidTransform( const Vector<Point2f>& A,\r
-                                       const Vector<Point2f>& B,\r
-                                       bool fullAffine );\r
-\r
-CV_EXPORTS void updateMotionHistory( const Mat& silhouette, Mat& mhi,\r
-                                     double timestamp, double duration );\r
-\r
-CV_EXPORTS void calcMotionGradient( const Mat& mhi, Mat& mask,\r
-                                    Mat& orientation,\r
-                                    double delta1, double delta2,\r
-                                    int apertureSize=3 );\r
-\r
-CV_EXPORTS double calcGlobalOrientation( const Mat& orientation, const Mat& mask,\r
-                                         const Mat& mhi, double timestamp,\r
-                                         double duration );\r
-// TODO: need good API for cvSegmentMotion\r
-\r
-CV_EXPORTS RotatedRect CAMShift( const Mat& probImage, Rect& window,\r
-                                 TermCriteria criteria );\r
-\r
-CV_EXPORTS int meanShift( const Mat& probImage, Rect& window,\r
-                          TermCriteria criteria );\r
-\r
-class CV_EXPORTS KalmanFilter\r
-{\r
-public:\r
-    KalmanFilter();\r
-    KalmanFilter(int dynamParams, int measureParams, int controlParams=0);\r
-    void init(int dynamParams, int measureParams, int controlParams=0);\r
-\r
-    const Mat& predict(const Mat& control=Mat());\r
-    const Mat& correct(const Mat& measurement);\r
-\r
-    Mat statePre;           // predicted state (x'(k)):\r
-                            //    x(k)=A*x(k-1)+B*u(k)\r
-    Mat statePost;          // corrected state (x(k)):\r
-                            //    x(k)=x'(k)+K(k)*(z(k)-H*x'(k))\r
-    Mat transitionMatrix;   // state transition matrix (A)\r
-    Mat controlMatrix;      // control matrix (B)\r
-                            //   (it is not used if there is no control)\r
-    Mat measurementMatrix;  // measurement matrix (H)\r
-    Mat processNoiseCov;    // process noise covariance matrix (Q)\r
-    Mat measurementNoiseCov;// measurement noise covariance matrix (R)\r
-    Mat errorCovPre;        // priori error estimate covariance matrix (P'(k)):\r
-                            //    P'(k)=A*P(k-1)*At + Q)*/\r
-    Mat gain;               // Kalman gain matrix (K(k)):\r
-                            //    K(k)=P'(k)*Ht*inv(H*P'(k)*Ht+R)\r
-    Mat errorCovPost;       // posteriori error estimate covariance matrix (P(k)):\r
-                            //    P(k)=(I-K(k)*H)*P'(k)\r
-    Mat temp1;              // temporary matrices\r
-    Mat temp2;\r
-    Mat temp3;\r
-    Mat temp4;\r
-    Mat temp5;\r
-};\r
-\r
-\r
-///////////////////////////// Object Detection ////////////////////////////\r
-\r
-template<> inline void Ptr<CvHaarClassifierCascade>::delete_obj()\r
-{ cvReleaseHaarClassifierCascade(&obj); }\r
-\r
-class CV_EXPORTS HaarClassifierCascade\r
-{\r
-public:\r
-    enum { DO_CANNY_PRUNING = CV_HAAR_DO_CANNY_PRUNING,\r
-           SCALE_IMAGE = CV_HAAR_SCALE_IMAGE,\r
-           FIND_BIGGEST_OBJECT = CV_HAAR_FIND_BIGGEST_OBJECT,\r
-           DO_ROUGH_SEARCH = CV_HAAR_DO_ROUGH_SEARCH };\r
-    \r
-    HaarClassifierCascade();\r
-    HaarClassifierCascade(const String& filename);\r
-    bool load(const String& filename);\r
-\r
-    void detectMultiScale( const Mat& image,\r
-                           Vector<Rect>& objects,\r
-                           double scaleFactor=1.1,\r
-                           int minNeighbors=3, int flags=0,\r
-                           Size minSize=Size());\r
-\r
-    int runAt(Point pt, int startStage=0, int nstages=0) const;\r
-\r
-    void setImages( const Mat& sum, const Mat& sqsum,\r
-                    const Mat& tiltedSum, double scale );\r
-    \r
-    Ptr<CvHaarClassifierCascade> cascade;\r
-};\r
-\r
-CV_EXPORTS void undistortPoints( const Vector<Point2f>& src, Vector<Point2f>& dst,\r
-                                 const Mat& cameraMatrix, const Mat& distCoeffs,\r
-                                 const Mat& R=Mat(), const Mat& P=Mat());\r
-\r
-CV_EXPORTS Mat Rodrigues(const Mat& src);\r
-CV_EXPORTS Mat Rodrigues(const Mat& src, Mat& jacobian);\r
-\r
-enum { LMEDS=4, RANSAC=8 };\r
-\r
-CV_EXPORTS Mat findHomography( const Vector<Point2f>& srcPoints,\r
-                               const Vector<Point2f>& dstPoints,\r
-                               Vector<bool>& mask, int method=0,\r
-                               double ransacReprojThreshold=0 );\r
-\r
-CV_EXPORTS Mat findHomography( const Vector<Point2f>& srcPoints,\r
-                               const Vector<Point2f>& dstPoints,\r
-                               int method=0, double ransacReprojThreshold=0 );\r
-\r
-/* Computes RQ decomposition for 3x3 matrices */\r
-CV_EXPORTS void RQDecomp3x3( const Mat& M, Mat& R, Mat& Q );\r
-CV_EXPORTS Vec3d RQDecomp3x3( const Mat& M, Mat& R, Mat& Q,\r
-                              Mat& Qx, Mat& Qy, Mat& Qz );\r
-\r
-CV_EXPORTS void decomposeProjectionMatrix( const Mat& projMatrix, Mat& cameraMatrix,\r
-                                           Mat& rotMatrix, Mat& transVect );\r
-CV_EXPORTS void decomposeProjectionMatrix( const Mat& projMatrix, Mat& cameraMatrix,\r
-                                           Mat& rotMatrix, Mat& transVect,\r
-                                           Mat& rotMatrixX, Mat& rotMatrixY,\r
-                                           Mat& rotMatrixZ, Vec3d& eulerAngles );\r
-\r
-CV_EXPORTS void matMulDeriv( const Mat& A, const Mat& B, Mat& dABdA, Mat& dABdB );\r
-\r
-CV_EXPORTS void composeRT( const Mat& rvec1, const Mat& tvec1,\r
-                           const Mat& rvec2, const Mat& tvec2,\r
-                           Mat& rvec3, Mat& tvec3 );\r
-\r
-CV_EXPORTS void composeRT( const Mat& rvec1, const Mat& tvec1,\r
-                           const Mat& rvec2, const Mat& tvec2,\r
-                           Mat& rvec3, Mat& tvec3,\r
-                           Mat& dr3dr1, Mat& dr3dt1,\r
-                           Mat& dr3dr2, Mat& dr3dt2,\r
-                           Mat& dt3dr1, Mat& dt3dt1,\r
-                           Mat& dt3dr2, Mat& dt3dt2 );\r
-\r
-CV_EXPORTS void projectPoints( const Vector<Point3f>& objectPoints,\r
-                               const Mat& rvec, const Mat& tvec,\r
-                               const Mat& cameraMatrix,\r
-                               const Mat& distCoeffs,\r
-                               Vector<Point2f>& imagePoints );\r
-\r
-CV_EXPORTS void projectPoints( const Vector<Point3f>& objectPoints,\r
-                               const Mat& rvec, const Mat& tvec,\r
-                               const Mat& cameraMatrix,\r
-                               const Mat& distCoeffs,\r
-                               Vector<Point2f>& imagePoints,\r
-                               Mat& dpdrot, Mat& dpdt, Mat& dpdf,\r
-                               Mat& dpdc, Mat& dpddist,\r
-                               double aspectRatio=0 );\r
-\r
-CV_EXPORTS void solvePnP( const Vector<Point3f>& objectPoints,\r
-                          const Vector<Point2f>& imagePoints,\r
-                          const Mat& cameraMatrix,\r
-                          const Mat& distCoeffs,\r
-                          Mat& rvec, Mat& tvec,\r
-                          bool useExtrinsicGuess=false );\r
-\r
-CV_EXPORTS Mat initCameraMatrix2D( const Vector<Vector<Point3f> >& objectPoints,\r
-                                   const Vector<Vector<Point2f> >& imagePoints,\r
-                                   Size imageSize, double aspectRatio=1. );\r
-\r
-enum { CALIB_CB_ADAPTIVE_THRESH = CV_CALIB_CB_ADAPTIVE_THRESH,\r
-       CALIB_CB_NORMALIZE_IMAGE = CV_CALIB_CB_NORMALIZE_IMAGE,\r
-       CALIB_CB_FILTER_QUADS = CV_CALIB_CB_FILTER_QUADS };\r
-\r
-CV_EXPORTS bool findChessboardCorners( const Mat& image, Size patternSize,\r
-                                       Vector<Point2f>& corners,\r
-                                       int flags=CV_CALIB_CB_ADAPTIVE_THRESH+\r
-                                            CV_CALIB_CB_NORMALIZE_IMAGE );\r
-\r
-CV_EXPORTS void drawChessboardCorners( Mat& image, Size patternSize,\r
-                                       const Vector<Point2f>& corners,\r
-                                       bool patternWasFound );\r
-\r
-enum\r
-{\r
-    CALIB_USE_INTRINSIC_GUESS = CV_CALIB_USE_INTRINSIC_GUESS,\r
-    CALIB_FIX_ASPECT_RATIO = CV_CALIB_FIX_ASPECT_RATIO,\r
-    CALIB_FIX_PRINCIPAL_POINT = CV_CALIB_FIX_PRINCIPAL_POINT,\r
-    CALIB_ZERO_TANGENT_DIST = CV_CALIB_ZERO_TANGENT_DIST,\r
-    CALIB_FIX_FOCAL_LENGTH = CV_CALIB_FIX_FOCAL_LENGTH,\r
-    CALIB_FIX_K1 = CV_CALIB_FIX_K1,\r
-    CALIB_FIX_K2 = CV_CALIB_FIX_K2,\r
-    CALIB_FIX_K3 = CV_CALIB_FIX_K3,\r
-    // only for stereo\r
-    CALIB_FIX_INTRINSIC = CV_CALIB_FIX_INTRINSIC,\r
-    CALIB_SAME_FOCAL_LENGTH = CV_CALIB_SAME_FOCAL_LENGTH,\r
-    // for stereo rectification\r
-    CALIB_ZERO_DISPARITY = CV_CALIB_ZERO_DISPARITY\r
-};\r
-\r
-CV_EXPORTS void calibrateCamera( const Vector<Vector<Point3f> >& objectPoints,\r
-                                 const Vector<Vector<Point2f> >& imagePoints,\r
-                                 Size imageSize,\r
-                                 Mat& cameraMatrix, Mat& distCoeffs,\r
-                                 Vector<Mat>& rvecs, Vector<Mat>& tvecs,\r
-                                 int flags=0 );\r
-\r
-CV_EXPORTS void calibrationMatrixValues( const Mat& cameraMatrix,\r
-                                Size imageSize,\r
-                                double apertureWidth,\r
-                                double apertureHeight,\r
-                                double& fovx,\r
-                                double& fovy,\r
-                                double& focalLength,\r
-                                Point2d& principalPoint,\r
-                                double& aspectRatio );\r
-\r
-CV_EXPORTS void stereoCalibrate( const Vector<Vector<Point3f> >& objectPoints,\r
-                                 const Vector<Vector<Point2f> >& imagePoints1,\r
-                                 const Vector<Vector<Point2f> >& imagePoints2,\r
-                                 Mat& cameraMatrix1, Mat& distCoeffs1,\r
-                                 Mat& cameraMatrix2, Mat& distCoeffs2,\r
-                                 Size imageSize, Mat& R, Mat& T,\r
-                                 Mat& E, Mat& F,\r
-                                 TermCriteria criteria = TermCriteria(TermCriteria::COUNT+\r
-                                    TermCriteria::EPS, 30, 1e-6),\r
-                                 int flags=CALIB_FIX_INTRINSIC );\r
-\r
-CV_EXPORTS void stereoRectify( const Mat& cameraMatrix1, const Mat& distCoeffs1,\r
-                               const Mat& cameraMatrix2, const Mat& distCoeffs2,\r
-                               Size imageSize, const Mat& R, const Mat& T,\r
-                               Mat& R1, Mat& R2, Mat& P1, Mat& P2, Mat& Q,\r
-                               int flags=CALIB_ZERO_DISPARITY );\r
-\r
-CV_EXPORTS bool stereoRectifyUncalibrated( const Vector<Point2f>& points1,\r
-                                           const Vector<Point2f>& points2,\r
-                                           const Mat& F, Size imgSize,\r
-                                           Mat& H1, Mat& H2,\r
-                                           double threshold=5 );\r
-\r
-CV_EXPORTS void convertPointsHomogeneous( const Vector<Point2f>& src,\r
-                                          Vector<Point3f>& dst );\r
-CV_EXPORTS void convertPointsHomogeneous( const Vector<Point3f>& src,\r
-                                          Vector<Point2f>& dst );\r
-\r
-enum\r
-{ \r
-    FM_7POINT = CV_FM_7POINT,\r
-    FM_8POINT = CV_FM_8POINT,\r
-    FM_LMEDS = CV_FM_LMEDS,\r
-    FM_RANSAC = CV_FM_RANSAC\r
-};\r
-\r
-CV_EXPORTS Mat findFundamentalMat( const Vector<Point2f>& points1,\r
-                                   const Vector<Point2f>& points2,\r
-                                   Vector<bool>& mask,\r
-                                   int method=FM_RANSAC,\r
-                                   double param1=3., double param2=0.99 );\r
-\r
-CV_EXPORTS Mat findFundamentalMat( const Vector<Point2f>& points1,\r
-                                   const Vector<Point2f>& points2,\r
-                                   int method=FM_RANSAC,\r
-                                   double param1=3., double param2=0.99 );\r
-\r
-CV_EXPORTS void computeCorrespondEpilines( const Vector<Point2f>& points1,\r
-                                           int whichImage, const Mat& F,\r
-                                           Vector<Vec3f>& lines );\r
-\r
-template<> inline void Ptr<CvStereoBMState>::delete_obj()\r
-{ cvReleaseStereoBMState(&obj); }\r
-\r
-// Block matching stereo correspondence algorithm\r
-class CV_EXPORTS StereoBM\r
-{\r
-    enum { NORMALIZED_RESPONSE = CV_STEREO_BM_NORMALIZED_RESPONSE,\r
-        BASIC_PRESET=CV_STEREO_BM_BASIC,\r
-        FISH_EYE_PRESET=CV_STEREO_BM_FISH_EYE,\r
-        NARROW_PRESET=CV_STEREO_BM_NARROW };\r
-    \r
-    StereoBM();\r
-    StereoBM(int preset, int ndisparities=0, int SADWindowSize=21);\r
-    void init(int preset, int ndisparities=0, int SADWindowSize=21);\r
-    void operator()( const Mat& left, const Mat& right, Mat& disparity );\r
-\r
-    Ptr<CvStereoBMState> state;\r
-};\r
-\r
-CV_EXPORTS void reprojectImageTo3D( const Mat& disparity,\r
-                                    Mat& _3dImage, const Mat& Q,\r
-                                    bool handleMissingValues=false );\r
-\r
-class CV_EXPORTS SURFKeypoint : public CvSURFPoint\r
-{\r
-public:\r
-    SURFKeypoint() { pt=Point2f(); laplacian=size=0; dir=hessian=0; }\r
-    SURFKeypoint(Point2f _pt, int _laplacian, int _size, float _dir=0.f, float _hessian=0.f)\r
-    { pt = _pt; laplacian = _laplacian; size = _size; dir = _dir; hessian = _hessian; }\r
-};\r
-\r
-class CV_EXPORTS SURF : public CvSURFParams\r
-{\r
-public:\r
-    SURF();\r
-    SURF(double _hessianThreshold, bool _extended=false);\r
-\r
-    int descriptorSize() const;\r
-    void operator()(const Mat& img, const Mat& mask,\r
-                    Vector<SURFKeypoint>& keypoints) const;\r
-    void operator()(const Mat& img, const Mat& mask,\r
-                    Vector<SURFKeypoint>& keypoints,\r
-                    Vector<float>& descriptors,\r
-                    bool useProvidedKeypoints=false) const;\r
-};\r
-\r
-\r
-class CV_EXPORTS MSER : public CvMSERParams\r
-{\r
-public:\r
-    MSER();\r
-    MSER( int _delta, int _min_area, int _max_area,\r
-          float _max_variation, float _min_diversity,\r
-          int _max_evolution, double _area_threshold,\r
-          double _min_margin, int _edge_blur_size );\r
-    Vector<Vector<Point> > operator()(Mat& image, const Mat& mask) const;\r
-};\r
-\r
-class CV_EXPORTS StarKeypoint : public CvStarKeypoint\r
-{\r
-public:\r
-    StarKeypoint() { pt = Point(); size = 0; response = 0.f; }\r
-    StarKeypoint(Point _pt, int _size, float _response)\r
-    {\r
-        pt = _pt; size = _size; response = _response;\r
-    }\r
-};\r
-\r
-class CV_EXPORTS StarDetector : CvStarDetectorParams\r
-{\r
-public:\r
-    StarDetector();\r
-    StarDetector(int _maxSize, int _responseThreshold,\r
-                 int _lineThresholdProjected,\r
-                 int _lineThresholdBinarized,\r
-                 int _suppressNonmaxSize);\r
-\r
-    void operator()(const Mat& image, Vector<StarKeypoint>& keypoints) const;\r
-};\r
-\r
-}\r
-\r
-//////////////////////////////////////////////////////////////////////////////////////////\r
-\r
-class CV_EXPORTS CvLevMarq\r
-{\r
-public:\r
-    CvLevMarq();\r
-    CvLevMarq( int nparams, int nerrs, CvTermCriteria criteria=\r
-        cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER,30,DBL_EPSILON),\r
-        bool completeSymmFlag=false );\r
-    ~CvLevMarq();\r
-    void init( int nparams, int nerrs, CvTermCriteria criteria=\r
-        cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER,30,DBL_EPSILON),\r
-        bool completeSymmFlag=false );\r
-    bool update( const CvMat*& param, CvMat*& J, CvMat*& err );\r
-    bool updateAlt( const CvMat*& param, CvMat*& JtJ, CvMat*& JtErr, double*& errNorm );\r
-\r
-    void clear();\r
-    void step();\r
-    enum { DONE=0, STARTED=1, CALC_J=2, CHECK_ERR=3 };\r
-\r
-    CvMat* mask;\r
-    CvMat* prevParam;\r
-    CvMat* param;\r
-    CvMat* J;\r
-    CvMat* err;\r
-    CvMat* JtJ;\r
-    CvMat* JtJN;\r
-    CvMat* JtErr;\r
-    CvMat* JtJV;\r
-    CvMat* JtJW;\r
-    double prevErrNorm, errNorm;\r
-    int lambdaLg10;\r
-    CvTermCriteria criteria;\r
-    int state;\r
-    int iters;\r
-    bool completeSymmFlag;\r
-};\r
-\r
-\r
-// 2009-01-12, Xavier Delacour <xavier.delacour@gmail.com>\r
-\r
-struct lsh_hash {\r
-  int h1, h2;\r
-};\r
-\r
-struct CvLSHOperations\r
-{\r
-  virtual ~CvLSHOperations() {}\r
-\r
-  virtual int vector_add(const void* data) = 0;\r
-  virtual void vector_remove(int i) = 0;\r
-  virtual const void* vector_lookup(int i) = 0;\r
-  virtual void vector_reserve(int n) = 0;\r
-  virtual unsigned int vector_count() = 0;\r
-\r
-  virtual void hash_insert(lsh_hash h, int l, int i) = 0;\r
-  virtual void hash_remove(lsh_hash h, int l, int i) = 0;\r
-  virtual int hash_lookup(lsh_hash h, int l, int* ret_i, int ret_i_max) = 0;\r
-};\r
-\r
-\r
-#endif /* __cplusplus */\r
-\r
-#endif /* _CV_HPP_ */\r
-\r
-/* End of file. */\r
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+//  By downloading, copying, installing or using the software you agree to this license.
+//  If you do not agree to this license, do not download, install,
+//  copy or use the software.
+//
+//
+//                           License Agreement
+//                For Open Source Computer Vision Library
+//
+// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
+// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+//   * Redistribution's of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//
+//   * Redistribution's in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//
+//   * The name of the copyright holders may not be used to endorse or promote products
+//     derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+#ifndef _CV_HPP_
+#define _CV_HPP_
+
+#ifdef __cplusplus
+
+namespace cv
+{
+
+enum { BORDER_REPLICATE=IPL_BORDER_REPLICATE, BORDER_CONSTANT=IPL_BORDER_CONSTANT,
+       BORDER_REFLECT=IPL_BORDER_REFLECT, BORDER_REFLECT_101=IPL_BORDER_REFLECT_101,
+       BORDER_REFLECT101=BORDER_REFLECT_101, BORDER_WRAP=IPL_BORDER_WRAP,
+       BORDER_TRANSPARENT, BORDER_DEFAULT=BORDER_REFLECT_101, BORDER_ISOLATED=16 };
+
+CV_EXPORTS int borderInterpolate( int p, int len, int borderType );
+
+class CV_EXPORTS BaseRowFilter
+{
+public:
+    BaseRowFilter();
+    virtual ~BaseRowFilter();
+    virtual void operator()(const uchar* src, uchar* dst,
+                            int width, int cn) = 0;
+    int ksize, anchor;
+};
+
+
+class CV_EXPORTS BaseColumnFilter
+{
+public:
+    BaseColumnFilter();
+    virtual ~BaseColumnFilter();
+    virtual void operator()(const uchar** src, uchar* dst, int dststep,
+                            int dstcount, int width) = 0;
+    virtual void reset();
+    int ksize, anchor;
+};
+
+
+class CV_EXPORTS BaseFilter
+{
+public:
+    BaseFilter();
+    virtual ~BaseFilter();
+    virtual void operator()(const uchar** src, uchar* dst, int dststep,
+                            int dstcount, int width, int cn) = 0;
+    virtual void reset();
+    Size ksize;
+    Point anchor;
+};
+
+
+class CV_EXPORTS FilterEngine
+{
+public:
+    FilterEngine();
+    FilterEngine(const Ptr<BaseFilter>& _filter2D,
+                 const Ptr<BaseRowFilter>& _rowFilter,
+                 const Ptr<BaseColumnFilter>& _columnFilter,
+                 int srcType, int dstType, int bufType,
+                 int _rowBorderType=BORDER_REPLICATE,
+                 int _columnBorderType=-1,
+                 const Scalar& _borderValue=Scalar());
+    virtual ~FilterEngine();
+    void init(const Ptr<BaseFilter>& _filter2D,
+              const Ptr<BaseRowFilter>& _rowFilter,
+              const Ptr<BaseColumnFilter>& _columnFilter,
+              int srcType, int dstType, int bufType,
+              int _rowBorderType=BORDER_REPLICATE, int _columnBorderType=-1,
+              const Scalar& _borderValue=Scalar());
+    virtual int start(Size wholeSize, Rect roi, int maxBufRows=-1);
+    virtual int start(const Mat& src, const Rect& srcRoi=Rect(0,0,-1,-1),
+                      bool isolated=false, int maxBufRows=-1);
+    virtual int proceed(const uchar* src, int srcStep, int srcCount,
+                        uchar* dst, int dstStep);
+    virtual void apply( const Mat& src, Mat& dst,
+                        const Rect& srcRoi=Rect(0,0,-1,-1),
+                        Point dstOfs=Point(0,0),
+                        bool isolated=false);
+    bool isSeparable() const { return (const BaseFilter*)filter2D == 0; }
+    int remainingInputRows() const;
+    int remainingOutputRows() const;
+    
+    int srcType, dstType, bufType;
+    Size ksize;
+    Point anchor;
+    int maxWidth;
+    Size wholeSize;
+    Rect roi;
+    int dx1, dx2;
+    int rowBorderType, columnBorderType;
+    Vector<int> borderTab;
+    int borderElemSize;
+    Vector<uchar> ringBuf;
+    Vector<uchar> srcRow;
+    Vector<uchar> constBorderValue;
+    Vector<uchar> constBorderRow;
+    int bufStep, startY, startY0, endY, rowCount, dstY;
+    Vector<uchar*> rows;
+    
+    Ptr<BaseFilter> filter2D;
+    Ptr<BaseRowFilter> rowFilter;
+    Ptr<BaseColumnFilter> columnFilter;
+};
+
+enum { KERNEL_GENERAL=0, KERNEL_SYMMETRICAL=1, KERNEL_ASYMMETRICAL=2,
+       KERNEL_SMOOTH=4, KERNEL_INTEGER=8 };
+
+CV_EXPORTS int getKernelType(const Mat& kernel, Point anchor);
+
+CV_EXPORTS Ptr<BaseRowFilter> getLinearRowFilter(int srcType, int bufType,
+                                            const Mat& kernel, int anchor,
+                                            int symmetryType);
+
+CV_EXPORTS Ptr<BaseColumnFilter> getLinearColumnFilter(int bufType, int dstType,
+                                            const Mat& kernel, int anchor,
+                                            int symmetryType, double delta=0,
+                                            int bits=0);
+
+CV_EXPORTS Ptr<BaseFilter> getLinearFilter(int srcType, int dstType,
+                                           const Mat& kernel,
+                                           Point anchor=Point(-1,-1),
+                                           double delta=0, int bits=0);
+
+CV_EXPORTS Ptr<FilterEngine> createSeparableLinearFilter(int srcType, int dstType,
+                          const Mat& rowKernel, const Mat& columnKernel,
+                          Point _anchor=Point(-1,-1), double delta=0,
+                          int _rowBorderType=BORDER_DEFAULT,
+                          int _columnBorderType=-1,
+                          const Scalar& _borderValue=Scalar());
+
+CV_EXPORTS Ptr<FilterEngine> createLinearFilter(int srcType, int dstType,
+                 const Mat& kernel, Point _anchor=Point(-1,-1),
+                 double delta=0, int _rowBorderType=BORDER_DEFAULT,
+                 int _columnBorderType=-1, const Scalar& _borderValue=Scalar());
+
+CV_EXPORTS Mat getGaussianKernel( int ksize, double sigma, int ktype=CV_64F );
+
+CV_EXPORTS Ptr<FilterEngine> createGaussianFilter( int type, Size ksize,
+                                    double sigma1, double sigma2=0,
+                                    int borderType=BORDER_DEFAULT);
+
+CV_EXPORTS void getDerivKernels( Mat& kx, Mat& ky, int dx, int dy, int ksize,
+                                 bool normalize=false, int ktype=CV_32F );
+
+CV_EXPORTS Ptr<FilterEngine> createDerivFilter( int srcType, int dstType,
+                                        int dx, int dy, int ksize,
+                                        int borderType=BORDER_DEFAULT );
+
+CV_EXPORTS Ptr<BaseRowFilter> getRowSumFilter(int srcType, int sumType,
+                                                 int ksize, int anchor=-1);
+CV_EXPORTS Ptr<BaseColumnFilter> getColumnSumFilter(int sumType, int dstType,
+                                                       int ksize, int anchor=-1,
+                                                       double scale=1);
+CV_EXPORTS Ptr<FilterEngine> createBoxFilter( int srcType, int dstType, Size ksize,
+                                                 Point anchor=Point(-1,-1),
+                                                 bool normalize=true,
+                                                 int borderType=BORDER_DEFAULT);
+
+enum { MORPH_ERODE=0, MORPH_DILATE=1, MORPH_OPEN=2, MORPH_CLOSE=3,
+       MORPH_GRADIENT=4, MORPH_TOPHAT=5, MORPH_BLACKHAT=6 };
+
+CV_EXPORTS Ptr<BaseRowFilter> getMorphologyRowFilter(int op, int type, int ksize, int anchor=-1);
+CV_EXPORTS Ptr<BaseColumnFilter> getMorphologyColumnFilter(int op, int type, int ksize, int anchor=-1);
+CV_EXPORTS Ptr<BaseFilter> getMorphologyFilter(int op, int type, const Mat& kernel,
+                                               Point anchor=Point(-1,-1));
+
+static inline Scalar morphologyDefaultBorderValue() { return Scalar::all(DBL_MAX); }
+
+CV_EXPORTS Ptr<FilterEngine> createMorphologyFilter(int op, int type, const Mat& kernel,
+                    Point anchor=Point(-1,-1), int _rowBorderType=BORDER_CONSTANT,
+                    int _columnBorderType=-1,
+                    const Scalar& _borderValue=morphologyDefaultBorderValue());
+
+enum { MORPH_RECT=0, MORPH_CROSS=1, MORPH_ELLIPSE=2 };
+CV_EXPORTS Mat getStructuringElement(int shape, Size ksize, Point anchor=Point(-1,-1));
+
+CV_EXPORTS void copyMakeBorder( const Mat& src, Mat& dst,
+                                int top, int bottom, int left, int right,
+                                int borderType );
+
+CV_EXPORTS void medianBlur( const Mat& src, Mat& dst, int ksize );
+CV_EXPORTS void GaussianBlur( const Mat& src, Mat& dst, Size ksize,
+                              double sigma1, double sigma2=0,
+                              int borderType=BORDER_DEFAULT );
+CV_EXPORTS void bilateralFilter( const Mat& src, Mat& dst, int d,
+                                 double sigmaColor, double sigmaSpace,
+                                 int borderType=BORDER_DEFAULT );
+CV_EXPORTS void boxFilter( const Mat& src, Mat& dst, int ddepth,
+                           Size ksize, Point anchor=Point(-1,-1),
+                           bool normalize=true,
+                           int borderType=BORDER_DEFAULT );
+static inline void blur( const Mat& src, Mat& dst,
+                         Size ksize, Point anchor=Point(-1,-1),
+                         int borderType=BORDER_DEFAULT )
+{
+    boxFilter( src, dst, -1, ksize, anchor, true, borderType );
+}
+
+CV_EXPORTS void filter2D( const Mat& src, Mat& dst, int ddepth,
+                          const Mat& kernel, Point anchor=Point(-1,-1),
+                          double delta=0, int borderType=BORDER_DEFAULT );
+
+CV_EXPORTS void sepFilter2D( const Mat& src, Mat& dst, int ddepth,
+                             const Mat& kernelX, const Mat& kernelY,
+                             Point anchor=Point(-1,-1),
+                             double delta=0, int borderType=BORDER_DEFAULT );
+
+CV_EXPORTS void Sobel( const Mat& src, Mat& dst, int ddepth,
+                       int dx, int dy, int ksize=3,
+                       double scale=1, double delta=0,
+                       int borderType=BORDER_DEFAULT );
+
+CV_EXPORTS void Scharr( const Mat& src, Mat& dst, int ddepth,
+                        int dx, int dy, double scale=1, double delta=0,
+                        int borderType=BORDER_DEFAULT );
+
+CV_EXPORTS void Laplacian( const Mat& src, Mat& dst, int ddepth,
+                           int ksize=1, double scale=1, double delta=0,
+                           int borderType=BORDER_DEFAULT );
+
+CV_EXPORTS void Canny( const Mat& image, Mat& edges,
+                       double threshold1, double threshold2,
+                       int apertureSize=3, bool L2gradient=false );
+
+CV_EXPORTS void cornerMinEigenVal( const Mat& src, Mat& dst,
+                                   int blockSize, int ksize=3,
+                                   int borderType=BORDER_DEFAULT );
+
+CV_EXPORTS void cornerHarris( const Mat& src, Mat& dst, int blockSize,
+                              int ksize, double k,
+                              int borderType=BORDER_DEFAULT );
+
+CV_EXPORTS void cornerEigenValsAndVecs( const Mat& src, Mat& dst,
+                                        int blockSize, int ksize,
+                                        int borderType=BORDER_DEFAULT );
+
+CV_EXPORTS void preCornerDetect( const Mat& src, Mat& dst, int ksize,
+                                 int borderType=BORDER_DEFAULT );
+
+CV_EXPORTS void cornerSubPix( const Mat& image, Vector<Point2f>& corners,
+                              Size winSize, Size zeroZone,
+                              TermCriteria criteria );
+
+CV_EXPORTS void goodFeaturesToTrack( const Mat& image, Vector<Point2f>& corners,
+                                     int maxCorners, double qualityLevel, double minDistance,
+                                     const Mat& mask=Mat(), int blockSize=3,
+                                     bool useHarrisDetector=false, double k=0.04 );
+
+CV_EXPORTS void HoughLines( Mat& image, Vector<Vec2f>& lines,
+                            double rho, double theta, int threshold,
+                            double srn=0, double stn=0 );
+
+CV_EXPORTS void HoughLinesP( Mat& image, Vector<Vec4i>& lines,
+                             double rho, double theta, int threshold,
+                             double minLineLength=0, double maxLineGap=0 );
+
+CV_EXPORTS void HoughCircles( Mat& image, Vector<Vec3f>& circles,
+                              int method, double dp, double minDist,
+                              double param1=100, double param2=100,
+                              int minRadius=0, int maxRadius=0 );
+
+CV_EXPORTS void erode( const Mat& src, Mat& dst, const Mat& kernel,
+                       Point anchor=Point(-1,-1), int iterations=1,
+                       int borderType=BORDER_CONSTANT,
+                       const Scalar& borderValue=morphologyDefaultBorderValue() );
+CV_EXPORTS void dilate( const Mat& src, Mat& dst, const Mat& kernel,
+                        Point anchor=Point(-1,-1), int iterations=1,
+                        int borderType=BORDER_CONSTANT,
+                        const Scalar& borderValue=morphologyDefaultBorderValue() );
+CV_EXPORTS void morphologyEx( const Mat& src, Mat& dst, int op, const Mat& kernel,
+                              Point anchor=Point(-1,-1), int iterations=1,
+                              int borderType=BORDER_CONSTANT,
+                              const Scalar& borderValue=morphologyDefaultBorderValue() );
+
+enum { INTER_NEAREST=0, INTER_LINEAR=1, INTER_CUBIC=2, INTER_AREA=3,
+       INTER_LANCZOS4=4, INTER_MAX=7, WARP_INVERSE_MAP=16 };
+
+CV_EXPORTS void resize( const Mat& src, Mat& dst,
+                        Size dsize=Size(), double fx=0, double fy=0,
+                        int interpolation=INTER_LINEAR );
+
+CV_EXPORTS void warpAffine( const Mat& src, Mat& dst,
+                            const Mat& M, Size dsize,
+                            int flags=INTER_LINEAR,
+                            int borderMode=BORDER_CONSTANT,
+                            const Scalar& borderValue=Scalar());
+CV_EXPORTS void warpPerspective( const Mat& src, Mat& dst,
+                                 const Mat& M, Size dsize,
+                                 int flags=INTER_LINEAR,
+                                 int borderMode=BORDER_CONSTANT,
+                                 const Scalar& borderValue=Scalar());
+
+CV_EXPORTS void remap( const Mat& src, Mat& dst, const Mat& map1, const Mat& map2,
+                       int interpolation, int borderMode=BORDER_CONSTANT,
+                       const Scalar& borderValue=Scalar());
+
+CV_EXPORTS void convertMaps( const Mat& map1, const Mat& map2, Mat& dstmap1, Mat& dstmap2,
+                             int dstmap1type, bool nninterpolation=false );
+
+CV_EXPORTS Mat getRotationMatrix2D( Point2f center, double angle, double scale );
+CV_EXPORTS Mat getPerspectiveTransform( const Point2f src[], const Point2f dst[] );
+CV_EXPORTS Mat getAffineTransform( const Point2f src[], const Point2f dst[] );
+CV_EXPORTS void invertAffineTransform(const Mat& M, Mat& iM);
+
+CV_EXPORTS void getRectSubPix( const Mat& image, Size patchSize,
+                               Point2f center, Mat& patch, int patchType=-1 );
+
+CV_EXPORTS void integral( const Mat& src, Mat& sum, int sdepth=-1 );
+CV_EXPORTS void integral( const Mat& src, Mat& sum, Mat& sqsum, int sdepth=-1 );
+CV_EXPORTS void integral( const Mat& src, Mat& sum, Mat& sqsum, Mat& tilted, int sdepth=-1 );
+
+CV_EXPORTS void accumulate( const Mat& src, Mat& dst, const Mat& mask=Mat() );
+CV_EXPORTS void accumulateSquare( const Mat& src, Mat& dst, const Mat& mask=Mat() );
+CV_EXPORTS void accumulateProduct( const Mat& src1, const Mat& src2,
+                                   Mat& dst, const Mat& mask=Mat() );
+CV_EXPORTS void accumulateWeighted( const Mat& src, Mat& dst,
+                                    double alpha, const Mat& mask=Mat() );
+
+enum { THRESH_BINARY=0, THRESH_BINARY_INV=1, THRESH_TRUNC=2, THRESH_TOZERO=3,
+       THRESH_TOZERO_INV=4, THRESH_MASK=7, THRESH_OTSU=8 };
+
+CV_EXPORTS double threshold( const Mat& src, Mat& dst, double thresh, double maxval, int type );
+
+enum { ADAPTIVE_THRESH_MEAN_C=0, ADAPTIVE_THRESH_GAUSSIAN_C=1 };
+
+CV_EXPORTS void adaptiveThreshold( const Mat& src, Mat& dst, double maxValue,
+                                   int adaptiveMethod, int thresholdType,
+                                   int blockSize, double C );
+
+CV_EXPORTS void pyrDown( const Mat& src, Mat& dst, const Size& dstsize=Size());
+CV_EXPORTS void pyrUp( const Mat& src, Mat& dst, const Size& dstsize=Size());
+CV_EXPORTS void buildPyramid( const Mat& src, Vector<Mat>& dst, int maxlevel );
+
+
+CV_EXPORTS void undistort( const Mat& src, Mat& dst, const Mat& cameraMatrix,
+                           const Mat& distCoeffs, const Mat& newCameraMatrix=Mat() );
+CV_EXPORTS void initUndistortRectifyMap( const Mat& cameraMatrix, const Mat& distCoeffs,
+                           const Mat& R, const Mat& newCameraMatrix,
+                           Size size, int m1type, Mat& map1, Mat& map2 );
+CV_EXPORTS Mat getDefaultNewCameraMatrix( const Mat& cameraMatrix, Size imgsize=Size(),
+                                          bool centerPrincipalPoint=false );
+
+enum { OPTFLOW_USE_INITIAL_FLOW=4, OPTFLOW_FARNEBACK_GAUSSIAN=256 };
+
+CV_EXPORTS void calcOpticalFlowPyrLK( const Mat& prevImg, const Mat& nextImg,
+                           const Vector<Point2f>& prevPts,
+                           Vector<Point2f>& nextPts,
+                           Vector<bool>& status, Vector<float>& err,
+                           Size winSize=Size(15,15), int maxLevel=3,
+                           TermCriteria criteria=TermCriteria(
+                            TermCriteria::COUNT+TermCriteria::EPS,
+                            30, 0.01),
+                           double derivLambda=0.5,
+                           int flags=0 );
+
+CV_EXPORTS void calcOpticalFlowFarneback( const Mat& prev0, const Mat& next0,
+                               Mat& flow0, double pyr_scale, int levels, int winsize,
+                               int iterations, int poly_n, double poly_sigma, int flags );
+    
+    
+CV_EXPORTS void calcHist( const Vector<Mat>& images, const Vector<int>& channels,
+                          const Mat& mask, MatND& hist, const Vector<int>& histSize,
+                          const Vector<Vector<float> >& ranges,
+                          bool uniform=true, bool accumulate=false );
+
+CV_EXPORTS void calcHist( const Vector<Mat>& images, const Vector<int>& channels,
+                          const Mat& mask, SparseMat& hist, const Vector<int>& histSize,
+                          const Vector<Vector<float> >& ranges,
+                          bool uniform=true, bool accumulate=false );
+    
+CV_EXPORTS void calcBackProject( const Vector<Mat>& images, const Vector<int>& channels,
+                                 const MatND& hist, Mat& backProject,
+                                 const Vector<Vector<float> >& ranges,
+                                 double scale=1, bool uniform=true );
+    
+CV_EXPORTS void calcBackProject( const Vector<Mat>& images, const Vector<int>& channels,
+                                 const SparseMat& hist, Mat& backProject,
+                                 const Vector<Vector<float> >& ranges,
+                                 double scale=1, bool uniform=true );
+
+CV_EXPORTS double compareHist( const MatND& H1, const MatND& H2, int method );
+
+CV_EXPORTS double compareHist( const SparseMat& H1, const SparseMat& H2, int method );
+
+CV_EXPORTS void equalizeHist( const Mat& src, Mat& dst );
+
+CV_EXPORTS void watershed( const Mat& image, Mat& markers );
+
+enum { INPAINT_NS=CV_INPAINT_NS, INPAINT_TELEA=CV_INPAINT_TELEA };
+
+CV_EXPORTS void inpaint( const Mat& src, const Mat& inpaintMask,
+                         Mat& dst, double inpaintRange, int flags );
+
+CV_EXPORTS void distanceTransform( const Mat& src, Mat& dst, Mat& labels,
+                                   int distanceType, int maskSize );
+
+CV_EXPORTS void distanceTransform( const Mat& src, Mat& dst,
+                                   int distanceType, int maskSize );
+
+enum { FLOODFILL_FIXED_RANGE = 1 << 16,
+       FLOODFILL_MASK_ONLY = 1 << 17 };
+
+CV_EXPORTS int floodFill( Mat& image,
+                          Point seedPoint, Scalar newVal, Rect* rect=0,
+                          Scalar loDiff=Scalar(), Scalar upDiff=Scalar(),
+                          int flags=4 );
+
+CV_EXPORTS int floodFill( Mat& image, Mat& mask,
+                          Point seedPoint, Scalar newVal, Rect* rect=0,
+                          Scalar loDiff=Scalar(), Scalar upDiff=Scalar(),
+                          int flags=4 );
+
+CV_EXPORTS void cvtColor( const Mat& src, Mat& dst, int code, int dstCn=0 );
+
+class CV_EXPORTS Moments
+{
+public:
+    Moments();
+    Moments(double m00, double m10, double m01, double m20, double m11,
+            double m02, double m30, double m21, double m12, double m03 );
+    Moments( const CvMoments& moments );
+    operator CvMoments() const;
+    
+    double  m00, m10, m01, m20, m11, m02, m30, m21, m12, m03; // spatial moments
+    double  mu20, mu11, mu02, mu30, mu21, mu12, mu03; // central moments
+    double  nu20, nu11, nu02, nu30, nu21, nu12, nu03; // central normalized moments
+};
+
+CV_EXPORTS Moments moments( const Mat& image, bool binaryImage=false );
+
+CV_EXPORTS void HuMoments( const Moments& moments, double hu[7] );
+
+enum { TM_SQDIFF=CV_TM_SQDIFF, TM_SQDIFF_NORMED=CV_TM_SQDIFF_NORMED,
+       TM_CCORR=CV_TM_CCORR, TM_CCORR_NORMED=CV_TM_CCORR_NORMED,
+       TM_CCOEFF=CV_TM_CCOEFF, TM_CCOEFF_NORMED=CV_TM_CCOEFF_NORMED };
+
+CV_EXPORTS void matchTemplate( const Mat& image, const Mat& templ, Mat& result, int method );
+
+enum { RETR_EXTERNAL=CV_RETR_EXTERNAL, RETR_LIST=CV_RETR_LIST,
+       RETR_CCOMP=CV_RETR_CCOMP, RETR_TREE=CV_RETR_TREE };
+
+enum { CHAIN_APPROX_NONE=CV_CHAIN_APPROX_NONE,
+       CHAIN_APPROX_SIMPLE=CV_CHAIN_APPROX_SIMPLE,
+       CHAIN_APPROX_TC89_L1=CV_CHAIN_APPROX_TC89_L1,
+       CHAIN_APPROX_TC89_KCOS=CV_CHAIN_APPROX_TC89_KCOS };
+
+CV_EXPORTS Vector<Vector<Point> >
+    findContours( const Mat& image, Vector<Vec4i>& hierarchy,
+                  int mode, int method, Point offset=Point());
+
+CV_EXPORTS Vector<Vector<Point> >
+    findContours( const Mat& image, int mode, int method, Point offset=Point());
+
+CV_EXPORTS void
+    drawContours( Mat& image, const Vector<Vector<Point> >& contours,
+                  const Scalar& color, int thickness=1,
+                  int lineType=8, const Vector<Vec4i>& hierarchy=Vector<Vec4i>(),
+                  int maxLevel=1, Point offset=Point() );
+
+CV_EXPORTS void approxPolyDP( const Vector<Point>& curve,
+                              Vector<Point>& approxCurve,
+                              double epsilon, bool closed );
+CV_EXPORTS void approxPolyDP( const Vector<Point2f>& curve,
+                              Vector<Point2f>& approxCurve,
+                              double epsilon, bool closed );
+
+CV_EXPORTS double arcLength( const Vector<Point>& curve, bool closed );
+CV_EXPORTS double arcLength( const Vector<Point2f>& curve, bool closed );
+
+CV_EXPORTS Rect boundingRect( const Vector<Point>& points );
+CV_EXPORTS Rect boundingRect( const Vector<Point2f>& points );
+
+CV_EXPORTS double contourArea( const Vector<Point>& contour );
+CV_EXPORTS double contourArea( const Vector<Point2f>& contour );
+
+CV_EXPORTS RotatedRect minAreaRect( const Vector<Point>& points );
+CV_EXPORTS RotatedRect minAreaRect( const Vector<Point2f>& points );
+
+CV_EXPORTS void minEnclosingCircle( const Vector<Point>& points,
+                                    Point2f center, float& radius );
+CV_EXPORTS void minEnclosingCircle( const Vector<Point2f>& points,
+                                    Point2f center, float& radius );
+
+CV_EXPORTS Moments moments( const Vector<Point>& points );
+CV_EXPORTS Moments moments( const Vector<Point2f>& points );
+
+CV_EXPORTS double matchShapes( const Vector<Point2f>& contour1,
+                               const Vector<Point2f>& contour2,
+                               int method, double parameter );
+CV_EXPORTS double matchShapes( const Vector<Point>& contour1,
+                               const Vector<Point>& contour2,
+                               int method, double parameter );
+
+CV_EXPORTS void convexHull( const Vector<Point>& points,
+                            Vector<int>& hull, bool clockwise=false );
+CV_EXPORTS void convexHull( const Vector<Point>& points,
+                            Vector<Point>& hull, bool clockwise=false );
+CV_EXPORTS void convexHull( const Vector<Point2f>& points,
+                            Vector<int>& hull, bool clockwise=false );
+CV_EXPORTS void convexHull( const Vector<Point2f>& points,
+                            Vector<Point2f>& hull, bool clockwise=false );
+
+CV_EXPORTS bool isContourConvex( const Vector<Point>& contour );
+CV_EXPORTS bool isContourConvex( const Vector<Point2f>& contour );
+
+CV_EXPORTS RotatedRect fitEllipse( const Vector<Point>& points );
+CV_EXPORTS RotatedRect fitEllipse( const Vector<Point2f>& points );
+
+CV_EXPORTS Vec4f fitLine( const Vector<Point> points, int distType,
+                          double param, double reps, double aeps );
+CV_EXPORTS Vec4f fitLine( const Vector<Point2f> points, int distType,
+                          double param, double reps, double aeps );
+CV_EXPORTS Vec6f fitLine( const Vector<Point3f> points, int distType,
+                          double param, double reps, double aeps );
+
+CV_EXPORTS double pointPolygonTest( const Vector<Point>& contour,
+                                    Point2f pt, bool measureDist );
+CV_EXPORTS double pointPolygonTest( const Vector<Point2f>& contour,
+                                    Point2f pt, bool measureDist );
+
+CV_EXPORTS Mat estimateRigidTransform( const Vector<Point2f>& A,
+                                       const Vector<Point2f>& B,
+                                       bool fullAffine );
+
+CV_EXPORTS void updateMotionHistory( const Mat& silhouette, Mat& mhi,
+                                     double timestamp, double duration );
+
+CV_EXPORTS void calcMotionGradient( const Mat& mhi, Mat& mask,
+                                    Mat& orientation,
+                                    double delta1, double delta2,
+                                    int apertureSize=3 );
+
+CV_EXPORTS double calcGlobalOrientation( const Mat& orientation, const Mat& mask,
+                                         const Mat& mhi, double timestamp,
+                                         double duration );
+// TODO: need good API for cvSegmentMotion
+
+CV_EXPORTS RotatedRect CAMShift( const Mat& probImage, Rect& window,
+                                 TermCriteria criteria );
+
+CV_EXPORTS int meanShift( const Mat& probImage, Rect& window,
+                          TermCriteria criteria );
+
+class CV_EXPORTS KalmanFilter
+{
+public:
+    KalmanFilter();
+    KalmanFilter(int dynamParams, int measureParams, int controlParams=0);
+    void init(int dynamParams, int measureParams, int controlParams=0);
+
+    const Mat& predict(const Mat& control=Mat());
+    const Mat& correct(const Mat& measurement);
+
+    Mat statePre;           // predicted state (x'(k)):
+                            //    x(k)=A*x(k-1)+B*u(k)
+    Mat statePost;          // corrected state (x(k)):
+                            //    x(k)=x'(k)+K(k)*(z(k)-H*x'(k))
+    Mat transitionMatrix;   // state transition matrix (A)
+    Mat controlMatrix;      // control matrix (B)
+                            //   (it is not used if there is no control)
+    Mat measurementMatrix;  // measurement matrix (H)
+    Mat processNoiseCov;    // process noise covariance matrix (Q)
+    Mat measurementNoiseCov;// measurement noise covariance matrix (R)
+    Mat errorCovPre;        // priori error estimate covariance matrix (P'(k)):
+                            //    P'(k)=A*P(k-1)*At + Q)*/
+    Mat gain;               // Kalman gain matrix (K(k)):
+                            //    K(k)=P'(k)*Ht*inv(H*P'(k)*Ht+R)
+    Mat errorCovPost;       // posteriori error estimate covariance matrix (P(k)):
+                            //    P(k)=(I-K(k)*H)*P'(k)
+    Mat temp1;              // temporary matrices
+    Mat temp2;
+    Mat temp3;
+    Mat temp4;
+    Mat temp5;
+};
+
+
+///////////////////////////// Object Detection ////////////////////////////
+
+template<> inline void Ptr<CvHaarClassifierCascade>::delete_obj()
+{ cvReleaseHaarClassifierCascade(&obj); }
+
+class CV_EXPORTS HaarClassifierCascade
+{
+public:
+    enum { DO_CANNY_PRUNING = CV_HAAR_DO_CANNY_PRUNING,
+           SCALE_IMAGE = CV_HAAR_SCALE_IMAGE,
+           FIND_BIGGEST_OBJECT = CV_HAAR_FIND_BIGGEST_OBJECT,
+           DO_ROUGH_SEARCH = CV_HAAR_DO_ROUGH_SEARCH };
+    
+    HaarClassifierCascade();
+    HaarClassifierCascade(const String& filename);
+    bool load(const String& filename);
+
+    void detectMultiScale( const Mat& image,
+                           Vector<Rect>& objects,
+                           double scaleFactor=1.1,
+                           int minNeighbors=3, int flags=0,
+                           Size minSize=Size());
+
+    int runAt(Point pt, int startStage=0, int nstages=0) const;
+
+    void setImages( const Mat& sum, const Mat& sqsum,
+                    const Mat& tiltedSum, double scale );
+    
+    Ptr<CvHaarClassifierCascade> cascade;
+};
+
+CV_EXPORTS void undistortPoints( const Vector<Point2f>& src, Vector<Point2f>& dst,
+                                 const Mat& cameraMatrix, const Mat& distCoeffs,
+                                 const Mat& R=Mat(), const Mat& P=Mat());
+
+CV_EXPORTS Mat Rodrigues(const Mat& src);
+CV_EXPORTS Mat Rodrigues(const Mat& src, Mat& jacobian);
+
+enum { LMEDS=4, RANSAC=8 };
+
+CV_EXPORTS Mat findHomography( const Vector<Point2f>& srcPoints,
+                               const Vector<Point2f>& dstPoints,
+                               Vector<bool>& mask, int method=0,
+                               double ransacReprojThreshold=0 );
+
+CV_EXPORTS Mat findHomography( const Vector<Point2f>& srcPoints,
+                               const Vector<Point2f>& dstPoints,
+                               int method=0, double ransacReprojThreshold=0 );
+
+/* Computes RQ decomposition for 3x3 matrices */
+CV_EXPORTS void RQDecomp3x3( const Mat& M, Mat& R, Mat& Q );
+CV_EXPORTS Vec3d RQDecomp3x3( const Mat& M, Mat& R, Mat& Q,
+                              Mat& Qx, Mat& Qy, Mat& Qz );
+
+CV_EXPORTS void decomposeProjectionMatrix( const Mat& projMatrix, Mat& cameraMatrix,
+                                           Mat& rotMatrix, Mat& transVect );
+CV_EXPORTS void decomposeProjectionMatrix( const Mat& projMatrix, Mat& cameraMatrix,
+                                           Mat& rotMatrix, Mat& transVect,
+                                           Mat& rotMatrixX, Mat& rotMatrixY,
+                                           Mat& rotMatrixZ, Vec3d& eulerAngles );
+
+CV_EXPORTS void matMulDeriv( const Mat& A, const Mat& B, Mat& dABdA, Mat& dABdB );
+
+CV_EXPORTS void composeRT( const Mat& rvec1, const Mat& tvec1,
+                           const Mat& rvec2, const Mat& tvec2,
+                           Mat& rvec3, Mat& tvec3 );
+
+CV_EXPORTS void composeRT( const Mat& rvec1, const Mat& tvec1,
+                           const Mat& rvec2, const Mat& tvec2,
+                           Mat& rvec3, Mat& tvec3,
+                           Mat& dr3dr1, Mat& dr3dt1,
+                           Mat& dr3dr2, Mat& dr3dt2,
+                           Mat& dt3dr1, Mat& dt3dt1,
+                           Mat& dt3dr2, Mat& dt3dt2 );
+
+CV_EXPORTS void projectPoints( const Vector<Point3f>& objectPoints,
+                               const Mat& rvec, const Mat& tvec,
+                               const Mat& cameraMatrix,
+                               const Mat& distCoeffs,
+                               Vector<Point2f>& imagePoints );
+
+CV_EXPORTS void projectPoints( const Vector<Point3f>& objectPoints,
+                               const Mat& rvec, const Mat& tvec,
+                               const Mat& cameraMatrix,
+                               const Mat& distCoeffs,
+                               Vector<Point2f>& imagePoints,
+                               Mat& dpdrot, Mat& dpdt, Mat& dpdf,
+                               Mat& dpdc, Mat& dpddist,
+                               double aspectRatio=0 );
+
+CV_EXPORTS void solvePnP( const Vector<Point3f>& objectPoints,
+                          const Vector<Point2f>& imagePoints,
+                          const Mat& cameraMatrix,
+                          const Mat& distCoeffs,
+                          Mat& rvec, Mat& tvec,
+                          bool useExtrinsicGuess=false );
+
+CV_EXPORTS Mat initCameraMatrix2D( const Vector<Vector<Point3f> >& objectPoints,
+                                   const Vector<Vector<Point2f> >& imagePoints,
+                                   Size imageSize, double aspectRatio=1. );
+
+enum { CALIB_CB_ADAPTIVE_THRESH = CV_CALIB_CB_ADAPTIVE_THRESH,
+       CALIB_CB_NORMALIZE_IMAGE = CV_CALIB_CB_NORMALIZE_IMAGE,
+       CALIB_CB_FILTER_QUADS = CV_CALIB_CB_FILTER_QUADS };
+
+CV_EXPORTS bool findChessboardCorners( const Mat& image, Size patternSize,
+                                       Vector<Point2f>& corners,
+                                       int flags=CV_CALIB_CB_ADAPTIVE_THRESH+
+                                            CV_CALIB_CB_NORMALIZE_IMAGE );
+
+CV_EXPORTS void drawChessboardCorners( Mat& image, Size patternSize,
+                                       const Vector<Point2f>& corners,
+                                       bool patternWasFound );
+
+enum
+{
+    CALIB_USE_INTRINSIC_GUESS = CV_CALIB_USE_INTRINSIC_GUESS,
+    CALIB_FIX_ASPECT_RATIO = CV_CALIB_FIX_ASPECT_RATIO,
+    CALIB_FIX_PRINCIPAL_POINT = CV_CALIB_FIX_PRINCIPAL_POINT,
+    CALIB_ZERO_TANGENT_DIST = CV_CALIB_ZERO_TANGENT_DIST,
+    CALIB_FIX_FOCAL_LENGTH = CV_CALIB_FIX_FOCAL_LENGTH,
+    CALIB_FIX_K1 = CV_CALIB_FIX_K1,
+    CALIB_FIX_K2 = CV_CALIB_FIX_K2,
+    CALIB_FIX_K3 = CV_CALIB_FIX_K3,
+    // only for stereo
+    CALIB_FIX_INTRINSIC = CV_CALIB_FIX_INTRINSIC,
+    CALIB_SAME_FOCAL_LENGTH = CV_CALIB_SAME_FOCAL_LENGTH,
+    // for stereo rectification
+    CALIB_ZERO_DISPARITY = CV_CALIB_ZERO_DISPARITY
+};
+
+CV_EXPORTS void calibrateCamera( const Vector<Vector<Point3f> >& objectPoints,
+                                 const Vector<Vector<Point2f> >& imagePoints,
+                                 Size imageSize,
+                                 Mat& cameraMatrix, Mat& distCoeffs,
+                                 Vector<Mat>& rvecs, Vector<Mat>& tvecs,
+                                 int flags=0 );
+
+CV_EXPORTS void calibrationMatrixValues( const Mat& cameraMatrix,
+                                Size imageSize,
+                                double apertureWidth,
+                                double apertureHeight,
+                                double& fovx,
+                                double& fovy,
+                                double& focalLength,
+                                Point2d& principalPoint,
+                                double& aspectRatio );
+
+CV_EXPORTS void stereoCalibrate( const Vector<Vector<Point3f> >& objectPoints,
+                                 const Vector<Vector<Point2f> >& imagePoints1,
+                                 const Vector<Vector<Point2f> >& imagePoints2,
+                                 Mat& cameraMatrix1, Mat& distCoeffs1,
+                                 Mat& cameraMatrix2, Mat& distCoeffs2,
+                                 Size imageSize, Mat& R, Mat& T,
+                                 Mat& E, Mat& F,
+                                 TermCriteria criteria = TermCriteria(TermCriteria::COUNT+
+                                    TermCriteria::EPS, 30, 1e-6),
+                                 int flags=CALIB_FIX_INTRINSIC );
+
+CV_EXPORTS void stereoRectify( const Mat& cameraMatrix1, const Mat& distCoeffs1,
+                               const Mat& cameraMatrix2, const Mat& distCoeffs2,
+                               Size imageSize, const Mat& R, const Mat& T,
+                               Mat& R1, Mat& R2, Mat& P1, Mat& P2, Mat& Q,
+                               int flags=CALIB_ZERO_DISPARITY );
+
+CV_EXPORTS bool stereoRectifyUncalibrated( const Vector<Point2f>& points1,
+                                           const Vector<Point2f>& points2,
+                                           const Mat& F, Size imgSize,
+                                           Mat& H1, Mat& H2,
+                                           double threshold=5 );
+
+CV_EXPORTS void convertPointsHomogeneous( const Vector<Point2f>& src,
+                                          Vector<Point3f>& dst );
+CV_EXPORTS void convertPointsHomogeneous( const Vector<Point3f>& src,
+                                          Vector<Point2f>& dst );
+
+enum
+{ 
+    FM_7POINT = CV_FM_7POINT,
+    FM_8POINT = CV_FM_8POINT,
+    FM_LMEDS = CV_FM_LMEDS,
+    FM_RANSAC = CV_FM_RANSAC
+};
+
+CV_EXPORTS Mat findFundamentalMat( const Vector<Point2f>& points1,
+                                   const Vector<Point2f>& points2,
+                                   Vector<bool>& mask,
+                                   int method=FM_RANSAC,
+                                   double param1=3., double param2=0.99 );
+
+CV_EXPORTS Mat findFundamentalMat( const Vector<Point2f>& points1,
+                                   const Vector<Point2f>& points2,
+                                   int method=FM_RANSAC,
+                                   double param1=3., double param2=0.99 );
+
+CV_EXPORTS void computeCorrespondEpilines( const Vector<Point2f>& points1,
+                                           int whichImage, const Mat& F,
+                                           Vector<Vec3f>& lines );
+
+template<> inline void Ptr<CvStereoBMState>::delete_obj()
+{ cvReleaseStereoBMState(&obj); }
+
+// Block matching stereo correspondence algorithm
+class CV_EXPORTS StereoBM
+{
+    enum { NORMALIZED_RESPONSE = CV_STEREO_BM_NORMALIZED_RESPONSE,
+        BASIC_PRESET=CV_STEREO_BM_BASIC,
+        FISH_EYE_PRESET=CV_STEREO_BM_FISH_EYE,
+        NARROW_PRESET=CV_STEREO_BM_NARROW };
+    
+    StereoBM();
+    StereoBM(int preset, int ndisparities=0, int SADWindowSize=21);
+    void init(int preset, int ndisparities=0, int SADWindowSize=21);
+    void operator()( const Mat& left, const Mat& right, Mat& disparity );
+
+    Ptr<CvStereoBMState> state;
+};
+
+CV_EXPORTS void reprojectImageTo3D( const Mat& disparity,
+                                    Mat& _3dImage, const Mat& Q,
+                                    bool handleMissingValues=false );
+
+class CV_EXPORTS SURFKeypoint : public CvSURFPoint
+{
+public:
+    SURFKeypoint() { pt=Point2f(); laplacian=size=0; dir=hessian=0; }
+    SURFKeypoint(Point2f _pt, int _laplacian, int _size, float _dir=0.f, float _hessian=0.f)
+    { pt = _pt; laplacian = _laplacian; size = _size; dir = _dir; hessian = _hessian; }
+};
+
+class CV_EXPORTS SURF : public CvSURFParams
+{
+public:
+    SURF();
+    SURF(double _hessianThreshold, bool _extended=false);
+
+    int descriptorSize() const;
+    void operator()(const Mat& img, const Mat& mask,
+                    Vector<SURFKeypoint>& keypoints) const;
+    void operator()(const Mat& img, const Mat& mask,
+                    Vector<SURFKeypoint>& keypoints,
+                    Vector<float>& descriptors,
+                    bool useProvidedKeypoints=false) const;
+};
+
+
+class CV_EXPORTS MSER : public CvMSERParams
+{
+public:
+    MSER();
+    MSER( int _delta, int _min_area, int _max_area,
+          float _max_variation, float _min_diversity,
+          int _max_evolution, double _area_threshold,
+          double _min_margin, int _edge_blur_size );
+    Vector<Vector<Point> > operator()(Mat& image, const Mat& mask) const;
+};
+
+class CV_EXPORTS StarKeypoint : public CvStarKeypoint
+{
+public:
+    StarKeypoint() { pt = Point(); size = 0; response = 0.f; }
+    StarKeypoint(Point _pt, int _size, float _response)
+    {
+        pt = _pt; size = _size; response = _response;
+    }
+};
+
+class CV_EXPORTS StarDetector : CvStarDetectorParams
+{
+public:
+    StarDetector();
+    StarDetector(int _maxSize, int _responseThreshold,
+                 int _lineThresholdProjected,
+                 int _lineThresholdBinarized,
+                 int _suppressNonmaxSize);
+
+    void operator()(const Mat& image, Vector<StarKeypoint>& keypoints) const;
+};
+    
+    
+class CV_EXPORTS Keypoint
+{
+public:    
+    Keypoint() : pt(0,0), size(0), angle(-1), response(0), octave(0) {}
+    Keypoint(Point2f _pt, float _size, float _angle=-1, float _response=0, int _octave=0)
+    : pt(_pt), size(_size), angle(_angle), response(_response), octave(_octave) {}
+    Keypoint(float x, float y, float _size, float _angle=-1, float _response=0, int _octave=0)
+    : pt(x, y), size(_size), angle(_angle), response(_response), octave(_octave) {}
+    
+    Point2f pt;
+    float size;
+    float angle;
+    float response;
+    int octave;
+};
+
+void write(FileStorage& fs, const String& name, const Vector<Keypoint>& keypoints);
+void read(const FileNode& node, Vector<Keypoint>& keypoints);    
+
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+class CV_EXPORTS CvLevMarq
+{
+public:
+    CvLevMarq();
+    CvLevMarq( int nparams, int nerrs, CvTermCriteria criteria=
+        cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER,30,DBL_EPSILON),
+        bool completeSymmFlag=false );
+    ~CvLevMarq();
+    void init( int nparams, int nerrs, CvTermCriteria criteria=
+        cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER,30,DBL_EPSILON),
+        bool completeSymmFlag=false );
+    bool update( const CvMat*& param, CvMat*& J, CvMat*& err );
+    bool updateAlt( const CvMat*& param, CvMat*& JtJ, CvMat*& JtErr, double*& errNorm );
+
+    void clear();
+    void step();
+    enum { DONE=0, STARTED=1, CALC_J=2, CHECK_ERR=3 };
+
+    CvMat* mask;
+    CvMat* prevParam;
+    CvMat* param;
+    CvMat* J;
+    CvMat* err;
+    CvMat* JtJ;
+    CvMat* JtJN;
+    CvMat* JtErr;
+    CvMat* JtJV;
+    CvMat* JtJW;
+    double prevErrNorm, errNorm;
+    int lambdaLg10;
+    CvTermCriteria criteria;
+    int state;
+    int iters;
+    bool completeSymmFlag;
+};
+
+
+// 2009-01-12, Xavier Delacour <xavier.delacour@gmail.com>
+
+struct lsh_hash {
+  int h1, h2;
+};
+
+struct CvLSHOperations
+{
+  virtual ~CvLSHOperations() {}
+
+  virtual int vector_add(const void* data) = 0;
+  virtual void vector_remove(int i) = 0;
+  virtual const void* vector_lookup(int i) = 0;
+  virtual void vector_reserve(int n) = 0;
+  virtual unsigned int vector_count() = 0;
+
+  virtual void hash_insert(lsh_hash h, int l, int i) = 0;
+  virtual void hash_remove(lsh_hash h, int l, int i) = 0;
+  virtual int hash_lookup(lsh_hash h, int l, int* ret_i, int ret_i_max) = 0;
+};
+
+
+#endif /* __cplusplus */
+
+#endif /* _CV_HPP_ */
+
+/* End of file. */
index 2f7443e42a713c0544bfe3045ade8ccb3a3ba5ef..1e98cb525c7372d2f1abc23d51463317ed5e8bfa 100644 (file)
@@ -458,7 +458,199 @@ public:
     bool gammaCorrection;
     Vector<float> svmDetector;
 };
+    
+    
+class CV_EXPORTS PatchGenerator
+{
+public:
+    PatchGenerator();
+    PatchGenerator(double _backgroundMin, double _backgroundMax,
+                   double _noiseRange, bool _randomBlur=true,
+                   double _lambdaMin=0.6, double _lambdaMax=1.5,
+                   double _thetaMin=-CV_PI, double _thetaMax=CV_PI,
+                   double _phiMin=-CV_PI, double _phiMax=CV_PI );
+    void operator()(const Mat& image, Point2f pt, Mat& patch, Size patchSize, RNG& rng) const;
+    void operator()(const Mat& image, const Mat& transform, Mat& patch,
+                    Size patchSize, RNG& rng) const;
+    void warpWholeImage(const Mat& image, Mat& _T, Mat& buf,
+                        Mat& warped, int border, RNG& rng) const;
+    void generateRandomTransform(Point2f srcCenter, Point2f dstCenter,
+                                 Mat& transform, RNG& rng, bool inverse=false) const;
+    double backgroundMin, backgroundMax;
+    double noiseRange;
+    bool randomBlur;
+    double lambdaMin, lambdaMax;
+    double thetaMin, thetaMax;
+    double phiMin, phiMax;
+};
+
+
+class CV_EXPORTS LDetector
+{
+public:    
+    LDetector();
+    LDetector(int _radius, int _threshold, int _nOctaves,
+              int _nViews, double _baseFeatureSize, double _clusteringDistance);
+    void operator()(const Mat& image, Vector<Keypoint>& keypoints, int maxCount=0, bool scaleCoords=true) const;
+    void operator()(const Vector<Mat>& pyr, Vector<Keypoint>& keypoints, int maxCount=0, bool scaleCoords=true) const;
+    void getMostStable2D(const Mat& image, Vector<Keypoint>& keypoints,
+                         int maxCount, const PatchGenerator& patchGenerator) const;
+    void setVerbose(bool verbose);
+    
+    void read(const FileNode& node);
+    void write(FileStorage& fs, const String& name=String()) const;
+    
+    int radius;
+    int threshold;
+    int nOctaves;
+    int nViews;
+    bool verbose;
+    
+    double baseFeatureSize;
+    double clusteringDistance;
+};
+
+
+class CV_EXPORTS FernClassifier
+{
+public:
+    FernClassifier();
+    FernClassifier(const FileNode& node);
+    FernClassifier(const Vector<Point2f>& points,
+                   const Vector<Ptr<Mat> >& refimgs,
+                   const Vector<int>& labels=Vector<int>(),
+                   int _nclasses=0, int _patchSize=PATCH_SIZE,
+                   int _signatureSize=DEFAULT_SIGNATURE_SIZE,
+                   int _nstructs=DEFAULT_STRUCTS,
+                   int _structSize=DEFAULT_STRUCT_SIZE,
+                   int _nviews=DEFAULT_VIEWS,
+                   int _compressionMethod=COMPRESSION_NONE,
+                   const PatchGenerator& patchGenerator=PatchGenerator());
+    virtual ~FernClassifier();
+    virtual void read(const FileNode& n);
+    virtual void write(FileStorage& fs, const String& name=String()) const;
+    virtual void trainFromSingleView(const Mat& image,
+                                     const Vector<Keypoint>& keypoints,
+                                     int _patchSize=PATCH_SIZE,
+                                     int _signatureSize=DEFAULT_SIGNATURE_SIZE,
+                                     int _nstructs=DEFAULT_STRUCTS,
+                                     int _structSize=DEFAULT_STRUCT_SIZE,
+                                     int _nviews=DEFAULT_VIEWS,
+                                     int _compressionMethod=COMPRESSION_NONE,
+                                     const PatchGenerator& patchGenerator=PatchGenerator());
+    virtual void train(const Vector<Point2f>& points,
+                       const Vector<Ptr<Mat> >& refimgs,
+                       const Vector<int>& labels=Vector<int>(),
+                       int _nclasses=0, int _patchSize=PATCH_SIZE,
+                       int _signatureSize=DEFAULT_SIGNATURE_SIZE,
+                       int _nstructs=DEFAULT_STRUCTS,
+                       int _structSize=DEFAULT_STRUCT_SIZE,
+                       int _nviews=DEFAULT_VIEWS,
+                       int _compressionMethod=COMPRESSION_NONE,
+                       const PatchGenerator& patchGenerator=PatchGenerator());
+    virtual int operator()(const Mat& img, Point2f kpt, Vector<float>& signature) const;
+    virtual int operator()(const Mat& patch, Vector<float>& signature) const;
+    virtual void clear();
+    void setVerbose(bool verbose);
+    
+    int getClassCount() const;
+    int getStructCount() const;
+    int getStructSize() const;
+    int getSignatureSize() const;
+    int getCompressionMethod() const;
+    Size getPatchSize() const;    
+    
+    struct Feature
+    {
+        uchar x1, y1, x2, y2;
+        Feature() : x1(0), y1(0), x2(0), y2(0) {}
+        Feature(int _x1, int _y1, int _x2, int _y2)
+        : x1((uchar)_x1), y1((uchar)_y1), x2((uchar)_x2), y2((uchar)_y2)
+        {}
+        template<typename _Tp> bool operator ()(const Mat_<_Tp>& patch) const
+        { return patch(y1,x1) > patch(y2, x2); }
+    };
+    
+    enum
+    {
+        PATCH_SIZE = 31,
+        DEFAULT_STRUCTS = 50,
+        DEFAULT_STRUCT_SIZE = 9,
+        DEFAULT_VIEWS = 5000,
+        DEFAULT_SIGNATURE_SIZE = 176,
+        COMPRESSION_NONE = 0,
+        COMPRESSION_RANDOM_PROJ = 1,
+        COMPRESSION_PCA = 2,
+        DEFAULT_COMPRESSION_METHOD = COMPRESSION_NONE,
+    };
+    
+protected:
+    virtual void prepare(int _nclasses, int _patchSize, int _signatureSize,
+                         int _nstructs, int _structSize,
+                         int _nviews, int _compressionMethod);
+    virtual void finalize(RNG& rng);
+    virtual int getLeaf(int fidx, const Mat& patch) const;
+    
+    bool verbose;
+    int nstructs;
+    int structSize;
+    int nclasses;
+    int signatureSize;
+    int compressionMethod;
+    int leavesPerStruct;
+    Size patchSize;
+    Vector<Feature> features;
+    Vector<int> classCounters;
+    Vector<float> posteriors;
+};
 
+class CV_EXPORTS PlanarObjectDetector
+{
+public:
+    PlanarObjectDetector();
+    PlanarObjectDetector(const FileNode& node);
+    PlanarObjectDetector(const Vector<Mat>& pyr, int _npoints=300,
+                         int _patchSize=FernClassifier::PATCH_SIZE,
+                         int _nstructs=FernClassifier::DEFAULT_STRUCTS,
+                         int _structSize=FernClassifier::DEFAULT_STRUCT_SIZE,
+                         int _nviews=FernClassifier::DEFAULT_VIEWS,
+                         const LDetector& detector=LDetector(),
+                         const PatchGenerator& patchGenerator=PatchGenerator()); 
+    virtual ~PlanarObjectDetector();
+    virtual void train(const Vector<Mat>& pyr, int _npoints=300,
+                       int _patchSize=FernClassifier::PATCH_SIZE,
+                       int _nstructs=FernClassifier::DEFAULT_STRUCTS,
+                       int _structSize=FernClassifier::DEFAULT_STRUCT_SIZE,
+                       int _nviews=FernClassifier::DEFAULT_VIEWS,
+                       const LDetector& detector=LDetector(),
+                       const PatchGenerator& patchGenerator=PatchGenerator());
+    virtual void train(const Vector<Mat>& pyr, const Vector<Keypoint>& keypoints,
+                       int _patchSize=FernClassifier::PATCH_SIZE,
+                       int _nstructs=FernClassifier::DEFAULT_STRUCTS,
+                       int _structSize=FernClassifier::DEFAULT_STRUCT_SIZE,
+                       int _nviews=FernClassifier::DEFAULT_VIEWS,
+                       const LDetector& detector=LDetector(),
+                       const PatchGenerator& patchGenerator=PatchGenerator());
+    Rect getModelROI() const;
+    Vector<Keypoint> getModelPoints() const;
+    const LDetector& getDetector() const;
+    const FernClassifier& getClassifier() const;
+    void setVerbose(bool verbose);
+    
+    void read(const FileNode& node);
+    void write(FileStorage& fs, const String& name=String()) const;
+    bool operator()(const Mat& image, Mat& H, Vector<Point2f>& corners) const;
+    bool operator()(const Vector<Mat>& pyr, const Vector<Keypoint>& keypoints,
+                    Mat& H, Vector<Point2f>& corners, Vector<int>* pairs=0) const;
+    
+protected:
+    bool verbose;
+    Rect modelROI;
+    Vector<Keypoint> modelPoints;
+    LDetector ldetector;
+    FernClassifier fernClassifier;
+};
+    
 }
 
 #endif /* __cplusplus */
index 0d4b3ac45ba3b49b7710eb45f5ef0c4f889c19f3..315ade0cbdcce878a2f4c8570f077cfe38795935 100644 (file)
-/*M///////////////////////////////////////////////////////////////////////////////////////\r
-//\r
-//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.\r
-//\r
-//  By downloading, copying, installing or using the software you agree to this license.\r
-//  If you do not agree to this license, do not download, install,\r
-//  copy or use the software.\r
-//\r
-//\r
-//                           License Agreement\r
-//                For Open Source Computer Vision Library\r
-//\r
-// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.\r
-// Copyright (C) 2009, Willow Garage Inc., all rights reserved.\r
-// Third party copyrights are property of their respective owners.\r
-//\r
-// Redistribution and use in source and binary forms, with or without modification,\r
-// are permitted provided that the following conditions are met:\r
-//\r
-//   * Redistribution's of source code must retain the above copyright notice,\r
-//     this list of conditions and the following disclaimer.\r
-//\r
-//   * Redistribution's in binary form must reproduce the above copyright notice,\r
-//     this list of conditions and the following disclaimer in the documentation\r
-//     and/or other materials provided with the distribution.\r
-//\r
-//   * The name of the copyright holders may not be used to endorse or promote products\r
-//     derived from this software without specific prior written permission.\r
-//\r
-// This software is provided by the copyright holders and contributors "as is" and\r
-// any express or implied warranties, including, but not limited to, the implied\r
-// warranties of merchantability and fitness for a particular purpose are disclaimed.\r
-// In no event shall the Intel Corporation or contributors be liable for any direct,\r
-// indirect, incidental, special, exemplary, or consequential damages\r
-// (including, but not limited to, procurement of substitute goods or services;\r
-// loss of use, data, or profits; or business interruption) however caused\r
-// and on any theory of liability, whether in contract, strict liability,\r
-// or tort (including negligence or otherwise) arising in any way out of\r
-// the use of this software, even if advised of the possibility of such damage.\r
-//\r
-//M*/\r
-\r
-#ifndef _CXCORE_HPP_\r
-#define _CXCORE_HPP_\r
-\r
-#include "cxmisc.h"\r
-\r
-#ifdef __cplusplus\r
-\r
-#ifndef SKIP_INCLUDES\r
-#include <algorithm>\r
-#include <complex>\r
-#include <map>\r
-#include <new>\r
-#include <string>\r
-#include <vector>\r
-#endif // SKIP_INCLUDES\r
-\r
-namespace cv {\r
-\r
-template<typename _Tp> class CV_EXPORTS Size_;\r
-template<typename _Tp> class CV_EXPORTS Point_;\r
-template<typename _Tp> class CV_EXPORTS Rect_;\r
-\r
-typedef std::string String;\r
-typedef std::basic_string<wchar_t> WString;\r
-\r
-CV_EXPORTS String fromUtf16(const WString& str);\r
-CV_EXPORTS WString toUtf16(const String& str);\r
-\r
-class CV_EXPORTS Exception\r
-{\r
-public:\r
-    Exception() { code = 0; line = 0; }\r
-    Exception(int _code, const String& _err, const String& _func, const String& _file, int _line)\r
-        : code(_code), err(_err), func(_func), file(_file), line(_line) {}\r
-    Exception(const Exception& exc)\r
-        : code(exc.code), err(exc.err), func(exc.func), file(exc.file), line(exc.line) {}\r
-    Exception& operator = (const Exception& exc)\r
-    {\r
-        if( this != &exc )\r
-        {\r
-            code = exc.code; err = exc.err; func = exc.func; file = exc.file; line = exc.line;\r
-        }\r
-        return *this;\r
-    }\r
-\r
-    int code;\r
-    String err;\r
-    String func;\r
-    String file;\r
-    int line;\r
-};\r
-\r
-CV_EXPORTS String format( const char* fmt, ... );\r
-CV_EXPORTS void error( const Exception& exc );\r
-\r
-#ifdef __GNUC__\r
-#define CV_Error( code, msg ) cv::error( cv::Exception(code, msg, __func__, __FILE__, __LINE__) )\r
-#define CV_Error_( code, args ) cv::error( cv::Exception(code, cv::format args, __func__, __FILE__, __LINE__) )\r
-#define CV_Assert( expr ) { if(!(expr)) cv::error( cv::Exception(CV_StsAssert, #expr, __func__, __FILE__, __LINE__) ); }\r
-#else\r
-#define CV_Error( code, msg ) cv::error( cv::Exception(code, msg, "", __FILE__, __LINE__) )\r
-#define CV_Error_( code, args ) cv::error( cv::Exception(code, cv::format args, "", __FILE__, __LINE__) )\r
-#define CV_Assert( expr ) { if(!(expr)) cv::error( cv::Exception(CV_StsAssert, #expr, "", __FILE__, __LINE__) ); }\r
-#endif\r
-    \r
-#ifdef _DEBUG\r
-#define CV_DbgAssert(expr) CV_Assert(expr)\r
-#else\r
-#define CV_DbgAssert(expr)\r
-#endif\r
-\r
-CV_EXPORTS void setNumThreads(int);\r
-CV_EXPORTS int getNumThreads();\r
-CV_EXPORTS int getThreadNum();\r
-\r
-CV_EXPORTS int64 getTickCount();\r
-CV_EXPORTS double getTickFrequency();\r
-\r
-CV_EXPORTS void* fastMalloc(size_t);\r
-CV_EXPORTS void fastFree(void* ptr);\r
-\r
-template<typename _Tp> static inline _Tp* allocate(size_t n)\r
-{\r
-    _Tp* ptr = (_Tp*)fastMalloc(n*sizeof(ptr[0]));\r
-    ::new(ptr) _Tp[n];\r
-    return ptr;\r
-}\r
-\r
-template<typename _Tp> static inline void deallocate(_Tp* ptr, size_t n)\r
-{\r
-    for( size_t i = 0; i < n; i++ ) (ptr+i)->~_Tp();\r
-    fastFree(ptr);\r
-}\r
-\r
-template<typename _Tp> static inline _Tp* alignPtr(_Tp* ptr, int n=(int)sizeof(_Tp))\r
-{\r
-    return (_Tp*)(((size_t)ptr + n-1) & -n);\r
-}\r
-\r
-static inline size_t alignSize(size_t sz, int n)\r
-{\r
-    return (sz + n-1) & -n;\r
-}\r
-\r
-CV_EXPORTS void setUseOptimized(bool);\r
-CV_EXPORTS bool useOptimized();\r
-\r
-template<typename _Tp> class CV_EXPORTS Allocator\r
-{\r
-public: \r
-    typedef _Tp value_type;\r
-    typedef value_type* pointer;\r
-    typedef const value_type* const_pointer;\r
-    typedef value_type& reference;\r
-    typedef const value_type& const_reference;\r
-    typedef size_t size_type;\r
-    typedef ptrdiff_t difference_type;\r
-    template<typename U> class rebind { typedef Allocator<U> other; };\r
-\r
-    explicit Allocator() {}\r
-    ~Allocator() {}\r
-    explicit Allocator(Allocator const&) {}\r
-    template<typename U>\r
-    explicit Allocator(Allocator<U> const&) {}\r
-\r
-    // address\r
-    pointer address(reference r) { return &r; }\r
-    const_pointer address(const_reference r) { return &r; }\r
-\r
-    pointer allocate(size_type count, const void* =0)\r
-    { return reinterpret_cast<pointer>(fastMalloc(count * sizeof (_Tp))); }\r
-\r
-    void deallocate(pointer p, size_type) {fastFree(p); }\r
-\r
-    size_type max_size() const\r
-    { return max(static_cast<_Tp>(-1)/sizeof(_Tp), 1); }\r
-\r
-    void construct(pointer p, const _Tp& v) { new(static_cast<void*>(p)) _Tp(v); }\r
-    void destroy(pointer p) { p->~_Tp(); }\r
-};\r
-\r
-/////////////////////// Vec (used as element of multi-channel images ///////////////////// \r
-\r
-template<typename _Tp> class CV_EXPORTS DataDepth { public: enum { value = -1, fmt=(int)'\0' }; };\r
-\r
-template<> class DataDepth<bool> { public: enum { value = CV_8U, fmt=(int)'u' }; };\r
-template<> class DataDepth<uchar> { public: enum { value = CV_8U, fmt=(int)'u' }; };\r
-template<> class DataDepth<schar> { public: enum { value = CV_8S, fmt=(int)'c' }; };\r
-template<> class DataDepth<ushort> { public: enum { value = CV_16U, fmt=(int)'w' }; };\r
-template<> class DataDepth<short> { public: enum { value = CV_16S, fmt=(int)'s' }; };\r
-template<> class DataDepth<int> { public: enum { value = CV_32S, fmt=(int)'i' }; };\r
-template<> class DataDepth<float> { public: enum { value = CV_32F, fmt=(int)'f' }; };\r
-template<> class DataDepth<double> { public: enum { value = CV_64F, fmt=(int)'d' }; };\r
-template<typename _Tp> class DataDepth<_Tp*> { public: enum { value = CV_USRTYPE1, fmt=(int)'r' }; };\r
-\r
-template<typename _Tp, int cn> class CV_EXPORTS Vec\r
-{\r
-public:\r
-    typedef _Tp value_type;\r
-    enum { depth = DataDepth<_Tp>::value, channels = cn, type = CV_MAKETYPE(depth, channels) };\r
-    \r
-    Vec();\r
-    Vec(_Tp v0);\r
-    Vec(_Tp v0, _Tp v1);\r
-    Vec(_Tp v0, _Tp v1, _Tp v2);\r
-    Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3);\r
-    Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4);\r
-    Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5);\r
-    Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6);\r
-    Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7);\r
-    Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8);\r
-    Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8, _Tp v9);\r
-    Vec(const Vec<_Tp, cn>& v);\r
-    static Vec all(_Tp alpha);\r
-    _Tp dot(const Vec& v) const;\r
-    double ddot(const Vec& v) const;\r
-    Vec cross(const Vec& v) const;\r
-    template<typename T2> operator Vec<T2, cn>() const;\r
-    operator CvScalar() const;\r
-    _Tp operator [](int i) const;\r
-    _Tp& operator[](int i);\r
-\r
-    _Tp val[cn];\r
-};\r
-\r
-typedef Vec<uchar, 2> Vec2b;\r
-typedef Vec<uchar, 3> Vec3b;\r
-typedef Vec<uchar, 4> Vec4b;\r
-\r
-typedef Vec<short, 2> Vec2s;\r
-typedef Vec<short, 3> Vec3s;\r
-typedef Vec<short, 4> Vec4s;\r
-\r
-typedef Vec<int, 2> Vec2i;\r
-typedef Vec<int, 3> Vec3i;\r
-typedef Vec<int, 4> Vec4i;\r
-\r
-typedef Vec<float, 2> Vec2f;\r
-typedef Vec<float, 3> Vec3f;\r
-typedef Vec<float, 4> Vec4f;\r
-typedef Vec<float, 6> Vec6f;\r
-\r
-typedef Vec<double, 2> Vec2d;\r
-typedef Vec<double, 3> Vec3d;\r
-typedef Vec<double, 4> Vec4d;\r
-typedef Vec<double, 6> Vec6d;\r
-\r
-//////////////////////////////// Complex //////////////////////////////\r
-\r
-template<typename _Tp> class CV_EXPORTS Complex\r
-{\r
-public:\r
-    Complex();\r
-    Complex( _Tp _re, _Tp _im=0 );\r
-    Complex( const std::complex<_Tp>& c );\r
-    template<typename T2> operator Complex<T2>() const;\r
-    Complex conj() const;\r
-    operator std::complex<_Tp>() const;\r
-\r
-    _Tp re, im;\r
-};\r
-\r
-typedef Complex<float> Complexf;\r
-typedef Complex<double> Complexd;\r
-\r
-//////////////////////////////// Point_ ////////////////////////////////\r
-\r
-template<typename _Tp> class CV_EXPORTS Point_\r
-{\r
-public:\r
-    typedef _Tp value_type;\r
-    \r
-    Point_();\r
-    Point_(_Tp _x, _Tp _y);\r
-    Point_(const Point_& pt);\r
-    Point_(const CvPoint& pt);\r
-    Point_(const CvPoint2D32f& pt);\r
-    Point_(const Size_<_Tp>& sz);\r
-    Point_& operator = (const Point_& pt);\r
-    operator Point_<int>() const;\r
-    operator Point_<float>() const;\r
-    operator Point_<double>() const;\r
-    operator CvPoint() const;\r
-    operator CvPoint2D32f() const;\r
-\r
-    _Tp dot(const Point_& pt) const;\r
-    double ddot(const Point_& pt) const;\r
-    bool inside(const Rect_<_Tp>& r) const;\r
-    \r
-    _Tp x, y;\r
-};\r
-\r
-template<typename _Tp> class CV_EXPORTS Point3_\r
-{\r
-public:\r
-    typedef _Tp value_type;\r
-    \r
-    Point3_();\r
-    Point3_(_Tp _x, _Tp _y, _Tp _z);\r
-    Point3_(const Point3_& pt);\r
-       Point3_(const Point_<_Tp>& pt);\r
-    Point3_(const CvPoint3D32f& pt);\r
-    Point3_(const Vec<_Tp, 3>& t);\r
-    Point3_& operator = (const Point3_& pt);\r
-    operator Point3_<int>() const;\r
-    operator Point3_<float>() const;\r
-    operator Point3_<double>() const;\r
-    operator CvPoint3D32f() const;\r
-\r
-    _Tp dot(const Point3_& pt) const;\r
-    double ddot(const Point3_& pt) const;\r
-    \r
-    _Tp x, y, z;\r
-};\r
-\r
-//////////////////////////////// Size_ ////////////////////////////////\r
-\r
-template<typename _Tp> class CV_EXPORTS Size_\r
-{\r
-public:\r
-    typedef _Tp value_type;\r
-    \r
-    Size_();\r
-    Size_(_Tp _width, _Tp _height);\r
-    Size_(const Size_& sz);\r
-    Size_(const CvSize& sz);\r
-    Size_(const CvSize2D32f& sz);\r
-    Size_(const Point_<_Tp>& pt);\r
-    Size_& operator = (const Size_& sz);\r
-    _Tp area() const;\r
-\r
-    operator Size_<int>() const;\r
-    operator Size_<float>() const;\r
-    operator Size_<double>() const;\r
-    operator CvSize() const;\r
-    operator CvSize2D32f() const;\r
-\r
-    _Tp width, height;\r
-};\r
-\r
-//////////////////////////////// Rect_ ////////////////////////////////\r
-\r
-template<typename _Tp> class CV_EXPORTS Rect_\r
-{\r
-public:\r
-    typedef _Tp value_type;\r
-    \r
-    Rect_();\r
-    Rect_(_Tp _x, _Tp _y, _Tp _width, _Tp _height);\r
-    Rect_(const Rect_& r);\r
-    Rect_(const CvRect& r);\r
-    Rect_(const Point_<_Tp>& org, const Size_<_Tp>& sz);\r
-    Rect_(const Point_<_Tp>& pt1, const Point_<_Tp>& pt2);\r
-    Rect_& operator = ( const Rect_& r );\r
-    Point_<_Tp> tl() const;\r
-    Point_<_Tp> br() const;\r
-    \r
-    Size_<_Tp> size() const;\r
-    _Tp area() const;\r
-\r
-    operator Rect_<int>() const;\r
-    operator Rect_<float>() const;\r
-    operator Rect_<double>() const;\r
-    operator CvRect() const;\r
-\r
-    bool contains(const Point_<_Tp>& pt) const;\r
-\r
-    _Tp x, y, width, height;\r
-};\r
-\r
-typedef Point_<int> Point2i;\r
-typedef Point2i Point;\r
-typedef Size_<int> Size2i;\r
-typedef Size2i Size;\r
-typedef Rect_<int> Rect;\r
-typedef Point_<float> Point2f;\r
-typedef Point_<double> Point2d;\r
-typedef Size_<float> Size2f;\r
-typedef Point3_<int> Point3i;\r
-typedef Point3_<float> Point3f;\r
-typedef Point3_<double> Point3d;\r
-\r
-class CV_EXPORTS RotatedRect\r
-{\r
-public:\r
-    RotatedRect();\r
-    RotatedRect(const Point2f& _center, const Size2f& _size, float _angle);\r
-    RotatedRect(const CvBox2D& box);\r
-    Rect boundingRect() const;\r
-    operator CvBox2D() const;\r
-    Point2f center;\r
-    Size2f size;\r
-    float angle;\r
-};\r
-\r
-//////////////////////////////// Scalar_ ///////////////////////////////\r
-\r
-template<typename _Tp> class CV_EXPORTS Scalar_ : public Vec<_Tp, 4>\r
-{\r
-public:\r
-    Scalar_();\r
-    Scalar_(_Tp v0, _Tp v1, _Tp v2=0, _Tp v3=0);\r
-    Scalar_(const CvScalar& s);\r
-    Scalar_(_Tp v0);\r
-    static Scalar_<_Tp> all(_Tp v0);\r
-    operator CvScalar() const;\r
-\r
-    template<typename T2> operator Scalar_<T2>() const;\r
-\r
-    Scalar_<_Tp> mul(const Scalar_<_Tp>& t, double scale=1 ) const;\r
-    template<typename T2> void convertTo(T2* buf, int channels, int unroll_to=0) const;\r
-};\r
-\r
-typedef Scalar_<double> Scalar;\r
-\r
-//////////////////////////////// Range /////////////////////////////////\r
-\r
-class CV_EXPORTS Range\r
-{\r
-public:\r
-    Range();\r
-    Range(int _start, int _end);\r
-    Range(const CvSlice& slice);\r
-    int size() const;\r
-    bool empty() const;\r
-    static Range all();\r
-    operator CvSlice() const;\r
-\r
-    int start, end;\r
-};\r
-\r
-/////////////////////////////// DataType ////////////////////////////////\r
-\r
-template<typename _Tp> class DataType\r
-{\r
-public:\r
-    typedef _Tp value_type;\r
-    typedef value_type work_type;\r
-    typedef value_type channel_type;\r
-    enum { depth = DataDepth<channel_type>::value, channels = 1,\r
-           fmt=DataDepth<channel_type>::fmt,\r
-           type = CV_MAKETYPE(depth, channels) };\r
-};\r
-\r
-template<> class DataType<bool>\r
-{\r
-public:\r
-    typedef bool value_type;\r
-    typedef int work_type;\r
-    typedef value_type channel_type;\r
-    enum { depth = DataDepth<channel_type>::value, channels = 1,\r
-           fmt=DataDepth<channel_type>::fmt,\r
-           type = CV_MAKETYPE(depth, channels) };\r
-};\r
-\r
-template<> class DataType<uchar>\r
-{\r
-public:\r
-    typedef uchar value_type;\r
-    typedef int work_type;\r
-    typedef value_type channel_type;\r
-    enum { depth = DataDepth<channel_type>::value, channels = 1,\r
-           fmt=DataDepth<channel_type>::fmt,\r
-           type = CV_MAKETYPE(depth, channels) };\r
-};\r
-\r
-template<> class DataType<schar>\r
-{\r
-public:\r
-    typedef schar value_type;\r
-    typedef int work_type;\r
-    typedef value_type channel_type;\r
-    enum { depth = DataDepth<channel_type>::value, channels = 1,\r
-           fmt=DataDepth<channel_type>::fmt,\r
-           type = CV_MAKETYPE(depth, channels) };\r
-};\r
-\r
-template<> class DataType<ushort>\r
-{\r
-public:\r
-    typedef ushort value_type;\r
-    typedef int work_type;\r
-    typedef value_type channel_type;\r
-    enum { depth = DataDepth<channel_type>::value, channels = 1,\r
-           fmt=DataDepth<channel_type>::fmt,\r
-           type = CV_MAKETYPE(depth, channels) };\r
-};\r
-\r
-template<> class DataType<short>\r
-{\r
-public:\r
-    typedef short value_type;\r
-    typedef int work_type;\r
-    typedef value_type channel_type;\r
-    enum { depth = DataDepth<channel_type>::value, channels = 1,\r
-           fmt=DataDepth<channel_type>::fmt,\r
-           type = CV_MAKETYPE(depth, channels) };\r
-};\r
-\r
-template<> class DataType<int>\r
-{\r
-public:\r
-    typedef int value_type;\r
-    typedef value_type work_type;\r
-    typedef value_type channel_type;\r
-    enum { depth = DataDepth<channel_type>::value, channels = 1,\r
-           fmt=DataDepth<channel_type>::fmt,\r
-           type = CV_MAKETYPE(depth, channels) };\r
-};\r
-\r
-template<> class DataType<float>\r
-{\r
-public:\r
-    typedef float value_type;\r
-    typedef value_type work_type;\r
-    typedef value_type channel_type;\r
-    enum { depth = DataDepth<channel_type>::value, channels = 1,\r
-           fmt=DataDepth<channel_type>::fmt,\r
-           type = CV_MAKETYPE(depth, channels) };\r
-};\r
-\r
-template<> class DataType<double>\r
-{\r
-public:\r
-    typedef double value_type;\r
-    typedef value_type work_type;\r
-    typedef value_type channel_type;\r
-    enum { depth = DataDepth<channel_type>::value, channels = 1,\r
-           fmt=DataDepth<channel_type>::fmt,\r
-           type = CV_MAKETYPE(depth, channels) };\r
-};\r
-\r
-template<typename _Tp, int cn> class DataType<Vec<_Tp, cn> >\r
-{\r
-public:\r
-    typedef Vec<_Tp, cn> value_type;\r
-    typedef Vec<typename DataType<_Tp>::work_type, cn> work_type;\r
-    typedef _Tp channel_type;\r
-    enum { depth = DataDepth<channel_type>::value, channels = cn,\r
-           fmt = ((channels-1)<<8) + DataDepth<channel_type>::fmt,\r
-           type = CV_MAKETYPE(depth, channels) };\r
-};\r
-\r
-template<typename _Tp> class DataType<std::complex<_Tp> >\r
-{\r
-public:\r
-    typedef std::complex<_Tp> value_type;\r
-    typedef value_type work_type;\r
-    typedef _Tp channel_type;\r
-    enum { depth = DataDepth<channel_type>::value, channels = 2,\r
-           fmt = ((channels-1)<<8) + DataDepth<channel_type>::fmt,\r
-           type = CV_MAKETYPE(depth, channels) };\r
-};\r
-\r
-template<typename _Tp> class DataType<Complex<_Tp> >\r
-{\r
-public:\r
-    typedef Complex<_Tp> value_type;\r
-    typedef value_type work_type;\r
-    typedef _Tp channel_type;\r
-    enum { depth = DataDepth<channel_type>::value, channels = 2,\r
-           fmt = ((channels-1)<<8) + DataDepth<channel_type>::fmt,\r
-           type = CV_MAKETYPE(depth, channels) };\r
-};\r
-\r
-template<typename _Tp> class DataType<Point_<_Tp> >\r
-{\r
-public:\r
-    typedef Point_<_Tp> value_type;\r
-    typedef Point_<typename DataType<_Tp>::work_type> work_type;\r
-    typedef _Tp channel_type;\r
-    enum { depth = DataDepth<channel_type>::value, channels = 2,\r
-           fmt = ((channels-1)<<8) + DataDepth<channel_type>::fmt,\r
-           type = CV_MAKETYPE(depth, channels) };\r
-};\r
-\r
-template<typename _Tp> class DataType<Point3_<_Tp> >\r
-{\r
-public:\r
-    typedef Point3_<_Tp> value_type;\r
-    typedef Point3_<typename DataType<_Tp>::work_type> work_type;\r
-    typedef _Tp channel_type;\r
-    enum { depth = DataDepth<channel_type>::value, channels = 3,\r
-           fmt = ((channels-1)<<8) + DataDepth<channel_type>::fmt,\r
-           type = CV_MAKETYPE(depth, channels) };\r
-};\r
-\r
-template<typename _Tp> class DataType<Size_<_Tp> >\r
-{\r
-public:\r
-    typedef Size_<_Tp> value_type;\r
-    typedef Size_<typename DataType<_Tp>::work_type> work_type;\r
-    typedef _Tp channel_type;\r
-    enum { depth = DataDepth<channel_type>::value, channels = 2,\r
-           fmt = ((channels-1)<<8) + DataDepth<channel_type>::fmt,\r
-           type = CV_MAKETYPE(depth, channels) };\r
-};\r
-\r
-template<typename _Tp> class DataType<Rect_<_Tp> >\r
-{\r
-public:\r
-    typedef Rect_<_Tp> value_type;\r
-    typedef Rect_<typename DataType<_Tp>::work_type> work_type;\r
-    typedef _Tp channel_type;\r
-    enum { depth = DataDepth<channel_type>::value, channels = 4,\r
-           fmt = ((channels-1)<<8) + DataDepth<channel_type>::fmt,\r
-           type = CV_MAKETYPE(depth, channels) };\r
-};\r
-\r
-template<typename _Tp> class DataType<Scalar_<_Tp> >\r
-{\r
-public:\r
-    typedef Scalar_<_Tp> value_type;\r
-    typedef Scalar_<typename DataType<_Tp>::work_type> work_type;\r
-    typedef _Tp channel_type;\r
-    enum { depth = DataDepth<channel_type>::value, channels = 4,\r
-           fmt = ((channels-1)<<8) + DataDepth<channel_type>::fmt,\r
-           type = CV_MAKETYPE(depth, channels) };\r
-};\r
-\r
-template<> class DataType<Range>\r
-{\r
-public:\r
-    typedef Range value_type;\r
-    typedef value_type work_type;\r
-    typedef int channel_type;\r
-    enum { depth = DataDepth<channel_type>::value, channels = 2,\r
-           fmt = ((channels-1)<<8) + DataDepth<channel_type>::fmt,\r
-           type = CV_MAKETYPE(depth, channels) };\r
-};\r
-\r
-\r
-//////////////////////////////// Vector ////////////////////////////////\r
-\r
-// template vector class. It is similar to STL's vector,\r
-// with a few important differences:\r
-//   1) it can be created on top of user-allocated data w/o copying it\r
-//   2) Vector b = a means copying the header,\r
-//      not the underlying data (use clone() to make a deep copy)\r
-template <typename _Tp> class CV_EXPORTS Vector\r
-{\r
-public:\r
-    typedef _Tp value_type;\r
-    typedef _Tp* iterator;\r
-    typedef const _Tp* const_iterator;\r
-    typedef _Tp& reference;\r
-    typedef const _Tp& const_reference;\r
-\r
-    struct CV_EXPORTS Hdr\r
-    {\r
-        Hdr() : data(0), datastart(0), refcount(0), size(0), capacity(0) {};\r
-        _Tp* data;\r
-        _Tp* datastart;\r
-        int* refcount;\r
-        size_t size;\r
-        size_t capacity;\r
-    };\r
-\r
-    Vector();\r
-    Vector(size_t _size);\r
-    Vector(size_t _size, const _Tp& val);\r
-    Vector(_Tp* _data, size_t _size, bool _copyData=false);\r
-    template<int n> Vector(const Vec<_Tp, n>& vec);\r
-    Vector(const std::vector<_Tp>& vec, bool _copyData=false);\r
-    Vector(const Vector& d);\r
-    Vector(const Vector& d, const Range& r);\r
-\r
-    Vector<_Tp>& operator = (const Vector& d);\r
-    ~Vector();\r
-    Vector clone() const;\r
-    void copyTo(Vector<_Tp>& vec) const;\r
-    void copyTo(std::vector<_Tp>& vec) const;\r
-    operator CvMat() const;\r
-    \r
-    _Tp& operator [] (size_t i);\r
-    const _Tp& operator [] (size_t i) const;\r
-    _Tp& operator [] (int i);\r
-    const _Tp& operator [] (int i) const;\r
-    Vector operator() (const Range& r) const;\r
-    _Tp& back();\r
-    const _Tp& back() const;\r
-    _Tp& front();\r
-    const _Tp& front() const;\r
-\r
-    _Tp* begin();\r
-    _Tp* end();\r
-    const _Tp* begin() const;\r
-    const _Tp* end() const;\r
-\r
-    void addref();\r
-    void release();\r
-    void set(_Tp* _data, size_t _size, bool _copyData=false);\r
-\r
-    void reserve(size_t newCapacity);\r
-    void resize(size_t newSize);\r
-    Vector<_Tp>& push_back(const _Tp& elem);\r
-    Vector<_Tp>& pop_back();\r
-    size_t size() const;\r
-    size_t capacity() const;\r
-    bool empty() const;\r
-    void clear();\r
-    int type() const;\r
-\r
-protected:\r
-    Hdr hdr;\r
-};\r
-\r
-//////////////////// Generic ref-cointing pointer class for C/C++ objects ////////////////////////\r
-\r
-template<typename _Tp> class CV_EXPORTS Ptr\r
-{\r
-public:\r
-    Ptr();\r
-    Ptr(_Tp* _obj);\r
-    ~Ptr();\r
-    Ptr(const Ptr& ptr);\r
-    Ptr& operator = (const Ptr& ptr);\r
-    void addref();\r
-    void release();\r
-    void delete_obj();\r
-    bool empty() const;\r
-\r
-    _Tp* operator -> ();\r
-    const _Tp* operator -> () const;\r
-\r
-    operator _Tp* ();\r
-    operator const _Tp*() const;\r
-protected:\r
-    _Tp* obj;\r
-    int* refcount;\r
-};\r
-\r
-//////////////////////////////// Mat ////////////////////////////////\r
-\r
-class Mat;\r
-template<typename M> class CV_EXPORTS MatExpr_Base_;\r
-typedef MatExpr_Base_<Mat> MatExpr_Base;\r
-template<typename E, typename M> class MatExpr_;\r
-template<typename A1, typename M, typename Op> class MatExpr_Op1_;\r
-template<typename A1, typename A2, typename M, typename Op> class MatExpr_Op2_;\r
-template<typename A1, typename A2, typename A3, typename M, typename Op> class MatExpr_Op3_;\r
-template<typename A1, typename A2, typename A3, typename A4,\r
-        typename M, typename Op> class MatExpr_Op4_;\r
-template<typename A1, typename A2, typename A3, typename A4,\r
-        typename A5, typename M, typename Op> class MatExpr_Op5_;\r
-template<typename M> class CV_EXPORTS MatOp_DivRS_;\r
-template<typename M> class CV_EXPORTS MatOp_Inv_;\r
-template<typename M> class CV_EXPORTS MatOp_MulDiv_;\r
-template<typename M> class CV_EXPORTS MatOp_Repeat_;\r
-template<typename M> class CV_EXPORTS MatOp_Set_;\r
-template<typename M> class CV_EXPORTS MatOp_Scale_;\r
-template<typename M> class CV_EXPORTS MatOp_T_;\r
-\r
-typedef MatExpr_<MatExpr_Op4_<Size, int, Scalar,\r
-    int, Mat, MatOp_Set_<Mat> >, Mat> MatExpr_Initializer;\r
-\r
-template<typename _Tp> class MatIterator_;\r
-template<typename _Tp> class MatConstIterator_;\r
-\r
-enum { MAGIC_MASK=0xFFFF0000, TYPE_MASK=0x00000FFF, DEPTH_MASK=7 };\r
-\r
-static inline size_t getElemSize(int type) { return CV_ELEM_SIZE(type); }\r
-\r
-// matrix decomposition types\r
-enum { DECOMP_LU=0, DECOMP_SVD=1, DECOMP_EIG=2, DECOMP_CHOLESKY=3, DECOMP_QR=4, DECOMP_NORMAL=16 };\r
-enum { NORM_INF=1, NORM_L1=2, NORM_L2=4, NORM_TYPE_MASK=7, NORM_RELATIVE=8};\r
-enum { CMP_EQ=0, CMP_GT=1, CMP_GE=2, CMP_LT=3, CMP_LE=4, CMP_NE=5 };\r
-enum { GEMM_1_T=1, GEMM_2_T=2, GEMM_3_T=4 };\r
-enum { DFT_INVERSE=1, DFT_SCALE=2, DFT_ROWS=4, DFT_COMPLEX_OUTPUT=16, DFT_REAL_OUTPUT=32,\r
-    DCT_INVERSE = DFT_INVERSE, DCT_ROWS=DFT_ROWS };\r
-\r
-class CV_EXPORTS Mat\r
-{\r
-public:\r
-    Mat();\r
-    Mat(int _rows, int _cols, int _type);\r
-    Mat(int _rows, int _cols, int _type, const Scalar& _s);\r
-    Mat(Size _size, int _type);\r
-    Mat(const Mat& m);\r
-    Mat(int _rows, int _cols, int _type, void* _data, size_t _step=AUTO_STEP);\r
-    Mat(Size _size, int _type, void* _data, size_t _step=AUTO_STEP);\r
-    Mat(const Mat& m, const Range& rowRange, const Range& colRange);\r
-    Mat(const Mat& m, const Rect& roi);\r
-    Mat(const CvMat* m, bool copyData=false);\r
-    Mat(const IplImage* img, bool copyData=false);\r
-    Mat( const MatExpr_Base& expr );\r
-    ~Mat();\r
-    Mat& operator = (const Mat& m);\r
-    Mat& operator = (const MatExpr_Base& expr);\r
-\r
-    operator MatExpr_<Mat, Mat>() const;\r
-\r
-    Mat row(int y) const;\r
-    Mat col(int x) const;\r
-    Mat rowRange(int startrow, int endrow) const;\r
-    Mat rowRange(const Range& r) const;\r
-    Mat colRange(int startcol, int endcol) const;\r
-    Mat colRange(const Range& r) const;\r
-    Mat diag(int d=0) const;\r
-    static Mat diag(const Mat& d);\r
-\r
-    Mat clone() const;\r
-    void copyTo( Mat& m ) const;\r
-    void copyTo( Mat& m, const Mat& mask ) const;\r
-    void convertTo( Mat& m, int rtype, double alpha=1, double beta=0 ) const;\r
-\r
-    void assignTo( Mat& m, int type=-1 ) const;\r
-    Mat& operator = (const Scalar& s);\r
-    Mat& setTo(const Scalar& s, const Mat& mask=Mat());\r
-    Mat reshape(int _cn, int _rows=0) const;\r
-\r
-    MatExpr_<MatExpr_Op2_<Mat, double, Mat, MatOp_T_<Mat> >, Mat>\r
-    t() const;\r
-    MatExpr_<MatExpr_Op2_<Mat, int, Mat, MatOp_Inv_<Mat> >, Mat>\r
-        inv(int method=DECOMP_LU) const;\r
-    MatExpr_<MatExpr_Op4_<Mat, Mat, double, char, Mat, MatOp_MulDiv_<Mat> >, Mat>\r
-    mul(const Mat& m, double scale=1) const;\r
-    MatExpr_<MatExpr_Op4_<Mat, Mat, double, char, Mat, MatOp_MulDiv_<Mat> >, Mat>\r
-    mul(const MatExpr_<MatExpr_Op2_<Mat, double, Mat, MatOp_Scale_<Mat> >, Mat>& m, double scale=1) const;\r
-    MatExpr_<MatExpr_Op4_<Mat, Mat, double, char, Mat, MatOp_MulDiv_<Mat> >, Mat>    \r
-    mul(const MatExpr_<MatExpr_Op2_<Mat, double, Mat, MatOp_DivRS_<Mat> >, Mat>& m, double scale=1) const;\r
-\r
-    Mat cross(const Mat& m) const;\r
-    double dot(const Mat& m) const;\r
-\r
-    static MatExpr_Initializer zeros(int rows, int cols, int type);\r
-    static MatExpr_Initializer zeros(Size size, int type);\r
-    static MatExpr_Initializer ones(int rows, int cols, int type);\r
-    static MatExpr_Initializer ones(Size size, int type);\r
-    static MatExpr_Initializer eye(int rows, int cols, int type);\r
-    static MatExpr_Initializer eye(Size size, int type);\r
-\r
-    void create(int _rows, int _cols, int _type);\r
-    void create(Size _size, int _type);\r
-    void addref();\r
-    void release();\r
-\r
-    void locateROI( Size& wholeSize, Point& ofs ) const;\r
-    Mat& adjustROI( int dtop, int dbottom, int dleft, int dright );\r
-    Mat operator()( Range rowRange, Range colRange ) const;\r
-    Mat operator()( const Rect& roi ) const;\r
-\r
-    operator CvMat() const;\r
-    operator IplImage() const;\r
-    bool isContinuous() const;\r
-    size_t elemSize() const;\r
-    size_t elemSize1() const;\r
-    int type() const;\r
-    int depth() const;\r
-    int channels() const;\r
-    size_t step1() const;\r
-    Size size() const;\r
-\r
-    uchar* ptr(int y=0);\r
-    const uchar* ptr(int y=0) const;\r
-\r
-    template<typename _Tp> _Tp* ptr(int y=0);\r
-    template<typename _Tp> const _Tp* ptr(int y=0) const;\r
-\r
-    enum { MAGIC_VAL=0x42FF0000, AUTO_STEP=0, CONTINUOUS_FLAG=CV_MAT_CONT_FLAG };\r
-\r
-    int flags;\r
-    int rows, cols;\r
-    size_t step;\r
-    uchar* data;\r
-\r
-    int* refcount;\r
-    uchar* datastart;\r
-    uchar* dataend;\r
-};\r
-\r
-\r
-// Multiply-with-Carry RNG\r
-class CV_EXPORTS RNG\r
-{\r
-public:\r
-    enum { A=4164903690U, UNIFORM=0, NORMAL=1 };\r
-\r
-    RNG();\r
-    RNG(uint64 _state);\r
-    unsigned next();\r
-\r
-    operator uchar();\r
-    operator schar();\r
-    operator ushort();\r
-    operator short();\r
-    operator unsigned();\r
-    operator int();\r
-    operator float();\r
-    operator double();\r
-    int uniform(int a, int b);\r
-    float uniform(float a, float b);\r
-    double uniform(double a, double b);\r
-    void fill( Mat& mat, int distType, const Scalar& a, const Scalar& b );\r
-\r
-    uint64 state;\r
-};\r
-\r
-class CV_EXPORTS TermCriteria\r
-{\r
-public:\r
-    enum { COUNT=1, MAX_ITER=COUNT, EPS=2 };\r
-\r
-    TermCriteria();\r
-    TermCriteria(int _type, int _maxCount, double _epsilon);\r
-    TermCriteria(const CvTermCriteria& criteria);\r
-    operator CvTermCriteria() const;\r
-    \r
-    int type;\r
-    int maxCount;\r
-    double epsilon;\r
-};\r
-\r
-CV_EXPORTS Mat cvarrToMat(const CvArr* arr, bool copyData=false, bool allowND=true);\r
-CV_EXPORTS Mat extractImageCOI(const CvArr* arr);\r
-\r
-CV_EXPORTS void add(const Mat& a, const Mat& b, Mat& c, const Mat& mask);\r
-CV_EXPORTS void subtract(const Mat& a, const Mat& b, Mat& c, const Mat& mask);\r
-CV_EXPORTS void add(const Mat& a, const Mat& b, Mat& c);\r
-CV_EXPORTS void subtract(const Mat& a, const Mat& b, Mat& c);\r
-CV_EXPORTS void add(const Mat& a, const Scalar& s, Mat& c, const Mat& mask=Mat());\r
-CV_EXPORTS void subtract(const Mat& a, const Scalar& s, Mat& c, const Mat& mask=Mat());\r
-\r
-CV_EXPORTS void multiply(const Mat& a, const Mat& b, Mat& c, double scale=1);\r
-CV_EXPORTS void divide(const Mat& a, const Mat& b, Mat& c, double scale=1);\r
-CV_EXPORTS void divide(double scale, const Mat& b, Mat& c);\r
-\r
-CV_EXPORTS void subtract(const Scalar& s, const Mat& a, Mat& c, const Mat& mask=Mat());\r
-CV_EXPORTS void scaleAdd(const Mat& a, double alpha, const Mat& b, Mat& c);\r
-CV_EXPORTS void addWeighted(const Mat& a, double alpha, const Mat& b,\r
-                            double beta, double gamma, Mat& c);\r
-CV_EXPORTS void convertScaleAbs(const Mat& a, Mat& c, double alpha=1, double beta=0);\r
-CV_EXPORTS void LUT(const Mat& a, const Mat& lut, Mat& b);\r
-\r
-CV_EXPORTS Scalar sum(const Mat& m);\r
-CV_EXPORTS int countNonZero( const Mat& m );\r
-\r
-CV_EXPORTS Scalar mean(const Mat& m);\r
-CV_EXPORTS Scalar mean(const Mat& m, const Mat& mask);\r
-CV_EXPORTS void meanStdDev(const Mat& m, Scalar& mean, Scalar& stddev, const Mat& mask=Mat());\r
-CV_EXPORTS double norm(const Mat& a, int normType=NORM_L2);\r
-CV_EXPORTS double norm(const Mat& a, const Mat& b, int normType=NORM_L2);\r
-CV_EXPORTS double norm(const Mat& a, int normType, const Mat& mask);\r
-CV_EXPORTS double norm(const Mat& a, const Mat& b,\r
-                       int normType, const Mat& mask);\r
-CV_EXPORTS void normalize( const Mat& a, Mat& b, double alpha=1, double beta=0,\r
-                          int norm_type=NORM_L2, int rtype=-1, const Mat& mask=Mat());\r
-\r
-CV_EXPORTS void minMaxLoc(const Mat& a, double* minVal,\r
-                          double* maxVal=0, Point* minLoc=0,\r
-                          Point* maxLoc=0, const Mat& mask=Mat());\r
-CV_EXPORTS void reduce(const Mat& m, Mat& dst, int dim, int rtype, int dtype=-1);\r
-CV_EXPORTS void merge(const Vector<Mat>& mv, Mat& dst);\r
-CV_EXPORTS void split(const Mat& m, Vector<Mat>& mv);\r
-CV_EXPORTS void mixChannels(const Vector<Mat>& src, Vector<Mat>& dst,\r
-                            const Vector<int>& fromTo);\r
-CV_EXPORTS void flip(const Mat& a, Mat& b, int flipCode);\r
-\r
-CV_EXPORTS void repeat(const Mat& a, int ny, int nx, Mat& b);\r
-static inline Mat repeat(const Mat& src, int ny, int nx)\r
-{\r
-    if( nx == 1 && ny == 1 ) return src;\r
-    Mat dst; repeat(src, ny, nx, dst); return dst;\r
-}\r
-\r
-CV_EXPORTS void bitwise_and(const Mat& a, const Mat& b, Mat& c, const Mat& mask=Mat());\r
-CV_EXPORTS void bitwise_or(const Mat& a, const Mat& b, Mat& c, const Mat& mask=Mat());\r
-CV_EXPORTS void bitwise_xor(const Mat& a, const Mat& b, Mat& c, const Mat& mask=Mat());\r
-CV_EXPORTS void bitwise_and(const Mat& a, const Scalar& s, Mat& c, const Mat& mask=Mat());\r
-CV_EXPORTS void bitwise_or(const Mat& a, const Scalar& s, Mat& c, const Mat& mask=Mat());\r
-CV_EXPORTS void bitwise_xor(const Mat& a, const Scalar& s, Mat& c, const Mat& mask=Mat());\r
-CV_EXPORTS void bitwise_not(const Mat& a, Mat& c);\r
-CV_EXPORTS void absdiff(const Mat& a, const Mat& b, Mat& c);\r
-CV_EXPORTS void absdiff(const Mat& a, const Scalar& s, Mat& c);\r
-CV_EXPORTS void inRange(const Mat& src, const Mat& lowerb,\r
-                        const Mat& upperb, Mat& dst);\r
-CV_EXPORTS void inRange(const Mat& src, const Scalar& lowerb,\r
-                        const Scalar& upperb, Mat& dst);\r
-CV_EXPORTS void compare(const Mat& a, const Mat& b, Mat& c, int cmpop);\r
-CV_EXPORTS void compare(const Mat& a, double s, Mat& c, int cmpop);\r
-CV_EXPORTS void min(const Mat& a, const Mat& b, Mat& c);\r
-CV_EXPORTS void min(const Mat& a, double alpha, Mat& c);\r
-CV_EXPORTS void max(const Mat& a, const Mat& b, Mat& c);\r
-CV_EXPORTS void max(const Mat& a, double alpha, Mat& c);\r
-\r
-CV_EXPORTS void sqrt(const Mat& a, Mat& b);\r
-CV_EXPORTS void pow(const Mat& a, double power, Mat& b);\r
-CV_EXPORTS void exp(const Mat& a, Mat& b);\r
-CV_EXPORTS void log(const Mat& a, Mat& b);\r
-CV_EXPORTS float cubeRoot(float val);\r
-CV_EXPORTS float fastAtan2(float y, float x);\r
-CV_EXPORTS void polarToCart(const Mat& magnitude, const Mat& angle,\r
-                            Mat& x, Mat& y, bool angleInDegrees=false);\r
-CV_EXPORTS void cartToPolar(const Mat& x, const Mat& y,\r
-                            Mat& magnitude, Mat& angle,\r
-                            bool angleInDegrees=false);\r
-CV_EXPORTS void phase(const Mat& x, const Mat& y, Mat& angle,\r
-                            bool angleInDegrees=false);\r
-CV_EXPORTS void magnitude(const Mat& x, const Mat& y, Mat& magnitude);\r
-CV_EXPORTS bool checkRange(const Mat& a, bool quiet=true, Point* pt=0,\r
-                           double minVal=-DBL_MAX, double maxVal=DBL_MAX);\r
-\r
-CV_EXPORTS void gemm(const Mat& a, const Mat& b, double alpha,\r
-                     const Mat& c, double gamma, Mat& d, int flags=0);\r
-CV_EXPORTS void mulTransposed( const Mat& a, Mat& c, bool aTa,\r
-                               const Mat& delta=Mat(),\r
-                               double scale=1, int rtype=-1 );\r
-CV_EXPORTS void transpose(const Mat& a, Mat& b);\r
-CV_EXPORTS void transform(const Mat& src, Mat& dst, const Mat& m );\r
-CV_EXPORTS void perspectiveTransform(const Mat& src, Mat& dst, const Mat& m );\r
-\r
-CV_EXPORTS void completeSymm(Mat& a, bool lowerToUpper=false);\r
-CV_EXPORTS void setIdentity(Mat& c, const Scalar& s=Scalar(1));\r
-CV_EXPORTS double determinant(const Mat& m);\r
-CV_EXPORTS Scalar trace(const Mat& m);\r
-CV_EXPORTS double invert(const Mat& a, Mat& c, int flags=DECOMP_LU);\r
-CV_EXPORTS bool solve(const Mat& a, const Mat& b, Mat& x, int flags=DECOMP_LU);\r
-CV_EXPORTS void sort(const Mat& a, Mat& b, int flags);\r
-CV_EXPORTS void sortIdx(const Mat& a, Mat& b, int flags);\r
-CV_EXPORTS void solveCubic(const Mat& coeffs, Mat& roots);\r
-CV_EXPORTS void solvePoly(const Mat& coeffs, Mat& roots, int maxIters=20, int fig=100);\r
-CV_EXPORTS bool eigen(const Mat& a, Mat& eigenvalues);\r
-CV_EXPORTS bool eigen(const Mat& a, Mat& eigenvalues, Mat& eigenvectors);\r
-\r
-CV_EXPORTS void calcCovariation( const Vector<Mat>& data, Mat& covar, Mat& mean,\r
-                                 int flags, int ctype=CV_64F);\r
-CV_EXPORTS void calcCovariation( const Mat& data, Mat& covar, Mat& mean,\r
-                                 int flags, int ctype=CV_64F);\r
-\r
-class CV_EXPORTS PCA\r
-{\r
-public:\r
-    PCA();\r
-    PCA(const Mat& data, const Mat& mean, int flags, int maxComponents=0);\r
-    PCA& operator()(const Mat& data, const Mat& mean, int flags, int maxComponents=0);\r
-    Mat project(const Mat& vec) const;\r
-    void project(const Mat& vec, Mat& result) const;\r
-    Mat backProject(const Mat& vec) const;\r
-    void backProject(const Mat& vec, Mat& result) const;\r
-\r
-    Mat eigenvectors;\r
-    Mat eigenvalues;\r
-    Mat mean;\r
-};\r
-\r
-class CV_EXPORTS SVD\r
-{\r
-public:\r
-    enum { MODIFY_A=1, NO_UV=2, FULL_UV=4 };\r
-    SVD();\r
-    SVD( const Mat& m, int flags=0 );\r
-    SVD& operator ()( const Mat& m, int flags=0 );\r
-\r
-    static void solveZ( const Mat& m, Mat& dst );\r
-    void backSubst( const Mat& rhs, Mat& dst ) const;\r
-\r
-    Mat u, w, vt;\r
-};\r
-\r
-CV_EXPORTS double mahalanobis(const Mat& v1, const Mat& v2, const Mat& icovar);\r
-static inline double mahalonobis(const Mat& v1, const Mat& v2, const Mat& icovar)\r
-{ return mahalanobis(v1, v2, icovar); }\r
-\r
-CV_EXPORTS void dft(const Mat& src, Mat& dst, int flags=0, int nonzeroRows=0);\r
-CV_EXPORTS void idft(const Mat& src, Mat& dst, int flags=0, int nonzeroRows=0);\r
-CV_EXPORTS void dct(const Mat& src, Mat& dst, int flags=0);\r
-CV_EXPORTS void idct(const Mat& src, Mat& dst, int flags=0);\r
-CV_EXPORTS void mulSpectrums(const Mat& a, const Mat& b, Mat& c,\r
-                             int flags, bool conjB=false);\r
-CV_EXPORTS int getOptimalDFTSize(int vecsize);\r
-\r
-enum { KMEANS_CENTERS_RANDOM=0, KMEANS_CENTERS_SPP=2, KMEANS_USE_INITIAL_LABELS=1 };\r
-CV_EXPORTS int kmeans( const Mat& samples, int K,\r
-                       Mat& labels, Mat& centers,\r
-                       TermCriteria crit, int attempts=1,\r
-                       int flags=KMEANS_CENTERS_SPP,\r
-                       double* compactness=0);\r
-\r
-CV_EXPORTS void seqToVector( const CvSeq* ptseq, Vector<Point>& pts );\r
-\r
-CV_EXPORTS RNG& theRNG();\r
-static inline int randi() { return (int)theRNG(); }\r
-static inline unsigned randu() { return (unsigned)theRNG(); }\r
-static inline float randf() { return (float)theRNG(); }\r
-static inline double randd() { return (double)theRNG(); }\r
-static inline void randu(Mat& dst, const Scalar& low, const Scalar& high)\r
-{ theRNG().fill(dst, RNG::UNIFORM, low, high); }\r
-static inline void randn(Mat& dst, const Scalar& mean, const Scalar& stddev)\r
-{ theRNG().fill(dst, RNG::NORMAL, mean, stddev); }\r
-CV_EXPORTS void randShuffle(Mat& dst, RNG& rng, double iterFactor=1.);\r
-static inline void randShuffle(Mat& dst, double iterFactor=1.)\r
-{ randShuffle(dst, theRNG(), iterFactor); }\r
-\r
-CV_EXPORTS void line(Mat& img, Point pt1, Point pt2, const Scalar& color,\r
-                     int thickness=1, int lineType=8, int shift=0);\r
-\r
-CV_EXPORTS void rectangle(Mat& img, Point pt1, Point pt2,\r
-                          const Scalar& color, int thickness=1,\r
-                          int lineType=8, int shift=0);\r
-\r
-CV_EXPORTS void circle(Mat& img, Point center, int radius,\r
-                       const Scalar& color, int thickness=1,\r
-                       int lineType=8, int shift=0);\r
-\r
-CV_EXPORTS void ellipse(Mat& img, Point center, Size axes,\r
-                        double angle, double startAngle, double endAngle,\r
-                        const Scalar& color, int thickness=1,\r
-                        int lineType=8, int shift=0);\r
-\r
-CV_EXPORTS void ellipse(Mat& img, const RotatedRect& box, const Scalar& color,\r
-                        int thickness=1, int lineType=8, int shift=0 );\r
-\r
-CV_EXPORTS void fillConvexPoly(Mat& img, const Vector<Point>& pts,\r
-                               const Scalar& color, int lineType=8,\r
-                               int shift=0);\r
-\r
-CV_EXPORTS void fillPoly(Mat& img, const Vector<Vector<Point> >& pts,\r
-                         const Scalar& color, int lineType=8, int shift=0,\r
-                         Point offset=Point() );\r
-\r
-CV_EXPORTS void polylines(Mat& img, const Vector<Vector<Point> >& pts, bool isClosed,\r
-                          const Scalar& color, int thickness=1, int lineType=8, int shift=0 );\r
-\r
-CV_EXPORTS bool clipLine(Size imgSize, Point& pt1, Point& pt2);\r
-\r
-class CV_EXPORTS LineIterator\r
-{\r
-public:\r
-    LineIterator(const Mat& img, Point pt1, Point pt2,\r
-                 int connectivity=8, bool leftToRight=false);\r
-    uchar* operator *();\r
-    LineIterator& operator ++();\r
-    LineIterator operator ++(int);\r
-\r
-    uchar* ptr;\r
-    int err, count;\r
-    int minusDelta, plusDelta;\r
-    int minusStep, plusStep;\r
-};\r
-\r
-CV_EXPORTS void ellipse2Poly( Point center, Size axes, int angle,\r
-                              int arcStart, int arcEnd, int delta, Vector<Point>& pts );\r
-\r
-enum\r
-{\r
-    FONT_HERSHEY_SIMPLEX = 0,\r
-    FONT_HERSHEY_PLAIN = 1,\r
-    FONT_HERSHEY_DUPLEX = 2,\r
-    FONT_HERSHEY_COMPLEX = 3,\r
-    FONT_HERSHEY_TRIPLEX = 4,\r
-    FONT_HERSHEY_COMPLEX_SMALL = 5,\r
-    FONT_HERSHEY_SCRIPT_SIMPLEX = 6,\r
-    FONT_HERSHEY_SCRIPT_COMPLEX = 7,\r
-    FONT_ITALIC = 16\r
-};\r
-\r
-CV_EXPORTS void putText( Mat& img, const String& text, Point org,\r
-                         int fontFace, double fontScale, Scalar color,\r
-                         int thickness=1, int linetype=8,\r
-                         bool bottomLeftOrigin=false );\r
-\r
-CV_EXPORTS Size getTextSize(const String& text, int fontFace,\r
-                            double fontScale, int thickness,\r
-                            int* baseLine);\r
-\r
-///////////////////////////////// Mat_<_Tp> ////////////////////////////////////\r
-\r
-template<typename _Tp> class CV_EXPORTS Mat_ : public Mat\r
-{\r
-public:\r
-    typedef _Tp value_type;\r
-    typedef typename DataType<_Tp>::channel_type channel_type;\r
-    typedef MatIterator_<_Tp> iterator;\r
-    typedef MatConstIterator_<_Tp> const_iterator;\r
-    \r
-    Mat_();\r
-    Mat_(int _rows, int _cols);\r
-    Mat_(int _rows, int _cols, const _Tp& value);\r
-    explicit Mat_(Size _size);\r
-    Mat_(Size _size, const _Tp& value);\r
-    Mat_(const Mat& m);\r
-    Mat_(const Mat_& m);\r
-    Mat_(int _rows, int _cols, _Tp* _data, size_t _step=AUTO_STEP);\r
-    Mat_(const Mat_& m, const Range& rowRange, const Range& colRange);\r
-    Mat_(const Mat_& m, const Rect& roi);\r
-    Mat_(const MatExpr_Base& expr);\r
-    template<int n> explicit Mat_(const Vec<_Tp, n>& vec);\r
-    Mat_(const Vector<_Tp>& vec);\r
-\r
-    Mat_& operator = (const Mat& m);\r
-    Mat_& operator = (const Mat_& m);\r
-    Mat_& operator = (const _Tp& s);\r
-\r
-    iterator begin();\r
-    iterator end();\r
-    const_iterator begin() const;\r
-    const_iterator end() const;\r
-\r
-    void create(int _rows, int _cols);\r
-    void create(Size _size);\r
-    Mat_ cross(const Mat_& m) const;\r
-    Mat_& operator = (const MatExpr_Base& expr);\r
-    template<typename T2> operator Mat_<T2>() const;\r
-    Mat_ row(int y) const;\r
-    Mat_ col(int x) const;\r
-    Mat_ diag(int d=0) const;\r
-    Mat_ clone() const;\r
-\r
-    MatExpr_<MatExpr_Op2_<Mat_, double, Mat_, MatOp_T_<Mat> >, Mat_> t() const;\r
-    MatExpr_<MatExpr_Op2_<Mat_, int, Mat_, MatOp_Inv_<Mat> >, Mat_> inv(int method=DECOMP_LU) const;\r
-\r
-    MatExpr_<MatExpr_Op4_<Mat_, Mat_, double, char, Mat_, MatOp_MulDiv_<Mat> >, Mat_>\r
-    mul(const Mat_& m, double scale=1) const;\r
-    MatExpr_<MatExpr_Op4_<Mat_, Mat_, double, char, Mat_, MatOp_MulDiv_<Mat> >, Mat_>\r
-    mul(const MatExpr_<MatExpr_Op2_<Mat_, double, Mat_,\r
-        MatOp_Scale_<Mat> >, Mat_>& m, double scale=1) const;\r
-    MatExpr_<MatExpr_Op4_<Mat_, Mat_, double, char, Mat_, MatOp_MulDiv_<Mat> >, Mat_>    \r
-    mul(const MatExpr_<MatExpr_Op2_<Mat_, double, Mat_,\r
-        MatOp_DivRS_<Mat> >, Mat_>& m, double scale=1) const;\r
-\r
-    size_t elemSize() const;\r
-    size_t elemSize1() const;\r
-    int type() const;\r
-    int depth() const;\r
-    int channels() const;\r
-    size_t stepT() const;\r
-    size_t step1() const;\r
-\r
-    static MatExpr_Initializer zeros(int rows, int cols);\r
-    static MatExpr_Initializer zeros(Size size);\r
-    static MatExpr_Initializer ones(int rows, int cols);\r
-    static MatExpr_Initializer ones(Size size);\r
-    static MatExpr_Initializer eye(int rows, int cols);\r
-    static MatExpr_Initializer eye(Size size);\r
-\r
-    Mat_ reshape(int _rows) const;\r
-    Mat_& adjustROI( int dtop, int dbottom, int dleft, int dright );\r
-    Mat_ operator()( const Range& rowRange, const Range& colRange ) const;\r
-    Mat_ operator()( const Rect& roi ) const;\r
-\r
-    _Tp* operator [](int y);\r
-    const _Tp* operator [](int y) const;\r
-\r
-    _Tp& operator ()(int row, int col);\r
-    const _Tp& operator ()(int row, int col) const;\r
-\r
-    operator MatExpr_<Mat_, Mat_>() const;\r
-    operator Vector<_Tp>() const;\r
-};\r
-\r
-//////////// Iterators & Comma initializers //////////////////\r
-\r
-template<typename _Tp>\r
-class CV_EXPORTS MatConstIterator_\r
-{\r
-public:\r
-    typedef _Tp value_type;\r
-    typedef int difference_type;\r
-\r
-    MatConstIterator_();\r
-    MatConstIterator_(const Mat_<_Tp>* _m);\r
-    MatConstIterator_(const Mat_<_Tp>* _m, int _row, int _col=0);\r
-    MatConstIterator_(const Mat_<_Tp>* _m, Point _pt);\r
-    MatConstIterator_(const MatConstIterator_& it);\r
-\r
-    MatConstIterator_& operator = (const MatConstIterator_& it );\r
-    _Tp operator *() const;\r
-    _Tp operator [](int i) const;\r
-    \r
-    MatConstIterator_& operator += (int ofs);\r
-    MatConstIterator_& operator -= (int ofs);\r
-    MatConstIterator_& operator --();\r
-    MatConstIterator_ operator --(int);\r
-    MatConstIterator_& operator ++();\r
-    MatConstIterator_ operator ++(int);\r
-    Point pos() const;\r
-\r
-protected:\r
-    const Mat_<_Tp>* m;\r
-    _Tp* ptr;\r
-    _Tp* sliceEnd;\r
-};\r
-\r
-\r
-template<typename _Tp>\r
-class CV_EXPORTS MatIterator_ : public MatConstIterator_<_Tp>\r
-{\r
-public:\r
-    typedef _Tp* pointer;\r
-    typedef _Tp& reference;\r
-    typedef std::random_access_iterator_tag iterator_category;\r
-\r
-    MatIterator_();\r
-    MatIterator_(Mat_<_Tp>* _m);\r
-    MatIterator_(Mat_<_Tp>* _m, int _row, int _col=0);\r
-    MatIterator_(const Mat_<_Tp>* _m, Point _pt);\r
-    MatIterator_(const MatIterator_& it);\r
-    MatIterator_& operator = (const MatIterator_<_Tp>& it );\r
-\r
-    _Tp& operator *() const;\r
-    _Tp& operator [](int i) const;\r
-\r
-    MatIterator_& operator += (int ofs);\r
-    MatIterator_& operator -= (int ofs);\r
-    MatIterator_& operator --();\r
-    MatIterator_ operator --(int);\r
-    MatIterator_& operator ++();\r
-    MatIterator_ operator ++(int);\r
-};\r
-\r
-template<typename _Tp> class CV_EXPORTS MatOp_Iter_;\r
-\r
-template<typename _Tp> class CV_EXPORTS MatCommaInitializer_ :\r
-    public MatExpr_<MatExpr_Op1_<MatIterator_<_Tp>, Mat_<_Tp>, MatOp_Iter_<_Tp> >, Mat_<_Tp> >\r
-{\r
-public:\r
-    MatCommaInitializer_(Mat_<_Tp>* _m);\r
-    template<typename T2> MatCommaInitializer_<_Tp>& operator , (T2 v);\r
-    operator Mat_<_Tp>() const;\r
-    Mat_<_Tp> operator *() const;\r
-    void assignTo(Mat& m, int type=-1) const;\r
-};\r
-\r
-template<typename _Tp> class VectorCommaInitializer_\r
-{\r
-public:\r
-    VectorCommaInitializer_(Vector<_Tp>* _vec);\r
-    template<typename T2> VectorCommaInitializer_<_Tp>& operator , (T2 val);\r
-    operator Vector<_Tp>() const;\r
-    Vector<_Tp> operator *() const;\r
-\r
-protected:\r
-    Vector<_Tp>* vec;\r
-    int idx;\r
-};\r
-\r
-template<typename _Tp, size_t fixed_size=4096/sizeof(_Tp)+8> class CV_EXPORTS AutoBuffer\r
-{\r
-public:\r
-    typedef _Tp value_type;\r
-\r
-    AutoBuffer();\r
-    AutoBuffer(size_t _size);\r
-    ~AutoBuffer();\r
-\r
-    void allocate(size_t _size);\r
-    void deallocate();\r
-    operator _Tp* ();\r
-    operator const _Tp* () const;\r
-\r
-protected:\r
-    _Tp* ptr;\r
-    size_t size;\r
-    _Tp buf[fixed_size];\r
-};\r
-\r
-/////////////////////////// multi-dimensional dense matrix //////////////////////////\r
-\r
-class MatND;\r
-class SparseMat;\r
-\r
-class CV_EXPORTS MatND\r
-{\r
-public:\r
-    MatND();\r
-    MatND(const Vector<int>& _sizes, int _type);\r
-    MatND(const Vector<int>& _sizes, int _type, const Scalar& _s);\r
-    MatND(const MatND& m);\r
-    MatND(const MatND& m, const Vector<Range>& ranges);\r
-    MatND(const CvMatND* m, bool copyData=false);\r
-    //MatND( const MatExpr_BaseND& expr );\r
-    ~MatND();\r
-    MatND& operator = (const MatND& m);\r
-    //MatND& operator = (const MatExpr_BaseND& expr);\r
-\r
-    //operator MatExpr_<MatND, MatND>() const;\r
-\r
-    MatND clone() const;\r
-    MatND operator()(const Vector<Range>& ranges) const;\r
-\r
-    void copyTo( MatND& m ) const;\r
-    void copyTo( MatND& m, const MatND& mask ) const;\r
-    void convertTo( MatND& m, int rtype, double alpha=1, double beta=0 ) const;\r
-\r
-    void assignTo( MatND& m, int type=-1 ) const;\r
-    MatND& operator = (const Scalar& s);\r
-    MatND& setTo(const Scalar& s, const MatND& mask=MatND());\r
-    MatND reshape(int newcn, const Vector<int>& newsz=Vector<int>()) const;\r
-\r
-    void create(const Vector<int>& _sizes, int _type);\r
-    void addref();\r
-    void release();\r
-\r
-    operator Mat() const;\r
-    operator CvMatND() const;\r
-    bool isContinuous() const;\r
-    size_t elemSize() const;\r
-    size_t elemSize1() const;\r
-    int type() const;\r
-    int depth() const;\r
-    int channels() const;\r
-    size_t step(int i) const;\r
-    size_t step1(int i) const;\r
-    Vector<int> size() const;\r
-    int size(int i) const;\r
-\r
-    uchar* ptr(int i0);\r
-    const uchar* ptr(int i0) const;\r
-    uchar* ptr(int i0, int i1);\r
-    const uchar* ptr(int i0, int i1) const;\r
-    uchar* ptr(int i0, int i1, int i2);\r
-    const uchar* ptr(int i0, int i1, int i2) const;\r
-    uchar* ptr(const int* idx);\r
-    const uchar* ptr(const int* idx) const;\r
-\r
-    enum { MAGIC_VAL=0x42FE0000, AUTO_STEP=-1,\r
-        CONTINUOUS_FLAG=CV_MAT_CONT_FLAG, MAX_DIM=CV_MAX_DIM };\r
-\r
-    int flags;\r
-    int dims;\r
-\r
-    int* refcount;\r
-    uchar* data;\r
-    uchar* datastart;\r
-    uchar* dataend;\r
-\r
-    struct\r
-    {\r
-        int size;\r
-        size_t step;\r
-    }\r
-    dim[MAX_DIM];\r
-};\r
-\r
-class CV_EXPORTS NAryMatNDIterator\r
-{\r
-public:\r
-    NAryMatNDIterator();\r
-    NAryMatNDIterator(const Vector<MatND>& arrays);\r
-    void init(const Vector<MatND>& arrays);\r
-\r
-    NAryMatNDIterator& operator ++();\r
-    NAryMatNDIterator operator ++(int);\r
-    \r
-    Vector<MatND> arrays;\r
-    Vector<Mat> planes;\r
-\r
-    int nplanes;\r
-protected:\r
-    int iterdepth, idx;\r
-};\r
-\r
-CV_EXPORTS void add(const MatND& a, const MatND& b, MatND& c, const MatND& mask);\r
-CV_EXPORTS void subtract(const MatND& a, const MatND& b, MatND& c, const MatND& mask);\r
-CV_EXPORTS void add(const MatND& a, const MatND& b, MatND& c);\r
-CV_EXPORTS void subtract(const MatND& a, const MatND& b, MatND& c);\r
-CV_EXPORTS void add(const MatND& a, const Scalar& s, MatND& c, const MatND& mask=MatND());\r
-\r
-CV_EXPORTS void multiply(const MatND& a, const MatND& b, MatND& c, double scale=1);\r
-CV_EXPORTS void divide(const MatND& a, const MatND& b, MatND& c, double scale=1);\r
-CV_EXPORTS void divide(double scale, const MatND& b, MatND& c);\r
-\r
-CV_EXPORTS void subtract(const Scalar& s, const MatND& a, MatND& c, const MatND& mask=MatND());\r
-CV_EXPORTS void scaleAdd(const MatND& a, double alpha, const MatND& b, MatND& c);\r
-CV_EXPORTS void addWeighted(const MatND& a, double alpha, const MatND& b,\r
-                            double beta, double gamma, MatND& c);\r
-\r
-CV_EXPORTS Scalar sum(const MatND& m);\r
-CV_EXPORTS int countNonZero( const MatND& m );\r
-\r
-CV_EXPORTS Scalar mean(const MatND& m);\r
-CV_EXPORTS Scalar mean(const MatND& m, const MatND& mask);\r
-CV_EXPORTS void meanStdDev(const MatND& m, Scalar& mean, Scalar& stddev, const MatND& mask=MatND());\r
-CV_EXPORTS double norm(const MatND& a, int normType=NORM_L2, const MatND& mask=MatND());\r
-CV_EXPORTS double norm(const MatND& a, const MatND& b,\r
-                       int normType=NORM_L2, const MatND& mask=MatND());\r
-CV_EXPORTS void normalize( const MatND& a, MatND& b, double alpha=1, double beta=0,\r
-                           int norm_type=NORM_L2, int rtype=-1, const MatND& mask=MatND());\r
-\r
-CV_EXPORTS void minMaxLoc(const MatND& a, double* minVal,\r
-                       double* maxVal, int* minIdx=0, int* maxIdx=0,\r
-                       const MatND& mask=MatND());\r
-CV_EXPORTS void merge(const Vector<MatND>& mv, MatND& dst);\r
-CV_EXPORTS void split(const MatND& m, Vector<MatND>& mv);\r
-CV_EXPORTS void mixChannels(const Vector<MatND>& src, Vector<MatND>& dst,\r
-                            const Vector<int>& fromTo);\r
-\r
-CV_EXPORTS void bitwise_and(const MatND& a, const MatND& b, MatND& c, const MatND& mask=MatND());\r
-CV_EXPORTS void bitwise_or(const MatND& a, const MatND& b, MatND& c, const MatND& mask=MatND());\r
-CV_EXPORTS void bitwise_xor(const MatND& a, const MatND& b, MatND& c, const MatND& mask=MatND());\r
-CV_EXPORTS void bitwise_and(const MatND& a, const Scalar& s, MatND& c, const MatND& mask=MatND());\r
-CV_EXPORTS void bitwise_or(const MatND& a, const Scalar& s, MatND& c, const MatND& mask=MatND());\r
-CV_EXPORTS void bitwise_xor(const MatND& a, const Scalar& s, MatND& c, const MatND& mask=MatND());\r
-CV_EXPORTS void bitwise_not(const MatND& a, MatND& c);\r
-CV_EXPORTS void absdiff(const MatND& a, const MatND& b, MatND& c);\r
-CV_EXPORTS void absdiff(const MatND& a, const Scalar& s, MatND& c);\r
-CV_EXPORTS void inRange(const MatND& src, const MatND& lowerb,\r
-                        const MatND& upperb, MatND& dst);\r
-CV_EXPORTS void inRange(const MatND& src, const Scalar& lowerb,\r
-                        const Scalar& upperb, MatND& dst);\r
-CV_EXPORTS void compare(const MatND& a, const MatND& b, MatND& c, int cmpop);\r
-CV_EXPORTS void compare(const MatND& a, double s, MatND& c, int cmpop);\r
-CV_EXPORTS void min(const MatND& a, const MatND& b, MatND& c);\r
-CV_EXPORTS void min(const MatND& a, double alpha, MatND& c);\r
-CV_EXPORTS void max(const MatND& a, const MatND& b, MatND& c);\r
-CV_EXPORTS void max(const MatND& a, double alpha, MatND& c);\r
-\r
-CV_EXPORTS void sqrt(const MatND& a, MatND& b);\r
-CV_EXPORTS void pow(const MatND& a, double power, MatND& b);\r
-CV_EXPORTS void exp(const MatND& a, MatND& b);\r
-CV_EXPORTS void log(const MatND& a, MatND& b);\r
-CV_EXPORTS bool checkRange(const MatND& a, bool quiet=true, int* idx=0,\r
-                           double minVal=-DBL_MAX, double maxVal=DBL_MAX);\r
-\r
-typedef void (*ConvertData)(const void* from, void* to, int cn);\r
-typedef void (*ConvertScaleData)(const void* from, void* to, int cn, double alpha, double beta);\r
-\r
-CV_EXPORTS ConvertData getConvertElem(int fromType, int toType);\r
-CV_EXPORTS ConvertScaleData getConvertScaleElem(int fromType, int toType);\r
-\r
-template<typename _Tp> class CV_EXPORTS MatND_ : public MatND\r
-{\r
-public:\r
-    typedef _Tp value_type;\r
-    typedef typename DataType<_Tp>::channel_type channel_type;\r
-\r
-    MatND_();\r
-    MatND_(const Vector<int>& _sizes);\r
-    MatND_(const Vector<int>& _sizes, const _Tp& _s);\r
-    MatND_(const MatND& m);\r
-    MatND_(const MatND_& m);\r
-    MatND_(const MatND_& m, const Vector<Range>& ranges);\r
-    MatND_(const CvMatND* m, bool copyData=false);\r
-    MatND_& operator = (const MatND& m);\r
-    MatND_& operator = (const MatND_& m);\r
-    MatND_& operator = (const _Tp& s);\r
-\r
-    void create(const Vector<int>& _sizes);\r
-    template<typename T2> operator MatND_<T2>() const;\r
-    MatND_ clone() const;\r
-    MatND_ operator()(const Vector<Range>& ranges) const;\r
-\r
-    size_t elemSize() const;\r
-    size_t elemSize1() const;\r
-    int type() const;\r
-    int depth() const;\r
-    int channels() const;\r
-    size_t stepT(int i) const;\r
-    size_t step1(int i) const;\r
-\r
-    _Tp& operator ()(const int* idx);\r
-    const _Tp& operator ()(const int* idx) const;\r
-\r
-    _Tp& operator ()(int idx0, int idx1, int idx2);\r
-    const _Tp& operator ()(int idx0, int idx1, int idx2) const;\r
-};\r
-\r
-/////////////////////////// multi-dimensional sparse matrix //////////////////////////\r
-\r
-class SparseMatIterator;\r
-class SparseMatConstIterator;\r
-\r
-class CV_EXPORTS SparseMat\r
-{\r
-public:\r
-    typedef SparseMatIterator iterator;\r
-    typedef SparseMatConstIterator const_iterator;\r
-\r
-    struct CV_EXPORTS Hdr\r
-    {\r
-        Hdr(const Vector<int>& _sizes, int _type);\r
-        void clear();\r
-        int refcount;\r
-        int dims;\r
-        int valueOffset;\r
-        size_t nodeSize;\r
-        size_t nodeCount;\r
-        size_t freeList;\r
-        Vector<uchar> pool;\r
-        Vector<size_t> hashtab;\r
-        int size[CV_MAX_DIM];\r
-    };\r
-\r
-    struct CV_EXPORTS Node\r
-    {\r
-        size_t hashval;\r
-        size_t next;\r
-        int idx[CV_MAX_DIM];\r
-    };\r
-\r
-    SparseMat();\r
-    SparseMat(const Vector<int>& _sizes, int _type);\r
-    SparseMat(const SparseMat& m);\r
-    SparseMat(const Mat& m, bool try1d=false);\r
-    SparseMat(const MatND& m);\r
-    SparseMat(const CvSparseMat* m);\r
-    ~SparseMat();\r
-    SparseMat& operator = (const SparseMat& m);\r
-    SparseMat& operator = (const Mat& m);\r
-    SparseMat& operator = (const MatND& m);\r
-\r
-    SparseMat clone() const;\r
-    void copyTo( SparseMat& m ) const;\r
-    void copyTo( Mat& m ) const;\r
-    void copyTo( MatND& m ) const;\r
-    void convertTo( SparseMat& m, int rtype, double alpha=1 ) const;\r
-    void convertTo( Mat& m, int rtype, double alpha=1, double beta=0 ) const;\r
-    void convertTo( MatND& m, int rtype, double alpha=1, double beta=0 ) const;\r
-\r
-    void assignTo( SparseMat& m, int type=-1 ) const;\r
-\r
-    void create(const Vector<int>& _sizes, int _type);\r
-    void clear();\r
-    void addref();\r
-    void release();\r
-\r
-    operator CvSparseMat*() const;\r
-    size_t elemSize() const;\r
-    size_t elemSize1() const;\r
-    int type() const;\r
-    int depth() const;\r
-    int channels() const;\r
-    Vector<int> size() const;\r
-    int size(int i) const;\r
-    int dims() const;\r
-    size_t nzcount() const;\r
-    \r
-    size_t hash(int i0) const;\r
-    size_t hash(int i0, int i1) const;\r
-    size_t hash(int i0, int i1, int i2) const;\r
-    size_t hash(const int* idx) const;\r
-    \r
-    uchar* ptr(int i0, int i1, bool createMissing, size_t* hashval=0);\r
-    const uchar* get(int i0, int i1, size_t* hashval=0) const;\r
-    uchar* ptr(int i0, int i1, int i2, bool createMissing, size_t* hashval=0);\r
-    const uchar* get(int i0, int i1, int i2, size_t* hashval=0) const;\r
-    uchar* ptr(const int* idx, bool createMissing, size_t* hashval=0);\r
-    const uchar* get(const int* idx, size_t* hashval=0) const;\r
-\r
-    void erase(int i0, int i1, size_t* hashval=0);\r
-    void erase(int i0, int i1, int i2, size_t* hashval=0);\r
-    void erase(const int* idx, size_t* hashval=0);\r
-\r
-    SparseMatIterator begin();\r
-    SparseMatConstIterator begin() const;\r
-    SparseMatIterator end();\r
-    SparseMatConstIterator end() const;\r
-\r
-    uchar* value(Node* n);\r
-    const uchar* value(const Node* n) const;\r
-    Node* node(size_t nidx);\r
-    const Node* node(size_t nidx) const;\r
-\r
-    uchar* newNode(const int* idx, size_t hashval);\r
-    void removeNode(size_t hidx, size_t nidx, size_t previdx);\r
-    void resizeHashTab(size_t newsize);\r
-\r
-    enum { MAGIC_VAL=0x42FD0000, MAX_DIM=CV_MAX_DIM, HASH_SCALE=0x5bd1e995, HASH_BIT=0x80000000 };\r
-\r
-    int flags;\r
-    Hdr* hdr;\r
-};\r
-\r
-\r
-CV_EXPORTS void minMaxLoc(const SparseMat& a, double* minVal,\r
-                          double* maxVal, int* minIdx=0, int* maxIdx=0);\r
-CV_EXPORTS double norm( const SparseMat& src, int normType );\r
-CV_EXPORTS void normalize( const SparseMat& src, SparseMat& dst, double alpha, int normType );\r
-\r
-class CV_EXPORTS SparseMatConstIterator\r
-{\r
-public:\r
-    SparseMatConstIterator();\r
-    SparseMatConstIterator(const SparseMat* _m);\r
-    SparseMatConstIterator(const SparseMatConstIterator& it);\r
-\r
-    SparseMatConstIterator& operator = (const SparseMatConstIterator& it);\r
-    const uchar* value() const;\r
-    const SparseMat::Node* node() const;\r
-    \r
-    SparseMatConstIterator& operator --();\r
-    SparseMatConstIterator operator --(int);\r
-    SparseMatConstIterator& operator ++();\r
-    SparseMatConstIterator operator ++(int);\r
-\r
-    const SparseMat* m;\r
-    size_t hashidx;\r
-    uchar* ptr;\r
-};\r
-\r
-class CV_EXPORTS SparseMatIterator : public SparseMatConstIterator\r
-{\r
-public:\r
-    SparseMatIterator();\r
-    SparseMatIterator(SparseMat* _m);\r
-    SparseMatIterator(SparseMat* _m, const int* idx);\r
-    SparseMatIterator(const SparseMatIterator& it);\r
-\r
-    SparseMatIterator& operator = (const SparseMatIterator& it);\r
-    uchar* value() const;\r
-    SparseMat::Node* node() const;\r
-    \r
-    SparseMatIterator& operator ++();\r
-    SparseMatIterator operator ++(int);\r
-};\r
-\r
-\r
-template<typename _Tp> class SparseMatIterator_;\r
-template<typename _Tp> class SparseMatConstIterator_;\r
-\r
-template<typename _Tp> class CV_EXPORTS SparseMat_ : public SparseMat\r
-{\r
-public:\r
-    typedef SparseMatIterator_<_Tp> iterator;\r
-    typedef SparseMatConstIterator_<_Tp> const_iterator;\r
-\r
-    SparseMat_();\r
-    SparseMat_(const Vector<int>& _sizes);\r
-    SparseMat_(const SparseMat& m);\r
-    SparseMat_(const SparseMat_& m);\r
-    SparseMat_(const Mat& m);\r
-    SparseMat_(const MatND& m);\r
-    SparseMat_(const CvSparseMat* m);\r
-    SparseMat_& operator = (const SparseMat& m);\r
-    SparseMat_& operator = (const SparseMat_& m);\r
-    SparseMat_& operator = (const Mat& m);\r
-    SparseMat_& operator = (const MatND& m);\r
-\r
-    SparseMat_ clone() const;\r
-    void create(const Vector<int>& _sizes);\r
-    operator CvSparseMat*() const;\r
-\r
-    int type() const;\r
-    int depth() const;\r
-    int channels() const;\r
-    \r
-    _Tp& operator()(int i0, int i1, size_t* hashval=0);\r
-    _Tp operator()(int i0, int i1, size_t* hashval=0) const;\r
-    _Tp& operator()(int i0, int i1, int i2, size_t* hashval=0);\r
-    _Tp operator()(int i0, int i1, int i2, size_t* hashval=0) const;\r
-    _Tp& operator()(const int* idx, size_t* hashval=0);\r
-    _Tp operator()(const int* idx, size_t* hashval=0) const;\r
-\r
-    SparseMatIterator_<_Tp> begin();\r
-    SparseMatConstIterator_<_Tp> begin() const;\r
-    SparseMatIterator_<_Tp> end();\r
-    SparseMatConstIterator_<_Tp> end() const;\r
-};\r
-\r
-template<typename _Tp> class CV_EXPORTS SparseMatConstIterator_ : public SparseMatConstIterator\r
-{\r
-public:\r
-    typedef std::forward_iterator_tag iterator_category;\r
-    \r
-    SparseMatConstIterator_();\r
-    SparseMatConstIterator_(const SparseMat_<_Tp>* _m);\r
-    SparseMatConstIterator_(const SparseMatConstIterator_& it);\r
-\r
-    SparseMatConstIterator_& operator = (const SparseMatConstIterator_& it);\r
-    const _Tp& operator *() const;\r
-    \r
-    SparseMatConstIterator_& operator ++();\r
-    SparseMatConstIterator_ operator ++(int);\r
-\r
-protected:\r
-    const SparseMat_<_Tp>* m;\r
-    size_t hashidx;\r
-    uchar* ptr;\r
-};\r
-\r
-template<typename _Tp> class CV_EXPORTS SparseMatIterator_ : public SparseMatConstIterator_<_Tp>\r
-{\r
-public:\r
-    typedef std::forward_iterator_tag iterator_category;\r
-    \r
-    SparseMatIterator_();\r
-    SparseMatIterator_(SparseMat_<_Tp>* _m);\r
-    SparseMatIterator_(const SparseMatIterator_& it);\r
-\r
-    SparseMatIterator_& operator = (const SparseMatIterator_& it);\r
-    _Tp& operator *() const;\r
-    \r
-    SparseMatIterator_& operator ++();\r
-    SparseMatIterator_ operator ++(int);\r
-};\r
-\r
-//////////////////// Fast Nearest-Neighbor Search Structure ////////////////////\r
-\r
-class CV_EXPORTS KDTree\r
-{\r
-public:\r
-    struct Node\r
-    {\r
-        Node() : idx(-1), left(-1), right(-1), boundary(0.f) {}\r
-        Node(int _idx, int _left, int _right, float _boundary)\r
-            : idx(_idx), left(_left), right(_right), boundary(_boundary) {}\r
-        int idx;            // split dimension; >=0 for nodes (dim),\r
-                            // < 0 for leaves (index of the point)\r
-        int left, right;    // node indices of left and right branches\r
-        float boundary;     // left if vec[dim]<=boundary, otherwise right\r
-    };\r
-\r
-    KDTree();\r
-    KDTree(const Mat& _points, bool copyPoints=true);\r
-    void build(const Mat& _points, bool copyPoints=true);\r
-\r
-    void findNearest(const Mat& vec, int K, int Emax, Vector<int>* neighborsIdx,\r
-        Mat* neighbors=0, Vector<float>* dist=0) const;\r
-    void findNearest(const Vector<float>& vec, int K, int Emax, Vector<int>* neighborsIdx,\r
-        Vector<float>* neighbors=0, Vector<float>* dist=0) const;\r
-    void findOrthoRange(const Mat& minBounds, const Mat& maxBounds,\r
-        Vector<int>* neighborsIdx, Mat* neighbors=0) const;\r
-    void findOrthoRange(const Vector<float>& minBounds, const Vector<float>& maxBounds,\r
-        Vector<int>* neighborsIdx, Vector<float>* neighbors=0) const;\r
-    void getPoints(const Vector<int>& ids, Mat& pts) const;\r
-    void getPoints(const Vector<int>& ids, Vector<float>& pts) const;\r
-    Vector<float> at(int ptidx, bool copyData=false) const;\r
-\r
-    Vector<Node> nodes;\r
-    Mat points;\r
-    int maxDepth;\r
-};\r
-\r
-//////////////////////////////////////// XML & YAML I/O ////////////////////////////////////\r
-\r
-class CV_EXPORTS FileNode;\r
-\r
-class CV_EXPORTS FileStorage\r
-{\r
-public:\r
-    enum { READ=0, WRITE=1, APPEND=2 };\r
-    enum { UNDEFINED=0, VALUE_EXPECTED=1, NAME_EXPECTED=2, INSIDE_MAP=4 };\r
-    FileStorage();\r
-    FileStorage(const String& filename, int flags);\r
-    FileStorage(CvFileStorage* fs);\r
-    virtual ~FileStorage();\r
-\r
-    virtual bool open(const String& filename, int flags);\r
-    virtual bool isOpened() const;\r
-    virtual void release();\r
-\r
-    FileNode getFirstTopLevelNode() const;\r
-    FileNode root(int streamidx=0) const;\r
-    FileNode operator[](const String& nodename) const;\r
-    FileNode operator[](const char* nodename) const;\r
-\r
-    CvFileStorage* operator *() { return fs; }\r
-    const CvFileStorage* operator *() const { return fs; }\r
-    void writeRaw( const String& fmt, const Vector<uchar>& vec );\r
-    void writeObj( const String& name, const void* obj );\r
-\r
-    static String getDefaultObjectName(const String& filename);\r
-\r
-    Ptr<CvFileStorage> fs;\r
-    String elname;\r
-    Vector<char> structs;\r
-    int state;\r
-};\r
-\r
-class CV_EXPORTS FileNodeIterator;\r
-\r
-class CV_EXPORTS FileNode\r
-{\r
-public:\r
-    enum { NONE=0, INT=1, REAL=2, FLOAT=REAL, STR=3, STRING=STR, REF=4, SEQ=5, MAP=6, TYPE_MASK=7,\r
-        FLOW=8, USER=16, EMPTY=32, NAMED=64 };\r
-    FileNode();\r
-    FileNode(const CvFileStorage* fs, const CvFileNode* node);\r
-    FileNode(const FileNode& node);\r
-    FileNode operator[](const String& nodename) const;\r
-    FileNode operator[](const char* nodename) const;\r
-    FileNode operator[](int i) const;\r
-    int type() const;\r
-    int rawDataSize(const String& fmt) const;\r
-    bool isNone() const;\r
-    bool isSeq() const;\r
-    bool isMap() const;\r
-    bool isInt() const;\r
-    bool isReal() const;\r
-    bool isString() const;\r
-    bool isNamed() const;\r
-    String name() const;\r
-    size_t count() const;\r
-    operator int() const;\r
-    operator float() const;\r
-    operator double() const;\r
-    operator String() const;\r
-\r
-    FileNodeIterator begin() const;\r
-    FileNodeIterator end() const;\r
-\r
-    void readRaw( const String& fmt, Vector<uchar>& vec ) const;\r
-    void* readObj() const;\r
-\r
-    // do not use wrapper pointer classes for better efficiency\r
-    const CvFileStorage* fs;\r
-    const CvFileNode* node;\r
-};\r
-\r
-class CV_EXPORTS FileNodeIterator\r
-{\r
-public:\r
-    FileNodeIterator();\r
-    FileNodeIterator(const CvFileStorage* fs, const CvFileNode* node, size_t ofs=0);\r
-    FileNodeIterator(const FileNodeIterator& it);\r
-    FileNode operator *() const;\r
-    FileNode operator ->() const;\r
-\r
-    FileNodeIterator& operator ++();\r
-    FileNodeIterator operator ++(int);\r
-    FileNodeIterator& operator --();\r
-    FileNodeIterator operator --(int);\r
-    FileNodeIterator& operator += (int);\r
-    FileNodeIterator& operator -= (int);\r
-\r
-    FileNodeIterator& readRaw( const String& fmt, Vector<uchar>& vec,\r
-                               size_t maxCount=(size_t)INT_MAX );\r
-\r
-    const CvFileStorage* fs;\r
-    const CvFileNode* container;\r
-    CvSeqReader reader;\r
-    size_t remaining;\r
-};\r
-\r
-////////////// convenient wrappers for operating old-style dynamic structures //////////////\r
-\r
-// !!! NOTE that the wrappers are "thin", i.e. they do not call\r
-// any element constructors/destructors\r
-\r
-template<typename _Tp> class SeqIterator;\r
-\r
-template<> inline void Ptr<CvMemStorage>::delete_obj()\r
-{ cvReleaseMemStorage(&obj); }\r
-\r
-typedef Ptr<CvMemStorage> MemStorage;\r
-\r
-template<typename _Tp> class CV_EXPORTS Seq\r
-{\r
-public:\r
-    Seq();\r
-    Seq(const CvSeq* seq);\r
-    Seq(const MemStorage& storage, int headerSize = sizeof(CvSeq));\r
-    _Tp& operator [](int idx);\r
-    const _Tp& operator[](int idx) const;\r
-    SeqIterator<_Tp> begin() const;\r
-    SeqIterator<_Tp> end() const;\r
-    size_t size() const;\r
-    int type() const;\r
-    int depth() const;\r
-    int channels() const;\r
-    size_t elemSize() const;\r
-    size_t index(const _Tp& elem) const;\r
-    void push_back(const _Tp& elem);\r
-    void push_front(const _Tp& elem);\r
-    _Tp& front();\r
-    const _Tp& front() const;\r
-    _Tp& back();\r
-    const _Tp& back() const;\r
-    bool empty() const;\r
-\r
-    void clear();\r
-    void pop_front();\r
-    void pop_back();\r
-\r
-    void copyTo(Vector<_Tp>& vec, const Range& range=Range::all()) const;\r
-    operator Vector<_Tp>() const;\r
-    \r
-    CvSeq* seq;\r
-};\r
-\r
-template<typename _Tp> class CV_EXPORTS SeqIterator : public CvSeqReader\r
-{\r
-public:\r
-    SeqIterator();\r
-    SeqIterator(const Seq<_Tp>& seq, bool seekEnd=false);\r
-    void seek(size_t pos);\r
-    size_t tell() const;\r
-    _Tp& operator *();\r
-    const _Tp& operator *() const;\r
-    SeqIterator& operator ++();\r
-    SeqIterator operator ++(int) const;\r
-    SeqIterator& operator --();\r
-    SeqIterator operator --(int) const;\r
-\r
-    SeqIterator& operator +=(int);\r
-    SeqIterator& operator -=(int);\r
-\r
-    // this is index of the current element module seq->total*2\r
-    // (to distinguish between 0 and seq->total)\r
-    int index;\r
-};\r
-\r
-}\r
-\r
-#endif // __cplusplus\r
-\r
-#include "cxoperations.hpp"\r
-#include "cxmat.hpp"\r
-\r
-#endif /*_CXCORE_HPP_*/\r
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+//  By downloading, copying, installing or using the software you agree to this license.
+//  If you do not agree to this license, do not download, install,
+//  copy or use the software.
+//
+//
+//                           License Agreement
+//                For Open Source Computer Vision Library
+//
+// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
+// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+//   * Redistribution's of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//
+//   * Redistribution's in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//
+//   * The name of the copyright holders may not be used to endorse or promote products
+//     derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+#ifndef _CXCORE_HPP_
+#define _CXCORE_HPP_
+
+#include "cxmisc.h"
+
+#ifdef __cplusplus
+
+#ifndef SKIP_INCLUDES
+#include <algorithm>
+#include <complex>
+#include <map>
+#include <new>
+#include <string>
+#include <vector>
+#endif // SKIP_INCLUDES
+
+namespace cv {
+
+template<typename _Tp> class CV_EXPORTS Size_;
+template<typename _Tp> class CV_EXPORTS Point_;
+template<typename _Tp> class CV_EXPORTS Rect_;
+
+typedef std::string String;
+typedef std::basic_string<wchar_t> WString;
+
+CV_EXPORTS String fromUtf16(const WString& str);
+CV_EXPORTS WString toUtf16(const String& str);
+
+class CV_EXPORTS Exception
+{
+public:
+    Exception() { code = 0; line = 0; }
+    Exception(int _code, const String& _err, const String& _func, const String& _file, int _line)
+        : code(_code), err(_err), func(_func), file(_file), line(_line) {}
+    Exception(const Exception& exc)
+        : code(exc.code), err(exc.err), func(exc.func), file(exc.file), line(exc.line) {}
+    Exception& operator = (const Exception& exc)
+    {
+        if( this != &exc )
+        {
+            code = exc.code; err = exc.err; func = exc.func; file = exc.file; line = exc.line;
+        }
+        return *this;
+    }
+
+    int code;
+    String err;
+    String func;
+    String file;
+    int line;
+};
+
+CV_EXPORTS String format( const char* fmt, ... );
+CV_EXPORTS void error( const Exception& exc );
+
+#ifdef __GNUC__
+#define CV_Error( code, msg ) cv::error( cv::Exception(code, msg, __func__, __FILE__, __LINE__) )
+#define CV_Error_( code, args ) cv::error( cv::Exception(code, cv::format args, __func__, __FILE__, __LINE__) )
+#define CV_Assert( expr ) { if(!(expr)) cv::error( cv::Exception(CV_StsAssert, #expr, __func__, __FILE__, __LINE__) ); }
+#else
+#define CV_Error( code, msg ) cv::error( cv::Exception(code, msg, "", __FILE__, __LINE__) )
+#define CV_Error_( code, args ) cv::error( cv::Exception(code, cv::format args, "", __FILE__, __LINE__) )
+#define CV_Assert( expr ) { if(!(expr)) cv::error( cv::Exception(CV_StsAssert, #expr, "", __FILE__, __LINE__) ); }
+#endif
+    
+#ifdef _DEBUG
+#define CV_DbgAssert(expr) CV_Assert(expr)
+#else
+#define CV_DbgAssert(expr)
+#endif
+
+CV_EXPORTS void setNumThreads(int);
+CV_EXPORTS int getNumThreads();
+CV_EXPORTS int getThreadNum();
+
+CV_EXPORTS int64 getTickCount();
+CV_EXPORTS double getTickFrequency();
+
+CV_EXPORTS void* fastMalloc(size_t);
+CV_EXPORTS void fastFree(void* ptr);
+
+template<typename _Tp> static inline _Tp* allocate(size_t n)
+{
+    _Tp* ptr = (_Tp*)fastMalloc(n*sizeof(ptr[0]));
+    ::new(ptr) _Tp[n];
+    return ptr;
+}
+
+template<typename _Tp> static inline void deallocate(_Tp* ptr, size_t n)
+{
+    for( size_t i = 0; i < n; i++ ) (ptr+i)->~_Tp();
+    fastFree(ptr);
+}
+
+template<typename _Tp> static inline _Tp* alignPtr(_Tp* ptr, int n=(int)sizeof(_Tp))
+{
+    return (_Tp*)(((size_t)ptr + n-1) & -n);
+}
+
+static inline size_t alignSize(size_t sz, int n)
+{
+    return (sz + n-1) & -n;
+}
+
+CV_EXPORTS void setUseOptimized(bool);
+CV_EXPORTS bool useOptimized();
+
+template<typename _Tp> class CV_EXPORTS Allocator
+{
+public: 
+    typedef _Tp value_type;
+    typedef value_type* pointer;
+    typedef const value_type* const_pointer;
+    typedef value_type& reference;
+    typedef const value_type& const_reference;
+    typedef size_t size_type;
+    typedef ptrdiff_t difference_type;
+    template<typename U> class rebind { typedef Allocator<U> other; };
+
+    explicit Allocator() {}
+    ~Allocator() {}
+    explicit Allocator(Allocator const&) {}
+    template<typename U>
+    explicit Allocator(Allocator<U> const&) {}
+
+    // address
+    pointer address(reference r) { return &r; }
+    const_pointer address(const_reference r) { return &r; }
+
+    pointer allocate(size_type count, const void* =0)
+    { return reinterpret_cast<pointer>(fastMalloc(count * sizeof (_Tp))); }
+
+    void deallocate(pointer p, size_type) {fastFree(p); }
+
+    size_type max_size() const
+    { return max(static_cast<_Tp>(-1)/sizeof(_Tp), 1); }
+
+    void construct(pointer p, const _Tp& v) { new(static_cast<void*>(p)) _Tp(v); }
+    void destroy(pointer p) { p->~_Tp(); }
+};
+
+/////////////////////// Vec (used as element of multi-channel images ///////////////////// 
+
+template<typename _Tp> class CV_EXPORTS DataDepth { public: enum { value = -1, fmt=(int)'\0' }; };
+
+template<> class DataDepth<bool> { public: enum { value = CV_8U, fmt=(int)'u' }; };
+template<> class DataDepth<uchar> { public: enum { value = CV_8U, fmt=(int)'u' }; };
+template<> class DataDepth<schar> { public: enum { value = CV_8S, fmt=(int)'c' }; };
+template<> class DataDepth<ushort> { public: enum { value = CV_16U, fmt=(int)'w' }; };
+template<> class DataDepth<short> { public: enum { value = CV_16S, fmt=(int)'s' }; };
+template<> class DataDepth<int> { public: enum { value = CV_32S, fmt=(int)'i' }; };
+template<> class DataDepth<float> { public: enum { value = CV_32F, fmt=(int)'f' }; };
+template<> class DataDepth<double> { public: enum { value = CV_64F, fmt=(int)'d' }; };
+template<typename _Tp> class DataDepth<_Tp*> { public: enum { value = CV_USRTYPE1, fmt=(int)'r' }; };
+
+template<typename _Tp, int cn> class CV_EXPORTS Vec
+{
+public:
+    typedef _Tp value_type;
+    enum { depth = DataDepth<_Tp>::value, channels = cn, type = CV_MAKETYPE(depth, channels) };
+    
+    Vec();
+    Vec(_Tp v0);
+    Vec(_Tp v0, _Tp v1);
+    Vec(_Tp v0, _Tp v1, _Tp v2);
+    Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3);
+    Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4);
+    Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5);
+    Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6);
+    Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7);
+    Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8);
+    Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8, _Tp v9);
+    Vec(const Vec<_Tp, cn>& v);
+    static Vec all(_Tp alpha);
+    _Tp dot(const Vec& v) const;
+    double ddot(const Vec& v) const;
+    Vec cross(const Vec& v) const;
+    template<typename T2> operator Vec<T2, cn>() const;
+    operator CvScalar() const;
+    _Tp operator [](int i) const;
+    _Tp& operator[](int i);
+
+    _Tp val[cn];
+};
+
+typedef Vec<uchar, 2> Vec2b;
+typedef Vec<uchar, 3> Vec3b;
+typedef Vec<uchar, 4> Vec4b;
+
+typedef Vec<short, 2> Vec2s;
+typedef Vec<short, 3> Vec3s;
+typedef Vec<short, 4> Vec4s;
+
+typedef Vec<int, 2> Vec2i;
+typedef Vec<int, 3> Vec3i;
+typedef Vec<int, 4> Vec4i;
+
+typedef Vec<float, 2> Vec2f;
+typedef Vec<float, 3> Vec3f;
+typedef Vec<float, 4> Vec4f;
+typedef Vec<float, 6> Vec6f;
+
+typedef Vec<double, 2> Vec2d;
+typedef Vec<double, 3> Vec3d;
+typedef Vec<double, 4> Vec4d;
+typedef Vec<double, 6> Vec6d;
+
+//////////////////////////////// Complex //////////////////////////////
+
+template<typename _Tp> class CV_EXPORTS Complex
+{
+public:
+    Complex();
+    Complex( _Tp _re, _Tp _im=0 );
+    Complex( const std::complex<_Tp>& c );
+    template<typename T2> operator Complex<T2>() const;
+    Complex conj() const;
+    operator std::complex<_Tp>() const;
+
+    _Tp re, im;
+};
+
+typedef Complex<float> Complexf;
+typedef Complex<double> Complexd;
+
+//////////////////////////////// Point_ ////////////////////////////////
+
+template<typename _Tp> class CV_EXPORTS Point_
+{
+public:
+    typedef _Tp value_type;
+    
+    Point_();
+    Point_(_Tp _x, _Tp _y);
+    Point_(const Point_& pt);
+    Point_(const CvPoint& pt);
+    Point_(const CvPoint2D32f& pt);
+    Point_(const Size_<_Tp>& sz);
+    Point_& operator = (const Point_& pt);
+    template<typename _Tp2> operator Point_<_Tp2>() const;
+    operator CvPoint() const;
+    operator CvPoint2D32f() const;
+
+    _Tp dot(const Point_& pt) const;
+    double ddot(const Point_& pt) const;
+    bool inside(const Rect_<_Tp>& r) const;
+    
+    _Tp x, y;
+};
+
+template<typename _Tp> class CV_EXPORTS Point3_
+{
+public:
+    typedef _Tp value_type;
+    
+    Point3_();
+    Point3_(_Tp _x, _Tp _y, _Tp _z);
+    Point3_(const Point3_& pt);
+       Point3_(const Point_<_Tp>& pt);
+    Point3_(const CvPoint3D32f& pt);
+    Point3_(const Vec<_Tp, 3>& t);
+    Point3_& operator = (const Point3_& pt);
+    template<typename _Tp2> operator Point3_<_Tp2>() const;
+    operator CvPoint3D32f() const;
+
+    _Tp dot(const Point3_& pt) const;
+    double ddot(const Point3_& pt) const;
+    
+    _Tp x, y, z;
+};
+
+//////////////////////////////// Size_ ////////////////////////////////
+
+template<typename _Tp> class CV_EXPORTS Size_
+{
+public:
+    typedef _Tp value_type;
+    
+    Size_();
+    Size_(_Tp _width, _Tp _height);
+    Size_(const Size_& sz);
+    Size_(const CvSize& sz);
+    Size_(const CvSize2D32f& sz);
+    Size_(const Point_<_Tp>& pt);
+    Size_& operator = (const Size_& sz);
+    _Tp area() const;
+
+    operator Size_<int>() const;
+    operator Size_<float>() const;
+    operator Size_<double>() const;
+    operator CvSize() const;
+    operator CvSize2D32f() const;
+
+    _Tp width, height;
+};
+
+//////////////////////////////// Rect_ ////////////////////////////////
+
+template<typename _Tp> class CV_EXPORTS Rect_
+{
+public:
+    typedef _Tp value_type;
+    
+    Rect_();
+    Rect_(_Tp _x, _Tp _y, _Tp _width, _Tp _height);
+    Rect_(const Rect_& r);
+    Rect_(const CvRect& r);
+    Rect_(const Point_<_Tp>& org, const Size_<_Tp>& sz);
+    Rect_(const Point_<_Tp>& pt1, const Point_<_Tp>& pt2);
+    Rect_& operator = ( const Rect_& r );
+    Point_<_Tp> tl() const;
+    Point_<_Tp> br() const;
+    
+    Size_<_Tp> size() const;
+    _Tp area() const;
+
+    operator Rect_<int>() const;
+    operator Rect_<float>() const;
+    operator Rect_<double>() const;
+    operator CvRect() const;
+
+    bool contains(const Point_<_Tp>& pt) const;
+
+    _Tp x, y, width, height;
+};
+
+typedef Point_<int> Point2i;
+typedef Point2i Point;
+typedef Size_<int> Size2i;
+typedef Size2i Size;
+typedef Rect_<int> Rect;
+typedef Point_<float> Point2f;
+typedef Point_<double> Point2d;
+typedef Size_<float> Size2f;
+typedef Point3_<int> Point3i;
+typedef Point3_<float> Point3f;
+typedef Point3_<double> Point3d;
+
+class CV_EXPORTS RotatedRect
+{
+public:
+    RotatedRect();
+    RotatedRect(const Point2f& _center, const Size2f& _size, float _angle);
+    RotatedRect(const CvBox2D& box);
+    Rect boundingRect() const;
+    operator CvBox2D() const;
+    Point2f center;
+    Size2f size;
+    float angle;
+};
+
+//////////////////////////////// Scalar_ ///////////////////////////////
+
+template<typename _Tp> class CV_EXPORTS Scalar_ : public Vec<_Tp, 4>
+{
+public:
+    Scalar_();
+    Scalar_(_Tp v0, _Tp v1, _Tp v2=0, _Tp v3=0);
+    Scalar_(const CvScalar& s);
+    Scalar_(_Tp v0);
+    static Scalar_<_Tp> all(_Tp v0);
+    operator CvScalar() const;
+
+    template<typename T2> operator Scalar_<T2>() const;
+
+    Scalar_<_Tp> mul(const Scalar_<_Tp>& t, double scale=1 ) const;
+    template<typename T2> void convertTo(T2* buf, int channels, int unroll_to=0) const;
+};
+
+typedef Scalar_<double> Scalar;
+
+//////////////////////////////// Range /////////////////////////////////
+
+class CV_EXPORTS Range
+{
+public:
+    Range();
+    Range(int _start, int _end);
+    Range(const CvSlice& slice);
+    int size() const;
+    bool empty() const;
+    static Range all();
+    operator CvSlice() const;
+
+    int start, end;
+};
+
+/////////////////////////////// DataType ////////////////////////////////
+
+template<typename _Tp> class DataType
+{
+public:
+    typedef _Tp value_type;
+    typedef value_type work_type;
+    typedef value_type channel_type;
+    enum { depth = DataDepth<channel_type>::value, channels = 1,
+           fmt=DataDepth<channel_type>::fmt,
+           type = CV_MAKETYPE(depth, channels) };
+};
+
+template<> class DataType<bool>
+{
+public:
+    typedef bool value_type;
+    typedef int work_type;
+    typedef value_type channel_type;
+    enum { depth = DataDepth<channel_type>::value, channels = 1,
+           fmt=DataDepth<channel_type>::fmt,
+           type = CV_MAKETYPE(depth, channels) };
+};
+
+template<> class DataType<uchar>
+{
+public:
+    typedef uchar value_type;
+    typedef int work_type;
+    typedef value_type channel_type;
+    enum { depth = DataDepth<channel_type>::value, channels = 1,
+           fmt=DataDepth<channel_type>::fmt,
+           type = CV_MAKETYPE(depth, channels) };
+};
+
+template<> class DataType<schar>
+{
+public:
+    typedef schar value_type;
+    typedef int work_type;
+    typedef value_type channel_type;
+    enum { depth = DataDepth<channel_type>::value, channels = 1,
+           fmt=DataDepth<channel_type>::fmt,
+           type = CV_MAKETYPE(depth, channels) };
+};
+
+template<> class DataType<ushort>
+{
+public:
+    typedef ushort value_type;
+    typedef int work_type;
+    typedef value_type channel_type;
+    enum { depth = DataDepth<channel_type>::value, channels = 1,
+           fmt=DataDepth<channel_type>::fmt,
+           type = CV_MAKETYPE(depth, channels) };
+};
+
+template<> class DataType<short>
+{
+public:
+    typedef short value_type;
+    typedef int work_type;
+    typedef value_type channel_type;
+    enum { depth = DataDepth<channel_type>::value, channels = 1,
+           fmt=DataDepth<channel_type>::fmt,
+           type = CV_MAKETYPE(depth, channels) };
+};
+
+template<> class DataType<int>
+{
+public:
+    typedef int value_type;
+    typedef value_type work_type;
+    typedef value_type channel_type;
+    enum { depth = DataDepth<channel_type>::value, channels = 1,
+           fmt=DataDepth<channel_type>::fmt,
+           type = CV_MAKETYPE(depth, channels) };
+};
+
+template<> class DataType<float>
+{
+public:
+    typedef float value_type;
+    typedef value_type work_type;
+    typedef value_type channel_type;
+    enum { depth = DataDepth<channel_type>::value, channels = 1,
+           fmt=DataDepth<channel_type>::fmt,
+           type = CV_MAKETYPE(depth, channels) };
+};
+
+template<> class DataType<double>
+{
+public:
+    typedef double value_type;
+    typedef value_type work_type;
+    typedef value_type channel_type;
+    enum { depth = DataDepth<channel_type>::value, channels = 1,
+           fmt=DataDepth<channel_type>::fmt,
+           type = CV_MAKETYPE(depth, channels) };
+};
+
+template<typename _Tp, int cn> class DataType<Vec<_Tp, cn> >
+{
+public:
+    typedef Vec<_Tp, cn> value_type;
+    typedef Vec<typename DataType<_Tp>::work_type, cn> work_type;
+    typedef _Tp channel_type;
+    enum { depth = DataDepth<channel_type>::value, channels = cn,
+           fmt = ((channels-1)<<8) + DataDepth<channel_type>::fmt,
+           type = CV_MAKETYPE(depth, channels) };
+};
+
+template<typename _Tp> class DataType<std::complex<_Tp> >
+{
+public:
+    typedef std::complex<_Tp> value_type;
+    typedef value_type work_type;
+    typedef _Tp channel_type;
+    enum { depth = DataDepth<channel_type>::value, channels = 2,
+           fmt = ((channels-1)<<8) + DataDepth<channel_type>::fmt,
+           type = CV_MAKETYPE(depth, channels) };
+};
+
+template<typename _Tp> class DataType<Complex<_Tp> >
+{
+public:
+    typedef Complex<_Tp> value_type;
+    typedef value_type work_type;
+    typedef _Tp channel_type;
+    enum { depth = DataDepth<channel_type>::value, channels = 2,
+           fmt = ((channels-1)<<8) + DataDepth<channel_type>::fmt,
+           type = CV_MAKETYPE(depth, channels) };
+};
+
+template<typename _Tp> class DataType<Point_<_Tp> >
+{
+public:
+    typedef Point_<_Tp> value_type;
+    typedef Point_<typename DataType<_Tp>::work_type> work_type;
+    typedef _Tp channel_type;
+    enum { depth = DataDepth<channel_type>::value, channels = 2,
+           fmt = ((channels-1)<<8) + DataDepth<channel_type>::fmt,
+           type = CV_MAKETYPE(depth, channels) };
+};
+
+template<typename _Tp> class DataType<Point3_<_Tp> >
+{
+public:
+    typedef Point3_<_Tp> value_type;
+    typedef Point3_<typename DataType<_Tp>::work_type> work_type;
+    typedef _Tp channel_type;
+    enum { depth = DataDepth<channel_type>::value, channels = 3,
+           fmt = ((channels-1)<<8) + DataDepth<channel_type>::fmt,
+           type = CV_MAKETYPE(depth, channels) };
+};
+
+template<typename _Tp> class DataType<Size_<_Tp> >
+{
+public:
+    typedef Size_<_Tp> value_type;
+    typedef Size_<typename DataType<_Tp>::work_type> work_type;
+    typedef _Tp channel_type;
+    enum { depth = DataDepth<channel_type>::value, channels = 2,
+           fmt = ((channels-1)<<8) + DataDepth<channel_type>::fmt,
+           type = CV_MAKETYPE(depth, channels) };
+};
+
+template<typename _Tp> class DataType<Rect_<_Tp> >
+{
+public:
+    typedef Rect_<_Tp> value_type;
+    typedef Rect_<typename DataType<_Tp>::work_type> work_type;
+    typedef _Tp channel_type;
+    enum { depth = DataDepth<channel_type>::value, channels = 4,
+           fmt = ((channels-1)<<8) + DataDepth<channel_type>::fmt,
+           type = CV_MAKETYPE(depth, channels) };
+};
+
+template<typename _Tp> class DataType<Scalar_<_Tp> >
+{
+public:
+    typedef Scalar_<_Tp> value_type;
+    typedef Scalar_<typename DataType<_Tp>::work_type> work_type;
+    typedef _Tp channel_type;
+    enum { depth = DataDepth<channel_type>::value, channels = 4,
+           fmt = ((channels-1)<<8) + DataDepth<channel_type>::fmt,
+           type = CV_MAKETYPE(depth, channels) };
+};
+
+template<> class DataType<Range>
+{
+public:
+    typedef Range value_type;
+    typedef value_type work_type;
+    typedef int channel_type;
+    enum { depth = DataDepth<channel_type>::value, channels = 2,
+           fmt = ((channels-1)<<8) + DataDepth<channel_type>::fmt,
+           type = CV_MAKETYPE(depth, channels) };
+};
+
+
+//////////////////////////////// Vector ////////////////////////////////
+
+// template vector class. It is similar to STL's vector,
+// with a few important differences:
+//   1) it can be created on top of user-allocated data w/o copying it
+//   2) Vector b = a means copying the header,
+//      not the underlying data (use clone() to make a deep copy)
+template <typename _Tp> class CV_EXPORTS Vector
+{
+public:
+    typedef _Tp value_type;
+    typedef _Tp* iterator;
+    typedef const _Tp* const_iterator;
+    typedef _Tp& reference;
+    typedef const _Tp& const_reference;
+
+    struct CV_EXPORTS Hdr
+    {
+        Hdr() : data(0), datastart(0), refcount(0), size(0), capacity(0) {};
+        _Tp* data;
+        _Tp* datastart;
+        int* refcount;
+        size_t size;
+        size_t capacity;
+    };
+
+    Vector();
+    Vector(size_t _size);
+    Vector(size_t _size, const _Tp& val);
+    Vector(_Tp* _data, size_t _size, bool _copyData=false);
+    template<int n> Vector(const Vec<_Tp, n>& vec);
+    Vector(const std::vector<_Tp>& vec, bool _copyData=false);
+    Vector(const Vector& d);
+    Vector(const Vector& d, const Range& r);
+
+    Vector<_Tp>& operator = (const Vector& d);
+    ~Vector();
+    Vector clone() const;
+    void copyTo(Vector<_Tp>& vec) const;
+    void copyTo(std::vector<_Tp>& vec) const;
+    operator CvMat() const;
+    
+    _Tp& operator [] (size_t i);
+    const _Tp& operator [] (size_t i) const;
+    _Tp& operator [] (int i);
+    const _Tp& operator [] (int i) const;
+    Vector operator() (const Range& r) const;
+    _Tp& back();
+    const _Tp& back() const;
+    _Tp& front();
+    const _Tp& front() const;
+
+    _Tp* begin();
+    _Tp* end();
+    const _Tp* begin() const;
+    const _Tp* end() const;
+
+    void addref();
+    void release();
+    void set(_Tp* _data, size_t _size, bool _copyData=false);
+
+    void reserve(size_t newCapacity);
+    void resize(size_t newSize);
+    Vector<_Tp>& push_back(const _Tp& elem);
+    Vector<_Tp>& pop_back();
+    size_t size() const;
+    size_t capacity() const;
+    bool empty() const;
+    void clear();
+    int type() const;
+
+protected:
+    Hdr hdr;
+};
+
+//////////////////// Generic ref-cointing pointer class for C/C++ objects ////////////////////////
+
+template<typename _Tp> class CV_EXPORTS Ptr
+{
+public:
+    Ptr();
+    Ptr(_Tp* _obj);
+    ~Ptr();
+    Ptr(const Ptr& ptr);
+    Ptr& operator = (const Ptr& ptr);
+    void addref();
+    void release();
+    void delete_obj();
+    bool empty() const;
+
+    _Tp* operator -> ();
+    const _Tp* operator -> () const;
+
+    operator _Tp* ();
+    operator const _Tp*() const;
+protected:
+    _Tp* obj;
+    int* refcount;
+};
+
+//////////////////////////////// Mat ////////////////////////////////
+
+class Mat;
+template<typename M> class CV_EXPORTS MatExpr_Base_;
+typedef MatExpr_Base_<Mat> MatExpr_Base;
+template<typename E, typename M> class MatExpr_;
+template<typename A1, typename M, typename Op> class MatExpr_Op1_;
+template<typename A1, typename A2, typename M, typename Op> class MatExpr_Op2_;
+template<typename A1, typename A2, typename A3, typename M, typename Op> class MatExpr_Op3_;
+template<typename A1, typename A2, typename A3, typename A4,
+        typename M, typename Op> class MatExpr_Op4_;
+template<typename A1, typename A2, typename A3, typename A4,
+        typename A5, typename M, typename Op> class MatExpr_Op5_;
+template<typename M> class CV_EXPORTS MatOp_DivRS_;
+template<typename M> class CV_EXPORTS MatOp_Inv_;
+template<typename M> class CV_EXPORTS MatOp_MulDiv_;
+template<typename M> class CV_EXPORTS MatOp_Repeat_;
+template<typename M> class CV_EXPORTS MatOp_Set_;
+template<typename M> class CV_EXPORTS MatOp_Scale_;
+template<typename M> class CV_EXPORTS MatOp_T_;
+
+typedef MatExpr_<MatExpr_Op4_<Size, int, Scalar,
+    int, Mat, MatOp_Set_<Mat> >, Mat> MatExpr_Initializer;
+
+template<typename _Tp> class MatIterator_;
+template<typename _Tp> class MatConstIterator_;
+
+enum { MAGIC_MASK=0xFFFF0000, TYPE_MASK=0x00000FFF, DEPTH_MASK=7 };
+
+static inline size_t getElemSize(int type) { return CV_ELEM_SIZE(type); }
+
+// matrix decomposition types
+enum { DECOMP_LU=0, DECOMP_SVD=1, DECOMP_EIG=2, DECOMP_CHOLESKY=3, DECOMP_QR=4, DECOMP_NORMAL=16 };
+enum { NORM_INF=1, NORM_L1=2, NORM_L2=4, NORM_TYPE_MASK=7, NORM_RELATIVE=8};
+enum { CMP_EQ=0, CMP_GT=1, CMP_GE=2, CMP_LT=3, CMP_LE=4, CMP_NE=5 };
+enum { GEMM_1_T=1, GEMM_2_T=2, GEMM_3_T=4 };
+enum { DFT_INVERSE=1, DFT_SCALE=2, DFT_ROWS=4, DFT_COMPLEX_OUTPUT=16, DFT_REAL_OUTPUT=32,
+    DCT_INVERSE = DFT_INVERSE, DCT_ROWS=DFT_ROWS };
+
+class CV_EXPORTS Mat
+{
+public:
+    Mat();
+    Mat(int _rows, int _cols, int _type);
+    Mat(int _rows, int _cols, int _type, const Scalar& _s);
+    Mat(Size _size, int _type);
+    Mat(const Mat& m);
+    Mat(int _rows, int _cols, int _type, void* _data, size_t _step=AUTO_STEP);
+    Mat(Size _size, int _type, void* _data, size_t _step=AUTO_STEP);
+    Mat(const Mat& m, const Range& rowRange, const Range& colRange);
+    Mat(const Mat& m, const Rect& roi);
+    Mat(const CvMat* m, bool copyData=false);
+    Mat(const IplImage* img, bool copyData=false);
+    Mat( const MatExpr_Base& expr );
+    ~Mat();
+    Mat& operator = (const Mat& m);
+    Mat& operator = (const MatExpr_Base& expr);
+
+    operator MatExpr_<Mat, Mat>() const;
+
+    Mat row(int y) const;
+    Mat col(int x) const;
+    Mat rowRange(int startrow, int endrow) const;
+    Mat rowRange(const Range& r) const;
+    Mat colRange(int startcol, int endcol) const;
+    Mat colRange(const Range& r) const;
+    Mat diag(int d=0) const;
+    static Mat diag(const Mat& d);
+
+    Mat clone() const;
+    void copyTo( Mat& m ) const;
+    void copyTo( Mat& m, const Mat& mask ) const;
+    void convertTo( Mat& m, int rtype, double alpha=1, double beta=0 ) const;
+
+    void assignTo( Mat& m, int type=-1 ) const;
+    Mat& operator = (const Scalar& s);
+    Mat& setTo(const Scalar& s, const Mat& mask=Mat());
+    Mat reshape(int _cn, int _rows=0) const;
+
+    MatExpr_<MatExpr_Op2_<Mat, double, Mat, MatOp_T_<Mat> >, Mat>
+    t() const;
+    MatExpr_<MatExpr_Op2_<Mat, int, Mat, MatOp_Inv_<Mat> >, Mat>
+        inv(int method=DECOMP_LU) const;
+    MatExpr_<MatExpr_Op4_<Mat, Mat, double, char, Mat, MatOp_MulDiv_<Mat> >, Mat>
+    mul(const Mat& m, double scale=1) const;
+    MatExpr_<MatExpr_Op4_<Mat, Mat, double, char, Mat, MatOp_MulDiv_<Mat> >, Mat>
+    mul(const MatExpr_<MatExpr_Op2_<Mat, double, Mat, MatOp_Scale_<Mat> >, Mat>& m, double scale=1) const;
+    MatExpr_<MatExpr_Op4_<Mat, Mat, double, char, Mat, MatOp_MulDiv_<Mat> >, Mat>    
+    mul(const MatExpr_<MatExpr_Op2_<Mat, double, Mat, MatOp_DivRS_<Mat> >, Mat>& m, double scale=1) const;
+
+    Mat cross(const Mat& m) const;
+    double dot(const Mat& m) const;
+
+    static MatExpr_Initializer zeros(int rows, int cols, int type);
+    static MatExpr_Initializer zeros(Size size, int type);
+    static MatExpr_Initializer ones(int rows, int cols, int type);
+    static MatExpr_Initializer ones(Size size, int type);
+    static MatExpr_Initializer eye(int rows, int cols, int type);
+    static MatExpr_Initializer eye(Size size, int type);
+
+    void create(int _rows, int _cols, int _type);
+    void create(Size _size, int _type);
+    void addref();
+    void release();
+
+    void locateROI( Size& wholeSize, Point& ofs ) const;
+    Mat& adjustROI( int dtop, int dbottom, int dleft, int dright );
+    Mat operator()( Range rowRange, Range colRange ) const;
+    Mat operator()( const Rect& roi ) const;
+
+    operator CvMat() const;
+    operator IplImage() const;
+    bool isContinuous() const;
+    size_t elemSize() const;
+    size_t elemSize1() const;
+    int type() const;
+    int depth() const;
+    int channels() const;
+    size_t step1() const;
+    Size size() const;
+
+    uchar* ptr(int y=0);
+    const uchar* ptr(int y=0) const;
+
+    template<typename _Tp> _Tp* ptr(int y=0);
+    template<typename _Tp> const _Tp* ptr(int y=0) const;
+
+    enum { MAGIC_VAL=0x42FF0000, AUTO_STEP=0, CONTINUOUS_FLAG=CV_MAT_CONT_FLAG };
+
+    int flags;
+    int rows, cols;
+    size_t step;
+    uchar* data;
+
+    int* refcount;
+    uchar* datastart;
+    uchar* dataend;
+};
+
+
+// Multiply-with-Carry RNG
+class CV_EXPORTS RNG
+{
+public:
+    enum { A=4164903690U, UNIFORM=0, NORMAL=1 };
+
+    RNG();
+    RNG(uint64 _state);
+    unsigned next();
+
+    operator uchar();
+    operator schar();
+    operator ushort();
+    operator short();
+    operator unsigned();
+    operator int();
+    operator float();
+    operator double();
+    int uniform(int a, int b);
+    float uniform(float a, float b);
+    double uniform(double a, double b);
+    void fill( Mat& mat, int distType, const Scalar& a, const Scalar& b );
+
+    uint64 state;
+};
+
+class CV_EXPORTS TermCriteria
+{
+public:
+    enum { COUNT=1, MAX_ITER=COUNT, EPS=2 };
+
+    TermCriteria();
+    TermCriteria(int _type, int _maxCount, double _epsilon);
+    TermCriteria(const CvTermCriteria& criteria);
+    operator CvTermCriteria() const;
+    
+    int type;
+    int maxCount;
+    double epsilon;
+};
+
+CV_EXPORTS Mat cvarrToMat(const CvArr* arr, bool copyData=false, bool allowND=true);
+CV_EXPORTS Mat extractImageCOI(const CvArr* arr);
+
+CV_EXPORTS void add(const Mat& a, const Mat& b, Mat& c, const Mat& mask);
+CV_EXPORTS void subtract(const Mat& a, const Mat& b, Mat& c, const Mat& mask);
+CV_EXPORTS void add(const Mat& a, const Mat& b, Mat& c);
+CV_EXPORTS void subtract(const Mat& a, const Mat& b, Mat& c);
+CV_EXPORTS void add(const Mat& a, const Scalar& s, Mat& c, const Mat& mask=Mat());
+CV_EXPORTS void subtract(const Mat& a, const Scalar& s, Mat& c, const Mat& mask=Mat());
+
+CV_EXPORTS void multiply(const Mat& a, const Mat& b, Mat& c, double scale=1);
+CV_EXPORTS void divide(const Mat& a, const Mat& b, Mat& c, double scale=1);
+CV_EXPORTS void divide(double scale, const Mat& b, Mat& c);
+
+CV_EXPORTS void subtract(const Scalar& s, const Mat& a, Mat& c, const Mat& mask=Mat());
+CV_EXPORTS void scaleAdd(const Mat& a, double alpha, const Mat& b, Mat& c);
+CV_EXPORTS void addWeighted(const Mat& a, double alpha, const Mat& b,
+                            double beta, double gamma, Mat& c);
+CV_EXPORTS void convertScaleAbs(const Mat& a, Mat& c, double alpha=1, double beta=0);
+CV_EXPORTS void LUT(const Mat& a, const Mat& lut, Mat& b);
+
+CV_EXPORTS Scalar sum(const Mat& m);
+CV_EXPORTS int countNonZero( const Mat& m );
+
+CV_EXPORTS Scalar mean(const Mat& m);
+CV_EXPORTS Scalar mean(const Mat& m, const Mat& mask);
+CV_EXPORTS void meanStdDev(const Mat& m, Scalar& mean, Scalar& stddev, const Mat& mask=Mat());
+CV_EXPORTS double norm(const Mat& a, int normType=NORM_L2);
+CV_EXPORTS double norm(const Mat& a, const Mat& b, int normType=NORM_L2);
+CV_EXPORTS double norm(const Mat& a, int normType, const Mat& mask);
+CV_EXPORTS double norm(const Mat& a, const Mat& b,
+                       int normType, const Mat& mask);
+CV_EXPORTS void normalize( const Mat& a, Mat& b, double alpha=1, double beta=0,
+                          int norm_type=NORM_L2, int rtype=-1, const Mat& mask=Mat());
+
+CV_EXPORTS void minMaxLoc(const Mat& a, double* minVal,
+                          double* maxVal=0, Point* minLoc=0,
+                          Point* maxLoc=0, const Mat& mask=Mat());
+CV_EXPORTS void reduce(const Mat& m, Mat& dst, int dim, int rtype, int dtype=-1);
+CV_EXPORTS void merge(const Vector<Mat>& mv, Mat& dst);
+CV_EXPORTS void split(const Mat& m, Vector<Mat>& mv);
+CV_EXPORTS void mixChannels(const Vector<Mat>& src, Vector<Mat>& dst,
+                            const Vector<int>& fromTo);
+CV_EXPORTS void flip(const Mat& a, Mat& b, int flipCode);
+
+CV_EXPORTS void repeat(const Mat& a, int ny, int nx, Mat& b);
+static inline Mat repeat(const Mat& src, int ny, int nx)
+{
+    if( nx == 1 && ny == 1 ) return src;
+    Mat dst; repeat(src, ny, nx, dst); return dst;
+}
+
+CV_EXPORTS void bitwise_and(const Mat& a, const Mat& b, Mat& c, const Mat& mask=Mat());
+CV_EXPORTS void bitwise_or(const Mat& a, const Mat& b, Mat& c, const Mat& mask=Mat());
+CV_EXPORTS void bitwise_xor(const Mat& a, const Mat& b, Mat& c, const Mat& mask=Mat());
+CV_EXPORTS void bitwise_and(const Mat& a, const Scalar& s, Mat& c, const Mat& mask=Mat());
+CV_EXPORTS void bitwise_or(const Mat& a, const Scalar& s, Mat& c, const Mat& mask=Mat());
+CV_EXPORTS void bitwise_xor(const Mat& a, const Scalar& s, Mat& c, const Mat& mask=Mat());
+CV_EXPORTS void bitwise_not(const Mat& a, Mat& c);
+CV_EXPORTS void absdiff(const Mat& a, const Mat& b, Mat& c);
+CV_EXPORTS void absdiff(const Mat& a, const Scalar& s, Mat& c);
+CV_EXPORTS void inRange(const Mat& src, const Mat& lowerb,
+                        const Mat& upperb, Mat& dst);
+CV_EXPORTS void inRange(const Mat& src, const Scalar& lowerb,
+                        const Scalar& upperb, Mat& dst);
+CV_EXPORTS void compare(const Mat& a, const Mat& b, Mat& c, int cmpop);
+CV_EXPORTS void compare(const Mat& a, double s, Mat& c, int cmpop);
+CV_EXPORTS void min(const Mat& a, const Mat& b, Mat& c);
+CV_EXPORTS void min(const Mat& a, double alpha, Mat& c);
+CV_EXPORTS void max(const Mat& a, const Mat& b, Mat& c);
+CV_EXPORTS void max(const Mat& a, double alpha, Mat& c);
+
+CV_EXPORTS void sqrt(const Mat& a, Mat& b);
+CV_EXPORTS void pow(const Mat& a, double power, Mat& b);
+CV_EXPORTS void exp(const Mat& a, Mat& b);
+CV_EXPORTS void log(const Mat& a, Mat& b);
+CV_EXPORTS float cubeRoot(float val);
+CV_EXPORTS float fastAtan2(float y, float x);
+CV_EXPORTS void polarToCart(const Mat& magnitude, const Mat& angle,
+                            Mat& x, Mat& y, bool angleInDegrees=false);
+CV_EXPORTS void cartToPolar(const Mat& x, const Mat& y,
+                            Mat& magnitude, Mat& angle,
+                            bool angleInDegrees=false);
+CV_EXPORTS void phase(const Mat& x, const Mat& y, Mat& angle,
+                            bool angleInDegrees=false);
+CV_EXPORTS void magnitude(const Mat& x, const Mat& y, Mat& magnitude);
+CV_EXPORTS bool checkRange(const Mat& a, bool quiet=true, Point* pt=0,
+                           double minVal=-DBL_MAX, double maxVal=DBL_MAX);
+
+CV_EXPORTS void gemm(const Mat& a, const Mat& b, double alpha,
+                     const Mat& c, double gamma, Mat& d, int flags=0);
+CV_EXPORTS void mulTransposed( const Mat& a, Mat& c, bool aTa,
+                               const Mat& delta=Mat(),
+                               double scale=1, int rtype=-1 );
+CV_EXPORTS void transpose(const Mat& a, Mat& b);
+CV_EXPORTS void transform(const Mat& src, Mat& dst, const Mat& m );
+CV_EXPORTS void perspectiveTransform(const Mat& src, Mat& dst, const Mat& m );
+
+CV_EXPORTS void completeSymm(Mat& a, bool lowerToUpper=false);
+CV_EXPORTS void setIdentity(Mat& c, const Scalar& s=Scalar(1));
+CV_EXPORTS double determinant(const Mat& m);
+CV_EXPORTS Scalar trace(const Mat& m);
+CV_EXPORTS double invert(const Mat& a, Mat& c, int flags=DECOMP_LU);
+CV_EXPORTS bool solve(const Mat& a, const Mat& b, Mat& x, int flags=DECOMP_LU);
+CV_EXPORTS void sort(const Mat& a, Mat& b, int flags);
+CV_EXPORTS void sortIdx(const Mat& a, Mat& b, int flags);
+CV_EXPORTS void solveCubic(const Mat& coeffs, Mat& roots);
+CV_EXPORTS void solvePoly(const Mat& coeffs, Mat& roots, int maxIters=20, int fig=100);
+CV_EXPORTS bool eigen(const Mat& a, Mat& eigenvalues);
+CV_EXPORTS bool eigen(const Mat& a, Mat& eigenvalues, Mat& eigenvectors);
+
+CV_EXPORTS void calcCovariation( const Vector<Mat>& data, Mat& covar, Mat& mean,
+                                 int flags, int ctype=CV_64F);
+CV_EXPORTS void calcCovariation( const Mat& data, Mat& covar, Mat& mean,
+                                 int flags, int ctype=CV_64F);
+
+class CV_EXPORTS PCA
+{
+public:
+    PCA();
+    PCA(const Mat& data, const Mat& mean, int flags, int maxComponents=0);
+    PCA& operator()(const Mat& data, const Mat& mean, int flags, int maxComponents=0);
+    Mat project(const Mat& vec) const;
+    void project(const Mat& vec, Mat& result) const;
+    Mat backProject(const Mat& vec) const;
+    void backProject(const Mat& vec, Mat& result) const;
+
+    Mat eigenvectors;
+    Mat eigenvalues;
+    Mat mean;
+};
+
+class CV_EXPORTS SVD
+{
+public:
+    enum { MODIFY_A=1, NO_UV=2, FULL_UV=4 };
+    SVD();
+    SVD( const Mat& m, int flags=0 );
+    SVD& operator ()( const Mat& m, int flags=0 );
+
+    static void solveZ( const Mat& m, Mat& dst );
+    void backSubst( const Mat& rhs, Mat& dst ) const;
+
+    Mat u, w, vt;
+};
+
+CV_EXPORTS double mahalanobis(const Mat& v1, const Mat& v2, const Mat& icovar);
+static inline double mahalonobis(const Mat& v1, const Mat& v2, const Mat& icovar)
+{ return mahalanobis(v1, v2, icovar); }
+
+CV_EXPORTS void dft(const Mat& src, Mat& dst, int flags=0, int nonzeroRows=0);
+CV_EXPORTS void idft(const Mat& src, Mat& dst, int flags=0, int nonzeroRows=0);
+CV_EXPORTS void dct(const Mat& src, Mat& dst, int flags=0);
+CV_EXPORTS void idct(const Mat& src, Mat& dst, int flags=0);
+CV_EXPORTS void mulSpectrums(const Mat& a, const Mat& b, Mat& c,
+                             int flags, bool conjB=false);
+CV_EXPORTS int getOptimalDFTSize(int vecsize);
+
+enum { KMEANS_CENTERS_RANDOM=0, KMEANS_CENTERS_SPP=2, KMEANS_USE_INITIAL_LABELS=1 };
+CV_EXPORTS int kmeans( const Mat& samples, int K,
+                       Mat& labels, Mat& centers,
+                       TermCriteria crit, int attempts=1,
+                       int flags=KMEANS_CENTERS_SPP,
+                       double* compactness=0);
+
+CV_EXPORTS void seqToVector( const CvSeq* ptseq, Vector<Point>& pts );
+
+CV_EXPORTS RNG& theRNG();
+static inline int randi() { return (int)theRNG(); }
+static inline unsigned randu() { return (unsigned)theRNG(); }
+static inline float randf() { return (float)theRNG(); }
+static inline double randd() { return (double)theRNG(); }
+static inline void randu(Mat& dst, const Scalar& low, const Scalar& high)
+{ theRNG().fill(dst, RNG::UNIFORM, low, high); }
+static inline void randn(Mat& dst, const Scalar& mean, const Scalar& stddev)
+{ theRNG().fill(dst, RNG::NORMAL, mean, stddev); }
+CV_EXPORTS void randShuffle(Mat& dst, RNG& rng, double iterFactor=1.);
+static inline void randShuffle(Mat& dst, double iterFactor=1.)
+{ randShuffle(dst, theRNG(), iterFactor); }
+
+CV_EXPORTS void line(Mat& img, Point pt1, Point pt2, const Scalar& color,
+                     int thickness=1, int lineType=8, int shift=0);
+
+CV_EXPORTS void rectangle(Mat& img, Point pt1, Point pt2,
+                          const Scalar& color, int thickness=1,
+                          int lineType=8, int shift=0);
+
+CV_EXPORTS void circle(Mat& img, Point center, int radius,
+                       const Scalar& color, int thickness=1,
+                       int lineType=8, int shift=0);
+
+CV_EXPORTS void ellipse(Mat& img, Point center, Size axes,
+                        double angle, double startAngle, double endAngle,
+                        const Scalar& color, int thickness=1,
+                        int lineType=8, int shift=0);
+
+CV_EXPORTS void ellipse(Mat& img, const RotatedRect& box, const Scalar& color,
+                        int thickness=1, int lineType=8, int shift=0 );
+
+CV_EXPORTS void fillConvexPoly(Mat& img, const Vector<Point>& pts,
+                               const Scalar& color, int lineType=8,
+                               int shift=0);
+
+CV_EXPORTS void fillPoly(Mat& img, const Vector<Vector<Point> >& pts,
+                         const Scalar& color, int lineType=8, int shift=0,
+                         Point offset=Point() );
+
+CV_EXPORTS void polylines(Mat& img, const Vector<Vector<Point> >& pts, bool isClosed,
+                          const Scalar& color, int thickness=1, int lineType=8, int shift=0 );
+
+CV_EXPORTS bool clipLine(Size imgSize, Point& pt1, Point& pt2);
+
+class CV_EXPORTS LineIterator
+{
+public:
+    LineIterator(const Mat& img, Point pt1, Point pt2,
+                 int connectivity=8, bool leftToRight=false);
+    uchar* operator *();
+    LineIterator& operator ++();
+    LineIterator operator ++(int);
+
+    uchar* ptr;
+    int err, count;
+    int minusDelta, plusDelta;
+    int minusStep, plusStep;
+};
+
+CV_EXPORTS void ellipse2Poly( Point center, Size axes, int angle,
+                              int arcStart, int arcEnd, int delta, Vector<Point>& pts );
+
+enum
+{
+    FONT_HERSHEY_SIMPLEX = 0,
+    FONT_HERSHEY_PLAIN = 1,
+    FONT_HERSHEY_DUPLEX = 2,
+    FONT_HERSHEY_COMPLEX = 3,
+    FONT_HERSHEY_TRIPLEX = 4,
+    FONT_HERSHEY_COMPLEX_SMALL = 5,
+    FONT_HERSHEY_SCRIPT_SIMPLEX = 6,
+    FONT_HERSHEY_SCRIPT_COMPLEX = 7,
+    FONT_ITALIC = 16
+};
+
+CV_EXPORTS void putText( Mat& img, const String& text, Point org,
+                         int fontFace, double fontScale, Scalar color,
+                         int thickness=1, int linetype=8,
+                         bool bottomLeftOrigin=false );
+
+CV_EXPORTS Size getTextSize(const String& text, int fontFace,
+                            double fontScale, int thickness,
+                            int* baseLine);
+
+///////////////////////////////// Mat_<_Tp> ////////////////////////////////////
+
+template<typename _Tp> class CV_EXPORTS Mat_ : public Mat
+{
+public:
+    typedef _Tp value_type;
+    typedef typename DataType<_Tp>::channel_type channel_type;
+    typedef MatIterator_<_Tp> iterator;
+    typedef MatConstIterator_<_Tp> const_iterator;
+    
+    Mat_();
+    Mat_(int _rows, int _cols);
+    Mat_(int _rows, int _cols, const _Tp& value);
+    explicit Mat_(Size _size);
+    Mat_(Size _size, const _Tp& value);
+    Mat_(const Mat& m);
+    Mat_(const Mat_& m);
+    Mat_(int _rows, int _cols, _Tp* _data, size_t _step=AUTO_STEP);
+    Mat_(const Mat_& m, const Range& rowRange, const Range& colRange);
+    Mat_(const Mat_& m, const Rect& roi);
+    Mat_(const MatExpr_Base& expr);
+    template<int n> explicit Mat_(const Vec<_Tp, n>& vec);
+    Mat_(const Vector<_Tp>& vec);
+
+    Mat_& operator = (const Mat& m);
+    Mat_& operator = (const Mat_& m);
+    Mat_& operator = (const _Tp& s);
+
+    iterator begin();
+    iterator end();
+    const_iterator begin() const;
+    const_iterator end() const;
+
+    void create(int _rows, int _cols);
+    void create(Size _size);
+    Mat_ cross(const Mat_& m) const;
+    Mat_& operator = (const MatExpr_Base& expr);
+    template<typename T2> operator Mat_<T2>() const;
+    Mat_ row(int y) const;
+    Mat_ col(int x) const;
+    Mat_ diag(int d=0) const;
+    Mat_ clone() const;
+
+    MatExpr_<MatExpr_Op2_<Mat_, double, Mat_, MatOp_T_<Mat> >, Mat_> t() const;
+    MatExpr_<MatExpr_Op2_<Mat_, int, Mat_, MatOp_Inv_<Mat> >, Mat_> inv(int method=DECOMP_LU) const;
+
+    MatExpr_<MatExpr_Op4_<Mat_, Mat_, double, char, Mat_, MatOp_MulDiv_<Mat> >, Mat_>
+    mul(const Mat_& m, double scale=1) const;
+    MatExpr_<MatExpr_Op4_<Mat_, Mat_, double, char, Mat_, MatOp_MulDiv_<Mat> >, Mat_>
+    mul(const MatExpr_<MatExpr_Op2_<Mat_, double, Mat_,
+        MatOp_Scale_<Mat> >, Mat_>& m, double scale=1) const;
+    MatExpr_<MatExpr_Op4_<Mat_, Mat_, double, char, Mat_, MatOp_MulDiv_<Mat> >, Mat_>    
+    mul(const MatExpr_<MatExpr_Op2_<Mat_, double, Mat_,
+        MatOp_DivRS_<Mat> >, Mat_>& m, double scale=1) const;
+
+    size_t elemSize() const;
+    size_t elemSize1() const;
+    int type() const;
+    int depth() const;
+    int channels() const;
+    size_t stepT() const;
+    size_t step1() const;
+
+    static MatExpr_Initializer zeros(int rows, int cols);
+    static MatExpr_Initializer zeros(Size size);
+    static MatExpr_Initializer ones(int rows, int cols);
+    static MatExpr_Initializer ones(Size size);
+    static MatExpr_Initializer eye(int rows, int cols);
+    static MatExpr_Initializer eye(Size size);
+
+    Mat_ reshape(int _rows) const;
+    Mat_& adjustROI( int dtop, int dbottom, int dleft, int dright );
+    Mat_ operator()( const Range& rowRange, const Range& colRange ) const;
+    Mat_ operator()( const Rect& roi ) const;
+
+    _Tp* operator [](int y);
+    const _Tp* operator [](int y) const;
+
+    _Tp& operator ()(int row, int col);
+    const _Tp& operator ()(int row, int col) const;
+
+    operator MatExpr_<Mat_, Mat_>() const;
+    operator Vector<_Tp>() const;
+};
+
+//////////// Iterators & Comma initializers //////////////////
+
+template<typename _Tp>
+class CV_EXPORTS MatConstIterator_
+{
+public:
+    typedef _Tp value_type;
+    typedef int difference_type;
+
+    MatConstIterator_();
+    MatConstIterator_(const Mat_<_Tp>* _m);
+    MatConstIterator_(const Mat_<_Tp>* _m, int _row, int _col=0);
+    MatConstIterator_(const Mat_<_Tp>* _m, Point _pt);
+    MatConstIterator_(const MatConstIterator_& it);
+
+    MatConstIterator_& operator = (const MatConstIterator_& it );
+    _Tp operator *() const;
+    _Tp operator [](int i) const;
+    
+    MatConstIterator_& operator += (int ofs);
+    MatConstIterator_& operator -= (int ofs);
+    MatConstIterator_& operator --();
+    MatConstIterator_ operator --(int);
+    MatConstIterator_& operator ++();
+    MatConstIterator_ operator ++(int);
+    Point pos() const;
+
+protected:
+    const Mat_<_Tp>* m;
+    _Tp* ptr;
+    _Tp* sliceEnd;
+};
+
+
+template<typename _Tp>
+class CV_EXPORTS MatIterator_ : public MatConstIterator_<_Tp>
+{
+public:
+    typedef _Tp* pointer;
+    typedef _Tp& reference;
+    typedef std::random_access_iterator_tag iterator_category;
+
+    MatIterator_();
+    MatIterator_(Mat_<_Tp>* _m);
+    MatIterator_(Mat_<_Tp>* _m, int _row, int _col=0);
+    MatIterator_(const Mat_<_Tp>* _m, Point _pt);
+    MatIterator_(const MatIterator_& it);
+    MatIterator_& operator = (const MatIterator_<_Tp>& it );
+
+    _Tp& operator *() const;
+    _Tp& operator [](int i) const;
+
+    MatIterator_& operator += (int ofs);
+    MatIterator_& operator -= (int ofs);
+    MatIterator_& operator --();
+    MatIterator_ operator --(int);
+    MatIterator_& operator ++();
+    MatIterator_ operator ++(int);
+};
+
+template<typename _Tp> class CV_EXPORTS MatOp_Iter_;
+
+template<typename _Tp> class CV_EXPORTS MatCommaInitializer_ :
+    public MatExpr_<MatExpr_Op1_<MatIterator_<_Tp>, Mat_<_Tp>, MatOp_Iter_<_Tp> >, Mat_<_Tp> >
+{
+public:
+    MatCommaInitializer_(Mat_<_Tp>* _m);
+    template<typename T2> MatCommaInitializer_<_Tp>& operator , (T2 v);
+    operator Mat_<_Tp>() const;
+    Mat_<_Tp> operator *() const;
+    void assignTo(Mat& m, int type=-1) const;
+};
+
+template<typename _Tp> class VectorCommaInitializer_
+{
+public:
+    VectorCommaInitializer_(Vector<_Tp>* _vec);
+    template<typename T2> VectorCommaInitializer_<_Tp>& operator , (T2 val);
+    operator Vector<_Tp>() const;
+    Vector<_Tp> operator *() const;
+
+protected:
+    Vector<_Tp>* vec;
+    int idx;
+};
+
+template<typename _Tp, size_t fixed_size=4096/sizeof(_Tp)+8> class CV_EXPORTS AutoBuffer
+{
+public:
+    typedef _Tp value_type;
+
+    AutoBuffer();
+    AutoBuffer(size_t _size);
+    ~AutoBuffer();
+
+    void allocate(size_t _size);
+    void deallocate();
+    operator _Tp* ();
+    operator const _Tp* () const;
+
+protected:
+    _Tp* ptr;
+    size_t size;
+    _Tp buf[fixed_size];
+};
+
+/////////////////////////// multi-dimensional dense matrix //////////////////////////
+
+class MatND;
+class SparseMat;
+
+class CV_EXPORTS MatND
+{
+public:
+    MatND();
+    MatND(const Vector<int>& _sizes, int _type);
+    MatND(const Vector<int>& _sizes, int _type, const Scalar& _s);
+    MatND(const MatND& m);
+    MatND(const MatND& m, const Vector<Range>& ranges);
+    MatND(const CvMatND* m, bool copyData=false);
+    //MatND( const MatExpr_BaseND& expr );
+    ~MatND();
+    MatND& operator = (const MatND& m);
+    //MatND& operator = (const MatExpr_BaseND& expr);
+
+    //operator MatExpr_<MatND, MatND>() const;
+
+    MatND clone() const;
+    MatND operator()(const Vector<Range>& ranges) const;
+
+    void copyTo( MatND& m ) const;
+    void copyTo( MatND& m, const MatND& mask ) const;
+    void convertTo( MatND& m, int rtype, double alpha=1, double beta=0 ) const;
+
+    void assignTo( MatND& m, int type=-1 ) const;
+    MatND& operator = (const Scalar& s);
+    MatND& setTo(const Scalar& s, const MatND& mask=MatND());
+    MatND reshape(int newcn, const Vector<int>& newsz=Vector<int>()) const;
+
+    void create(const Vector<int>& _sizes, int _type);
+    void addref();
+    void release();
+
+    operator Mat() const;
+    operator CvMatND() const;
+    bool isContinuous() const;
+    size_t elemSize() const;
+    size_t elemSize1() const;
+    int type() const;
+    int depth() const;
+    int channels() const;
+    size_t step(int i) const;
+    size_t step1(int i) const;
+    Vector<int> size() const;
+    int size(int i) const;
+
+    uchar* ptr(int i0);
+    const uchar* ptr(int i0) const;
+    uchar* ptr(int i0, int i1);
+    const uchar* ptr(int i0, int i1) const;
+    uchar* ptr(int i0, int i1, int i2);
+    const uchar* ptr(int i0, int i1, int i2) const;
+    uchar* ptr(const int* idx);
+    const uchar* ptr(const int* idx) const;
+
+    enum { MAGIC_VAL=0x42FE0000, AUTO_STEP=-1,
+        CONTINUOUS_FLAG=CV_MAT_CONT_FLAG, MAX_DIM=CV_MAX_DIM };
+
+    int flags;
+    int dims;
+
+    int* refcount;
+    uchar* data;
+    uchar* datastart;
+    uchar* dataend;
+
+    struct
+    {
+        int size;
+        size_t step;
+    }
+    dim[MAX_DIM];
+};
+
+class CV_EXPORTS NAryMatNDIterator
+{
+public:
+    NAryMatNDIterator();
+    NAryMatNDIterator(const Vector<MatND>& arrays);
+    void init(const Vector<MatND>& arrays);
+
+    NAryMatNDIterator& operator ++();
+    NAryMatNDIterator operator ++(int);
+    
+    Vector<MatND> arrays;
+    Vector<Mat> planes;
+
+    int nplanes;
+protected:
+    int iterdepth, idx;
+};
+
+CV_EXPORTS void add(const MatND& a, const MatND& b, MatND& c, const MatND& mask);
+CV_EXPORTS void subtract(const MatND& a, const MatND& b, MatND& c, const MatND& mask);
+CV_EXPORTS void add(const MatND& a, const MatND& b, MatND& c);
+CV_EXPORTS void subtract(const MatND& a, const MatND& b, MatND& c);
+CV_EXPORTS void add(const MatND& a, const Scalar& s, MatND& c, const MatND& mask=MatND());
+
+CV_EXPORTS void multiply(const MatND& a, const MatND& b, MatND& c, double scale=1);
+CV_EXPORTS void divide(const MatND& a, const MatND& b, MatND& c, double scale=1);
+CV_EXPORTS void divide(double scale, const MatND& b, MatND& c);
+
+CV_EXPORTS void subtract(const Scalar& s, const MatND& a, MatND& c, const MatND& mask=MatND());
+CV_EXPORTS void scaleAdd(const MatND& a, double alpha, const MatND& b, MatND& c);
+CV_EXPORTS void addWeighted(const MatND& a, double alpha, const MatND& b,
+                            double beta, double gamma, MatND& c);
+
+CV_EXPORTS Scalar sum(const MatND& m);
+CV_EXPORTS int countNonZero( const MatND& m );
+
+CV_EXPORTS Scalar mean(const MatND& m);
+CV_EXPORTS Scalar mean(const MatND& m, const MatND& mask);
+CV_EXPORTS void meanStdDev(const MatND& m, Scalar& mean, Scalar& stddev, const MatND& mask=MatND());
+CV_EXPORTS double norm(const MatND& a, int normType=NORM_L2, const MatND& mask=MatND());
+CV_EXPORTS double norm(const MatND& a, const MatND& b,
+                       int normType=NORM_L2, const MatND& mask=MatND());
+CV_EXPORTS void normalize( const MatND& a, MatND& b, double alpha=1, double beta=0,
+                           int norm_type=NORM_L2, int rtype=-1, const MatND& mask=MatND());
+
+CV_EXPORTS void minMaxLoc(const MatND& a, double* minVal,
+                       double* maxVal, int* minIdx=0, int* maxIdx=0,
+                       const MatND& mask=MatND());
+CV_EXPORTS void merge(const Vector<MatND>& mv, MatND& dst);
+CV_EXPORTS void split(const MatND& m, Vector<MatND>& mv);
+CV_EXPORTS void mixChannels(const Vector<MatND>& src, Vector<MatND>& dst,
+                            const Vector<int>& fromTo);
+
+CV_EXPORTS void bitwise_and(const MatND& a, const MatND& b, MatND& c, const MatND& mask=MatND());
+CV_EXPORTS void bitwise_or(const MatND& a, const MatND& b, MatND& c, const MatND& mask=MatND());
+CV_EXPORTS void bitwise_xor(const MatND& a, const MatND& b, MatND& c, const MatND& mask=MatND());
+CV_EXPORTS void bitwise_and(const MatND& a, const Scalar& s, MatND& c, const MatND& mask=MatND());
+CV_EXPORTS void bitwise_or(const MatND& a, const Scalar& s, MatND& c, const MatND& mask=MatND());
+CV_EXPORTS void bitwise_xor(const MatND& a, const Scalar& s, MatND& c, const MatND& mask=MatND());
+CV_EXPORTS void bitwise_not(const MatND& a, MatND& c);
+CV_EXPORTS void absdiff(const MatND& a, const MatND& b, MatND& c);
+CV_EXPORTS void absdiff(const MatND& a, const Scalar& s, MatND& c);
+CV_EXPORTS void inRange(const MatND& src, const MatND& lowerb,
+                        const MatND& upperb, MatND& dst);
+CV_EXPORTS void inRange(const MatND& src, const Scalar& lowerb,
+                        const Scalar& upperb, MatND& dst);
+CV_EXPORTS void compare(const MatND& a, const MatND& b, MatND& c, int cmpop);
+CV_EXPORTS void compare(const MatND& a, double s, MatND& c, int cmpop);
+CV_EXPORTS void min(const MatND& a, const MatND& b, MatND& c);
+CV_EXPORTS void min(const MatND& a, double alpha, MatND& c);
+CV_EXPORTS void max(const MatND& a, const MatND& b, MatND& c);
+CV_EXPORTS void max(const MatND& a, double alpha, MatND& c);
+
+CV_EXPORTS void sqrt(const MatND& a, MatND& b);
+CV_EXPORTS void pow(const MatND& a, double power, MatND& b);
+CV_EXPORTS void exp(const MatND& a, MatND& b);
+CV_EXPORTS void log(const MatND& a, MatND& b);
+CV_EXPORTS bool checkRange(const MatND& a, bool quiet=true, int* idx=0,
+                           double minVal=-DBL_MAX, double maxVal=DBL_MAX);
+
+typedef void (*ConvertData)(const void* from, void* to, int cn);
+typedef void (*ConvertScaleData)(const void* from, void* to, int cn, double alpha, double beta);
+
+CV_EXPORTS ConvertData getConvertElem(int fromType, int toType);
+CV_EXPORTS ConvertScaleData getConvertScaleElem(int fromType, int toType);
+
+template<typename _Tp> class CV_EXPORTS MatND_ : public MatND
+{
+public:
+    typedef _Tp value_type;
+    typedef typename DataType<_Tp>::channel_type channel_type;
+
+    MatND_();
+    MatND_(const Vector<int>& _sizes);
+    MatND_(const Vector<int>& _sizes, const _Tp& _s);
+    MatND_(const MatND& m);
+    MatND_(const MatND_& m);
+    MatND_(const MatND_& m, const Vector<Range>& ranges);
+    MatND_(const CvMatND* m, bool copyData=false);
+    MatND_& operator = (const MatND& m);
+    MatND_& operator = (const MatND_& m);
+    MatND_& operator = (const _Tp& s);
+
+    void create(const Vector<int>& _sizes);
+    template<typename T2> operator MatND_<T2>() const;
+    MatND_ clone() const;
+    MatND_ operator()(const Vector<Range>& ranges) const;
+
+    size_t elemSize() const;
+    size_t elemSize1() const;
+    int type() const;
+    int depth() const;
+    int channels() const;
+    size_t stepT(int i) const;
+    size_t step1(int i) const;
+
+    _Tp& operator ()(const int* idx);
+    const _Tp& operator ()(const int* idx) const;
+
+    _Tp& operator ()(int idx0, int idx1, int idx2);
+    const _Tp& operator ()(int idx0, int idx1, int idx2) const;
+};
+
+/////////////////////////// multi-dimensional sparse matrix //////////////////////////
+
+class SparseMatIterator;
+class SparseMatConstIterator;
+
+class CV_EXPORTS SparseMat
+{
+public:
+    typedef SparseMatIterator iterator;
+    typedef SparseMatConstIterator const_iterator;
+
+    struct CV_EXPORTS Hdr
+    {
+        Hdr(const Vector<int>& _sizes, int _type);
+        void clear();
+        int refcount;
+        int dims;
+        int valueOffset;
+        size_t nodeSize;
+        size_t nodeCount;
+        size_t freeList;
+        Vector<uchar> pool;
+        Vector<size_t> hashtab;
+        int size[CV_MAX_DIM];
+    };
+
+    struct CV_EXPORTS Node
+    {
+        size_t hashval;
+        size_t next;
+        int idx[CV_MAX_DIM];
+    };
+
+    SparseMat();
+    SparseMat(const Vector<int>& _sizes, int _type);
+    SparseMat(const SparseMat& m);
+    SparseMat(const Mat& m, bool try1d=false);
+    SparseMat(const MatND& m);
+    SparseMat(const CvSparseMat* m);
+    ~SparseMat();
+    SparseMat& operator = (const SparseMat& m);
+    SparseMat& operator = (const Mat& m);
+    SparseMat& operator = (const MatND& m);
+
+    SparseMat clone() const;
+    void copyTo( SparseMat& m ) const;
+    void copyTo( Mat& m ) const;
+    void copyTo( MatND& m ) const;
+    void convertTo( SparseMat& m, int rtype, double alpha=1 ) const;
+    void convertTo( Mat& m, int rtype, double alpha=1, double beta=0 ) const;
+    void convertTo( MatND& m, int rtype, double alpha=1, double beta=0 ) const;
+
+    void assignTo( SparseMat& m, int type=-1 ) const;
+
+    void create(const Vector<int>& _sizes, int _type);
+    void clear();
+    void addref();
+    void release();
+
+    operator CvSparseMat*() const;
+    size_t elemSize() const;
+    size_t elemSize1() const;
+    int type() const;
+    int depth() const;
+    int channels() const;
+    Vector<int> size() const;
+    int size(int i) const;
+    int dims() const;
+    size_t nzcount() const;
+    
+    size_t hash(int i0) const;
+    size_t hash(int i0, int i1) const;
+    size_t hash(int i0, int i1, int i2) const;
+    size_t hash(const int* idx) const;
+    
+    uchar* ptr(int i0, int i1, bool createMissing, size_t* hashval=0);
+    const uchar* get(int i0, int i1, size_t* hashval=0) const;
+    uchar* ptr(int i0, int i1, int i2, bool createMissing, size_t* hashval=0);
+    const uchar* get(int i0, int i1, int i2, size_t* hashval=0) const;
+    uchar* ptr(const int* idx, bool createMissing, size_t* hashval=0);
+    const uchar* get(const int* idx, size_t* hashval=0) const;
+
+    void erase(int i0, int i1, size_t* hashval=0);
+    void erase(int i0, int i1, int i2, size_t* hashval=0);
+    void erase(const int* idx, size_t* hashval=0);
+
+    SparseMatIterator begin();
+    SparseMatConstIterator begin() const;
+    SparseMatIterator end();
+    SparseMatConstIterator end() const;
+
+    uchar* value(Node* n);
+    const uchar* value(const Node* n) const;
+    Node* node(size_t nidx);
+    const Node* node(size_t nidx) const;
+
+    uchar* newNode(const int* idx, size_t hashval);
+    void removeNode(size_t hidx, size_t nidx, size_t previdx);
+    void resizeHashTab(size_t newsize);
+
+    enum { MAGIC_VAL=0x42FD0000, MAX_DIM=CV_MAX_DIM, HASH_SCALE=0x5bd1e995, HASH_BIT=0x80000000 };
+
+    int flags;
+    Hdr* hdr;
+};
+
+
+CV_EXPORTS void minMaxLoc(const SparseMat& a, double* minVal,
+                          double* maxVal, int* minIdx=0, int* maxIdx=0);
+CV_EXPORTS double norm( const SparseMat& src, int normType );
+CV_EXPORTS void normalize( const SparseMat& src, SparseMat& dst, double alpha, int normType );
+
+class CV_EXPORTS SparseMatConstIterator
+{
+public:
+    SparseMatConstIterator();
+    SparseMatConstIterator(const SparseMat* _m);
+    SparseMatConstIterator(const SparseMatConstIterator& it);
+
+    SparseMatConstIterator& operator = (const SparseMatConstIterator& it);
+    const uchar* value() const;
+    const SparseMat::Node* node() const;
+    
+    SparseMatConstIterator& operator --();
+    SparseMatConstIterator operator --(int);
+    SparseMatConstIterator& operator ++();
+    SparseMatConstIterator operator ++(int);
+
+    const SparseMat* m;
+    size_t hashidx;
+    uchar* ptr;
+};
+
+class CV_EXPORTS SparseMatIterator : public SparseMatConstIterator
+{
+public:
+    SparseMatIterator();
+    SparseMatIterator(SparseMat* _m);
+    SparseMatIterator(SparseMat* _m, const int* idx);
+    SparseMatIterator(const SparseMatIterator& it);
+
+    SparseMatIterator& operator = (const SparseMatIterator& it);
+    uchar* value() const;
+    SparseMat::Node* node() const;
+    
+    SparseMatIterator& operator ++();
+    SparseMatIterator operator ++(int);
+};
+
+
+template<typename _Tp> class SparseMatIterator_;
+template<typename _Tp> class SparseMatConstIterator_;
+
+template<typename _Tp> class CV_EXPORTS SparseMat_ : public SparseMat
+{
+public:
+    typedef SparseMatIterator_<_Tp> iterator;
+    typedef SparseMatConstIterator_<_Tp> const_iterator;
+
+    SparseMat_();
+    SparseMat_(const Vector<int>& _sizes);
+    SparseMat_(const SparseMat& m);
+    SparseMat_(const SparseMat_& m);
+    SparseMat_(const Mat& m);
+    SparseMat_(const MatND& m);
+    SparseMat_(const CvSparseMat* m);
+    SparseMat_& operator = (const SparseMat& m);
+    SparseMat_& operator = (const SparseMat_& m);
+    SparseMat_& operator = (const Mat& m);
+    SparseMat_& operator = (const MatND& m);
+
+    SparseMat_ clone() const;
+    void create(const Vector<int>& _sizes);
+    operator CvSparseMat*() const;
+
+    int type() const;
+    int depth() const;
+    int channels() const;
+    
+    _Tp& operator()(int i0, int i1, size_t* hashval=0);
+    _Tp operator()(int i0, int i1, size_t* hashval=0) const;
+    _Tp& operator()(int i0, int i1, int i2, size_t* hashval=0);
+    _Tp operator()(int i0, int i1, int i2, size_t* hashval=0) const;
+    _Tp& operator()(const int* idx, size_t* hashval=0);
+    _Tp operator()(const int* idx, size_t* hashval=0) const;
+
+    SparseMatIterator_<_Tp> begin();
+    SparseMatConstIterator_<_Tp> begin() const;
+    SparseMatIterator_<_Tp> end();
+    SparseMatConstIterator_<_Tp> end() const;
+};
+
+template<typename _Tp> class CV_EXPORTS SparseMatConstIterator_ : public SparseMatConstIterator
+{
+public:
+    typedef std::forward_iterator_tag iterator_category;
+    
+    SparseMatConstIterator_();
+    SparseMatConstIterator_(const SparseMat_<_Tp>* _m);
+    SparseMatConstIterator_(const SparseMatConstIterator_& it);
+
+    SparseMatConstIterator_& operator = (const SparseMatConstIterator_& it);
+    const _Tp& operator *() const;
+    
+    SparseMatConstIterator_& operator ++();
+    SparseMatConstIterator_ operator ++(int);
+
+protected:
+    const SparseMat_<_Tp>* m;
+    size_t hashidx;
+    uchar* ptr;
+};
+
+template<typename _Tp> class CV_EXPORTS SparseMatIterator_ : public SparseMatConstIterator_<_Tp>
+{
+public:
+    typedef std::forward_iterator_tag iterator_category;
+    
+    SparseMatIterator_();
+    SparseMatIterator_(SparseMat_<_Tp>* _m);
+    SparseMatIterator_(const SparseMatIterator_& it);
+
+    SparseMatIterator_& operator = (const SparseMatIterator_& it);
+    _Tp& operator *() const;
+    
+    SparseMatIterator_& operator ++();
+    SparseMatIterator_ operator ++(int);
+};
+
+//////////////////// Fast Nearest-Neighbor Search Structure ////////////////////
+
+class CV_EXPORTS KDTree
+{
+public:
+    struct Node
+    {
+        Node() : idx(-1), left(-1), right(-1), boundary(0.f) {}
+        Node(int _idx, int _left, int _right, float _boundary)
+            : idx(_idx), left(_left), right(_right), boundary(_boundary) {}
+        int idx;            // split dimension; >=0 for nodes (dim),
+                            // < 0 for leaves (index of the point)
+        int left, right;    // node indices of left and right branches
+        float boundary;     // left if vec[dim]<=boundary, otherwise right
+    };
+
+    KDTree();
+    KDTree(const Mat& _points, bool copyPoints=true);
+    void build(const Mat& _points, bool copyPoints=true);
+
+    void findNearest(const Mat& vec, int K, int Emax, Vector<int>* neighborsIdx,
+        Mat* neighbors=0, Vector<float>* dist=0) const;
+    void findNearest(const Vector<float>& vec, int K, int Emax, Vector<int>* neighborsIdx,
+        Vector<float>* neighbors=0, Vector<float>* dist=0) const;
+    void findOrthoRange(const Mat& minBounds, const Mat& maxBounds,
+        Vector<int>* neighborsIdx, Mat* neighbors=0) const;
+    void findOrthoRange(const Vector<float>& minBounds, const Vector<float>& maxBounds,
+        Vector<int>* neighborsIdx, Vector<float>* neighbors=0) const;
+    void getPoints(const Vector<int>& ids, Mat& pts) const;
+    void getPoints(const Vector<int>& ids, Vector<float>& pts) const;
+    Vector<float> at(int ptidx, bool copyData=false) const;
+
+    Vector<Node> nodes;
+    Mat points;
+    int maxDepth;
+};
+
+//////////////////////////////////////// XML & YAML I/O ////////////////////////////////////
+
+class CV_EXPORTS FileNode;
+
+class CV_EXPORTS FileStorage
+{
+public:
+    enum { READ=0, WRITE=1, APPEND=2 };
+    enum { UNDEFINED=0, VALUE_EXPECTED=1, NAME_EXPECTED=2, INSIDE_MAP=4 };
+    FileStorage();
+    FileStorage(const String& filename, int flags);
+    FileStorage(CvFileStorage* fs);
+    virtual ~FileStorage();
+
+    virtual bool open(const String& filename, int flags);
+    virtual bool isOpened() const;
+    virtual void release();
+
+    FileNode getFirstTopLevelNode() const;
+    FileNode root(int streamidx=0) const;
+    FileNode operator[](const String& nodename) const;
+    FileNode operator[](const char* nodename) const;
+
+    CvFileStorage* operator *() { return fs; }
+    const CvFileStorage* operator *() const { return fs; }
+    void writeRaw( const String& fmt, const Vector<uchar>& vec );
+    void writeObj( const String& name, const void* obj );
+
+    static String getDefaultObjectName(const String& filename);
+
+    Ptr<CvFileStorage> fs;
+    String elname;
+    Vector<char> structs;
+    int state;
+};
+
+class CV_EXPORTS FileNodeIterator;
+
+class CV_EXPORTS FileNode
+{
+public:
+    enum { NONE=0, INT=1, REAL=2, FLOAT=REAL, STR=3, STRING=STR, REF=4, SEQ=5, MAP=6, TYPE_MASK=7,
+        FLOW=8, USER=16, EMPTY=32, NAMED=64 };
+    FileNode();
+    FileNode(const CvFileStorage* fs, const CvFileNode* node);
+    FileNode(const FileNode& node);
+    FileNode operator[](const String& nodename) const;
+    FileNode operator[](const char* nodename) const;
+    FileNode operator[](int i) const;
+    int type() const;
+    int rawDataSize(const String& fmt) const;
+    bool isNone() const;
+    bool isSeq() const;
+    bool isMap() const;
+    bool isInt() const;
+    bool isReal() const;
+    bool isString() const;
+    bool isNamed() const;
+    String name() const;
+    size_t count() const;
+    operator int() const;
+    operator float() const;
+    operator double() const;
+    operator String() const;
+
+    FileNodeIterator begin() const;
+    FileNodeIterator end() const;
+
+    void readRaw( const String& fmt, Vector<uchar>& vec ) const;
+    void* readObj() const;
+
+    // do not use wrapper pointer classes for better efficiency
+    const CvFileStorage* fs;
+    const CvFileNode* node;
+};
+
+class CV_EXPORTS FileNodeIterator
+{
+public:
+    FileNodeIterator();
+    FileNodeIterator(const CvFileStorage* fs, const CvFileNode* node, size_t ofs=0);
+    FileNodeIterator(const FileNodeIterator& it);
+    FileNode operator *() const;
+    FileNode operator ->() const;
+
+    FileNodeIterator& operator ++();
+    FileNodeIterator operator ++(int);
+    FileNodeIterator& operator --();
+    FileNodeIterator operator --(int);
+    FileNodeIterator& operator += (int);
+    FileNodeIterator& operator -= (int);
+
+    FileNodeIterator& readRaw( const String& fmt, Vector<uchar>& vec,
+                               size_t maxCount=(size_t)INT_MAX );
+
+    const CvFileStorage* fs;
+    const CvFileNode* container;
+    CvSeqReader reader;
+    size_t remaining;
+};
+
+////////////// convenient wrappers for operating old-style dynamic structures //////////////
+
+// !!! NOTE that the wrappers are "thin", i.e. they do not call
+// any element constructors/destructors
+
+template<typename _Tp> class SeqIterator;
+
+template<> inline void Ptr<CvMemStorage>::delete_obj()
+{ cvReleaseMemStorage(&obj); }
+
+typedef Ptr<CvMemStorage> MemStorage;
+
+template<typename _Tp> class CV_EXPORTS Seq
+{
+public:
+    Seq();
+    Seq(const CvSeq* seq);
+    Seq(const MemStorage& storage, int headerSize = sizeof(CvSeq));
+    _Tp& operator [](int idx);
+    const _Tp& operator[](int idx) const;
+    SeqIterator<_Tp> begin() const;
+    SeqIterator<_Tp> end() const;
+    size_t size() const;
+    int type() const;
+    int depth() const;
+    int channels() const;
+    size_t elemSize() const;
+    size_t index(const _Tp& elem) const;
+    void push_back(const _Tp& elem);
+    void push_front(const _Tp& elem);
+    _Tp& front();
+    const _Tp& front() const;
+    _Tp& back();
+    const _Tp& back() const;
+    bool empty() const;
+
+    void clear();
+    void pop_front();
+    void pop_back();
+
+    void copyTo(Vector<_Tp>& vec, const Range& range=Range::all()) const;
+    operator Vector<_Tp>() const;
+    
+    CvSeq* seq;
+};
+
+template<typename _Tp> class CV_EXPORTS SeqIterator : public CvSeqReader
+{
+public:
+    SeqIterator();
+    SeqIterator(const Seq<_Tp>& seq, bool seekEnd=false);
+    void seek(size_t pos);
+    size_t tell() const;
+    _Tp& operator *();
+    const _Tp& operator *() const;
+    SeqIterator& operator ++();
+    SeqIterator operator ++(int) const;
+    SeqIterator& operator --();
+    SeqIterator operator --(int) const;
+
+    SeqIterator& operator +=(int);
+    SeqIterator& operator -=(int);
+
+    // this is index of the current element module seq->total*2
+    // (to distinguish between 0 and seq->total)
+    int index;
+};
+
+}
+
+#endif // __cplusplus
+
+#include "cxoperations.hpp"
+#include "cxmat.hpp"
+
+#endif /*_CXCORE_HPP_*/
index bdb2eb6f2c48a8ece6eb2c0818631c7c62413315..673a2590bbb7c30d5b335a1ead4e3fec0b395a65 100644 (file)
@@ -487,12 +487,8 @@ template<typename _Tp> inline Point_<_Tp>::Point_(const Size_<_Tp>& sz) : x(sz.w
 template<typename _Tp> inline Point_<_Tp>& Point_<_Tp>::operator = (const Point_& pt)
 { x = pt.x; y = pt.y; return *this; }
 
-template<typename _Tp> inline Point_<_Tp>::operator Point_<int>() const
-{ return Point_<int>(saturate_cast<int>(x), saturate_cast<int>(y)); }
-template<typename _Tp> inline Point_<_Tp>::operator Point_<float>() const
-{ return Point_<float>(float(x), float(y)); }
-template<typename _Tp> inline Point_<_Tp>::operator Point_<double>() const
-{ return Point_<double>(x, y); }
+template<typename _Tp> template<typename _Tp2> inline Point_<_Tp>::operator Point_<_Tp2>() const
+{ return Point_<_Tp2>(saturate_cast<_Tp2>(x), saturate_cast<_Tp2>(y)); }
 template<typename _Tp> inline Point_<_Tp>::operator CvPoint() const
 { return cvPoint(saturate_cast<int>(x), saturate_cast<int>(y)); }
 template<typename _Tp> inline Point_<_Tp>::operator CvPoint2D32f() const
@@ -543,12 +539,9 @@ template<typename _Tp> inline Point3_<_Tp>::Point3_(const CvPoint3D32f& pt) :
     x(saturate_cast<_Tp>(pt.x)), y(saturate_cast<_Tp>(pt.y)), z(saturate_cast<_Tp>(pt.z)) {}
 template<typename _Tp> inline Point3_<_Tp>::Point3_(const Vec<_Tp, 3>& t) : x(t[0]), y(t[1]), z(t[2]) {}
 
-template<typename _Tp> inline Point3_<_Tp>::operator Point3_<int>() const
-{ return Point3_<int>(saturate_cast<int>(x), saturate_cast<int>(y), saturate_cast<int>(z)); }
-template<typename _Tp> inline Point3_<_Tp>::operator Point3_<float>() const
-{ return Point3_<float>(float(x), float(y), float(z)); }
-template<typename _Tp> inline Point3_<_Tp>::operator Point3_<double>() const
-{ return Point3_<double>(x, y, z); }
+template<typename _Tp> template<typename _Tp2> inline Point3_<_Tp>::operator Point3_<_Tp2>() const
+{ return Point3_<_Tp2>(saturate_cast<_Tp2>(x), saturate_cast<_Tp2>(y), saturate_cast<_Tp2>(z)); }
+    
 template<typename _Tp> inline Point3_<_Tp>::operator CvPoint3D32f() const
 { return cvPoint3D32f((float)x, (float)y, (float)z); }
 
@@ -963,7 +956,7 @@ template <typename _Tp> inline Vector<_Tp>::Vector(_Tp* _data, size_t _size, boo
 template <typename _Tp> template<int n> inline Vector<_Tp>::Vector(const Vec<_Tp, n>& vec)
 { set((_Tp*)&vec.val[0], n, true); }
 template <typename _Tp> inline Vector<_Tp>::Vector(const std::vector<_Tp>& vec, bool _copyData)
-{ set(&vec[0], vec.size(), _copyData); }
+{ set((_Tp*)&vec[0], vec.size(), _copyData); }
 template <typename _Tp> inline Vector<_Tp>::Vector(const Vector& d)
 { *this = d; }
 template <typename _Tp> inline Vector<_Tp>::Vector(const Vector& d, const Range& r)
index 09e40c136fcdd9eac75c87584e1eb0e32ff385d9..4e809dbfc9fa878464bffa39af96dc7a1cdfdfd7 100644 (file)
-/*M///////////////////////////////////////////////////////////////////////////////////////\r
-//\r
-//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.\r
-//\r
-//  By downloading, copying, installing or using the software you agree to this license.\r
-//  If you do not agree to this license, do not download, install,\r
-//  copy or use the software.\r
-//\r
-//\r
-//                        Intel License Agreement\r
-//                For Open Source Computer Vision Library\r
-//\r
-// Copyright (C) 2000, Intel Corporation, all rights reserved.\r
-// Third party copyrights are property of their respective owners.\r
-//\r
-// Redistribution and use in source and binary forms, with or without modification,\r
-// are permitted provided that the following conditions are met:\r
-//\r
-//   * Redistribution's of source code must retain the above copyright notice,\r
-//     this list of conditions and the following disclaimer.\r
-//\r
-//   * Redistribution's in binary form must reproduce the above copyright notice,\r
-//     this list of conditions and the following disclaimer in the documentation\r
-//     and/or other materials provided with the distribution.\r
-//\r
-//   * The name of Intel Corporation may not be used to endorse or promote products\r
-//     derived from this software without specific prior written permission.\r
-//\r
-// This software is provided by the copyright holders and contributors "as is" and\r
-// any express or implied warranties, including, but not limited to, the implied\r
-// warranties of merchantability and fitness for a particular purpose are disclaimed.\r
-// In no event shall the Intel Corporation or contributors be liable for any direct,\r
-// indirect, incidental, special, exemplary, or consequential damages\r
-// (including, but not limited to, procurement of substitute goods or services;\r
-// loss of use, data, or profits; or business interruption) however caused\r
-// and on any theory of liability, whether in contract, strict liability,\r
-// or tort (including negligence or otherwise) arising in any way out of\r
-// the use of this software, even if advised of the possibility of such damage.\r
-//\r
-//M*/\r
-#include "_cv.h"\r
-\r
-namespace cv\r
-{\r
-\r
-template<typename T> struct lessThanPtr\r
-{\r
-    bool operator()(const T* a, const T* b) const { return *a < *b; }\r
-};\r
-\r
-void goodFeaturesToTrack( const Mat& image, Vector<Point2f>& corners,\r
-                          int maxCorners, double qualityLevel, double minDistance,\r
-                          const Mat& mask, int blockSize,\r
-                          bool useHarrisDetector, double harrisK )\r
-{\r
-    CV_Assert( qualityLevel > 0 && minDistance >= 0 && maxCorners >= 0 );\r
-\r
-    if( mask.data )\r
-        CV_Assert( mask.type() == CV_8UC1 && mask.size() == image.size() );\r
-\r
-    Mat eig, tmp;\r
-    if( useHarrisDetector )\r
-        cornerHarris( image, eig, blockSize, 3, harrisK );\r
-    else\r
-        cornerMinEigenVal( image, eig, blockSize, 3 );\r
-\r
-    double maxVal = 0;\r
-    minMaxLoc( eig, 0, &maxVal, 0, 0, mask );\r
-    threshold( eig, eig, maxVal*qualityLevel, 0, THRESH_TOZERO );\r
-    dilate( eig, tmp, Mat());\r
-\r
-    Size imgsize = image.size();\r
-\r
-    Vector<const float*> tmpCorners;\r
-\r
-    // collect list of pointers to features - put them into temporary image\r
-    for( int y = 1; y < imgsize.height - 1; y++ )\r
-    {\r
-        const float* eig_data = (const float*)eig.ptr(y);\r
-        const float* tmp_data = (const float*)tmp.ptr(y);\r
-        const uchar* mask_data = mask.data ? mask.ptr(y) : 0;\r
-\r
-        for( int x = 1; x < imgsize.width - 1; x++ )\r
-        {\r
-            float val = eig_data[x];\r
-            if( val != 0 && val == tmp_data[x] && (!mask_data || mask_data[x]) )\r
-                tmpCorners.push_back(eig_data + x);\r
-        }\r
-    }\r
-\r
-    sort( tmpCorners, lessThanPtr<float>() );\r
-    corners.clear();\r
-    size_t i, j, total = tmpCorners.size(), ncorners = 0;\r
-    \r
-    minDistance *= minDistance;\r
-\r
-    // select the strongest features\r
-    for( i = 0; i < total; i++ )\r
-    {\r
-        int ofs = (int)((const uchar*)tmpCorners[i] - eig.data);\r
-        int y = (int)(ofs / eig.step);\r
-        int x = (int)((ofs - y*eig.step)/sizeof(float));\r
-\r
-        if( minDistance > 0 )\r
-        {\r
-            for( j = 0; j < ncorners; j++ )\r
-            {\r
-                float dx = x - corners[j].x;\r
-                float dy = y - corners[j].y;\r
-                if( dx*dx + dy*dy < minDistance )\r
-                    break;\r
-            }\r
-            if( j < ncorners )\r
-                continue;\r
-        }\r
-\r
-        corners.push_back(Point2f((float)x, (float)y));\r
-        ++ncorners;\r
-        if( maxCorners > 0 && (int)ncorners == maxCorners )\r
-            break;\r
-    }\r
-}\r
-\r
-}\r
-\r
-CV_IMPL void\r
-cvGoodFeaturesToTrack( const void* _image, void*, void*,\r
-                       CvPoint2D32f* _corners, int *_corner_count,\r
-                       double quality_level, double min_distance,\r
-                       const void* _maskImage, int block_size,\r
-                       int use_harris, double harris_k )\r
-{\r
-    cv::Mat image = cv::cvarrToMat(_image), mask;\r
-    cv::Vector<cv::Point2f> corners;\r
-\r
-    if( _maskImage )\r
-        mask = cv::cvarrToMat(_maskImage);\r
-\r
-    CV_Assert( _corners && _corner_count );\r
-    cv::goodFeaturesToTrack( image, corners, *_corner_count, quality_level,\r
-        min_distance, mask, block_size, use_harris != 0, harris_k );\r
-\r
-    size_t i, ncorners = corners.size();\r
-    for( i = 0; i < ncorners; i++ )\r
-        _corners[i] = corners[i];\r
-    *_corner_count = (int)ncorners;\r
-}\r
-\r
-/* End of file. */\r
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+//  By downloading, copying, installing or using the software you agree to this license.
+//  If you do not agree to this license, do not download, install,
+//  copy or use the software.
+//
+//
+//                        Intel License Agreement
+//                For Open Source Computer Vision Library
+//
+// Copyright (C) 2000, Intel Corporation, all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+//   * Redistribution's of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//
+//   * Redistribution's in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//
+//   * The name of Intel Corporation may not be used to endorse or promote products
+//     derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+#include "_cv.h"
+
+namespace cv
+{
+
+template<typename T> struct lessThanPtr
+{
+    bool operator()(const T* a, const T* b) const { return *a < *b; }
+};
+
+void goodFeaturesToTrack( const Mat& image, Vector<Point2f>& corners,
+                          int maxCorners, double qualityLevel, double minDistance,
+                          const Mat& mask, int blockSize,
+                          bool useHarrisDetector, double harrisK )
+{
+    CV_Assert( qualityLevel > 0 && minDistance >= 0 && maxCorners >= 0 );
+
+    if( mask.data )
+        CV_Assert( mask.type() == CV_8UC1 && mask.size() == image.size() );
+
+    Mat eig, tmp;
+    if( useHarrisDetector )
+        cornerHarris( image, eig, blockSize, 3, harrisK );
+    else
+        cornerMinEigenVal( image, eig, blockSize, 3 );
+
+    double maxVal = 0;
+    minMaxLoc( eig, 0, &maxVal, 0, 0, mask );
+    threshold( eig, eig, maxVal*qualityLevel, 0, THRESH_TOZERO );
+    dilate( eig, tmp, Mat());
+
+    Size imgsize = image.size();
+
+    Vector<const float*> tmpCorners;
+
+    // collect list of pointers to features - put them into temporary image
+    for( int y = 1; y < imgsize.height - 1; y++ )
+    {
+        const float* eig_data = (const float*)eig.ptr(y);
+        const float* tmp_data = (const float*)tmp.ptr(y);
+        const uchar* mask_data = mask.data ? mask.ptr(y) : 0;
+
+        for( int x = 1; x < imgsize.width - 1; x++ )
+        {
+            float val = eig_data[x];
+            if( val != 0 && val == tmp_data[x] && (!mask_data || mask_data[x]) )
+                tmpCorners.push_back(eig_data + x);
+        }
+    }
+
+    sort( tmpCorners, lessThanPtr<float>() );
+    corners.clear();
+    size_t i, j, total = tmpCorners.size(), ncorners = 0;
+    
+    minDistance *= minDistance;
+
+    // select the strongest features
+    for( i = 0; i < total; i++ )
+    {
+        int ofs = (int)((const uchar*)tmpCorners[i] - eig.data);
+        int y = (int)(ofs / eig.step);
+        int x = (int)((ofs - y*eig.step)/sizeof(float));
+
+        if( minDistance > 0 )
+        {
+            for( j = 0; j < ncorners; j++ )
+            {
+                float dx = x - corners[j].x;
+                float dy = y - corners[j].y;
+                if( dx*dx + dy*dy < minDistance )
+                    break;
+            }
+            if( j < ncorners )
+                continue;
+        }
+
+        corners.push_back(Point2f((float)x, (float)y));
+        ++ncorners;
+        if( maxCorners > 0 && (int)ncorners == maxCorners )
+            break;
+    }
+}
+    
+void write(FileStorage& fs, const String& objname, const Vector<Keypoint>& keypoints)
+{
+    WriteStructContext ws(fs, objname, CV_NODE_SEQ + CV_NODE_FLOW);
+    
+    int i, npoints = (int)keypoints.size();
+    for( i = 0; i < npoints; i++ )
+    {
+        const Keypoint& kpt = keypoints[i];
+        write(fs, kpt.pt.x);
+        write(fs, kpt.pt.y);
+        write(fs, kpt.size);
+        write(fs, kpt.angle);
+        write(fs, kpt.response);
+        write(fs, kpt.octave);
+    }
+}
+
+
+void read(const FileNode& node, Vector<Keypoint>& keypoints)
+{
+    keypoints.resize(0);
+    FileNodeIterator it = node.begin(), it_end = node.end();
+    for( ; it != it_end; )
+    {
+        Keypoint kpt;
+        it >> kpt.pt.x >> kpt.pt.y >> kpt.size >> kpt.angle >> kpt.response >> kpt.octave;
+        keypoints.push_back(kpt);
+    }
+}
+    
+}
+
+CV_IMPL void
+cvGoodFeaturesToTrack( const void* _image, void*, void*,
+                       CvPoint2D32f* _corners, int *_corner_count,
+                       double quality_level, double min_distance,
+                       const void* _maskImage, int block_size,
+                       int use_harris, double harris_k )
+{
+    cv::Mat image = cv::cvarrToMat(_image), mask;
+    cv::Vector<cv::Point2f> corners;
+
+    if( _maskImage )
+        mask = cv::cvarrToMat(_maskImage);
+
+    CV_Assert( _corners && _corner_count );
+    cv::goodFeaturesToTrack( image, corners, *_corner_count, quality_level,
+        min_distance, mask, block_size, use_harris != 0, harris_k );
+
+    size_t i, ncorners = corners.size();
+    for( i = 0; i < ncorners; i++ )
+        _corners[i] = corners[i];
+    *_corner_count = (int)ncorners;
+}
+
+/* End of file. */
index f7ea8e07921879f367853d20d2ef27b0c534c50a..82355d7041ad2ac6d0ce52c8edd076e3a1ed83eb 100644 (file)
-/*M///////////////////////////////////////////////////////////////////////////////////////\r
-//\r
-//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.\r
-//\r
-//  By downloading, copying, installing or using the software you agree to this license.\r
-//  If you do not agree to this license, do not download, install,\r
-//  copy or use the software.\r
-//\r
-//\r
-//                        Intel License Agreement\r
-//                For Open Source Computer Vision Library\r
-//\r
-// Copyright (C) 2000, Intel Corporation, all rights reserved.\r
-// Third party copyrights are property of their respective owners.\r
-//\r
-// Redistribution and use in source and binary forms, with or without modification,\r
-// are permitted provided that the following conditions are met:\r
-//\r
-//   * Redistribution's of source code must retain the above copyright notice,\r
-//     this list of conditions and the following disclaimer.\r
-//\r
-//   * Redistribution's in binary form must reproduce the above copyright notice,\r
-//     this list of conditions and the following disclaimer in the documentation\r
-//     and/or other materials provided with the distribution.\r
-//\r
-//   * The name of Intel Corporation may not be used to endorse or promote products\r
-//     derived from this software without specific prior written permission.\r
-//\r
-// This software is provided by the copyright holders and contributors "as is" and\r
-// any express or implied warranties, including, but not limited to, the implied\r
-// warranties of merchantability and fitness for a particular purpose are disclaimed.\r
-// In no event shall the Intel Corporation or contributors be liable for any direct,\r
-// indirect, incidental, special, exemplary, or consequential damages\r
-// (including, but not limited to, procurement of substitute goods or services;\r
-// loss of use, data, or profits; or business interruption) however caused\r
-// and on any theory of liability, whether in contract, strict liability,\r
-// or tort (including negligence or otherwise) arising in any way out of\r
-// the use of this software, even if advised of the possibility of such damage.\r
-//\r
-//M*/\r
-\r
-#include "_cv.h"\r
-#include "_cvmodelest.h"\r
-\r
-template<typename T> int icvCompressPoints( T* ptr, const uchar* mask, int mstep, int count )\r
-{\r
-    int i, j;\r
-    for( i = j = 0; i < count; i++ )\r
-        if( mask[i*mstep] )\r
-        {\r
-            if( i > j )\r
-                ptr[j] = ptr[i];\r
-            j++;\r
-        }\r
-    return j;\r
-}\r
-\r
-class CvHomographyEstimator : public CvModelEstimator2\r
-{\r
-public:\r
-    CvHomographyEstimator( int modelPoints );\r
-\r
-    virtual int runKernel( const CvMat* m1, const CvMat* m2, CvMat* model );\r
-    virtual bool refine( const CvMat* m1, const CvMat* m2,\r
-                         CvMat* model, int maxIters );\r
-protected:\r
-    virtual void computeReprojError( const CvMat* m1, const CvMat* m2,\r
-                                     const CvMat* model, CvMat* error );\r
-};\r
-\r
-\r
-CvHomographyEstimator::CvHomographyEstimator(int _modelPoints)\r
-    : CvModelEstimator2(_modelPoints, cvSize(3,3), 1)\r
-{\r
-    assert( _modelPoints == 4 || _modelPoints == 5 );\r
-}\r
-\r
-int CvHomographyEstimator::runKernel( const CvMat* m1, const CvMat* m2, CvMat* H )\r
-{\r
-    int i, count = m1->rows*m1->cols;\r
-    const CvPoint2D64f* M = (const CvPoint2D64f*)m1->data.ptr;\r
-    const CvPoint2D64f* m = (const CvPoint2D64f*)m2->data.ptr;\r
-\r
-    double LtL[9][9], W[9][9], V[9][9];\r
-    CvMat _LtL = cvMat( 9, 9, CV_64F, LtL );\r
-    CvMat _W = cvMat( 9, 9, CV_64F, W );\r
-    CvMat _V = cvMat( 9, 9, CV_64F, V );\r
-    CvMat _H0 = cvMat( 3, 3, CV_64F, V[8] );\r
-    CvMat _Htemp = cvMat( 3, 3, CV_64F, V[7] );\r
-    CvPoint2D64f cM={0,0}, cm={0,0}, sM={0,0}, sm={0,0};\r
-\r
-    for( i = 0; i < count; i++ )\r
-    {\r
-        cm.x += m[i].x; cm.y += m[i].y;\r
-        cM.x += M[i].x; cM.y += M[i].y;\r
-    }\r
-\r
-    cm.x /= count; cm.y /= count;\r
-    cM.x /= count; cM.y /= count;\r
-\r
-    for( i = 0; i < count; i++ )\r
-    {\r
-        sm.x += fabs(m[i].x - cm.x);\r
-        sm.y += fabs(m[i].y - cm.y);\r
-        sM.x += fabs(M[i].x - cM.x);\r
-        sM.y += fabs(M[i].y - cM.y);\r
-    }\r
-\r
-    sm.x = count/sm.x; sm.y = count/sm.y;\r
-    sM.x = count/sM.x; sM.y = count/sM.y;\r
-\r
-    double invHnorm[9] = { 1./sm.x, 0, cm.x, 0, 1./sm.y, cm.y, 0, 0, 1 };\r
-    double Hnorm2[9] = { sM.x, 0, -cM.x*sM.x, 0, sM.y, -cM.y*sM.y, 0, 0, 1 };\r
-    CvMat _invHnorm = cvMat( 3, 3, CV_64FC1, invHnorm );\r
-    CvMat _Hnorm2 = cvMat( 3, 3, CV_64FC1, Hnorm2 );\r
-\r
-    cvZero( &_LtL );\r
-    for( i = 0; i < count; i++ )\r
-    {\r
-        double x = (m[i].x - cm.x)*sm.x, y = (m[i].y - cm.y)*sm.y;\r
-        double X = (M[i].x - cM.x)*sM.x, Y = (M[i].y - cM.y)*sM.y;\r
-        double Lx[] = { X, Y, 1, 0, 0, 0, -x*X, -x*Y, -x };\r
-        double Ly[] = { 0, 0, 0, X, Y, 1, -y*X, -y*Y, -y };\r
-        int j, k;\r
-        for( j = 0; j < 9; j++ )\r
-            for( k = j; k < 9; k++ )\r
-                LtL[j][k] += Lx[j]*Lx[k] + Ly[j]*Ly[k];\r
-    }\r
-    cvCompleteSymm( &_LtL );\r
-\r
-    cvSVD( &_LtL, &_W, 0, &_V, CV_SVD_MODIFY_A + CV_SVD_V_T );\r
-    cvMatMul( &_invHnorm, &_H0, &_Htemp );\r
-    cvMatMul( &_Htemp, &_Hnorm2, &_H0 );\r
-    cvConvertScale( &_H0, H, 1./_H0.data.db[8] );\r
-\r
-    return 1;\r
-}\r
-\r
-\r
-void CvHomographyEstimator::computeReprojError( const CvMat* m1, const CvMat* m2,\r
-                                                const CvMat* model, CvMat* _err )\r
-{\r
-    int i, count = m1->rows*m1->cols;\r
-    const CvPoint2D64f* M = (const CvPoint2D64f*)m1->data.ptr;\r
-    const CvPoint2D64f* m = (const CvPoint2D64f*)m2->data.ptr;\r
-    const double* H = model->data.db;\r
-    float* err = _err->data.fl;\r
-\r
-    for( i = 0; i < count; i++ )\r
-    {\r
-        double ww = 1./(H[6]*M[i].x + H[7]*M[i].y + 1.);\r
-        double dx = (H[0]*M[i].x + H[1]*M[i].y + H[2])*ww - m[i].x;\r
-        double dy = (H[3]*M[i].x + H[4]*M[i].y + H[5])*ww - m[i].y;\r
-        err[i] = (float)(dx*dx + dy*dy);\r
-    }\r
-}\r
-\r
-bool CvHomographyEstimator::refine( const CvMat* m1, const CvMat* m2, CvMat* model, int maxIters )\r
-{\r
-    CvLevMarq solver(8, 0, cvTermCriteria(CV_TERMCRIT_ITER+CV_TERMCRIT_EPS, maxIters, DBL_EPSILON));\r
-    int i, j, k, count = m1->rows*m1->cols;\r
-    const CvPoint2D64f* M = (const CvPoint2D64f*)m1->data.ptr;\r
-    const CvPoint2D64f* m = (const CvPoint2D64f*)m2->data.ptr;\r
-    CvMat modelPart = cvMat( solver.param->rows, solver.param->cols, model->type, model->data.ptr );\r
-    cvCopy( &modelPart, solver.param );\r
-\r
-    for(;;)\r
-    {\r
-        const CvMat* _param = 0;\r
-        CvMat *_JtJ = 0, *_JtErr = 0;\r
-        double* _errNorm = 0;\r
-\r
-        if( !solver.updateAlt( _param, _JtJ, _JtErr, _errNorm ))\r
-            break;\r
-\r
-        for( i = 0; i < count; i++ )\r
-        {\r
-            const double* h = _param->data.db;\r
-            double Mx = M[i].x, My = M[i].y;\r
-            double ww = 1./(h[6]*Mx + h[7]*My + 1.);\r
-            double _xi = (h[0]*Mx + h[1]*My + h[2])*ww;\r
-            double _yi = (h[3]*Mx + h[4]*My + h[5])*ww;\r
-            double err[] = { _xi - m[i].x, _yi - m[i].y };\r
-            if( _JtJ || _JtErr )\r
-            {\r
-                double J[][8] =\r
-                {\r
-                    { Mx*ww, My*ww, ww, 0, 0, 0, -Mx*ww*_xi, -My*ww*_xi },\r
-                    { 0, 0, 0, Mx*ww, My*ww, ww, -Mx*ww*_yi, -My*ww*_yi }\r
-                };\r
-\r
-                for( j = 0; j < 8; j++ )\r
-                {\r
-                    for( k = j; k < 8; k++ )\r
-                        _JtJ->data.db[j*8+k] += J[0][j]*J[0][k] + J[1][j]*J[1][k];\r
-                    _JtErr->data.db[j] += J[0][j]*err[0] + J[1][j]*err[1];\r
-                }\r
-            }\r
-            if( _errNorm )\r
-                *_errNorm += err[0]*err[0] + err[1]*err[1];\r
-        }\r
-    }\r
-\r
-    cvCopy( solver.param, &modelPart );\r
-    return true;\r
-}\r
-\r
-\r
-CV_IMPL int\r
-cvFindHomography( const CvMat* objectPoints, const CvMat* imagePoints,\r
-                  CvMat* __H, int method, double ransacReprojThreshold,\r
-                  CvMat* mask )\r
-{\r
-    const double confidence = 0.99;\r
-    bool result = false;\r
-    CvMat *m = 0, *M = 0, *tempMask = 0;\r
-\r
-    CV_FUNCNAME( "cvFindHomography" );\r
-\r
-    __BEGIN__;\r
-\r
-    double H[9];\r
-    CvMat _H = cvMat( 3, 3, CV_64FC1, H );\r
-    int count;\r
-\r
-    CV_ASSERT( CV_IS_MAT(imagePoints) && CV_IS_MAT(objectPoints) );\r
-\r
-    count = MAX(imagePoints->cols, imagePoints->rows);\r
-    CV_ASSERT( count >= 4 );\r
-\r
-    m = cvCreateMat( 1, count, CV_64FC2 );\r
-    cvConvertPointsHomogeneous( imagePoints, m );\r
-\r
-    M = cvCreateMat( 1, count, CV_64FC2 );\r
-    cvConvertPointsHomogeneous( objectPoints, M );\r
-\r
-    if( mask )\r
-    {\r
-        CV_ASSERT( CV_IS_MASK_ARR(mask) && CV_IS_MAT_CONT(mask->type) &&\r
-            (mask->rows == 1 || mask->cols == 1) &&\r
-            mask->rows*mask->cols == count );\r
-        tempMask = mask;\r
-    }\r
-    else if( count > 4 )\r
-        tempMask = cvCreateMat( 1, count, CV_8U );\r
-    if( tempMask )\r
-        cvSet( tempMask, cvScalarAll(1.) );\r
-\r
-    {\r
-    CvHomographyEstimator estimator( MIN(count, 5) );\r
-    if( count == 4 )\r
-        method = 0;\r
-    if( method == CV_LMEDS )\r
-        result = estimator.runLMeDS( M, m, &_H, tempMask, confidence );\r
-    else if( method == CV_RANSAC )\r
-        result = estimator.runRANSAC( M, m, &_H, tempMask, ransacReprojThreshold, confidence );\r
-    else\r
-        result = estimator.runKernel( M, m, &_H ) > 0;\r
-\r
-    if( result && count > 4 )\r
-    {\r
-        icvCompressPoints( (CvPoint2D64f*)M->data.ptr, tempMask->data.ptr, 1, count );\r
-        count = icvCompressPoints( (CvPoint2D64f*)m->data.ptr, tempMask->data.ptr, 1, count );\r
-        M->cols = m->cols = count;\r
-        estimator.refine( M, m, &_H, 10 );\r
-    }\r
-    }\r
-\r
-    if( result )\r
-        cvConvert( &_H, __H );\r
-\r
-    __END__;\r
-\r
-    cvReleaseMat( &m );\r
-    cvReleaseMat( &M );\r
-    if( tempMask != mask )\r
-        cvReleaseMat( &tempMask );\r
-\r
-    return (int)result;\r
-}\r
-\r
-\r
-/* Evaluation of Fundamental Matrix from point correspondences.\r
-   The original code has been written by Valery Mosyagin */\r
-\r
-/* The algorithms (except for RANSAC) and the notation have been taken from\r
-   Zhengyou Zhang's research report\r
-   "Determining the Epipolar Geometry and its Uncertainty: A Review"\r
-   that can be found at http://www-sop.inria.fr/robotvis/personnel/zzhang/zzhang-eng.html */\r
-\r
-/************************************** 7-point algorithm *******************************/\r
-class CvFMEstimator : public CvModelEstimator2\r
-{\r
-public:\r
-    CvFMEstimator( int _modelPoints );\r
-\r
-    virtual int runKernel( const CvMat* m1, const CvMat* m2, CvMat* model );\r
-    virtual int run7Point( const CvMat* m1, const CvMat* m2, CvMat* model );\r
-    virtual int run8Point( const CvMat* m1, const CvMat* m2, CvMat* model );\r
-protected:\r
-    virtual void computeReprojError( const CvMat* m1, const CvMat* m2,\r
-                                     const CvMat* model, CvMat* error );\r
-};\r
-\r
-CvFMEstimator::CvFMEstimator( int _modelPoints )\r
-: CvModelEstimator2( _modelPoints, cvSize(3,3), _modelPoints == 7 ? 3 : 1 )\r
-{\r
-    assert( _modelPoints == 7 || _modelPoints == 8 );\r
-}\r
-\r
-\r
-int CvFMEstimator::runKernel( const CvMat* m1, const CvMat* m2, CvMat* model )\r
-{\r
-    return modelPoints == 7 ? run7Point( m1, m2, model ) : run8Point( m1, m2, model );\r
-}\r
-\r
-int CvFMEstimator::run7Point( const CvMat* _m1, const CvMat* _m2, CvMat* _fmatrix )\r
-{\r
-    double a[7*9], w[7], v[9*9], c[4], r[3];\r
-    double* f1, *f2;\r
-    double t0, t1, t2;\r
-    CvMat A = cvMat( 7, 9, CV_64F, a );\r
-    CvMat V = cvMat( 9, 9, CV_64F, v );\r
-    CvMat W = cvMat( 7, 1, CV_64F, w );\r
-    CvMat coeffs = cvMat( 1, 4, CV_64F, c );\r
-    CvMat roots = cvMat( 1, 3, CV_64F, r );\r
-    const CvPoint2D64f* m1 = (const CvPoint2D64f*)_m1->data.ptr;\r
-    const CvPoint2D64f* m2 = (const CvPoint2D64f*)_m2->data.ptr;\r
-    double* fmatrix = _fmatrix->data.db;\r
-    int i, k, n;\r
-\r
-    // form a linear system: i-th row of A(=a) represents\r
-    // the equation: (m2[i], 1)'*F*(m1[i], 1) = 0\r
-    for( i = 0; i < 7; i++ )\r
-    {\r
-        double x0 = m1[i].x, y0 = m1[i].y;\r
-        double x1 = m2[i].x, y1 = m2[i].y;\r
-\r
-        a[i*9+0] = x1*x0;\r
-        a[i*9+1] = x1*y0;\r
-        a[i*9+2] = x1;\r
-        a[i*9+3] = y1*x0;\r
-        a[i*9+4] = y1*y0;\r
-        a[i*9+5] = y1;\r
-        a[i*9+6] = x0;\r
-        a[i*9+7] = y0;\r
-        a[i*9+8] = 1;\r
-    }\r
-\r
-    // A*(f11 f12 ... f33)' = 0 is singular (7 equations for 9 variables), so\r
-    // the solution is linear subspace of dimensionality 2.\r
-    // => use the last two singular vectors as a basis of the space\r
-    // (according to SVD properties)\r
-    cvSVD( &A, &W, 0, &V, CV_SVD_MODIFY_A + CV_SVD_V_T );\r
-    f1 = v + 7*9;\r
-    f2 = v + 8*9;\r
-\r
-    // f1, f2 is a basis => lambda*f1 + mu*f2 is an arbitrary f. matrix.\r
-    // as it is determined up to a scale, normalize lambda & mu (lambda + mu = 1),\r
-    // so f ~ lambda*f1 + (1 - lambda)*f2.\r
-    // use the additional constraint det(f) = det(lambda*f1 + (1-lambda)*f2) to find lambda.\r
-    // it will be a cubic equation.\r
-    // find c - polynomial coefficients.\r
-    for( i = 0; i < 9; i++ )\r
-        f1[i] -= f2[i];\r
-\r
-    t0 = f2[4]*f2[8] - f2[5]*f2[7];\r
-    t1 = f2[3]*f2[8] - f2[5]*f2[6];\r
-    t2 = f2[3]*f2[7] - f2[4]*f2[6];\r
-\r
-    c[3] = f2[0]*t0 - f2[1]*t1 + f2[2]*t2;\r
-\r
-    c[2] = f1[0]*t0 - f1[1]*t1 + f1[2]*t2 -\r
-           f1[3]*(f2[1]*f2[8] - f2[2]*f2[7]) +\r
-           f1[4]*(f2[0]*f2[8] - f2[2]*f2[6]) -\r
-           f1[5]*(f2[0]*f2[7] - f2[1]*f2[6]) +\r
-           f1[6]*(f2[1]*f2[5] - f2[2]*f2[4]) -\r
-           f1[7]*(f2[0]*f2[5] - f2[2]*f2[3]) +\r
-           f1[8]*(f2[0]*f2[4] - f2[1]*f2[3]);\r
-\r
-    t0 = f1[4]*f1[8] - f1[5]*f1[7];\r
-    t1 = f1[3]*f1[8] - f1[5]*f1[6];\r
-    t2 = f1[3]*f1[7] - f1[4]*f1[6];\r
-\r
-    c[1] = f2[0]*t0 - f2[1]*t1 + f2[2]*t2 -\r
-           f2[3]*(f1[1]*f1[8] - f1[2]*f1[7]) +\r
-           f2[4]*(f1[0]*f1[8] - f1[2]*f1[6]) -\r
-           f2[5]*(f1[0]*f1[7] - f1[1]*f1[6]) +\r
-           f2[6]*(f1[1]*f1[5] - f1[2]*f1[4]) -\r
-           f2[7]*(f1[0]*f1[5] - f1[2]*f1[3]) +\r
-           f2[8]*(f1[0]*f1[4] - f1[1]*f1[3]);\r
-\r
-    c[0] = f1[0]*t0 - f1[1]*t1 + f1[2]*t2;\r
-\r
-    // solve the cubic equation; there can be 1 to 3 roots ...\r
-    n = cvSolveCubic( &coeffs, &roots );\r
-\r
-    if( n < 1 || n > 3 )\r
-        return n;\r
-\r
-    for( k = 0; k < n; k++, fmatrix += 9 )\r
-    {\r
-        // for each root form the fundamental matrix\r
-        double lambda = r[k], mu = 1.;\r
-        double s = f1[8]*r[k] + f2[8];\r
-\r
-        // normalize each matrix, so that F(3,3) (~fmatrix[8]) == 1\r
-        if( fabs(s) > DBL_EPSILON )\r
-        {\r
-            mu = 1./s;\r
-            lambda *= mu;\r
-            fmatrix[8] = 1.;\r
-        }\r
-        else\r
-            fmatrix[8] = 0.;\r
-\r
-        for( i = 0; i < 8; i++ )\r
-            fmatrix[i] = f1[i]*lambda + f2[i]*mu;\r
-    }\r
-\r
-    return n;\r
-}\r
-\r
-\r
-int CvFMEstimator::run8Point( const CvMat* _m1, const CvMat* _m2, CvMat* _fmatrix )\r
-{\r
-    double a[9*9], w[9], v[9*9];\r
-    CvMat W = cvMat( 1, 9, CV_64F, w );\r
-    CvMat V = cvMat( 9, 9, CV_64F, v );\r
-    CvMat A = cvMat( 9, 9, CV_64F, a );\r
-    CvMat U, F0, TF;\r
-\r
-    CvPoint2D64f m0c = {0,0}, m1c = {0,0};\r
-    double t, scale0 = 0, scale1 = 0;\r
-\r
-    const CvPoint2D64f* m1 = (const CvPoint2D64f*)_m1->data.ptr;\r
-    const CvPoint2D64f* m2 = (const CvPoint2D64f*)_m2->data.ptr;\r
-    double* fmatrix = _fmatrix->data.db;\r
-    int i, j, k, count = _m1->cols*_m1->rows;\r
-\r
-    // compute centers and average distances for each of the two point sets\r
-    for( i = 0; i < count; i++ )\r
-    {\r
-        double x = m1[i].x, y = m1[i].y;\r
-        m0c.x += x; m0c.y += y;\r
-\r
-        x = m2[i].x, y = m2[i].y;\r
-        m1c.x += x; m1c.y += y;\r
-    }\r
-\r
-    // calculate the normalizing transformations for each of the point sets:\r
-    // after the transformation each set will have the mass center at the coordinate origin\r
-    // and the average distance from the origin will be ~sqrt(2).\r
-    t = 1./count;\r
-    m0c.x *= t; m0c.y *= t;\r
-    m1c.x *= t; m1c.y *= t;\r
-\r
-    for( i = 0; i < count; i++ )\r
-    {\r
-        double x = m1[i].x - m0c.x, y = m1[i].y - m0c.y;\r
-        scale0 += sqrt(x*x + y*y);\r
-\r
-        x = fabs(m2[i].x - m1c.x), y = fabs(m2[i].y - m1c.y);\r
-        scale1 += sqrt(x*x + y*y);\r
-    }\r
-\r
-    scale0 *= t;\r
-    scale1 *= t;\r
-\r
-    if( scale0 < FLT_EPSILON || scale1 < FLT_EPSILON )\r
-        return 0;\r
-\r
-    scale0 = sqrt(2.)/scale0;\r
-    scale1 = sqrt(2.)/scale1;\r
-    \r
-    cvZero( &A );\r
-\r
-    // form a linear system Ax=0: for each selected pair of points m1 & m2,\r
-    // the row of A(=a) represents the coefficients of equation: (m2, 1)'*F*(m1, 1) = 0\r
-    // to save computation time, we compute (At*A) instead of A and then solve (At*A)x=0. \r
-    for( i = 0; i < count; i++ )\r
-    {\r
-        double x0 = (m1[i].x - m0c.x)*scale0;\r
-        double y0 = (m1[i].y - m0c.y)*scale0;\r
-        double x1 = (m2[i].x - m1c.x)*scale1;\r
-        double y1 = (m2[i].y - m1c.y)*scale1;\r
-        double r[9] = { x1*x0, x1*y0, x1, y1*x0, y1*y0, y1, x0, y0, 1 };\r
-        for( j = 0; j < 9; j++ )\r
-            for( k = 0; k < 9; k++ )\r
-                a[j*9+k] += r[j]*r[k];\r
-    }\r
-\r
-    cvSVD( &A, &W, 0, &V, CV_SVD_MODIFY_A + CV_SVD_V_T );\r
-\r
-    for( i = 0; i < 8; i++ )\r
-    {\r
-        if( fabs(w[i]) < DBL_EPSILON )\r
-            break;\r
-    }\r
-\r
-    if( i < 7 )\r
-        return 0;\r
-\r
-    F0 = cvMat( 3, 3, CV_64F, v + 9*8 ); // take the last column of v as a solution of Af = 0\r
-\r
-    // make F0 singular (of rank 2) by decomposing it with SVD,\r
-    // zeroing the last diagonal element of W and then composing the matrices back.\r
-\r
-    // use v as a temporary storage for different 3x3 matrices\r
-    W = U = V = TF = F0;\r
-    W.data.db = v;\r
-    U.data.db = v + 9;\r
-    V.data.db = v + 18;\r
-    TF.data.db = v + 27;\r
-\r
-    cvSVD( &F0, &W, &U, &V, CV_SVD_MODIFY_A + CV_SVD_U_T + CV_SVD_V_T );\r
-    W.data.db[8] = 0.;\r
-\r
-    // F0 <- U*diag([W(1), W(2), 0])*V'\r
-    cvGEMM( &U, &W, 1., 0, 0., &TF, CV_GEMM_A_T );\r
-    cvGEMM( &TF, &V, 1., 0, 0., &F0, 0/*CV_GEMM_B_T*/ );\r
-\r
-    // apply the transformation that is inverse\r
-    // to what we used to normalize the point coordinates\r
-    {\r
-        double tt0[] = { scale0, 0, -scale0*m0c.x, 0, scale0, -scale0*m0c.y, 0, 0, 1 };\r
-        double tt1[] = { scale1, 0, -scale1*m1c.x, 0, scale1, -scale1*m1c.y, 0, 0, 1 };\r
-        CvMat T0, T1;\r
-        T0 = T1 = F0;\r
-        T0.data.db = tt0;\r
-        T1.data.db = tt1;\r
-\r
-        // F0 <- T1'*F0*T0\r
-        cvGEMM( &T1, &F0, 1., 0, 0., &TF, CV_GEMM_A_T );\r
-        F0.data.db = fmatrix;\r
-        cvGEMM( &TF, &T0, 1., 0, 0., &F0, 0 );\r
-\r
-        // make F(3,3) = 1\r
-        if( fabs(F0.data.db[8]) > FLT_EPSILON )\r
-            cvScale( &F0, &F0, 1./F0.data.db[8] );\r
-    }\r
-\r
-    return 1;\r
-}\r
-\r
-\r
-void CvFMEstimator::computeReprojError( const CvMat* _m1, const CvMat* _m2,\r
-                                        const CvMat* model, CvMat* _err )\r
-{\r
-    int i, count = _m1->rows*_m1->cols;\r
-    const CvPoint2D64f* m1 = (const CvPoint2D64f*)_m1->data.ptr;\r
-    const CvPoint2D64f* m2 = (const CvPoint2D64f*)_m2->data.ptr;\r
-    const double* F = model->data.db;\r
-    float* err = _err->data.fl;\r
-    \r
-    for( i = 0; i < count; i++ )\r
-    {\r
-        double a, b, c, d1, d2, s1, s2;\r
-\r
-        a = F[0]*m1[i].x + F[1]*m1[i].y + F[2];\r
-        b = F[3]*m1[i].x + F[4]*m1[i].y + F[5];\r
-        c = F[6]*m1[i].x + F[7]*m1[i].y + F[8];\r
-\r
-        s2 = 1./(a*a + b*b);\r
-        d2 = m2[i].x*a + m2[i].y*b + c;\r
-\r
-        a = F[0]*m2[i].x + F[3]*m2[i].y + F[6];\r
-        b = F[1]*m2[i].x + F[4]*m2[i].y + F[7];\r
-        c = F[2]*m2[i].x + F[5]*m2[i].y + F[8];\r
-\r
-        s1 = 1./(a*a + b*b);\r
-        d1 = m1[i].x*a + m1[i].y*b + c;\r
-\r
-        err[i] = (float)std::max(d1*d1*s1, d2*d2*s2);\r
-    }\r
-}\r
-\r
-\r
-CV_IMPL int\r
-cvFindFundamentalMat( const CvMat* points1, const CvMat* points2,\r
-                      CvMat* fmatrix, int method,\r
-                      double param1, double param2, CvMat* mask )\r
-{\r
-    int result = 0;\r
-    CvMat *m1 = 0, *m2 = 0, *tempMask = 0;\r
-\r
-    CV_FUNCNAME( "cvFindFundamentalMat" );\r
-\r
-    __BEGIN__;\r
-\r
-    double F[3*9];\r
-    CvMat _F3x3 = cvMat( 3, 3, CV_64FC1, F ), _F9x3 = cvMat( 9, 3, CV_64FC1, F );\r
-    int count;\r
-\r
-    CV_ASSERT( CV_IS_MAT(points1) && CV_IS_MAT(points2) && CV_ARE_SIZES_EQ(points1, points2) );\r
-    CV_ASSERT( CV_IS_MAT(fmatrix) && fmatrix->cols == 3 &&\r
-        (fmatrix->rows == 3 || (fmatrix->rows == 9 && method == CV_FM_7POINT)) );\r
-\r
-    count = MAX(points1->cols, points1->rows);\r
-    if( count < 7 )\r
-        EXIT;\r
-\r
-    m1 = cvCreateMat( 1, count, CV_64FC2 );\r
-    cvConvertPointsHomogeneous( points1, m1 );\r
-\r
-    m2 = cvCreateMat( 1, count, CV_64FC2 );\r
-    cvConvertPointsHomogeneous( points2, m2 );\r
-\r
-    if( mask )\r
-    {\r
-        CV_ASSERT( CV_IS_MASK_ARR(mask) && CV_IS_MAT_CONT(mask->type) &&\r
-            (mask->rows == 1 || mask->cols == 1) &&\r
-            mask->rows*mask->cols == count );\r
-        tempMask = cvCreateMatHeader(1, count, CV_8U);\r
-        cvSetData(tempMask, mask->data.ptr, 0);\r
-    }\r
-    else if( count > 8 )\r
-        tempMask = cvCreateMat( 1, count, CV_8U );\r
-    if( tempMask )\r
-        cvSet( tempMask, cvScalarAll(1.) );\r
-\r
-    {\r
-    CvFMEstimator estimator( MIN(count, (method & 3) == CV_FM_7POINT ? 7 : 8) );\r
-    if( count == 7 )\r
-        result = estimator.run7Point(m1, m2, &_F9x3);\r
-    else if( count == 8 || method == CV_FM_8POINT )\r
-        result = estimator.run8Point(m1, m2, &_F3x3);\r
-    else if( count > 8 )\r
-    {\r
-        if( param1 <= 0 )\r
-            param1 = 3;\r
-        if( param2 < DBL_EPSILON || param2 > 1 - DBL_EPSILON )\r
-            param2 = 0.99;\r
-        \r
-        if( (method & ~3) == CV_RANSAC )\r
-            result = estimator.runRANSAC(m1, m2, &_F3x3, tempMask, param1, param2 );\r
-        else\r
-            result = estimator.runLMeDS(m1, m2, &_F3x3, tempMask, param2 );\r
-        if( result <= 0 )\r
-            EXIT;\r
-        /*icvCompressPoints( (CvPoint2D64f*)m1->data.ptr, tempMask->data.ptr, 1, count );\r
-        count = icvCompressPoints( (CvPoint2D64f*)m2->data.ptr, tempMask->data.ptr, 1, count );\r
-        assert( count >= 8 );\r
-        m1->cols = m2->cols = count;\r
-        estimator.run8Point(m1, m2, &_F3x3);*/\r
-    }\r
-    }\r
-\r
-    if( result )\r
-        cvConvert( fmatrix->rows == 3 ? &_F3x3 : &_F9x3, fmatrix );\r
-\r
-    __END__;\r
-\r
-    cvReleaseMat( &m1 );\r
-    cvReleaseMat( &m2 );\r
-    if( tempMask != mask )\r
-        cvReleaseMat( &tempMask );\r
-\r
-    return result;\r
-}\r
-\r
-\r
-CV_IMPL void\r
-cvComputeCorrespondEpilines( const CvMat* points, int pointImageID,\r
-                             const CvMat* fmatrix, CvMat* lines )\r
-{\r
-    CV_FUNCNAME( "cvComputeCorrespondEpilines" );\r
-\r
-    __BEGIN__;\r
-\r
-    int abc_stride, abc_plane_stride, abc_elem_size;\r
-    int plane_stride, stride, elem_size;\r
-    int i, dims, count, depth, cn, abc_dims, abc_count, abc_depth, abc_cn;\r
-    uchar *ap, *bp, *cp;\r
-    const uchar *xp, *yp, *zp;\r
-    double f[9];\r
-    CvMat F = cvMat( 3, 3, CV_64F, f );\r
-\r
-    if( !CV_IS_MAT(points) )\r
-        CV_ERROR( !points ? CV_StsNullPtr : CV_StsBadArg, "points parameter is not a valid matrix" );\r
-\r
-    depth = CV_MAT_DEPTH(points->type);\r
-    cn = CV_MAT_CN(points->type);\r
-    if( (depth != CV_32F && depth != CV_64F) || (cn != 1 && cn != 2 && cn != 3) )\r
-        CV_ERROR( CV_StsUnsupportedFormat, "The format of point matrix is unsupported" );\r
-\r
-    if( points->rows > points->cols )\r
-    {\r
-        dims = cn*points->cols;\r
-        count = points->rows;\r
-    }\r
-    else\r
-    {\r
-        if( (points->rows > 1 && cn > 1) || (points->rows == 1 && cn == 1) )\r
-            CV_ERROR( CV_StsBadSize, "The point matrix does not have a proper layout (2xn, 3xn, nx2 or nx3)" );\r
-        dims = cn * points->rows;\r
-        count = points->cols;\r
-    }\r
-\r
-    if( dims != 2 && dims != 3 )\r
-        CV_ERROR( CV_StsOutOfRange, "The dimensionality of points must be 2 or 3" );\r
-\r
-    if( !CV_IS_MAT(fmatrix) )\r
-        CV_ERROR( !fmatrix ? CV_StsNullPtr : CV_StsBadArg, "fmatrix is not a valid matrix" );\r
-\r
-    if( CV_MAT_TYPE(fmatrix->type) != CV_32FC1 && CV_MAT_TYPE(fmatrix->type) != CV_64FC1 )\r
-        CV_ERROR( CV_StsUnsupportedFormat, "fundamental matrix must have 32fC1 or 64fC1 type" );\r
-\r
-    if( fmatrix->cols != 3 || fmatrix->rows != 3 )\r
-        CV_ERROR( CV_StsBadSize, "fundamental matrix must be 3x3" );\r
-\r
-    if( !CV_IS_MAT(lines) )\r
-        CV_ERROR( !lines ? CV_StsNullPtr : CV_StsBadArg, "lines parameter is not a valid matrix" );\r
-\r
-    abc_depth = CV_MAT_DEPTH(lines->type);\r
-    abc_cn = CV_MAT_CN(lines->type);\r
-    if( (abc_depth != CV_32F && abc_depth != CV_64F) || (abc_cn != 1 && abc_cn != 3) )\r
-        CV_ERROR( CV_StsUnsupportedFormat, "The format of the matrix of lines is unsupported" );\r
-\r
-    if( lines->rows > lines->cols )\r
-    {\r
-        abc_dims = abc_cn*lines->cols;\r
-        abc_count = lines->rows;\r
-    }\r
-    else\r
-    {\r
-        if( (lines->rows > 1 && abc_cn > 1) || (lines->rows == 1 && abc_cn == 1) )\r
-            CV_ERROR( CV_StsBadSize, "The lines matrix does not have a proper layout (3xn or nx3)" );\r
-        abc_dims = abc_cn * lines->rows;\r
-        abc_count = lines->cols;\r
-    }\r
-\r
-    if( abc_dims != 3 )\r
-        CV_ERROR( CV_StsOutOfRange, "The lines matrix does not have a proper layout (3xn or nx3)" );\r
-\r
-    if( abc_count != count )\r
-        CV_ERROR( CV_StsUnmatchedSizes, "The numbers of points and lines are different" );\r
-\r
-    elem_size = CV_ELEM_SIZE(depth);\r
-    abc_elem_size = CV_ELEM_SIZE(abc_depth);\r
-\r
-    if( points->rows == dims )\r
-    {\r
-        plane_stride = points->step;\r
-        stride = elem_size;\r
-    }\r
-    else\r
-    {\r
-        plane_stride = elem_size;\r
-        stride = points->rows == 1 ? dims*elem_size : points->step;\r
-    }\r
-\r
-    if( lines->rows == 3 )\r
-    {\r
-        abc_plane_stride = lines->step;\r
-        abc_stride = abc_elem_size;\r
-    }\r
-    else\r
-    {\r
-        abc_plane_stride = abc_elem_size;\r
-        abc_stride = lines->rows == 1 ? 3*abc_elem_size : lines->step;\r
-    }\r
-\r
-    CV_CALL( cvConvert( fmatrix, &F ));\r
-    if( pointImageID == 2 )\r
-        cvTranspose( &F, &F );\r
-\r
-    xp = points->data.ptr;\r
-    yp = xp + plane_stride;\r
-    zp = dims == 3 ? yp + plane_stride : 0;\r
-\r
-    ap = lines->data.ptr;\r
-    bp = ap + abc_plane_stride;\r
-    cp = bp + abc_plane_stride;\r
-\r
-    for( i = 0; i < count; i++ )\r
-    {\r
-        double x, y, z = 1.;\r
-        double a, b, c, nu;\r
-\r
-        if( depth == CV_32F )\r
-        {\r
-            x = *(float*)xp; y = *(float*)yp;\r
-            if( zp )\r
-                z = *(float*)zp, zp += stride;\r
-        }\r
-        else\r
-        {\r
-            x = *(double*)xp; y = *(double*)yp;\r
-            if( zp )\r
-                z = *(double*)zp, zp += stride;\r
-        }\r
-\r
-        xp += stride; yp += stride;\r
-\r
-        a = f[0]*x + f[1]*y + f[2]*z;\r
-        b = f[3]*x + f[4]*y + f[5]*z;\r
-        c = f[6]*x + f[7]*y + f[8]*z;\r
-        nu = a*a + b*b;\r
-        nu = nu ? 1./sqrt(nu) : 1.;\r
-        a *= nu; b *= nu; c *= nu;\r
-\r
-        if( abc_depth == CV_32F )\r
-        {\r
-            *(float*)ap = (float)a;\r
-            *(float*)bp = (float)b;\r
-            *(float*)cp = (float)c;\r
-        }\r
-        else\r
-        {\r
-            *(double*)ap = a;\r
-            *(double*)bp = b;\r
-            *(double*)cp = c;\r
-        }\r
-\r
-        ap += abc_stride;\r
-        bp += abc_stride;\r
-        cp += abc_stride;\r
-    }\r
-\r
-    __END__;\r
-}\r
-\r
-\r
-CV_IMPL void\r
-cvConvertPointsHomogeneous( const CvMat* src, CvMat* dst )\r
-{\r
-    CvMat* temp = 0;\r
-    CvMat* denom = 0;\r
-\r
-    CV_FUNCNAME( "cvConvertPointsHomogeneous" );\r
-\r
-    __BEGIN__;\r
-\r
-    int i, s_count, s_dims, d_count, d_dims;\r
-    CvMat _src, _dst, _ones;\r
-    CvMat* ones = 0;\r
-\r
-    if( !CV_IS_MAT(src) )\r
-        CV_ERROR( !src ? CV_StsNullPtr : CV_StsBadArg,\r
-        "The input parameter is not a valid matrix" );\r
-\r
-    if( !CV_IS_MAT(dst) )\r
-        CV_ERROR( !dst ? CV_StsNullPtr : CV_StsBadArg,\r
-        "The output parameter is not a valid matrix" );\r
-\r
-    if( src == dst || src->data.ptr == dst->data.ptr )\r
-    {\r
-        if( src != dst && (!CV_ARE_TYPES_EQ(src, dst) || !CV_ARE_SIZES_EQ(src,dst)) )\r
-            CV_ERROR( CV_StsBadArg, "Invalid inplace operation" );\r
-        EXIT;\r
-    }\r
-\r
-    if( src->rows > src->cols )\r
-    {\r
-        if( !((src->cols > 1) ^ (CV_MAT_CN(src->type) > 1)) )\r
-            CV_ERROR( CV_StsBadSize, "Either the number of channels or columns or rows must be =1" );\r
-\r
-        s_dims = CV_MAT_CN(src->type)*src->cols;\r
-        s_count = src->rows;\r
-    }\r
-    else\r
-    {\r
-        if( !((src->rows > 1) ^ (CV_MAT_CN(src->type) > 1)) )\r
-            CV_ERROR( CV_StsBadSize, "Either the number of channels or columns or rows must be =1" );\r
-\r
-        s_dims = CV_MAT_CN(src->type)*src->rows;\r
-        s_count = src->cols;\r
-    }\r
-\r
-    if( src->rows == 1 || src->cols == 1 )\r
-        src = cvReshape( src, &_src, 1, s_count );\r
-\r
-    if( dst->rows > dst->cols )\r
-    {\r
-        if( !((dst->cols > 1) ^ (CV_MAT_CN(dst->type) > 1)) )\r
-            CV_ERROR( CV_StsBadSize,\r
-            "Either the number of channels or columns or rows in the input matrix must be =1" );\r
-\r
-        d_dims = CV_MAT_CN(dst->type)*dst->cols;\r
-        d_count = dst->rows;\r
-    }\r
-    else\r
-    {\r
-        if( !((dst->rows > 1) ^ (CV_MAT_CN(dst->type) > 1)) )\r
-            CV_ERROR( CV_StsBadSize,\r
-            "Either the number of channels or columns or rows in the output matrix must be =1" );\r
-\r
-        d_dims = CV_MAT_CN(dst->type)*dst->rows;\r
-        d_count = dst->cols;\r
-    }\r
-\r
-    if( dst->rows == 1 || dst->cols == 1 )\r
-        dst = cvReshape( dst, &_dst, 1, d_count );\r
-\r
-    if( s_count != d_count )\r
-        CV_ERROR( CV_StsUnmatchedSizes, "Both matrices must have the same number of points" );\r
-\r
-    if( CV_MAT_DEPTH(src->type) < CV_32F || CV_MAT_DEPTH(dst->type) < CV_32F )\r
-        CV_ERROR( CV_StsUnsupportedFormat,\r
-        "Both matrices must be floating-point (single or double precision)" );\r
-\r
-    if( s_dims < 2 || s_dims > 4 || d_dims < 2 || d_dims > 4 )\r
-        CV_ERROR( CV_StsOutOfRange,\r
-        "Both input and output point dimensionality must be 2, 3 or 4" );\r
-\r
-    if( s_dims < d_dims - 1 || s_dims > d_dims + 1 )\r
-        CV_ERROR( CV_StsUnmatchedSizes,\r
-        "The dimensionalities of input and output point sets differ too much" );\r
-\r
-    if( s_dims == d_dims - 1 )\r
-    {\r
-        if( d_count == dst->rows )\r
-        {\r
-            ones = cvGetSubRect( dst, &_ones, cvRect( s_dims, 0, 1, d_count ));\r
-            dst = cvGetSubRect( dst, &_dst, cvRect( 0, 0, s_dims, d_count ));\r
-        }\r
-        else\r
-        {\r
-            ones = cvGetSubRect( dst, &_ones, cvRect( 0, s_dims, d_count, 1 ));\r
-            dst = cvGetSubRect( dst, &_dst, cvRect( 0, 0, d_count, s_dims ));\r
-        }\r
-    }\r
-\r
-    if( s_dims <= d_dims )\r
-    {\r
-        if( src->rows == dst->rows && src->cols == dst->cols )\r
-        {\r
-            if( CV_ARE_TYPES_EQ( src, dst ) )\r
-                cvCopy( src, dst );\r
-            else\r
-                cvConvert( src, dst );\r
-        }\r
-        else\r
-        {\r
-            if( !CV_ARE_TYPES_EQ( src, dst ))\r
-            {\r
-                CV_CALL( temp = cvCreateMat( src->rows, src->cols, dst->type ));\r
-                cvConvert( src, temp );\r
-                src = temp;\r
-            }\r
-            cvTranspose( src, dst );\r
-        }\r
-\r
-        if( ones )\r
-            cvSet( ones, cvRealScalar(1.) );\r
-    }\r
-    else\r
-    {\r
-        int s_plane_stride, s_stride, d_plane_stride, d_stride, elem_size;\r
-\r
-        if( !CV_ARE_TYPES_EQ( src, dst ))\r
-        {\r
-            CV_CALL( temp = cvCreateMat( src->rows, src->cols, dst->type ));\r
-            cvConvert( src, temp );\r
-            src = temp;\r
-        }\r
-\r
-        elem_size = CV_ELEM_SIZE(src->type);\r
-\r
-        if( s_count == src->cols )\r
-            s_plane_stride = src->step / elem_size, s_stride = 1;\r
-        else\r
-            s_stride = src->step / elem_size, s_plane_stride = 1;\r
-\r
-        if( d_count == dst->cols )\r
-            d_plane_stride = dst->step / elem_size, d_stride = 1;\r
-        else\r
-            d_stride = dst->step / elem_size, d_plane_stride = 1;\r
-\r
-        CV_CALL( denom = cvCreateMat( 1, d_count, dst->type ));\r
-\r
-        if( CV_MAT_DEPTH(dst->type) == CV_32F )\r
-        {\r
-            const float* xs = src->data.fl;\r
-            const float* ys = xs + s_plane_stride;\r
-            const float* zs = 0;\r
-            const float* ws = xs + (s_dims - 1)*s_plane_stride;\r
-\r
-            float* iw = denom->data.fl;\r
-\r
-            float* xd = dst->data.fl;\r
-            float* yd = xd + d_plane_stride;\r
-            float* zd = 0;\r
-\r
-            if( d_dims == 3 )\r
-            {\r
-                zs = ys + s_plane_stride;\r
-                zd = yd + d_plane_stride;\r
-            }\r
-\r
-            for( i = 0; i < d_count; i++, ws += s_stride )\r
-            {\r
-                float t = *ws;\r
-                iw[i] = fabs((double)t) > FLT_EPSILON ? t : 1.f;\r
-            }\r
-\r
-            cvDiv( 0, denom, denom );\r
-\r
-            if( d_dims == 3 )\r
-                for( i = 0; i < d_count; i++ )\r
-                {\r
-                    float w = iw[i];\r
-                    float x = *xs * w, y = *ys * w, z = *zs * w;\r
-                    xs += s_stride; ys += s_stride; zs += s_stride;\r
-                    *xd = x; *yd = y; *zd = z;\r
-                    xd += d_stride; yd += d_stride; zd += d_stride;\r
-                }\r
-            else\r
-                for( i = 0; i < d_count; i++ )\r
-                {\r
-                    float w = iw[i];\r
-                    float x = *xs * w, y = *ys * w;\r
-                    xs += s_stride; ys += s_stride;\r
-                    *xd = x; *yd = y;\r
-                    xd += d_stride; yd += d_stride;\r
-                }\r
-        }\r
-        else\r
-        {\r
-            const double* xs = src->data.db;\r
-            const double* ys = xs + s_plane_stride;\r
-            const double* zs = 0;\r
-            const double* ws = xs + (s_dims - 1)*s_plane_stride;\r
-\r
-            double* iw = denom->data.db;\r
-\r
-            double* xd = dst->data.db;\r
-            double* yd = xd + d_plane_stride;\r
-            double* zd = 0;\r
-\r
-            if( d_dims == 3 )\r
-            {\r
-                zs = ys + s_plane_stride;\r
-                zd = yd + d_plane_stride;\r
-            }\r
-\r
-            for( i = 0; i < d_count; i++, ws += s_stride )\r
-            {\r
-                double t = *ws;\r
-                iw[i] = fabs(t) > DBL_EPSILON ? t : 1.;\r
-            }\r
-\r
-            cvDiv( 0, denom, denom );\r
-\r
-            if( d_dims == 3 )\r
-                for( i = 0; i < d_count; i++ )\r
-                {\r
-                    double w = iw[i];\r
-                    double x = *xs * w, y = *ys * w, z = *zs * w;\r
-                    xs += s_stride; ys += s_stride; zs += s_stride;\r
-                    *xd = x; *yd = y; *zd = z;\r
-                    xd += d_stride; yd += d_stride; zd += d_stride;\r
-                }\r
-            else\r
-                for( i = 0; i < d_count; i++ )\r
-                {\r
-                    double w = iw[i];\r
-                    double x = *xs * w, y = *ys * w;\r
-                    xs += s_stride; ys += s_stride;\r
-                    *xd = x; *yd = y;\r
-                    xd += d_stride; yd += d_stride;\r
-                }\r
-        }\r
-    }\r
-\r
-    __END__;\r
-\r
-    cvReleaseMat( &denom );\r
-    cvReleaseMat( &temp );\r
-}\r
-\r
-namespace cv\r
-{\r
-\r
-static Mat _findHomography( const Vector<Point2f>& srcPoints,\r
-                            const Vector<Point2f>& dstPoints,\r
-                            int method, double ransacReprojThreshold,\r
-                            Vector<bool>* mask )\r
-{\r
-    Mat H(3, 3, CV_64F);\r
-    CvMat _pt1 = srcPoints, _pt2 = dstPoints;\r
-    CvMat _H = H, _mask, *pmask = 0;\r
-    if( mask )\r
-    {\r
-        mask->resize(srcPoints.size());\r
-        pmask = &(_mask = cvMat(1, (int)mask->size(), CV_8U, (void*)&(*mask)[0]));\r
-    }\r
-    bool ok = cvFindHomography( &_pt1, &_pt2, &_H, method, ransacReprojThreshold, pmask ) > 0;\r
-    if( !ok )\r
-        H = Scalar(0);\r
-    return H;\r
-}\r
-\r
-Mat findHomography( const Vector<Point2f>& srcPoints,\r
-                    const Vector<Point2f>& dstPoints,\r
-                    Vector<bool>& mask, int method,\r
-                    double ransacReprojThreshold )\r
-{\r
-    return _findHomography(srcPoints, dstPoints, method, ransacReprojThreshold, &mask);\r
-}\r
-\r
-Mat findHomography( const Vector<Point2f>& srcPoints,\r
-                    const Vector<Point2f>& dstPoints,\r
-                    int method, double ransacReprojThreshold )\r
-{\r
-    return _findHomography(srcPoints, dstPoints, method, ransacReprojThreshold, 0);\r
-}\r
-\r
-static Mat _findFundamentalMat( const Vector<Point2f>& points1,\r
-                                const Vector<Point2f>& points2,\r
-                                int method, double param1, double param2,\r
-                                Vector<bool>* mask )\r
-{\r
-    Mat F(3, 3, CV_64F);\r
-    CvMat _pt1 = points1, _pt2 = points2;\r
-    CvMat _F = F, _mask, *pmask = 0;\r
-    if( mask )\r
-    {\r
-        mask->resize(points1.size());\r
-        pmask = &(_mask = cvMat(1, (int)mask->size(), CV_8U, (void*)&(*mask)[0]));\r
-    }\r
-    int n = cvFindFundamentalMat( &_pt1, &_pt2, &_F, method, param1, param2, pmask );\r
-    if( n <= 0 )\r
-        F = Scalar(0);\r
-    return F;\r
-}\r
-\r
-Mat findFundamentalMat( const Vector<Point2f>& points1,\r
-                        const Vector<Point2f>& points2,\r
-                        Vector<bool>& mask,\r
-                        int method, double param1, double param2 )\r
-{\r
-    return _findFundamentalMat( points1, points2, method, param1, param2, &mask );\r
-}\r
-\r
-Mat findFundamentalMat( const Vector<Point2f>& points1,\r
-                        const Vector<Point2f>& points2,\r
-                        int method, double param1, double param2 )\r
-{\r
-    return _findFundamentalMat( points1, points2, method, param1, param2, 0 );\r
-}\r
-\r
-void computeCorrespondEpilines( const Vector<Point2f>& points,\r
-                                int whichImage, const Mat& F,\r
-                                Vector<Vec3f>& lines )\r
-{\r
-    lines.resize(points.size());\r
-    CvMat _points = points, _lines = lines, _F = F;\r
-    cvComputeCorrespondEpilines(&_points, whichImage, &_F, &_lines);\r
-}\r
-\r
-void convertPointsHomogeneous( const Vector<Point2f>& src,\r
-                               Vector<Point3f>& dst )\r
-{\r
-    dst.resize(src.size());\r
-    CvMat _src = src, _dst = dst;\r
-    cvConvertPointsHomogeneous(&_src, &_dst);\r
-}\r
-\r
-void convertPointsHomogeneous( const Vector<Point3f>& src,\r
-                               Vector<Point2f>& dst )\r
-{\r
-    dst.resize(src.size());\r
-    CvMat _src = src, _dst = dst;\r
-    cvConvertPointsHomogeneous(&_src, &_dst);\r
-}\r
-\r
-}\r
-\r
-/* End of file. */\r
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+//  By downloading, copying, installing or using the software you agree to this license.
+//  If you do not agree to this license, do not download, install,
+//  copy or use the software.
+//
+//
+//                        Intel License Agreement
+//                For Open Source Computer Vision Library
+//
+// Copyright (C) 2000, Intel Corporation, all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+//   * Redistribution's of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//
+//   * Redistribution's in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//
+//   * The name of Intel Corporation may not be used to endorse or promote products
+//     derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+#include "_cv.h"
+#include "_cvmodelest.h"
+
+template<typename T> int icvCompressPoints( T* ptr, const uchar* mask, int mstep, int count )
+{
+    int i, j;
+    for( i = j = 0; i < count; i++ )
+        if( mask[i*mstep] )
+        {
+            if( i > j )
+                ptr[j] = ptr[i];
+            j++;
+        }
+    return j;
+}
+
+class CvHomographyEstimator : public CvModelEstimator2
+{
+public:
+    CvHomographyEstimator( int modelPoints );
+
+    virtual int runKernel( const CvMat* m1, const CvMat* m2, CvMat* model );
+    virtual bool refine( const CvMat* m1, const CvMat* m2,
+                         CvMat* model, int maxIters );
+protected:
+    virtual void computeReprojError( const CvMat* m1, const CvMat* m2,
+                                     const CvMat* model, CvMat* error );
+};
+
+
+CvHomographyEstimator::CvHomographyEstimator(int _modelPoints)
+    : CvModelEstimator2(_modelPoints, cvSize(3,3), 1)
+{
+    assert( _modelPoints == 4 || _modelPoints == 5 );
+}
+
+int CvHomographyEstimator::runKernel( const CvMat* m1, const CvMat* m2, CvMat* H )
+{
+    int i, count = m1->rows*m1->cols;
+    const CvPoint2D64f* M = (const CvPoint2D64f*)m1->data.ptr;
+    const CvPoint2D64f* m = (const CvPoint2D64f*)m2->data.ptr;
+
+    double LtL[9][9], W[9][9], V[9][9];
+    CvMat _LtL = cvMat( 9, 9, CV_64F, LtL );
+    CvMat _W = cvMat( 9, 9, CV_64F, W );
+    CvMat _V = cvMat( 9, 9, CV_64F, V );
+    CvMat _H0 = cvMat( 3, 3, CV_64F, V[8] );
+    CvMat _Htemp = cvMat( 3, 3, CV_64F, V[7] );
+    CvPoint2D64f cM={0,0}, cm={0,0}, sM={0,0}, sm={0,0};
+
+    for( i = 0; i < count; i++ )
+    {
+        cm.x += m[i].x; cm.y += m[i].y;
+        cM.x += M[i].x; cM.y += M[i].y;
+    }
+
+    cm.x /= count; cm.y /= count;
+    cM.x /= count; cM.y /= count;
+
+    for( i = 0; i < count; i++ )
+    {
+        sm.x += fabs(m[i].x - cm.x);
+        sm.y += fabs(m[i].y - cm.y);
+        sM.x += fabs(M[i].x - cM.x);
+        sM.y += fabs(M[i].y - cM.y);
+    }
+
+    sm.x = count/sm.x; sm.y = count/sm.y;
+    sM.x = count/sM.x; sM.y = count/sM.y;
+
+    double invHnorm[9] = { 1./sm.x, 0, cm.x, 0, 1./sm.y, cm.y, 0, 0, 1 };
+    double Hnorm2[9] = { sM.x, 0, -cM.x*sM.x, 0, sM.y, -cM.y*sM.y, 0, 0, 1 };
+    CvMat _invHnorm = cvMat( 3, 3, CV_64FC1, invHnorm );
+    CvMat _Hnorm2 = cvMat( 3, 3, CV_64FC1, Hnorm2 );
+
+    cvZero( &_LtL );
+    for( i = 0; i < count; i++ )
+    {
+        double x = (m[i].x - cm.x)*sm.x, y = (m[i].y - cm.y)*sm.y;
+        double X = (M[i].x - cM.x)*sM.x, Y = (M[i].y - cM.y)*sM.y;
+        double Lx[] = { X, Y, 1, 0, 0, 0, -x*X, -x*Y, -x };
+        double Ly[] = { 0, 0, 0, X, Y, 1, -y*X, -y*Y, -y };
+        int j, k;
+        for( j = 0; j < 9; j++ )
+            for( k = j; k < 9; k++ )
+                LtL[j][k] += Lx[j]*Lx[k] + Ly[j]*Ly[k];
+    }
+    cvCompleteSymm( &_LtL );
+
+    cvSVD( &_LtL, &_W, 0, &_V, CV_SVD_MODIFY_A + CV_SVD_V_T );
+    cvMatMul( &_invHnorm, &_H0, &_Htemp );
+    cvMatMul( &_Htemp, &_Hnorm2, &_H0 );
+    cvConvertScale( &_H0, H, 1./_H0.data.db[8] );
+
+    return 1;
+}
+
+
+void CvHomographyEstimator::computeReprojError( const CvMat* m1, const CvMat* m2,
+                                                const CvMat* model, CvMat* _err )
+{
+    int i, count = m1->rows*m1->cols;
+    const CvPoint2D64f* M = (const CvPoint2D64f*)m1->data.ptr;
+    const CvPoint2D64f* m = (const CvPoint2D64f*)m2->data.ptr;
+    const double* H = model->data.db;
+    float* err = _err->data.fl;
+
+    for( i = 0; i < count; i++ )
+    {
+        double ww = 1./(H[6]*M[i].x + H[7]*M[i].y + 1.);
+        double dx = (H[0]*M[i].x + H[1]*M[i].y + H[2])*ww - m[i].x;
+        double dy = (H[3]*M[i].x + H[4]*M[i].y + H[5])*ww - m[i].y;
+        err[i] = (float)(dx*dx + dy*dy);
+    }
+}
+
+bool CvHomographyEstimator::refine( const CvMat* m1, const CvMat* m2, CvMat* model, int maxIters )
+{
+    CvLevMarq solver(8, 0, cvTermCriteria(CV_TERMCRIT_ITER+CV_TERMCRIT_EPS, maxIters, DBL_EPSILON));
+    int i, j, k, count = m1->rows*m1->cols;
+    const CvPoint2D64f* M = (const CvPoint2D64f*)m1->data.ptr;
+    const CvPoint2D64f* m = (const CvPoint2D64f*)m2->data.ptr;
+    CvMat modelPart = cvMat( solver.param->rows, solver.param->cols, model->type, model->data.ptr );
+    cvCopy( &modelPart, solver.param );
+
+    for(;;)
+    {
+        const CvMat* _param = 0;
+        CvMat *_JtJ = 0, *_JtErr = 0;
+        double* _errNorm = 0;
+
+        if( !solver.updateAlt( _param, _JtJ, _JtErr, _errNorm ))
+            break;
+
+        for( i = 0; i < count; i++ )
+        {
+            const double* h = _param->data.db;
+            double Mx = M[i].x, My = M[i].y;
+            double ww = 1./(h[6]*Mx + h[7]*My + 1.);
+            double _xi = (h[0]*Mx + h[1]*My + h[2])*ww;
+            double _yi = (h[3]*Mx + h[4]*My + h[5])*ww;
+            double err[] = { _xi - m[i].x, _yi - m[i].y };
+            if( _JtJ || _JtErr )
+            {
+                double J[][8] =
+                {
+                    { Mx*ww, My*ww, ww, 0, 0, 0, -Mx*ww*_xi, -My*ww*_xi },
+                    { 0, 0, 0, Mx*ww, My*ww, ww, -Mx*ww*_yi, -My*ww*_yi }
+                };
+
+                for( j = 0; j < 8; j++ )
+                {
+                    for( k = j; k < 8; k++ )
+                        _JtJ->data.db[j*8+k] += J[0][j]*J[0][k] + J[1][j]*J[1][k];
+                    _JtErr->data.db[j] += J[0][j]*err[0] + J[1][j]*err[1];
+                }
+            }
+            if( _errNorm )
+                *_errNorm += err[0]*err[0] + err[1]*err[1];
+        }
+    }
+
+    cvCopy( solver.param, &modelPart );
+    return true;
+}
+
+
+CV_IMPL int
+cvFindHomography( const CvMat* objectPoints, const CvMat* imagePoints,
+                  CvMat* __H, int method, double ransacReprojThreshold,
+                  CvMat* mask )
+{
+    const double confidence = 0.99;
+    const int maxIters = 1500;
+    bool result = false;
+    CvMat *m = 0, *M = 0, *tempMask = 0;
+
+    CV_FUNCNAME( "cvFindHomography" );
+
+    __BEGIN__;
+
+    double H[9];
+    CvMat _H = cvMat( 3, 3, CV_64FC1, H );
+    int count;
+
+    CV_ASSERT( CV_IS_MAT(imagePoints) && CV_IS_MAT(objectPoints) );
+
+    count = MAX(imagePoints->cols, imagePoints->rows);
+    CV_ASSERT( count >= 4 );
+
+    m = cvCreateMat( 1, count, CV_64FC2 );
+    cvConvertPointsHomogeneous( imagePoints, m );
+
+    M = cvCreateMat( 1, count, CV_64FC2 );
+    cvConvertPointsHomogeneous( objectPoints, M );
+
+    if( mask )
+    {
+        CV_ASSERT( CV_IS_MASK_ARR(mask) && CV_IS_MAT_CONT(mask->type) &&
+            (mask->rows == 1 || mask->cols == 1) &&
+            mask->rows*mask->cols == count );
+        tempMask = mask;
+    }
+    else if( count > 4 )
+        tempMask = cvCreateMat( 1, count, CV_8U );
+    if( tempMask )
+        cvSet( tempMask, cvScalarAll(1.) );
+
+    {
+    CvHomographyEstimator estimator( MIN(count, 5) );
+    if( count == 4 )
+        method = 0;
+    if( method == CV_LMEDS )
+        result = estimator.runLMeDS( M, m, &_H, tempMask, confidence, maxIters );
+    else if( method == CV_RANSAC )
+        result = estimator.runRANSAC( M, m, &_H, tempMask, ransacReprojThreshold, confidence, maxIters);
+    else
+        result = estimator.runKernel( M, m, &_H ) > 0;
+
+    if( result && count > 4 )
+    {
+        icvCompressPoints( (CvPoint2D64f*)M->data.ptr, tempMask->data.ptr, 1, count );
+        count = icvCompressPoints( (CvPoint2D64f*)m->data.ptr, tempMask->data.ptr, 1, count );
+        M->cols = m->cols = count;
+        estimator.refine( M, m, &_H, 10 );
+    }
+    }
+
+    if( result )
+        cvConvert( &_H, __H );
+
+    __END__;
+
+    cvReleaseMat( &m );
+    cvReleaseMat( &M );
+    if( tempMask != mask )
+        cvReleaseMat( &tempMask );
+
+    return (int)result;
+}
+
+
+/* Evaluation of Fundamental Matrix from point correspondences.
+   The original code has been written by Valery Mosyagin */
+
+/* The algorithms (except for RANSAC) and the notation have been taken from
+   Zhengyou Zhang's research report
+   "Determining the Epipolar Geometry and its Uncertainty: A Review"
+   that can be found at http://www-sop.inria.fr/robotvis/personnel/zzhang/zzhang-eng.html */
+
+/************************************** 7-point algorithm *******************************/
+class CvFMEstimator : public CvModelEstimator2
+{
+public:
+    CvFMEstimator( int _modelPoints );
+
+    virtual int runKernel( const CvMat* m1, const CvMat* m2, CvMat* model );
+    virtual int run7Point( const CvMat* m1, const CvMat* m2, CvMat* model );
+    virtual int run8Point( const CvMat* m1, const CvMat* m2, CvMat* model );
+protected:
+    virtual void computeReprojError( const CvMat* m1, const CvMat* m2,
+                                     const CvMat* model, CvMat* error );
+};
+
+CvFMEstimator::CvFMEstimator( int _modelPoints )
+: CvModelEstimator2( _modelPoints, cvSize(3,3), _modelPoints == 7 ? 3 : 1 )
+{
+    assert( _modelPoints == 7 || _modelPoints == 8 );
+}
+
+
+int CvFMEstimator::runKernel( const CvMat* m1, const CvMat* m2, CvMat* model )
+{
+    return modelPoints == 7 ? run7Point( m1, m2, model ) : run8Point( m1, m2, model );
+}
+
+int CvFMEstimator::run7Point( const CvMat* _m1, const CvMat* _m2, CvMat* _fmatrix )
+{
+    double a[7*9], w[7], v[9*9], c[4], r[3];
+    double* f1, *f2;
+    double t0, t1, t2;
+    CvMat A = cvMat( 7, 9, CV_64F, a );
+    CvMat V = cvMat( 9, 9, CV_64F, v );
+    CvMat W = cvMat( 7, 1, CV_64F, w );
+    CvMat coeffs = cvMat( 1, 4, CV_64F, c );
+    CvMat roots = cvMat( 1, 3, CV_64F, r );
+    const CvPoint2D64f* m1 = (const CvPoint2D64f*)_m1->data.ptr;
+    const CvPoint2D64f* m2 = (const CvPoint2D64f*)_m2->data.ptr;
+    double* fmatrix = _fmatrix->data.db;
+    int i, k, n;
+
+    // form a linear system: i-th row of A(=a) represents
+    // the equation: (m2[i], 1)'*F*(m1[i], 1) = 0
+    for( i = 0; i < 7; i++ )
+    {
+        double x0 = m1[i].x, y0 = m1[i].y;
+        double x1 = m2[i].x, y1 = m2[i].y;
+
+        a[i*9+0] = x1*x0;
+        a[i*9+1] = x1*y0;
+        a[i*9+2] = x1;
+        a[i*9+3] = y1*x0;
+        a[i*9+4] = y1*y0;
+        a[i*9+5] = y1;
+        a[i*9+6] = x0;
+        a[i*9+7] = y0;
+        a[i*9+8] = 1;
+    }
+
+    // A*(f11 f12 ... f33)' = 0 is singular (7 equations for 9 variables), so
+    // the solution is linear subspace of dimensionality 2.
+    // => use the last two singular vectors as a basis of the space
+    // (according to SVD properties)
+    cvSVD( &A, &W, 0, &V, CV_SVD_MODIFY_A + CV_SVD_V_T );
+    f1 = v + 7*9;
+    f2 = v + 8*9;
+
+    // f1, f2 is a basis => lambda*f1 + mu*f2 is an arbitrary f. matrix.
+    // as it is determined up to a scale, normalize lambda & mu (lambda + mu = 1),
+    // so f ~ lambda*f1 + (1 - lambda)*f2.
+    // use the additional constraint det(f) = det(lambda*f1 + (1-lambda)*f2) to find lambda.
+    // it will be a cubic equation.
+    // find c - polynomial coefficients.
+    for( i = 0; i < 9; i++ )
+        f1[i] -= f2[i];
+
+    t0 = f2[4]*f2[8] - f2[5]*f2[7];
+    t1 = f2[3]*f2[8] - f2[5]*f2[6];
+    t2 = f2[3]*f2[7] - f2[4]*f2[6];
+
+    c[3] = f2[0]*t0 - f2[1]*t1 + f2[2]*t2;
+
+    c[2] = f1[0]*t0 - f1[1]*t1 + f1[2]*t2 -
+           f1[3]*(f2[1]*f2[8] - f2[2]*f2[7]) +
+           f1[4]*(f2[0]*f2[8] - f2[2]*f2[6]) -
+           f1[5]*(f2[0]*f2[7] - f2[1]*f2[6]) +
+           f1[6]*(f2[1]*f2[5] - f2[2]*f2[4]) -
+           f1[7]*(f2[0]*f2[5] - f2[2]*f2[3]) +
+           f1[8]*(f2[0]*f2[4] - f2[1]*f2[3]);
+
+    t0 = f1[4]*f1[8] - f1[5]*f1[7];
+    t1 = f1[3]*f1[8] - f1[5]*f1[6];
+    t2 = f1[3]*f1[7] - f1[4]*f1[6];
+
+    c[1] = f2[0]*t0 - f2[1]*t1 + f2[2]*t2 -
+           f2[3]*(f1[1]*f1[8] - f1[2]*f1[7]) +
+           f2[4]*(f1[0]*f1[8] - f1[2]*f1[6]) -
+           f2[5]*(f1[0]*f1[7] - f1[1]*f1[6]) +
+           f2[6]*(f1[1]*f1[5] - f1[2]*f1[4]) -
+           f2[7]*(f1[0]*f1[5] - f1[2]*f1[3]) +
+           f2[8]*(f1[0]*f1[4] - f1[1]*f1[3]);
+
+    c[0] = f1[0]*t0 - f1[1]*t1 + f1[2]*t2;
+
+    // solve the cubic equation; there can be 1 to 3 roots ...
+    n = cvSolveCubic( &coeffs, &roots );
+
+    if( n < 1 || n > 3 )
+        return n;
+
+    for( k = 0; k < n; k++, fmatrix += 9 )
+    {
+        // for each root form the fundamental matrix
+        double lambda = r[k], mu = 1.;
+        double s = f1[8]*r[k] + f2[8];
+
+        // normalize each matrix, so that F(3,3) (~fmatrix[8]) == 1
+        if( fabs(s) > DBL_EPSILON )
+        {
+            mu = 1./s;
+            lambda *= mu;
+            fmatrix[8] = 1.;
+        }
+        else
+            fmatrix[8] = 0.;
+
+        for( i = 0; i < 8; i++ )
+            fmatrix[i] = f1[i]*lambda + f2[i]*mu;
+    }
+
+    return n;
+}
+
+
+int CvFMEstimator::run8Point( const CvMat* _m1, const CvMat* _m2, CvMat* _fmatrix )
+{
+    double a[9*9], w[9], v[9*9];
+    CvMat W = cvMat( 1, 9, CV_64F, w );
+    CvMat V = cvMat( 9, 9, CV_64F, v );
+    CvMat A = cvMat( 9, 9, CV_64F, a );
+    CvMat U, F0, TF;
+
+    CvPoint2D64f m0c = {0,0}, m1c = {0,0};
+    double t, scale0 = 0, scale1 = 0;
+
+    const CvPoint2D64f* m1 = (const CvPoint2D64f*)_m1->data.ptr;
+    const CvPoint2D64f* m2 = (const CvPoint2D64f*)_m2->data.ptr;
+    double* fmatrix = _fmatrix->data.db;
+    int i, j, k, count = _m1->cols*_m1->rows;
+
+    // compute centers and average distances for each of the two point sets
+    for( i = 0; i < count; i++ )
+    {
+        double x = m1[i].x, y = m1[i].y;
+        m0c.x += x; m0c.y += y;
+
+        x = m2[i].x, y = m2[i].y;
+        m1c.x += x; m1c.y += y;
+    }
+
+    // calculate the normalizing transformations for each of the point sets:
+    // after the transformation each set will have the mass center at the coordinate origin
+    // and the average distance from the origin will be ~sqrt(2).
+    t = 1./count;
+    m0c.x *= t; m0c.y *= t;
+    m1c.x *= t; m1c.y *= t;
+
+    for( i = 0; i < count; i++ )
+    {
+        double x = m1[i].x - m0c.x, y = m1[i].y - m0c.y;
+        scale0 += sqrt(x*x + y*y);
+
+        x = fabs(m2[i].x - m1c.x), y = fabs(m2[i].y - m1c.y);
+        scale1 += sqrt(x*x + y*y);
+    }
+
+    scale0 *= t;
+    scale1 *= t;
+
+    if( scale0 < FLT_EPSILON || scale1 < FLT_EPSILON )
+        return 0;
+
+    scale0 = sqrt(2.)/scale0;
+    scale1 = sqrt(2.)/scale1;
+    
+    cvZero( &A );
+
+    // form a linear system Ax=0: for each selected pair of points m1 & m2,
+    // the row of A(=a) represents the coefficients of equation: (m2, 1)'*F*(m1, 1) = 0
+    // to save computation time, we compute (At*A) instead of A and then solve (At*A)x=0. 
+    for( i = 0; i < count; i++ )
+    {
+        double x0 = (m1[i].x - m0c.x)*scale0;
+        double y0 = (m1[i].y - m0c.y)*scale0;
+        double x1 = (m2[i].x - m1c.x)*scale1;
+        double y1 = (m2[i].y - m1c.y)*scale1;
+        double r[9] = { x1*x0, x1*y0, x1, y1*x0, y1*y0, y1, x0, y0, 1 };
+        for( j = 0; j < 9; j++ )
+            for( k = 0; k < 9; k++ )
+                a[j*9+k] += r[j]*r[k];
+    }
+
+    cvSVD( &A, &W, 0, &V, CV_SVD_MODIFY_A + CV_SVD_V_T );
+
+    for( i = 0; i < 8; i++ )
+    {
+        if( fabs(w[i]) < DBL_EPSILON )
+            break;
+    }
+
+    if( i < 7 )
+        return 0;
+
+    F0 = cvMat( 3, 3, CV_64F, v + 9*8 ); // take the last column of v as a solution of Af = 0
+
+    // make F0 singular (of rank 2) by decomposing it with SVD,
+    // zeroing the last diagonal element of W and then composing the matrices back.
+
+    // use v as a temporary storage for different 3x3 matrices
+    W = U = V = TF = F0;
+    W.data.db = v;
+    U.data.db = v + 9;
+    V.data.db = v + 18;
+    TF.data.db = v + 27;
+
+    cvSVD( &F0, &W, &U, &V, CV_SVD_MODIFY_A + CV_SVD_U_T + CV_SVD_V_T );
+    W.data.db[8] = 0.;
+
+    // F0 <- U*diag([W(1), W(2), 0])*V'
+    cvGEMM( &U, &W, 1., 0, 0., &TF, CV_GEMM_A_T );
+    cvGEMM( &TF, &V, 1., 0, 0., &F0, 0/*CV_GEMM_B_T*/ );
+
+    // apply the transformation that is inverse
+    // to what we used to normalize the point coordinates
+    {
+        double tt0[] = { scale0, 0, -scale0*m0c.x, 0, scale0, -scale0*m0c.y, 0, 0, 1 };
+        double tt1[] = { scale1, 0, -scale1*m1c.x, 0, scale1, -scale1*m1c.y, 0, 0, 1 };
+        CvMat T0, T1;
+        T0 = T1 = F0;
+        T0.data.db = tt0;
+        T1.data.db = tt1;
+
+        // F0 <- T1'*F0*T0
+        cvGEMM( &T1, &F0, 1., 0, 0., &TF, CV_GEMM_A_T );
+        F0.data.db = fmatrix;
+        cvGEMM( &TF, &T0, 1., 0, 0., &F0, 0 );
+
+        // make F(3,3) = 1
+        if( fabs(F0.data.db[8]) > FLT_EPSILON )
+            cvScale( &F0, &F0, 1./F0.data.db[8] );
+    }
+
+    return 1;
+}
+
+
+void CvFMEstimator::computeReprojError( const CvMat* _m1, const CvMat* _m2,
+                                        const CvMat* model, CvMat* _err )
+{
+    int i, count = _m1->rows*_m1->cols;
+    const CvPoint2D64f* m1 = (const CvPoint2D64f*)_m1->data.ptr;
+    const CvPoint2D64f* m2 = (const CvPoint2D64f*)_m2->data.ptr;
+    const double* F = model->data.db;
+    float* err = _err->data.fl;
+    
+    for( i = 0; i < count; i++ )
+    {
+        double a, b, c, d1, d2, s1, s2;
+
+        a = F[0]*m1[i].x + F[1]*m1[i].y + F[2];
+        b = F[3]*m1[i].x + F[4]*m1[i].y + F[5];
+        c = F[6]*m1[i].x + F[7]*m1[i].y + F[8];
+
+        s2 = 1./(a*a + b*b);
+        d2 = m2[i].x*a + m2[i].y*b + c;
+
+        a = F[0]*m2[i].x + F[3]*m2[i].y + F[6];
+        b = F[1]*m2[i].x + F[4]*m2[i].y + F[7];
+        c = F[2]*m2[i].x + F[5]*m2[i].y + F[8];
+
+        s1 = 1./(a*a + b*b);
+        d1 = m1[i].x*a + m1[i].y*b + c;
+
+        err[i] = (float)std::max(d1*d1*s1, d2*d2*s2);
+    }
+}
+
+
+CV_IMPL int
+cvFindFundamentalMat( const CvMat* points1, const CvMat* points2,
+                      CvMat* fmatrix, int method,
+                      double param1, double param2, CvMat* mask )
+{
+    int result = 0;
+    CvMat *m1 = 0, *m2 = 0, *tempMask = 0;
+
+    CV_FUNCNAME( "cvFindFundamentalMat" );
+
+    __BEGIN__;
+
+    double F[3*9];
+    CvMat _F3x3 = cvMat( 3, 3, CV_64FC1, F ), _F9x3 = cvMat( 9, 3, CV_64FC1, F );
+    int count;
+
+    CV_ASSERT( CV_IS_MAT(points1) && CV_IS_MAT(points2) && CV_ARE_SIZES_EQ(points1, points2) );
+    CV_ASSERT( CV_IS_MAT(fmatrix) && fmatrix->cols == 3 &&
+        (fmatrix->rows == 3 || (fmatrix->rows == 9 && method == CV_FM_7POINT)) );
+
+    count = MAX(points1->cols, points1->rows);
+    if( count < 7 )
+        EXIT;
+
+    m1 = cvCreateMat( 1, count, CV_64FC2 );
+    cvConvertPointsHomogeneous( points1, m1 );
+
+    m2 = cvCreateMat( 1, count, CV_64FC2 );
+    cvConvertPointsHomogeneous( points2, m2 );
+
+    if( mask )
+    {
+        CV_ASSERT( CV_IS_MASK_ARR(mask) && CV_IS_MAT_CONT(mask->type) &&
+            (mask->rows == 1 || mask->cols == 1) &&
+            mask->rows*mask->cols == count );
+        tempMask = cvCreateMatHeader(1, count, CV_8U);
+        cvSetData(tempMask, mask->data.ptr, 0);
+    }
+    else if( count > 8 )
+        tempMask = cvCreateMat( 1, count, CV_8U );
+    if( tempMask )
+        cvSet( tempMask, cvScalarAll(1.) );
+
+    {
+    CvFMEstimator estimator( MIN(count, (method & 3) == CV_FM_7POINT ? 7 : 8) );
+    if( count == 7 )
+        result = estimator.run7Point(m1, m2, &_F9x3);
+    else if( count == 8 || method == CV_FM_8POINT )
+        result = estimator.run8Point(m1, m2, &_F3x3);
+    else if( count > 8 )
+    {
+        if( param1 <= 0 )
+            param1 = 3;
+        if( param2 < DBL_EPSILON || param2 > 1 - DBL_EPSILON )
+            param2 = 0.99;
+        
+        if( (method & ~3) == CV_RANSAC )
+            result = estimator.runRANSAC(m1, m2, &_F3x3, tempMask, param1, param2 );
+        else
+            result = estimator.runLMeDS(m1, m2, &_F3x3, tempMask, param2 );
+        if( result <= 0 )
+            EXIT;
+        /*icvCompressPoints( (CvPoint2D64f*)m1->data.ptr, tempMask->data.ptr, 1, count );
+        count = icvCompressPoints( (CvPoint2D64f*)m2->data.ptr, tempMask->data.ptr, 1, count );
+        assert( count >= 8 );
+        m1->cols = m2->cols = count;
+        estimator.run8Point(m1, m2, &_F3x3);*/
+    }
+    }
+
+    if( result )
+        cvConvert( fmatrix->rows == 3 ? &_F3x3 : &_F9x3, fmatrix );
+
+    __END__;
+
+    cvReleaseMat( &m1 );
+    cvReleaseMat( &m2 );
+    if( tempMask != mask )
+        cvReleaseMat( &tempMask );
+
+    return result;
+}
+
+
+CV_IMPL void
+cvComputeCorrespondEpilines( const CvMat* points, int pointImageID,
+                             const CvMat* fmatrix, CvMat* lines )
+{
+    CV_FUNCNAME( "cvComputeCorrespondEpilines" );
+
+    __BEGIN__;
+
+    int abc_stride, abc_plane_stride, abc_elem_size;
+    int plane_stride, stride, elem_size;
+    int i, dims, count, depth, cn, abc_dims, abc_count, abc_depth, abc_cn;
+    uchar *ap, *bp, *cp;
+    const uchar *xp, *yp, *zp;
+    double f[9];
+    CvMat F = cvMat( 3, 3, CV_64F, f );
+
+    if( !CV_IS_MAT(points) )
+        CV_ERROR( !points ? CV_StsNullPtr : CV_StsBadArg, "points parameter is not a valid matrix" );
+
+    depth = CV_MAT_DEPTH(points->type);
+    cn = CV_MAT_CN(points->type);
+    if( (depth != CV_32F && depth != CV_64F) || (cn != 1 && cn != 2 && cn != 3) )
+        CV_ERROR( CV_StsUnsupportedFormat, "The format of point matrix is unsupported" );
+
+    if( points->rows > points->cols )
+    {
+        dims = cn*points->cols;
+        count = points->rows;
+    }
+    else
+    {
+        if( (points->rows > 1 && cn > 1) || (points->rows == 1 && cn == 1) )
+            CV_ERROR( CV_StsBadSize, "The point matrix does not have a proper layout (2xn, 3xn, nx2 or nx3)" );
+        dims = cn * points->rows;
+        count = points->cols;
+    }
+
+    if( dims != 2 && dims != 3 )
+        CV_ERROR( CV_StsOutOfRange, "The dimensionality of points must be 2 or 3" );
+
+    if( !CV_IS_MAT(fmatrix) )
+        CV_ERROR( !fmatrix ? CV_StsNullPtr : CV_StsBadArg, "fmatrix is not a valid matrix" );
+
+    if( CV_MAT_TYPE(fmatrix->type) != CV_32FC1 && CV_MAT_TYPE(fmatrix->type) != CV_64FC1 )
+        CV_ERROR( CV_StsUnsupportedFormat, "fundamental matrix must have 32fC1 or 64fC1 type" );
+
+    if( fmatrix->cols != 3 || fmatrix->rows != 3 )
+        CV_ERROR( CV_StsBadSize, "fundamental matrix must be 3x3" );
+
+    if( !CV_IS_MAT(lines) )
+        CV_ERROR( !lines ? CV_StsNullPtr : CV_StsBadArg, "lines parameter is not a valid matrix" );
+
+    abc_depth = CV_MAT_DEPTH(lines->type);
+    abc_cn = CV_MAT_CN(lines->type);
+    if( (abc_depth != CV_32F && abc_depth != CV_64F) || (abc_cn != 1 && abc_cn != 3) )
+        CV_ERROR( CV_StsUnsupportedFormat, "The format of the matrix of lines is unsupported" );
+
+    if( lines->rows > lines->cols )
+    {
+        abc_dims = abc_cn*lines->cols;
+        abc_count = lines->rows;
+    }
+    else
+    {
+        if( (lines->rows > 1 && abc_cn > 1) || (lines->rows == 1 && abc_cn == 1) )
+            CV_ERROR( CV_StsBadSize, "The lines matrix does not have a proper layout (3xn or nx3)" );
+        abc_dims = abc_cn * lines->rows;
+        abc_count = lines->cols;
+    }
+
+    if( abc_dims != 3 )
+        CV_ERROR( CV_StsOutOfRange, "The lines matrix does not have a proper layout (3xn or nx3)" );
+
+    if( abc_count != count )
+        CV_ERROR( CV_StsUnmatchedSizes, "The numbers of points and lines are different" );
+
+    elem_size = CV_ELEM_SIZE(depth);
+    abc_elem_size = CV_ELEM_SIZE(abc_depth);
+
+    if( points->rows == dims )
+    {
+        plane_stride = points->step;
+        stride = elem_size;
+    }
+    else
+    {
+        plane_stride = elem_size;
+        stride = points->rows == 1 ? dims*elem_size : points->step;
+    }
+
+    if( lines->rows == 3 )
+    {
+        abc_plane_stride = lines->step;
+        abc_stride = abc_elem_size;
+    }
+    else
+    {
+        abc_plane_stride = abc_elem_size;
+        abc_stride = lines->rows == 1 ? 3*abc_elem_size : lines->step;
+    }
+
+    CV_CALL( cvConvert( fmatrix, &F ));
+    if( pointImageID == 2 )
+        cvTranspose( &F, &F );
+
+    xp = points->data.ptr;
+    yp = xp + plane_stride;
+    zp = dims == 3 ? yp + plane_stride : 0;
+
+    ap = lines->data.ptr;
+    bp = ap + abc_plane_stride;
+    cp = bp + abc_plane_stride;
+
+    for( i = 0; i < count; i++ )
+    {
+        double x, y, z = 1.;
+        double a, b, c, nu;
+
+        if( depth == CV_32F )
+        {
+            x = *(float*)xp; y = *(float*)yp;
+            if( zp )
+                z = *(float*)zp, zp += stride;
+        }
+        else
+        {
+            x = *(double*)xp; y = *(double*)yp;
+            if( zp )
+                z = *(double*)zp, zp += stride;
+        }
+
+        xp += stride; yp += stride;
+
+        a = f[0]*x + f[1]*y + f[2]*z;
+        b = f[3]*x + f[4]*y + f[5]*z;
+        c = f[6]*x + f[7]*y + f[8]*z;
+        nu = a*a + b*b;
+        nu = nu ? 1./sqrt(nu) : 1.;
+        a *= nu; b *= nu; c *= nu;
+
+        if( abc_depth == CV_32F )
+        {
+            *(float*)ap = (float)a;
+            *(float*)bp = (float)b;
+            *(float*)cp = (float)c;
+        }
+        else
+        {
+            *(double*)ap = a;
+            *(double*)bp = b;
+            *(double*)cp = c;
+        }
+
+        ap += abc_stride;
+        bp += abc_stride;
+        cp += abc_stride;
+    }
+
+    __END__;
+}
+
+
+CV_IMPL void
+cvConvertPointsHomogeneous( const CvMat* src, CvMat* dst )
+{
+    CvMat* temp = 0;
+    CvMat* denom = 0;
+
+    CV_FUNCNAME( "cvConvertPointsHomogeneous" );
+
+    __BEGIN__;
+
+    int i, s_count, s_dims, d_count, d_dims;
+    CvMat _src, _dst, _ones;
+    CvMat* ones = 0;
+
+    if( !CV_IS_MAT(src) )
+        CV_ERROR( !src ? CV_StsNullPtr : CV_StsBadArg,
+        "The input parameter is not a valid matrix" );
+
+    if( !CV_IS_MAT(dst) )
+        CV_ERROR( !dst ? CV_StsNullPtr : CV_StsBadArg,
+        "The output parameter is not a valid matrix" );
+
+    if( src == dst || src->data.ptr == dst->data.ptr )
+    {
+        if( src != dst && (!CV_ARE_TYPES_EQ(src, dst) || !CV_ARE_SIZES_EQ(src,dst)) )
+            CV_ERROR( CV_StsBadArg, "Invalid inplace operation" );
+        EXIT;
+    }
+
+    if( src->rows > src->cols )
+    {
+        if( !((src->cols > 1) ^ (CV_MAT_CN(src->type) > 1)) )
+            CV_ERROR( CV_StsBadSize, "Either the number of channels or columns or rows must be =1" );
+
+        s_dims = CV_MAT_CN(src->type)*src->cols;
+        s_count = src->rows;
+    }
+    else
+    {
+        if( !((src->rows > 1) ^ (CV_MAT_CN(src->type) > 1)) )
+            CV_ERROR( CV_StsBadSize, "Either the number of channels or columns or rows must be =1" );
+
+        s_dims = CV_MAT_CN(src->type)*src->rows;
+        s_count = src->cols;
+    }
+
+    if( src->rows == 1 || src->cols == 1 )
+        src = cvReshape( src, &_src, 1, s_count );
+
+    if( dst->rows > dst->cols )
+    {
+        if( !((dst->cols > 1) ^ (CV_MAT_CN(dst->type) > 1)) )
+            CV_ERROR( CV_StsBadSize,
+            "Either the number of channels or columns or rows in the input matrix must be =1" );
+
+        d_dims = CV_MAT_CN(dst->type)*dst->cols;
+        d_count = dst->rows;
+    }
+    else
+    {
+        if( !((dst->rows > 1) ^ (CV_MAT_CN(dst->type) > 1)) )
+            CV_ERROR( CV_StsBadSize,
+            "Either the number of channels or columns or rows in the output matrix must be =1" );
+
+        d_dims = CV_MAT_CN(dst->type)*dst->rows;
+        d_count = dst->cols;
+    }
+
+    if( dst->rows == 1 || dst->cols == 1 )
+        dst = cvReshape( dst, &_dst, 1, d_count );
+
+    if( s_count != d_count )
+        CV_ERROR( CV_StsUnmatchedSizes, "Both matrices must have the same number of points" );
+
+    if( CV_MAT_DEPTH(src->type) < CV_32F || CV_MAT_DEPTH(dst->type) < CV_32F )
+        CV_ERROR( CV_StsUnsupportedFormat,
+        "Both matrices must be floating-point (single or double precision)" );
+
+    if( s_dims < 2 || s_dims > 4 || d_dims < 2 || d_dims > 4 )
+        CV_ERROR( CV_StsOutOfRange,
+        "Both input and output point dimensionality must be 2, 3 or 4" );
+
+    if( s_dims < d_dims - 1 || s_dims > d_dims + 1 )
+        CV_ERROR( CV_StsUnmatchedSizes,
+        "The dimensionalities of input and output point sets differ too much" );
+
+    if( s_dims == d_dims - 1 )
+    {
+        if( d_count == dst->rows )
+        {
+            ones = cvGetSubRect( dst, &_ones, cvRect( s_dims, 0, 1, d_count ));
+            dst = cvGetSubRect( dst, &_dst, cvRect( 0, 0, s_dims, d_count ));
+        }
+        else
+        {
+            ones = cvGetSubRect( dst, &_ones, cvRect( 0, s_dims, d_count, 1 ));
+            dst = cvGetSubRect( dst, &_dst, cvRect( 0, 0, d_count, s_dims ));
+        }
+    }
+
+    if( s_dims <= d_dims )
+    {
+        if( src->rows == dst->rows && src->cols == dst->cols )
+        {
+            if( CV_ARE_TYPES_EQ( src, dst ) )
+                cvCopy( src, dst );
+            else
+                cvConvert( src, dst );
+        }
+        else
+        {
+            if( !CV_ARE_TYPES_EQ( src, dst ))
+            {
+                CV_CALL( temp = cvCreateMat( src->rows, src->cols, dst->type ));
+                cvConvert( src, temp );
+                src = temp;
+            }
+            cvTranspose( src, dst );
+        }
+
+        if( ones )
+            cvSet( ones, cvRealScalar(1.) );
+    }
+    else
+    {
+        int s_plane_stride, s_stride, d_plane_stride, d_stride, elem_size;
+
+        if( !CV_ARE_TYPES_EQ( src, dst ))
+        {
+            CV_CALL( temp = cvCreateMat( src->rows, src->cols, dst->type ));
+            cvConvert( src, temp );
+            src = temp;
+        }
+
+        elem_size = CV_ELEM_SIZE(src->type);
+
+        if( s_count == src->cols )
+            s_plane_stride = src->step / elem_size, s_stride = 1;
+        else
+            s_stride = src->step / elem_size, s_plane_stride = 1;
+
+        if( d_count == dst->cols )
+            d_plane_stride = dst->step / elem_size, d_stride = 1;
+        else
+            d_stride = dst->step / elem_size, d_plane_stride = 1;
+
+        CV_CALL( denom = cvCreateMat( 1, d_count, dst->type ));
+
+        if( CV_MAT_DEPTH(dst->type) == CV_32F )
+        {
+            const float* xs = src->data.fl;
+            const float* ys = xs + s_plane_stride;
+            const float* zs = 0;
+            const float* ws = xs + (s_dims - 1)*s_plane_stride;
+
+            float* iw = denom->data.fl;
+
+            float* xd = dst->data.fl;
+            float* yd = xd + d_plane_stride;
+            float* zd = 0;
+
+            if( d_dims == 3 )
+            {
+                zs = ys + s_plane_stride;
+                zd = yd + d_plane_stride;
+            }
+
+            for( i = 0; i < d_count; i++, ws += s_stride )
+            {
+                float t = *ws;
+                iw[i] = fabs((double)t) > FLT_EPSILON ? t : 1.f;
+            }
+
+            cvDiv( 0, denom, denom );
+
+            if( d_dims == 3 )
+                for( i = 0; i < d_count; i++ )
+                {
+                    float w = iw[i];
+                    float x = *xs * w, y = *ys * w, z = *zs * w;
+                    xs += s_stride; ys += s_stride; zs += s_stride;
+                    *xd = x; *yd = y; *zd = z;
+                    xd += d_stride; yd += d_stride; zd += d_stride;
+                }
+            else
+                for( i = 0; i < d_count; i++ )
+                {
+                    float w = iw[i];
+                    float x = *xs * w, y = *ys * w;
+                    xs += s_stride; ys += s_stride;
+                    *xd = x; *yd = y;
+                    xd += d_stride; yd += d_stride;
+                }
+        }
+        else
+        {
+            const double* xs = src->data.db;
+            const double* ys = xs + s_plane_stride;
+            const double* zs = 0;
+            const double* ws = xs + (s_dims - 1)*s_plane_stride;
+
+            double* iw = denom->data.db;
+
+            double* xd = dst->data.db;
+            double* yd = xd + d_plane_stride;
+            double* zd = 0;
+
+            if( d_dims == 3 )
+            {
+                zs = ys + s_plane_stride;
+                zd = yd + d_plane_stride;
+            }
+
+            for( i = 0; i < d_count; i++, ws += s_stride )
+            {
+                double t = *ws;
+                iw[i] = fabs(t) > DBL_EPSILON ? t : 1.;
+            }
+
+            cvDiv( 0, denom, denom );
+
+            if( d_dims == 3 )
+                for( i = 0; i < d_count; i++ )
+                {
+                    double w = iw[i];
+                    double x = *xs * w, y = *ys * w, z = *zs * w;
+                    xs += s_stride; ys += s_stride; zs += s_stride;
+                    *xd = x; *yd = y; *zd = z;
+                    xd += d_stride; yd += d_stride; zd += d_stride;
+                }
+            else
+                for( i = 0; i < d_count; i++ )
+                {
+                    double w = iw[i];
+                    double x = *xs * w, y = *ys * w;
+                    xs += s_stride; ys += s_stride;
+                    *xd = x; *yd = y;
+                    xd += d_stride; yd += d_stride;
+                }
+        }
+    }
+
+    __END__;
+
+    cvReleaseMat( &denom );
+    cvReleaseMat( &temp );
+}
+
+namespace cv
+{
+
+static Mat _findHomography( const Vector<Point2f>& srcPoints,
+                            const Vector<Point2f>& dstPoints,
+                            int method, double ransacReprojThreshold,
+                            Vector<bool>* mask )
+{
+    Mat H(3, 3, CV_64F);
+    CvMat _pt1 = srcPoints, _pt2 = dstPoints;
+    CvMat _H = H, _mask, *pmask = 0;
+    if( mask )
+    {
+        mask->resize(srcPoints.size());
+        pmask = &(_mask = cvMat(1, (int)mask->size(), CV_8U, (void*)&(*mask)[0]));
+    }
+    bool ok = cvFindHomography( &_pt1, &_pt2, &_H, method, ransacReprojThreshold, pmask ) > 0;
+    if( !ok )
+        H = Scalar(0);
+    return H;
+}
+
+Mat findHomography( const Vector<Point2f>& srcPoints,
+                    const Vector<Point2f>& dstPoints,
+                    Vector<bool>& mask, int method,
+                    double ransacReprojThreshold )
+{
+    return _findHomography(srcPoints, dstPoints, method, ransacReprojThreshold, &mask);
+}
+
+Mat findHomography( const Vector<Point2f>& srcPoints,
+                    const Vector<Point2f>& dstPoints,
+                    int method, double ransacReprojThreshold )
+{
+    return _findHomography(srcPoints, dstPoints, method, ransacReprojThreshold, 0);
+}
+
+static Mat _findFundamentalMat( const Vector<Point2f>& points1,
+                                const Vector<Point2f>& points2,
+                                int method, double param1, double param2,
+                                Vector<bool>* mask )
+{
+    Mat F(3, 3, CV_64F);
+    CvMat _pt1 = points1, _pt2 = points2;
+    CvMat _F = F, _mask, *pmask = 0;
+    if( mask )
+    {
+        mask->resize(points1.size());
+        pmask = &(_mask = cvMat(1, (int)mask->size(), CV_8U, (void*)&(*mask)[0]));
+    }
+    int n = cvFindFundamentalMat( &_pt1, &_pt2, &_F, method, param1, param2, pmask );
+    if( n <= 0 )
+        F = Scalar(0);
+    return F;
+}
+
+Mat findFundamentalMat( const Vector<Point2f>& points1,
+                        const Vector<Point2f>& points2,
+                        Vector<bool>& mask,
+                        int method, double param1, double param2 )
+{
+    return _findFundamentalMat( points1, points2, method, param1, param2, &mask );
+}
+
+Mat findFundamentalMat( const Vector<Point2f>& points1,
+                        const Vector<Point2f>& points2,
+                        int method, double param1, double param2 )
+{
+    return _findFundamentalMat( points1, points2, method, param1, param2, 0 );
+}
+
+void computeCorrespondEpilines( const Vector<Point2f>& points,
+                                int whichImage, const Mat& F,
+                                Vector<Vec3f>& lines )
+{
+    lines.resize(points.size());
+    CvMat _points = points, _lines = lines, _F = F;
+    cvComputeCorrespondEpilines(&_points, whichImage, &_F, &_lines);
+}
+
+void convertPointsHomogeneous( const Vector<Point2f>& src,
+                               Vector<Point3f>& dst )
+{
+    dst.resize(src.size());
+    CvMat _src = src, _dst = dst;
+    cvConvertPointsHomogeneous(&_src, &_dst);
+}
+
+void convertPointsHomogeneous( const Vector<Point3f>& src,
+                               Vector<Point2f>& dst )
+{
+    dst.resize(src.size());
+    CvMat _src = src, _dst = dst;
+    cvConvertPointsHomogeneous(&_src, &_dst);
+}
+
+}
+
+/* End of file. */
index f203c645eb0b3d03bdabad53c3d054f0a26da234..6417125d0c5ae9be9d1f3a8b6dc197a508486524 100644 (file)
@@ -2996,6 +2996,44 @@ Mat getAffineTransform( const Point2f src[], const Point2f dst[] )
     solve( A, B, X );
     return M;
 }
+    
+void invertAffineTransform(const Mat& _M, Mat& _iM)
+{
+    CV_Assert(_M.rows == 2 && _M.cols == 3);
+    _iM.create(2, 3, _M.type());
+    if( _M.type() == CV_32F )
+    {
+        const float* M = (const float*)_M.data;
+        float* iM = (float*)_iM.data;
+        int step = _M.step/sizeof(M[0]), istep = _iM.step/sizeof(iM[0]);
+        
+        double D = M[0]*M[step+1] - M[1]*M[step];
+        D = D != 0 ? 1./D : 0;
+        double A11 = M[step+1]*D, A22 = M[0]*D, A12 = -M[1]*D, A21 = -M[step]*D;
+        double b1 = -A11*M[2] - A12*M[step+2];
+        double b2 = -A21*M[2] - A22*M[step+2];
+        
+        iM[0] = (float)A11; iM[1] = (float)A12; iM[2] = (float)b1;
+        iM[istep] = (float)A21; iM[istep+1] = (float)A22; iM[istep+2] = (float)b2;
+    }
+    else if( _M.type() == CV_64F )
+    {
+        const double* M = (const double*)_M.data;
+        double* iM = (double*)_iM.data;
+        int step = _M.step/sizeof(M[0]), istep = _iM.step/sizeof(iM[0]);
+        
+        double D = M[0]*M[step+1] - M[1]*M[step];
+        D = D != 0 ? 1./D : 0;
+        double A11 = M[step+1]*D, A22 = M[0]*D, A12 = -M[1]*D, A21 = -M[step]*D;
+        double b1 = -A11*M[2] - A12*M[step+2];
+        double b2 = -A21*M[2] - A22*M[step+2];
+        
+        iM[0] = A11; iM[1] = A12; iM[2] = b1;
+        iM[istep] = A21; iM[istep+1] = A22; iM[istep+2] = b2;
+    }
+    else
+        CV_Error( CV_StsUnsupportedFormat, "" );
+}    
 
 }
 
diff --git a/opencv/src/cvaux/cvplanardetect.cpp b/opencv/src/cvaux/cvplanardetect.cpp
new file mode 100644 (file)
index 0000000..6b291e3
--- /dev/null
@@ -0,0 +1,1338 @@
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+//  By downloading, copying, installing or using the software you agree to this license.
+//  If you do not agree to this license, do not download, install,
+//  copy or use the software.
+//
+//
+//                           License Agreement
+//                For Open Source Computer Vision Library
+//
+// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
+// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+//   * Redistribution's of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//
+//   * Redistribution's in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//
+//   * The name of the copyright holders may not be used to endorse or promote products
+//     derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+#include "_cvaux.h"
+
+namespace cv
+{
+
+const int progressBarSize = 50;    
+
+//////////////////////////// Patch Generator //////////////////////////////////    
+
+static const double DEFAULT_BACKGROUND_MIN = 0;
+static const double DEFAULT_BACKGROUND_MAX = 256;
+static const double DEFAULT_NOISE_RANGE = 5;
+static const double DEFAULT_LAMBDA_MIN = 0.6;
+static const double DEFAULT_LAMBDA_MAX = 1.5;
+static const double DEFAULT_THETA_MIN = -CV_PI;
+static const double DEFAULT_THETA_MAX = CV_PI;
+static const double DEFAULT_PHI_MIN = -CV_PI;
+static const double DEFAULT_PHI_MAX = CV_PI;
+
+PatchGenerator::PatchGenerator()
+: backgroundMin(DEFAULT_BACKGROUND_MIN), backgroundMax(DEFAULT_BACKGROUND_MAX),
+noiseRange(DEFAULT_NOISE_RANGE), randomBlur(true), lambdaMin(DEFAULT_LAMBDA_MIN),
+lambdaMax(DEFAULT_LAMBDA_MAX), thetaMin(DEFAULT_THETA_MIN),
+thetaMax(DEFAULT_THETA_MAX), phiMin(DEFAULT_PHI_MIN),
+phiMax(DEFAULT_PHI_MAX)
+{
+}
+
+
+PatchGenerator::PatchGenerator(double _backgroundMin, double _backgroundMax,
+                               double _noiseRange, bool _randomBlur,
+                               double _lambdaMin, double _lambdaMax,
+                               double _thetaMin, double _thetaMax,
+                               double _phiMin, double _phiMax )
+: backgroundMin(_backgroundMin), backgroundMax(_backgroundMax),
+noiseRange(_noiseRange), randomBlur(_randomBlur),
+lambdaMin(_lambdaMin), lambdaMax(_lambdaMax),
+thetaMin(_thetaMin), thetaMax(_thetaMax),
+phiMin(_phiMin), phiMax(_phiMax)
+{
+}
+
+
+void PatchGenerator::generateRandomTransform(Point2f srcCenter, Point2f dstCenter,
+                                             Mat& transform, RNG& rng, bool inverse) const
+{
+    double lambda1 = rng.uniform(lambdaMin, lambdaMax);
+    double lambda2 = rng.uniform(lambdaMin, lambdaMax);
+    double theta = rng.uniform(thetaMin, thetaMax);
+    double phi = rng.uniform(phiMin, phiMax);
+    
+    // Calculate random parameterized affine transformation A,
+    // A = T(patch center) * R(theta) * R(phi)' *
+    //     S(lambda1, lambda2) * R(phi) * T(-pt)
+    double st = sin(theta);
+    double ct = cos(theta);
+    double sp = sin(phi);
+    double cp = cos(phi);
+    double c2p = cp*cp;
+    double s2p = sp*sp;
+    
+    double A = lambda1*c2p + lambda2*s2p;
+    double B = (lambda2 - lambda1)*sp*cp;
+    double C = lambda1*s2p + lambda2*c2p;
+    
+    double Ax_plus_By = A*srcCenter.x + B*srcCenter.y;
+    double Bx_plus_Cy = B*srcCenter.x + C*srcCenter.y;
+    
+    transform.create(2, 3, CV_64F);
+    Mat_<double>& T = (Mat_<double>&)transform;
+    T(0,0) = A*ct - B*st;
+    T(0,1) = B*ct - C*st;
+    T(0,2) = -ct*Ax_plus_By + st*Bx_plus_Cy + dstCenter.x;
+    T(1,0) = A*st + B*ct;
+    T(1,1) = B*st + C*ct;
+    T(1,2) = -st*Ax_plus_By - ct*Bx_plus_Cy + dstCenter.y;
+    
+    if( inverse )
+        invertAffineTransform(T, T);
+}
+
+
+void PatchGenerator::operator ()(const Mat& image, Point2f pt, Mat& patch, Size patchSize, RNG& rng) const
+{
+    double buffer[6];
+    Mat_<double> T(2, 3, buffer);
+    
+    generateRandomTransform(pt, Point2f((patchSize.width-1)*0.5f, (patchSize.height-1)*0.5f), T, rng);
+    (*this)(image, T, patch, patchSize, rng);
+}
+
+
+void PatchGenerator::operator ()(const Mat& image, const Mat& T,
+                                 Mat& patch, Size patchSize, RNG& rng) const
+{
+    patch.create( patchSize, image.type() );
+    if( backgroundMin != backgroundMax )
+    {
+        rng.fill(patch, RNG::UNIFORM, Scalar::all(backgroundMin), Scalar::all(backgroundMax));
+        warpAffine(image, patch, T, patchSize, INTER_LINEAR, BORDER_TRANSPARENT);
+    }
+    else
+        warpAffine(image, patch, T, patchSize, INTER_LINEAR, BORDER_CONSTANT, Scalar::all(backgroundMin));
+    
+    int ksize = randomBlur ? (unsigned)rng % 9 - 5 : 0;
+    if( ksize > 0 )
+    {
+        ksize = ksize*2 + 1;
+        GaussianBlur(patch, patch, Size(ksize, ksize), 0, 0);
+    }
+    
+    if( noiseRange > 0 )
+    {
+        AutoBuffer<uchar> _noiseBuf( patchSize.width*patchSize.height*image.elemSize() );
+        Mat noise(patchSize, image.type(), (uchar*)_noiseBuf);
+        int delta = image.depth() == CV_8U ? 128 : image.depth() == CV_16U ? 32768 : 0;
+        rng.fill(noise, RNG::NORMAL, Scalar::all(delta), Scalar::all(noiseRange));
+        if( backgroundMin != backgroundMax )
+            addWeighted(patch, 1, noise, 1, -delta, patch);
+        else
+        {
+            for( int i = 0; i < patchSize.height; i++ )
+            {
+                uchar* prow = patch.ptr<uchar>(i);
+                const uchar* nrow =  noise.ptr<uchar>(i);
+                for( int j = 0; j < patchSize.width; j++ )
+                    if( prow[j] != backgroundMin )
+                        prow[j] = saturate_cast<uchar>(prow[j] + nrow[j] - delta);
+            }
+        }
+    }
+}
+
+void PatchGenerator::warpWholeImage(const Mat& image, Mat& _T, Mat& buf,
+                                    Mat& warped, int border, RNG& rng) const
+{
+    Mat_<double> T = _T;
+    Rect roi(INT_MAX, INT_MAX, INT_MIN, INT_MIN);
+    
+    for( int k = 0; k < 4; k++ )
+    {
+        Point2f pt0, pt1;
+        pt0.x = (float)(k == 0 || k == 3 ? 0 : image.cols);
+        pt0.y = (float)(k < 2 ? 0 : image.rows);
+        pt1.x = T(0,0)*pt0.x + T(0,1)*pt0.y + T(0,2);
+        pt1.y = T(1,0)*pt0.x + T(1,1)*pt0.y + T(1,2);
+        
+        roi.x = std::min(roi.x, cvFloor(pt1.x));
+        roi.y = std::min(roi.y, cvFloor(pt1.y));
+        roi.width = std::max(roi.width, cvCeil(pt1.x));
+        roi.height = std::max(roi.height, cvCeil(pt1.y));
+    }
+    
+    roi.width -= roi.x - 1;
+    roi.height -= roi.y - 1;
+    int dx = border - roi.x;
+    int dy = border - roi.y;
+    
+    if( (roi.width+border*2)*(roi.height+border*2) > buf.cols )
+        buf.create(1, (roi.width+border*2)*(roi.height+border*2), image.type());
+    
+    warped = Mat(roi.height + border*2, roi.width + border*2,
+                 image.type(), buf.data);
+    
+    T(0,2) += dx;
+    T(1,2) += dy;
+    (*this)(image, T, warped, warped.size(), rng);
+    
+    if( T.data != _T.data )
+        T.convertTo(_T, _T.type());        
+}
+
+
+/////////////////////////////////////// LDetector //////////////////////////////////////////////
+
+LDetector::LDetector() : radius(7), threshold(20), nOctaves(3), nViews(1000),
+    verbose(false), baseFeatureSize(32), clusteringDistance(2)
+{
+}
+
+LDetector::LDetector(int _radius, int _threshold, int _nOctaves, int _nViews,
+                     double _baseFeatureSize, double _clusteringDistance)
+: radius(_radius), threshold(_threshold), nOctaves(_nOctaves), nViews(_nViews),
+    verbose(false), baseFeatureSize(_baseFeatureSize), clusteringDistance(_clusteringDistance)
+{
+}
+
+static void getDiscreteCircle(int R, Vector<Point>& circle, Vector<int>& filledHCircle)
+{
+    int x = R, y = 0;
+    for( ;;y++ )
+    {
+        x = cvRound(std::sqrt((double)R*R - y*y));
+        if( x < y )
+            break;
+        circle.push_back(Point(x,y));
+        if( x == y )
+            break;
+    }
+    
+    int i, n8 = (int)circle.size() - (x == y), n8_ = n8 - (x != y), n4 = n8 + n8_, n = n4*4;
+    CV_Assert(n8 > 0);
+    circle.resize(n);
+    
+    for( i = 0; i < n8; i++ )
+    {
+        Point p = circle[i];
+        circle[i+n4] = Point(-p.y, p.x);
+        circle[i+n4*2] = Point(-p.x, -p.y);
+        circle[i+n4*3] = Point(p.y, -p.x);
+    }
+    
+    for( i = n8; i < n4; i++ )
+    {
+        Point p = circle[n4 - i], q = Point(p.y, p.x);
+        circle[i] = q;
+        circle[i+n4] = Point(-q.y, q.x);
+        circle[i+n4*2] = Point(-q.x, -q.y);
+        circle[i+n4*3] = Point(q.y, -q.x);
+    }
+    
+    // the filled upper half of the circle is encoded as sequence of integers,
+    // i-th element is the coordinate of right-most circle point in each horizontal line y=i.
+    // the left-most point will be -filledHCircle[i].
+    for( i = 0, y = -1; i < n4; i++ )
+    {
+        Point p = circle[i];
+        if( p.y != y )
+        {
+            filledHCircle.push_back(p.x);
+            y = p.y;
+            if( y == R )
+                break;
+        }
+    }
+}
+
+
+struct CmpKeypointScores
+{
+    bool operator ()(const Keypoint& a, const Keypoint& b) const { return std::abs(a.response) > std::abs(b.response); }
+};
+
+
+void LDetector::getMostStable2D(const Mat& image, Vector<Keypoint>& keypoints,
+                                int maxPoints, const PatchGenerator& _patchGenerator) const
+{
+    PatchGenerator patchGenerator = _patchGenerator;
+    patchGenerator.backgroundMin = patchGenerator.backgroundMax = 128;
+    
+    Mat warpbuf, warped;
+    Mat _M(2, 3, CV_64F), _iM(2, 3, CV_64F);
+    double *M = (double*)_M.data, *iM = (double*)_iM.data;
+    RNG& rng = theRNG();
+    int i, k;
+    Vector<Keypoint> tempKeypoints;
+    double d2 = clusteringDistance*clusteringDistance;
+    keypoints.clear();
+    
+    // TODO: this loop can be run in parallel, for that we need
+    // a separate accumulator keypoint lists for different threads.
+    for( i = 0; i < nViews; i++ )
+    {
+        // 1. generate random transform
+        // 2. map the source image corners and compute the ROI in canvas
+        // 3. select the ROI in canvas, adjust the transformation matrix
+        // 4. apply the transformation
+        // 5. run keypoint detector in pyramids
+        // 6. map each point back and update the lists of most stable points
+        
+        if(verbose && (i+1)*progressBarSize/nViews != i*progressBarSize/nViews)
+            putchar('.');
+        
+        if( i > 0 )
+            patchGenerator.generateRandomTransform(Point2f(), Point2f(), _M, rng);
+        else
+        {
+            // identity transformation
+            M[0] = M[4] = 1;
+            M[1] = M[3] = M[2] = M[5] = 0;
+        }
+        
+        patchGenerator.warpWholeImage(image, _M, warpbuf, warped, cvCeil(baseFeatureSize*0.5+radius), rng);
+        (*this)(warped, tempKeypoints, maxPoints*3);
+        invertAffineTransform(_M, _iM);
+        
+        int j, sz0 = (int)tempKeypoints.size(), sz1;
+        for( j = 0; j < sz0; j++ )
+        {
+            Keypoint kpt1 = tempKeypoints[j];
+            Keypoint kpt0((float)(iM[0]*kpt1.pt.x + iM[1]*kpt1.pt.y + iM[2]),
+                          (float)(iM[3]*kpt1.pt.x + iM[4]*kpt1.pt.y + iM[5]),
+                          kpt1.size, -1.f, 1.f, kpt1.octave);
+            float r = kpt1.size*0.5f;
+            if( kpt0.pt.x < r || kpt0.pt.x >= image.cols - r ||
+               kpt0.pt.y < r || kpt0.pt.y >= image.rows - r )
+                continue;
+            
+            sz1 = (int)keypoints.size();
+            for( k = 0; k < sz1; k++ )
+            {
+                Keypoint kpt = keypoints[k];
+                if( kpt.octave != kpt0.octave )
+                    continue;
+                double dx = kpt.pt.x - kpt0.pt.x, dy = kpt.pt.y - kpt0.pt.y;
+                if( dx*dx + dy*dy <= d2*(1 << kpt.octave*2) )
+                {
+                    keypoints[k] = Keypoint((kpt.pt.x*kpt.response + kpt0.pt.x)/(kpt.response+1),
+                                            (kpt.pt.y*kpt.response + kpt0.pt.y)/(kpt.response+1),
+                                            kpt.size, -1.f, kpt.response + 1, kpt.octave);
+                    break;
+                }
+            }
+            if( k == sz1 )
+                keypoints.push_back(kpt0);
+        }
+    }
+    
+    if( verbose )
+        putchar('\n');
+    
+    if( (int)keypoints.size() > maxPoints )
+    {
+        sort(keypoints, CmpKeypointScores());
+        keypoints.resize(maxPoints);
+    }
+}
+
+
+static inline int computeLResponse(const uchar* ptr, const int* cdata, int csize)
+{
+    int i, csize2 = csize/2, sum = -ptr[0]*csize;
+    for( i = 0; i < csize2; i++ )
+    {
+        int ofs = cdata[i];
+        sum += ptr[ofs] + ptr[-ofs];
+    }
+    return sum;    
+}
+
+
+static Point2f adjustCorner(const float* fval, float& fvaln)
+{
+    double bx = (fval[3] - fval[5])*0.5;
+    double by = (fval[2] - fval[7])*0.5;
+    double Axx = fval[3] - fval[4]*2 + fval[5];
+    double Axy = (fval[0] - fval[2] - fval[6] + fval[8])*0.25;
+    double Ayy = fval[1] - fval[4]*2 + fval[7];
+    double D = Axx*Ayy - Axy*Axy;
+    D = D != 0 ? 1./D : 0;
+    double dx = (bx*Ayy - by*Axy)*D;
+    double dy = (by*Axx - bx*Axy)*D;
+    dx = std::min(std::max(dx, -1.), 1.);
+    dy = std::min(std::max(dy, -1.), 1.);
+    fvaln = (float)(fval[4] + (bx*dx + by*dy)*0.5);
+    if(fvaln*fval[4] < 0 || std::abs(fvaln) < std::abs(fval[4]))
+        fvaln = fval[4];
+    
+    return Point2f((float)dx, (float)dy);
+}    
+
+void LDetector::operator()(const Mat& image, Vector<Keypoint>& keypoints, int maxCount, bool scaleCoords) const
+{
+    Vector<Mat> pyr;
+    buildPyramid(image, pyr, std::max(nOctaves-1, 0));
+    (*this)(pyr, keypoints, maxCount, scaleCoords);    
+}       
+
+void LDetector::operator()(const Vector<Mat>& pyr, Vector<Keypoint>& keypoints, int maxCount, bool scaleCoords) const
+{
+    const int lthreshold = 3;
+    int L, x, y, i, j, k, tau = lthreshold;
+    Mat scoreBuf(pyr[0].size(), CV_16S), maskBuf(pyr[0].size(), CV_8U);
+    int scoreElSize = scoreBuf.elemSize();
+    Vector<Point> circle0;
+    Vector<int> fhcircle0, circle, fcircle_s, fcircle;
+    getDiscreteCircle(radius, circle0, fhcircle0);
+    CV_Assert(fhcircle0.size() == (size_t)(radius+1) && circle0.size() % 2 == 0);
+    keypoints.clear();
+    
+    for( L = 0; L < nOctaves; L++ )
+    {
+        //  Pyramidal keypoint detector body:
+        //    1. build next pyramid layer
+        //    2. scan points, check the circular neighborhood, compute the score
+        //    3. do non-maxima suppression
+        //    4. adjust the corners (sub-pix)
+        double cscale = scaleCoords ? 1 << L : 1;
+        Size layerSize = pyr[L].size();
+        if( layerSize.width < radius*2 + 3 || layerSize.height < radius*2 + 3 )
+            break;
+        Mat scoreLayer(layerSize, scoreBuf.type(), scoreBuf.data);
+        Mat maskLayer(layerSize, maskBuf.type(), maskBuf.data);
+        const Mat& pyrLayer = pyr[L];
+        int sstep = scoreLayer.step/sizeof(short);
+        int mstep = maskLayer.step;
+        
+        int csize = (int)circle0.size(), csize2 = csize/2;
+        circle.resize(csize*3);
+        for( i = 0; i < csize; i++ )
+            circle[i] = circle[i+csize] = circle[i+csize*2] = (-circle0[i].y)*pyrLayer.step + circle0[i].x;
+        fcircle.clear();
+        fcircle_s.clear();
+        for( i = -radius; i <= radius; i++ )
+        {
+            x = fhcircle0[std::abs(i)];
+            for( j = -x; j <= x; j++ )
+            {
+                fcircle_s.push_back(i*sstep + j);
+                fcircle.push_back(i*pyrLayer.step + j);
+            }
+        }
+        int nsize = (int)fcircle.size();
+        const int* cdata = &circle[0];
+        const int* ndata = &fcircle[0];
+        const int* ndata_s = &fcircle_s[0];
+        
+        for( y = 0; y < radius; y++ )
+        {
+            memset( scoreLayer.ptr<short>(y), 0, layerSize.width*scoreElSize );
+            memset( scoreLayer.ptr<short>(layerSize.height-y-1), 0, layerSize.width*scoreElSize );
+            memset( maskLayer.ptr<uchar>(y), 0, layerSize.width );
+            memset( maskLayer.ptr<uchar>(layerSize.height-y-1), 0, layerSize.width );
+        }
+        
+        int vradius = radius*pyrLayer.step;
+        
+        for( y = radius; y < layerSize.height - radius; y++ )
+        {
+            const uchar* img = pyrLayer.ptr<uchar>(y) + radius;
+            short* scores = scoreLayer.ptr<short>(y);
+            uchar* mask = maskLayer.ptr<uchar>(y);
+            
+            for( x = 0; x < radius; x++ )
+            {
+                scores[x] = scores[layerSize.width - 1 - x] = 0;
+                mask[x] = mask[layerSize.width - 1 - x] = 0;
+            }
+            
+            for( x = radius; x < layerSize.width - radius; x++, img++ )
+            {
+                int val0 = *img;
+                if( (std::abs(val0 - img[radius]) < tau && std::abs(val0 - img[-radius]) < tau) ||
+                   (std::abs(val0 - img[vradius]) < tau && std::abs(val0 - img[-vradius]) < tau))
+                {
+                    scores[x] = 0;
+                    mask[x] = 0;
+                    continue;
+                }
+                
+                for( k = 0; k < csize; k++ )
+                {
+                    if( std::abs(val0 - img[cdata[k]]) < tau &&
+                       (std::abs(val0 - img[cdata[k + csize2]]) < tau ||
+                        std::abs(val0 - img[cdata[k + csize2 - 1]]) < tau ||
+                        std::abs(val0 - img[cdata[k + csize2 + 1]]) < tau ||
+                        std::abs(val0 - img[cdata[k + csize2 - 2]]) < tau ||
+                        std::abs(val0 - img[cdata[k + csize2 + 2]]) < tau/* ||
+                     std::abs(val0 - img[cdata[k + csize2 - 3]]) < tau ||
+                     std::abs(val0 - img[cdata[k + csize2 + 3]]) < tau*/) )
+                        break;
+                }
+                
+                if( k < csize )
+                {
+                    scores[x] = 0;
+                    mask[x] = 0;
+                }
+                else
+                {
+                    scores[x] = computeLResponse(img, cdata, csize);
+                    mask[x] = 1;
+                }
+            }
+        }
+        
+        for( y = radius+1; y < layerSize.height - radius-1; y++ )
+        {
+            const uchar* img = pyrLayer.ptr<uchar>(y) + radius+1;
+            short* scores = scoreLayer.ptr<short>(y) + radius+1;
+            const uchar* mask = maskLayer.ptr<uchar>(y) + radius+1;
+            
+            for( x = radius+1; x < layerSize.width - radius-1; x++, img++, scores++, mask++ )
+            {
+                int val0 = *scores;
+                if( !*mask || std::abs(val0) < lthreshold ||
+                   (mask[-1] + mask[1] + mask[-mstep-1] + mask[-mstep] + mask[-mstep+1]+
+                    mask[mstep-1] + mask[mstep] + mask[mstep+1] < 3))
+                    continue;
+                bool recomputeZeroScores = radius*2 < y && y < layerSize.height - radius*2 &&
+                radius*2 < x && x < layerSize.width - radius*2;
+                
+                if( val0 > 0 )
+                {
+                    for( k = 0; k < nsize; k++ )
+                    {
+                        int val = scores[ndata_s[k]];
+                        if( val == 0 && recomputeZeroScores )
+                            scores[ndata_s[k]] = val = computeLResponse(img + ndata[k], cdata, csize);
+                        if( val0 < val )
+                            break;
+                    }
+                }
+                else
+                {
+                    for( k = 0; k < nsize; k++ )
+                    {
+                        int val = scores[ndata_s[k]];
+                        if( val == 0 && recomputeZeroScores )
+                            scores[ndata_s[k]] = val = computeLResponse(img + ndata[k], cdata, csize);
+                        if( val0 > val )
+                            break;
+                    }
+                }
+                if( k < nsize )
+                    continue;
+                float fval[9], fvaln = 0;
+                for( int i1 = -1; i1 <= 1; i1++ )
+                    for( int j1 = -1; j1 <= 1; j1++ )
+                    {
+                        fval[(i1+1)*3 + j1 + 1] = scores[sstep*i1+j1] ? scores[sstep*i1+j1] :
+                        computeLResponse(img + pyrLayer.step*i1 + j1, cdata, csize);
+                    }
+                Point2f pt = adjustCorner(fval, fvaln);
+                pt.x += x;
+                pt.y += y;
+                keypoints.push_back(Keypoint((float)(pt.x*cscale), (float)(pt.y*cscale),
+                                             (float)(baseFeatureSize*cscale), -1, fvaln, L));
+            }
+        }
+    }
+    
+    if( keypoints.size() > (size_t)maxCount )
+    {
+        sort(keypoints, CmpKeypointScores());
+        keypoints.resize(maxCount);
+    }
+}    
+
+void LDetector::read(const FileNode& objnode)
+{
+    radius = (int)objnode["radius"];
+    threshold = (int)objnode["threshold"];
+    nOctaves = (int)objnode["noctaves"];
+    nViews = (int)objnode["nviews"];
+    baseFeatureSize = (int)objnode["base-feature-size"];
+    clusteringDistance = (int)objnode["clustering-distance"];    
+}
+
+void LDetector::write(FileStorage& fs, const String& name) const
+{
+    WriteStructContext ws(fs, name, CV_NODE_MAP);
+    
+    fs << "radius" << radius
+    << "threshold" << threshold
+    << "noctaves" << nOctaves
+    << "nviews" << nViews
+    << "base-feature-size" << baseFeatureSize
+    << "clustering-distance" << clusteringDistance;
+}    
+
+void LDetector::setVerbose(bool _verbose)
+{
+    verbose = _verbose;
+}
+
+/////////////////////////////////////// FernClassifier ////////////////////////////////////////////    
+
+FernClassifier::FernClassifier()
+{
+    clear();
+}
+
+
+FernClassifier::FernClassifier(const FileNode& node)
+{
+    clear();
+    read(node);
+}
+
+FernClassifier::~FernClassifier()
+{
+}
+   
+
+int FernClassifier::getClassCount() const
+{
+    return nclasses;
+}
+
+
+int FernClassifier::getStructCount() const
+{
+    return nstructs;
+}
+
+
+int FernClassifier::getStructSize() const
+{
+    return structSize;
+}
+
+
+int FernClassifier::getSignatureSize() const
+{
+    return signatureSize;
+}
+
+
+int FernClassifier::getCompressionMethod() const
+{
+    return compressionMethod;
+}
+
+
+Size FernClassifier::getPatchSize() const
+{
+    return patchSize;
+}        
+
+
+FernClassifier::FernClassifier(const Vector<Point2f>& points,
+                               const Vector<Ptr<Mat> >& refimgs,
+                               const Vector<int>& labels,
+                               int _nclasses, int _patchSize,
+                               int _signatureSize, int _nstructs,
+                               int _structSize, int _nviews, int _compressionMethod,
+                               const PatchGenerator& patchGenerator)
+{
+    clear();
+    train(points, refimgs, labels, _nclasses, _patchSize,
+          _signatureSize, _nstructs, _structSize, _nviews,
+          _compressionMethod, patchGenerator);
+}
+
+
+void FernClassifier::write(FileStorage& fs, const String& objname) const
+{
+    WriteStructContext ws(fs, objname, CV_NODE_MAP);
+    
+    cv::write(fs, "nstructs", nstructs);
+    cv::write(fs, "struct-size", structSize);
+    cv::write(fs, "nclasses", nclasses);
+    cv::write(fs, "signature-size", signatureSize);
+    cv::write(fs, "compression-method", compressionMethod);
+    cv::write(fs, "patch-size", patchSize.width);
+    {
+        WriteStructContext wsf(fs, "features", CV_NODE_SEQ + CV_NODE_FLOW);
+        int i, nfeatures = (int)features.size();
+        for( i = 0; i < nfeatures; i++ )
+        {
+            cv::write(fs, features[i].y1*patchSize.width + features[i].x1);
+            cv::write(fs, features[i].y2*patchSize.width + features[i].x2);
+        }
+    }
+    {
+        WriteStructContext wsp(fs, "posteriors", CV_NODE_SEQ + CV_NODE_FLOW);    
+        cv::write(fs, posteriors);
+    }
+}
+
+
+void FernClassifier::read(const FileNode& objnode)
+{
+    clear();
+    
+    nstructs = (int)objnode["nstructs"];
+    structSize = (int)objnode["struct-size"];
+    nclasses = (int)objnode["nclasses"];
+    signatureSize = (int)objnode["signature-size"];
+    compressionMethod = (int)objnode["compression-method"];
+    patchSize.width = patchSize.height = (int)objnode["patch-size"];
+    leavesPerStruct = 1 << structSize;
+    
+    FileNode _nodes = objnode["nodes"];
+    int i, nfeatures = structSize*nstructs;
+    features.resize(nfeatures);
+    FileNodeIterator it = _nodes.begin(), it_end = _nodes.end();
+    for( i = 0; i < nfeatures && it != it_end; i++ )
+    {
+        int ofs1, ofs2;
+        it >> ofs1 >> ofs2;
+        features[i] = Feature(ofs1%patchSize.width, ofs1/patchSize.width,
+                              ofs2%patchSize.width, ofs2/patchSize.width);
+    }
+    
+    FileNode _posteriors = objnode["posteriors"];
+    int psz = leavesPerStruct*nstructs*signatureSize;
+    posteriors.reserve(psz);
+    _posteriors >> posteriors;
+}
+
+
+void FernClassifier::clear()
+{
+    signatureSize = nclasses = nstructs = structSize = compressionMethod = leavesPerStruct = 0;
+    verbose = false;
+    features.release();
+    posteriors.release();
+}
+
+
+int FernClassifier::getLeaf(int fern, const Mat& _patch) const
+{
+    assert( 0 <= fern && fern < nstructs );
+    size_t fofs = fern*structSize, idx = 0;
+    const Mat_<uchar>& patch = (const Mat_<uchar>&)_patch;
+    
+    for( int i = 0; i < structSize; i++ )
+    {
+        const Feature& f = features[fofs + i];
+        idx = (idx << 1) + f(patch);
+    }
+    
+    return fern*leavesPerStruct + idx;
+}
+
+
+void FernClassifier::prepare(int _nclasses, int _patchSize, int _signatureSize,
+                             int _nstructs, int _structSize,
+                             int _nviews, int _compressionMethod)
+{
+    clear();
+    
+    CV_Assert( _nclasses > 1 && _patchSize >= 5 && _nstructs > 0 &&
+              _nviews > 0 && _structSize > 0 &&
+              (_compressionMethod == COMPRESSION_NONE ||
+               _compressionMethod == COMPRESSION_RANDOM_PROJ ||
+               _compressionMethod == COMPRESSION_PCA) );
+    
+    nclasses = _nclasses;
+    patchSize = Size(_patchSize, _patchSize);
+    nstructs = _nstructs;
+    structSize = _structSize;
+    signatureSize = std::min(_signatureSize, nclasses);
+    compressionMethod = signatureSize == nclasses ? COMPRESSION_NONE : _compressionMethod;
+    
+    leavesPerStruct = 1 << structSize;
+    
+    int i, nfeatures = structSize*nstructs;
+    
+    features = Vector<Feature>( nfeatures );
+    posteriors = Vector<float>( leavesPerStruct*nstructs*nclasses, 1.f );
+    classCounters = Vector<int>( nclasses, leavesPerStruct );
+    
+    CV_Assert( patchSize.width <= 256 && patchSize.height <= 256 );
+    RNG& rng = theRNG();
+    
+    for( i = 0; i < nfeatures; i++ )
+    {
+        int x1 = (unsigned)rng % patchSize.width;
+        int y1 = (unsigned)rng % patchSize.height;
+        int x2 = (unsigned)rng % patchSize.width;
+        int y2 = (unsigned)rng % patchSize.height;
+        features[i] = Feature(x1, y1, x2, y2);
+    }
+}
+
+
+void FernClassifier::train(const Vector<Point2f>& points,
+                           const Vector<Ptr<Mat> >& refimgs,
+                           const Vector<int>& labels,
+                           int _nclasses, int _patchSize,
+                           int _signatureSize, int _nstructs,
+                           int _structSize, int _nviews, int _compressionMethod,
+                           const PatchGenerator& patchGenerator)
+{
+    _nclasses = _nclasses > 0 ? _nclasses : (int)points.size();
+    CV_Assert( labels.empty() || labels.size() == points.size() );
+    
+    prepare(_nclasses, _patchSize, _signatureSize, _nstructs,
+            _structSize, _nviews, _compressionMethod);
+    
+    // pass all the views of all the samples through the generated trees and accumulate
+    // the statistics (posterior probabilities) in leaves.
+    Mat patch;
+    int i, j, nsamples = (int)points.size();
+    RNG& rng = theRNG();
+    
+    for( i = 0; i < nsamples; i++ )
+    {
+        Point2f pt = points[i];
+        const Mat& src = *refimgs[i];
+        int classId = labels.empty() ? i : labels[i];
+        if( verbose && (i+1)*progressBarSize/nsamples != i*progressBarSize/nsamples )
+            putchar('.');
+        CV_Assert( 0 <= classId && classId < nclasses );
+        classCounters[classId] += _nviews; 
+        for( j = 0; j < _nviews; j++ )
+        {
+            patchGenerator(src, pt, patch, patchSize, rng);
+            for( int f = 0; f < nstructs; f++ )
+                posteriors[getLeaf(f, patch)*nclasses + classId]++;
+        }
+    }
+    if( verbose )
+        putchar('\n');
+    
+    finalize(rng);
+}
+
+
+void FernClassifier::trainFromSingleView(const Mat& image,
+                                         const Vector<Keypoint>& keypoints,
+                                         int _patchSize, int _signatureSize,
+                                         int _nstructs, int _structSize,
+                                         int _nviews, int _compressionMethod,
+                                         const PatchGenerator& patchGenerator)
+{
+    prepare((int)keypoints.size(), _patchSize, _signatureSize, _nstructs,
+            _structSize, _nviews, _compressionMethod);
+    int i, j, k, nsamples = (int)keypoints.size(), maxOctave = 0;
+    for( i = 0; i < nsamples; i++ )
+    {
+        classCounters[i] = _nviews;
+        maxOctave = std::max(maxOctave, keypoints[i].octave);
+    }
+    
+    double maxScale = patchGenerator.lambdaMax*2;
+    Mat canvas(cvRound(std::max(image.cols,image.rows)*maxScale + patchSize.width*2 + 10),
+               cvRound(std::max(image.cols,image.rows)*maxScale + patchSize.width*2 + 10), image.type());
+    Mat noisebuf;
+    Vector<Mat> pyrbuf(maxOctave+1), pyr(maxOctave+1);
+    Point2f center0((image.cols-1)*0.5f, (image.rows-1)*0.5f),
+    center1((canvas.cols - 1)*0.5f, (canvas.rows - 1)*0.5f);
+    Mat _M(2, 3, CV_64F);
+    double *M = (double*)_M.data;
+    RNG& rng = theRNG();
+    
+    Mat patch(patchSize, CV_8U);
+    
+    for( i = 0; i < _nviews; i++ )
+    {
+        patchGenerator.generateRandomTransform(center0, center1, _M, rng);
+        
+        CV_Assert(_M.type() == CV_64F);
+        Rect roi(INT_MAX, INT_MAX, INT_MIN, INT_MIN);
+        
+        for( k = 0; k < 4; k++ )
+        {
+            Point2f pt0, pt1;
+            pt0.x = (float)(k == 0 || k == 3 ? 0 : image.cols);
+            pt0.y = (float)(k < 2 ? 0 : image.rows);
+            pt1.x = M[0]*pt0.x + M[1]*pt0.y + M[2];
+            pt1.y = M[3]*pt0.x + M[4]*pt0.y + M[5];
+            
+            roi.x = std::min(roi.x, cvFloor(pt1.x));
+            roi.y = std::min(roi.y, cvFloor(pt1.y));
+            roi.width = std::max(roi.width, cvCeil(pt1.x));
+            roi.height = std::max(roi.height, cvCeil(pt1.y));
+        }
+        
+        roi.width -= roi.x + 1;
+        roi.height -= roi.y + 1;
+        
+        Mat canvas_roi(canvas, roi);
+        M[2] -= roi.x;
+        M[5] -= roi.y;
+        
+        Size size = canvas_roi.size();
+        rng.fill(canvas_roi, RNG::UNIFORM, Scalar::all(0), Scalar::all(256));
+        warpAffine( image, canvas_roi, _M, size, INTER_LINEAR, BORDER_TRANSPARENT);
+        
+        pyr[0] = canvas_roi;                
+        for( j = 1; j <= maxOctave; j++ )
+        {
+            size = Size((size.width+1)/2, (size.height+1)/2);
+            if( pyrbuf[j].cols < size.width*size.height )
+                pyrbuf[j].create(1, size.width*size.height, image.type());
+            pyr[j] = Mat(size, image.type(), pyrbuf[j].data);
+            pyrDown(pyr[j-1], pyr[j]);
+        }
+        
+        if( patchGenerator.noiseRange > 0 )
+        {
+            const int noiseDelta = 128;
+            if( noisebuf.cols < pyr[0].cols*pyr[0].rows )
+                noisebuf.create(1, pyr[0].cols*pyr[0].rows, image.type());
+            for( j = 0; j <= maxOctave; j++ )
+            {
+                Mat noise(pyr[j].size(), image.type(), noisebuf.data);
+                rng.fill(noise, RNG::UNIFORM, Scalar::all(-patchGenerator.noiseRange + noiseDelta),
+                         Scalar::all(patchGenerator.noiseRange + noiseDelta));
+                addWeighted(pyr[j], 1, noise, 1, -noiseDelta, pyr[j]);
+            }
+        }
+        
+        for( j = 0; j < nsamples; j++ )
+        {
+            Keypoint kpt = keypoints[j];
+            float scale = 1.f/(1 << kpt.octave);
+            Point2f pt((M[0]*kpt.pt.x + M[1]*kpt.pt.y + M[2])*scale,
+                       (M[3]*kpt.pt.x + M[4]*kpt.pt.y + M[5])*scale);
+            getRectSubPix(pyr[kpt.octave], patchSize, pt, patch, patch.type());
+            for( int f = 0; f < nstructs; f++ )
+                posteriors[getLeaf(f, patch)*nclasses + j]++;
+        }
+        
+        if( verbose && (i+1)*progressBarSize/_nviews != i*progressBarSize/_nviews )
+            putchar('.');
+    }
+    if( verbose )
+        putchar('\n');
+    
+    finalize(rng);
+}
+
+
+int FernClassifier::operator()(const Mat& img, Point2f pt, Vector<float>& signature) const
+{
+    Mat patch;
+    getRectSubPix(img, patchSize, pt, patch, img.type());
+    return (*this)(patch, signature);
+}
+
+
+int FernClassifier::operator()(const Mat& patch, Vector<float>& signature) const
+{
+    if( posteriors.empty() )
+        CV_Error(CV_StsNullPtr,
+                 "The descriptor has not been trained or "
+                 "the floating-point posteriors have been deleted");
+    CV_Assert(patch.size() == patchSize);
+    
+    int i, j, sz = signatureSize;
+    signature.resize(sz);
+    float* s = &signature[0];
+    
+    for( j = 0; j < sz; j++ )
+        s[j] = 0;
+    
+    for( i = 0; i < nstructs; i++ )
+    {
+        int lf = getLeaf(i, patch);
+        const float* ldata = &posteriors[lf*signatureSize];
+        for( j = 0; j <= sz - 4; j += 4 )
+        {
+            float t0 = s[j] + ldata[j];
+            float t1 = s[j+1] + ldata[j+1];
+            s[j] = t0; s[j+1] = t1;
+            t0 = s[j+2] + ldata[j+2];
+            t1 = s[j+3] + ldata[j+3];
+            s[j+2] = t0; s[j+3] = t1;
+        }
+        for( ; j < sz; j++ )
+            s[j] += ldata[j];
+    }
+    
+    j = 0;
+    if( signatureSize == nclasses && compressionMethod == COMPRESSION_NONE )
+    {
+        for( i = 1; i < nclasses; i++ )
+            if( s[j] < s[i] )
+                j = i;
+    }
+    return j;
+}
+
+
+void FernClassifier::finalize(RNG& rng)
+{
+    int i, j, k, n = nclasses;
+    Vector<double> invClassCounters(n);
+    Mat_<double> _temp(1, n);
+    double* temp = &_temp(0,0);
+    
+    for( i = 0; i < n; i++ )
+        invClassCounters[i] = 1./classCounters[i];
+    
+    for( i = 0; i < nstructs; i++ )
+    {
+        for( j = 0; j < leavesPerStruct; j++ )
+        {
+            float* P = &posteriors[(i*leavesPerStruct + j)*nclasses];
+            double sum = 0;
+            for( k = 0; k < n; k++ )
+                sum += P[k]*invClassCounters[k];
+            sum = 1./sum;
+            for( k = 0; k < n; k++ )
+                temp[k] = P[k]*invClassCounters[k]*sum;
+            log(_temp, _temp);
+            for( k = 0; k < n; k++ )
+                P[k] = (float)temp[k];
+        }
+    }
+    
+#if 0    
+    // do the first pass over the data.
+    if( compressionMethod == COMPRESSION_RANDOM_PROJ )
+    {
+        // In case of random projection
+        // we generate a random m x n matrix consisting of -1's and 1's
+        // (called Bernoulli matrix) and multiply it by each vector
+        // of posterior probabilities.
+        // the product is stored back into the same input vector.
+        
+        Mat_<uchar> csmatrix;
+        if( m < n )
+        {
+            // generate random Bernoulli matrix:
+            //   -1's are replaced with 0's and 1's stay 1's.
+            csmatrix.create(m, n);
+            rng.fill(csmatrix, RNG::UNIFORM, Scalar::all(0), Scalar::all(2));
+        }
+        Vector<float> dst(m);
+        
+        for( i = 0; i < totalLeaves; i++ )
+        {
+            int S = sampleCounters[i];
+            if( S == 0 )
+                continue;
+            
+            float scale = 1.f/(S*(m < n ? std::sqrt((float)m) : 1.f));
+            const int* leaf = (const int*)&posteriors[i*n];
+            float* out_leaf = (float*)&posteriors[i*m];
+            
+            for( j = 0; j < m; j++ )
+            {
+                float val = 0;
+                if( m < n )
+                {
+                    const uchar* csrow = csmatrix.ptr(j);
+                    // Because -1's in the Bernoulli matrix are encoded as 0's,
+                    // the real dot product value will be
+                    // A - B, where A is the sum of leaf[j]'s for which csrow[j]==1 and
+                    // B is the sum of leaf[j]'s for which csrow[j]==0.
+                    // since A + B = S, then A - B = A - (S - A) = 2*A - S.
+                    int A = 0;
+                    for( k = 0; k < n; k++ )
+                        A += leaf[k] & -(int)csrow[k];
+                    val = (A*2 - S)*scale;
+                }
+                else
+                    val = leaf[j]*scale;
+                dst[j] = val;
+            }
+            
+            // put the vector back (since it's shorter than the original, we can do it in-place)
+            for( j = 0; j < m; j++ )
+                out_leaf[j] = dst[j];
+        }
+    }
+    else if( compressionMethod == COMPRESSION_PCA )
+    {
+        // In case of PCA we do 3 passes over the data:
+        //   first, we compute the mean vector
+        //   second, we compute the covariation matrix
+        //     then we do eigen decomposition of the matrix and construct the PCA
+        //     projection matrix
+        //   and on the third pass we actually do PCA compression.
+        
+        int nonEmptyLeaves = 0;
+        Mat_<double> _mean(1, n), _vec(1, n), _dvec(m, 1),
+        _cov(n, n), _evals(n, 1), _evects(n, n);
+        _mean = 0.;
+        double* mean = &_mean(0,0);
+        double* vec = &_vec(0,0);
+        double* dvec = &_dvec(0,0);
+        
+        for( i = 0; i < totalLeaves; i++ )
+        {
+            int S = sampleCounters[i];
+            if( S == 0 )
+                continue;
+            float invS = 1.f/S;
+            const int* leaf = (const int*)&posteriors[0] + i*n;
+            float* out_leaf = (float*)&posteriors[0] + i*n;
+            
+            for( j = 0; j < n; j++ )
+            {
+                float t = leaf[j]*invS;
+                out_leaf[j] = t;
+                mean[j] += t;
+            }
+            nonEmptyLeaves++;
+        }
+        
+        CV_Assert( nonEmptyLeaves >= ntrees );
+        _mean *= 1./nonEmptyLeaves;
+        
+        for( i = 0; i < totalLeaves; i++ )
+        {
+            int S = sampleCounters[i];
+            if( S == 0 )
+                continue;
+            const float* leaf = (const float*)&posteriors[0] + i*n;
+            for( j = 0; j < n; j++ )
+                vec[j] = leaf[j] - mean[j];
+            gemm(_vec, _vec, 1, _cov, 1, _cov, GEMM_1_T);
+        }
+        
+        _cov *= 1./nonEmptyLeaves;
+        eigen(_cov, _evals, _evects);
+        // use the first m eigenvectors (stored as rows of the eigenvector matrix)
+        // as the projection matrix in PCA
+        _evects = _evects(Range(0, m), Range::all());
+        
+        for( i = 0; i < totalLeaves; i++ )
+        {
+            int S = sampleCounters[i];
+            if( S == 0 )
+                continue;
+            const float* leaf = (const float*)&posteriors[0] + i*n;
+            float* out_leaf = (float*)&posteriors[0] + i*m;
+            
+            for( j = 0; j < n; j++ )
+                vec[j] = leaf[j] - mean[j];
+            gemm(_evects, _vec, 1, Mat(), 0, _dvec, GEMM_2_T);
+            
+            for( j = 0; j < m; j++ )
+                out_leaf[j] = (float)dvec[j];
+        }
+    }
+    else
+        CV_Error( CV_StsBadArg,
+                 "Unknown compression method; use COMPRESSION_RANDOM_PROJ or COMPRESSION_PCA" );
+    
+    // and shrink the vector
+    posteriors.resize(totalLeaves*m);
+#endif
+}
+
+void FernClassifier::setVerbose(bool _verbose)
+{
+    verbose = _verbose;
+}    
+
+////////////////////////////////////// Planar Object Detector ////////////////////////////////////
+
+PlanarObjectDetector::PlanarObjectDetector()
+{
+}
+
+PlanarObjectDetector::PlanarObjectDetector(const FileNode& node)
+{
+    read(node);    
+}
+
+PlanarObjectDetector::PlanarObjectDetector(const Vector<Mat>& pyr, int npoints,
+                                           int patchSize, int nstructs, int structSize,
+                                           int nviews, const LDetector& detector,
+                                           const PatchGenerator& patchGenerator)
+{
+    train(pyr, npoints, patchSize, nstructs,
+          structSize, nviews, detector, patchGenerator);
+}
+
+PlanarObjectDetector::~PlanarObjectDetector()
+{
+}    
+
+Vector<Keypoint> PlanarObjectDetector::getModelPoints() const
+{
+    return modelPoints;
+}   
+
+void PlanarObjectDetector::train(const Vector<Mat>& pyr, int npoints,
+                                 int patchSize, int nstructs, int structSize,
+                                 int nviews, const LDetector& detector,
+                                 const PatchGenerator& patchGenerator)
+{
+    modelROI = Rect(0, 0, pyr[0].cols, pyr[0].rows);
+    ldetector = detector;
+    ldetector.setVerbose(verbose);
+    ldetector.getMostStable2D(pyr[0], modelPoints, npoints, patchGenerator);
+    
+    npoints = modelPoints.size();
+    fernClassifier.setVerbose(verbose);
+    fernClassifier.trainFromSingleView(pyr[0], modelPoints, 
+                                       patchSize, (int)modelPoints.size(), nstructs, structSize, nviews,
+                                       FernClassifier::COMPRESSION_NONE, patchGenerator);
+}
+
+void PlanarObjectDetector::train(const Vector<Mat>& pyr, const Vector<Keypoint>& keypoints,
+                                 int patchSize, int nstructs, int structSize,
+                                 int nviews, const LDetector& detector,
+                                 const PatchGenerator& patchGenerator)
+{
+    modelROI = Rect(0, 0, pyr[0].cols, pyr[0].rows);
+    ldetector = detector;
+    modelPoints = keypoints.clone();
+    
+    fernClassifier.setVerbose(verbose);
+    fernClassifier.trainFromSingleView(pyr[0], modelPoints, 
+                                       patchSize, (int)modelPoints.size(), nstructs, structSize, nviews,
+                                       FernClassifier::COMPRESSION_NONE, patchGenerator);
+}    
+
+void PlanarObjectDetector::read(const FileNode& node)
+{
+    FileNodeIterator it = node["model-roi"].begin(), it_end;
+    it >> modelROI.x >> modelROI.y >> modelROI.width >> modelROI.height;
+    ldetector.read(node["detector"]);
+    fernClassifier.read(node["fern-classifier"]);
+    cv::read(node["model-points"], modelPoints);
+    CV_Assert(modelPoints.size() == (size_t)fernClassifier.getClassCount());
+}
+
+
+void PlanarObjectDetector::write(FileStorage& fs, const String& objname) const
+{
+    WriteStructContext ws(fs, objname, CV_NODE_MAP);
+    
+    {
+        WriteStructContext wsroi(fs, "model-roi", CV_NODE_SEQ + CV_NODE_FLOW);
+        cv::write(fs, modelROI.x);
+        cv::write(fs, modelROI.y);
+        cv::write(fs, modelROI.width);
+        cv::write(fs, modelROI.height);
+    }
+    ldetector.write(fs, "detector");
+    cv::write(fs, "model-points", modelPoints);
+    fernClassifier.write(fs, "fern-classifier");
+}
+
+
+bool PlanarObjectDetector::operator()(const Mat& image, Mat& H, Vector<Point2f>& corners) const
+{
+    Vector<Mat> pyr;
+    buildPyramid(image, pyr, ldetector.nOctaves - 1);
+    Vector<Keypoint> keypoints;
+    ldetector(pyr, keypoints);
+    
+    return (*this)(pyr, keypoints, H, corners);
+}
+
+bool PlanarObjectDetector::operator()(const Vector<Mat>& pyr, const Vector<Keypoint>& keypoints,
+                                      Mat& _H, Vector<Point2f>& corners, Vector<int>* pairs) const
+{
+    int i, j, m = (int)modelPoints.size(), n = (int)keypoints.size();
+    Vector<int> bestMatches(m, -1);
+    Vector<float> maxLogProb(m, -FLT_MAX);
+    Vector<float> signature;
+    Vector<Point2f> fromPt, toPt;
+    
+    for( i = 0; i < n; i++ )
+    {
+        Keypoint kpt = keypoints[i];
+        CV_Assert(0 <= kpt.octave && kpt.octave < (int)pyr.size());
+        kpt.pt.x /= (float)(1 << kpt.octave);
+        kpt.pt.y /= (float)(1 << kpt.octave);
+        int k = fernClassifier(pyr[kpt.octave], kpt.pt, signature);
+        if( k >= 0 && (bestMatches[k] < 0 || signature[k] > maxLogProb[k]) )
+        {
+            maxLogProb[k] = signature[k];
+            bestMatches[k] = i;
+        }
+    }
+    
+    if(pairs)
+        pairs->resize(0);
+    
+    for( i = 0; i < m; i++ )
+        if( bestMatches[i] >= 0 )
+        {
+            fromPt.push_back(modelPoints[i].pt);
+            toPt.push_back(keypoints[bestMatches[i]].pt);
+        }
+    
+    if( fromPt.size() < 4 )
+        return false;
+    
+    Vector<bool> mask;
+    _H = findHomography(fromPt, toPt, mask, RANSAC, 10);
+    if( _H.data )
+    {
+        const Mat_<double>& H = _H;
+        corners.resize(4);
+        for( i = 0; i < 4; i++ )
+        {
+            Point2f pt(modelROI.x + (i == 0 || i == 3 ? 0 : modelROI.width),
+                       modelROI.y + (i <= 1 ? 0 : modelROI.height));
+            float w = 1./(H(2,0)*pt.x + H(2,1)*pt.y + H(2,2));
+            corners[i] = Point2f((H(0,0)*pt.x + H(0,1)*pt.y + H(0,2))*w,
+                                 (H(1,0)*pt.x + H(1,1)*pt.y + H(1,2))*w);
+        }
+    }
+    
+    for( i = j = 0; i < m; i++ )
+        if( bestMatches[i] >= 0 && mask[j++] )
+        {
+            pairs->push_back(i);
+            pairs->push_back(bestMatches[i]);
+        }
+    
+    
+    return _H.data != 0;
+}
+
+
+void PlanarObjectDetector::setVerbose(bool _verbose)
+{
+    verbose = _verbose;
+}           
+        
+}
index a007dee2ed9f6796177d125f5e0b3395c8c75bf1..f5d3164e876b4142efbbd95c1a9977f13dd93ec6 100644 (file)
-/*M///////////////////////////////////////////////////////////////////////////////////////\r
-//\r
-//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.\r
-//\r
-//  By downloading, copying, installing or using the software you agree to this license.\r
-//  If you do not agree to this license, do not download, install,\r
-//  copy or use the software.\r
-//\r
-//\r
-//                           License Agreement\r
-//                For Open Source Computer Vision Library\r
-//\r
-// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.\r
-// Copyright (C) 2009, Willow Garage Inc., all rights reserved.\r
-// Third party copyrights are property of their respective owners.\r
-//\r
-// Redistribution and use in source and binary forms, with or without modification,\r
-// are permitted provided that the following conditions are met:\r
-//\r
-//   * Redistribution's of source code must retain the above copyright notice,\r
-//     this list of conditions and the following disclaimer.\r
-//\r
-//   * Redistribution's in binary form must reproduce the above copyright notice,\r
-//     this list of conditions and the following disclaimer in the documentation\r
-//     and/or other materials provided with the distribution.\r
-//\r
-//   * The name of the copyright holders may not be used to endorse or promote products\r
-//     derived from this software without specific prior written permission.\r
-//\r
-// This software is provided by the copyright holders and contributors "as is" and\r
-// any express or implied warranties, including, but not limited to, the implied\r
-// warranties of merchantability and fitness for a particular purpose are disclaimed.\r
-// In no event shall the Intel Corporation or contributors be liable for any direct,\r
-// indirect, incidental, special, exemplary, or consequential damages\r
-// (including, but not limited to, procurement of substitute goods or services;\r
-// loss of use, data, or profits; or business interruption) however caused\r
-// and on any theory of liability, whether in contract, strict liability,\r
-// or tort (including negligence or otherwise) arising in any way out of\r
-// the use of this software, even if advised of the possibility of such damage.\r
-//\r
-//M*/\r
-\r
-#include "_cxcore.h"\r
-#include <ctype.h>\r
-#include <wchar.h>\r
-\r
-/****************************************************************************************\\r
-*                            Common macros and type definitions                          *\r
-\****************************************************************************************/\r
-\r
-#define cv_isprint(c)     ((signed char)(c) >= (signed char)' ')\r
-#define cv_isprint_or_tab(c)  ((signed char)(c) >= (signed char)' ' || (c) == '\t')\r
-\r
-static char* icv_itoa( int _val, char* buffer, int /*radix*/ )\r
-{\r
-    const int radix = 10;\r
-    char* ptr=buffer + 23 /* enough even for 64-bit integers */;\r
-    unsigned val = abs(_val);\r
-\r
-    *ptr = '\0';\r
-    do\r
-    {\r
-        unsigned r = val / radix;\r
-        *--ptr = (char)(val - (r*radix) + '0');\r
-        val = r;\r
-    }\r
-    while( val != 0 );\r
-\r
-    if( _val < 0 )\r
-        *--ptr = '-';\r
-\r
-    return ptr;\r
-}\r
-\r
-cv::String cv::FileStorage::getDefaultObjectName(const String& _filename)\r
-{\r
-    static const char* stubname = "unnamed";\r
-    const char* filename = _filename.c_str();\r
-    const char* ptr2 = filename + _filename.size();\r
-    const char* ptr = ptr2 - 1;\r
-    cv::AutoBuffer<char> name_buf(_filename.size()+1);\r
-\r
-    while( ptr >= filename && *ptr != '\\' && *ptr != '/' && *ptr != ':' )\r
-    {\r
-        if( *ptr == '.' && !*ptr2 )\r
-            ptr2 = ptr;\r
-        ptr--;\r
-    }\r
-    ptr++;\r
-    if( ptr == ptr2 )\r
-        CV_Error( CV_StsBadArg, "Invalid filename" );\r
-\r
-    char* name = name_buf;\r
-\r
-    // name must start with letter or '_'\r
-    if( !isalpha(*ptr) && *ptr!= '_' ){\r
-        *name++ = '_';\r
-    }\r
-\r
-    while( ptr < ptr2 )\r
-    {\r
-        char c = *ptr++;\r
-        if( !isalnum(c) && c != '-' && c != '_' )\r
-            c = '_';\r
-        *name++ = c;\r
-    }\r
-    *name = '\0';\r
-    name = name_buf;\r
-    if( strcmp( name, "_" ) == 0 )\r
-        strcpy( name, stubname );\r
-    return cv::String(name);\r
-}\r
-\r
-namespace cv\r
-{\r
-\r
-String fromUtf16(const WString& str)\r
-{\r
-    cv::AutoBuffer<char> _buf(str.size()*4 + 1);\r
-    char* buf = _buf;\r
-        \r
-    size_t sz = wcstombs(buf, str.c_str(), str.size());\r
-    if( sz == (size_t)-1 )\r
-        return String();\r
-    buf[sz] = '\0';\r
-    return String(buf);\r
-}\r
-\r
-WString toUtf16(const String& str)\r
-{\r
-    cv::AutoBuffer<wchar_t> _buf(str.size() + 1);\r
-    wchar_t* buf = _buf;\r
-        \r
-    size_t sz = mbstowcs(buf, str.c_str(), str.size());\r
-    if( sz == (size_t)-1 )\r
-        return WString();\r
-    buf[sz] = '\0';\r
-    return WString(buf);\r
-}\r
-\r
-}\r
-\r
-typedef struct CvGenericHash\r
-{\r
-    CV_SET_FIELDS()\r
-    int tab_size;\r
-    void** table;\r
-}\r
-CvGenericHash;\r
-\r
-typedef CvGenericHash CvStringHash;\r
-\r
-typedef struct CvFileMapNode\r
-{\r
-    CvFileNode value;\r
-    const CvStringHashNode* key;\r
-    struct CvFileMapNode* next;\r
-}\r
-CvFileMapNode;\r
-\r
-typedef struct CvXMLStackRecord\r
-{\r
-    CvMemStoragePos pos;\r
-    CvString struct_tag;\r
-    int struct_indent;\r
-    int struct_flags;\r
-}\r
-CvXMLStackRecord;\r
-\r
-#define CV_XML_OPENING_TAG 1\r
-#define CV_XML_CLOSING_TAG 2\r
-#define CV_XML_EMPTY_TAG 3\r
-#define CV_XML_HEADER_TAG 4\r
-#define CV_XML_DIRECTIVE_TAG 5\r
-\r
-//typedef void (*CvParse)( struct CvFileStorage* fs );\r
-typedef void (*CvStartWriteStruct)( struct CvFileStorage* fs, const char* key,\r
-                                    int struct_flags, const char* type_name );\r
-typedef void (*CvEndWriteStruct)( struct CvFileStorage* fs );\r
-typedef void (*CvWriteInt)( struct CvFileStorage* fs, const char* key, int value );\r
-typedef void (*CvWriteReal)( struct CvFileStorage* fs, const char* key, double value );\r
-typedef void (*CvWriteString)( struct CvFileStorage* fs, const char* key,\r
-                               const char* value, int quote );\r
-typedef void (*CvWriteComment)( struct CvFileStorage* fs, const char* comment, int eol_comment );\r
-typedef void (*CvStartNextStream)( struct CvFileStorage* fs );\r
-\r
-typedef struct CvFileStorage\r
-{\r
-    int flags;\r
-    int is_xml;\r
-    int write_mode;\r
-    int is_first;\r
-    CvMemStorage* memstorage;\r
-    CvMemStorage* dststorage;\r
-    CvMemStorage* strstorage;\r
-    CvStringHash* str_hash;\r
-    CvSeq* roots;\r
-    CvSeq* write_stack;\r
-    int struct_indent;\r
-    int struct_flags;\r
-    CvString struct_tag;\r
-    int space;\r
-    char* filename;\r
-    FILE* file;\r
-    char* buffer;\r
-    char* buffer_start;\r
-    char* buffer_end;\r
-    int wrap_margin;\r
-    int lineno;\r
-    int dummy_eof;\r
-    const char* errmsg;\r
-    char errmsgbuf[128];\r
-\r
-    CvStartWriteStruct start_write_struct;\r
-    CvEndWriteStruct end_write_struct;\r
-    CvWriteInt write_int;\r
-    CvWriteReal write_real;\r
-    CvWriteString write_string;\r
-    CvWriteComment write_comment;\r
-    CvStartNextStream start_next_stream;\r
-    //CvParse parse;\r
-}\r
-CvFileStorage;\r
-\r
-\r
-#define CV_YML_INDENT  3\r
-#define CV_XML_INDENT  2\r
-#define CV_YML_INDENT_FLOW  1\r
-#define CV_FS_MAX_LEN 4096\r
-\r
-#define CV_FILE_STORAGE ('Y' + ('A' << 8) + ('M' << 16) + ('L' << 24))\r
-#define CV_IS_FILE_STORAGE(fs) ((fs) != 0 && (fs)->flags == CV_FILE_STORAGE)\r
-\r
-#define CV_CHECK_FILE_STORAGE(fs)                       \\r
-{                                                       \\r
-    if( !CV_IS_FILE_STORAGE(fs) )                       \\r
-        CV_Error( (fs) ? CV_StsBadArg : CV_StsNullPtr,  \\r
-                  "Invalid pointer to file storage" );  \\r
-}\r
-\r
-#define CV_CHECK_OUTPUT_FILE_STORAGE(fs)                \\r
-{                                                       \\r
-    CV_CHECK_FILE_STORAGE(fs);                          \\r
-    if( !fs->write_mode )                               \\r
-        CV_Error( CV_StsError, "The file storage is opened for reading" ); \\r
-}\r
-\r
-CV_IMPL const char*\r
-cvAttrValue( const CvAttrList* attr, const char* attr_name )\r
-{\r
-    while( attr && attr->attr )\r
-    {\r
-        int i;\r
-        for( i = 0; attr->attr[i*2] != 0; i++ )\r
-        {\r
-            if( strcmp( attr_name, attr->attr[i*2] ) == 0 )\r
-                return attr->attr[i*2+1];\r
-        }\r
-        attr = attr->next;\r
-    }\r
-\r
-    return 0;\r
-}\r
-\r
-\r
-static CvGenericHash*\r
-cvCreateMap( int flags, int header_size, int elem_size,\r
-             CvMemStorage* storage, int start_tab_size )\r
-{\r
-    if( header_size < (int)sizeof(CvGenericHash) )\r
-        CV_Error( CV_StsBadSize, "Too small map header_size" );\r
-\r
-    if( start_tab_size <= 0 )\r
-        start_tab_size = 16;\r
-\r
-    CvGenericHash* map = (CvGenericHash*)cvCreateSet( flags, header_size, elem_size, storage );\r
-\r
-    map->tab_size = start_tab_size;\r
-    start_tab_size *= sizeof(map->table[0]);\r
-    map->table = (void**)cvMemStorageAlloc( storage, start_tab_size );\r
-    memset( map->table, 0, start_tab_size );\r
-\r
-    return map;\r
-}\r
-\r
-#ifdef __GNUC__\r
-#define CV_PARSE_ERROR( errmsg )                                    \\r
-    icvParseError( fs, __func__, (errmsg), __FILE__, __LINE__ )\r
-#else\r
-#define CV_PARSE_ERROR( errmsg )                                    \\r
-    icvParseError( fs, "", (errmsg), __FILE__, __LINE__ )\r
-#endif\r
-\r
-static void\r
-icvParseError( CvFileStorage* fs, const char* func_name,\r
-               const char* err_msg, const char* source_file, int source_line )\r
-{\r
-    char buf[1<<10];\r
-    sprintf( buf, "%s(%d): %s", fs->filename, fs->lineno, err_msg );\r
-    cvError( CV_StsParseError, func_name, buf, source_file, source_line );\r
-}\r
-\r
-\r
-static void\r
-icvFSCreateCollection( CvFileStorage* fs, int tag, CvFileNode* collection )\r
-{\r
-    if( CV_NODE_IS_MAP(tag) )\r
-    {\r
-        if( collection->tag != CV_NODE_NONE )\r
-        {\r
-            assert( fs->is_xml != 0 );\r
-            CV_PARSE_ERROR( "Sequence element should not have name (use <_></_>)" );\r
-        }\r
-\r
-        collection->data.map = cvCreateMap( 0, sizeof(CvFileNodeHash),\r
-                            sizeof(CvFileMapNode), fs->memstorage, 16 );\r
-    }\r
-    else\r
-    {\r
-        CvSeq* seq;\r
-        seq = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvFileNode), fs->memstorage );\r
-\r
-        // if <collection> contains some scalar element, add it to the newly created collection\r
-        if( CV_NODE_TYPE(collection->tag) != CV_NODE_NONE )\r
-            cvSeqPush( seq, collection );\r
-\r
-        collection->data.seq = seq;\r
-    }\r
-\r
-    collection->tag = tag;\r
-    cvSetSeqBlockSize( collection->data.seq, 8 );\r
-}\r
-\r
-\r
-/*static void\r
-icvFSReleaseCollection( CvSeq* seq )\r
-{\r
-    if( seq )\r
-    {\r
-        int is_map = CV_IS_SET(seq);\r
-        CvSeqReader reader;\r
-        int i, total = seq->total;\r
-        cvStartReadSeq( seq, &reader, 0 );\r
-\r
-        for( i = 0; i < total; i++ )\r
-        {\r
-            CvFileNode* node = (CvFileNode*)reader.ptr;\r
-\r
-            if( (!is_map || CV_IS_SET_ELEM( node )) && CV_NODE_IS_COLLECTION(node->tag) )\r
-            {\r
-                if( CV_NODE_IS_USER(node->tag) && node->info && node->data.obj.decoded )\r
-                    cvRelease( (void**)&node->data.obj.decoded );\r
-                if( !CV_NODE_SEQ_IS_SIMPLE( node->data.seq ))\r
-                    icvFSReleaseCollection( node->data.seq );\r
-            }\r
-            CV_NEXT_SEQ_ELEM( seq->elem_size, reader );\r
-        }\r
-    }\r
-}*/\r
-\r
-\r
-static char*\r
-icvFSDoResize( CvFileStorage* fs, char* ptr, int len )\r
-{\r
-    char* new_ptr = 0;\r
-    int written_len = (int)(ptr - fs->buffer_start);\r
-    int new_size = (int)((fs->buffer_end - fs->buffer_start)*3/2);\r
-    new_size = MAX( written_len + len, new_size );\r
-    new_ptr = (char*)cvAlloc( new_size + 256 );\r
-    fs->buffer = new_ptr + (fs->buffer - fs->buffer_start);\r
-    if( written_len > 0 )\r
-        memcpy( new_ptr, fs->buffer_start, written_len );\r
-    fs->buffer_start = new_ptr;\r
-    fs->buffer_end = fs->buffer_start + new_size;\r
-    new_ptr += written_len;\r
-    return new_ptr;\r
-}\r
-\r
-\r
-inline char* icvFSResizeWriteBuffer( CvFileStorage* fs, char* ptr, int len )\r
-{\r
-    return ptr + len < fs->buffer_end ? ptr : icvFSDoResize( fs, ptr, len );\r
-}\r
-\r
-\r
-static char*\r
-icvFSFlush( CvFileStorage* fs )\r
-{\r
-    char* ptr = fs->buffer;\r
-    int indent;\r
-\r
-    if( ptr > fs->buffer_start + fs->space )\r
-    {\r
-        ptr[0] = '\n';\r
-        ptr[1] = '\0';\r
-        fputs( fs->buffer_start, fs->file );\r
-        fs->buffer = fs->buffer_start;\r
-    }\r
-\r
-    indent = fs->struct_indent;\r
-\r
-    if( fs->space != indent )\r
-    {\r
-        if( fs->space < indent )\r
-            memset( fs->buffer_start + fs->space, ' ', indent - fs->space );\r
-        fs->space = indent;\r
-    }\r
-\r
-    ptr = fs->buffer = fs->buffer_start + fs->space;\r
-\r
-    return ptr;\r
-}\r
-\r
-\r
-/* closes file storage and deallocates buffers */\r
-CV_IMPL  void\r
-cvReleaseFileStorage( CvFileStorage** p_fs )\r
-{\r
-    if( !p_fs )\r
-        CV_Error( CV_StsNullPtr, "NULL double pointer to file storage" );\r
-\r
-    if( *p_fs )\r
-    {\r
-        CvFileStorage* fs = *p_fs;\r
-        *p_fs = 0;\r
-\r
-        if( fs->write_mode && fs->file )\r
-        {\r
-            if( fs->write_stack )\r
-            {\r
-                while( fs->write_stack->total > 0 )\r
-                    cvEndWriteStruct(fs);\r
-            }\r
-            icvFSFlush(fs);\r
-            if( fs->is_xml )\r
-                fputs("</opencv_storage>\n", fs->file );\r
-        }\r
-\r
-        //icvFSReleaseCollection( fs->roots ); // delete all the user types recursively\r
-\r
-        if( fs->file )\r
-        {\r
-            fclose( fs->file );\r
-            fs->file = 0;\r
-        }\r
-\r
-        cvReleaseMemStorage( &fs->strstorage );\r
-\r
-        cvFree( &fs->buffer_start );\r
-        cvReleaseMemStorage( &fs->memstorage );\r
-\r
-        memset( fs, 0, sizeof(*fs) );\r
-        cvFree( &fs );\r
-    }\r
-}\r
-\r
-\r
-#define CV_HASHVAL_SCALE 33\r
-\r
-CV_IMPL CvStringHashNode*\r
-cvGetHashedKey( CvFileStorage* fs, const char* str, int len, int create_missing )\r
-{\r
-    CvStringHashNode* node = 0;\r
-    unsigned hashval = 0;\r
-    int i, tab_size;\r
-    CvStringHash* map = fs->str_hash;\r
-\r
-    if( !fs )\r
-        return 0;\r
-\r
-    if( len < 0 )\r
-    {\r
-        for( i = 0; str[i] != '\0'; i++ )\r
-            hashval = hashval*CV_HASHVAL_SCALE + (unsigned char)str[i];\r
-        len = i;\r
-    }\r
-    else for( i = 0; i < len; i++ )\r
-        hashval = hashval*CV_HASHVAL_SCALE + (unsigned char)str[i];\r
-\r
-    hashval &= INT_MAX;\r
-    tab_size = map->tab_size;\r
-    if( (tab_size & (tab_size - 1)) == 0 )\r
-        i = (int)(hashval & (tab_size - 1));\r
-    else\r
-        i = (int)(hashval % tab_size);\r
-\r
-    for( node = (CvStringHashNode*)(map->table[i]); node != 0; node = node->next )\r
-    {\r
-        if( node->hashval == hashval &&\r
-            node->str.len == len &&\r
-            memcmp( node->str.ptr, str, len ) == 0 )\r
-            break;\r
-    }\r
-\r
-    if( !node && create_missing )\r
-    {\r
-        node = (CvStringHashNode*)cvSetNew( (CvSet*)map );\r
-        node->hashval = hashval;\r
-        node->str = cvMemStorageAllocString( map->storage, str, len );\r
-        node->next = (CvStringHashNode*)(map->table[i]);\r
-        map->table[i] = node;\r
-    }\r
-\r
-    return node;\r
-}\r
-\r
-\r
-CV_IMPL CvFileNode*\r
-cvGetFileNode( CvFileStorage* fs, CvFileNode* _map_node,\r
-               const CvStringHashNode* key,\r
-               int create_missing )\r
-{\r
-    CvFileNode* value = 0;\r
-    int k = 0, attempts = 1;\r
-\r
-    if( !fs )\r
-        return 0;\r
-\r
-    CV_CHECK_FILE_STORAGE(fs);\r
-\r
-    if( !key )\r
-        CV_Error( CV_StsNullPtr, "Null key element" );\r
-\r
-    if( _map_node )\r
-    {\r
-        if( !fs->roots )\r
-            return 0;\r
-        attempts = fs->roots->total;\r
-    }\r
-\r
-    for( k = 0; k < attempts; k++ )\r
-    {\r
-        int i, tab_size;\r
-        CvFileNode* map_node = _map_node;\r
-        CvFileMapNode* another;\r
-        CvFileNodeHash* map;\r
-\r
-        if( !map_node )\r
-            map_node = (CvFileNode*)cvGetSeqElem( fs->roots, k );\r
-\r
-        if( !CV_NODE_IS_MAP(map_node->tag) )\r
-        {\r
-            if( (!CV_NODE_IS_SEQ(map_node->tag) || map_node->data.seq->total != 0) &&\r
-                CV_NODE_TYPE(map_node->tag) != CV_NODE_NONE )\r
-                CV_Error( CV_StsError, "The node is neither a map nor an empty collection" );\r
-            return 0;\r
-        }\r
-\r
-        map = map_node->data.map;\r
-        tab_size = map->tab_size;\r
-\r
-        if( (tab_size & (tab_size - 1)) == 0 )\r
-            i = (int)(key->hashval & (tab_size - 1));\r
-        else\r
-            i = (int)(key->hashval % tab_size);\r
-\r
-        for( another = (CvFileMapNode*)(map->table[i]); another != 0; another = another->next )\r
-            if( another->key == key )\r
-            {\r
-                if( !create_missing )\r
-                {\r
-                    value = &another->value;\r
-                    return value;\r
-                }\r
-                CV_PARSE_ERROR( "Duplicated key" );\r
-            }\r
-\r
-        if( k == attempts - 1 && create_missing )\r
-        {\r
-            CvFileMapNode* node = (CvFileMapNode*)cvSetNew( (CvSet*)map );\r
-            node->key = key;\r
-\r
-            node->next = (CvFileMapNode*)(map->table[i]);\r
-            map->table[i] = node;\r
-            value = (CvFileNode*)node;\r
-        }\r
-    }\r
-\r
-    return value;\r
-}\r
-\r
-\r
-CV_IMPL CvFileNode*\r
-cvGetFileNodeByName( const CvFileStorage* fs, const CvFileNode* _map_node, const char* str )\r
-{\r
-    CvFileNode* value = 0;\r
-    int i, len, tab_size;\r
-    unsigned hashval = 0;\r
-    int k = 0, attempts = 1;\r
-\r
-    if( !fs )\r
-        return 0;\r
-\r
-    CV_CHECK_FILE_STORAGE(fs);\r
-\r
-    if( !str )\r
-        CV_Error( CV_StsNullPtr, "Null element name" );\r
-\r
-    for( i = 0; str[i] != '\0'; i++ )\r
-        hashval = hashval*CV_HASHVAL_SCALE + (unsigned char)str[i];\r
-    hashval &= INT_MAX;\r
-    len = i;\r
-\r
-    if( !_map_node )\r
-    {\r
-        if( !fs->roots )\r
-            return 0;\r
-        attempts = fs->roots->total;\r
-    }\r
-\r
-    for( k = 0; k < attempts; k++ )\r
-    {\r
-        CvFileNodeHash* map;\r
-        const CvFileNode* map_node = _map_node;\r
-        CvFileMapNode* another;\r
-\r
-        if( !map_node )\r
-            map_node = (CvFileNode*)cvGetSeqElem( fs->roots, k );\r
-\r
-        if( !CV_NODE_IS_MAP(map_node->tag) )\r
-        {\r
-            if( (!CV_NODE_IS_SEQ(map_node->tag) || map_node->data.seq->total != 0) &&\r
-                CV_NODE_TYPE(map_node->tag) != CV_NODE_NONE )\r
-                CV_Error( CV_StsError, "The node is neither a map nor an empty collection" );\r
-            return 0;\r
-        }\r
-\r
-        map = map_node->data.map;\r
-        tab_size = map->tab_size;\r
-\r
-        if( (tab_size & (tab_size - 1)) == 0 )\r
-            i = (int)(hashval & (tab_size - 1));\r
-        else\r
-            i = (int)(hashval % tab_size);\r
-\r
-        for( another = (CvFileMapNode*)(map->table[i]); another != 0; another = another->next )\r
-        {\r
-            const CvStringHashNode* key = another->key;\r
-\r
-            if( key->hashval == hashval &&\r
-                key->str.len == len &&\r
-                memcmp( key->str.ptr, str, len ) == 0 )\r
-            {\r
-                value = &another->value;\r
-                return value;\r
-            }\r
-        }\r
-    }\r
-\r
-    return value;\r
-}\r
-\r
-\r
-CV_IMPL CvFileNode*\r
-cvGetRootFileNode( const CvFileStorage* fs, int stream_index )\r
-{\r
-    CV_CHECK_FILE_STORAGE(fs);\r
-\r
-    if( !fs->roots || (unsigned)stream_index >= (unsigned)fs->roots->total )\r
-        return 0;\r
-\r
-    return (CvFileNode*)cvGetSeqElem( fs->roots, stream_index );\r
-}\r
-\r
-\r
-/* returns the sequence element by its index */\r
-/*CV_IMPL CvFileNode*\r
-cvGetFileNodeFromSeq( CvFileStorage* fs,\r
-                      CvFileNode* seq_node, int index )\r
-{\r
-    CvFileNode* value = 0;\r
-    CvSeq* seq;\r
-\r
-    if( !seq_node )\r
-        seq = fs->roots;\r
-    else if( !CV_NODE_IS_SEQ(seq_node->tag) )\r
-    {\r
-        if( CV_NODE_IS_MAP(seq_node->tag) )\r
-            CV_Error( CV_StsError, "The node is map. Use cvGetFileNodeFromMap()." );\r
-        if( CV_NODE_TYPE(seq_node->tag) == CV_NODE_NONE )\r
-            CV_Error( CV_StsError, "The node is an empty object (None)." );\r
-        if( index != 0 && index != -1 )\r
-            CV_Error( CV_StsOutOfRange, "" );\r
-        value = seq_node;\r
-        EXIT;\r
-    }\r
-    else\r
-        seq = seq_node->data.seq;\r
-\r
-    if( !seq )\r
-        CV_Error( CV_StsNullPtr, "The file storage is empty" );\r
-\r
-    value = (CvFileNode*)cvGetSeqElem( seq, index, 0 );\r
-\r
-    \r
-\r
-    return value;\r
-}*/\r
-\r
-\r
-static char*\r
-icvDoubleToString( char* buf, double value )\r
-{\r
-    Cv64suf val;\r
-    unsigned ieee754_hi;\r
-\r
-    val.f = value;\r
-    ieee754_hi = (unsigned)(val.u >> 32);\r
-\r
-    if( (ieee754_hi & 0x7ff00000) != 0x7ff00000 )\r
-    {\r
-        int ivalue = cvRound(value);\r
-        if( ivalue == value )\r
-            sprintf( buf, "%d.", ivalue );\r
-        else\r
-        {\r
-            static const char* fmt[] = {"%.16e", "%.16f"};\r
-            double avalue = fabs(value);\r
-            char* ptr = buf;\r
-            sprintf( buf, fmt[0.01 <= avalue && avalue < 1000], value );\r
-            if( *ptr == '+' || *ptr == '-' )\r
-                ptr++;\r
-            for( ; isdigit(*ptr); ptr++ )\r
-                ;\r
-            if( *ptr == ',' )\r
-                *ptr = '.';\r
-        }\r
-    }\r
-    else\r
-    {\r
-        unsigned ieee754_lo = (unsigned)val.u;\r
-        if( (ieee754_hi & 0x7fffffff) + (ieee754_lo != 0) > 0x7ff00000 )\r
-            strcpy( buf, ".Nan" );\r
-        else\r
-            strcpy( buf, (int)ieee754_hi < 0 ? "-.Inf" : ".Inf" );\r
-    }\r
-\r
-    return buf;\r
-}\r
-\r
-\r
-static char*\r
-icvFloatToString( char* buf, float value )\r
-{\r
-    Cv32suf val;\r
-    unsigned ieee754;\r
-    val.f = value;\r
-    ieee754 = val.u;\r
-\r
-    if( (ieee754 & 0x7f800000) != 0x7f800000 )\r
-    {\r
-        int ivalue = cvRound(value);\r
-        if( ivalue == value )\r
-            sprintf( buf, "%d.", ivalue );\r
-        else\r
-        {\r
-            static const char* fmt[] = {"%.8e", "%.8f"};\r
-            double avalue = fabs((double)value);\r
-            char* ptr = buf;\r
-            sprintf( buf, fmt[0.01 <= avalue && avalue < 1000], value );\r
-            if( *ptr == '+' || *ptr == '-' )\r
-                ptr++;\r
-            for( ; isdigit(*ptr); ptr++ )\r
-                ;\r
-            if( *ptr == ',' )\r
-                *ptr = '.';\r
-        }\r
-    }\r
-    else\r
-    {\r
-        if( (ieee754 & 0x7fffffff) != 0x7f800000 )\r
-            strcpy( buf, ".Nan" );\r
-        else\r
-            strcpy( buf, (int)ieee754 < 0 ? "-.Inf" : ".Inf" );\r
-    }\r
-\r
-    return buf;\r
-}\r
-\r
-\r
-static void\r
-icvProcessSpecialDouble( CvFileStorage* fs, char* buf, double* value, char** endptr )\r
-{\r
-    char c = buf[0];\r
-    int inf_hi = 0x7ff00000;\r
-\r
-    if( c == '-' || c == '+' )\r
-    {\r
-        inf_hi = c == '-' ? 0xfff00000 : 0x7ff00000;\r
-        c = *++buf;\r
-    }\r
-\r
-    if( c != '.' )\r
-        CV_PARSE_ERROR( "Bad format of floating-point constant" );\r
-\r
-    if( toupper(buf[1]) == 'I' && toupper(buf[2]) == 'N' && toupper(buf[3]) == 'F' )\r
-        *(uint64*)value = ((uint64)inf_hi << 32);\r
-    else if( toupper(buf[1]) == 'N' && toupper(buf[2]) == 'A' && toupper(buf[3]) == 'N' )\r
-        *(uint64*)value = (uint64)-1;\r
-    else\r
-        CV_PARSE_ERROR( "Bad format of floating-point constant" );\r
-\r
-    *endptr = buf + 4;\r
-}\r
-\r
-\r
-static double icv_strtod( CvFileStorage* fs, char* ptr, char** endptr )\r
-{\r
-    double fval = strtod( ptr, endptr );\r
-    if( **endptr == '.' )\r
-    {\r
-        char* dot_pos = *endptr;\r
-        *dot_pos = ',';\r
-        double fval2 = strtod( ptr, endptr );\r
-        *dot_pos = '.';\r
-        if( *endptr > dot_pos )\r
-            fval = fval2;\r
-        else\r
-            *endptr = dot_pos;\r
-    }\r
-\r
-    if( *endptr == ptr || isalpha(**endptr) )\r
-        icvProcessSpecialDouble( fs, ptr, &fval, endptr );\r
-\r
-    return fval;\r
-}\r
-\r
-\r
-/****************************************************************************************\\r
-*                                       YAML Parser                                      *\r
-\****************************************************************************************/\r
-\r
-static char*\r
-icvYMLSkipSpaces( CvFileStorage* fs, char* ptr, int min_indent, int max_comment_indent )\r
-{\r
-    for(;;)\r
-    {\r
-        while( *ptr == ' ' )\r
-            ptr++;\r
-        if( *ptr == '#' )\r
-        {\r
-            if( ptr - fs->buffer_start > max_comment_indent )\r
-                return ptr;\r
-            *ptr = '\0';\r
-        }\r
-        else if( cv_isprint(*ptr) )\r
-        {\r
-            if( ptr - fs->buffer_start < min_indent )\r
-                CV_PARSE_ERROR( "Incorrect indentation" );\r
-            break;\r
-        }\r
-        else if( *ptr == '\0' || *ptr == '\n' || *ptr == '\r' )\r
-        {\r
-            int max_size = (int)(fs->buffer_end - fs->buffer_start);\r
-            ptr = fgets( fs->buffer_start, max_size, fs->file );\r
-            if( !ptr )\r
-            {\r
-                // emulate end of stream\r
-                ptr = fs->buffer_start;\r
-                ptr[0] = ptr[1] = ptr[2] = '.';\r
-                ptr[3] = '\0';\r
-                fs->dummy_eof = 1;\r
-                break;\r
-            }\r
-            else\r
-            {\r
-                int l = (int)strlen(ptr);\r
-                if( ptr[l-1] != '\n' && ptr[l-1] != '\r' && !feof(fs->file) )\r
-                    CV_PARSE_ERROR( "Too long string or a last string w/o newline" );\r
-            }\r
-\r
-            fs->lineno++;\r
-        }\r
-        else\r
-            CV_PARSE_ERROR( *ptr == '\t' ? "Tabs are prohibited in YAML!" : "Invalid character" );\r
-    }\r
-\r
-    return ptr;\r
-}\r
-\r
-\r
-static char*\r
-icvYMLParseKey( CvFileStorage* fs, char* ptr,\r
-                CvFileNode* map_node, CvFileNode** value_placeholder )\r
-{\r
-    char c;\r
-    char *endptr = ptr - 1, *saveptr;\r
-    CvStringHashNode* str_hash_node;\r
-\r
-    if( *ptr == '-' )\r
-        CV_PARSE_ERROR( "Key may not start with \'-\'" );\r
-\r
-    do c = *++endptr;\r
-    while( cv_isprint(c) && c != ':' );\r
-\r
-    if( c != ':' )\r
-        CV_PARSE_ERROR( "Missing \':\'" );\r
-\r
-    saveptr = endptr + 1;\r
-    do c = *--endptr;\r
-    while( c == ' ' );\r
-\r
-    ++endptr;\r
-    if( endptr == ptr )\r
-        CV_PARSE_ERROR( "An empty key" );\r
-\r
-    str_hash_node = cvGetHashedKey( fs, ptr, (int)(endptr - ptr), 1 );\r
-    *value_placeholder = cvGetFileNode( fs, map_node, str_hash_node, 1 );\r
-    ptr = saveptr;\r
-\r
-    return ptr;\r
-}\r
-\r
-\r
-static char*\r
-icvYMLParseValue( CvFileStorage* fs, char* ptr, CvFileNode* node,\r
-                  int parent_flags, int min_indent )\r
-{\r
-    char buf[CV_FS_MAX_LEN + 1024];\r
-    char* endptr = 0;\r
-    char c = ptr[0], d = ptr[1];\r
-    int is_parent_flow = CV_NODE_IS_FLOW(parent_flags);\r
-    int value_type = CV_NODE_NONE;\r
-    int len;\r
-\r
-    memset( node, 0, sizeof(*node) );\r
-\r
-    if( c == '!' ) // handle explicit type specification\r
-    {\r
-        if( d == '!' || d == '^' )\r
-        {\r
-            ptr++;\r
-            value_type |= CV_NODE_USER;\r
-        }\r
-\r
-        endptr = ptr++;\r
-        do d = *++endptr;\r
-        while( cv_isprint(d) && d != ' ' );\r
-        len = (int)(endptr - ptr);\r
-        if( len == 0 )\r
-            CV_PARSE_ERROR( "Empty type name" );\r
-        d = *endptr;\r
-        *endptr = '\0';\r
-\r
-        if( len == 3 && !CV_NODE_IS_USER(value_type) )\r
-        {\r
-            if( memcmp( ptr, "str", 3 ) == 0 )\r
-                value_type = CV_NODE_STRING;\r
-            else if( memcmp( ptr, "int", 3 ) == 0 )\r
-                value_type = CV_NODE_INT;\r
-            else if( memcmp( ptr, "seq", 3 ) == 0 )\r
-                value_type = CV_NODE_SEQ;\r
-            else if( memcmp( ptr, "map", 3 ) == 0 )\r
-                value_type = CV_NODE_MAP;\r
-        }\r
-        else if( len == 5 && !CV_NODE_IS_USER(value_type) )\r
-        {\r
-            if( memcmp( ptr, "float", 5 ) == 0 )\r
-                value_type = CV_NODE_REAL;\r
-        }\r
-        else if( CV_NODE_IS_USER(value_type) )\r
-        {\r
-            node->info = cvFindType( ptr );\r
-            if( !node->info )\r
-                node->tag &= ~CV_NODE_USER;\r
-        }\r
-\r
-        *endptr = d;\r
-        ptr = icvYMLSkipSpaces( fs, endptr, min_indent, INT_MAX );\r
-\r
-        c = *ptr;\r
-\r
-        if( !CV_NODE_IS_USER(value_type) )\r
-        {\r
-            if( value_type == CV_NODE_STRING && c != '\'' && c != '\"' )\r
-                goto force_string;\r
-            if( value_type == CV_NODE_INT )\r
-                goto force_int;\r
-            if( value_type == CV_NODE_REAL )\r
-                goto force_real;\r
-        }\r
-    }\r
-\r
-    if( isdigit(c) ||\r
-        ((c == '-' || c == '+') && (isdigit(d) || d == '.')) ||\r
-        (c == '.' && isalnum(d))) // a number\r
-    {\r
-        double fval;\r
-        int ival;\r
-        endptr = ptr + (c == '-' || c == '+');\r
-        while( isdigit(*endptr) )\r
-            endptr++;\r
-        if( *endptr == '.' || *endptr == 'e' )\r
-        {\r
-force_real:\r
-            fval = icv_strtod( fs, ptr, &endptr );\r
-            /*if( endptr == ptr || isalpha(*endptr) )\r
-                icvProcessSpecialDouble( fs, endptr, &fval, &endptr ));*/\r
-\r
-            node->tag = CV_NODE_REAL;\r
-            node->data.f = fval;\r
-        }\r
-        else\r
-        {\r
-force_int:\r
-            ival = (int)strtol( ptr, &endptr, 0 );\r
-            node->tag = CV_NODE_INT;\r
-            node->data.i = ival;\r
-        }\r
-\r
-        if( !endptr || endptr == ptr )\r
-            CV_PARSE_ERROR( "Invalid numeric value (inconsistent explicit type specification?)" );\r
-\r
-        ptr = endptr;\r
-    }\r
-    else if( c == '\'' || c == '\"' ) // an explicit string\r
-    {\r
-        node->tag = CV_NODE_STRING;\r
-        if( c == '\'' )\r
-            for( len = 0; len < CV_FS_MAX_LEN; )\r
-            {\r
-                c = *++ptr;\r
-                if( isalnum(c) || (c != '\'' && cv_isprint(c)))\r
-                    buf[len++] = c;\r
-                else if( c == '\'' )\r
-                {\r
-                    c = *++ptr;\r
-                    if( c != '\'' )\r
-                        break;\r
-                    buf[len++] = c;\r
-                }\r
-                else\r
-                    CV_PARSE_ERROR( "Invalid character" );\r
-            }\r
-        else\r
-            for( len = 0; len < CV_FS_MAX_LEN; )\r
-            {\r
-                c = *++ptr;\r
-                if( isalnum(c) || (c != '\\' && c != '\"' && cv_isprint(c)))\r
-                    buf[len++] = c;\r
-                else if( c == '\"' )\r
-                {\r
-                    ++ptr;\r
-                    break;\r
-                }\r
-                else if( c == '\\' )\r
-                {\r
-                    d = *++ptr;\r
-                    if( d == '\'' )\r
-                        buf[len++] = d;\r
-                    else if( d == '\"' || d == '\\' || d == '\'' )\r
-                        buf[len++] = d;\r
-                    else if( d == 'n' )\r
-                        buf[len++] = '\n';\r
-                    else if( d == 'r' )\r
-                        buf[len++] = '\r';\r
-                    else if( d == 't' )\r
-                        buf[len++] = '\t';\r
-                    else if( d == 'x' || (isdigit(d) && d < '8') )\r
-                    {\r
-                        int val, is_hex = d == 'x';\r
-                        c = ptr[3];\r
-                        ptr[3] = '\0';\r
-                        val = strtol( ptr + is_hex, &endptr, is_hex ? 8 : 16 );\r
-                        ptr[3] = c;\r
-                        if( endptr == ptr + is_hex )\r
-                            buf[len++] = 'x';\r
-                        else\r
-                        {\r
-                            buf[len++] = (char)val;\r
-                            ptr = endptr;\r
-                        }\r
-                    }\r
-                }\r
-                else\r
-                    CV_PARSE_ERROR( "Invalid character" );\r
-            }\r
-\r
-        if( len >= CV_FS_MAX_LEN )\r
-            CV_PARSE_ERROR( "Too long string literal" );\r
-\r
-        node->data.str = cvMemStorageAllocString( fs->memstorage, buf, len );\r
-    }\r
-    else if( c == '[' || c == '{' ) // collection as a flow\r
-    {\r
-        int new_min_indent = min_indent + !is_parent_flow;\r
-        int struct_flags = CV_NODE_FLOW + (c == '{' ? CV_NODE_MAP : CV_NODE_SEQ);\r
-        int is_simple = 1;\r
-\r
-        icvFSCreateCollection( fs, CV_NODE_TYPE(struct_flags) +\r
-                                        (node->info ? CV_NODE_USER : 0), node );\r
-\r
-        d = c == '[' ? ']' : '}';\r
-\r
-        for( ++ptr ;;)\r
-        {\r
-            CvFileNode* elem = 0;\r
-\r
-            ptr = icvYMLSkipSpaces( fs, ptr, new_min_indent, INT_MAX );\r
-            if( *ptr == '}' || *ptr == ']' )\r
-            {\r
-                if( *ptr != d )\r
-                    CV_PARSE_ERROR( "The wrong closing bracket" );\r
-                ptr++;\r
-                break;\r
-            }\r
-\r
-            if( node->data.seq->total != 0 )\r
-            {\r
-                if( *ptr != ',' )\r
-                    CV_PARSE_ERROR( "Missing , between the elements" );\r
-                ptr = icvYMLSkipSpaces( fs, ptr + 1, new_min_indent, INT_MAX );\r
-            }\r
-\r
-            if( CV_NODE_IS_MAP(struct_flags) )\r
-            {\r
-                ptr = icvYMLParseKey( fs, ptr, node, &elem );\r
-                ptr = icvYMLSkipSpaces( fs, ptr, new_min_indent, INT_MAX );\r
-            }\r
-            else\r
-            {\r
-                if( *ptr == ']' )\r
-                    break;\r
-                elem = (CvFileNode*)cvSeqPush( node->data.seq, 0 );\r
-            }\r
-            ptr = icvYMLParseValue( fs, ptr, elem, struct_flags, new_min_indent );\r
-            if( CV_NODE_IS_MAP(struct_flags) )\r
-                elem->tag |= CV_NODE_NAMED;\r
-            is_simple &= !CV_NODE_IS_COLLECTION(elem->tag);\r
-        }\r
-        node->data.seq->flags |= is_simple ? CV_NODE_SEQ_SIMPLE : 0;\r
-    }\r
-    else\r
-    {\r
-        int indent, struct_flags, is_simple;\r
-\r
-        if( is_parent_flow || c != '-' )\r
-        {\r
-            // implicit (one-line) string or nested block-style collection\r
-            if( !is_parent_flow )\r
-            {\r
-                if( c == '?' )\r
-                    CV_PARSE_ERROR( "Complex keys are not supported" );\r
-                if( c == '|' || c == '>' )\r
-                    CV_PARSE_ERROR( "Multi-line text literals are not supported" );\r
-            }\r
-\r
-force_string:\r
-            endptr = ptr - 1;\r
-\r
-            do c = *++endptr;\r
-            while( cv_isprint(c) &&\r
-                   (!is_parent_flow || (c != ',' && c != '}' && c != ']')) &&\r
-                   (is_parent_flow || c != ':' || value_type == CV_NODE_STRING));\r
-\r
-            if( endptr == ptr )\r
-                CV_PARSE_ERROR( "Invalid character" );\r
-\r
-            if( is_parent_flow || c != ':' )\r
-            {\r
-                char* str_end = endptr;\r
-                node->tag = CV_NODE_STRING;\r
-                // strip spaces in the end of string\r
-                do c = *--str_end;\r
-                while( str_end > ptr && c == ' ' );\r
-                str_end++;\r
-                node->data.str = cvMemStorageAllocString( fs->memstorage, ptr, (int)(str_end - ptr) );\r
-                ptr = endptr;\r
-                return ptr;\r
-            }\r
-            struct_flags = CV_NODE_MAP;\r
-        }\r
-        else\r
-            struct_flags = CV_NODE_SEQ;\r
-\r
-        icvFSCreateCollection( fs, struct_flags +\r
-                    (node->info ? CV_NODE_USER : 0), node );\r
-\r
-        indent = (int)(ptr - fs->buffer_start);\r
-        is_simple = 1;\r
-\r
-        for(;;)\r
-        {\r
-            CvFileNode* elem = 0;\r
-\r
-            if( CV_NODE_IS_MAP(struct_flags) )\r
-            {\r
-                ptr = icvYMLParseKey( fs, ptr, node, &elem );\r
-            }\r
-            else\r
-            {\r
-                c = *ptr++;\r
-                if( c != '-' )\r
-                    CV_PARSE_ERROR( "Block sequence elements must be preceded with \'-\'" );\r
-\r
-                elem = (CvFileNode*)cvSeqPush( node->data.seq, 0 );\r
-            }\r
-\r
-            ptr = icvYMLSkipSpaces( fs, ptr, indent + 1, INT_MAX );\r
-            ptr = icvYMLParseValue( fs, ptr, elem, struct_flags, indent + 1 );\r
-            if( CV_NODE_IS_MAP(struct_flags) )\r
-                elem->tag |= CV_NODE_NAMED;\r
-            is_simple &= !CV_NODE_IS_COLLECTION(elem->tag);\r
-\r
-            ptr = icvYMLSkipSpaces( fs, ptr, 0, INT_MAX );\r
-            if( ptr - fs->buffer_start != indent )\r
-            {\r
-                if( ptr - fs->buffer_start < indent )\r
-                    break;\r
-                else\r
-                    CV_PARSE_ERROR( "Incorrect indentation" );\r
-            }\r
-            if( memcmp( ptr, "...", 3 ) == 0 )\r
-                break;\r
-        }\r
-\r
-        node->data.seq->flags |= is_simple ? CV_NODE_SEQ_SIMPLE : 0;\r
-    }\r
-\r
-    return ptr;\r
-}\r
-\r
-\r
-static void\r
-icvYMLParse( CvFileStorage* fs )\r
-{\r
-    char* ptr = fs->buffer_start;\r
-    int is_first = 1;\r
-\r
-    for(;;)\r
-    {\r
-        // 0. skip leading comments and directives  and ...\r
-        // 1. reach the first item\r
-        for(;;)\r
-        {\r
-            ptr = icvYMLSkipSpaces( fs, ptr, 0, INT_MAX );\r
-            if( !ptr )\r
-                return;\r
-\r
-            if( *ptr == '%' )\r
-            {\r
-                if( memcmp( ptr, "%YAML:", 6 ) == 0 &&\r
-                    memcmp( ptr, "%YAML:1.", 8 ) != 0 )\r
-                    CV_PARSE_ERROR( "Unsupported YAML version (it must be 1.x)" );\r
-                *ptr = '\0';\r
-            }\r
-            else if( *ptr == '-' )\r
-            {\r
-                if( memcmp(ptr, "---", 3) == 0 )\r
-                {\r
-                    ptr += 3;\r
-                    break;\r
-                }\r
-                else if( is_first )\r
-                    break;\r
-            }\r
-            else if( isalnum(*ptr) || *ptr=='_')\r
-            {\r
-                if( !is_first )\r
-                    CV_PARSE_ERROR( "The YAML streams must start with '---', except the first one" );\r
-                break;\r
-            }\r
-            else\r
-                CV_PARSE_ERROR( "Invalid or unsupported syntax" );\r
-        }\r
-\r
-        ptr = icvYMLSkipSpaces( fs, ptr, 0, INT_MAX );\r
-        if( memcmp( ptr, "...", 3 ) != 0 )\r
-        {\r
-            // 2. parse the collection\r
-            CvFileNode* root_node = (CvFileNode*)cvSeqPush( fs->roots, 0 );\r
-\r
-            ptr = icvYMLParseValue( fs, ptr, root_node, CV_NODE_NONE, 0 );\r
-            if( !CV_NODE_IS_COLLECTION(root_node->tag) )\r
-                CV_PARSE_ERROR( "Only collections as YAML streams are supported by this parser" );\r
-\r
-            // 3. parse until the end of file or next collection\r
-            ptr = icvYMLSkipSpaces( fs, ptr, 0, INT_MAX );\r
-            if( !ptr )\r
-                return;\r
-        }\r
-\r
-        if( fs->dummy_eof )\r
-            break;\r
-        ptr += 3;\r
-        is_first = 0;\r
-    }\r
-}\r
-\r
-\r
-/****************************************************************************************\\r
-*                                       YAML Emitter                                     *\r
-\****************************************************************************************/\r
-\r
-static void\r
-icvYMLWrite( CvFileStorage* fs, const char* key, const char* data )\r
-{\r
-    int i, keylen = 0;\r
-    int datalen = 0;\r
-    int struct_flags;\r
-    char* ptr;\r
-\r
-    struct_flags = fs->struct_flags;\r
-\r
-    if( key && key[0] == '\0' )\r
-        key = 0;\r
-\r
-    if( CV_NODE_IS_COLLECTION(struct_flags) )\r
-    {\r
-        if( (CV_NODE_IS_MAP(struct_flags) ^ (key != 0)) )\r
-            CV_Error( CV_StsBadArg, "An attempt to add element without a key to a map, "\r
-                                    "or add element with key to sequence" );\r
-    }\r
-    else\r
-    {\r
-        fs->is_first = 0;\r
-        struct_flags = CV_NODE_EMPTY | (key ? CV_NODE_MAP : CV_NODE_SEQ);\r
-    }\r
-\r
-    if( key )\r
-    {\r
-        keylen = (int)strlen(key);\r
-        if( keylen == 0 )\r
-            CV_Error( CV_StsBadArg, "The key is an empty" );\r
-\r
-        if( keylen > CV_FS_MAX_LEN )\r
-            CV_Error( CV_StsBadArg, "The key is too long" );\r
-    }\r
-\r
-    if( data )\r
-        datalen = (int)strlen(data);\r
-\r
-    if( CV_NODE_IS_FLOW(struct_flags) )\r
-    {\r
-        int new_offset;\r
-        ptr = fs->buffer;\r
-        if( !CV_NODE_IS_EMPTY(struct_flags) )\r
-            *ptr++ = ',';\r
-        new_offset = (int)(ptr - fs->buffer_start) + keylen + datalen;\r
-        if( new_offset > fs->wrap_margin && new_offset - fs->struct_indent > 10 )\r
-        {\r
-            fs->buffer = ptr;\r
-            ptr = icvFSFlush(fs);\r
-        }\r
-        else\r
-            *ptr++ = ' ';\r
-    }\r
-    else\r
-    {\r
-        ptr = icvFSFlush(fs);\r
-        if( !CV_NODE_IS_MAP(struct_flags) )\r
-        {\r
-            *ptr++ = '-';\r
-            if( data )\r
-                *ptr++ = ' ';\r
-        }\r
-    }\r
-\r
-    if( key )\r
-    {\r
-        if( !isalpha(key[0]) && key[0] != '_' )\r
-            CV_Error( CV_StsBadArg, "Key must start with a letter or _" );\r
-\r
-        ptr = icvFSResizeWriteBuffer( fs, ptr, keylen );\r
-\r
-        for( i = 0; i < keylen; i++ )\r
-        {\r
-            int c = key[i];\r
-\r
-            ptr[i] = (char)c;\r
-            if( !isalnum(c) && c != '-' && c != '_' && c != ' ' )\r
-                CV_Error( CV_StsBadArg, "Key names may only contain alphanumeric characters [a-zA-Z0-9], '-', '_' and ' '" );\r
-        }\r
-\r
-        ptr += keylen;\r
-        *ptr++ = ':';\r
-        if( !CV_NODE_IS_FLOW(struct_flags) && data )\r
-            *ptr++ = ' ';\r
-    }\r
-\r
-    if( data )\r
-    {\r
-        ptr = icvFSResizeWriteBuffer( fs, ptr, datalen );\r
-        memcpy( ptr, data, datalen );\r
-        ptr += datalen;\r
-    }\r
-\r
-    fs->buffer = ptr;\r
-    fs->struct_flags = struct_flags & ~CV_NODE_EMPTY;\r
-}\r
-\r
-\r
-static void\r
-icvYMLStartWriteStruct( CvFileStorage* fs, const char* key, int struct_flags,\r
-                        const char* type_name CV_DEFAULT(0))\r
-{\r
-    int parent_flags;\r
-    char buf[CV_FS_MAX_LEN + 1024];\r
-    const char* data = 0;\r
-\r
-    struct_flags = (struct_flags & (CV_NODE_TYPE_MASK|CV_NODE_FLOW)) | CV_NODE_EMPTY;\r
-    if( !CV_NODE_IS_COLLECTION(struct_flags))\r
-        CV_Error( CV_StsBadArg,\r
-        "Some collection type - CV_NODE_SEQ or CV_NODE_MAP, must be specified" );\r
-\r
-    if( CV_NODE_IS_FLOW(struct_flags) )\r
-    {\r
-        char c = CV_NODE_IS_MAP(struct_flags) ? '{' : '[';\r
-        struct_flags |= CV_NODE_FLOW;\r
-\r
-        if( type_name )\r
-            sprintf( buf, "!!%s %c", type_name, c );\r
-        else\r
-        {\r
-            buf[0] = c;\r
-            buf[1] = '\0';\r
-        }\r
-        data = buf;\r
-    }\r
-    else if( type_name )\r
-    {\r
-        sprintf( buf, "!!%s", type_name );\r
-        data = buf;\r
-    }\r
-\r
-    icvYMLWrite( fs, key, data );\r
-\r
-    parent_flags = fs->struct_flags;\r
-    cvSeqPush( fs->write_stack, &parent_flags );\r
-    fs->struct_flags = struct_flags;\r
-\r
-    if( !CV_NODE_IS_FLOW(parent_flags) )\r
-        fs->struct_indent += CV_YML_INDENT + CV_NODE_IS_FLOW(struct_flags);\r
-}\r
-\r
-\r
-static void\r
-icvYMLEndWriteStruct( CvFileStorage* fs )\r
-{\r
-    int parent_flags = 0, struct_flags;\r
-    char* ptr;\r
-\r
-    struct_flags = fs->struct_flags;\r
-    if( fs->write_stack->total == 0 )\r
-        CV_Error( CV_StsError, "EndWriteStruct w/o matching StartWriteStruct" );\r
-\r
-    cvSeqPop( fs->write_stack, &parent_flags );\r
-\r
-    if( CV_NODE_IS_FLOW(struct_flags) )\r
-    {\r
-        ptr = fs->buffer;\r
-        if( ptr > fs->buffer_start + fs->struct_indent && !CV_NODE_IS_EMPTY(struct_flags) )\r
-            *ptr++ = ' ';\r
-        *ptr++ = CV_NODE_IS_MAP(struct_flags) ? '}' : ']';\r
-        fs->buffer = ptr;\r
-    }\r
-    else if( CV_NODE_IS_EMPTY(struct_flags) )\r
-    {\r
-        ptr = icvFSFlush(fs);\r
-        memcpy( ptr, CV_NODE_IS_MAP(struct_flags) ? "{}" : "[]", 2 );\r
-        fs->buffer = ptr + 2;\r
-    }\r
-\r
-    if( !CV_NODE_IS_FLOW(parent_flags) )\r
-        fs->struct_indent -= CV_YML_INDENT + CV_NODE_IS_FLOW(struct_flags);\r
-    assert( fs->struct_indent >= 0 );\r
-\r
-    fs->struct_flags = parent_flags;\r
-}\r
-\r
-\r
-static void\r
-icvYMLStartNextStream( CvFileStorage* fs )\r
-{\r
-    if( !fs->is_first )\r
-    {\r
-        while( fs->write_stack->total > 0 )\r
-            icvYMLEndWriteStruct(fs);\r
-\r
-        fs->struct_indent = 0;\r
-        icvFSFlush(fs);\r
-        fputs( "...\n", fs->file );\r
-        fputs( "---\n", fs->file );\r
-        fs->buffer = fs->buffer_start;\r
-    }\r
-}\r
-\r
-\r
-static void\r
-icvYMLWriteInt( CvFileStorage* fs, const char* key, int value )\r
-{\r
-    char buf[128];\r
-    icvYMLWrite( fs, key, icv_itoa( value, buf, 10 ));\r
-}\r
-\r
-\r
-static void\r
-icvYMLWriteReal( CvFileStorage* fs, const char* key, double value )\r
-{\r
-    char buf[128];\r
-    icvYMLWrite( fs, key, icvDoubleToString( buf, value ));\r
-}\r
-\r
-\r
-static void\r
-icvYMLWriteString( CvFileStorage* fs, const char* key,\r
-                   const char* str, int quote CV_DEFAULT(0))\r
-{\r
-    char buf[CV_FS_MAX_LEN*4+16];\r
-    char* data = (char*)str;\r
-    int i, len;\r
-\r
-    if( !str )\r
-        CV_Error( CV_StsNullPtr, "Null string pointer" );\r
-\r
-    len = (int)strlen(str);\r
-    if( len > CV_FS_MAX_LEN )\r
-        CV_Error( CV_StsBadArg, "The written string is too long" );\r
-\r
-    if( quote || len == 0 || str[0] != str[len-1] || (str[0] != '\"' && str[0] != '\'') )\r
-    {\r
-        int need_quote = quote || len == 0;\r
-        data = buf;\r
-        *data++ = '\"';\r
-        for( i = 0; i < len; i++ )\r
-        {\r
-            char c = str[i];\r
-\r
-            if( !need_quote && !isalnum(c) && c != '_' && c != ' ' && c != '-' &&\r
-                c != '(' && c != ')' && c != '/' && c != '+' && c != ';' )\r
-                need_quote = 1;\r
-\r
-            if( !isalnum(c) && (!cv_isprint(c) || c == '\\' || c == '\'' || c == '\"') )\r
-            {\r
-                *data++ = '\\';\r
-                if( cv_isprint(c) )\r
-                    *data++ = c;\r
-                else if( c == '\n' )\r
-                    *data++ = 'n';\r
-                else if( c == '\r' )\r
-                    *data++ = 'r';\r
-                else if( c == '\t' )\r
-                    *data++ = 't';\r
-                else\r
-                {\r
-                    sprintf( data, "x%02x", c );\r
-                    data += 3;\r
-                }\r
-            }\r
-            else\r
-                *data++ = c;\r
-        }\r
-        if( !need_quote && (isdigit(str[0]) ||\r
-            str[0] == '+' || str[0] == '-' || str[0] == '.' ))\r
-            need_quote = 1;\r
-\r
-        if( need_quote )\r
-            *data++ = '\"';\r
-        *data++ = '\0';\r
-        data = buf + !need_quote;\r
-    }\r
-\r
-    icvYMLWrite( fs, key, data );\r
-}\r
-\r
-\r
-static void\r
-icvYMLWriteComment( CvFileStorage* fs, const char* comment, int eol_comment )\r
-{\r
-    int len; //, indent;\r
-    int multiline;\r
-    const char* eol;\r
-    char* ptr;\r
-\r
-    if( !comment )\r
-        CV_Error( CV_StsNullPtr, "Null comment" );\r
-\r
-    len = (int)strlen(comment);\r
-    eol = strchr(comment, '\n');\r
-    multiline = eol != 0;\r
-    ptr = fs->buffer;\r
-\r
-    if( !eol_comment || multiline ||\r
-        fs->buffer_end - ptr < len || ptr == fs->buffer_start )\r
-        ptr = icvFSFlush( fs );\r
-    else\r
-        *ptr++ = ' ';\r
-\r
-    while( comment )\r
-    {\r
-        *ptr++ = '#';\r
-        *ptr++ = ' ';\r
-        if( eol )\r
-        {\r
-            ptr = icvFSResizeWriteBuffer( fs, ptr, (int)(eol - comment) + 1 );\r
-            memcpy( ptr, comment, eol - comment + 1 );\r
-            fs->buffer = ptr + (eol - comment);\r
-            comment = eol + 1;\r
-            eol = strchr( comment, '\n' );\r
-        }\r
-        else\r
-        {\r
-            len = (int)strlen(comment);\r
-            ptr = icvFSResizeWriteBuffer( fs, ptr, len );\r
-            memcpy( ptr, comment, len );\r
-            fs->buffer = ptr + len;\r
-            comment = 0;\r
-        }\r
-        ptr = icvFSFlush( fs );\r
-    }\r
-}\r
-\r
-\r
-/****************************************************************************************\\r
-*                                       XML Parser                                       *\r
-\****************************************************************************************/\r
-\r
-#define CV_XML_INSIDE_COMMENT 1\r
-#define CV_XML_INSIDE_TAG 2\r
-#define CV_XML_INSIDE_DIRECTIVE 3\r
-\r
-static char*\r
-icvXMLSkipSpaces( CvFileStorage* fs, char* ptr, int mode )\r
-{\r
-    int level = 0;\r
-\r
-    for(;;)\r
-    {\r
-        char c;\r
-        ptr--;\r
-\r
-        if( mode == CV_XML_INSIDE_COMMENT )\r
-        {\r
-            do c = *++ptr;\r
-            while( cv_isprint_or_tab(c) && (c != '-' || ptr[1] != '-' || ptr[2] != '>') );\r
-\r
-            if( c == '-' )\r
-            {\r
-                assert( ptr[1] == '-' && ptr[2] == '>' );\r
-                mode = 0;\r
-                ptr += 3;\r
-            }\r
-        }\r
-        else if( mode == CV_XML_INSIDE_DIRECTIVE )\r
-        {\r
-            // !!!NOTE!!! This is not quite correct, but should work in most cases\r
-            do\r
-            {\r
-                c = *++ptr;\r
-                level += c == '<';\r
-                level -= c == '>';\r
-                if( level < 0 )\r
-                    return ptr;\r
-            } while( cv_isprint_or_tab(c) );\r
-        }\r
-        else\r
-        {\r
-            do c = *++ptr;\r
-            while( c == ' ' || c == '\t' );\r
-\r
-            if( c == '<' && ptr[1] == '!' && ptr[2] == '-' && ptr[3] == '-' )\r
-            {\r
-                if( mode != 0 )\r
-                    CV_PARSE_ERROR( "Comments are not allowed here" );\r
-                mode = CV_XML_INSIDE_COMMENT;\r
-                ptr += 4;\r
-            }\r
-            else if( cv_isprint(c) )\r
-                break;\r
-        }\r
-\r
-        if( !cv_isprint(*ptr) )\r
-        {\r
-            int max_size = (int)(fs->buffer_end - fs->buffer_start);\r
-            if( *ptr != '\0' && *ptr != '\n' && *ptr != '\r' )\r
-                CV_PARSE_ERROR( "Invalid character in the stream" );\r
-            ptr = fgets( fs->buffer_start, max_size, fs->file );\r
-            if( !ptr )\r
-            {\r
-                ptr = fs->buffer_start;\r
-                *ptr = '\0';\r
-                fs->dummy_eof = 1;\r
-                break;\r
-            }\r
-            else\r
-            {\r
-                int l = (int)strlen(ptr);\r
-                if( ptr[l-1] != '\n' && ptr[l-1] != '\r' && !feof(fs->file) )\r
-                    CV_PARSE_ERROR( "Too long string or a last string w/o newline" );\r
-            }\r
-            fs->lineno++;\r
-        }\r
-    }\r
-    return ptr;\r
-}\r
-\r
-\r
-static char*\r
-icvXMLParseTag( CvFileStorage* fs, char* ptr, CvStringHashNode** _tag,\r
-                CvAttrList** _list, int* _tag_type );\r
-\r
-static char*\r
-icvXMLParseValue( CvFileStorage* fs, char* ptr, CvFileNode* node,\r
-                  int value_type CV_DEFAULT(CV_NODE_NONE))\r
-{\r
-    CvFileNode *elem = node;\r
-    int have_space = 1, is_simple = 1;\r
-    int is_user_type = CV_NODE_IS_USER(value_type);\r
-    memset( node, 0, sizeof(*node) );\r
-\r
-    value_type = CV_NODE_TYPE(value_type);\r
-\r
-    for(;;)\r
-    {\r
-        char c = *ptr, d;\r
-        char* endptr;\r
-\r
-        if( isspace(c) || c == '\0' || (c == '<' && ptr[1] == '!' && ptr[2] == '-') )\r
-        {\r
-            ptr = icvXMLSkipSpaces( fs, ptr, 0 );\r
-            have_space = 1;\r
-            c = *ptr;\r
-        }\r
-\r
-        d = ptr[1];\r
-\r
-        if( c =='<' )\r
-        {\r
-            CvStringHashNode *key = 0, *key2 = 0;\r
-            CvAttrList* list = 0;\r
-            CvTypeInfo* info = 0;\r
-            int tag_type = 0;\r
-            int is_noname = 0;\r
-            const char* type_name = 0;\r
-            int elem_type = CV_NODE_NONE;\r
-\r
-            if( d == '/' )\r
-                break;\r
-\r
-            ptr = icvXMLParseTag( fs, ptr, &key, &list, &tag_type );\r
-\r
-            if( tag_type == CV_XML_DIRECTIVE_TAG )\r
-                CV_PARSE_ERROR( "Directive tags are not allowed here" );\r
-            if( tag_type == CV_XML_EMPTY_TAG )\r
-                CV_PARSE_ERROR( "Empty tags are not supported" );\r
-\r
-            assert( tag_type == CV_XML_OPENING_TAG );\r
-\r
-            type_name = list ? cvAttrValue( list, "type_id" ) : 0;\r
-            if( type_name )\r
-            {\r
-                if( strcmp( type_name, "str" ) == 0 )\r
-                    elem_type = CV_NODE_STRING;\r
-                else if( strcmp( type_name, "map" ) == 0 )\r
-                    elem_type = CV_NODE_MAP;\r
-                else if( strcmp( type_name, "seq" ) == 0 )\r
-                    elem_type = CV_NODE_SEQ;\r
-                else\r
-                {\r
-                    info = cvFindType( type_name );\r
-                    if( info )\r
-                        elem_type = CV_NODE_USER;\r
-                }\r
-            }\r
-\r
-            is_noname = key->str.len == 1 && key->str.ptr[0] == '_';\r
-            if( !CV_NODE_IS_COLLECTION(node->tag) )\r
-            {\r
-                icvFSCreateCollection( fs, is_noname ? CV_NODE_SEQ : CV_NODE_MAP, node );\r
-            }\r
-            else if( is_noname ^ CV_NODE_IS_SEQ(node->tag) )\r
-                CV_PARSE_ERROR( is_noname ? "Map element should have a name" :\r
-                              "Sequence element should not have name (use <_></_>)" );\r
-\r
-            if( is_noname )\r
-                elem = (CvFileNode*)cvSeqPush( node->data.seq, 0 );\r
-            else\r
-                elem = cvGetFileNode( fs, node, key, 1 );\r
-\r
-            ptr = icvXMLParseValue( fs, ptr, elem, elem_type);\r
-            if( !is_noname )\r
-                elem->tag |= CV_NODE_NAMED;\r
-            is_simple &= !CV_NODE_IS_COLLECTION(elem->tag);\r
-            elem->info = info;\r
-            ptr = icvXMLParseTag( fs, ptr, &key2, &list, &tag_type );\r
-            if( tag_type != CV_XML_CLOSING_TAG || key2 != key )\r
-                CV_PARSE_ERROR( "Mismatched closing tag" );\r
-            have_space = 1;\r
-        }\r
-        else\r
-        {\r
-            if( !have_space )\r
-                CV_PARSE_ERROR( "There should be space between literals" );\r
-\r
-            elem = node;\r
-            if( node->tag != CV_NODE_NONE )\r
-            {\r
-                if( !CV_NODE_IS_COLLECTION(node->tag) )\r
-                    icvFSCreateCollection( fs, CV_NODE_SEQ, node );\r
-\r
-                elem = (CvFileNode*)cvSeqPush( node->data.seq, 0 );\r
-                elem->info = 0;\r
-            }\r
-\r
-            if( value_type != CV_NODE_STRING &&\r
-                (isdigit(c) || ((c == '-' || c == '+') &&\r
-                (isdigit(d) || d == '.')) || (c == '.' && isalnum(d))) ) // a number\r
-            {\r
-                double fval;\r
-                int ival;\r
-                endptr = ptr + (c == '-' || c == '+');\r
-                while( isdigit(*endptr) )\r
-                    endptr++;\r
-                if( *endptr == '.' || *endptr == 'e' )\r
-                {\r
-                    fval = icv_strtod( fs, ptr, &endptr );\r
-                    /*if( endptr == ptr || isalpha(*endptr) )\r
-                        icvProcessSpecialDouble( fs, ptr, &fval, &endptr ));*/\r
-                    elem->tag = CV_NODE_REAL;\r
-                    elem->data.f = fval;\r
-                }\r
-                else\r
-                {\r
-                    ival = (int)strtol( ptr, &endptr, 0 );\r
-                    elem->tag = CV_NODE_INT;\r
-                    elem->data.i = ival;\r
-                }\r
-\r
-                if( endptr == ptr )\r
-                    CV_PARSE_ERROR( "Invalid numeric value (inconsistent explicit type specification?)" );\r
-\r
-                ptr = endptr;\r
-            }\r
-            else\r
-            {\r
-                // string\r
-                char buf[CV_FS_MAX_LEN+16];\r
-                int i = 0, len, is_quoted = 0;\r
-                elem->tag = CV_NODE_STRING;\r
-                if( c == '\"' )\r
-                    is_quoted = 1;\r
-                else\r
-                    --ptr;\r
-\r
-                for( ;; )\r
-                {\r
-                    c = *++ptr;\r
-                    if( !isalnum(c) )\r
-                    {\r
-                        if( c == '\"' )\r
-                        {\r
-                            if( !is_quoted )\r
-                                CV_PARSE_ERROR( "Literal \" is not allowed within a string. Use &quot;" );\r
-                            ++ptr;\r
-                            break;\r
-                        }\r
-                        else if( !cv_isprint(c) || c == '<' || (!is_quoted && isspace(c)))\r
-                        {\r
-                            if( is_quoted )\r
-                                CV_PARSE_ERROR( "Closing \" is expected" );\r
-                            break;\r
-                        }\r
-                        else if( c == '\'' || c == '>' )\r
-                        {\r
-                            CV_PARSE_ERROR( "Literal \' or > are not allowed. Use &apos; or &gt;" );\r
-                        }\r
-                        else if( c == '&' )\r
-                        {\r
-                            if( *ptr == '#' )\r
-                            {\r
-                                int val;\r
-                                ptr++;\r
-                                val = (int)strtol( ptr, &endptr, 0 );\r
-                                if( (unsigned)val > (unsigned)255 ||\r
-                                    !endptr || *endptr != ';' )\r
-                                    CV_PARSE_ERROR( "Invalid numeric value in the string" );\r
-                                c = (char)val;\r
-                            }\r
-                            else\r
-                            {\r
-                                endptr = ptr++;\r
-                                do c = *++endptr;\r
-                                while( isalnum(c) );\r
-                                if( c != ';' )\r
-                                    CV_PARSE_ERROR( "Invalid character in the symbol entity name" );\r
-                                len = (int)(endptr - ptr);\r
-                                if( len == 2 && memcmp( ptr, "lt", len ) == 0 )\r
-                                    c = '<';\r
-                                else if( len == 2 && memcmp( ptr, "gt", len ) == 0 )\r
-                                    c = '>';\r
-                                else if( len == 3 && memcmp( ptr, "amp", len ) == 0 )\r
-                                    c = '&';\r
-                                else if( len == 4 && memcmp( ptr, "apos", len ) == 0 )\r
-                                    c = '\'';\r
-                                else if( len == 4 && memcmp( ptr, "quot", len ) == 0 )\r
-                                    c = '\"';\r
-                                else\r
-                                {\r
-                                    memcpy( buf + i, ptr-1, len + 2 );\r
-                                    i += len + 2;\r
-                                }\r
-                            }\r
-                            ptr = endptr;\r
-                        }\r
-                    }\r
-                    buf[i++] = c;\r
-                    if( i >= CV_FS_MAX_LEN )\r
-                        CV_PARSE_ERROR( "Too long string literal" );\r
-                }\r
-                elem->data.str = cvMemStorageAllocString( fs->memstorage, buf, i );\r
-            }\r
-\r
-            if( !CV_NODE_IS_COLLECTION(value_type) && value_type != CV_NODE_NONE )\r
-                break;\r
-            have_space = 0;\r
-        }\r
-    }\r
-\r
-    if( (CV_NODE_TYPE(node->tag) == CV_NODE_NONE ||\r
-        (CV_NODE_TYPE(node->tag) != value_type &&\r
-        !CV_NODE_IS_COLLECTION(node->tag))) &&\r
-        CV_NODE_IS_COLLECTION(value_type) )\r
-    {\r
-        icvFSCreateCollection( fs, CV_NODE_IS_MAP(value_type) ?\r
-                                        CV_NODE_MAP : CV_NODE_SEQ, node );\r
-    }\r
-\r
-    if( value_type != CV_NODE_NONE &&\r
-        value_type != CV_NODE_TYPE(node->tag) )\r
-        CV_PARSE_ERROR( "The actual type is different from the specified type" );\r
-\r
-    if( CV_NODE_IS_COLLECTION(node->tag) && is_simple )\r
-            node->data.seq->flags |= CV_NODE_SEQ_SIMPLE;\r
-\r
-    node->tag |= is_user_type ? CV_NODE_USER : 0;\r
-    return ptr;\r
-}\r
-\r
-\r
-static char*\r
-icvXMLParseTag( CvFileStorage* fs, char* ptr, CvStringHashNode** _tag,\r
-                CvAttrList** _list, int* _tag_type )\r
-{\r
-    int tag_type = 0;\r
-    CvStringHashNode* tagname = 0;\r
-    CvAttrList *first = 0, *last = 0;\r
-    int count = 0, max_count = 4;\r
-    int attr_buf_size = (max_count*2 + 1)*sizeof(char*) + sizeof(CvAttrList);\r
-    char* endptr;\r
-    char c;\r
-    int have_space;\r
-\r
-    if( *ptr != '<' )\r
-        CV_PARSE_ERROR( "Tag should start with \'<\'" );\r
-\r
-    ptr++;\r
-    if( isalnum(*ptr) || *ptr == '_' )\r
-        tag_type = CV_XML_OPENING_TAG;\r
-    else if( *ptr == '/' )\r
-    {\r
-        tag_type = CV_XML_CLOSING_TAG;\r
-        ptr++;\r
-    }\r
-    else if( *ptr == '?' )\r
-    {\r
-        tag_type = CV_XML_HEADER_TAG;\r
-        ptr++;\r
-    }\r
-    else if( *ptr == '!' )\r
-    {\r
-        tag_type = CV_XML_DIRECTIVE_TAG;\r
-        assert( ptr[1] != '-' || ptr[2] != '-' );\r
-        ptr++;\r
-    }\r
-    else\r
-        CV_PARSE_ERROR( "Unknown tag type" );\r
-\r
-    for(;;)\r
-    {\r
-        CvStringHashNode* attrname;\r
-\r
-        if( !isalpha(*ptr) && *ptr != '_' )\r
-            CV_PARSE_ERROR( "Name should start with a letter or underscore" );\r
-\r
-        endptr = ptr - 1;\r
-        do c = *++endptr;\r
-        while( isalnum(c) || c == '_' || c == '-' );\r
-\r
-        attrname = cvGetHashedKey( fs, ptr, (int)(endptr - ptr), 1 );\r
-        ptr = endptr;\r
-\r
-        if( !tagname )\r
-            tagname = attrname;\r
-        else\r
-        {\r
-            if( tag_type == CV_XML_CLOSING_TAG )\r
-                CV_PARSE_ERROR( "Closing tag should not contain any attributes" );\r
-\r
-            if( !last || count >= max_count )\r
-            {\r
-                CvAttrList* chunk;\r
-\r
-                chunk = (CvAttrList*)cvMemStorageAlloc( fs->memstorage, attr_buf_size );\r
-                memset( chunk, 0, attr_buf_size );\r
-                chunk->attr = (const char**)(chunk + 1);\r
-                count = 0;\r
-                if( !last )\r
-                    first = last = chunk;\r
-                else\r
-                    last = last->next = chunk;\r
-            }\r
-            last->attr[count*2] = attrname->str.ptr;\r
-        }\r
-\r
-        if( last )\r
-        {\r
-            CvFileNode stub;\r
-\r
-            if( *ptr != '=' )\r
-            {\r
-                ptr = icvXMLSkipSpaces( fs, ptr, CV_XML_INSIDE_TAG );\r
-                if( *ptr != '=' )\r
-                    CV_PARSE_ERROR( "Attribute name should be followed by \'=\'" );\r
-            }\r
-\r
-            c = *++ptr;\r
-            if( c != '\"' && c != '\'' )\r
-            {\r
-                ptr = icvXMLSkipSpaces( fs, ptr, CV_XML_INSIDE_TAG );\r
-                if( *ptr != '\"' && *ptr != '\'' )\r
-                    CV_PARSE_ERROR( "Attribute value should be put into single or double quotes" );\r
-            }\r
-\r
-            ptr = icvXMLParseValue( fs, ptr, &stub, CV_NODE_STRING );\r
-            assert( stub.tag == CV_NODE_STRING );\r
-            last->attr[count*2+1] = stub.data.str.ptr;\r
-            count++;\r
-        }\r
-\r
-        c = *ptr;\r
-        have_space = isspace(c) || c == '\0';\r
-\r
-        if( c != '>' )\r
-        {\r
-            ptr = icvXMLSkipSpaces( fs, ptr, CV_XML_INSIDE_TAG );\r
-            c = *ptr;\r
-        }\r
-\r
-        if( c == '>' )\r
-        {\r
-            if( tag_type == CV_XML_HEADER_TAG )\r
-                CV_PARSE_ERROR( "Invalid closing tag for <?xml ..." );\r
-            ptr++;\r
-            break;\r
-        }\r
-        else if( c == '?' && tag_type == CV_XML_HEADER_TAG )\r
-        {\r
-            if( ptr[1] != '>'  )\r
-                CV_PARSE_ERROR( "Invalid closing tag for <?xml ..." );\r
-            ptr += 2;\r
-            break;\r
-        }\r
-        else if( c == '/' && ptr[1] == '>' && tag_type == CV_XML_OPENING_TAG )\r
-        {\r
-            tag_type = CV_XML_EMPTY_TAG;\r
-            ptr += 2;\r
-            break;\r
-        }\r
-\r
-        if( !have_space )\r
-            CV_PARSE_ERROR( "There should be space between attributes" );\r
-    }\r
-\r
-    *_tag = tagname;\r
-    *_tag_type = tag_type;\r
-    *_list = first;\r
-\r
-    return ptr;\r
-}\r
-\r
-\r
-static void\r
-icvXMLParse( CvFileStorage* fs )\r
-{\r
-    char* ptr = fs->buffer_start;\r
-    CvStringHashNode *key = 0, *key2 = 0;\r
-    CvAttrList* list = 0;\r
-    int tag_type = 0;\r
-\r
-    // CV_XML_INSIDE_TAG is used to prohibit leading comments\r
-    ptr = icvXMLSkipSpaces( fs, ptr, CV_XML_INSIDE_TAG );\r
-\r
-    if( memcmp( ptr, "<?xml", 5 ) != 0 )\r
-        CV_PARSE_ERROR( "Valid XML should start with \'<?xml ...?>\'" );\r
-\r
-    ptr = icvXMLParseTag( fs, ptr, &key, &list, &tag_type );\r
-\r
-    /*{\r
-        const char* version = cvAttrValue( list, "version" );\r
-        if( version && strncmp( version, "1.", 2 ) != 0 )\r
-            CV_Error( CV_StsParseError, "Unsupported version of XML" );\r
-    }*/\r
-    {\r
-        const char* encoding = cvAttrValue( list, "encoding" );\r
-        if( encoding && strcmp( encoding, "ASCII" ) != 0 )\r
-            CV_PARSE_ERROR( "Unsupported encoding" );\r
-    }\r
-\r
-    while( *ptr != '\0' )\r
-    {\r
-        ptr = icvXMLSkipSpaces( fs, ptr, 0 );\r
-\r
-        if( *ptr != '\0' )\r
-        {\r
-            CvFileNode* root_node;\r
-            ptr = icvXMLParseTag( fs, ptr, &key, &list, &tag_type );\r
-            if( tag_type != CV_XML_OPENING_TAG ||\r
-                strcmp(key->str.ptr,"opencv_storage") != 0 )\r
-                CV_PARSE_ERROR( "<opencv_storage> tag is missing" );\r
-\r
-            root_node = (CvFileNode*)cvSeqPush( fs->roots, 0 );\r
-            ptr = icvXMLParseValue( fs, ptr, root_node, CV_NODE_NONE );\r
-            ptr = icvXMLParseTag( fs, ptr, &key2, &list, &tag_type );\r
-            if( tag_type != CV_XML_CLOSING_TAG || key != key2 )\r
-                CV_PARSE_ERROR( "</opencv_storage> tag is missing" );\r
-            ptr = icvXMLSkipSpaces( fs, ptr, 0 );\r
-        }\r
-    }\r
-\r
-    assert( fs->dummy_eof != 0 );\r
-}\r
-\r
-\r
-/****************************************************************************************\\r
-*                                       XML Emitter                                      *\r
-\****************************************************************************************/\r
-\r
-#define icvXMLFlush icvFSFlush\r
-\r
-static void\r
-icvXMLWriteTag( CvFileStorage* fs, const char* key, int tag_type, CvAttrList list )\r
-{\r
-    char* ptr = fs->buffer;\r
-    int i, len = 0;\r
-    int struct_flags = fs->struct_flags;\r
-\r
-    if( key && key[0] == '\0' )\r
-        key = 0;\r
-\r
-    if( tag_type == CV_XML_OPENING_TAG || tag_type == CV_XML_EMPTY_TAG )\r
-    {\r
-        if( CV_NODE_IS_COLLECTION(struct_flags) )\r
-        {\r
-            if( CV_NODE_IS_MAP(struct_flags) ^ (key != 0) )\r
-                CV_Error( CV_StsBadArg, "An attempt to add element without a key to a map, "\r
-                                        "or add element with key to sequence" );\r
-        }\r
-        else\r
-        {\r
-            struct_flags = CV_NODE_EMPTY + (key ? CV_NODE_MAP : CV_NODE_SEQ);\r
-            fs->is_first = 0;\r
-        }\r
-\r
-        if( !CV_NODE_IS_EMPTY(struct_flags) )\r
-            ptr = icvXMLFlush(fs);\r
-    }\r
-\r
-    if( !key )\r
-        key = "_";\r
-    else if( key[0] == '_' && key[1] == '\0' )\r
-        CV_Error( CV_StsBadArg, "A single _ is a reserved tag name" );\r
-\r
-    len = (int)strlen( key );\r
-    *ptr++ = '<';\r
-    if( tag_type == CV_XML_CLOSING_TAG )\r
-    {\r
-        if( list.attr )\r
-            CV_Error( CV_StsBadArg, "Closing tag should not include any attributes" );\r
-        *ptr++ = '/';\r
-    }\r
-\r
-    if( !isalpha(key[0]) && key[0] != '_' )\r
-        CV_Error( CV_StsBadArg, "Key should start with a letter or _" );\r
-\r
-    ptr = icvFSResizeWriteBuffer( fs, ptr, len );\r
-    for( i = 0; i < len; i++ )\r
-    {\r
-        char c = key[i];\r
-        if( !isalnum(c) && c != '_' && c != '-' )\r
-            CV_Error( CV_StsBadArg, "Key name may only contain alphanumeric characters [a-zA-Z0-9], '-' and '_'" );\r
-        ptr[i] = c;\r
-    }\r
-    ptr += len;\r
-\r
-    for(;;)\r
-    {\r
-        const char** attr = list.attr;\r
-\r
-        for( ; attr && attr[0] != 0; attr += 2 )\r
-        {\r
-            int len0 = (int)strlen(attr[0]);\r
-            int len1 = (int)strlen(attr[1]);\r
-\r
-            ptr = icvFSResizeWriteBuffer( fs, ptr, len0 + len1 + 4 );\r
-            *ptr++ = ' ';\r
-            memcpy( ptr, attr[0], len0 );\r
-            ptr += len0;\r
-            *ptr++ = '=';\r
-            *ptr++ = '\"';\r
-            memcpy( ptr, attr[1], len1 );\r
-            ptr += len1;\r
-            *ptr++ = '\"';\r
-        }\r
-        if( !list.next )\r
-            break;\r
-        list = *list.next;\r
-    }\r
-\r
-    if( tag_type == CV_XML_EMPTY_TAG )\r
-        *ptr++ = '/';\r
-    *ptr++ = '>';\r
-    fs->buffer = ptr;\r
-    fs->struct_flags = struct_flags & ~CV_NODE_EMPTY;\r
-}\r
-\r
-\r
-static void\r
-icvXMLStartWriteStruct( CvFileStorage* fs, const char* key, int struct_flags,\r
-                        const char* type_name CV_DEFAULT(0))\r
-{\r
-    CvXMLStackRecord parent;\r
-    const char* attr[10];\r
-    int idx = 0;\r
-\r
-    struct_flags = (struct_flags & (CV_NODE_TYPE_MASK|CV_NODE_FLOW)) | CV_NODE_EMPTY;\r
-    if( !CV_NODE_IS_COLLECTION(struct_flags))\r
-        CV_Error( CV_StsBadArg,\r
-        "Some collection type: CV_NODE_SEQ or CV_NODE_MAP must be specified" );\r
-\r
-    if( type_name )\r
-    {\r
-        attr[idx++] = "type_id";\r
-        attr[idx++] = type_name;\r
-    }\r
-    attr[idx++] = 0;\r
-\r
-    icvXMLWriteTag( fs, key, CV_XML_OPENING_TAG, cvAttrList(attr,0) );\r
-\r
-    parent.struct_flags = fs->struct_flags & ~CV_NODE_EMPTY;\r
-    parent.struct_indent = fs->struct_indent;\r
-    parent.struct_tag = fs->struct_tag;\r
-    cvSaveMemStoragePos( fs->strstorage, &parent.pos );\r
-    cvSeqPush( fs->write_stack, &parent );\r
-\r
-    fs->struct_indent += CV_XML_INDENT;\r
-    if( !CV_NODE_IS_FLOW(struct_flags) )\r
-        icvXMLFlush( fs );\r
-\r
-    fs->struct_flags = struct_flags;\r
-    if( key )\r
-    {\r
-        fs->struct_tag = cvMemStorageAllocString( fs->strstorage, (char*)key, -1 );\r
-    }\r
-    else\r
-    {\r
-        fs->struct_tag.ptr = 0;\r
-        fs->struct_tag.len = 0;\r
-    }\r
-}\r
-\r
-\r
-static void\r
-icvXMLEndWriteStruct( CvFileStorage* fs )\r
-{\r
-    CvXMLStackRecord parent;\r
-\r
-    if( fs->write_stack->total == 0 )\r
-        CV_Error( CV_StsError, "An extra closing tag" );\r
-\r
-    icvXMLWriteTag( fs, fs->struct_tag.ptr, CV_XML_CLOSING_TAG, cvAttrList(0,0) );\r
-    cvSeqPop( fs->write_stack, &parent );\r
-\r
-    fs->struct_indent = parent.struct_indent;\r
-    fs->struct_flags = parent.struct_flags;\r
-    fs->struct_tag = parent.struct_tag;\r
-    cvRestoreMemStoragePos( fs->strstorage, &parent.pos );\r
-}\r
-\r
-\r
-static void\r
-icvXMLStartNextStream( CvFileStorage* fs )\r
-{\r
-    if( !fs->is_first )\r
-    {\r
-        while( fs->write_stack->total > 0 )\r
-            icvXMLEndWriteStruct(fs);\r
-\r
-        fs->struct_indent = 0;\r
-        icvXMLFlush(fs);\r
-        /* XML does not allow multiple top-level elements,\r
-           so we just put a comment and continue\r
-           the current (and the only) "stream" */\r
-        fputs( "\n<!-- next stream -->\n", fs->file );\r
-        /*fputs( "</opencv_storage>\n", fs->file );\r
-        fputs( "<opencv_storage>\n", fs->file );*/\r
-        fs->buffer = fs->buffer_start;\r
-    }\r
-}\r
-\r
-\r
-static void\r
-icvXMLWriteScalar( CvFileStorage* fs, const char* key, const char* data, int len )\r
-{\r
-    if( CV_NODE_IS_MAP(fs->struct_flags) ||\r
-        (!CV_NODE_IS_COLLECTION(fs->struct_flags) && key) )\r
-    {\r
-        icvXMLWriteTag( fs, key, CV_XML_OPENING_TAG, cvAttrList(0,0) );\r
-        char* ptr = icvFSResizeWriteBuffer( fs, fs->buffer, len );\r
-        memcpy( ptr, data, len );\r
-        fs->buffer = ptr + len;\r
-        icvXMLWriteTag( fs, key, CV_XML_CLOSING_TAG, cvAttrList(0,0) );\r
-    }\r
-    else\r
-    {\r
-        char* ptr = fs->buffer;\r
-        int new_offset = (int)(ptr - fs->buffer_start) + len;\r
-\r
-        if( key )\r
-            CV_Error( CV_StsBadArg, "elements with keys can not be written to sequence" );\r
-\r
-        fs->struct_flags = CV_NODE_SEQ;\r
-\r
-        if( (new_offset > fs->wrap_margin && new_offset - fs->struct_indent > 10) ||\r
-            (ptr > fs->buffer_start && ptr[-1] == '>' && !CV_NODE_IS_EMPTY(fs->struct_flags)) )\r
-        {\r
-            ptr = icvXMLFlush(fs);\r
-        }\r
-        else if( ptr > fs->buffer_start + fs->struct_indent && ptr[-1] != '>' )\r
-            *ptr++ = ' ';\r
-\r
-        memcpy( ptr, data, len );\r
-        fs->buffer = ptr + len;\r
-    }\r
-}\r
-\r
-\r
-static void\r
-icvXMLWriteInt( CvFileStorage* fs, const char* key, int value )\r
-{\r
-    char buf[128], *ptr = icv_itoa( value, buf, 10 );\r
-    int len = (int)strlen(ptr);\r
-    icvXMLWriteScalar( fs, key, ptr, len );\r
-}\r
-\r
-\r
-static void\r
-icvXMLWriteReal( CvFileStorage* fs, const char* key, double value )\r
-{\r
-    char buf[128];\r
-    int len = (int)strlen( icvDoubleToString( buf, value ));\r
-    icvXMLWriteScalar( fs, key, buf, len );\r
-}\r
-\r
-\r
-static void\r
-icvXMLWriteString( CvFileStorage* fs, const char* key, const char* str, int quote )\r
-{\r
-    char buf[CV_FS_MAX_LEN*6+16];\r
-    char* data = (char*)str;\r
-    int i, len;\r
-\r
-    if( !str )\r
-        CV_Error( CV_StsNullPtr, "Null string pointer" );\r
-\r
-    len = (int)strlen(str);\r
-    if( len > CV_FS_MAX_LEN )\r
-        CV_Error( CV_StsBadArg, "The written string is too long" );\r
-\r
-    if( quote || len == 0 || str[0] != '\"' || str[0] != str[len-1] )\r
-    {\r
-        int need_quote = quote || len == 0;\r
-        data = buf;\r
-        *data++ = '\"';\r
-        for( i = 0; i < len; i++ )\r
-        {\r
-            char c = str[i];\r
-\r
-            if( !isalnum(c) && (!cv_isprint(c) || c == '<' || c == '>' ||\r
-                c == '&' || c == '\'' || c == '\"') )\r
-            {\r
-                *data++ = '&';\r
-                if( c == '<' )\r
-                {\r
-                    memcpy(data, "lt", 2);\r
-                    data += 2;\r
-                }\r
-                else if( c == '>' )\r
-                {\r
-                    memcpy(data, "gt", 2);\r
-                    data += 2;\r
-                }\r
-                else if( c == '&' )\r
-                {\r
-                    memcpy(data, "amp", 3);\r
-                    data += 3;\r
-                }\r
-                else if( c == '\'' )\r
-                {\r
-                    memcpy(data, "apos", 4);\r
-                    data += 4;\r
-                }\r
-                else if( c == '\"' )\r
-                {\r
-                    memcpy( data, "quot", 4);\r
-                    data += 4;\r
-                }\r
-                else\r
-                {\r
-                    sprintf( data, "#x%02x", c );\r
-                    data += 4;\r
-                }\r
-                *data++ = ';';\r
-            }\r
-            else\r
-            {\r
-                if( c == ' ' )\r
-                    need_quote = 1;\r
-                *data++ = c;\r
-            }\r
-        }\r
-        if( !need_quote && (isdigit(str[0]) ||\r
-            str[0] == '+' || str[0] == '-' || str[0] == '.' ))\r
-            need_quote = 1;\r
-\r
-        if( need_quote )\r
-            *data++ = '\"';\r
-        len = (int)(data - buf) - !need_quote;\r
-        *data++ = '\0';\r
-        data = buf + !need_quote;\r
-    }\r
-\r
-    icvXMLWriteScalar( fs, key, data, len );\r
-}\r
-\r
-\r
-static void\r
-icvXMLWriteComment( CvFileStorage* fs, const char* comment, int eol_comment )\r
-{\r
-    int len;\r
-    int multiline;\r
-    const char* eol;\r
-    char* ptr;\r
-\r
-    if( !comment )\r
-        CV_Error( CV_StsNullPtr, "Null comment" );\r
-\r
-    if( strstr(comment, "--") != 0 )\r
-        CV_Error( CV_StsBadArg, "Double hyphen \'--\' is not allowed in the comments" );\r
-\r
-    len = (int)strlen(comment);\r
-    eol = strchr(comment, '\n');\r
-    multiline = eol != 0;\r
-    ptr = fs->buffer;\r
-\r
-    if( multiline || !eol_comment || fs->buffer_end - ptr < len + 5 )\r
-        ptr = icvXMLFlush( fs );\r
-    else if( ptr > fs->buffer_start + fs->struct_indent )\r
-        *ptr++ = ' ';\r
-\r
-    if( !multiline )\r
-    {\r
-        ptr = icvFSResizeWriteBuffer( fs, ptr, len + 9 );\r
-        sprintf( ptr, "<!-- %s -->", comment );\r
-        len = (int)strlen(ptr);\r
-    }\r
-    else\r
-    {\r
-        strcpy( ptr, "<!--" );\r
-        len = 4;\r
-    }\r
-\r
-    fs->buffer = ptr + len;\r
-    ptr = icvXMLFlush(fs);\r
-\r
-    if( multiline )\r
-    {\r
-        while( comment )\r
-        {\r
-            if( eol )\r
-            {\r
-                ptr = icvFSResizeWriteBuffer( fs, ptr, (int)(eol - comment) + 1 );\r
-                memcpy( ptr, comment, eol - comment + 1 );\r
-                ptr += eol - comment;\r
-                comment = eol + 1;\r
-                eol = strchr( comment, '\n' );\r
-            }\r
-            else\r
-            {\r
-                len = (int)strlen(comment);\r
-                ptr = icvFSResizeWriteBuffer( fs, ptr, len );\r
-                memcpy( ptr, comment, len );\r
-                ptr += len;\r
-                comment = 0;\r
-            }\r
-            fs->buffer = ptr;\r
-            ptr = icvXMLFlush( fs );\r
-        }\r
-        sprintf( ptr, "-->" );\r
-        fs->buffer = ptr + 3;\r
-        icvXMLFlush( fs );\r
-    }\r
-}\r
-\r
-\r
-/****************************************************************************************\\r
-*                              Common High-Level Functions                               *\r
-\****************************************************************************************/\r
-\r
-CV_IMPL CvFileStorage*\r
-cvOpenFileStorage( const char* filename, CvMemStorage* dststorage, int flags )\r
-{\r
-    CvFileStorage* fs = 0;\r
-    char* xml_buf = 0;\r
-    int default_block_size = 1 << 18;\r
-    bool append = (flags & 3) == CV_STORAGE_APPEND;\r
-\r
-    if( !filename )\r
-        CV_Error( CV_StsNullPtr, "NULL filename" );\r
-\r
-    fs = (CvFileStorage*)cvAlloc( sizeof(*fs) );\r
-    memset( fs, 0, sizeof(*fs));\r
-\r
-    fs->memstorage = cvCreateMemStorage( default_block_size );\r
-    fs->dststorage = dststorage ? dststorage : fs->memstorage;\r
-\r
-    fs->filename = (char*)cvMemStorageAlloc( fs->memstorage, strlen(filename)+1 );\r
-    strcpy( fs->filename, filename );\r
-\r
-    fs->flags = CV_FILE_STORAGE;\r
-    fs->write_mode = (flags & 3) != 0;\r
-#ifdef WIN32\r
-    fs->file = _wfopen( cv::toUtf16(fs->filename).c_str(), !fs->write_mode ? L"rt" : !append ? L"wt" : L"a+t" );\r
-#else\r
-    fs->file = fopen(fs->filename, !fs->write_mode ? "rt" : !append ? "wt" : "a+t" );\r
-#endif\r
-    if( !fs->file )\r
-        goto _exit_;\r
-\r
-    fs->roots = 0;\r
-    fs->struct_indent = 0;\r
-    fs->struct_flags = 0;\r
-    fs->wrap_margin = 71;\r
-\r
-    if( fs->write_mode )\r
-    {\r
-        // we use factor=6 for XML (the longest characters (' and ") are encoded with 6 bytes (&apos; and &quot;)\r
-        // and factor=4 for YAML ( as we use 4 bytes for non ASCII characters (e.g. \xAB))\r
-        int buf_size = CV_FS_MAX_LEN*(fs->is_xml ? 6 : 4) + 1024;\r
-\r
-        char* dot_pos = strrchr( fs->filename, '.' );\r
-        fs->is_xml = dot_pos && (strcmp( dot_pos, ".xml" ) == 0 ||\r
-                      strcmp( dot_pos, ".XML" ) == 0 || strcmp( dot_pos, ".Xml" ) == 0);\r
-\r
-        if( append )\r
-            fseek( fs->file, 0, SEEK_END );\r
-\r
-        fs->write_stack = cvCreateSeq( 0, sizeof(CvSeq), fs->is_xml ?\r
-                sizeof(CvXMLStackRecord) : sizeof(int), fs->memstorage );\r
-        fs->is_first = 1;\r
-        fs->struct_indent = 0;\r
-        fs->struct_flags = CV_NODE_EMPTY;\r
-        fs->buffer_start = fs->buffer = (char*)cvAlloc( buf_size + 1024 );\r
-        fs->buffer_end = fs->buffer_start + buf_size;\r
-        if( fs->is_xml )\r
-        {\r
-            int file_size = (int)ftell( fs->file );\r
-            fs->strstorage = cvCreateChildMemStorage( fs->memstorage );\r
-            if( !append || file_size == 0 )\r
-            {\r
-                fputs( "<?xml version=\"1.0\"?>\n", fs->file );\r
-                fputs( "<opencv_storage>\n", fs->file );\r
-            }\r
-            else\r
-            {\r
-                int xml_buf_size = 1 << 10;\r
-                char substr[] = "</opencv_storage>";\r
-                int last_occurence = -1;\r
-                xml_buf_size = MIN(xml_buf_size, file_size);\r
-                fseek( fs->file, -xml_buf_size, SEEK_END );\r
-                xml_buf = (char*)cvAlloc( xml_buf_size+2 );\r
-                // find the last occurence of </opencv_storage>\r
-                for(;;)\r
-                {\r
-                    int line_offset = ftell( fs->file );\r
-                    char* ptr0 = fgets( xml_buf, xml_buf_size, fs->file ), *ptr;\r
-                    if( !ptr0 )\r
-                        break;\r
-                    ptr = ptr0;\r
-                    for(;;)\r
-                    {\r
-                        ptr = strstr( ptr, substr );\r
-                        if( !ptr )\r
-                            break;\r
-                        last_occurence = line_offset + (int)(ptr - ptr0);\r
-                        ptr += strlen(substr);\r
-                    }\r
-                }\r
-                if( last_occurence < 0 )\r
-                    CV_Error( CV_StsError, "Could not find </opencv_storage> in the end of file.\n" );\r
-                fclose( fs->file );\r
-            #ifdef WIN32\r
-                fs->file = _wfopen( cv::toUtf16(fs->filename).c_str(), L"r+t" );\r
-            #else\r
-                fs->file = fopen( fs->filename, "r+t" );\r
-            #endif\r
-                fseek( fs->file, last_occurence, SEEK_SET );\r
-                // replace the last "</opencv_storage>" with " <!-- resumed -->", which has the same length\r
-                fputs( " <!-- resumed -->", fs->file );\r
-                fseek( fs->file, 0, SEEK_END );\r
-                fputs( "\n", fs->file );\r
-            }\r
-            fs->start_write_struct = icvXMLStartWriteStruct;\r
-            fs->end_write_struct = icvXMLEndWriteStruct;\r
-            fs->write_int = icvXMLWriteInt;\r
-            fs->write_real = icvXMLWriteReal;\r
-            fs->write_string = icvXMLWriteString;\r
-            fs->write_comment = icvXMLWriteComment;\r
-            fs->start_next_stream = icvXMLStartNextStream;\r
-        }\r
-        else\r
-        {\r
-            if( !append )\r
-                fputs( "%YAML:1.0\n", fs->file );\r
-            else\r
-                fputs( "...\n---\n", fs->file );\r
-            fs->start_write_struct = icvYMLStartWriteStruct;\r
-            fs->end_write_struct = icvYMLEndWriteStruct;\r
-            fs->write_int = icvYMLWriteInt;\r
-            fs->write_real = icvYMLWriteReal;\r
-            fs->write_string = icvYMLWriteString;\r
-            fs->write_comment = icvYMLWriteComment;\r
-            fs->start_next_stream = icvYMLStartNextStream;\r
-        }\r
-    }\r
-    else\r
-    {\r
-        int buf_size;\r
-        const char* yaml_signature = "%YAML:";\r
-        char buf[16];\r
-        fgets( buf, sizeof(buf)-2, fs->file );\r
-        fs->is_xml = strncmp( buf, yaml_signature, strlen(yaml_signature) ) != 0;\r
-\r
-        fseek( fs->file, 0, SEEK_END );\r
-        buf_size = ftell( fs->file );\r
-        fseek( fs->file, 0, SEEK_SET );\r
-\r
-        buf_size = MIN( buf_size, (1 << 20) );\r
-        buf_size = MAX( buf_size, CV_FS_MAX_LEN*2 + 1024 );\r
-\r
-        fs->str_hash = cvCreateMap( 0, sizeof(CvStringHash),\r
-                        sizeof(CvStringHashNode), fs->memstorage, 256 );\r
-\r
-        fs->roots = cvCreateSeq( 0, sizeof(CvSeq),\r
-                        sizeof(CvFileNode), fs->memstorage );\r
-\r
-        fs->buffer = fs->buffer_start = (char*)cvAlloc( buf_size + 256 );\r
-        fs->buffer_end = fs->buffer_start + buf_size;\r
-        fs->buffer[0] = '\n';\r
-        fs->buffer[1] = '\0';\r
-\r
-        //mode = cvGetErrMode();\r
-        //cvSetErrMode( CV_ErrModeSilent );\r
-        if( fs->is_xml )\r
-            icvXMLParse( fs );\r
-        else\r
-            icvYMLParse( fs );\r
-        //cvSetErrMode( mode );\r
-\r
-        // release resources that we do not need anymore\r
-        cvFree( &fs->buffer_start );\r
-        fs->buffer = fs->buffer_end = 0;\r
-    }\r
-_exit_:\r
-    if( fs )\r
-    {\r
-        if( cvGetErrStatus() < 0 || !fs->file )\r
-        {\r
-            cvReleaseFileStorage( &fs );\r
-        }\r
-        else if( !fs->write_mode )\r
-        {\r
-            fclose( fs->file );\r
-            fs->file = 0;\r
-        }\r
-    }\r
-\r
-    cvFree( &xml_buf );\r
-    return  fs;\r
-}\r
-\r
-\r
-CV_IMPL void\r
-cvStartWriteStruct( CvFileStorage* fs, const char* key, int struct_flags,\r
-                    const char* type_name, CvAttrList /*attributes*/ )\r
-{\r
-    CV_CHECK_OUTPUT_FILE_STORAGE(fs);\r
-    fs->start_write_struct( fs, key, struct_flags, type_name );\r
-}\r
-\r
-\r
-CV_IMPL void\r
-cvEndWriteStruct( CvFileStorage* fs )\r
-{\r
-    CV_CHECK_OUTPUT_FILE_STORAGE(fs);\r
-    fs->end_write_struct( fs );\r
-}\r
-\r
-\r
-CV_IMPL void\r
-cvWriteInt( CvFileStorage* fs, const char* key, int value )\r
-{\r
-    CV_CHECK_OUTPUT_FILE_STORAGE(fs);\r
-    fs->write_int( fs, key, value );\r
-}\r
-\r
-\r
-CV_IMPL void\r
-cvWriteReal( CvFileStorage* fs, const char* key, double value )\r
-{\r
-    CV_CHECK_OUTPUT_FILE_STORAGE(fs);\r
-    fs->write_real( fs, key, value );\r
-}\r
-\r
-\r
-CV_IMPL void\r
-cvWriteString( CvFileStorage* fs, const char* key, const char* value, int quote )\r
-{\r
-    CV_CHECK_OUTPUT_FILE_STORAGE(fs);\r
-    fs->write_string( fs, key, value, quote );\r
-}\r
-\r
-\r
-CV_IMPL void\r
-cvWriteComment( CvFileStorage* fs, const char* comment, int eol_comment )\r
-{\r
-    CV_CHECK_OUTPUT_FILE_STORAGE(fs);\r
-    fs->write_comment( fs, comment, eol_comment );\r
-}\r
-\r
-\r
-CV_IMPL void\r
-cvStartNextStream( CvFileStorage* fs )\r
-{\r
-    CV_CHECK_OUTPUT_FILE_STORAGE(fs);\r
-    fs->start_next_stream( fs );\r
-}\r
-\r
-\r
-static const char icvTypeSymbol[] = "ucwsifdr";\r
-#define CV_FS_MAX_FMT_PAIRS  128\r
-\r
-static char*\r
-icvEncodeFormat( int elem_type, char* dt )\r
-{\r
-    sprintf( dt, "%d%c", CV_MAT_CN(elem_type), icvTypeSymbol[CV_MAT_DEPTH(elem_type)] );\r
-    return dt + ( dt[2] == '\0' && dt[0] == '1' );\r
-}\r
-\r
-static int\r
-icvDecodeFormat( const char* dt, int* fmt_pairs, int max_len )\r
-{\r
-    int fmt_pair_count = 0;\r
-    int i = 0, k = 0, len = dt ? (int)strlen(dt) : 0;\r
-\r
-    if( !dt || !len )\r
-        return 0;\r
-\r
-    assert( fmt_pairs != 0 && max_len > 0 );\r
-    fmt_pairs[0] = 0;\r
-    max_len *= 2;\r
-\r
-    for( ; k < len; k++ )\r
-    {\r
-        char c = dt[k];\r
-\r
-        if( isdigit(c) )\r
-        {\r
-            int count = c - '0';\r
-            if( isdigit(dt[k+1]) )\r
-            {\r
-                char* endptr = 0;\r
-                count = (int)strtol( dt+k, &endptr, 10 );\r
-                k = (int)(endptr - dt) - 1;\r
-            }\r
-\r
-            if( count <= 0 )\r
-                CV_Error( CV_StsBadArg, "Invalid data type specification" );\r
-\r
-            fmt_pairs[i] = count;\r
-        }\r
-        else\r
-        {\r
-            const char* pos = strchr( icvTypeSymbol, c );\r
-            if( !pos )\r
-                CV_Error( CV_StsBadArg, "Invalid data type specification" );\r
-            if( fmt_pairs[i] == 0 )\r
-                fmt_pairs[i] = 1;\r
-            fmt_pairs[i+1] = (int)(pos - icvTypeSymbol);\r
-            if( i > 0 && fmt_pairs[i+1] == fmt_pairs[i-1] )\r
-                fmt_pairs[i-2] += fmt_pairs[i];\r
-            else\r
-            {\r
-                i += 2;\r
-                if( i >= max_len )\r
-                    CV_Error( CV_StsBadArg, "Too long data type specification" );\r
-            }\r
-            fmt_pairs[i] = 0;\r
-        }\r
-    }\r
-\r
-    fmt_pair_count = i/2;\r
-    return fmt_pair_count;\r
-}\r
-\r
-\r
-static int\r
-icvCalcElemSize( const char* dt, int initial_size )\r
-{\r
-    int size = 0;\r
-    int fmt_pairs[CV_FS_MAX_FMT_PAIRS], i, fmt_pair_count;\r
-    int comp_size;\r
-\r
-    fmt_pair_count = icvDecodeFormat( dt, fmt_pairs, CV_FS_MAX_FMT_PAIRS );\r
-    fmt_pair_count *= 2;\r
-    for( i = 0, size = initial_size; i < fmt_pair_count; i += 2 )\r
-    {\r
-        comp_size = CV_ELEM_SIZE(fmt_pairs[i+1]);\r
-        size = cvAlign( size, comp_size );\r
-        size += comp_size * fmt_pairs[i];\r
-    }\r
-    if( initial_size == 0 )\r
-    {\r
-        comp_size = CV_ELEM_SIZE(fmt_pairs[1]);\r
-        size = cvAlign( size, comp_size );\r
-    }\r
-    return size;\r
-}\r
-\r
-\r
-static int\r
-icvDecodeSimpleFormat( const char* dt )\r
-{\r
-    int elem_type = -1;\r
-    int fmt_pairs[CV_FS_MAX_FMT_PAIRS], fmt_pair_count;\r
-\r
-    fmt_pair_count = icvDecodeFormat( dt, fmt_pairs, CV_FS_MAX_FMT_PAIRS );\r
-    if( fmt_pair_count != 1 || fmt_pairs[0] > 4 )\r
-        CV_Error( CV_StsError, "Too complex format for the matrix" );\r
-\r
-    elem_type = CV_MAKETYPE( fmt_pairs[1], fmt_pairs[0] );\r
-\r
-    return elem_type;\r
-}\r
-\r
-\r
-CV_IMPL void\r
-cvWriteRawData( CvFileStorage* fs, const void* _data, int len, const char* dt )\r
-{\r
-    const char* data0 = (const char*)_data;\r
-    int offset = 0;\r
-    int fmt_pairs[CV_FS_MAX_FMT_PAIRS*2], k, fmt_pair_count;\r
-    char buf[256] = "";\r
-\r
-    CV_CHECK_OUTPUT_FILE_STORAGE( fs );\r
-\r
-    if( !data0 )\r
-        CV_Error( CV_StsNullPtr, "Null data pointer" );\r
-\r
-    if( len < 0 )\r
-        CV_Error( CV_StsOutOfRange, "Negative number of elements" );\r
-\r
-    fmt_pair_count = icvDecodeFormat( dt, fmt_pairs, CV_FS_MAX_FMT_PAIRS );\r
-\r
-    if( !len )\r
-        return;\r
-\r
-    if( fmt_pair_count == 1 )\r
-    {\r
-        fmt_pairs[0] *= len;\r
-        len = 1;\r
-    }\r
-\r
-    for(;len--;)\r
-    {\r
-        for( k = 0; k < fmt_pair_count; k++ )\r
-        {\r
-            int i, count = fmt_pairs[k*2];\r
-            int elem_type = fmt_pairs[k*2+1];\r
-            int elem_size = CV_ELEM_SIZE(elem_type);\r
-            const char* data, *ptr;\r
-\r
-            offset = cvAlign( offset, elem_size );\r
-            data = data0 + offset;\r
-\r
-            for( i = 0; i < count; i++ )\r
-            {\r
-                switch( elem_type )\r
-                {\r
-                case CV_8U:\r
-                    ptr = icv_itoa( *(uchar*)data, buf, 10 );\r
-                    data++;\r
-                    break;\r
-                case CV_8S:\r
-                    ptr = icv_itoa( *(char*)data, buf, 10 );\r
-                    data++;\r
-                    break;\r
-                case CV_16U:\r
-                    ptr = icv_itoa( *(ushort*)data, buf, 10 );\r
-                    data += sizeof(ushort);\r
-                    break;\r
-                case CV_16S:\r
-                    ptr = icv_itoa( *(short*)data, buf, 10 );\r
-                    data += sizeof(short);\r
-                    break;\r
-                case CV_32S:\r
-                    ptr = icv_itoa( *(int*)data, buf, 10 );\r
-                    data += sizeof(int);\r
-                    break;\r
-                case CV_32F:\r
-                    ptr = icvFloatToString( buf, *(float*)data );\r
-                    data += sizeof(float);\r
-                    break;\r
-                case CV_64F:\r
-                    ptr = icvDoubleToString( buf, *(double*)data );\r
-                    data += sizeof(double);\r
-                    break;\r
-                case CV_USRTYPE1: /* reference */\r
-                    ptr = icv_itoa( (int)*(size_t*)data, buf, 10 );\r
-                    data += sizeof(size_t);\r
-                    break;\r
-                default:\r
-                    assert(0);\r
-                    return;\r
-                }\r
-\r
-                if( fs->is_xml )\r
-                {\r
-                    int buf_len = (int)strlen(ptr);\r
-                    icvXMLWriteScalar( fs, 0, ptr, buf_len );\r
-                }\r
-                else\r
-                    icvYMLWrite( fs, 0, ptr );\r
-            }\r
-\r
-            offset = (int)(data - data0);\r
-        }\r
-    }\r
-}\r
-\r
-\r
-CV_IMPL void\r
-cvStartReadRawData( const CvFileStorage* fs, const CvFileNode* src, CvSeqReader* reader )\r
-{\r
-    int node_type;\r
-    CV_CHECK_FILE_STORAGE( fs );\r
-\r
-    if( !src || !reader )\r
-        CV_Error( CV_StsNullPtr, "Null pointer to source file node or reader" );\r
-\r
-    node_type = CV_NODE_TYPE(src->tag);\r
-    if( node_type == CV_NODE_INT || node_type == CV_NODE_REAL )\r
-    {\r
-        // emulate reading from 1-element sequence\r
-        reader->ptr = (schar*)src;\r
-        reader->block_max = reader->ptr + sizeof(*src)*2;\r
-        reader->block_min = reader->ptr;\r
-        reader->seq = 0;\r
-    }\r
-    else if( node_type == CV_NODE_SEQ )\r
-    {\r
-        cvStartReadSeq( src->data.seq, reader, 0 );\r
-    }\r
-    else if( node_type == CV_NODE_NONE )\r
-    {\r
-        memset( reader, 0, sizeof(*reader) );\r
-    }\r
-    else\r
-        CV_Error( CV_StsBadArg, "The file node should be a numerical scalar or a sequence" );\r
-}\r
-\r
-\r
-CV_IMPL void\r
-cvReadRawDataSlice( const CvFileStorage* fs, CvSeqReader* reader,\r
-                    int len, void* _data, const char* dt )\r
-{\r
-    char* data0 = (char*)_data;\r
-    int fmt_pairs[CV_FS_MAX_FMT_PAIRS*2], k = 0, fmt_pair_count;\r
-    int i = 0, offset = 0, count = 0;\r
-\r
-    CV_CHECK_FILE_STORAGE( fs );\r
-\r
-    if( !reader || !data0 )\r
-        CV_Error( CV_StsNullPtr, "Null pointer to reader or destination array" );\r
-\r
-    if( !reader->seq && len != 1 )\r
-        CV_Error( CV_StsBadSize, "The readed sequence is a scalar, thus len must be 1" );\r
-\r
-    fmt_pair_count = icvDecodeFormat( dt, fmt_pairs, CV_FS_MAX_FMT_PAIRS );\r
-\r
-    for(;;)\r
-    {\r
-        for( k = 0; k < fmt_pair_count; k++ )\r
-        {\r
-            int elem_type = fmt_pairs[k*2+1];\r
-            int elem_size = CV_ELEM_SIZE(elem_type);\r
-            char* data;\r
-\r
-            count = fmt_pairs[k*2];\r
-            offset = cvAlign( offset, elem_size );\r
-            data = data0 + offset;\r
-\r
-            for( i = 0; i < count; i++ )\r
-            {\r
-                CvFileNode* node = (CvFileNode*)reader->ptr;\r
-                if( CV_NODE_IS_INT(node->tag) )\r
-                {\r
-                    int ival = node->data.i;\r
-\r
-                    switch( elem_type )\r
-                    {\r
-                    case CV_8U:\r
-                        *(uchar*)data = CV_CAST_8U(ival);\r
-                        data++;\r
-                        break;\r
-                    case CV_8S:\r
-                        *(char*)data = CV_CAST_8S(ival);\r
-                        data++;\r
-                        break;\r
-                    case CV_16U:\r
-                        *(ushort*)data = CV_CAST_16U(ival);\r
-                        data += sizeof(ushort);\r
-                        break;\r
-                    case CV_16S:\r
-                        *(short*)data = CV_CAST_16S(ival);\r
-                        data += sizeof(short);\r
-                        break;\r
-                    case CV_32S:\r
-                        *(int*)data = ival;\r
-                        data += sizeof(int);\r
-                        break;\r
-                    case CV_32F:\r
-                        *(float*)data = (float)ival;\r
-                        data += sizeof(float);\r
-                        break;\r
-                    case CV_64F:\r
-                        *(double*)data = (double)ival;\r
-                        data += sizeof(double);\r
-                        break;\r
-                    case CV_USRTYPE1: /* reference */\r
-                        *(size_t*)data = ival;\r
-                        data += sizeof(size_t);\r
-                        break;\r
-                    default:\r
-                        assert(0);\r
-                        return;\r
-                    }\r
-                }\r
-                else if( CV_NODE_IS_REAL(node->tag) )\r
-                {\r
-                    double fval = node->data.f;\r
-                    int ival;\r
-\r
-                    switch( elem_type )\r
-                    {\r
-                    case CV_8U:\r
-                        ival = cvRound(fval);\r
-                        *(uchar*)data = CV_CAST_8U(ival);\r
-                        data++;\r
-                        break;\r
-                    case CV_8S:\r
-                        ival = cvRound(fval);\r
-                        *(char*)data = CV_CAST_8S(ival);\r
-                        data++;\r
-                        break;\r
-                    case CV_16U:\r
-                        ival = cvRound(fval);\r
-                        *(ushort*)data = CV_CAST_16U(ival);\r
-                        data += sizeof(ushort);\r
-                        break;\r
-                    case CV_16S:\r
-                        ival = cvRound(fval);\r
-                        *(short*)data = CV_CAST_16S(ival);\r
-                        data += sizeof(short);\r
-                        break;\r
-                    case CV_32S:\r
-                        ival = cvRound(fval);\r
-                        *(int*)data = ival;\r
-                        data += sizeof(int);\r
-                        break;\r
-                    case CV_32F:\r
-                        *(float*)data = (float)fval;\r
-                        data += sizeof(float);\r
-                        break;\r
-                    case CV_64F:\r
-                        *(double*)data = fval;\r
-                        data += sizeof(double);\r
-                        break;\r
-                    case CV_USRTYPE1: /* reference */\r
-                        ival = cvRound(fval);\r
-                        *(size_t*)data = ival;\r
-                        data += sizeof(size_t);\r
-                        break;\r
-                    default:\r
-                        assert(0);\r
-                        return;\r
-                    }\r
-                }\r
-                else\r
-                    CV_Error( CV_StsError,\r
-                    "The sequence element is not a numerical scalar" );\r
-\r
-                CV_NEXT_SEQ_ELEM( sizeof(CvFileNode), *reader );\r
-                if( !--len )\r
-                    goto end_loop;\r
-            }\r
-\r
-            offset = (int)(data - data0);\r
-        }\r
-    }\r
-\r
-end_loop:\r
-    if( i != count - 1 || k != fmt_pair_count - 1 )\r
-        CV_Error( CV_StsBadSize,\r
-        "The sequence slice does not fit an integer number of records" );\r
-\r
-    if( !reader->seq )\r
-        reader->ptr -= sizeof(CvFileNode);\r
-}\r
-\r
-\r
-CV_IMPL void\r
-cvReadRawData( const CvFileStorage* fs, const CvFileNode* src,\r
-               void* data, const char* dt )\r
-{\r
-    CvSeqReader reader;\r
-\r
-    if( !src || !data )\r
-        CV_Error( CV_StsNullPtr, "Null pointers to source file node or destination array" );\r
-\r
-    cvStartReadRawData( fs, src, &reader );\r
-    cvReadRawDataSlice( fs, &reader, CV_NODE_IS_SEQ(src->tag) ?\r
-                        src->data.seq->total : 1, data, dt );\r
-}\r
-\r
-\r
-static void\r
-icvWriteFileNode( CvFileStorage* fs, const char* name, const CvFileNode* node );\r
-\r
-static void\r
-icvWriteCollection( CvFileStorage* fs, const CvFileNode* node )\r
-{\r
-    int i, total = node->data.seq->total;\r
-    int elem_size = node->data.seq->elem_size;\r
-    int is_map = CV_NODE_IS_MAP(node->tag);\r
-    CvSeqReader reader;\r
-\r
-    cvStartReadSeq( node->data.seq, &reader, 0 );\r
-\r
-    for( i = 0; i < total; i++ )\r
-    {\r
-        CvFileMapNode* elem = (CvFileMapNode*)reader.ptr;\r
-        if( !is_map || CV_IS_SET_ELEM(elem) )\r
-        {\r
-            const char* name = is_map ? elem->key->str.ptr : 0;\r
-            icvWriteFileNode( fs, name, &elem->value );\r
-        }\r
-        CV_NEXT_SEQ_ELEM( elem_size, reader );\r
-    }\r
-}\r
-\r
-static void\r
-icvWriteFileNode( CvFileStorage* fs, const char* name, const CvFileNode* node )\r
-{\r
-    switch( CV_NODE_TYPE(node->tag) )\r
-    {\r
-    case CV_NODE_INT:\r
-        fs->write_int( fs, name, node->data.i );\r
-        break;\r
-    case CV_NODE_REAL:\r
-        fs->write_real( fs, name, node->data.f );\r
-        break;\r
-    case CV_NODE_STR:\r
-        fs->write_string( fs, name, node->data.str.ptr, 0 );\r
-        break;\r
-    case CV_NODE_SEQ:\r
-    case CV_NODE_MAP:\r
-        fs->start_write_struct( fs, name, CV_NODE_TYPE(node->tag) +\r
-                (CV_NODE_SEQ_IS_SIMPLE(node->data.seq) ? CV_NODE_FLOW : 0),\r
-                node->info ? node->info->type_name : 0 );\r
-        icvWriteCollection( fs, node );\r
-        fs->end_write_struct( fs );\r
-        break;\r
-    case CV_NODE_NONE:\r
-        fs->start_write_struct( fs, name, CV_NODE_SEQ, 0 );\r
-        fs->end_write_struct( fs );\r
-        break;\r
-    default:\r
-        CV_Error( CV_StsBadFlag, "Unknown type of file node" );\r
-    }\r
-}\r
-\r
-\r
-CV_IMPL void\r
-cvWriteFileNode( CvFileStorage* fs, const char* new_node_name,\r
-                 const CvFileNode* node, int embed )\r
-{\r
-    CvFileStorage* dst = 0;\r
-    CV_CHECK_OUTPUT_FILE_STORAGE(fs);\r
-\r
-    if( !node )\r
-        return;\r
-\r
-    if( CV_NODE_IS_COLLECTION(node->tag) && embed )\r
-    {\r
-        icvWriteCollection( fs, node );\r
-    }\r
-    else\r
-    {\r
-        icvWriteFileNode( fs, new_node_name, node );\r
-    }\r
-    /*\r
-    int i, stream_count;\r
-    stream_count = fs->roots->total;\r
-    for( i = 0; i < stream_count; i++ )\r
-    {\r
-        CvFileNode* node = (CvFileNode*)cvGetSeqElem( fs->roots, i, 0 );\r
-        icvDumpCollection( dst, node );\r
-        if( i < stream_count - 1 )\r
-            dst->start_next_stream( dst );\r
-    }*/\r
-    cvReleaseFileStorage( &dst );\r
-}\r
-\r
-\r
-CV_IMPL const char*\r
-cvGetFileNodeName( const CvFileNode* file_node )\r
-{\r
-    return file_node && CV_NODE_HAS_NAME(file_node->tag) ?\r
-        ((CvFileMapNode*)file_node)->key->str.ptr : 0;\r
-}\r
-\r
-/****************************************************************************************\\r
-*                          Reading/Writing etc. for standard types                       *\r
-\****************************************************************************************/\r
-\r
-/*#define CV_TYPE_NAME_MAT "opencv-matrix"\r
-#define CV_TYPE_NAME_MATND "opencv-nd-matrix"\r
-#define CV_TYPE_NAME_SPARSE_MAT "opencv-sparse-matrix"\r
-#define CV_TYPE_NAME_IMAGE "opencv-image"\r
-#define CV_TYPE_NAME_SEQ "opencv-sequence"\r
-#define CV_TYPE_NAME_SEQ_TREE "opencv-sequence-tree"\r
-#define CV_TYPE_NAME_GRAPH "opencv-graph"*/\r
-\r
-/******************************* CvMat ******************************/\r
-\r
-static int\r
-icvIsMat( const void* ptr )\r
-{\r
-    return CV_IS_MAT_HDR(ptr);\r
-}\r
-\r
-static void\r
-icvWriteMat( CvFileStorage* fs, const char* name,\r
-             const void* struct_ptr, CvAttrList /*attr*/ )\r
-{\r
-    const CvMat* mat = (const CvMat*)struct_ptr;\r
-    char dt[16];\r
-    CvSize size;\r
-    int y;\r
-\r
-    assert( CV_IS_MAT(mat) );\r
-\r
-    cvStartWriteStruct( fs, name, CV_NODE_MAP, CV_TYPE_NAME_MAT );\r
-    cvWriteInt( fs, "rows", mat->rows );\r
-    cvWriteInt( fs, "cols", mat->cols );\r
-    cvWriteString( fs, "dt", icvEncodeFormat( CV_MAT_TYPE(mat->type), dt ), 0 );\r
-    cvStartWriteStruct( fs, "data", CV_NODE_SEQ + CV_NODE_FLOW );\r
-\r
-    size = cvGetSize(mat);\r
-    if( CV_IS_MAT_CONT(mat->type) )\r
-    {\r
-        size.width *= size.height;\r
-        size.height = 1;\r
-    }\r
-\r
-    for( y = 0; y < size.height; y++ )\r
-        cvWriteRawData( fs, mat->data.ptr + y*mat->step, size.width, dt );\r
-    cvEndWriteStruct( fs );\r
-    cvEndWriteStruct( fs );\r
-}\r
-\r
-\r
-static int\r
-icvFileNodeSeqLen( CvFileNode* node )\r
-{\r
-    return CV_NODE_IS_COLLECTION(node->tag) ? node->data.seq->total :\r
-           CV_NODE_TYPE(node->tag) != CV_NODE_NONE;\r
-}\r
-\r
-\r
-static void*\r
-icvReadMat( CvFileStorage* fs, CvFileNode* node )\r
-{\r
-    void* ptr = 0;\r
-    CvMat* mat;\r
-    const char* dt;\r
-    CvFileNode* data;\r
-    int rows, cols, elem_type;\r
-\r
-    rows = cvReadIntByName( fs, node, "rows", 0 );\r
-    cols = cvReadIntByName( fs, node, "cols", 0 );\r
-    dt = cvReadStringByName( fs, node, "dt", 0 );\r
-\r
-    if( rows == 0 || cols == 0 || dt == 0 )\r
-        CV_Error( CV_StsError, "Some of essential matrix attributes are absent" );\r
-\r
-    elem_type = icvDecodeSimpleFormat( dt );\r
-\r
-    data = cvGetFileNodeByName( fs, node, "data" );\r
-    if( !data )\r
-        CV_Error( CV_StsError, "The matrix data is not found in file storage" );\r
-\r
-    if( icvFileNodeSeqLen( data ) != rows*cols*CV_MAT_CN(elem_type) )\r
-        CV_Error( CV_StsUnmatchedSizes,\r
-        "The matrix size does not match to the number of stored elements" );\r
-\r
-    mat = cvCreateMat( rows, cols, elem_type );\r
-    cvReadRawData( fs, data, mat->data.ptr, dt );\r
-\r
-    ptr = mat;\r
-    return ptr;\r
-}\r
-\r
-\r
-/******************************* CvMatND ******************************/\r
-\r
-static int\r
-icvIsMatND( const void* ptr )\r
-{\r
-    return CV_IS_MATND(ptr);\r
-}\r
-\r
-\r
-static void\r
-icvWriteMatND( CvFileStorage* fs, const char* name,\r
-               const void* struct_ptr, CvAttrList /*attr*/ )\r
-{\r
-    void* mat = (void*)struct_ptr;\r
-    CvMatND stub;\r
-    CvNArrayIterator iterator;\r
-    int dims, sizes[CV_MAX_DIM];\r
-    char dt[16];\r
-\r
-    assert( CV_IS_MATND(mat) );\r
-\r
-    cvStartWriteStruct( fs, name, CV_NODE_MAP, CV_TYPE_NAME_MATND );\r
-    dims = cvGetDims( mat, sizes );\r
-    cvStartWriteStruct( fs, "sizes", CV_NODE_SEQ + CV_NODE_FLOW );\r
-    cvWriteRawData( fs, sizes, dims, "i" );\r
-    cvEndWriteStruct( fs );\r
-    cvWriteString( fs, "dt", icvEncodeFormat( cvGetElemType(mat), dt ), 0 );\r
-    cvStartWriteStruct( fs, "data", CV_NODE_SEQ + CV_NODE_FLOW );\r
-\r
-    cvInitNArrayIterator( 1, &mat, 0, &stub, &iterator );\r
-\r
-    do\r
-        cvWriteRawData( fs, iterator.ptr[0], iterator.size.width, dt );\r
-    while( cvNextNArraySlice( &iterator ));\r
-    cvEndWriteStruct( fs );\r
-    cvEndWriteStruct( fs );\r
-}\r
-\r
-\r
-static void*\r
-icvReadMatND( CvFileStorage* fs, CvFileNode* node )\r
-{\r
-    void* ptr = 0;\r
-    CvMatND* mat;\r
-    const char* dt;\r
-    CvFileNode* data;\r
-    CvFileNode* sizes_node;\r
-    int sizes[CV_MAX_DIM], dims, elem_type;\r
-    int i, total_size;\r
-\r
-    sizes_node = cvGetFileNodeByName( fs, node, "sizes" );\r
-    dt = cvReadStringByName( fs, node, "dt", 0 );\r
-\r
-    if( !sizes_node || !dt )\r
-        CV_Error( CV_StsError, "Some of essential matrix attributes are absent" );\r
-\r
-    dims = CV_NODE_IS_SEQ(sizes_node->tag) ? sizes_node->data.seq->total :\r
-           CV_NODE_IS_INT(sizes_node->tag) ? 1 : -1;\r
-\r
-    if( dims <= 0 || dims > CV_MAX_DIM )\r
-        CV_Error( CV_StsParseError, "Could not determine the matrix dimensionality" );\r
-\r
-    cvReadRawData( fs, sizes_node, sizes, "i" );\r
-    elem_type = icvDecodeSimpleFormat( dt );\r
-\r
-    data = cvGetFileNodeByName( fs, node, "data" );\r
-    if( !data )\r
-        CV_Error( CV_StsError, "The matrix data is not found in file storage" );\r
-\r
-    for( total_size = CV_MAT_CN(elem_type), i = 0; i < dims; i++ )\r
-        total_size *= sizes[i];\r
-\r
-    if( icvFileNodeSeqLen( data ) != total_size )\r
-        CV_Error( CV_StsUnmatchedSizes,\r
-        "The matrix size does not match to the number of stored elements" );\r
-\r
-    mat = cvCreateMatND( dims, sizes, elem_type );\r
-    cvReadRawData( fs, data, mat->data.ptr, dt );\r
-\r
-    ptr = mat;\r
-    return ptr;\r
-}\r
-\r
-\r
-/******************************* CvSparseMat ******************************/\r
-\r
-static int\r
-icvIsSparseMat( const void* ptr )\r
-{\r
-    return CV_IS_SPARSE_MAT(ptr);\r
-}\r
-\r
-\r
-static int\r
-icvSortIdxCmpFunc( const void* _a, const void* _b, void* userdata )\r
-{\r
-    int i, dims = *(int*)userdata;\r
-    const int* a = *(const int**)_a;\r
-    const int* b = *(const int**)_b;\r
-\r
-    for( i = 0; i < dims; i++ )\r
-    {\r
-        int delta = a[i] - b[i];\r
-        if( delta )\r
-            return delta;\r
-    }\r
-\r
-    return 0;\r
-}\r
-\r
-\r
-static void\r
-icvWriteSparseMat( CvFileStorage* fs, const char* name,\r
-                   const void* struct_ptr, CvAttrList /*attr*/ )\r
-{\r
-    CvMemStorage* memstorage = 0;\r
-    const CvSparseMat* mat = (const CvSparseMat*)struct_ptr;\r
-    CvSparseMatIterator iterator;\r
-    CvSparseNode* node;\r
-    CvSeq* elements;\r
-    CvSeqReader reader;\r
-    int i, dims;\r
-    int *prev_idx = 0;\r
-    char dt[16];\r
-\r
-    assert( CV_IS_SPARSE_MAT(mat) );\r
-\r
-    memstorage = cvCreateMemStorage();\r
-\r
-    cvStartWriteStruct( fs, name, CV_NODE_MAP, CV_TYPE_NAME_SPARSE_MAT );\r
-    dims = cvGetDims( mat, 0 );\r
-\r
-    cvStartWriteStruct( fs, "sizes", CV_NODE_SEQ + CV_NODE_FLOW );\r
-    cvWriteRawData( fs, mat->size, dims, "i" );\r
-    cvEndWriteStruct( fs );\r
-    cvWriteString( fs, "dt", icvEncodeFormat( CV_MAT_TYPE(mat->type), dt ), 0 );\r
-    cvStartWriteStruct( fs, "data", CV_NODE_SEQ + CV_NODE_FLOW );\r
-\r
-    elements = cvCreateSeq( CV_SEQ_ELTYPE_PTR, sizeof(CvSeq), sizeof(int*), memstorage );\r
-\r
-    node = cvInitSparseMatIterator( mat, &iterator );\r
-    while( node )\r
-    {\r
-        int* idx = CV_NODE_IDX( mat, node );\r
-        cvSeqPush( elements, &idx );\r
-        node = cvGetNextSparseNode( &iterator );\r
-    }\r
-\r
-    cvSeqSort( elements, icvSortIdxCmpFunc, &dims );\r
-    cvStartReadSeq( elements, &reader, 0 );\r
-\r
-    for( i = 0; i < elements->total; i++ )\r
-    {\r
-        int* idx;\r
-        void* val;\r
-        int k = 0;\r
-\r
-        CV_READ_SEQ_ELEM( idx, reader );\r
-        if( i > 0 )\r
-        {\r
-            for( ; idx[k] == prev_idx[k]; k++ )\r
-                assert( k < dims );\r
-            if( k < dims - 1 )\r
-                fs->write_int( fs, 0, k - dims + 1 );\r
-        }\r
-        for( ; k < dims; k++ )\r
-            fs->write_int( fs, 0, idx[k] );\r
-        prev_idx = idx;\r
-\r
-        node = (CvSparseNode*)((uchar*)idx - mat->idxoffset );\r
-        val = CV_NODE_VAL( mat, node );\r
-\r
-        cvWriteRawData( fs, val, 1, dt );\r
-    }\r
-\r
-    cvEndWriteStruct( fs );\r
-    cvEndWriteStruct( fs );\r
-    cvReleaseMemStorage( &memstorage );\r
-}\r
-\r
-\r
-static void*\r
-icvReadSparseMat( CvFileStorage* fs, CvFileNode* node )\r
-{\r
-    void* ptr = 0;\r
-    CvSparseMat* mat;\r
-    const char* dt;\r
-    CvFileNode* data;\r
-    CvFileNode* sizes_node;\r
-    CvSeqReader reader;\r
-    CvSeq* elements;\r
-    int* idx;\r
-    int* sizes = 0, dims, elem_type, cn;\r
-    int i;\r
-\r
-    sizes_node = cvGetFileNodeByName( fs, node, "sizes" );\r
-    dt = cvReadStringByName( fs, node, "dt", 0 );\r
-\r
-    if( !sizes_node || !dt )\r
-        CV_Error( CV_StsError, "Some of essential matrix attributes are absent" );\r
-\r
-    dims = CV_NODE_IS_SEQ(sizes_node->tag) ? sizes_node->data.seq->total :\r
-           CV_NODE_IS_INT(sizes_node->tag) ? 1 : -1;\r
-\r
-    if( dims <= 0 || dims > CV_MAX_DIM_HEAP )\r
-        CV_Error( CV_StsParseError, "Could not determine sparse matrix dimensionality" );\r
-\r
-    sizes = (int*)cvStackAlloc( dims*sizeof(sizes[0]));\r
-    cvReadRawData( fs, sizes_node, sizes, "i" );\r
-    elem_type = icvDecodeSimpleFormat( dt );\r
-\r
-    data = cvGetFileNodeByName( fs, node, "data" );\r
-    if( !data || !CV_NODE_IS_SEQ(data->tag) )\r
-        CV_Error( CV_StsError, "The matrix data is not found in file storage" );\r
-\r
-    mat = cvCreateSparseMat( dims, sizes, elem_type );\r
-\r
-    cn = CV_MAT_CN(elem_type);\r
-    idx = (int*)alloca( dims*sizeof(idx[0]) );\r
-    elements = data->data.seq;\r
-    cvStartReadRawData( fs, data, &reader );\r
-\r
-    for( i = 0; i < elements->total; )\r
-    {\r
-        CvFileNode* elem = (CvFileNode*)reader.ptr;\r
-        uchar* val;\r
-        int k;\r
-        if( !CV_NODE_IS_INT(elem->tag ))\r
-            CV_Error( CV_StsParseError, "Sparse matrix data is corrupted" );\r
-        k = elem->data.i;\r
-        if( i > 0 && k >= 0 )\r
-            idx[dims-1] = k;\r
-        else\r
-        {\r
-            if( i > 0 )\r
-                k = dims + k - 1;\r
-            else\r
-                idx[0] = k, k = 1;\r
-            for( ; k < dims; k++ )\r
-            {\r
-                CV_NEXT_SEQ_ELEM( elements->elem_size, reader );\r
-                i++;\r
-                elem = (CvFileNode*)reader.ptr;\r
-                if( !CV_NODE_IS_INT(elem->tag ) || elem->data.i < 0 )\r
-                    CV_Error( CV_StsParseError, "Sparse matrix data is corrupted" );\r
-                idx[k] = elem->data.i;\r
-            }\r
-        }\r
-        CV_NEXT_SEQ_ELEM( elements->elem_size, reader );\r
-        i++;\r
-        val = cvPtrND( mat, idx, 0, 1, 0 );\r
-        cvReadRawDataSlice( fs, &reader, cn, val, dt );\r
-        i += cn;\r
-    }\r
-\r
-    ptr = mat;\r
-    return ptr;\r
-}\r
-\r
-\r
-/******************************* IplImage ******************************/\r
-\r
-static int\r
-icvIsImage( const void* ptr )\r
-{\r
-    return CV_IS_IMAGE_HDR(ptr);\r
-}\r
-\r
-static void\r
-icvWriteImage( CvFileStorage* fs, const char* name,\r
-               const void* struct_ptr, CvAttrList /*attr*/ )\r
-{\r
-    const IplImage* image = (const IplImage*)struct_ptr;\r
-    char dt_buf[16], *dt;\r
-    CvSize size;\r
-    int y, depth;\r
-\r
-    assert( CV_IS_IMAGE(image) );\r
-\r
-    if( image->dataOrder == IPL_DATA_ORDER_PLANE )\r
-        CV_Error( CV_StsUnsupportedFormat,\r
-        "Images with planar data layout are not supported" );\r
-\r
-    cvStartWriteStruct( fs, name, CV_NODE_MAP, CV_TYPE_NAME_IMAGE );\r
-    cvWriteInt( fs, "width", image->width );\r
-    cvWriteInt( fs, "height", image->height );\r
-    cvWriteString( fs, "origin", image->origin == IPL_ORIGIN_TL\r
-                   ? "top-left" : "bottom-left", 0 );\r
-    cvWriteString( fs, "layout", image->dataOrder == IPL_DATA_ORDER_PLANE\r
-                   ? "planar" : "interleaved", 0 );\r
-    if( image->roi )\r
-    {\r
-        cvStartWriteStruct( fs, "roi", CV_NODE_MAP + CV_NODE_FLOW );\r
-        cvWriteInt( fs, "x", image->roi->xOffset );\r
-        cvWriteInt( fs, "y", image->roi->yOffset );\r
-        cvWriteInt( fs, "width", image->roi->width );\r
-        cvWriteInt( fs, "height", image->roi->height );\r
-        cvWriteInt( fs, "coi", image->roi->coi );\r
-        cvEndWriteStruct( fs );\r
-    }\r
-\r
-    depth = IplToCvDepth(image->depth);\r
-    sprintf( dt_buf, "%d%c", image->nChannels, icvTypeSymbol[depth] );\r
-    dt = dt_buf + (dt_buf[2] == '\0' && dt_buf[0] == '1');\r
-    cvWriteString( fs, "dt", dt, 0 );\r
-\r
-    size = cvSize(image->width, image->height);\r
-    if( size.width*image->nChannels*CV_ELEM_SIZE(depth) == image->widthStep )\r
-    {\r
-        size.width *= size.height;\r
-        size.height = 1;\r
-    }\r
-\r
-    cvStartWriteStruct( fs, "data", CV_NODE_SEQ + CV_NODE_FLOW );\r
-    for( y = 0; y < size.height; y++ )\r
-        cvWriteRawData( fs, image->imageData + y*image->widthStep, size.width, dt );\r
-    cvEndWriteStruct( fs );\r
-    cvEndWriteStruct( fs );\r
-}\r
-\r
-\r
-static void*\r
-icvReadImage( CvFileStorage* fs, CvFileNode* node )\r
-{\r
-    void* ptr = 0;\r
-    IplImage* image;\r
-    const char* dt;\r
-    CvFileNode* data;\r
-    CvFileNode* roi_node;\r
-    CvSeqReader reader;\r
-    CvRect roi;\r
-    int y, width, height, elem_type, coi, depth;\r
-    const char* origin, *data_order;\r
-\r
-    width = cvReadIntByName( fs, node, "width", 0 );\r
-    height = cvReadIntByName( fs, node, "height", 0 );\r
-    dt = cvReadStringByName( fs, node, "dt", 0 );\r
-    origin = cvReadStringByName( fs, node, "origin", 0 );\r
-\r
-    if( width == 0 || height == 0 || dt == 0 || origin == 0 )\r
-        CV_Error( CV_StsError, "Some of essential image attributes are absent" );\r
-\r
-    elem_type = icvDecodeSimpleFormat( dt );\r
-    data_order = cvReadStringByName( fs, node, "layout", "interleaved" );\r
-    if( strcmp( data_order, "interleaved" ) != 0 )\r
-        CV_Error( CV_StsError, "Only interleaved images can be read" );\r
-\r
-    data = cvGetFileNodeByName( fs, node, "data" );\r
-    if( !data )\r
-        CV_Error( CV_StsError, "The image data is not found in file storage" );\r
-\r
-    if( icvFileNodeSeqLen( data ) != width*height*CV_MAT_CN(elem_type) )\r
-        CV_Error( CV_StsUnmatchedSizes,\r
-        "The matrix size does not match to the number of stored elements" );\r
-\r
-    depth = cvIplDepth(elem_type);\r
-    image = cvCreateImage( cvSize(width,height), depth, CV_MAT_CN(elem_type) );\r
-\r
-    roi_node = cvGetFileNodeByName( fs, node, "roi" );\r
-    if( roi_node )\r
-    {\r
-        roi.x = cvReadIntByName( fs, roi_node, "x", 0 );\r
-        roi.y = cvReadIntByName( fs, roi_node, "y", 0 );\r
-        roi.width = cvReadIntByName( fs, roi_node, "width", 0 );\r
-        roi.height = cvReadIntByName( fs, roi_node, "height", 0 );\r
-        coi = cvReadIntByName( fs, roi_node, "coi", 0 );\r
-\r
-        cvSetImageROI( image, roi );\r
-        cvSetImageCOI( image, coi );\r
-    }\r
-\r
-    if( width*CV_ELEM_SIZE(elem_type) == image->widthStep )\r
-    {\r
-        width *= height;\r
-        height = 1;\r
-    }\r
-\r
-    width *= CV_MAT_CN(elem_type);\r
-    cvStartReadRawData( fs, data, &reader );\r
-    for( y = 0; y < height; y++ )\r
-    {\r
-        cvReadRawDataSlice( fs, &reader, width,\r
-            image->imageData + y*image->widthStep, dt );\r
-    }\r
-\r
-    ptr = image;\r
-    return ptr;\r
-}\r
-\r
-\r
-/******************************* CvSeq ******************************/\r
-\r
-static int\r
-icvIsSeq( const void* ptr )\r
-{\r
-    return CV_IS_SEQ(ptr);\r
-}\r
-\r
-\r
-static void\r
-icvReleaseSeq( void** ptr )\r
-{\r
-    if( !ptr )\r
-        CV_Error( CV_StsNullPtr, "NULL double pointer" );\r
-    *ptr = 0; // it's impossible now to release seq, so just clear the pointer\r
-}\r
-\r
-\r
-static void*\r
-icvCloneSeq( const void* ptr )\r
-{\r
-    return cvSeqSlice( (CvSeq*)ptr, CV_WHOLE_SEQ,\r
-                       0 /* use the same storage as for the original sequence */, 1 );\r
-}\r
-\r
-\r
-static void\r
-icvWriteHeaderData( CvFileStorage* fs, const CvSeq* seq,\r
-                    CvAttrList* attr, int initial_header_size )\r
-{\r
-    char header_dt_buf[128];\r
-    const char* header_dt = cvAttrValue( attr, "header_dt" );\r
-\r
-    if( header_dt )\r
-    {\r
-        int dt_header_size;\r
-        dt_header_size = icvCalcElemSize( header_dt, initial_header_size );\r
-        if( dt_header_size > seq->header_size )\r
-            CV_Error( CV_StsUnmatchedSizes,\r
-            "The size of header calculated from \"header_dt\" is greater than header_size" );\r
-    }\r
-    else if( seq->header_size > initial_header_size )\r
-    {\r
-        if( CV_IS_SEQ(seq) && CV_IS_SEQ_POINT_SET(seq) &&\r
-            seq->header_size == sizeof(CvPoint2DSeq) &&\r
-            seq->elem_size == sizeof(int)*2 )\r
-        {\r
-            CvPoint2DSeq* point_seq = (CvPoint2DSeq*)seq;\r
-\r
-            cvStartWriteStruct( fs, "rect", CV_NODE_MAP + CV_NODE_FLOW );\r
-            cvWriteInt( fs, "x", point_seq->rect.x );\r
-            cvWriteInt( fs, "y", point_seq->rect.y );\r
-            cvWriteInt( fs, "width", point_seq->rect.width );\r
-            cvWriteInt( fs, "height", point_seq->rect.height );\r
-            cvEndWriteStruct( fs );\r
-            cvWriteInt( fs, "color", point_seq->color );\r
-        }\r
-        else if( CV_IS_SEQ(seq) && CV_IS_SEQ_CHAIN(seq) &&\r
-                 CV_MAT_TYPE(seq->flags) == CV_8UC1 )\r
-        {\r
-            CvChain* chain = (CvChain*)seq;\r
-\r
-            cvStartWriteStruct( fs, "origin", CV_NODE_MAP + CV_NODE_FLOW );\r
-            cvWriteInt( fs, "x", chain->origin.x );\r
-            cvWriteInt( fs, "y", chain->origin.y );\r
-            cvEndWriteStruct( fs );\r
-        }\r
-        else\r
-        {\r
-            unsigned extra_size = seq->header_size - initial_header_size;\r
-            // a heuristic to provide nice defaults for sequences of int's & float's\r
-            if( extra_size % sizeof(int) == 0 )\r
-                sprintf( header_dt_buf, "%ui", (unsigned)(extra_size/sizeof(int)) );\r
-            else\r
-                sprintf( header_dt_buf, "%uu", extra_size );\r
-            header_dt = header_dt_buf;\r
-        }\r
-    }\r
-\r
-    if( header_dt )\r
-    {\r
-        cvWriteString( fs, "header_dt", header_dt, 0 );\r
-        cvStartWriteStruct( fs, "header_user_data", CV_NODE_SEQ + CV_NODE_FLOW );\r
-        cvWriteRawData( fs, (uchar*)seq + sizeof(CvSeq), 1, header_dt );\r
-        cvEndWriteStruct( fs );\r
-    }\r
-}\r
-\r
-\r
-static char*\r
-icvGetFormat( const CvSeq* seq, const char* dt_key, CvAttrList* attr,\r
-              int initial_elem_size, char* dt_buf )\r
-{\r
-    char* dt = 0;\r
-    dt = (char*)cvAttrValue( attr, dt_key );\r
-\r
-    if( dt )\r
-    {\r
-        int dt_elem_size;\r
-        dt_elem_size = icvCalcElemSize( dt, initial_elem_size );\r
-        if( dt_elem_size != seq->elem_size )\r
-            CV_Error( CV_StsUnmatchedSizes,\r
-            "The size of element calculated from \"dt\" and "\r
-            "the elem_size do not match" );\r
-    }\r
-    else if( CV_MAT_TYPE(seq->flags) != 0 || seq->elem_size == 1 )\r
-    {\r
-        int align = CV_MAT_DEPTH(seq->flags) == CV_64F ? sizeof(double) : sizeof(size_t);\r
-        int full_elem_size = cvAlign(CV_ELEM_SIZE(seq->flags) + initial_elem_size, align);\r
-        if( seq->elem_size != full_elem_size )\r
-            CV_Error( CV_StsUnmatchedSizes,\r
-            "Size of sequence element (elem_size) is inconsistent with seq->flags" );\r
-        dt = icvEncodeFormat( CV_MAT_TYPE(seq->flags), dt_buf );\r
-    }\r
-    else if( seq->elem_size > initial_elem_size )\r
-    {\r
-        unsigned extra_elem_size = seq->elem_size - initial_elem_size;\r
-        // a heuristic to provide nice defaults for sequences of int's & float's\r
-        if( extra_elem_size % sizeof(int) == 0 )\r
-            sprintf( dt_buf, "%ui", (unsigned)(extra_elem_size/sizeof(int)) );\r
-        else\r
-            sprintf( dt_buf, "%uu", extra_elem_size );\r
-        dt = dt_buf;\r
-    }\r
-\r
-    return dt;\r
-}\r
-\r
-\r
-static void\r
-icvWriteSeq( CvFileStorage* fs, const char* name,\r
-             const void* struct_ptr,\r
-             CvAttrList attr, int level )\r
-{\r
-    const CvSeq* seq = (CvSeq*)struct_ptr;\r
-    CvSeqBlock* block;\r
-    char buf[128];\r
-    char dt_buf[128], *dt;\r
-\r
-    assert( CV_IS_SEQ( seq ));\r
-    cvStartWriteStruct( fs, name, CV_NODE_MAP, CV_TYPE_NAME_SEQ );\r
-\r
-    if( level >= 0 )\r
-        cvWriteInt( fs, "level", level );\r
-\r
-    sprintf( buf, "%08x", seq->flags );\r
-    cvWriteString( fs, "flags", buf, 1 );\r
-    cvWriteInt( fs, "count", seq->total );\r
-    dt = icvGetFormat( seq, "dt", &attr, 0, dt_buf );\r
-    cvWriteString( fs, "dt", dt, 0 );\r
-\r
-    icvWriteHeaderData( fs, seq, &attr, sizeof(CvSeq) );\r
-    cvStartWriteStruct( fs, "data", CV_NODE_SEQ + CV_NODE_FLOW );\r
-\r
-    for( block = seq->first; block; block = block->next )\r
-    {\r
-        cvWriteRawData( fs, block->data, block->count, dt );\r
-        if( block == seq->first->prev )\r
-            break;\r
-    }\r
-    cvEndWriteStruct( fs );\r
-    cvEndWriteStruct( fs );\r
-}\r
-\r
-\r
-static void\r
-icvWriteSeqTree( CvFileStorage* fs, const char* name,\r
-                 const void* struct_ptr, CvAttrList attr )\r
-{\r
-    const CvSeq* seq = (CvSeq*)struct_ptr;\r
-    const char* recursive_value = cvAttrValue( &attr, "recursive" );\r
-    int is_recursive = recursive_value &&\r
-                       strcmp(recursive_value,"0") != 0 &&\r
-                       strcmp(recursive_value,"false") != 0 &&\r
-                       strcmp(recursive_value,"False") != 0 &&\r
-                       strcmp(recursive_value,"FALSE") != 0;\r
-\r
-    assert( CV_IS_SEQ( seq ));\r
-\r
-    if( !is_recursive )\r
-    {\r
-        icvWriteSeq( fs, name, seq, attr, -1 );\r
-    }\r
-    else\r
-    {\r
-        CvTreeNodeIterator tree_iterator;\r
-\r
-        cvStartWriteStruct( fs, name, CV_NODE_MAP, CV_TYPE_NAME_SEQ_TREE );\r
-        cvStartWriteStruct( fs, "sequences", CV_NODE_SEQ );\r
-        cvInitTreeNodeIterator( &tree_iterator, seq, INT_MAX );\r
-\r
-        for(;;)\r
-        {\r
-            if( !tree_iterator.node )\r
-                break;\r
-            icvWriteSeq( fs, 0, tree_iterator.node, attr, tree_iterator.level );\r
-            cvNextTreeNode( &tree_iterator );\r
-        }\r
-\r
-        cvEndWriteStruct( fs );\r
-        cvEndWriteStruct( fs );\r
-    }\r
-}\r
-\r
-\r
-static void*\r
-icvReadSeq( CvFileStorage* fs, CvFileNode* node )\r
-{\r
-    void* ptr = 0;\r
-    CvSeq* seq;\r
-    CvSeqBlock* block;\r
-    CvFileNode *data, *header_node, *rect_node, *origin_node;\r
-    CvSeqReader reader;\r
-    int total, flags;\r
-    int elem_size, header_size = sizeof(CvSeq);\r
-    int fmt_pairs[CV_FS_MAX_FMT_PAIRS], i, fmt_pair_count;\r
-    int items_per_elem = 0;\r
-    const char* flags_str;\r
-    const char* header_dt;\r
-    const char* dt;\r
-    char* endptr = 0;\r
-\r
-    flags_str = cvReadStringByName( fs, node, "flags", 0 );\r
-    total = cvReadIntByName( fs, node, "count", -1 );\r
-    dt = cvReadStringByName( fs, node, "dt", 0 );\r
-\r
-    if( !flags_str || total == -1 || !dt )\r
-        CV_Error( CV_StsError, "Some of essential sequence attributes are absent" );\r
-\r
-    flags = (int)strtol( flags_str, &endptr, 16 );\r
-    if( endptr == flags_str || (flags & CV_MAGIC_MASK) != CV_SEQ_MAGIC_VAL )\r
-        CV_Error( CV_StsError, "The sequence flags are invalid" );\r
-\r
-    header_dt = cvReadStringByName( fs, node, "header_dt", 0 );\r
-    header_node = cvGetFileNodeByName( fs, node, "header_user_data" );\r
-\r
-    if( (header_dt != 0) ^ (header_node != 0) )\r
-        CV_Error( CV_StsError,\r
-        "One of \"header_dt\" and \"header_user_data\" is there, while the other is not" );\r
-\r
-    rect_node = cvGetFileNodeByName( fs, node, "rect" );\r
-    origin_node = cvGetFileNodeByName( fs, node, "origin" );\r
-\r
-    if( (header_node != 0) + (rect_node != 0) + (origin_node != 0) > 1 )\r
-        CV_Error( CV_StsError, "Only one of \"header_user_data\", \"rect\" and \"origin\" tags may occur" );\r
-\r
-    if( header_dt )\r
-    {\r
-        header_size = icvCalcElemSize( header_dt, header_size );\r
-    }\r
-    else if( rect_node )\r
-        header_size = sizeof(CvPoint2DSeq);\r
-    else if( origin_node )\r
-        header_size = sizeof(CvChain);\r
-\r
-    elem_size = icvCalcElemSize( dt, 0 );\r
-    seq = cvCreateSeq( flags, header_size, elem_size, fs->dststorage );\r
-\r
-    if( header_node )\r
-    {\r
-        cvReadRawData( fs, header_node, (char*)seq + sizeof(CvSeq), header_dt );\r
-    }\r
-    else if( rect_node )\r
-    {\r
-        CvPoint2DSeq* point_seq = (CvPoint2DSeq*)seq;\r
-        point_seq->rect.x = cvReadIntByName( fs, rect_node, "x", 0 );\r
-        point_seq->rect.y = cvReadIntByName( fs, rect_node, "y", 0 );\r
-        point_seq->rect.width = cvReadIntByName( fs, rect_node, "width", 0 );\r
-        point_seq->rect.height = cvReadIntByName( fs, rect_node, "height", 0 );\r
-        point_seq->color = cvReadIntByName( fs, node, "color", 0 );\r
-    }\r
-    else if( origin_node )\r
-    {\r
-        CvChain* chain = (CvChain*)seq;\r
-        chain->origin.x = cvReadIntByName( fs, origin_node, "x", 0 );\r
-        chain->origin.y = cvReadIntByName( fs, origin_node, "y", 0 );\r
-    }\r
-\r
-    cvSeqPushMulti( seq, 0, total, 0 );\r
-    fmt_pair_count = icvDecodeFormat( dt, fmt_pairs, CV_FS_MAX_FMT_PAIRS );\r
-    fmt_pair_count *= 2;\r
-    for( i = 0; i < fmt_pair_count; i += 2 )\r
-        items_per_elem += fmt_pairs[i];\r
-\r
-    data = cvGetFileNodeByName( fs, node, "data" );\r
-    if( !data )\r
-        CV_Error( CV_StsError, "The image data is not found in file storage" );\r
-\r
-    if( icvFileNodeSeqLen( data ) != total*items_per_elem )\r
-        CV_Error( CV_StsError, "The number of stored elements does not match to \"count\"" );\r
-\r
-    cvStartReadRawData( fs, data, &reader );\r
-    for( block = seq->first; block; block = block->next )\r
-    {\r
-        int delta = block->count*items_per_elem;\r
-        cvReadRawDataSlice( fs, &reader, delta, block->data, dt );\r
-        if( block == seq->first->prev )\r
-            break;\r
-    }\r
-\r
-    ptr = seq;\r
-    return ptr;\r
-}\r
-\r
-\r
-static void*\r
-icvReadSeqTree( CvFileStorage* fs, CvFileNode* node )\r
-{\r
-    void* ptr = 0;\r
-    CvFileNode *sequences_node = cvGetFileNodeByName( fs, node, "sequences" );\r
-    CvSeq* sequences;\r
-    CvSeq* root = 0;\r
-    CvSeq* parent = 0;\r
-    CvSeq* prev_seq = 0;\r
-    CvSeqReader reader;\r
-    int i, total;\r
-    int prev_level = 0;\r
-\r
-    if( !sequences_node || !CV_NODE_IS_SEQ(sequences_node->tag) )\r
-        CV_Error( CV_StsParseError,\r
-        "opencv-sequence-tree instance should contain a field \"sequences\" that should be a sequence" );\r
-\r
-    sequences = sequences_node->data.seq;\r
-    total = sequences->total;\r
-\r
-    cvStartReadSeq( sequences, &reader, 0 );\r
-    for( i = 0; i < total; i++ )\r
-    {\r
-        CvFileNode* elem = (CvFileNode*)reader.ptr;\r
-        CvSeq* seq;\r
-        int level;\r
-        seq = (CvSeq*)cvRead( fs, elem );\r
-        level = cvReadIntByName( fs, elem, "level", -1 );\r
-        if( level < 0 )\r
-            CV_Error( CV_StsParseError, "All the sequence tree nodes should contain \"level\" field" );\r
-        if( !root )\r
-            root = seq;\r
-        if( level > prev_level )\r
-        {\r
-            assert( level == prev_level + 1 );\r
-            parent = prev_seq;\r
-            prev_seq = 0;\r
-            if( parent )\r
-                parent->v_next = seq;\r
-        }\r
-        else if( level < prev_level )\r
-        {\r
-            for( ; prev_level > level; prev_level-- )\r
-                prev_seq = prev_seq->v_prev;\r
-            parent = prev_seq->v_prev;\r
-        }\r
-        seq->h_prev = prev_seq;\r
-        if( prev_seq )\r
-            prev_seq->h_next = seq;\r
-        seq->v_prev = parent;\r
-        prev_seq = seq;\r
-        prev_level = level;\r
-        CV_NEXT_SEQ_ELEM( sequences->elem_size, reader );\r
-    }\r
-\r
-    ptr = root;\r
-    return ptr;\r
-}\r
-\r
-/******************************* CvGraph ******************************/\r
-\r
-static int\r
-icvIsGraph( const void* ptr )\r
-{\r
-    return CV_IS_GRAPH(ptr);\r
-}\r
-\r
-\r
-static void\r
-icvReleaseGraph( void** ptr )\r
-{\r
-    if( !ptr )\r
-        CV_Error( CV_StsNullPtr, "NULL double pointer" );\r
-\r
-    *ptr = 0; // it's impossible now to release graph, so just clear the pointer\r
-}\r
-\r
-\r
-static void*\r
-icvCloneGraph( const void* ptr )\r
-{\r
-    return cvCloneGraph( (const CvGraph*)ptr, 0 );\r
-}\r
-\r
-\r
-static void\r
-icvWriteGraph( CvFileStorage* fs, const char* name,\r
-               const void* struct_ptr, CvAttrList attr )\r
-{\r
-    int* flag_buf = 0;\r
-    char* write_buf = 0;\r
-    const CvGraph* graph = (const CvGraph*)struct_ptr;\r
-    CvSeqReader reader;\r
-    char buf[128];\r
-    int i, k, vtx_count, edge_count;\r
-    char vtx_dt_buf[128], *vtx_dt;\r
-    char edge_dt_buf[128], *edge_dt;\r
-    int write_buf_size;\r
-\r
-    assert( CV_IS_GRAPH(graph) );\r
-    vtx_count = cvGraphGetVtxCount( graph );\r
-    edge_count = cvGraphGetEdgeCount( graph );\r
-    flag_buf = (int*)cvAlloc( vtx_count*sizeof(flag_buf[0]));\r
-\r
-    // count vertices\r
-    cvStartReadSeq( (CvSeq*)graph, &reader );\r
-    for( i = 0, k = 0; i < graph->total; i++ )\r
-    {\r
-        if( CV_IS_SET_ELEM( reader.ptr ))\r
-        {\r
-            CvGraphVtx* vtx = (CvGraphVtx*)reader.ptr;\r
-            flag_buf[k] = vtx->flags;\r
-            vtx->flags = k++;\r
-        }\r
-        CV_NEXT_SEQ_ELEM( graph->elem_size, reader );\r
-    }\r
-\r
-    // write header\r
-    cvStartWriteStruct( fs, name, CV_NODE_MAP, CV_TYPE_NAME_GRAPH );\r
-\r
-    sprintf( buf, "%08x", graph->flags );\r
-    cvWriteString( fs, "flags", buf, 1 );\r
-\r
-    cvWriteInt( fs, "vertex_count", vtx_count );\r
-    vtx_dt = icvGetFormat( (CvSeq*)graph, "vertex_dt",\r
-                    &attr, sizeof(CvGraphVtx), vtx_dt_buf );\r
-    if( vtx_dt )\r
-        cvWriteString( fs, "vertex_dt", vtx_dt, 0 );\r
-\r
-    cvWriteInt( fs, "edge_count", edge_count );\r
-    edge_dt = icvGetFormat( (CvSeq*)graph->edges, "edge_dt",\r
-                                &attr, sizeof(CvGraphEdge), buf );\r
-    sprintf( edge_dt_buf, "2if%s", edge_dt ? edge_dt : "" );\r
-    edge_dt = edge_dt_buf;\r
-    cvWriteString( fs, "edge_dt", edge_dt, 0 );\r
-\r
-    icvWriteHeaderData( fs, (CvSeq*)graph, &attr, sizeof(CvGraph) );\r
-\r
-    write_buf_size = MAX( 3*graph->elem_size, 1 << 16 );\r
-    write_buf_size = MAX( 3*graph->edges->elem_size, write_buf_size );\r
-    write_buf = (char*)cvAlloc( write_buf_size );\r
-\r
-    // as vertices and edges are written in similar way,\r
-    // do it as a parametrized 2-iteration loop\r
-    for( k = 0; k < 2; k++ )\r
-    {\r
-        const char* dt = k == 0 ? vtx_dt : edge_dt;\r
-        if( dt )\r
-        {\r
-            CvSet* data = k == 0 ? (CvSet*)graph : graph->edges;\r
-            int elem_size = data->elem_size;\r
-            int write_elem_size = icvCalcElemSize( dt, 0 );\r
-            char* src_ptr = write_buf;\r
-            int write_max = write_buf_size / write_elem_size, write_count = 0;\r
-\r
-            // alignment of user part of the edge data following 2if\r
-            int edge_user_align = sizeof(float);\r
-\r
-            if( k == 1 )\r
-            {\r
-                int fmt_pairs[CV_FS_MAX_FMT_PAIRS], fmt_pair_count;\r
-                fmt_pair_count = icvDecodeFormat( dt, fmt_pairs, CV_FS_MAX_FMT_PAIRS );\r
-                if( fmt_pair_count > 2 || CV_ELEM_SIZE(fmt_pairs[2*2+1]) >= (int)sizeof(double))\r
-                    edge_user_align = sizeof(double);\r
-            }\r
-\r
-            cvStartWriteStruct( fs, k == 0 ? "vertices" : "edges",\r
-                                CV_NODE_SEQ + CV_NODE_FLOW );\r
-            cvStartReadSeq( (CvSeq*)data, &reader );\r
-            for( i = 0; i < data->total; i++ )\r
-            {\r
-                if( CV_IS_SET_ELEM( reader.ptr ))\r
-                {\r
-                    if( k == 0 ) // vertices\r
-                        memcpy( src_ptr, reader.ptr + sizeof(CvGraphVtx), write_elem_size );\r
-                    else\r
-                    {\r
-                        CvGraphEdge* edge = (CvGraphEdge*)reader.ptr;\r
-                        src_ptr = (char*)cvAlignPtr( src_ptr, sizeof(int) );\r
-                        ((int*)src_ptr)[0] = edge->vtx[0]->flags;\r
-                        ((int*)src_ptr)[1] = edge->vtx[1]->flags;\r
-                        *(float*)(src_ptr + sizeof(int)*2) = edge->weight;\r
-                        if( elem_size > (int)sizeof(CvGraphEdge) )\r
-                        {\r
-                            char* src_ptr2 = (char*)cvAlignPtr( src_ptr + 2*sizeof(int)\r
-                                                + sizeof(float), edge_user_align );\r
-                            memcpy( src_ptr2, edge + 1, elem_size - sizeof(CvGraphEdge) );\r
-                        }\r
-                    }\r
-                    src_ptr += write_elem_size;\r
-                    if( ++write_count >= write_max )\r
-                    {\r
-                        cvWriteRawData( fs, write_buf, write_count, dt );\r
-                        write_count = 0;\r
-                        src_ptr = write_buf;\r
-                    }\r
-                }\r
-                CV_NEXT_SEQ_ELEM( data->elem_size, reader );\r
-            }\r
-\r
-            if( write_count > 0 )\r
-                cvWriteRawData( fs, write_buf, write_count, dt );\r
-            cvEndWriteStruct( fs );\r
-        }\r
-    }\r
-\r
-    cvEndWriteStruct( fs );\r
-\r
-    // final stage. restore the graph flags\r
-    cvStartReadSeq( (CvSeq*)graph, &reader );\r
-    vtx_count = 0;\r
-    for( i = 0; i < graph->total; i++ )\r
-    {\r
-        if( CV_IS_SET_ELEM( reader.ptr ))\r
-            ((CvGraphVtx*)reader.ptr)->flags = flag_buf[vtx_count++];\r
-        CV_NEXT_SEQ_ELEM( graph->elem_size, reader );\r
-    }\r
-\r
-    cvFree( &write_buf );\r
-    cvFree( &flag_buf );\r
-}\r
-\r
-\r
-static void*\r
-icvReadGraph( CvFileStorage* fs, CvFileNode* node )\r
-{\r
-    void* ptr = 0;\r
-    char* read_buf = 0;\r
-    CvGraphVtx** vtx_buf = 0;\r
-    CvGraph* graph;\r
-    CvFileNode *header_node, *vtx_node, *edge_node;\r
-    int flags, vtx_count, edge_count;\r
-    int vtx_size = sizeof(CvGraphVtx), edge_size, header_size = sizeof(CvGraph);\r
-    int src_vtx_size = 0, src_edge_size;\r
-    int fmt_pairs[CV_FS_MAX_FMT_PAIRS], fmt_pair_count;\r
-    int vtx_items_per_elem = 0, edge_items_per_elem = 0;\r
-    int edge_user_align = sizeof(float);\r
-    int read_buf_size;\r
-    int i, k;\r
-    const char* flags_str;\r
-    const char* header_dt;\r
-    const char* vtx_dt;\r
-    const char* edge_dt;\r
-    char* endptr = 0;\r
-\r
-    flags_str = cvReadStringByName( fs, node, "flags", 0 );\r
-    vtx_dt = cvReadStringByName( fs, node, "vertex_dt", 0 );\r
-    edge_dt = cvReadStringByName( fs, node, "edge_dt", 0 );\r
-    vtx_count = cvReadIntByName( fs, node, "vertex_count", -1 );\r
-    edge_count = cvReadIntByName( fs, node, "edge_count", -1 );\r
-\r
-    if( !flags_str || vtx_count == -1 || edge_count == -1 || !edge_dt )\r
-        CV_Error( CV_StsError, "Some of essential sequence attributes are absent" );\r
-\r
-    flags = (int)strtol( flags_str, &endptr, 16 );\r
-    if( endptr == flags_str ||\r
-        (flags & (CV_SEQ_KIND_MASK|CV_MAGIC_MASK)) != (CV_GRAPH|CV_SET_MAGIC_VAL))\r
-        CV_Error( CV_StsError, "Invalid graph signature" );\r
-\r
-    header_dt = cvReadStringByName( fs, node, "header_dt", 0 );\r
-    header_node = cvGetFileNodeByName( fs, node, "header_user_data" );\r
-\r
-    if( (header_dt != 0) ^ (header_node != 0) )\r
-        CV_Error( CV_StsError,\r
-        "One of \"header_dt\" and \"header_user_data\" is there, while the other is not" );\r
-\r
-    if( header_dt )\r
-        header_size = icvCalcElemSize( header_dt, header_size );\r
-\r
-    if( vtx_dt > 0 )\r
-    {\r
-        src_vtx_size = icvCalcElemSize( vtx_dt, 0 );\r
-        vtx_size = icvCalcElemSize( vtx_dt, vtx_size );\r
-        fmt_pair_count = icvDecodeFormat( edge_dt,\r
-                            fmt_pairs, CV_FS_MAX_FMT_PAIRS );\r
-        fmt_pair_count *= 2;\r
-        for( i = 0; i < fmt_pair_count; i += 2 )\r
-            vtx_items_per_elem += fmt_pairs[i];\r
-    }\r
-\r
-    {\r
-        char dst_edge_dt_buf[128];\r
-        const char* dst_edge_dt = 0;\r
-\r
-        fmt_pair_count = icvDecodeFormat( edge_dt,\r
-                            fmt_pairs, CV_FS_MAX_FMT_PAIRS );\r
-        if( fmt_pair_count < 2 ||\r
-            fmt_pairs[0] != 2 || fmt_pairs[1] != CV_32S ||\r
-            fmt_pairs[2] < 1 || fmt_pairs[3] != CV_32F )\r
-            CV_Error( CV_StsBadArg,\r
-            "Graph edges should start with 2 integers and a float" );\r
-\r
-        // alignment of user part of the edge data following 2if\r
-        if( fmt_pair_count > 2 && CV_ELEM_SIZE(fmt_pairs[5]) >= (int)sizeof(double))\r
-            edge_user_align = sizeof(double);\r
-\r
-        fmt_pair_count *= 2;\r
-        for( i = 0; i < fmt_pair_count; i += 2 )\r
-            edge_items_per_elem += fmt_pairs[i];\r
-\r
-        if( edge_dt[2] == 'f' || (edge_dt[2] == '1' && edge_dt[3] == 'f') )\r
-            dst_edge_dt = edge_dt + 3 + isdigit(edge_dt[2]);\r
-        else\r
-        {\r
-            int val = (int)strtol( edge_dt + 2, &endptr, 10 );\r
-            sprintf( dst_edge_dt_buf, "%df%s", val-1, endptr );\r
-            dst_edge_dt = dst_edge_dt_buf;\r
-        }\r
-\r
-        edge_size = icvCalcElemSize( dst_edge_dt, sizeof(CvGraphEdge) );\r
-        src_edge_size = icvCalcElemSize( edge_dt, 0 );\r
-    }\r
-\r
-    graph = cvCreateGraph( flags, header_size, vtx_size, edge_size, fs->dststorage );\r
-\r
-    if( header_node )\r
-        cvReadRawData( fs, header_node, (char*)graph + sizeof(CvGraph), header_dt );\r
-\r
-    read_buf_size = MAX( src_vtx_size*3, 1 << 16 );\r
-    read_buf_size = MAX( src_edge_size*3, read_buf_size );\r
-    read_buf = (char*)cvAlloc( read_buf_size );\r
-    vtx_buf = (CvGraphVtx**)cvAlloc( vtx_count * sizeof(vtx_buf[0]) );\r
-\r
-    vtx_node = cvGetFileNodeByName( fs, node, "vertices" );\r
-    edge_node = cvGetFileNodeByName( fs, node, "edges" );\r
-    if( !edge_node )\r
-        CV_Error( CV_StsBadArg, "No edges data" );\r
-    if( vtx_dt && !vtx_node )\r
-        CV_Error( CV_StsBadArg, "No vertices data" );\r
-\r
-    // as vertices and edges are read in similar way,\r
-    // do it as a parametrized 2-iteration loop\r
-    for( k = 0; k < 2; k++ )\r
-    {\r
-        const char* dt = k == 0 ? vtx_dt : edge_dt;\r
-        int elem_size = k == 0 ? vtx_size : edge_size;\r
-        int src_elem_size = k == 0 ? src_vtx_size : src_edge_size;\r
-        int items_per_elem = k == 0 ? vtx_items_per_elem : edge_items_per_elem;\r
-        int elem_count = k == 0 ? vtx_count : edge_count;\r
-        char* dst_ptr = read_buf;\r
-        int read_max = read_buf_size /MAX(src_elem_size, 1), read_count = 0;\r
-        CvSeqReader reader;\r
-        cvStartReadRawData( fs, k == 0 ? vtx_node : edge_node, &reader );\r
-\r
-        for( i = 0; i < elem_count; i++ )\r
-        {\r
-            if( read_count == 0 && dt )\r
-            {\r
-                int count = MIN( elem_count - i, read_max )*items_per_elem;\r
-                cvReadRawDataSlice( fs, &reader, count, read_buf, dt );\r
-                read_count = count;\r
-                dst_ptr = read_buf;\r
-            }\r
-\r
-            if( k == 0 )\r
-            {\r
-                CvGraphVtx* vtx;\r
-                cvGraphAddVtx( graph, 0, &vtx );\r
-                vtx_buf[i] = vtx;\r
-                if( dt )\r
-                    memcpy( vtx + 1, dst_ptr, src_elem_size );\r
-            }\r
-            else\r
-            {\r
-                CvGraphEdge* edge = 0;\r
-                int vtx1 = ((int*)dst_ptr)[0];\r
-                int vtx2 = ((int*)dst_ptr)[1];\r
-                int result;\r
-\r
-                if( (unsigned)vtx1 >= (unsigned)vtx_count ||\r
-                    (unsigned)vtx2 >= (unsigned)vtx_count )\r
-                    CV_Error( CV_StsOutOfRange,\r
-                    "Some of stored vertex indices are out of range" );\r
-\r
-                result = cvGraphAddEdgeByPtr( graph,\r
-                    vtx_buf[vtx1], vtx_buf[vtx2], 0, &edge );\r
-\r
-                if( result == 0 )\r
-                    CV_Error( CV_StsBadArg, "Duplicated edge has occured" );\r
-\r
-                edge->weight = *(float*)(dst_ptr + sizeof(int)*2);\r
-                if( elem_size > (int)sizeof(CvGraphEdge) )\r
-                {\r
-                    char* dst_ptr2 = (char*)cvAlignPtr( dst_ptr + sizeof(int)*2 +\r
-                                                sizeof(float), edge_user_align );\r
-                    memcpy( edge + 1, dst_ptr2, elem_size - sizeof(CvGraphEdge) );\r
-                }\r
-            }\r
-\r
-            dst_ptr += src_elem_size;\r
-            read_count--;\r
-        }\r
-    }\r
-\r
-    ptr = graph;\r
-    cvFree( &read_buf );\r
-    cvFree( &vtx_buf );\r
-\r
-    return ptr;\r
-}\r
-\r
-/****************************************************************************************\\r
-*                                    RTTI Functions                                      *\r
-\****************************************************************************************/\r
-\r
-CvTypeInfo *CvType::first = 0, *CvType::last = 0;\r
-\r
-CvType::CvType( const char* type_name,\r
-                CvIsInstanceFunc is_instance, CvReleaseFunc release,\r
-                CvReadFunc read, CvWriteFunc write, CvCloneFunc clone )\r
-{\r
-    CvTypeInfo _info;\r
-    _info.flags = 0;\r
-    _info.header_size = sizeof(_info);\r
-    _info.type_name = type_name;\r
-    _info.prev = _info.next = 0;\r
-    _info.is_instance = is_instance;\r
-    _info.release = release;\r
-    _info.clone = clone;\r
-    _info.read = read;\r
-    _info.write = write;\r
-\r
-    cvRegisterType( &_info );\r
-    info = first;\r
-}\r
-\r
-\r
-CvType::~CvType()\r
-{\r
-    cvUnregisterType( info->type_name );\r
-}\r
-\r
-\r
-CvType seq_type( CV_TYPE_NAME_SEQ, icvIsSeq, icvReleaseSeq, icvReadSeq,\r
-                 icvWriteSeqTree /* this is the entry point for\r
-                 writing a single sequence too */, icvCloneSeq );\r
-\r
-CvType seq_tree_type( CV_TYPE_NAME_SEQ_TREE, icvIsSeq, icvReleaseSeq,\r
-                      icvReadSeqTree, icvWriteSeqTree, icvCloneSeq );\r
-\r
-CvType seq_graph_type( CV_TYPE_NAME_GRAPH, icvIsGraph, icvReleaseGraph,\r
-                       icvReadGraph, icvWriteGraph, icvCloneGraph );\r
-\r
-CvType sparse_mat_type( CV_TYPE_NAME_SPARSE_MAT, icvIsSparseMat,\r
-                        (CvReleaseFunc)cvReleaseSparseMat, icvReadSparseMat,\r
-                        icvWriteSparseMat, (CvCloneFunc)cvCloneSparseMat );\r
-\r
-CvType image_type( CV_TYPE_NAME_IMAGE, icvIsImage, (CvReleaseFunc)cvReleaseImage,\r
-                   icvReadImage, icvWriteImage, (CvCloneFunc)cvCloneImage );\r
-\r
-CvType mat_type( CV_TYPE_NAME_MAT, icvIsMat, (CvReleaseFunc)cvReleaseMat,\r
-                 icvReadMat, icvWriteMat, (CvCloneFunc)cvCloneMat );\r
-\r
-CvType matnd_type( CV_TYPE_NAME_MATND, icvIsMatND, (CvReleaseFunc)cvReleaseMatND,\r
-                   icvReadMatND, icvWriteMatND, (CvCloneFunc)cvCloneMatND );\r
-\r
-CV_IMPL  void\r
-cvRegisterType( const CvTypeInfo* _info )\r
-{\r
-    CvTypeInfo* info = 0;\r
-    int i, len;\r
-    char c;\r
-\r
-    //if( !CvType::first )\r
-    //    icvCreateStandardTypes();\r
-\r
-    if( !_info || _info->header_size != sizeof(CvTypeInfo) )\r
-        CV_Error( CV_StsBadSize, "Invalid type info" );\r
-\r
-    if( !_info->is_instance || !_info->release ||\r
-        !_info->read || !_info->write )\r
-        CV_Error( CV_StsNullPtr,\r
-        "Some of required function pointers "\r
-        "(is_instance, release, read or write) are NULL");\r
-\r
-    c = _info->type_name[0];\r
-    if( !isalpha(c) && c != '_' )\r
-        CV_Error( CV_StsBadArg, "Type name should start with a letter or _" );\r
-\r
-    len = (int)strlen(_info->type_name);\r
-\r
-    for( i = 0; i < len; i++ )\r
-    {\r
-        c = _info->type_name[i];\r
-        if( !isalnum(c) && c != '-' && c != '_' )\r
-            CV_Error( CV_StsBadArg,\r
-            "Type name should contain only letters, digits, - and _" );\r
-    }\r
-\r
-    info = (CvTypeInfo*)malloc( sizeof(*info) + len + 1 );\r
-\r
-    *info = *_info;\r
-    info->type_name = (char*)(info + 1);\r
-    memcpy( (char*)info->type_name, _info->type_name, len + 1 );\r
-\r
-    info->flags = 0;\r
-    info->next = CvType::first;\r
-    info->prev = 0;\r
-    if( CvType::first )\r
-        CvType::first->prev = info;\r
-    else\r
-        CvType::last = info;\r
-    CvType::first = info;\r
-}\r
-\r
-\r
-CV_IMPL void\r
-cvUnregisterType( const char* type_name )\r
-{\r
-    CvTypeInfo* info;\r
-\r
-    info = cvFindType( type_name );\r
-    if( info )\r
-    {\r
-        if( info->prev )\r
-            info->prev->next = info->next;\r
-        else\r
-            CvType::first = info->next;\r
-\r
-        if( info->next )\r
-            info->next->prev = info->prev;\r
-        else\r
-            CvType::last = info->prev;\r
-\r
-        if( !CvType::first || !CvType::last )\r
-            CvType::first = CvType::last = 0;\r
-\r
-        free( info );\r
-    }\r
-}\r
-\r
-\r
-CV_IMPL CvTypeInfo*\r
-cvFirstType( void )\r
-{\r
-    return CvType::first;\r
-}\r
-\r
-\r
-CV_IMPL CvTypeInfo*\r
-cvFindType( const char* type_name )\r
-{\r
-    CvTypeInfo* info = 0;\r
-\r
-    for( info = CvType::first; info != 0; info = info->next )\r
-        if( strcmp( info->type_name, type_name ) == 0 )\r
-            break;\r
-\r
-    return info;\r
-}\r
-\r
-\r
-CV_IMPL CvTypeInfo*\r
-cvTypeOf( const void* struct_ptr )\r
-{\r
-    CvTypeInfo* info = 0;\r
-\r
-    for( info = CvType::first; info != 0; info = info->next )\r
-        if( info->is_instance( struct_ptr ))\r
-            break;\r
-\r
-    return info;\r
-}\r
-\r
-\r
-/* universal functions */\r
-CV_IMPL void\r
-cvRelease( void** struct_ptr )\r
-{\r
-    CvTypeInfo* info;\r
-\r
-    if( !struct_ptr )\r
-        CV_Error( CV_StsNullPtr, "NULL double pointer" );\r
-\r
-    if( *struct_ptr )\r
-    {\r
-        info = cvTypeOf( *struct_ptr );\r
-        if( !info )\r
-            CV_Error( CV_StsError, "Unknown object type" );\r
-        if( !info->release )\r
-            CV_Error( CV_StsError, "release function pointer is NULL" );\r
-\r
-        info->release( struct_ptr );\r
-        *struct_ptr = 0;\r
-    }\r
-}\r
-\r
-\r
-void* cvClone( const void* struct_ptr )\r
-{\r
-    void* struct_copy = 0;\r
-    CvTypeInfo* info;\r
-\r
-    if( !struct_ptr )\r
-        CV_Error( CV_StsNullPtr, "NULL structure pointer" );\r
-\r
-    info = cvTypeOf( struct_ptr );\r
-    if( !info )\r
-        CV_Error( CV_StsError, "Unknown object type" );\r
-    if( !info->clone )\r
-        CV_Error( CV_StsError, "clone function pointer is NULL" );\r
-\r
-    struct_copy = info->clone( struct_ptr );\r
-    return struct_copy;\r
-}\r
-\r
-\r
-/* reads matrix, image, sequence, graph etc. */\r
-CV_IMPL void*\r
-cvRead( CvFileStorage* fs, CvFileNode* node, CvAttrList* list )\r
-{\r
-    void* obj = 0;\r
-    CV_CHECK_FILE_STORAGE( fs );\r
-\r
-    if( !node )\r
-        return 0;\r
-\r
-    if( !CV_NODE_IS_USER(node->tag) || !node->info )\r
-        CV_Error( CV_StsError, "The node does not represent a user object (unknown type?)" );\r
-\r
-    obj = node->info->read( fs, node );\r
-    if( list )\r
-        *list = cvAttrList(0,0);\r
-\r
-    return obj;\r
-}\r
-\r
-\r
-/* writes matrix, image, sequence, graph etc. */\r
-CV_IMPL void\r
-cvWrite( CvFileStorage* fs, const char* name,\r
-         const void* ptr, CvAttrList attributes )\r
-{\r
-    CvTypeInfo* info;\r
-\r
-    CV_CHECK_OUTPUT_FILE_STORAGE( fs );\r
-\r
-    if( !ptr )\r
-        CV_Error( CV_StsNullPtr, "Null pointer to the written object" );\r
-\r
-    info = cvTypeOf( ptr );\r
-    if( !info )\r
-        CV_Error( CV_StsBadArg, "Unknown object" );\r
-\r
-    if( !info->write )\r
-        CV_Error( CV_StsBadArg, "The object does not have write function" );\r
-\r
-    info->write( fs, name, ptr, attributes );\r
-}\r
-\r
-\r
-/* simple API for reading/writing data */\r
-CV_IMPL void\r
-cvSave( const char* filename, const void* struct_ptr,\r
-        const char* _name, const char* comment, CvAttrList attributes )\r
-{\r
-    CvFileStorage* fs = 0;\r
-\r
-    if( !struct_ptr )\r
-        CV_Error( CV_StsNullPtr, "NULL object pointer" );\r
-\r
-    fs = cvOpenFileStorage( filename, 0, CV_STORAGE_WRITE );\r
-    if( !fs )\r
-        CV_Error( CV_StsError, "Could not open the file storage. Check the path and permissions" );\r
-\r
-    cv::String name = _name ? cv::String(_name) : cv::FileStorage::getDefaultObjectName(filename);\r
-\r
-    if( comment )\r
-        cvWriteComment( fs, comment, 0 );\r
-    cvWrite( fs, name.c_str(), struct_ptr, attributes );\r
-    cvReleaseFileStorage( &fs );\r
-}\r
-\r
-CV_IMPL void*\r
-cvLoad( const char* filename, CvMemStorage* memstorage,\r
-        const char* name, const char** _real_name )\r
-{\r
-    void* ptr = 0;\r
-    const char* real_name = 0;\r
-    CvFileStorage* fs = 0;\r
-\r
-    CvFileNode* node = 0;\r
-    fs = cvOpenFileStorage( filename, memstorage, CV_STORAGE_READ );\r
-\r
-    if( !fs )\r
-        return 0;\r
-\r
-    if( name )\r
-    {\r
-        node = cvGetFileNodeByName( fs, 0, name );\r
-    }\r
-    else\r
-    {\r
-        int i, k;\r
-        for( k = 0; k < fs->roots->total; k++ )\r
-        {\r
-            CvSeq* seq;\r
-            CvSeqReader reader;\r
-\r
-            node = (CvFileNode*)cvGetSeqElem( fs->roots, k );\r
-            if( !CV_NODE_IS_MAP( node->tag ))\r
-                EXIT;\r
-            seq = node->data.seq;\r
-            node = 0;\r
-\r
-            cvStartReadSeq( seq, &reader, 0 );\r
-\r
-            // find the first element in the map\r
-            for( i = 0; i < seq->total; i++ )\r
-            {\r
-                if( CV_IS_SET_ELEM( reader.ptr ))\r
-                {\r
-                    node = (CvFileNode*)reader.ptr;\r
-                    goto stop_search;\r
-                }\r
-                CV_NEXT_SEQ_ELEM( seq->elem_size, reader );\r
-            }\r
-        }\r
-\r
-stop_search:\r
-        ;\r
-    }\r
-\r
-    if( !node )\r
-        CV_Error( CV_StsObjectNotFound, "Could not find the/an object in file storage" );\r
-\r
-    real_name = cvGetFileNodeName( node );\r
-    ptr = cvRead( fs, node, 0 );\r
-\r
-    // sanity check\r
-    if( !memstorage && (CV_IS_SEQ( ptr ) || CV_IS_SET( ptr )) )\r
-        CV_Error( CV_StsNullPtr,\r
-        "NULL memory storage is passed - the loaded dynamic structure can not be stored" );\r
-\r
-    if( cvGetErrStatus() < 0 )\r
-    {\r
-        cvRelease( (void**)&ptr );\r
-        real_name = 0;\r
-    }\r
-\r
-    if( _real_name)\r
-    {\r
-       if (real_name)\r
-       {\r
-           *_real_name = (const char*)cvAlloc(strlen(real_name));\r
-           memcpy((void*)*_real_name, real_name, strlen(real_name));\r
-       } else {\r
-           *_real_name = 0;\r
-       }\r
-    }\r
-exit:\r
-    cvReleaseFileStorage( &fs );\r
-\r
-    return ptr;\r
-}\r
-\r
-\r
-///////////////////////// new C++ interface for CvFileStorage ///////////////////////////\r
-\r
-namespace cv\r
-{\r
-\r
-static void getElemSize( const String& fmt, size_t& elemSize, size_t& cn )\r
-{\r
-    const char* dt = fmt.c_str();\r
-    cn = 1;\r
-    if( isdigit(dt[0]) )\r
-    {\r
-        cn = dt[0] - '0';\r
-        dt++;\r
-    }\r
-    char c = dt[0];\r
-    elemSize = cn*(c == 'u' || c == 'c' ? sizeof(uchar) : c == 'w' || c == 's' ? sizeof(ushort) :\r
-        c == 'i' ? sizeof(int) : c == 'f' ? sizeof(float) : c == 'd' ? sizeof(double) :\r
-        c == 'r' ? sizeof(void*) : (size_t)0);\r
-}\r
-\r
-FileStorage::FileStorage()\r
-{\r
-    state = UNDEFINED;\r
-}\r
-\r
-FileStorage::FileStorage(const String& filename, int flags)\r
-{\r
-    state = UNDEFINED;\r
-    open( filename, flags );\r
-}\r
-\r
-FileStorage::FileStorage(CvFileStorage* _fs)\r
-{\r
-    fs = Ptr<CvFileStorage>(_fs);\r
-    state = _fs ? NAME_EXPECTED + INSIDE_MAP : UNDEFINED;\r
-}\r
-\r
-FileStorage::~FileStorage()\r
-{\r
-    while( structs.size() > 0 )\r
-    {\r
-        cvEndWriteStruct(fs);\r
-        structs.pop_back();\r
-    }\r
-}\r
-\r
-bool FileStorage::open(const String& filename, int flags)\r
-{\r
-    release();\r
-    fs = Ptr<CvFileStorage>(cvOpenFileStorage( filename.c_str(), 0, flags ));\r
-    bool ok = isOpened();\r
-    state = ok ? NAME_EXPECTED + INSIDE_MAP : UNDEFINED;\r
-    return ok;\r
-}\r
-\r
-bool FileStorage::isOpened() const\r
-{\r
-    return !fs.empty();\r
-}\r
-\r
-void FileStorage::release()\r
-{\r
-    fs.release();\r
-    structs.clear();\r
-    state = UNDEFINED;\r
-}\r
-\r
-FileNode FileStorage::root(int streamidx) const\r
-{\r
-    return isOpened() ? FileNode(fs, cvGetRootFileNode(fs, streamidx)) : FileNode();\r
-}\r
-\r
-FileStorage& operator << (FileStorage& fs, const String& str)\r
-{\r
-    enum { NAME_EXPECTED = FileStorage::NAME_EXPECTED,\r
-        VALUE_EXPECTED = FileStorage::VALUE_EXPECTED,\r
-        INSIDE_MAP = FileStorage::INSIDE_MAP };\r
-    const char* _str = str.c_str();\r
-    if( !fs.isOpened() || !_str )\r
-        return fs;\r
-    if( *_str == '}' || *_str == ']' )\r
-    {\r
-        if( fs.structs.empty() )\r
-            CV_Error_( CV_StsError, ("Extra closing '%c'", *_str) );\r
-        if( (*_str == ']' ? '[' : '{') != fs.structs.back() )\r
-            CV_Error_( CV_StsError,\r
-            ("The closing '%c' does not match the opening '%c'", *_str, fs.structs.back()));\r
-        fs.structs.pop_back();\r
-        fs.state = fs.structs.empty() || fs.structs.back() == '{' ?\r
-            INSIDE_MAP + NAME_EXPECTED : VALUE_EXPECTED;\r
-        cvEndWriteStruct( *fs );\r
-        fs.elname = String();\r
-    }\r
-    else if( fs.state == NAME_EXPECTED + INSIDE_MAP )\r
-    {\r
-        if( !isalpha(*_str) )\r
-            CV_Error_( CV_StsError, ("Incorrect element name %s", _str) );\r
-        fs.elname = str;\r
-        fs.state = VALUE_EXPECTED + INSIDE_MAP;\r
-    }\r
-    else if( (fs.state & 3) == VALUE_EXPECTED )\r
-    {\r
-        if( *_str == '{' || *_str == '[' )\r
-        {\r
-            fs.structs.push_back(*_str);\r
-            int flags = *_str++ == '{' ? CV_NODE_MAP : CV_NODE_SEQ;\r
-            fs.state = flags == CV_NODE_MAP ? INSIDE_MAP +\r
-                NAME_EXPECTED : VALUE_EXPECTED;\r
-            if( *_str == ':' )\r
-            {\r
-                flags |= CV_NODE_FLOW;\r
-                _str++;\r
-            }\r
-            cvStartWriteStruct( *fs, fs.elname.size() > 0 ? fs.elname.c_str() : 0,\r
-                flags, *_str ? _str : 0 );\r
-            fs.elname = String();\r
-        }\r
-        else\r
-        {\r
-            write( fs, fs.elname, (_str[0] == '\\' && (_str[1] == '{' || _str[1] == '}' ||\r
-                _str[1] == '[' || _str[1] == ']')) ? String(_str+1) : str );\r
-            if( fs.state == INSIDE_MAP + VALUE_EXPECTED )\r
-                fs.state = INSIDE_MAP + NAME_EXPECTED;\r
-        }\r
-    }\r
-    else\r
-        CV_Error( CV_StsError, "Invalid fs.state" );\r
-    return fs;\r
-}\r
-\r
-\r
-void FileStorage::writeRaw( const String& fmt, const Vector<uchar>& vec )\r
-{\r
-    if( !isOpened() )\r
-        return;\r
-    size_t elemSize, cn;\r
-    getElemSize( fmt, elemSize, cn );\r
-    CV_Assert( vec.size() % elemSize == 0 );\r
-    cvWriteRawData( fs, &vec[0], (int)(vec.size()/elemSize), fmt.c_str());\r
-}\r
-\r
-\r
-void FileStorage::writeObj( const String& name, const void* obj )\r
-{\r
-    if( !isOpened() )\r
-        return;\r
-    cvWrite( fs, name.size() > 0 ? name.c_str() : 0, obj );\r
-}\r
-\r
-\r
-void* FileNode::readObj() const\r
-{\r
-    if( !fs || !node )\r
-        return 0;\r
-    return cvRead( (CvFileStorage*)fs, (CvFileNode*)node );\r
-}\r
-\r
-\r
-FileNodeIterator::FileNodeIterator()\r
-{\r
-    fs = 0;\r
-    container = 0;\r
-    reader.ptr = 0;\r
-    remaining = 0;\r
-}\r
-\r
-FileNodeIterator::FileNodeIterator(const CvFileStorage* _fs,\r
-                                   const CvFileNode* _node, size_t _ofs)\r
-{\r
-    if( _fs && _node )\r
-    {\r
-        int node_type = _node->tag & FileNode::TYPE_MASK;\r
-        fs = _fs;\r
-        container = _node;\r
-        if( node_type == FileNode::SEQ || node_type == FileNode::MAP )\r
-        {\r
-            cvStartReadSeq( _node->data.seq, &reader );\r
-            remaining = FileNode(_fs, _node).count();\r
-        }\r
-        else\r
-        {\r
-            reader.ptr = (schar*)_node;\r
-            reader.seq = 0;\r
-            remaining = 1;\r
-        }\r
-        (*this) += (int)_ofs;\r
-    }\r
-    else\r
-    {\r
-        fs = 0;\r
-        container = 0;\r
-        reader.ptr = 0;\r
-        remaining = 0;\r
-    }\r
-}\r
-\r
-FileNodeIterator::FileNodeIterator(const FileNodeIterator& it)\r
-{\r
-    fs = it.fs;\r
-    container = it.container;\r
-    reader = it.reader;\r
-    remaining = it.remaining;\r
-}\r
-\r
-FileNodeIterator& FileNodeIterator::operator ++()\r
-{\r
-    if( remaining > 0 )\r
-    {\r
-        if( reader.seq )\r
-            CV_NEXT_SEQ_ELEM( reader.seq->elem_size, reader );\r
-        remaining--;\r
-    }\r
-    return *this;\r
-}\r
-\r
-FileNodeIterator FileNodeIterator::operator ++(int)\r
-{\r
-    FileNodeIterator it = *this;\r
-    ++(*this);\r
-    return it;\r
-}\r
-\r
-FileNodeIterator& FileNodeIterator::operator --()\r
-{\r
-    if( remaining < FileNode(fs, container).count() )\r
-    {\r
-        if( reader.seq )\r
-            CV_PREV_SEQ_ELEM( reader.seq->elem_size, reader );\r
-        remaining++;\r
-    }\r
-    return *this;\r
-}\r
-\r
-FileNodeIterator FileNodeIterator::operator --(int)\r
-{\r
-    FileNodeIterator it = *this;\r
-    --(*this);\r
-    return it;\r
-}\r
-\r
-FileNodeIterator& FileNodeIterator::operator += (int ofs)\r
-{\r
-    if( ofs == 0 )\r
-        return *this;\r
-    if( ofs > 0 )\r
-        ofs = std::min(ofs, (int)remaining);\r
-    else\r
-    {\r
-        size_t count = FileNode(fs, container).count();\r
-        ofs = (int)(remaining - std::min(remaining - ofs, count));\r
-    }\r
-    if( reader.seq )\r
-        cvSetSeqReaderPos( &reader, ofs, 1 );\r
-    return *this;\r
-}\r
-\r
-FileNodeIterator& FileNodeIterator::operator -= (int ofs)\r
-{\r
-    return operator += (-ofs);\r
-}\r
-\r
-\r
-FileNodeIterator& FileNodeIterator::readRaw( const String& fmt, Vector<uchar>& vec, size_t maxCount )\r
-{\r
-    if( fs && container && remaining > 0 )\r
-    {\r
-        size_t elem_size, cn;\r
-        getElemSize( fmt, elem_size, cn );\r
-        CV_Assert( elem_size > 0 );\r
-        size_t count = std::min(remaining, maxCount);\r
-        vec.resize( count*elem_size );\r
-        \r
-        if( reader.seq )\r
-        {\r
-            cvReadRawDataSlice( fs, &reader, (int)count, &vec[0], fmt.c_str() );\r
-            remaining -= count*cn;\r
-        }\r
-        else\r
-        {\r
-            cvReadRawData( fs, container, &vec[0], fmt.c_str() );\r
-            remaining = 0;\r
-        }\r
-    }\r
-    return *this;\r
-}\r
-\r
-}\r
-\r
-/* End of file. */\r
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+//  By downloading, copying, installing or using the software you agree to this license.
+//  If you do not agree to this license, do not download, install,
+//  copy or use the software.
+//
+//
+//                           License Agreement
+//                For Open Source Computer Vision Library
+//
+// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
+// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+//   * Redistribution's of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//
+//   * Redistribution's in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//
+//   * The name of the copyright holders may not be used to endorse or promote products
+//     derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+#include "_cxcore.h"
+#include <ctype.h>
+#include <wchar.h>
+
+/****************************************************************************************\
+*                            Common macros and type definitions                          *
+\****************************************************************************************/
+
+#define cv_isprint(c)     ((signed char)(c) >= (signed char)' ')
+#define cv_isprint_or_tab(c)  ((signed char)(c) >= (signed char)' ' || (c) == '\t')
+
+static char* icv_itoa( int _val, char* buffer, int /*radix*/ )
+{
+    const int radix = 10;
+    char* ptr=buffer + 23 /* enough even for 64-bit integers */;
+    unsigned val = abs(_val);
+
+    *ptr = '\0';
+    do
+    {
+        unsigned r = val / radix;
+        *--ptr = (char)(val - (r*radix) + '0');
+        val = r;
+    }
+    while( val != 0 );
+
+    if( _val < 0 )
+        *--ptr = '-';
+
+    return ptr;
+}
+
+cv::String cv::FileStorage::getDefaultObjectName(const String& _filename)
+{
+    static const char* stubname = "unnamed";
+    const char* filename = _filename.c_str();
+    const char* ptr2 = filename + _filename.size();
+    const char* ptr = ptr2 - 1;
+    cv::AutoBuffer<char> name_buf(_filename.size()+1);
+
+    while( ptr >= filename && *ptr != '\\' && *ptr != '/' && *ptr != ':' )
+    {
+        if( *ptr == '.' && !*ptr2 )
+            ptr2 = ptr;
+        ptr--;
+    }
+    ptr++;
+    if( ptr == ptr2 )
+        CV_Error( CV_StsBadArg, "Invalid filename" );
+
+    char* name = name_buf;
+
+    // name must start with letter or '_'
+    if( !isalpha(*ptr) && *ptr!= '_' ){
+        *name++ = '_';
+    }
+
+    while( ptr < ptr2 )
+    {
+        char c = *ptr++;
+        if( !isalnum(c) && c != '-' && c != '_' )
+            c = '_';
+        *name++ = c;
+    }
+    *name = '\0';
+    name = name_buf;
+    if( strcmp( name, "_" ) == 0 )
+        strcpy( name, stubname );
+    return cv::String(name);
+}
+
+namespace cv
+{
+
+String fromUtf16(const WString& str)
+{
+    cv::AutoBuffer<char> _buf(str.size()*4 + 1);
+    char* buf = _buf;
+        
+    size_t sz = wcstombs(buf, str.c_str(), str.size());
+    if( sz == (size_t)-1 )
+        return String();
+    buf[sz] = '\0';
+    return String(buf);
+}
+
+WString toUtf16(const String& str)
+{
+    cv::AutoBuffer<wchar_t> _buf(str.size() + 1);
+    wchar_t* buf = _buf;
+        
+    size_t sz = mbstowcs(buf, str.c_str(), str.size());
+    if( sz == (size_t)-1 )
+        return WString();
+    buf[sz] = '\0';
+    return WString(buf);
+}
+
+}
+
+typedef struct CvGenericHash
+{
+    CV_SET_FIELDS()
+    int tab_size;
+    void** table;
+}
+CvGenericHash;
+
+typedef CvGenericHash CvStringHash;
+
+typedef struct CvFileMapNode
+{
+    CvFileNode value;
+    const CvStringHashNode* key;
+    struct CvFileMapNode* next;
+}
+CvFileMapNode;
+
+typedef struct CvXMLStackRecord
+{
+    CvMemStoragePos pos;
+    CvString struct_tag;
+    int struct_indent;
+    int struct_flags;
+}
+CvXMLStackRecord;
+
+#define CV_XML_OPENING_TAG 1
+#define CV_XML_CLOSING_TAG 2
+#define CV_XML_EMPTY_TAG 3
+#define CV_XML_HEADER_TAG 4
+#define CV_XML_DIRECTIVE_TAG 5
+
+//typedef void (*CvParse)( struct CvFileStorage* fs );
+typedef void (*CvStartWriteStruct)( struct CvFileStorage* fs, const char* key,
+                                    int struct_flags, const char* type_name );
+typedef void (*CvEndWriteStruct)( struct CvFileStorage* fs );
+typedef void (*CvWriteInt)( struct CvFileStorage* fs, const char* key, int value );
+typedef void (*CvWriteReal)( struct CvFileStorage* fs, const char* key, double value );
+typedef void (*CvWriteString)( struct CvFileStorage* fs, const char* key,
+                               const char* value, int quote );
+typedef void (*CvWriteComment)( struct CvFileStorage* fs, const char* comment, int eol_comment );
+typedef void (*CvStartNextStream)( struct CvFileStorage* fs );
+
+typedef struct CvFileStorage
+{
+    int flags;
+    int is_xml;
+    int write_mode;
+    int is_first;
+    CvMemStorage* memstorage;
+    CvMemStorage* dststorage;
+    CvMemStorage* strstorage;
+    CvStringHash* str_hash;
+    CvSeq* roots;
+    CvSeq* write_stack;
+    int struct_indent;
+    int struct_flags;
+    CvString struct_tag;
+    int space;
+    char* filename;
+    FILE* file;
+    char* buffer;
+    char* buffer_start;
+    char* buffer_end;
+    int wrap_margin;
+    int lineno;
+    int dummy_eof;
+    const char* errmsg;
+    char errmsgbuf[128];
+
+    CvStartWriteStruct start_write_struct;
+    CvEndWriteStruct end_write_struct;
+    CvWriteInt write_int;
+    CvWriteReal write_real;
+    CvWriteString write_string;
+    CvWriteComment write_comment;
+    CvStartNextStream start_next_stream;
+    //CvParse parse;
+}
+CvFileStorage;
+
+
+#define CV_YML_INDENT  3
+#define CV_XML_INDENT  2
+#define CV_YML_INDENT_FLOW  1
+#define CV_FS_MAX_LEN 4096
+
+#define CV_FILE_STORAGE ('Y' + ('A' << 8) + ('M' << 16) + ('L' << 24))
+#define CV_IS_FILE_STORAGE(fs) ((fs) != 0 && (fs)->flags == CV_FILE_STORAGE)
+
+#define CV_CHECK_FILE_STORAGE(fs)                       \
+{                                                       \
+    if( !CV_IS_FILE_STORAGE(fs) )                       \
+        CV_Error( (fs) ? CV_StsBadArg : CV_StsNullPtr,  \
+                  "Invalid pointer to file storage" );  \
+}
+
+#define CV_CHECK_OUTPUT_FILE_STORAGE(fs)                \
+{                                                       \
+    CV_CHECK_FILE_STORAGE(fs);                          \
+    if( !fs->write_mode )                               \
+        CV_Error( CV_StsError, "The file storage is opened for reading" ); \
+}
+
+CV_IMPL const char*
+cvAttrValue( const CvAttrList* attr, const char* attr_name )
+{
+    while( attr && attr->attr )
+    {
+        int i;
+        for( i = 0; attr->attr[i*2] != 0; i++ )
+        {
+            if( strcmp( attr_name, attr->attr[i*2] ) == 0 )
+                return attr->attr[i*2+1];
+        }
+        attr = attr->next;
+    }
+
+    return 0;
+}
+
+
+static CvGenericHash*
+cvCreateMap( int flags, int header_size, int elem_size,
+             CvMemStorage* storage, int start_tab_size )
+{
+    if( header_size < (int)sizeof(CvGenericHash) )
+        CV_Error( CV_StsBadSize, "Too small map header_size" );
+
+    if( start_tab_size <= 0 )
+        start_tab_size = 16;
+
+    CvGenericHash* map = (CvGenericHash*)cvCreateSet( flags, header_size, elem_size, storage );
+
+    map->tab_size = start_tab_size;
+    start_tab_size *= sizeof(map->table[0]);
+    map->table = (void**)cvMemStorageAlloc( storage, start_tab_size );
+    memset( map->table, 0, start_tab_size );
+
+    return map;
+}
+
+#ifdef __GNUC__
+#define CV_PARSE_ERROR( errmsg )                                    \
+    icvParseError( fs, __func__, (errmsg), __FILE__, __LINE__ )
+#else
+#define CV_PARSE_ERROR( errmsg )                                    \
+    icvParseError( fs, "", (errmsg), __FILE__, __LINE__ )
+#endif
+
+static void
+icvParseError( CvFileStorage* fs, const char* func_name,
+               const char* err_msg, const char* source_file, int source_line )
+{
+    char buf[1<<10];
+    sprintf( buf, "%s(%d): %s", fs->filename, fs->lineno, err_msg );
+    cvError( CV_StsParseError, func_name, buf, source_file, source_line );
+}
+
+
+static void
+icvFSCreateCollection( CvFileStorage* fs, int tag, CvFileNode* collection )
+{
+    if( CV_NODE_IS_MAP(tag) )
+    {
+        if( collection->tag != CV_NODE_NONE )
+        {
+            assert( fs->is_xml != 0 );
+            CV_PARSE_ERROR( "Sequence element should not have name (use <_></_>)" );
+        }
+
+        collection->data.map = cvCreateMap( 0, sizeof(CvFileNodeHash),
+                            sizeof(CvFileMapNode), fs->memstorage, 16 );
+    }
+    else
+    {
+        CvSeq* seq;
+        seq = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvFileNode), fs->memstorage );
+
+        // if <collection> contains some scalar element, add it to the newly created collection
+        if( CV_NODE_TYPE(collection->tag) != CV_NODE_NONE )
+            cvSeqPush( seq, collection );
+
+        collection->data.seq = seq;
+    }
+
+    collection->tag = tag;
+    cvSetSeqBlockSize( collection->data.seq, 8 );
+}
+
+
+/*static void
+icvFSReleaseCollection( CvSeq* seq )
+{
+    if( seq )
+    {
+        int is_map = CV_IS_SET(seq);
+        CvSeqReader reader;
+        int i, total = seq->total;
+        cvStartReadSeq( seq, &reader, 0 );
+
+        for( i = 0; i < total; i++ )
+        {
+            CvFileNode* node = (CvFileNode*)reader.ptr;
+
+            if( (!is_map || CV_IS_SET_ELEM( node )) && CV_NODE_IS_COLLECTION(node->tag) )
+            {
+                if( CV_NODE_IS_USER(node->tag) && node->info && node->data.obj.decoded )
+                    cvRelease( (void**)&node->data.obj.decoded );
+                if( !CV_NODE_SEQ_IS_SIMPLE( node->data.seq ))
+                    icvFSReleaseCollection( node->data.seq );
+            }
+            CV_NEXT_SEQ_ELEM( seq->elem_size, reader );
+        }
+    }
+}*/
+
+
+static char*
+icvFSDoResize( CvFileStorage* fs, char* ptr, int len )
+{
+    char* new_ptr = 0;
+    int written_len = (int)(ptr - fs->buffer_start);
+    int new_size = (int)((fs->buffer_end - fs->buffer_start)*3/2);
+    new_size = MAX( written_len + len, new_size );
+    new_ptr = (char*)cvAlloc( new_size + 256 );
+    fs->buffer = new_ptr + (fs->buffer - fs->buffer_start);
+    if( written_len > 0 )
+        memcpy( new_ptr, fs->buffer_start, written_len );
+    fs->buffer_start = new_ptr;
+    fs->buffer_end = fs->buffer_start + new_size;
+    new_ptr += written_len;
+    return new_ptr;
+}
+
+
+inline char* icvFSResizeWriteBuffer( CvFileStorage* fs, char* ptr, int len )
+{
+    return ptr + len < fs->buffer_end ? ptr : icvFSDoResize( fs, ptr, len );
+}
+
+
+static char*
+icvFSFlush( CvFileStorage* fs )
+{
+    char* ptr = fs->buffer;
+    int indent;
+
+    if( ptr > fs->buffer_start + fs->space )
+    {
+        ptr[0] = '\n';
+        ptr[1] = '\0';
+        fputs( fs->buffer_start, fs->file );
+        fs->buffer = fs->buffer_start;
+    }
+
+    indent = fs->struct_indent;
+
+    if( fs->space != indent )
+    {
+        if( fs->space < indent )
+            memset( fs->buffer_start + fs->space, ' ', indent - fs->space );
+        fs->space = indent;
+    }
+
+    ptr = fs->buffer = fs->buffer_start + fs->space;
+
+    return ptr;
+}
+
+
+/* closes file storage and deallocates buffers */
+CV_IMPL  void
+cvReleaseFileStorage( CvFileStorage** p_fs )
+{
+    if( !p_fs )
+        CV_Error( CV_StsNullPtr, "NULL double pointer to file storage" );
+
+    if( *p_fs )
+    {
+        CvFileStorage* fs = *p_fs;
+        *p_fs = 0;
+
+        if( fs->write_mode && fs->file )
+        {
+            if( fs->write_stack )
+            {
+                while( fs->write_stack->total > 0 )
+                    cvEndWriteStruct(fs);
+            }
+            icvFSFlush(fs);
+            if( fs->is_xml )
+                fputs("</opencv_storage>\n", fs->file );
+        }
+
+        //icvFSReleaseCollection( fs->roots ); // delete all the user types recursively
+
+        if( fs->file )
+        {
+            fclose( fs->file );
+            fs->file = 0;
+        }
+
+        cvReleaseMemStorage( &fs->strstorage );
+
+        cvFree( &fs->buffer_start );
+        cvReleaseMemStorage( &fs->memstorage );
+
+        memset( fs, 0, sizeof(*fs) );
+        cvFree( &fs );
+    }
+}
+
+
+#define CV_HASHVAL_SCALE 33
+
+CV_IMPL CvStringHashNode*
+cvGetHashedKey( CvFileStorage* fs, const char* str, int len, int create_missing )
+{
+    CvStringHashNode* node = 0;
+    unsigned hashval = 0;
+    int i, tab_size;
+    CvStringHash* map = fs->str_hash;
+
+    if( !fs )
+        return 0;
+
+    if( len < 0 )
+    {
+        for( i = 0; str[i] != '\0'; i++ )
+            hashval = hashval*CV_HASHVAL_SCALE + (unsigned char)str[i];
+        len = i;
+    }
+    else for( i = 0; i < len; i++ )
+        hashval = hashval*CV_HASHVAL_SCALE + (unsigned char)str[i];
+
+    hashval &= INT_MAX;
+    tab_size = map->tab_size;
+    if( (tab_size & (tab_size - 1)) == 0 )
+        i = (int)(hashval & (tab_size - 1));
+    else
+        i = (int)(hashval % tab_size);
+
+    for( node = (CvStringHashNode*)(map->table[i]); node != 0; node = node->next )
+    {
+        if( node->hashval == hashval &&
+            node->str.len == len &&
+            memcmp( node->str.ptr, str, len ) == 0 )
+            break;
+    }
+
+    if( !node && create_missing )
+    {
+        node = (CvStringHashNode*)cvSetNew( (CvSet*)map );
+        node->hashval = hashval;
+        node->str = cvMemStorageAllocString( map->storage, str, len );
+        node->next = (CvStringHashNode*)(map->table[i]);
+        map->table[i] = node;
+    }
+
+    return node;
+}
+
+
+CV_IMPL CvFileNode*
+cvGetFileNode( CvFileStorage* fs, CvFileNode* _map_node,
+               const CvStringHashNode* key,
+               int create_missing )
+{
+    CvFileNode* value = 0;
+    int k = 0, attempts = 1;
+
+    if( !fs )
+        return 0;
+
+    CV_CHECK_FILE_STORAGE(fs);
+
+    if( !key )
+        CV_Error( CV_StsNullPtr, "Null key element" );
+
+    if( _map_node )
+    {
+        if( !fs->roots )
+            return 0;
+        attempts = fs->roots->total;
+    }
+
+    for( k = 0; k < attempts; k++ )
+    {
+        int i, tab_size;
+        CvFileNode* map_node = _map_node;
+        CvFileMapNode* another;
+        CvFileNodeHash* map;
+
+        if( !map_node )
+            map_node = (CvFileNode*)cvGetSeqElem( fs->roots, k );
+
+        if( !CV_NODE_IS_MAP(map_node->tag) )
+        {
+            if( (!CV_NODE_IS_SEQ(map_node->tag) || map_node->data.seq->total != 0) &&
+                CV_NODE_TYPE(map_node->tag) != CV_NODE_NONE )
+                CV_Error( CV_StsError, "The node is neither a map nor an empty collection" );
+            return 0;
+        }
+
+        map = map_node->data.map;
+        tab_size = map->tab_size;
+
+        if( (tab_size & (tab_size - 1)) == 0 )
+            i = (int)(key->hashval & (tab_size - 1));
+        else
+            i = (int)(key->hashval % tab_size);
+
+        for( another = (CvFileMapNode*)(map->table[i]); another != 0; another = another->next )
+            if( another->key == key )
+            {
+                if( !create_missing )
+                {
+                    value = &another->value;
+                    return value;
+                }
+                CV_PARSE_ERROR( "Duplicated key" );
+            }
+
+        if( k == attempts - 1 && create_missing )
+        {
+            CvFileMapNode* node = (CvFileMapNode*)cvSetNew( (CvSet*)map );
+            node->key = key;
+
+            node->next = (CvFileMapNode*)(map->table[i]);
+            map->table[i] = node;
+            value = (CvFileNode*)node;
+        }
+    }
+
+    return value;
+}
+
+
+CV_IMPL CvFileNode*
+cvGetFileNodeByName( const CvFileStorage* fs, const CvFileNode* _map_node, const char* str )
+{
+    CvFileNode* value = 0;
+    int i, len, tab_size;
+    unsigned hashval = 0;
+    int k = 0, attempts = 1;
+
+    if( !fs )
+        return 0;
+
+    CV_CHECK_FILE_STORAGE(fs);
+
+    if( !str )
+        CV_Error( CV_StsNullPtr, "Null element name" );
+
+    for( i = 0; str[i] != '\0'; i++ )
+        hashval = hashval*CV_HASHVAL_SCALE + (unsigned char)str[i];
+    hashval &= INT_MAX;
+    len = i;
+
+    if( !_map_node )
+    {
+        if( !fs->roots )
+            return 0;
+        attempts = fs->roots->total;
+    }
+
+    for( k = 0; k < attempts; k++ )
+    {
+        CvFileNodeHash* map;
+        const CvFileNode* map_node = _map_node;
+        CvFileMapNode* another;
+
+        if( !map_node )
+            map_node = (CvFileNode*)cvGetSeqElem( fs->roots, k );
+
+        if( !CV_NODE_IS_MAP(map_node->tag) )
+        {
+            if( (!CV_NODE_IS_SEQ(map_node->tag) || map_node->data.seq->total != 0) &&
+                CV_NODE_TYPE(map_node->tag) != CV_NODE_NONE )
+                CV_Error( CV_StsError, "The node is neither a map nor an empty collection" );
+            return 0;
+        }
+
+        map = map_node->data.map;
+        tab_size = map->tab_size;
+
+        if( (tab_size & (tab_size - 1)) == 0 )
+            i = (int)(hashval & (tab_size - 1));
+        else
+            i = (int)(hashval % tab_size);
+
+        for( another = (CvFileMapNode*)(map->table[i]); another != 0; another = another->next )
+        {
+            const CvStringHashNode* key = another->key;
+
+            if( key->hashval == hashval &&
+                key->str.len == len &&
+                memcmp( key->str.ptr, str, len ) == 0 )
+            {
+                value = &another->value;
+                return value;
+            }
+        }
+    }
+
+    return value;
+}
+
+
+CV_IMPL CvFileNode*
+cvGetRootFileNode( const CvFileStorage* fs, int stream_index )
+{
+    CV_CHECK_FILE_STORAGE(fs);
+
+    if( !fs->roots || (unsigned)stream_index >= (unsigned)fs->roots->total )
+        return 0;
+
+    return (CvFileNode*)cvGetSeqElem( fs->roots, stream_index );
+}
+
+
+/* returns the sequence element by its index */
+/*CV_IMPL CvFileNode*
+cvGetFileNodeFromSeq( CvFileStorage* fs,
+                      CvFileNode* seq_node, int index )
+{
+    CvFileNode* value = 0;
+    CvSeq* seq;
+
+    if( !seq_node )
+        seq = fs->roots;
+    else if( !CV_NODE_IS_SEQ(seq_node->tag) )
+    {
+        if( CV_NODE_IS_MAP(seq_node->tag) )
+            CV_Error( CV_StsError, "The node is map. Use cvGetFileNodeFromMap()." );
+        if( CV_NODE_TYPE(seq_node->tag) == CV_NODE_NONE )
+            CV_Error( CV_StsError, "The node is an empty object (None)." );
+        if( index != 0 && index != -1 )
+            CV_Error( CV_StsOutOfRange, "" );
+        value = seq_node;
+        EXIT;
+    }
+    else
+        seq = seq_node->data.seq;
+
+    if( !seq )
+        CV_Error( CV_StsNullPtr, "The file storage is empty" );
+
+    value = (CvFileNode*)cvGetSeqElem( seq, index, 0 );
+
+    
+
+    return value;
+}*/
+
+
+static char*
+icvDoubleToString( char* buf, double value )
+{
+    Cv64suf val;
+    unsigned ieee754_hi;
+
+    val.f = value;
+    ieee754_hi = (unsigned)(val.u >> 32);
+
+    if( (ieee754_hi & 0x7ff00000) != 0x7ff00000 )
+    {
+        int ivalue = cvRound(value);
+        if( ivalue == value )
+            sprintf( buf, "%d.", ivalue );
+        else
+        {
+            static const char* fmt[] = {"%.16e", "%.16f"};
+            double avalue = fabs(value);
+            char* ptr = buf;
+            sprintf( buf, fmt[0.01 <= avalue && avalue < 1000], value );
+            if( *ptr == '+' || *ptr == '-' )
+                ptr++;
+            for( ; isdigit(*ptr); ptr++ )
+                ;
+            if( *ptr == ',' )
+                *ptr = '.';
+        }
+    }
+    else
+    {
+        unsigned ieee754_lo = (unsigned)val.u;
+        if( (ieee754_hi & 0x7fffffff) + (ieee754_lo != 0) > 0x7ff00000 )
+            strcpy( buf, ".Nan" );
+        else
+            strcpy( buf, (int)ieee754_hi < 0 ? "-.Inf" : ".Inf" );
+    }
+
+    return buf;
+}
+
+
+static char*
+icvFloatToString( char* buf, float value )
+{
+    Cv32suf val;
+    unsigned ieee754;
+    val.f = value;
+    ieee754 = val.u;
+
+    if( (ieee754 & 0x7f800000) != 0x7f800000 )
+    {
+        int ivalue = cvRound(value);
+        if( ivalue == value )
+            sprintf( buf, "%d.", ivalue );
+        else
+        {
+            static const char* fmt[] = {"%.8e", "%.8f"};
+            double avalue = fabs((double)value);
+            char* ptr = buf;
+            sprintf( buf, fmt[0.01 <= avalue && avalue < 1000], value );
+            if( *ptr == '+' || *ptr == '-' )
+                ptr++;
+            for( ; isdigit(*ptr); ptr++ )
+                ;
+            if( *ptr == ',' )
+                *ptr = '.';
+        }
+    }
+    else
+    {
+        if( (ieee754 & 0x7fffffff) != 0x7f800000 )
+            strcpy( buf, ".Nan" );
+        else
+            strcpy( buf, (int)ieee754 < 0 ? "-.Inf" : ".Inf" );
+    }
+
+    return buf;
+}
+
+
+static void
+icvProcessSpecialDouble( CvFileStorage* fs, char* buf, double* value, char** endptr )
+{
+    char c = buf[0];
+    int inf_hi = 0x7ff00000;
+
+    if( c == '-' || c == '+' )
+    {
+        inf_hi = c == '-' ? 0xfff00000 : 0x7ff00000;
+        c = *++buf;
+    }
+
+    if( c != '.' )
+        CV_PARSE_ERROR( "Bad format of floating-point constant" );
+
+    if( toupper(buf[1]) == 'I' && toupper(buf[2]) == 'N' && toupper(buf[3]) == 'F' )
+        *(uint64*)value = ((uint64)inf_hi << 32);
+    else if( toupper(buf[1]) == 'N' && toupper(buf[2]) == 'A' && toupper(buf[3]) == 'N' )
+        *(uint64*)value = (uint64)-1;
+    else
+        CV_PARSE_ERROR( "Bad format of floating-point constant" );
+
+    *endptr = buf + 4;
+}
+
+
+static double icv_strtod( CvFileStorage* fs, char* ptr, char** endptr )
+{
+    double fval = strtod( ptr, endptr );
+    if( **endptr == '.' )
+    {
+        char* dot_pos = *endptr;
+        *dot_pos = ',';
+        double fval2 = strtod( ptr, endptr );
+        *dot_pos = '.';
+        if( *endptr > dot_pos )
+            fval = fval2;
+        else
+            *endptr = dot_pos;
+    }
+
+    if( *endptr == ptr || isalpha(**endptr) )
+        icvProcessSpecialDouble( fs, ptr, &fval, endptr );
+
+    return fval;
+}
+
+
+/****************************************************************************************\
+*                                       YAML Parser                                      *
+\****************************************************************************************/
+
+static char*
+icvYMLSkipSpaces( CvFileStorage* fs, char* ptr, int min_indent, int max_comment_indent )
+{
+    for(;;)
+    {
+        while( *ptr == ' ' )
+            ptr++;
+        if( *ptr == '#' )
+        {
+            if( ptr - fs->buffer_start > max_comment_indent )
+                return ptr;
+            *ptr = '\0';
+        }
+        else if( cv_isprint(*ptr) )
+        {
+            if( ptr - fs->buffer_start < min_indent )
+                CV_PARSE_ERROR( "Incorrect indentation" );
+            break;
+        }
+        else if( *ptr == '\0' || *ptr == '\n' || *ptr == '\r' )
+        {
+            int max_size = (int)(fs->buffer_end - fs->buffer_start);
+            ptr = fgets( fs->buffer_start, max_size, fs->file );
+            if( !ptr )
+            {
+                // emulate end of stream
+                ptr = fs->buffer_start;
+                ptr[0] = ptr[1] = ptr[2] = '.';
+                ptr[3] = '\0';
+                fs->dummy_eof = 1;
+                break;
+            }
+            else
+            {
+                int l = (int)strlen(ptr);
+                if( ptr[l-1] != '\n' && ptr[l-1] != '\r' && !feof(fs->file) )
+                    CV_PARSE_ERROR( "Too long string or a last string w/o newline" );
+            }
+
+            fs->lineno++;
+        }
+        else
+            CV_PARSE_ERROR( *ptr == '\t' ? "Tabs are prohibited in YAML!" : "Invalid character" );
+    }
+
+    return ptr;
+}
+
+
+static char*
+icvYMLParseKey( CvFileStorage* fs, char* ptr,
+                CvFileNode* map_node, CvFileNode** value_placeholder )
+{
+    char c;
+    char *endptr = ptr - 1, *saveptr;
+    CvStringHashNode* str_hash_node;
+
+    if( *ptr == '-' )
+        CV_PARSE_ERROR( "Key may not start with \'-\'" );
+
+    do c = *++endptr;
+    while( cv_isprint(c) && c != ':' );
+
+    if( c != ':' )
+        CV_PARSE_ERROR( "Missing \':\'" );
+
+    saveptr = endptr + 1;
+    do c = *--endptr;
+    while( c == ' ' );
+
+    ++endptr;
+    if( endptr == ptr )
+        CV_PARSE_ERROR( "An empty key" );
+
+    str_hash_node = cvGetHashedKey( fs, ptr, (int)(endptr - ptr), 1 );
+    *value_placeholder = cvGetFileNode( fs, map_node, str_hash_node, 1 );
+    ptr = saveptr;
+
+    return ptr;
+}
+
+
+static char*
+icvYMLParseValue( CvFileStorage* fs, char* ptr, CvFileNode* node,
+                  int parent_flags, int min_indent )
+{
+    char buf[CV_FS_MAX_LEN + 1024];
+    char* endptr = 0;
+    char c = ptr[0], d = ptr[1];
+    int is_parent_flow = CV_NODE_IS_FLOW(parent_flags);
+    int value_type = CV_NODE_NONE;
+    int len;
+
+    memset( node, 0, sizeof(*node) );
+
+    if( c == '!' ) // handle explicit type specification
+    {
+        if( d == '!' || d == '^' )
+        {
+            ptr++;
+            value_type |= CV_NODE_USER;
+        }
+
+        endptr = ptr++;
+        do d = *++endptr;
+        while( cv_isprint(d) && d != ' ' );
+        len = (int)(endptr - ptr);
+        if( len == 0 )
+            CV_PARSE_ERROR( "Empty type name" );
+        d = *endptr;
+        *endptr = '\0';
+
+        if( len == 3 && !CV_NODE_IS_USER(value_type) )
+        {
+            if( memcmp( ptr, "str", 3 ) == 0 )
+                value_type = CV_NODE_STRING;
+            else if( memcmp( ptr, "int", 3 ) == 0 )
+                value_type = CV_NODE_INT;
+            else if( memcmp( ptr, "seq", 3 ) == 0 )
+                value_type = CV_NODE_SEQ;
+            else if( memcmp( ptr, "map", 3 ) == 0 )
+                value_type = CV_NODE_MAP;
+        }
+        else if( len == 5 && !CV_NODE_IS_USER(value_type) )
+        {
+            if( memcmp( ptr, "float", 5 ) == 0 )
+                value_type = CV_NODE_REAL;
+        }
+        else if( CV_NODE_IS_USER(value_type) )
+        {
+            node->info = cvFindType( ptr );
+            if( !node->info )
+                node->tag &= ~CV_NODE_USER;
+        }
+
+        *endptr = d;
+        ptr = icvYMLSkipSpaces( fs, endptr, min_indent, INT_MAX );
+
+        c = *ptr;
+
+        if( !CV_NODE_IS_USER(value_type) )
+        {
+            if( value_type == CV_NODE_STRING && c != '\'' && c != '\"' )
+                goto force_string;
+            if( value_type == CV_NODE_INT )
+                goto force_int;
+            if( value_type == CV_NODE_REAL )
+                goto force_real;
+        }
+    }
+
+    if( isdigit(c) ||
+        ((c == '-' || c == '+') && (isdigit(d) || d == '.')) ||
+        (c == '.' && isalnum(d))) // a number
+    {
+        double fval;
+        int ival;
+        endptr = ptr + (c == '-' || c == '+');
+        while( isdigit(*endptr) )
+            endptr++;
+        if( *endptr == '.' || *endptr == 'e' )
+        {
+force_real:
+            fval = icv_strtod( fs, ptr, &endptr );
+            /*if( endptr == ptr || isalpha(*endptr) )
+                icvProcessSpecialDouble( fs, endptr, &fval, &endptr ));*/
+
+            node->tag = CV_NODE_REAL;
+            node->data.f = fval;
+        }
+        else
+        {
+force_int:
+            ival = (int)strtol( ptr, &endptr, 0 );
+            node->tag = CV_NODE_INT;
+            node->data.i = ival;
+        }
+
+        if( !endptr || endptr == ptr )
+            CV_PARSE_ERROR( "Invalid numeric value (inconsistent explicit type specification?)" );
+
+        ptr = endptr;
+    }
+    else if( c == '\'' || c == '\"' ) // an explicit string
+    {
+        node->tag = CV_NODE_STRING;
+        if( c == '\'' )
+            for( len = 0; len < CV_FS_MAX_LEN; )
+            {
+                c = *++ptr;
+                if( isalnum(c) || (c != '\'' && cv_isprint(c)))
+                    buf[len++] = c;
+                else if( c == '\'' )
+                {
+                    c = *++ptr;
+                    if( c != '\'' )
+                        break;
+                    buf[len++] = c;
+                }
+                else
+                    CV_PARSE_ERROR( "Invalid character" );
+            }
+        else
+            for( len = 0; len < CV_FS_MAX_LEN; )
+            {
+                c = *++ptr;
+                if( isalnum(c) || (c != '\\' && c != '\"' && cv_isprint(c)))
+                    buf[len++] = c;
+                else if( c == '\"' )
+                {
+                    ++ptr;
+                    break;
+                }
+                else if( c == '\\' )
+                {
+                    d = *++ptr;
+                    if( d == '\'' )
+                        buf[len++] = d;
+                    else if( d == '\"' || d == '\\' || d == '\'' )
+                        buf[len++] = d;
+                    else if( d == 'n' )
+                        buf[len++] = '\n';
+                    else if( d == 'r' )
+                        buf[len++] = '\r';
+                    else if( d == 't' )
+                        buf[len++] = '\t';
+                    else if( d == 'x' || (isdigit(d) && d < '8') )
+                    {
+                        int val, is_hex = d == 'x';
+                        c = ptr[3];
+                        ptr[3] = '\0';
+                        val = strtol( ptr + is_hex, &endptr, is_hex ? 8 : 16 );
+                        ptr[3] = c;
+                        if( endptr == ptr + is_hex )
+                            buf[len++] = 'x';
+                        else
+                        {
+                            buf[len++] = (char)val;
+                            ptr = endptr;
+                        }
+                    }
+                }
+                else
+                    CV_PARSE_ERROR( "Invalid character" );
+            }
+
+        if( len >= CV_FS_MAX_LEN )
+            CV_PARSE_ERROR( "Too long string literal" );
+
+        node->data.str = cvMemStorageAllocString( fs->memstorage, buf, len );
+    }
+    else if( c == '[' || c == '{' ) // collection as a flow
+    {
+        int new_min_indent = min_indent + !is_parent_flow;
+        int struct_flags = CV_NODE_FLOW + (c == '{' ? CV_NODE_MAP : CV_NODE_SEQ);
+        int is_simple = 1;
+
+        icvFSCreateCollection( fs, CV_NODE_TYPE(struct_flags) +
+                                        (node->info ? CV_NODE_USER : 0), node );
+
+        d = c == '[' ? ']' : '}';
+
+        for( ++ptr ;;)
+        {
+            CvFileNode* elem = 0;
+
+            ptr = icvYMLSkipSpaces( fs, ptr, new_min_indent, INT_MAX );
+            if( *ptr == '}' || *ptr == ']' )
+            {
+                if( *ptr != d )
+                    CV_PARSE_ERROR( "The wrong closing bracket" );
+                ptr++;
+                break;
+            }
+
+            if( node->data.seq->total != 0 )
+            {
+                if( *ptr != ',' )
+                    CV_PARSE_ERROR( "Missing , between the elements" );
+                ptr = icvYMLSkipSpaces( fs, ptr + 1, new_min_indent, INT_MAX );
+            }
+
+            if( CV_NODE_IS_MAP(struct_flags) )
+            {
+                ptr = icvYMLParseKey( fs, ptr, node, &elem );
+                ptr = icvYMLSkipSpaces( fs, ptr, new_min_indent, INT_MAX );
+            }
+            else
+            {
+                if( *ptr == ']' )
+                    break;
+                elem = (CvFileNode*)cvSeqPush( node->data.seq, 0 );
+            }
+            ptr = icvYMLParseValue( fs, ptr, elem, struct_flags, new_min_indent );
+            if( CV_NODE_IS_MAP(struct_flags) )
+                elem->tag |= CV_NODE_NAMED;
+            is_simple &= !CV_NODE_IS_COLLECTION(elem->tag);
+        }
+        node->data.seq->flags |= is_simple ? CV_NODE_SEQ_SIMPLE : 0;
+    }
+    else
+    {
+        int indent, struct_flags, is_simple;
+
+        if( is_parent_flow || c != '-' )
+        {
+            // implicit (one-line) string or nested block-style collection
+            if( !is_parent_flow )
+            {
+                if( c == '?' )
+                    CV_PARSE_ERROR( "Complex keys are not supported" );
+                if( c == '|' || c == '>' )
+                    CV_PARSE_ERROR( "Multi-line text literals are not supported" );
+            }
+
+force_string:
+            endptr = ptr - 1;
+
+            do c = *++endptr;
+            while( cv_isprint(c) &&
+                   (!is_parent_flow || (c != ',' && c != '}' && c != ']')) &&
+                   (is_parent_flow || c != ':' || value_type == CV_NODE_STRING));
+
+            if( endptr == ptr )
+                CV_PARSE_ERROR( "Invalid character" );
+
+            if( is_parent_flow || c != ':' )
+            {
+                char* str_end = endptr;
+                node->tag = CV_NODE_STRING;
+                // strip spaces in the end of string
+                do c = *--str_end;
+                while( str_end > ptr && c == ' ' );
+                str_end++;
+                node->data.str = cvMemStorageAllocString( fs->memstorage, ptr, (int)(str_end - ptr) );
+                ptr = endptr;
+                return ptr;
+            }
+            struct_flags = CV_NODE_MAP;
+        }
+        else
+            struct_flags = CV_NODE_SEQ;
+
+        icvFSCreateCollection( fs, struct_flags +
+                    (node->info ? CV_NODE_USER : 0), node );
+
+        indent = (int)(ptr - fs->buffer_start);
+        is_simple = 1;
+
+        for(;;)
+        {
+            CvFileNode* elem = 0;
+
+            if( CV_NODE_IS_MAP(struct_flags) )
+            {
+                ptr = icvYMLParseKey( fs, ptr, node, &elem );
+            }
+            else
+            {
+                c = *ptr++;
+                if( c != '-' )
+                    CV_PARSE_ERROR( "Block sequence elements must be preceded with \'-\'" );
+
+                elem = (CvFileNode*)cvSeqPush( node->data.seq, 0 );
+            }
+
+            ptr = icvYMLSkipSpaces( fs, ptr, indent + 1, INT_MAX );
+            ptr = icvYMLParseValue( fs, ptr, elem, struct_flags, indent + 1 );
+            if( CV_NODE_IS_MAP(struct_flags) )
+                elem->tag |= CV_NODE_NAMED;
+            is_simple &= !CV_NODE_IS_COLLECTION(elem->tag);
+
+            ptr = icvYMLSkipSpaces( fs, ptr, 0, INT_MAX );
+            if( ptr - fs->buffer_start != indent )
+            {
+                if( ptr - fs->buffer_start < indent )
+                    break;
+                else
+                    CV_PARSE_ERROR( "Incorrect indentation" );
+            }
+            if( memcmp( ptr, "...", 3 ) == 0 )
+                break;
+        }
+
+        node->data.seq->flags |= is_simple ? CV_NODE_SEQ_SIMPLE : 0;
+    }
+
+    return ptr;
+}
+
+
+static void
+icvYMLParse( CvFileStorage* fs )
+{
+    char* ptr = fs->buffer_start;
+    int is_first = 1;
+
+    for(;;)
+    {
+        // 0. skip leading comments and directives  and ...
+        // 1. reach the first item
+        for(;;)
+        {
+            ptr = icvYMLSkipSpaces( fs, ptr, 0, INT_MAX );
+            if( !ptr )
+                return;
+
+            if( *ptr == '%' )
+            {
+                if( memcmp( ptr, "%YAML:", 6 ) == 0 &&
+                    memcmp( ptr, "%YAML:1.", 8 ) != 0 )
+                    CV_PARSE_ERROR( "Unsupported YAML version (it must be 1.x)" );
+                *ptr = '\0';
+            }
+            else if( *ptr == '-' )
+            {
+                if( memcmp(ptr, "---", 3) == 0 )
+                {
+                    ptr += 3;
+                    break;
+                }
+                else if( is_first )
+                    break;
+            }
+            else if( isalnum(*ptr) || *ptr=='_')
+            {
+                if( !is_first )
+                    CV_PARSE_ERROR( "The YAML streams must start with '---', except the first one" );
+                break;
+            }
+            else
+                CV_PARSE_ERROR( "Invalid or unsupported syntax" );
+        }
+
+        ptr = icvYMLSkipSpaces( fs, ptr, 0, INT_MAX );
+        if( memcmp( ptr, "...", 3 ) != 0 )
+        {
+            // 2. parse the collection
+            CvFileNode* root_node = (CvFileNode*)cvSeqPush( fs->roots, 0 );
+
+            ptr = icvYMLParseValue( fs, ptr, root_node, CV_NODE_NONE, 0 );
+            if( !CV_NODE_IS_COLLECTION(root_node->tag) )
+                CV_PARSE_ERROR( "Only collections as YAML streams are supported by this parser" );
+
+            // 3. parse until the end of file or next collection
+            ptr = icvYMLSkipSpaces( fs, ptr, 0, INT_MAX );
+            if( !ptr )
+                return;
+        }
+
+        if( fs->dummy_eof )
+            break;
+        ptr += 3;
+        is_first = 0;
+    }
+}
+
+
+/****************************************************************************************\
+*                                       YAML Emitter                                     *
+\****************************************************************************************/
+
+static void
+icvYMLWrite( CvFileStorage* fs, const char* key, const char* data )
+{
+    int i, keylen = 0;
+    int datalen = 0;
+    int struct_flags;
+    char* ptr;
+
+    struct_flags = fs->struct_flags;
+
+    if( key && key[0] == '\0' )
+        key = 0;
+
+    if( CV_NODE_IS_COLLECTION(struct_flags) )
+    {
+        if( (CV_NODE_IS_MAP(struct_flags) ^ (key != 0)) )
+            CV_Error( CV_StsBadArg, "An attempt to add element without a key to a map, "
+                                    "or add element with key to sequence" );
+    }
+    else
+    {
+        fs->is_first = 0;
+        struct_flags = CV_NODE_EMPTY | (key ? CV_NODE_MAP : CV_NODE_SEQ);
+    }
+
+    if( key )
+    {
+        keylen = (int)strlen(key);
+        if( keylen == 0 )
+            CV_Error( CV_StsBadArg, "The key is an empty" );
+
+        if( keylen > CV_FS_MAX_LEN )
+            CV_Error( CV_StsBadArg, "The key is too long" );
+    }
+
+    if( data )
+        datalen = (int)strlen(data);
+
+    if( CV_NODE_IS_FLOW(struct_flags) )
+    {
+        int new_offset;
+        ptr = fs->buffer;
+        if( !CV_NODE_IS_EMPTY(struct_flags) )
+            *ptr++ = ',';
+        new_offset = (int)(ptr - fs->buffer_start) + keylen + datalen;
+        if( new_offset > fs->wrap_margin && new_offset - fs->struct_indent > 10 )
+        {
+            fs->buffer = ptr;
+            ptr = icvFSFlush(fs);
+        }
+        else
+            *ptr++ = ' ';
+    }
+    else
+    {
+        ptr = icvFSFlush(fs);
+        if( !CV_NODE_IS_MAP(struct_flags) )
+        {
+            *ptr++ = '-';
+            if( data )
+                *ptr++ = ' ';
+        }
+    }
+
+    if( key )
+    {
+        if( !isalpha(key[0]) && key[0] != '_' )
+            CV_Error( CV_StsBadArg, "Key must start with a letter or _" );
+
+        ptr = icvFSResizeWriteBuffer( fs, ptr, keylen );
+
+        for( i = 0; i < keylen; i++ )
+        {
+            int c = key[i];
+
+            ptr[i] = (char)c;
+            if( !isalnum(c) && c != '-' && c != '_' && c != ' ' )
+                CV_Error( CV_StsBadArg, "Key names may only contain alphanumeric characters [a-zA-Z0-9], '-', '_' and ' '" );
+        }
+
+        ptr += keylen;
+        *ptr++ = ':';
+        if( !CV_NODE_IS_FLOW(struct_flags) && data )
+            *ptr++ = ' ';
+    }
+
+    if( data )
+    {
+        ptr = icvFSResizeWriteBuffer( fs, ptr, datalen );
+        memcpy( ptr, data, datalen );
+        ptr += datalen;
+    }
+
+    fs->buffer = ptr;
+    fs->struct_flags = struct_flags & ~CV_NODE_EMPTY;
+}
+
+
+static void
+icvYMLStartWriteStruct( CvFileStorage* fs, const char* key, int struct_flags,
+                        const char* type_name CV_DEFAULT(0))
+{
+    int parent_flags;
+    char buf[CV_FS_MAX_LEN + 1024];
+    const char* data = 0;
+
+    struct_flags = (struct_flags & (CV_NODE_TYPE_MASK|CV_NODE_FLOW)) | CV_NODE_EMPTY;
+    if( !CV_NODE_IS_COLLECTION(struct_flags))
+        CV_Error( CV_StsBadArg,
+        "Some collection type - CV_NODE_SEQ or CV_NODE_MAP, must be specified" );
+
+    if( CV_NODE_IS_FLOW(struct_flags) )
+    {
+        char c = CV_NODE_IS_MAP(struct_flags) ? '{' : '[';
+        struct_flags |= CV_NODE_FLOW;
+
+        if( type_name )
+            sprintf( buf, "!!%s %c", type_name, c );
+        else
+        {
+            buf[0] = c;
+            buf[1] = '\0';
+        }
+        data = buf;
+    }
+    else if( type_name )
+    {
+        sprintf( buf, "!!%s", type_name );
+        data = buf;
+    }
+
+    icvYMLWrite( fs, key, data );
+
+    parent_flags = fs->struct_flags;
+    cvSeqPush( fs->write_stack, &parent_flags );
+    fs->struct_flags = struct_flags;
+
+    if( !CV_NODE_IS_FLOW(parent_flags) )
+        fs->struct_indent += CV_YML_INDENT + CV_NODE_IS_FLOW(struct_flags);
+}
+
+
+static void
+icvYMLEndWriteStruct( CvFileStorage* fs )
+{
+    int parent_flags = 0, struct_flags;
+    char* ptr;
+
+    struct_flags = fs->struct_flags;
+    if( fs->write_stack->total == 0 )
+        CV_Error( CV_StsError, "EndWriteStruct w/o matching StartWriteStruct" );
+
+    cvSeqPop( fs->write_stack, &parent_flags );
+
+    if( CV_NODE_IS_FLOW(struct_flags) )
+    {
+        ptr = fs->buffer;
+        if( ptr > fs->buffer_start + fs->struct_indent && !CV_NODE_IS_EMPTY(struct_flags) )
+            *ptr++ = ' ';
+        *ptr++ = CV_NODE_IS_MAP(struct_flags) ? '}' : ']';
+        fs->buffer = ptr;
+    }
+    else if( CV_NODE_IS_EMPTY(struct_flags) )
+    {
+        ptr = icvFSFlush(fs);
+        memcpy( ptr, CV_NODE_IS_MAP(struct_flags) ? "{}" : "[]", 2 );
+        fs->buffer = ptr + 2;
+    }
+
+    if( !CV_NODE_IS_FLOW(parent_flags) )
+        fs->struct_indent -= CV_YML_INDENT + CV_NODE_IS_FLOW(struct_flags);
+    assert( fs->struct_indent >= 0 );
+
+    fs->struct_flags = parent_flags;
+}
+
+
+static void
+icvYMLStartNextStream( CvFileStorage* fs )
+{
+    if( !fs->is_first )
+    {
+        while( fs->write_stack->total > 0 )
+            icvYMLEndWriteStruct(fs);
+
+        fs->struct_indent = 0;
+        icvFSFlush(fs);
+        fputs( "...\n", fs->file );
+        fputs( "---\n", fs->file );
+        fs->buffer = fs->buffer_start;
+    }
+}
+
+
+static void
+icvYMLWriteInt( CvFileStorage* fs, const char* key, int value )
+{
+    char buf[128];
+    icvYMLWrite( fs, key, icv_itoa( value, buf, 10 ));
+}
+
+
+static void
+icvYMLWriteReal( CvFileStorage* fs, const char* key, double value )
+{
+    char buf[128];
+    icvYMLWrite( fs, key, icvDoubleToString( buf, value ));
+}
+
+
+static void
+icvYMLWriteString( CvFileStorage* fs, const char* key,
+                   const char* str, int quote CV_DEFAULT(0))
+{
+    char buf[CV_FS_MAX_LEN*4+16];
+    char* data = (char*)str;
+    int i, len;
+
+    if( !str )
+        CV_Error( CV_StsNullPtr, "Null string pointer" );
+
+    len = (int)strlen(str);
+    if( len > CV_FS_MAX_LEN )
+        CV_Error( CV_StsBadArg, "The written string is too long" );
+
+    if( quote || len == 0 || str[0] != str[len-1] || (str[0] != '\"' && str[0] != '\'') )
+    {
+        int need_quote = quote || len == 0;
+        data = buf;
+        *data++ = '\"';
+        for( i = 0; i < len; i++ )
+        {
+            char c = str[i];
+
+            if( !need_quote && !isalnum(c) && c != '_' && c != ' ' && c != '-' &&
+                c != '(' && c != ')' && c != '/' && c != '+' && c != ';' )
+                need_quote = 1;
+
+            if( !isalnum(c) && (!cv_isprint(c) || c == '\\' || c == '\'' || c == '\"') )
+            {
+                *data++ = '\\';
+                if( cv_isprint(c) )
+                    *data++ = c;
+                else if( c == '\n' )
+                    *data++ = 'n';
+                else if( c == '\r' )
+                    *data++ = 'r';
+                else if( c == '\t' )
+                    *data++ = 't';
+                else
+                {
+                    sprintf( data, "x%02x", c );
+                    data += 3;
+                }
+            }
+            else
+                *data++ = c;
+        }
+        if( !need_quote && (isdigit(str[0]) ||
+            str[0] == '+' || str[0] == '-' || str[0] == '.' ))
+            need_quote = 1;
+
+        if( need_quote )
+            *data++ = '\"';
+        *data++ = '\0';
+        data = buf + !need_quote;
+    }
+
+    icvYMLWrite( fs, key, data );
+}
+
+
+static void
+icvYMLWriteComment( CvFileStorage* fs, const char* comment, int eol_comment )
+{
+    int len; //, indent;
+    int multiline;
+    const char* eol;
+    char* ptr;
+
+    if( !comment )
+        CV_Error( CV_StsNullPtr, "Null comment" );
+
+    len = (int)strlen(comment);
+    eol = strchr(comment, '\n');
+    multiline = eol != 0;
+    ptr = fs->buffer;
+
+    if( !eol_comment || multiline ||
+        fs->buffer_end - ptr < len || ptr == fs->buffer_start )
+        ptr = icvFSFlush( fs );
+    else
+        *ptr++ = ' ';
+
+    while( comment )
+    {
+        *ptr++ = '#';
+        *ptr++ = ' ';
+        if( eol )
+        {
+            ptr = icvFSResizeWriteBuffer( fs, ptr, (int)(eol - comment) + 1 );
+            memcpy( ptr, comment, eol - comment + 1 );
+            fs->buffer = ptr + (eol - comment);
+            comment = eol + 1;
+            eol = strchr( comment, '\n' );
+        }
+        else
+        {
+            len = (int)strlen(comment);
+            ptr = icvFSResizeWriteBuffer( fs, ptr, len );
+            memcpy( ptr, comment, len );
+            fs->buffer = ptr + len;
+            comment = 0;
+        }
+        ptr = icvFSFlush( fs );
+    }
+}
+
+
+/****************************************************************************************\
+*                                       XML Parser                                       *
+\****************************************************************************************/
+
+#define CV_XML_INSIDE_COMMENT 1
+#define CV_XML_INSIDE_TAG 2
+#define CV_XML_INSIDE_DIRECTIVE 3
+
+static char*
+icvXMLSkipSpaces( CvFileStorage* fs, char* ptr, int mode )
+{
+    int level = 0;
+
+    for(;;)
+    {
+        char c;
+        ptr--;
+
+        if( mode == CV_XML_INSIDE_COMMENT )
+        {
+            do c = *++ptr;
+            while( cv_isprint_or_tab(c) && (c != '-' || ptr[1] != '-' || ptr[2] != '>') );
+
+            if( c == '-' )
+            {
+                assert( ptr[1] == '-' && ptr[2] == '>' );
+                mode = 0;
+                ptr += 3;
+            }
+        }
+        else if( mode == CV_XML_INSIDE_DIRECTIVE )
+        {
+            // !!!NOTE!!! This is not quite correct, but should work in most cases
+            do
+            {
+                c = *++ptr;
+                level += c == '<';
+                level -= c == '>';
+                if( level < 0 )
+                    return ptr;
+            } while( cv_isprint_or_tab(c) );
+        }
+        else
+        {
+            do c = *++ptr;
+            while( c == ' ' || c == '\t' );
+
+            if( c == '<' && ptr[1] == '!' && ptr[2] == '-' && ptr[3] == '-' )
+            {
+                if( mode != 0 )
+                    CV_PARSE_ERROR( "Comments are not allowed here" );
+                mode = CV_XML_INSIDE_COMMENT;
+                ptr += 4;
+            }
+            else if( cv_isprint(c) )
+                break;
+        }
+
+        if( !cv_isprint(*ptr) )
+        {
+            int max_size = (int)(fs->buffer_end - fs->buffer_start);
+            if( *ptr != '\0' && *ptr != '\n' && *ptr != '\r' )
+                CV_PARSE_ERROR( "Invalid character in the stream" );
+            ptr = fgets( fs->buffer_start, max_size, fs->file );
+            if( !ptr )
+            {
+                ptr = fs->buffer_start;
+                *ptr = '\0';
+                fs->dummy_eof = 1;
+                break;
+            }
+            else
+            {
+                int l = (int)strlen(ptr);
+                if( ptr[l-1] != '\n' && ptr[l-1] != '\r' && !feof(fs->file) )
+                    CV_PARSE_ERROR( "Too long string or a last string w/o newline" );
+            }
+            fs->lineno++;
+        }
+    }
+    return ptr;
+}
+
+
+static char*
+icvXMLParseTag( CvFileStorage* fs, char* ptr, CvStringHashNode** _tag,
+                CvAttrList** _list, int* _tag_type );
+
+static char*
+icvXMLParseValue( CvFileStorage* fs, char* ptr, CvFileNode* node,
+                  int value_type CV_DEFAULT(CV_NODE_NONE))
+{
+    CvFileNode *elem = node;
+    int have_space = 1, is_simple = 1;
+    int is_user_type = CV_NODE_IS_USER(value_type);
+    memset( node, 0, sizeof(*node) );
+
+    value_type = CV_NODE_TYPE(value_type);
+
+    for(;;)
+    {
+        char c = *ptr, d;
+        char* endptr;
+
+        if( isspace(c) || c == '\0' || (c == '<' && ptr[1] == '!' && ptr[2] == '-') )
+        {
+            ptr = icvXMLSkipSpaces( fs, ptr, 0 );
+            have_space = 1;
+            c = *ptr;
+        }
+
+        d = ptr[1];
+
+        if( c =='<' )
+        {
+            CvStringHashNode *key = 0, *key2 = 0;
+            CvAttrList* list = 0;
+            CvTypeInfo* info = 0;
+            int tag_type = 0;
+            int is_noname = 0;
+            const char* type_name = 0;
+            int elem_type = CV_NODE_NONE;
+
+            if( d == '/' )
+                break;
+
+            ptr = icvXMLParseTag( fs, ptr, &key, &list, &tag_type );
+
+            if( tag_type == CV_XML_DIRECTIVE_TAG )
+                CV_PARSE_ERROR( "Directive tags are not allowed here" );
+            if( tag_type == CV_XML_EMPTY_TAG )
+                CV_PARSE_ERROR( "Empty tags are not supported" );
+
+            assert( tag_type == CV_XML_OPENING_TAG );
+
+            type_name = list ? cvAttrValue( list, "type_id" ) : 0;
+            if( type_name )
+            {
+                if( strcmp( type_name, "str" ) == 0 )
+                    elem_type = CV_NODE_STRING;
+                else if( strcmp( type_name, "map" ) == 0 )
+                    elem_type = CV_NODE_MAP;
+                else if( strcmp( type_name, "seq" ) == 0 )
+                    elem_type = CV_NODE_SEQ;
+                else
+                {
+                    info = cvFindType( type_name );
+                    if( info )
+                        elem_type = CV_NODE_USER;
+                }
+            }
+
+            is_noname = key->str.len == 1 && key->str.ptr[0] == '_';
+            if( !CV_NODE_IS_COLLECTION(node->tag) )
+            {
+                icvFSCreateCollection( fs, is_noname ? CV_NODE_SEQ : CV_NODE_MAP, node );
+            }
+            else if( is_noname ^ CV_NODE_IS_SEQ(node->tag) )
+                CV_PARSE_ERROR( is_noname ? "Map element should have a name" :
+                              "Sequence element should not have name (use <_></_>)" );
+
+            if( is_noname )
+                elem = (CvFileNode*)cvSeqPush( node->data.seq, 0 );
+            else
+                elem = cvGetFileNode( fs, node, key, 1 );
+
+            ptr = icvXMLParseValue( fs, ptr, elem, elem_type);
+            if( !is_noname )
+                elem->tag |= CV_NODE_NAMED;
+            is_simple &= !CV_NODE_IS_COLLECTION(elem->tag);
+            elem->info = info;
+            ptr = icvXMLParseTag( fs, ptr, &key2, &list, &tag_type );
+            if( tag_type != CV_XML_CLOSING_TAG || key2 != key )
+                CV_PARSE_ERROR( "Mismatched closing tag" );
+            have_space = 1;
+        }
+        else
+        {
+            if( !have_space )
+                CV_PARSE_ERROR( "There should be space between literals" );
+
+            elem = node;
+            if( node->tag != CV_NODE_NONE )
+            {
+                if( !CV_NODE_IS_COLLECTION(node->tag) )
+                    icvFSCreateCollection( fs, CV_NODE_SEQ, node );
+
+                elem = (CvFileNode*)cvSeqPush( node->data.seq, 0 );
+                elem->info = 0;
+            }
+
+            if( value_type != CV_NODE_STRING &&
+                (isdigit(c) || ((c == '-' || c == '+') &&
+                (isdigit(d) || d == '.')) || (c == '.' && isalnum(d))) ) // a number
+            {
+                double fval;
+                int ival;
+                endptr = ptr + (c == '-' || c == '+');
+                while( isdigit(*endptr) )
+                    endptr++;
+                if( *endptr == '.' || *endptr == 'e' )
+                {
+                    fval = icv_strtod( fs, ptr, &endptr );
+                    /*if( endptr == ptr || isalpha(*endptr) )
+                        icvProcessSpecialDouble( fs, ptr, &fval, &endptr ));*/
+                    elem->tag = CV_NODE_REAL;
+                    elem->data.f = fval;
+                }
+                else
+                {
+                    ival = (int)strtol( ptr, &endptr, 0 );
+                    elem->tag = CV_NODE_INT;
+                    elem->data.i = ival;
+                }
+
+                if( endptr == ptr )
+                    CV_PARSE_ERROR( "Invalid numeric value (inconsistent explicit type specification?)" );
+
+                ptr = endptr;
+            }
+            else
+            {
+                // string
+                char buf[CV_FS_MAX_LEN+16];
+                int i = 0, len, is_quoted = 0;
+                elem->tag = CV_NODE_STRING;
+                if( c == '\"' )
+                    is_quoted = 1;
+                else
+                    --ptr;
+
+                for( ;; )
+                {
+                    c = *++ptr;
+                    if( !isalnum(c) )
+                    {
+                        if( c == '\"' )
+                        {
+                            if( !is_quoted )
+                                CV_PARSE_ERROR( "Literal \" is not allowed within a string. Use &quot;" );
+                            ++ptr;
+                            break;
+                        }
+                        else if( !cv_isprint(c) || c == '<' || (!is_quoted && isspace(c)))
+                        {
+                            if( is_quoted )
+                                CV_PARSE_ERROR( "Closing \" is expected" );
+                            break;
+                        }
+                        else if( c == '\'' || c == '>' )
+                        {
+                            CV_PARSE_ERROR( "Literal \' or > are not allowed. Use &apos; or &gt;" );
+                        }
+                        else if( c == '&' )
+                        {
+                            if( *ptr == '#' )
+                            {
+                                int val;
+                                ptr++;
+                                val = (int)strtol( ptr, &endptr, 0 );
+                                if( (unsigned)val > (unsigned)255 ||
+                                    !endptr || *endptr != ';' )
+                                    CV_PARSE_ERROR( "Invalid numeric value in the string" );
+                                c = (char)val;
+                            }
+                            else
+                            {
+                                endptr = ptr++;
+                                do c = *++endptr;
+                                while( isalnum(c) );
+                                if( c != ';' )
+                                    CV_PARSE_ERROR( "Invalid character in the symbol entity name" );
+                                len = (int)(endptr - ptr);
+                                if( len == 2 && memcmp( ptr, "lt", len ) == 0 )
+                                    c = '<';
+                                else if( len == 2 && memcmp( ptr, "gt", len ) == 0 )
+                                    c = '>';
+                                else if( len == 3 && memcmp( ptr, "amp", len ) == 0 )
+                                    c = '&';
+                                else if( len == 4 && memcmp( ptr, "apos", len ) == 0 )
+                                    c = '\'';
+                                else if( len == 4 && memcmp( ptr, "quot", len ) == 0 )
+                                    c = '\"';
+                                else
+                                {
+                                    memcpy( buf + i, ptr-1, len + 2 );
+                                    i += len + 2;
+                                }
+                            }
+                            ptr = endptr;
+                        }
+                    }
+                    buf[i++] = c;
+                    if( i >= CV_FS_MAX_LEN )
+                        CV_PARSE_ERROR( "Too long string literal" );
+                }
+                elem->data.str = cvMemStorageAllocString( fs->memstorage, buf, i );
+            }
+
+            if( !CV_NODE_IS_COLLECTION(value_type) && value_type != CV_NODE_NONE )
+                break;
+            have_space = 0;
+        }
+    }
+
+    if( (CV_NODE_TYPE(node->tag) == CV_NODE_NONE ||
+        (CV_NODE_TYPE(node->tag) != value_type &&
+        !CV_NODE_IS_COLLECTION(node->tag))) &&
+        CV_NODE_IS_COLLECTION(value_type) )
+    {
+        icvFSCreateCollection( fs, CV_NODE_IS_MAP(value_type) ?
+                                        CV_NODE_MAP : CV_NODE_SEQ, node );
+    }
+
+    if( value_type != CV_NODE_NONE &&
+        value_type != CV_NODE_TYPE(node->tag) )
+        CV_PARSE_ERROR( "The actual type is different from the specified type" );
+
+    if( CV_NODE_IS_COLLECTION(node->tag) && is_simple )
+            node->data.seq->flags |= CV_NODE_SEQ_SIMPLE;
+
+    node->tag |= is_user_type ? CV_NODE_USER : 0;
+    return ptr;
+}
+
+
+static char*
+icvXMLParseTag( CvFileStorage* fs, char* ptr, CvStringHashNode** _tag,
+                CvAttrList** _list, int* _tag_type )
+{
+    int tag_type = 0;
+    CvStringHashNode* tagname = 0;
+    CvAttrList *first = 0, *last = 0;
+    int count = 0, max_count = 4;
+    int attr_buf_size = (max_count*2 + 1)*sizeof(char*) + sizeof(CvAttrList);
+    char* endptr;
+    char c;
+    int have_space;
+
+    if( *ptr != '<' )
+        CV_PARSE_ERROR( "Tag should start with \'<\'" );
+
+    ptr++;
+    if( isalnum(*ptr) || *ptr == '_' )
+        tag_type = CV_XML_OPENING_TAG;
+    else if( *ptr == '/' )
+    {
+        tag_type = CV_XML_CLOSING_TAG;
+        ptr++;
+    }
+    else if( *ptr == '?' )
+    {
+        tag_type = CV_XML_HEADER_TAG;
+        ptr++;
+    }
+    else if( *ptr == '!' )
+    {
+        tag_type = CV_XML_DIRECTIVE_TAG;
+        assert( ptr[1] != '-' || ptr[2] != '-' );
+        ptr++;
+    }
+    else
+        CV_PARSE_ERROR( "Unknown tag type" );
+
+    for(;;)
+    {
+        CvStringHashNode* attrname;
+
+        if( !isalpha(*ptr) && *ptr != '_' )
+            CV_PARSE_ERROR( "Name should start with a letter or underscore" );
+
+        endptr = ptr - 1;
+        do c = *++endptr;
+        while( isalnum(c) || c == '_' || c == '-' );
+
+        attrname = cvGetHashedKey( fs, ptr, (int)(endptr - ptr), 1 );
+        ptr = endptr;
+
+        if( !tagname )
+            tagname = attrname;
+        else
+        {
+            if( tag_type == CV_XML_CLOSING_TAG )
+                CV_PARSE_ERROR( "Closing tag should not contain any attributes" );
+
+            if( !last || count >= max_count )
+            {
+                CvAttrList* chunk;
+
+                chunk = (CvAttrList*)cvMemStorageAlloc( fs->memstorage, attr_buf_size );
+                memset( chunk, 0, attr_buf_size );
+                chunk->attr = (const char**)(chunk + 1);
+                count = 0;
+                if( !last )
+                    first = last = chunk;
+                else
+                    last = last->next = chunk;
+            }
+            last->attr[count*2] = attrname->str.ptr;
+        }
+
+        if( last )
+        {
+            CvFileNode stub;
+
+            if( *ptr != '=' )
+            {
+                ptr = icvXMLSkipSpaces( fs, ptr, CV_XML_INSIDE_TAG );
+                if( *ptr != '=' )
+                    CV_PARSE_ERROR( "Attribute name should be followed by \'=\'" );
+            }
+
+            c = *++ptr;
+            if( c != '\"' && c != '\'' )
+            {
+                ptr = icvXMLSkipSpaces( fs, ptr, CV_XML_INSIDE_TAG );
+                if( *ptr != '\"' && *ptr != '\'' )
+                    CV_PARSE_ERROR( "Attribute value should be put into single or double quotes" );
+            }
+
+            ptr = icvXMLParseValue( fs, ptr, &stub, CV_NODE_STRING );
+            assert( stub.tag == CV_NODE_STRING );
+            last->attr[count*2+1] = stub.data.str.ptr;
+            count++;
+        }
+
+        c = *ptr;
+        have_space = isspace(c) || c == '\0';
+
+        if( c != '>' )
+        {
+            ptr = icvXMLSkipSpaces( fs, ptr, CV_XML_INSIDE_TAG );
+            c = *ptr;
+        }
+
+        if( c == '>' )
+        {
+            if( tag_type == CV_XML_HEADER_TAG )
+                CV_PARSE_ERROR( "Invalid closing tag for <?xml ..." );
+            ptr++;
+            break;
+        }
+        else if( c == '?' && tag_type == CV_XML_HEADER_TAG )
+        {
+            if( ptr[1] != '>'  )
+                CV_PARSE_ERROR( "Invalid closing tag for <?xml ..." );
+            ptr += 2;
+            break;
+        }
+        else if( c == '/' && ptr[1] == '>' && tag_type == CV_XML_OPENING_TAG )
+        {
+            tag_type = CV_XML_EMPTY_TAG;
+            ptr += 2;
+            break;
+        }
+
+        if( !have_space )
+            CV_PARSE_ERROR( "There should be space between attributes" );
+    }
+
+    *_tag = tagname;
+    *_tag_type = tag_type;
+    *_list = first;
+
+    return ptr;
+}
+
+
+static void
+icvXMLParse( CvFileStorage* fs )
+{
+    char* ptr = fs->buffer_start;
+    CvStringHashNode *key = 0, *key2 = 0;
+    CvAttrList* list = 0;
+    int tag_type = 0;
+
+    // CV_XML_INSIDE_TAG is used to prohibit leading comments
+    ptr = icvXMLSkipSpaces( fs, ptr, CV_XML_INSIDE_TAG );
+
+    if( memcmp( ptr, "<?xml", 5 ) != 0 )
+        CV_PARSE_ERROR( "Valid XML should start with \'<?xml ...?>\'" );
+
+    ptr = icvXMLParseTag( fs, ptr, &key, &list, &tag_type );
+
+    /*{
+        const char* version = cvAttrValue( list, "version" );
+        if( version && strncmp( version, "1.", 2 ) != 0 )
+            CV_Error( CV_StsParseError, "Unsupported version of XML" );
+    }*/
+    {
+        const char* encoding = cvAttrValue( list, "encoding" );
+        if( encoding && strcmp( encoding, "ASCII" ) != 0 )
+            CV_PARSE_ERROR( "Unsupported encoding" );
+    }
+
+    while( *ptr != '\0' )
+    {
+        ptr = icvXMLSkipSpaces( fs, ptr, 0 );
+
+        if( *ptr != '\0' )
+        {
+            CvFileNode* root_node;
+            ptr = icvXMLParseTag( fs, ptr, &key, &list, &tag_type );
+            if( tag_type != CV_XML_OPENING_TAG ||
+                strcmp(key->str.ptr,"opencv_storage") != 0 )
+                CV_PARSE_ERROR( "<opencv_storage> tag is missing" );
+
+            root_node = (CvFileNode*)cvSeqPush( fs->roots, 0 );
+            ptr = icvXMLParseValue( fs, ptr, root_node, CV_NODE_NONE );
+            ptr = icvXMLParseTag( fs, ptr, &key2, &list, &tag_type );
+            if( tag_type != CV_XML_CLOSING_TAG || key != key2 )
+                CV_PARSE_ERROR( "</opencv_storage> tag is missing" );
+            ptr = icvXMLSkipSpaces( fs, ptr, 0 );
+        }
+    }
+
+    assert( fs->dummy_eof != 0 );
+}
+
+
+/****************************************************************************************\
+*                                       XML Emitter                                      *
+\****************************************************************************************/
+
+#define icvXMLFlush icvFSFlush
+
+static void
+icvXMLWriteTag( CvFileStorage* fs, const char* key, int tag_type, CvAttrList list )
+{
+    char* ptr = fs->buffer;
+    int i, len = 0;
+    int struct_flags = fs->struct_flags;
+
+    if( key && key[0] == '\0' )
+        key = 0;
+
+    if( tag_type == CV_XML_OPENING_TAG || tag_type == CV_XML_EMPTY_TAG )
+    {
+        if( CV_NODE_IS_COLLECTION(struct_flags) )
+        {
+            if( CV_NODE_IS_MAP(struct_flags) ^ (key != 0) )
+                CV_Error( CV_StsBadArg, "An attempt to add element without a key to a map, "
+                                        "or add element with key to sequence" );
+        }
+        else
+        {
+            struct_flags = CV_NODE_EMPTY + (key ? CV_NODE_MAP : CV_NODE_SEQ);
+            fs->is_first = 0;
+        }
+
+        if( !CV_NODE_IS_EMPTY(struct_flags) )
+            ptr = icvXMLFlush(fs);
+    }
+
+    if( !key )
+        key = "_";
+    else if( key[0] == '_' && key[1] == '\0' )
+        CV_Error( CV_StsBadArg, "A single _ is a reserved tag name" );
+
+    len = (int)strlen( key );
+    *ptr++ = '<';
+    if( tag_type == CV_XML_CLOSING_TAG )
+    {
+        if( list.attr )
+            CV_Error( CV_StsBadArg, "Closing tag should not include any attributes" );
+        *ptr++ = '/';
+    }
+
+    if( !isalpha(key[0]) && key[0] != '_' )
+        CV_Error( CV_StsBadArg, "Key should start with a letter or _" );
+
+    ptr = icvFSResizeWriteBuffer( fs, ptr, len );
+    for( i = 0; i < len; i++ )
+    {
+        char c = key[i];
+        if( !isalnum(c) && c != '_' && c != '-' )
+            CV_Error( CV_StsBadArg, "Key name may only contain alphanumeric characters [a-zA-Z0-9], '-' and '_'" );
+        ptr[i] = c;
+    }
+    ptr += len;
+
+    for(;;)
+    {
+        const char** attr = list.attr;
+
+        for( ; attr && attr[0] != 0; attr += 2 )
+        {
+            int len0 = (int)strlen(attr[0]);
+            int len1 = (int)strlen(attr[1]);
+
+            ptr = icvFSResizeWriteBuffer( fs, ptr, len0 + len1 + 4 );
+            *ptr++ = ' ';
+            memcpy( ptr, attr[0], len0 );
+            ptr += len0;
+            *ptr++ = '=';
+            *ptr++ = '\"';
+            memcpy( ptr, attr[1], len1 );
+            ptr += len1;
+            *ptr++ = '\"';
+        }
+        if( !list.next )
+            break;
+        list = *list.next;
+    }
+
+    if( tag_type == CV_XML_EMPTY_TAG )
+        *ptr++ = '/';
+    *ptr++ = '>';
+    fs->buffer = ptr;
+    fs->struct_flags = struct_flags & ~CV_NODE_EMPTY;
+}
+
+
+static void
+icvXMLStartWriteStruct( CvFileStorage* fs, const char* key, int struct_flags,
+                        const char* type_name CV_DEFAULT(0))
+{
+    CvXMLStackRecord parent;
+    const char* attr[10];
+    int idx = 0;
+
+    struct_flags = (struct_flags & (CV_NODE_TYPE_MASK|CV_NODE_FLOW)) | CV_NODE_EMPTY;
+    if( !CV_NODE_IS_COLLECTION(struct_flags))
+        CV_Error( CV_StsBadArg,
+        "Some collection type: CV_NODE_SEQ or CV_NODE_MAP must be specified" );
+
+    if( type_name )
+    {
+        attr[idx++] = "type_id";
+        attr[idx++] = type_name;
+    }
+    attr[idx++] = 0;
+
+    icvXMLWriteTag( fs, key, CV_XML_OPENING_TAG, cvAttrList(attr,0) );
+
+    parent.struct_flags = fs->struct_flags & ~CV_NODE_EMPTY;
+    parent.struct_indent = fs->struct_indent;
+    parent.struct_tag = fs->struct_tag;
+    cvSaveMemStoragePos( fs->strstorage, &parent.pos );
+    cvSeqPush( fs->write_stack, &parent );
+
+    fs->struct_indent += CV_XML_INDENT;
+    if( !CV_NODE_IS_FLOW(struct_flags) )
+        icvXMLFlush( fs );
+
+    fs->struct_flags = struct_flags;
+    if( key )
+    {
+        fs->struct_tag = cvMemStorageAllocString( fs->strstorage, (char*)key, -1 );
+    }
+    else
+    {
+        fs->struct_tag.ptr = 0;
+        fs->struct_tag.len = 0;
+    }
+}
+
+
+static void
+icvXMLEndWriteStruct( CvFileStorage* fs )
+{
+    CvXMLStackRecord parent;
+
+    if( fs->write_stack->total == 0 )
+        CV_Error( CV_StsError, "An extra closing tag" );
+
+    icvXMLWriteTag( fs, fs->struct_tag.ptr, CV_XML_CLOSING_TAG, cvAttrList(0,0) );
+    cvSeqPop( fs->write_stack, &parent );
+
+    fs->struct_indent = parent.struct_indent;
+    fs->struct_flags = parent.struct_flags;
+    fs->struct_tag = parent.struct_tag;
+    cvRestoreMemStoragePos( fs->strstorage, &parent.pos );
+}
+
+
+static void
+icvXMLStartNextStream( CvFileStorage* fs )
+{
+    if( !fs->is_first )
+    {
+        while( fs->write_stack->total > 0 )
+            icvXMLEndWriteStruct(fs);
+
+        fs->struct_indent = 0;
+        icvXMLFlush(fs);
+        /* XML does not allow multiple top-level elements,
+           so we just put a comment and continue
+           the current (and the only) "stream" */
+        fputs( "\n<!-- next stream -->\n", fs->file );
+        /*fputs( "</opencv_storage>\n", fs->file );
+        fputs( "<opencv_storage>\n", fs->file );*/
+        fs->buffer = fs->buffer_start;
+    }
+}
+
+
+static void
+icvXMLWriteScalar( CvFileStorage* fs, const char* key, const char* data, int len )
+{
+    if( CV_NODE_IS_MAP(fs->struct_flags) ||
+        (!CV_NODE_IS_COLLECTION(fs->struct_flags) && key) )
+    {
+        icvXMLWriteTag( fs, key, CV_XML_OPENING_TAG, cvAttrList(0,0) );
+        char* ptr = icvFSResizeWriteBuffer( fs, fs->buffer, len );
+        memcpy( ptr, data, len );
+        fs->buffer = ptr + len;
+        icvXMLWriteTag( fs, key, CV_XML_CLOSING_TAG, cvAttrList(0,0) );
+    }
+    else
+    {
+        char* ptr = fs->buffer;
+        int new_offset = (int)(ptr - fs->buffer_start) + len;
+
+        if( key )
+            CV_Error( CV_StsBadArg, "elements with keys can not be written to sequence" );
+
+        fs->struct_flags = CV_NODE_SEQ;
+
+        if( (new_offset > fs->wrap_margin && new_offset - fs->struct_indent > 10) ||
+            (ptr > fs->buffer_start && ptr[-1] == '>' && !CV_NODE_IS_EMPTY(fs->struct_flags)) )
+        {
+            ptr = icvXMLFlush(fs);
+        }
+        else if( ptr > fs->buffer_start + fs->struct_indent && ptr[-1] != '>' )
+            *ptr++ = ' ';
+
+        memcpy( ptr, data, len );
+        fs->buffer = ptr + len;
+    }
+}
+
+
+static void
+icvXMLWriteInt( CvFileStorage* fs, const char* key, int value )
+{
+    char buf[128], *ptr = icv_itoa( value, buf, 10 );
+    int len = (int)strlen(ptr);
+    icvXMLWriteScalar( fs, key, ptr, len );
+}
+
+
+static void
+icvXMLWriteReal( CvFileStorage* fs, const char* key, double value )
+{
+    char buf[128];
+    int len = (int)strlen( icvDoubleToString( buf, value ));
+    icvXMLWriteScalar( fs, key, buf, len );
+}
+
+
+static void
+icvXMLWriteString( CvFileStorage* fs, const char* key, const char* str, int quote )
+{
+    char buf[CV_FS_MAX_LEN*6+16];
+    char* data = (char*)str;
+    int i, len;
+
+    if( !str )
+        CV_Error( CV_StsNullPtr, "Null string pointer" );
+
+    len = (int)strlen(str);
+    if( len > CV_FS_MAX_LEN )
+        CV_Error( CV_StsBadArg, "The written string is too long" );
+
+    if( quote || len == 0 || str[0] != '\"' || str[0] != str[len-1] )
+    {
+        int need_quote = quote || len == 0;
+        data = buf;
+        *data++ = '\"';
+        for( i = 0; i < len; i++ )
+        {
+            char c = str[i];
+
+            if( !isalnum(c) && (!cv_isprint(c) || c == '<' || c == '>' ||
+                c == '&' || c == '\'' || c == '\"') )
+            {
+                *data++ = '&';
+                if( c == '<' )
+                {
+                    memcpy(data, "lt", 2);
+                    data += 2;
+                }
+                else if( c == '>' )
+                {
+                    memcpy(data, "gt", 2);
+                    data += 2;
+                }
+                else if( c == '&' )
+                {
+                    memcpy(data, "amp", 3);
+                    data += 3;
+                }
+                else if( c == '\'' )
+                {
+                    memcpy(data, "apos", 4);
+                    data += 4;
+                }
+                else if( c == '\"' )
+                {
+                    memcpy( data, "quot", 4);
+                    data += 4;
+                }
+                else
+                {
+                    sprintf( data, "#x%02x", c );
+                    data += 4;
+                }
+                *data++ = ';';
+            }
+            else
+            {
+                if( c == ' ' )
+                    need_quote = 1;
+                *data++ = c;
+            }
+        }
+        if( !need_quote && (isdigit(str[0]) ||
+            str[0] == '+' || str[0] == '-' || str[0] == '.' ))
+            need_quote = 1;
+
+        if( need_quote )
+            *data++ = '\"';
+        len = (int)(data - buf) - !need_quote;
+        *data++ = '\0';
+        data = buf + !need_quote;
+    }
+
+    icvXMLWriteScalar( fs, key, data, len );
+}
+
+
+static void
+icvXMLWriteComment( CvFileStorage* fs, const char* comment, int eol_comment )
+{
+    int len;
+    int multiline;
+    const char* eol;
+    char* ptr;
+
+    if( !comment )
+        CV_Error( CV_StsNullPtr, "Null comment" );
+
+    if( strstr(comment, "--") != 0 )
+        CV_Error( CV_StsBadArg, "Double hyphen \'--\' is not allowed in the comments" );
+
+    len = (int)strlen(comment);
+    eol = strchr(comment, '\n');
+    multiline = eol != 0;
+    ptr = fs->buffer;
+
+    if( multiline || !eol_comment || fs->buffer_end - ptr < len + 5 )
+        ptr = icvXMLFlush( fs );
+    else if( ptr > fs->buffer_start + fs->struct_indent )
+        *ptr++ = ' ';
+
+    if( !multiline )
+    {
+        ptr = icvFSResizeWriteBuffer( fs, ptr, len + 9 );
+        sprintf( ptr, "<!-- %s -->", comment );
+        len = (int)strlen(ptr);
+    }
+    else
+    {
+        strcpy( ptr, "<!--" );
+        len = 4;
+    }
+
+    fs->buffer = ptr + len;
+    ptr = icvXMLFlush(fs);
+
+    if( multiline )
+    {
+        while( comment )
+        {
+            if( eol )
+            {
+                ptr = icvFSResizeWriteBuffer( fs, ptr, (int)(eol - comment) + 1 );
+                memcpy( ptr, comment, eol - comment + 1 );
+                ptr += eol - comment;
+                comment = eol + 1;
+                eol = strchr( comment, '\n' );
+            }
+            else
+            {
+                len = (int)strlen(comment);
+                ptr = icvFSResizeWriteBuffer( fs, ptr, len );
+                memcpy( ptr, comment, len );
+                ptr += len;
+                comment = 0;
+            }
+            fs->buffer = ptr;
+            ptr = icvXMLFlush( fs );
+        }
+        sprintf( ptr, "-->" );
+        fs->buffer = ptr + 3;
+        icvXMLFlush( fs );
+    }
+}
+
+
+/****************************************************************************************\
+*                              Common High-Level Functions                               *
+\****************************************************************************************/
+
+CV_IMPL CvFileStorage*
+cvOpenFileStorage( const char* filename, CvMemStorage* dststorage, int flags )
+{
+    CvFileStorage* fs = 0;
+    char* xml_buf = 0;
+    int default_block_size = 1 << 18;
+    bool append = (flags & 3) == CV_STORAGE_APPEND;
+
+    if( !filename )
+        CV_Error( CV_StsNullPtr, "NULL filename" );
+
+    fs = (CvFileStorage*)cvAlloc( sizeof(*fs) );
+    memset( fs, 0, sizeof(*fs));
+
+    fs->memstorage = cvCreateMemStorage( default_block_size );
+    fs->dststorage = dststorage ? dststorage : fs->memstorage;
+
+    fs->filename = (char*)cvMemStorageAlloc( fs->memstorage, strlen(filename)+1 );
+    strcpy( fs->filename, filename );
+
+    fs->flags = CV_FILE_STORAGE;
+    fs->write_mode = (flags & 3) != 0;
+#ifdef WIN32
+    fs->file = _wfopen( cv::toUtf16(fs->filename).c_str(), !fs->write_mode ? L"rt" : !append ? L"wt" : L"a+t" );
+#else
+    fs->file = fopen(fs->filename, !fs->write_mode ? "rt" : !append ? "wt" : "a+t" );
+#endif
+    if( !fs->file )
+        goto _exit_;
+
+    fs->roots = 0;
+    fs->struct_indent = 0;
+    fs->struct_flags = 0;
+    fs->wrap_margin = 71;
+
+    if( fs->write_mode )
+    {
+        // we use factor=6 for XML (the longest characters (' and ") are encoded with 6 bytes (&apos; and &quot;)
+        // and factor=4 for YAML ( as we use 4 bytes for non ASCII characters (e.g. \xAB))
+        int buf_size = CV_FS_MAX_LEN*(fs->is_xml ? 6 : 4) + 1024;
+
+        char* dot_pos = strrchr( fs->filename, '.' );
+        fs->is_xml = dot_pos && (strcmp( dot_pos, ".xml" ) == 0 ||
+                      strcmp( dot_pos, ".XML" ) == 0 || strcmp( dot_pos, ".Xml" ) == 0);
+
+        if( append )
+            fseek( fs->file, 0, SEEK_END );
+
+        fs->write_stack = cvCreateSeq( 0, sizeof(CvSeq), fs->is_xml ?
+                sizeof(CvXMLStackRecord) : sizeof(int), fs->memstorage );
+        fs->is_first = 1;
+        fs->struct_indent = 0;
+        fs->struct_flags = CV_NODE_EMPTY;
+        fs->buffer_start = fs->buffer = (char*)cvAlloc( buf_size + 1024 );
+        fs->buffer_end = fs->buffer_start + buf_size;
+        if( fs->is_xml )
+        {
+            int file_size = (int)ftell( fs->file );
+            fs->strstorage = cvCreateChildMemStorage( fs->memstorage );
+            if( !append || file_size == 0 )
+            {
+                fputs( "<?xml version=\"1.0\"?>\n", fs->file );
+                fputs( "<opencv_storage>\n", fs->file );
+            }
+            else
+            {
+                int xml_buf_size = 1 << 10;
+                char substr[] = "</opencv_storage>";
+                int last_occurence = -1;
+                xml_buf_size = MIN(xml_buf_size, file_size);
+                fseek( fs->file, -xml_buf_size, SEEK_END );
+                xml_buf = (char*)cvAlloc( xml_buf_size+2 );
+                // find the last occurence of </opencv_storage>
+                for(;;)
+                {
+                    int line_offset = ftell( fs->file );
+                    char* ptr0 = fgets( xml_buf, xml_buf_size, fs->file ), *ptr;
+                    if( !ptr0 )
+                        break;
+                    ptr = ptr0;
+                    for(;;)
+                    {
+                        ptr = strstr( ptr, substr );
+                        if( !ptr )
+                            break;
+                        last_occurence = line_offset + (int)(ptr - ptr0);
+                        ptr += strlen(substr);
+                    }
+                }
+                if( last_occurence < 0 )
+                    CV_Error( CV_StsError, "Could not find </opencv_storage> in the end of file.\n" );
+                fclose( fs->file );
+            #ifdef WIN32
+                fs->file = _wfopen( cv::toUtf16(fs->filename).c_str(), L"r+t" );
+            #else
+                fs->file = fopen( fs->filename, "r+t" );
+            #endif
+                fseek( fs->file, last_occurence, SEEK_SET );
+                // replace the last "</opencv_storage>" with " <!-- resumed -->", which has the same length
+                fputs( " <!-- resumed -->", fs->file );
+                fseek( fs->file, 0, SEEK_END );
+                fputs( "\n", fs->file );
+            }
+            fs->start_write_struct = icvXMLStartWriteStruct;
+            fs->end_write_struct = icvXMLEndWriteStruct;
+            fs->write_int = icvXMLWriteInt;
+            fs->write_real = icvXMLWriteReal;
+            fs->write_string = icvXMLWriteString;
+            fs->write_comment = icvXMLWriteComment;
+            fs->start_next_stream = icvXMLStartNextStream;
+        }
+        else
+        {
+            if( !append )
+                fputs( "%YAML:1.0\n", fs->file );
+            else
+                fputs( "...\n---\n", fs->file );
+            fs->start_write_struct = icvYMLStartWriteStruct;
+            fs->end_write_struct = icvYMLEndWriteStruct;
+            fs->write_int = icvYMLWriteInt;
+            fs->write_real = icvYMLWriteReal;
+            fs->write_string = icvYMLWriteString;
+            fs->write_comment = icvYMLWriteComment;
+            fs->start_next_stream = icvYMLStartNextStream;
+        }
+    }
+    else
+    {
+        int buf_size;
+        const char* yaml_signature = "%YAML:";
+        char buf[16];
+        fgets( buf, sizeof(buf)-2, fs->file );
+        fs->is_xml = strncmp( buf, yaml_signature, strlen(yaml_signature) ) != 0;
+
+        fseek( fs->file, 0, SEEK_END );
+        buf_size = ftell( fs->file );
+        fseek( fs->file, 0, SEEK_SET );
+
+        buf_size = MIN( buf_size, (1 << 20) );
+        buf_size = MAX( buf_size, CV_FS_MAX_LEN*2 + 1024 );
+
+        fs->str_hash = cvCreateMap( 0, sizeof(CvStringHash),
+                        sizeof(CvStringHashNode), fs->memstorage, 256 );
+
+        fs->roots = cvCreateSeq( 0, sizeof(CvSeq),
+                        sizeof(CvFileNode), fs->memstorage );
+
+        fs->buffer = fs->buffer_start = (char*)cvAlloc( buf_size + 256 );
+        fs->buffer_end = fs->buffer_start + buf_size;
+        fs->buffer[0] = '\n';
+        fs->buffer[1] = '\0';
+
+        //mode = cvGetErrMode();
+        //cvSetErrMode( CV_ErrModeSilent );
+        if( fs->is_xml )
+            icvXMLParse( fs );
+        else
+            icvYMLParse( fs );
+        //cvSetErrMode( mode );
+
+        // release resources that we do not need anymore
+        cvFree( &fs->buffer_start );
+        fs->buffer = fs->buffer_end = 0;
+    }
+_exit_:
+    if( fs )
+    {
+        if( cvGetErrStatus() < 0 || !fs->file )
+        {
+            cvReleaseFileStorage( &fs );
+        }
+        else if( !fs->write_mode )
+        {
+            fclose( fs->file );
+            fs->file = 0;
+        }
+    }
+
+    cvFree( &xml_buf );
+    return  fs;
+}
+
+
+CV_IMPL void
+cvStartWriteStruct( CvFileStorage* fs, const char* key, int struct_flags,
+                    const char* type_name, CvAttrList /*attributes*/ )
+{
+    CV_CHECK_OUTPUT_FILE_STORAGE(fs);
+    fs->start_write_struct( fs, key, struct_flags, type_name );
+}
+
+
+CV_IMPL void
+cvEndWriteStruct( CvFileStorage* fs )
+{
+    CV_CHECK_OUTPUT_FILE_STORAGE(fs);
+    fs->end_write_struct( fs );
+}
+
+
+CV_IMPL void
+cvWriteInt( CvFileStorage* fs, const char* key, int value )
+{
+    CV_CHECK_OUTPUT_FILE_STORAGE(fs);
+    fs->write_int( fs, key, value );
+}
+
+
+CV_IMPL void
+cvWriteReal( CvFileStorage* fs, const char* key, double value )
+{
+    CV_CHECK_OUTPUT_FILE_STORAGE(fs);
+    fs->write_real( fs, key, value );
+}
+
+
+CV_IMPL void
+cvWriteString( CvFileStorage* fs, const char* key, const char* value, int quote )
+{
+    CV_CHECK_OUTPUT_FILE_STORAGE(fs);
+    fs->write_string( fs, key, value, quote );
+}
+
+
+CV_IMPL void
+cvWriteComment( CvFileStorage* fs, const char* comment, int eol_comment )
+{
+    CV_CHECK_OUTPUT_FILE_STORAGE(fs);
+    fs->write_comment( fs, comment, eol_comment );
+}
+
+
+CV_IMPL void
+cvStartNextStream( CvFileStorage* fs )
+{
+    CV_CHECK_OUTPUT_FILE_STORAGE(fs);
+    fs->start_next_stream( fs );
+}
+
+
+static const char icvTypeSymbol[] = "ucwsifdr";
+#define CV_FS_MAX_FMT_PAIRS  128
+
+static char*
+icvEncodeFormat( int elem_type, char* dt )
+{
+    sprintf( dt, "%d%c", CV_MAT_CN(elem_type), icvTypeSymbol[CV_MAT_DEPTH(elem_type)] );
+    return dt + ( dt[2] == '\0' && dt[0] == '1' );
+}
+
+static int
+icvDecodeFormat( const char* dt, int* fmt_pairs, int max_len )
+{
+    int fmt_pair_count = 0;
+    int i = 0, k = 0, len = dt ? (int)strlen(dt) : 0;
+
+    if( !dt || !len )
+        return 0;
+
+    assert( fmt_pairs != 0 && max_len > 0 );
+    fmt_pairs[0] = 0;
+    max_len *= 2;
+
+    for( ; k < len; k++ )
+    {
+        char c = dt[k];
+
+        if( isdigit(c) )
+        {
+            int count = c - '0';
+            if( isdigit(dt[k+1]) )
+            {
+                char* endptr = 0;
+                count = (int)strtol( dt+k, &endptr, 10 );
+                k = (int)(endptr - dt) - 1;
+            }
+
+            if( count <= 0 )
+                CV_Error( CV_StsBadArg, "Invalid data type specification" );
+
+            fmt_pairs[i] = count;
+        }
+        else
+        {
+            const char* pos = strchr( icvTypeSymbol, c );
+            if( !pos )
+                CV_Error( CV_StsBadArg, "Invalid data type specification" );
+            if( fmt_pairs[i] == 0 )
+                fmt_pairs[i] = 1;
+            fmt_pairs[i+1] = (int)(pos - icvTypeSymbol);
+            if( i > 0 && fmt_pairs[i+1] == fmt_pairs[i-1] )
+                fmt_pairs[i-2] += fmt_pairs[i];
+            else
+            {
+                i += 2;
+                if( i >= max_len )
+                    CV_Error( CV_StsBadArg, "Too long data type specification" );
+            }
+            fmt_pairs[i] = 0;
+        }
+    }
+
+    fmt_pair_count = i/2;
+    return fmt_pair_count;
+}
+
+
+static int
+icvCalcElemSize( const char* dt, int initial_size )
+{
+    int size = 0;
+    int fmt_pairs[CV_FS_MAX_FMT_PAIRS], i, fmt_pair_count;
+    int comp_size;
+
+    fmt_pair_count = icvDecodeFormat( dt, fmt_pairs, CV_FS_MAX_FMT_PAIRS );
+    fmt_pair_count *= 2;
+    for( i = 0, size = initial_size; i < fmt_pair_count; i += 2 )
+    {
+        comp_size = CV_ELEM_SIZE(fmt_pairs[i+1]);
+        size = cvAlign( size, comp_size );
+        size += comp_size * fmt_pairs[i];
+    }
+    if( initial_size == 0 )
+    {
+        comp_size = CV_ELEM_SIZE(fmt_pairs[1]);
+        size = cvAlign( size, comp_size );
+    }
+    return size;
+}
+
+
+static int
+icvDecodeSimpleFormat( const char* dt )
+{
+    int elem_type = -1;
+    int fmt_pairs[CV_FS_MAX_FMT_PAIRS], fmt_pair_count;
+
+    fmt_pair_count = icvDecodeFormat( dt, fmt_pairs, CV_FS_MAX_FMT_PAIRS );
+    if( fmt_pair_count != 1 || fmt_pairs[0] > 4 )
+        CV_Error( CV_StsError, "Too complex format for the matrix" );
+
+    elem_type = CV_MAKETYPE( fmt_pairs[1], fmt_pairs[0] );
+
+    return elem_type;
+}
+
+
+CV_IMPL void
+cvWriteRawData( CvFileStorage* fs, const void* _data, int len, const char* dt )
+{
+    const char* data0 = (const char*)_data;
+    int offset = 0;
+    int fmt_pairs[CV_FS_MAX_FMT_PAIRS*2], k, fmt_pair_count;
+    char buf[256] = "";
+
+    CV_CHECK_OUTPUT_FILE_STORAGE( fs );
+
+    if( !data0 )
+        CV_Error( CV_StsNullPtr, "Null data pointer" );
+
+    if( len < 0 )
+        CV_Error( CV_StsOutOfRange, "Negative number of elements" );
+
+    fmt_pair_count = icvDecodeFormat( dt, fmt_pairs, CV_FS_MAX_FMT_PAIRS );
+
+    if( !len )
+        return;
+
+    if( fmt_pair_count == 1 )
+    {
+        fmt_pairs[0] *= len;
+        len = 1;
+    }
+
+    for(;len--;)
+    {
+        for( k = 0; k < fmt_pair_count; k++ )
+        {
+            int i, count = fmt_pairs[k*2];
+            int elem_type = fmt_pairs[k*2+1];
+            int elem_size = CV_ELEM_SIZE(elem_type);
+            const char* data, *ptr;
+
+            offset = cvAlign( offset, elem_size );
+            data = data0 + offset;
+
+            for( i = 0; i < count; i++ )
+            {
+                switch( elem_type )
+                {
+                case CV_8U:
+                    ptr = icv_itoa( *(uchar*)data, buf, 10 );
+                    data++;
+                    break;
+                case CV_8S:
+                    ptr = icv_itoa( *(char*)data, buf, 10 );
+                    data++;
+                    break;
+                case CV_16U:
+                    ptr = icv_itoa( *(ushort*)data, buf, 10 );
+                    data += sizeof(ushort);
+                    break;
+                case CV_16S:
+                    ptr = icv_itoa( *(short*)data, buf, 10 );
+                    data += sizeof(short);
+                    break;
+                case CV_32S:
+                    ptr = icv_itoa( *(int*)data, buf, 10 );
+                    data += sizeof(int);
+                    break;
+                case CV_32F:
+                    ptr = icvFloatToString( buf, *(float*)data );
+                    data += sizeof(float);
+                    break;
+                case CV_64F:
+                    ptr = icvDoubleToString( buf, *(double*)data );
+                    data += sizeof(double);
+                    break;
+                case CV_USRTYPE1: /* reference */
+                    ptr = icv_itoa( (int)*(size_t*)data, buf, 10 );
+                    data += sizeof(size_t);
+                    break;
+                default:
+                    assert(0);
+                    return;
+                }
+
+                if( fs->is_xml )
+                {
+                    int buf_len = (int)strlen(ptr);
+                    icvXMLWriteScalar( fs, 0, ptr, buf_len );
+                }
+                else
+                    icvYMLWrite( fs, 0, ptr );
+            }
+
+            offset = (int)(data - data0);
+        }
+    }
+}
+
+
+CV_IMPL void
+cvStartReadRawData( const CvFileStorage* fs, const CvFileNode* src, CvSeqReader* reader )
+{
+    int node_type;
+    CV_CHECK_FILE_STORAGE( fs );
+
+    if( !src || !reader )
+        CV_Error( CV_StsNullPtr, "Null pointer to source file node or reader" );
+
+    node_type = CV_NODE_TYPE(src->tag);
+    if( node_type == CV_NODE_INT || node_type == CV_NODE_REAL )
+    {
+        // emulate reading from 1-element sequence
+        reader->ptr = (schar*)src;
+        reader->block_max = reader->ptr + sizeof(*src)*2;
+        reader->block_min = reader->ptr;
+        reader->seq = 0;
+    }
+    else if( node_type == CV_NODE_SEQ )
+    {
+        cvStartReadSeq( src->data.seq, reader, 0 );
+    }
+    else if( node_type == CV_NODE_NONE )
+    {
+        memset( reader, 0, sizeof(*reader) );
+    }
+    else
+        CV_Error( CV_StsBadArg, "The file node should be a numerical scalar or a sequence" );
+}
+
+
+CV_IMPL void
+cvReadRawDataSlice( const CvFileStorage* fs, CvSeqReader* reader,
+                    int len, void* _data, const char* dt )
+{
+    char* data0 = (char*)_data;
+    int fmt_pairs[CV_FS_MAX_FMT_PAIRS*2], k = 0, fmt_pair_count;
+    int i = 0, offset = 0, count = 0;
+
+    CV_CHECK_FILE_STORAGE( fs );
+
+    if( !reader || !data0 )
+        CV_Error( CV_StsNullPtr, "Null pointer to reader or destination array" );
+
+    if( !reader->seq && len != 1 )
+        CV_Error( CV_StsBadSize, "The readed sequence is a scalar, thus len must be 1" );
+
+    fmt_pair_count = icvDecodeFormat( dt, fmt_pairs, CV_FS_MAX_FMT_PAIRS );
+
+    for(;;)
+    {
+        for( k = 0; k < fmt_pair_count; k++ )
+        {
+            int elem_type = fmt_pairs[k*2+1];
+            int elem_size = CV_ELEM_SIZE(elem_type);
+            char* data;
+
+            count = fmt_pairs[k*2];
+            offset = cvAlign( offset, elem_size );
+            data = data0 + offset;
+
+            for( i = 0; i < count; i++ )
+            {
+                CvFileNode* node = (CvFileNode*)reader->ptr;
+                if( CV_NODE_IS_INT(node->tag) )
+                {
+                    int ival = node->data.i;
+
+                    switch( elem_type )
+                    {
+                    case CV_8U:
+                        *(uchar*)data = CV_CAST_8U(ival);
+                        data++;
+                        break;
+                    case CV_8S:
+                        *(char*)data = CV_CAST_8S(ival);
+                        data++;
+                        break;
+                    case CV_16U:
+                        *(ushort*)data = CV_CAST_16U(ival);
+                        data += sizeof(ushort);
+                        break;
+                    case CV_16S:
+                        *(short*)data = CV_CAST_16S(ival);
+                        data += sizeof(short);
+                        break;
+                    case CV_32S:
+                        *(int*)data = ival;
+                        data += sizeof(int);
+                        break;
+                    case CV_32F:
+                        *(float*)data = (float)ival;
+                        data += sizeof(float);
+                        break;
+                    case CV_64F:
+                        *(double*)data = (double)ival;
+                        data += sizeof(double);
+                        break;
+                    case CV_USRTYPE1: /* reference */
+                        *(size_t*)data = ival;
+                        data += sizeof(size_t);
+                        break;
+                    default:
+                        assert(0);
+                        return;
+                    }
+                }
+                else if( CV_NODE_IS_REAL(node->tag) )
+                {
+                    double fval = node->data.f;
+                    int ival;
+
+                    switch( elem_type )
+                    {
+                    case CV_8U:
+                        ival = cvRound(fval);
+                        *(uchar*)data = CV_CAST_8U(ival);
+                        data++;
+                        break;
+                    case CV_8S:
+                        ival = cvRound(fval);
+                        *(char*)data = CV_CAST_8S(ival);
+                        data++;
+                        break;
+                    case CV_16U:
+                        ival = cvRound(fval);
+                        *(ushort*)data = CV_CAST_16U(ival);
+                        data += sizeof(ushort);
+                        break;
+                    case CV_16S:
+                        ival = cvRound(fval);
+                        *(short*)data = CV_CAST_16S(ival);
+                        data += sizeof(short);
+                        break;
+                    case CV_32S:
+                        ival = cvRound(fval);
+                        *(int*)data = ival;
+                        data += sizeof(int);
+                        break;
+                    case CV_32F:
+                        *(float*)data = (float)fval;
+                        data += sizeof(float);
+                        break;
+                    case CV_64F:
+                        *(double*)data = fval;
+                        data += sizeof(double);
+                        break;
+                    case CV_USRTYPE1: /* reference */
+                        ival = cvRound(fval);
+                        *(size_t*)data = ival;
+                        data += sizeof(size_t);
+                        break;
+                    default:
+                        assert(0);
+                        return;
+                    }
+                }
+                else
+                    CV_Error( CV_StsError,
+                    "The sequence element is not a numerical scalar" );
+
+                CV_NEXT_SEQ_ELEM( sizeof(CvFileNode), *reader );
+                if( !--len )
+                    goto end_loop;
+            }
+
+            offset = (int)(data - data0);
+        }
+    }
+
+end_loop:
+    if( i != count - 1 || k != fmt_pair_count - 1 )
+        CV_Error( CV_StsBadSize,
+        "The sequence slice does not fit an integer number of records" );
+
+    if( !reader->seq )
+        reader->ptr -= sizeof(CvFileNode);
+}
+
+
+CV_IMPL void
+cvReadRawData( const CvFileStorage* fs, const CvFileNode* src,
+               void* data, const char* dt )
+{
+    CvSeqReader reader;
+
+    if( !src || !data )
+        CV_Error( CV_StsNullPtr, "Null pointers to source file node or destination array" );
+
+    cvStartReadRawData( fs, src, &reader );
+    cvReadRawDataSlice( fs, &reader, CV_NODE_IS_SEQ(src->tag) ?
+                        src->data.seq->total : 1, data, dt );
+}
+
+
+static void
+icvWriteFileNode( CvFileStorage* fs, const char* name, const CvFileNode* node );
+
+static void
+icvWriteCollection( CvFileStorage* fs, const CvFileNode* node )
+{
+    int i, total = node->data.seq->total;
+    int elem_size = node->data.seq->elem_size;
+    int is_map = CV_NODE_IS_MAP(node->tag);
+    CvSeqReader reader;
+
+    cvStartReadSeq( node->data.seq, &reader, 0 );
+
+    for( i = 0; i < total; i++ )
+    {
+        CvFileMapNode* elem = (CvFileMapNode*)reader.ptr;
+        if( !is_map || CV_IS_SET_ELEM(elem) )
+        {
+            const char* name = is_map ? elem->key->str.ptr : 0;
+            icvWriteFileNode( fs, name, &elem->value );
+        }
+        CV_NEXT_SEQ_ELEM( elem_size, reader );
+    }
+}
+
+static void
+icvWriteFileNode( CvFileStorage* fs, const char* name, const CvFileNode* node )
+{
+    switch( CV_NODE_TYPE(node->tag) )
+    {
+    case CV_NODE_INT:
+        fs->write_int( fs, name, node->data.i );
+        break;
+    case CV_NODE_REAL:
+        fs->write_real( fs, name, node->data.f );
+        break;
+    case CV_NODE_STR:
+        fs->write_string( fs, name, node->data.str.ptr, 0 );
+        break;
+    case CV_NODE_SEQ:
+    case CV_NODE_MAP:
+        fs->start_write_struct( fs, name, CV_NODE_TYPE(node->tag) +
+                (CV_NODE_SEQ_IS_SIMPLE(node->data.seq) ? CV_NODE_FLOW : 0),
+                node->info ? node->info->type_name : 0 );
+        icvWriteCollection( fs, node );
+        fs->end_write_struct( fs );
+        break;
+    case CV_NODE_NONE:
+        fs->start_write_struct( fs, name, CV_NODE_SEQ, 0 );
+        fs->end_write_struct( fs );
+        break;
+    default:
+        CV_Error( CV_StsBadFlag, "Unknown type of file node" );
+    }
+}
+
+
+CV_IMPL void
+cvWriteFileNode( CvFileStorage* fs, const char* new_node_name,
+                 const CvFileNode* node, int embed )
+{
+    CvFileStorage* dst = 0;
+    CV_CHECK_OUTPUT_FILE_STORAGE(fs);
+
+    if( !node )
+        return;
+
+    if( CV_NODE_IS_COLLECTION(node->tag) && embed )
+    {
+        icvWriteCollection( fs, node );
+    }
+    else
+    {
+        icvWriteFileNode( fs, new_node_name, node );
+    }
+    /*
+    int i, stream_count;
+    stream_count = fs->roots->total;
+    for( i = 0; i < stream_count; i++ )
+    {
+        CvFileNode* node = (CvFileNode*)cvGetSeqElem( fs->roots, i, 0 );
+        icvDumpCollection( dst, node );
+        if( i < stream_count - 1 )
+            dst->start_next_stream( dst );
+    }*/
+    cvReleaseFileStorage( &dst );
+}
+
+
+CV_IMPL const char*
+cvGetFileNodeName( const CvFileNode* file_node )
+{
+    return file_node && CV_NODE_HAS_NAME(file_node->tag) ?
+        ((CvFileMapNode*)file_node)->key->str.ptr : 0;
+}
+
+/****************************************************************************************\
+*                          Reading/Writing etc. for standard types                       *
+\****************************************************************************************/
+
+/*#define CV_TYPE_NAME_MAT "opencv-matrix"
+#define CV_TYPE_NAME_MATND "opencv-nd-matrix"
+#define CV_TYPE_NAME_SPARSE_MAT "opencv-sparse-matrix"
+#define CV_TYPE_NAME_IMAGE "opencv-image"
+#define CV_TYPE_NAME_SEQ "opencv-sequence"
+#define CV_TYPE_NAME_SEQ_TREE "opencv-sequence-tree"
+#define CV_TYPE_NAME_GRAPH "opencv-graph"*/
+
+/******************************* CvMat ******************************/
+
+static int
+icvIsMat( const void* ptr )
+{
+    return CV_IS_MAT_HDR(ptr);
+}
+
+static void
+icvWriteMat( CvFileStorage* fs, const char* name,
+             const void* struct_ptr, CvAttrList /*attr*/ )
+{
+    const CvMat* mat = (const CvMat*)struct_ptr;
+    char dt[16];
+    CvSize size;
+    int y;
+
+    assert( CV_IS_MAT(mat) );
+
+    cvStartWriteStruct( fs, name, CV_NODE_MAP, CV_TYPE_NAME_MAT );
+    cvWriteInt( fs, "rows", mat->rows );
+    cvWriteInt( fs, "cols", mat->cols );
+    cvWriteString( fs, "dt", icvEncodeFormat( CV_MAT_TYPE(mat->type), dt ), 0 );
+    cvStartWriteStruct( fs, "data", CV_NODE_SEQ + CV_NODE_FLOW );
+
+    size = cvGetSize(mat);
+    if( CV_IS_MAT_CONT(mat->type) )
+    {
+        size.width *= size.height;
+        size.height = 1;
+    }
+
+    for( y = 0; y < size.height; y++ )
+        cvWriteRawData( fs, mat->data.ptr + y*mat->step, size.width, dt );
+    cvEndWriteStruct( fs );
+    cvEndWriteStruct( fs );
+}
+
+
+static int
+icvFileNodeSeqLen( CvFileNode* node )
+{
+    return CV_NODE_IS_COLLECTION(node->tag) ? node->data.seq->total :
+           CV_NODE_TYPE(node->tag) != CV_NODE_NONE;
+}
+
+
+static void*
+icvReadMat( CvFileStorage* fs, CvFileNode* node )
+{
+    void* ptr = 0;
+    CvMat* mat;
+    const char* dt;
+    CvFileNode* data;
+    int rows, cols, elem_type;
+
+    rows = cvReadIntByName( fs, node, "rows", 0 );
+    cols = cvReadIntByName( fs, node, "cols", 0 );
+    dt = cvReadStringByName( fs, node, "dt", 0 );
+
+    if( rows == 0 || cols == 0 || dt == 0 )
+        CV_Error( CV_StsError, "Some of essential matrix attributes are absent" );
+
+    elem_type = icvDecodeSimpleFormat( dt );
+
+    data = cvGetFileNodeByName( fs, node, "data" );
+    if( !data )
+        CV_Error( CV_StsError, "The matrix data is not found in file storage" );
+
+    if( icvFileNodeSeqLen( data ) != rows*cols*CV_MAT_CN(elem_type) )
+        CV_Error( CV_StsUnmatchedSizes,
+        "The matrix size does not match to the number of stored elements" );
+
+    mat = cvCreateMat( rows, cols, elem_type );
+    cvReadRawData( fs, data, mat->data.ptr, dt );
+
+    ptr = mat;
+    return ptr;
+}
+
+
+/******************************* CvMatND ******************************/
+
+static int
+icvIsMatND( const void* ptr )
+{
+    return CV_IS_MATND(ptr);
+}
+
+
+static void
+icvWriteMatND( CvFileStorage* fs, const char* name,
+               const void* struct_ptr, CvAttrList /*attr*/ )
+{
+    void* mat = (void*)struct_ptr;
+    CvMatND stub;
+    CvNArrayIterator iterator;
+    int dims, sizes[CV_MAX_DIM];
+    char dt[16];
+
+    assert( CV_IS_MATND(mat) );
+
+    cvStartWriteStruct( fs, name, CV_NODE_MAP, CV_TYPE_NAME_MATND );
+    dims = cvGetDims( mat, sizes );
+    cvStartWriteStruct( fs, "sizes", CV_NODE_SEQ + CV_NODE_FLOW );
+    cvWriteRawData( fs, sizes, dims, "i" );
+    cvEndWriteStruct( fs );
+    cvWriteString( fs, "dt", icvEncodeFormat( cvGetElemType(mat), dt ), 0 );
+    cvStartWriteStruct( fs, "data", CV_NODE_SEQ + CV_NODE_FLOW );
+
+    cvInitNArrayIterator( 1, &mat, 0, &stub, &iterator );
+
+    do
+        cvWriteRawData( fs, iterator.ptr[0], iterator.size.width, dt );
+    while( cvNextNArraySlice( &iterator ));
+    cvEndWriteStruct( fs );
+    cvEndWriteStruct( fs );
+}
+
+
+static void*
+icvReadMatND( CvFileStorage* fs, CvFileNode* node )
+{
+    void* ptr = 0;
+    CvMatND* mat;
+    const char* dt;
+    CvFileNode* data;
+    CvFileNode* sizes_node;
+    int sizes[CV_MAX_DIM], dims, elem_type;
+    int i, total_size;
+
+    sizes_node = cvGetFileNodeByName( fs, node, "sizes" );
+    dt = cvReadStringByName( fs, node, "dt", 0 );
+
+    if( !sizes_node || !dt )
+        CV_Error( CV_StsError, "Some of essential matrix attributes are absent" );
+
+    dims = CV_NODE_IS_SEQ(sizes_node->tag) ? sizes_node->data.seq->total :
+           CV_NODE_IS_INT(sizes_node->tag) ? 1 : -1;
+
+    if( dims <= 0 || dims > CV_MAX_DIM )
+        CV_Error( CV_StsParseError, "Could not determine the matrix dimensionality" );
+
+    cvReadRawData( fs, sizes_node, sizes, "i" );
+    elem_type = icvDecodeSimpleFormat( dt );
+
+    data = cvGetFileNodeByName( fs, node, "data" );
+    if( !data )
+        CV_Error( CV_StsError, "The matrix data is not found in file storage" );
+
+    for( total_size = CV_MAT_CN(elem_type), i = 0; i < dims; i++ )
+        total_size *= sizes[i];
+
+    if( icvFileNodeSeqLen( data ) != total_size )
+        CV_Error( CV_StsUnmatchedSizes,
+        "The matrix size does not match to the number of stored elements" );
+
+    mat = cvCreateMatND( dims, sizes, elem_type );
+    cvReadRawData( fs, data, mat->data.ptr, dt );
+
+    ptr = mat;
+    return ptr;
+}
+
+
+/******************************* CvSparseMat ******************************/
+
+static int
+icvIsSparseMat( const void* ptr )
+{
+    return CV_IS_SPARSE_MAT(ptr);
+}
+
+
+static int
+icvSortIdxCmpFunc( const void* _a, const void* _b, void* userdata )
+{
+    int i, dims = *(int*)userdata;
+    const int* a = *(const int**)_a;
+    const int* b = *(const int**)_b;
+
+    for( i = 0; i < dims; i++ )
+    {
+        int delta = a[i] - b[i];
+        if( delta )
+            return delta;
+    }
+
+    return 0;
+}
+
+
+static void
+icvWriteSparseMat( CvFileStorage* fs, const char* name,
+                   const void* struct_ptr, CvAttrList /*attr*/ )
+{
+    CvMemStorage* memstorage = 0;
+    const CvSparseMat* mat = (const CvSparseMat*)struct_ptr;
+    CvSparseMatIterator iterator;
+    CvSparseNode* node;
+    CvSeq* elements;
+    CvSeqReader reader;
+    int i, dims;
+    int *prev_idx = 0;
+    char dt[16];
+
+    assert( CV_IS_SPARSE_MAT(mat) );
+
+    memstorage = cvCreateMemStorage();
+
+    cvStartWriteStruct( fs, name, CV_NODE_MAP, CV_TYPE_NAME_SPARSE_MAT );
+    dims = cvGetDims( mat, 0 );
+
+    cvStartWriteStruct( fs, "sizes", CV_NODE_SEQ + CV_NODE_FLOW );
+    cvWriteRawData( fs, mat->size, dims, "i" );
+    cvEndWriteStruct( fs );
+    cvWriteString( fs, "dt", icvEncodeFormat( CV_MAT_TYPE(mat->type), dt ), 0 );
+    cvStartWriteStruct( fs, "data", CV_NODE_SEQ + CV_NODE_FLOW );
+
+    elements = cvCreateSeq( CV_SEQ_ELTYPE_PTR, sizeof(CvSeq), sizeof(int*), memstorage );
+
+    node = cvInitSparseMatIterator( mat, &iterator );
+    while( node )
+    {
+        int* idx = CV_NODE_IDX( mat, node );
+        cvSeqPush( elements, &idx );
+        node = cvGetNextSparseNode( &iterator );
+    }
+
+    cvSeqSort( elements, icvSortIdxCmpFunc, &dims );
+    cvStartReadSeq( elements, &reader, 0 );
+
+    for( i = 0; i < elements->total; i++ )
+    {
+        int* idx;
+        void* val;
+        int k = 0;
+
+        CV_READ_SEQ_ELEM( idx, reader );
+        if( i > 0 )
+        {
+            for( ; idx[k] == prev_idx[k]; k++ )
+                assert( k < dims );
+            if( k < dims - 1 )
+                fs->write_int( fs, 0, k - dims + 1 );
+        }
+        for( ; k < dims; k++ )
+            fs->write_int( fs, 0, idx[k] );
+        prev_idx = idx;
+
+        node = (CvSparseNode*)((uchar*)idx - mat->idxoffset );
+        val = CV_NODE_VAL( mat, node );
+
+        cvWriteRawData( fs, val, 1, dt );
+    }
+
+    cvEndWriteStruct( fs );
+    cvEndWriteStruct( fs );
+    cvReleaseMemStorage( &memstorage );
+}
+
+
+static void*
+icvReadSparseMat( CvFileStorage* fs, CvFileNode* node )
+{
+    void* ptr = 0;
+    CvSparseMat* mat;
+    const char* dt;
+    CvFileNode* data;
+    CvFileNode* sizes_node;
+    CvSeqReader reader;
+    CvSeq* elements;
+    int* idx;
+    int* sizes = 0, dims, elem_type, cn;
+    int i;
+
+    sizes_node = cvGetFileNodeByName( fs, node, "sizes" );
+    dt = cvReadStringByName( fs, node, "dt", 0 );
+
+    if( !sizes_node || !dt )
+        CV_Error( CV_StsError, "Some of essential matrix attributes are absent" );
+
+    dims = CV_NODE_IS_SEQ(sizes_node->tag) ? sizes_node->data.seq->total :
+           CV_NODE_IS_INT(sizes_node->tag) ? 1 : -1;
+
+    if( dims <= 0 || dims > CV_MAX_DIM_HEAP )
+        CV_Error( CV_StsParseError, "Could not determine sparse matrix dimensionality" );
+
+    sizes = (int*)cvStackAlloc( dims*sizeof(sizes[0]));
+    cvReadRawData( fs, sizes_node, sizes, "i" );
+    elem_type = icvDecodeSimpleFormat( dt );
+
+    data = cvGetFileNodeByName( fs, node, "data" );
+    if( !data || !CV_NODE_IS_SEQ(data->tag) )
+        CV_Error( CV_StsError, "The matrix data is not found in file storage" );
+
+    mat = cvCreateSparseMat( dims, sizes, elem_type );
+
+    cn = CV_MAT_CN(elem_type);
+    idx = (int*)alloca( dims*sizeof(idx[0]) );
+    elements = data->data.seq;
+    cvStartReadRawData( fs, data, &reader );
+
+    for( i = 0; i < elements->total; )
+    {
+        CvFileNode* elem = (CvFileNode*)reader.ptr;
+        uchar* val;
+        int k;
+        if( !CV_NODE_IS_INT(elem->tag ))
+            CV_Error( CV_StsParseError, "Sparse matrix data is corrupted" );
+        k = elem->data.i;
+        if( i > 0 && k >= 0 )
+            idx[dims-1] = k;
+        else
+        {
+            if( i > 0 )
+                k = dims + k - 1;
+            else
+                idx[0] = k, k = 1;
+            for( ; k < dims; k++ )
+            {
+                CV_NEXT_SEQ_ELEM( elements->elem_size, reader );
+                i++;
+                elem = (CvFileNode*)reader.ptr;
+                if( !CV_NODE_IS_INT(elem->tag ) || elem->data.i < 0 )
+                    CV_Error( CV_StsParseError, "Sparse matrix data is corrupted" );
+                idx[k] = elem->data.i;
+            }
+        }
+        CV_NEXT_SEQ_ELEM( elements->elem_size, reader );
+        i++;
+        val = cvPtrND( mat, idx, 0, 1, 0 );
+        cvReadRawDataSlice( fs, &reader, cn, val, dt );
+        i += cn;
+    }
+
+    ptr = mat;
+    return ptr;
+}
+
+
+/******************************* IplImage ******************************/
+
+static int
+icvIsImage( const void* ptr )
+{
+    return CV_IS_IMAGE_HDR(ptr);
+}
+
+static void
+icvWriteImage( CvFileStorage* fs, const char* name,
+               const void* struct_ptr, CvAttrList /*attr*/ )
+{
+    const IplImage* image = (const IplImage*)struct_ptr;
+    char dt_buf[16], *dt;
+    CvSize size;
+    int y, depth;
+
+    assert( CV_IS_IMAGE(image) );
+
+    if( image->dataOrder == IPL_DATA_ORDER_PLANE )
+        CV_Error( CV_StsUnsupportedFormat,
+        "Images with planar data layout are not supported" );
+
+    cvStartWriteStruct( fs, name, CV_NODE_MAP, CV_TYPE_NAME_IMAGE );
+    cvWriteInt( fs, "width", image->width );
+    cvWriteInt( fs, "height", image->height );
+    cvWriteString( fs, "origin", image->origin == IPL_ORIGIN_TL
+                   ? "top-left" : "bottom-left", 0 );
+    cvWriteString( fs, "layout", image->dataOrder == IPL_DATA_ORDER_PLANE
+                   ? "planar" : "interleaved", 0 );
+    if( image->roi )
+    {
+        cvStartWriteStruct( fs, "roi", CV_NODE_MAP + CV_NODE_FLOW );
+        cvWriteInt( fs, "x", image->roi->xOffset );
+        cvWriteInt( fs, "y", image->roi->yOffset );
+        cvWriteInt( fs, "width", image->roi->width );
+        cvWriteInt( fs, "height", image->roi->height );
+        cvWriteInt( fs, "coi", image->roi->coi );
+        cvEndWriteStruct( fs );
+    }
+
+    depth = IplToCvDepth(image->depth);
+    sprintf( dt_buf, "%d%c", image->nChannels, icvTypeSymbol[depth] );
+    dt = dt_buf + (dt_buf[2] == '\0' && dt_buf[0] == '1');
+    cvWriteString( fs, "dt", dt, 0 );
+
+    size = cvSize(image->width, image->height);
+    if( size.width*image->nChannels*CV_ELEM_SIZE(depth) == image->widthStep )
+    {
+        size.width *= size.height;
+        size.height = 1;
+    }
+
+    cvStartWriteStruct( fs, "data", CV_NODE_SEQ + CV_NODE_FLOW );
+    for( y = 0; y < size.height; y++ )
+        cvWriteRawData( fs, image->imageData + y*image->widthStep, size.width, dt );
+    cvEndWriteStruct( fs );
+    cvEndWriteStruct( fs );
+}
+
+
+static void*
+icvReadImage( CvFileStorage* fs, CvFileNode* node )
+{
+    void* ptr = 0;
+    IplImage* image;
+    const char* dt;
+    CvFileNode* data;
+    CvFileNode* roi_node;
+    CvSeqReader reader;
+    CvRect roi;
+    int y, width, height, elem_type, coi, depth;
+    const char* origin, *data_order;
+
+    width = cvReadIntByName( fs, node, "width", 0 );
+    height = cvReadIntByName( fs, node, "height", 0 );
+    dt = cvReadStringByName( fs, node, "dt", 0 );
+    origin = cvReadStringByName( fs, node, "origin", 0 );
+
+    if( width == 0 || height == 0 || dt == 0 || origin == 0 )
+        CV_Error( CV_StsError, "Some of essential image attributes are absent" );
+
+    elem_type = icvDecodeSimpleFormat( dt );
+    data_order = cvReadStringByName( fs, node, "layout", "interleaved" );
+    if( strcmp( data_order, "interleaved" ) != 0 )
+        CV_Error( CV_StsError, "Only interleaved images can be read" );
+
+    data = cvGetFileNodeByName( fs, node, "data" );
+    if( !data )
+        CV_Error( CV_StsError, "The image data is not found in file storage" );
+
+    if( icvFileNodeSeqLen( data ) != width*height*CV_MAT_CN(elem_type) )
+        CV_Error( CV_StsUnmatchedSizes,
+        "The matrix size does not match to the number of stored elements" );
+
+    depth = cvIplDepth(elem_type);
+    image = cvCreateImage( cvSize(width,height), depth, CV_MAT_CN(elem_type) );
+
+    roi_node = cvGetFileNodeByName( fs, node, "roi" );
+    if( roi_node )
+    {
+        roi.x = cvReadIntByName( fs, roi_node, "x", 0 );
+        roi.y = cvReadIntByName( fs, roi_node, "y", 0 );
+        roi.width = cvReadIntByName( fs, roi_node, "width", 0 );
+        roi.height = cvReadIntByName( fs, roi_node, "height", 0 );
+        coi = cvReadIntByName( fs, roi_node, "coi", 0 );
+
+        cvSetImageROI( image, roi );
+        cvSetImageCOI( image, coi );
+    }
+
+    if( width*CV_ELEM_SIZE(elem_type) == image->widthStep )
+    {
+        width *= height;
+        height = 1;
+    }
+
+    width *= CV_MAT_CN(elem_type);
+    cvStartReadRawData( fs, data, &reader );
+    for( y = 0; y < height; y++ )
+    {
+        cvReadRawDataSlice( fs, &reader, width,
+            image->imageData + y*image->widthStep, dt );
+    }
+
+    ptr = image;
+    return ptr;
+}
+
+
+/******************************* CvSeq ******************************/
+
+static int
+icvIsSeq( const void* ptr )
+{
+    return CV_IS_SEQ(ptr);
+}
+
+
+static void
+icvReleaseSeq( void** ptr )
+{
+    if( !ptr )
+        CV_Error( CV_StsNullPtr, "NULL double pointer" );
+    *ptr = 0; // it's impossible now to release seq, so just clear the pointer
+}
+
+
+static void*
+icvCloneSeq( const void* ptr )
+{
+    return cvSeqSlice( (CvSeq*)ptr, CV_WHOLE_SEQ,
+                       0 /* use the same storage as for the original sequence */, 1 );
+}
+
+
+static void
+icvWriteHeaderData( CvFileStorage* fs, const CvSeq* seq,
+                    CvAttrList* attr, int initial_header_size )
+{
+    char header_dt_buf[128];
+    const char* header_dt = cvAttrValue( attr, "header_dt" );
+
+    if( header_dt )
+    {
+        int dt_header_size;
+        dt_header_size = icvCalcElemSize( header_dt, initial_header_size );
+        if( dt_header_size > seq->header_size )
+            CV_Error( CV_StsUnmatchedSizes,
+            "The size of header calculated from \"header_dt\" is greater than header_size" );
+    }
+    else if( seq->header_size > initial_header_size )
+    {
+        if( CV_IS_SEQ(seq) && CV_IS_SEQ_POINT_SET(seq) &&
+            seq->header_size == sizeof(CvPoint2DSeq) &&
+            seq->elem_size == sizeof(int)*2 )
+        {
+            CvPoint2DSeq* point_seq = (CvPoint2DSeq*)seq;
+
+            cvStartWriteStruct( fs, "rect", CV_NODE_MAP + CV_NODE_FLOW );
+            cvWriteInt( fs, "x", point_seq->rect.x );
+            cvWriteInt( fs, "y", point_seq->rect.y );
+            cvWriteInt( fs, "width", point_seq->rect.width );
+            cvWriteInt( fs, "height", point_seq->rect.height );
+            cvEndWriteStruct( fs );
+            cvWriteInt( fs, "color", point_seq->color );
+        }
+        else if( CV_IS_SEQ(seq) && CV_IS_SEQ_CHAIN(seq) &&
+                 CV_MAT_TYPE(seq->flags) == CV_8UC1 )
+        {
+            CvChain* chain = (CvChain*)seq;
+
+            cvStartWriteStruct( fs, "origin", CV_NODE_MAP + CV_NODE_FLOW );
+            cvWriteInt( fs, "x", chain->origin.x );
+            cvWriteInt( fs, "y", chain->origin.y );
+            cvEndWriteStruct( fs );
+        }
+        else
+        {
+            unsigned extra_size = seq->header_size - initial_header_size;
+            // a heuristic to provide nice defaults for sequences of int's & float's
+            if( extra_size % sizeof(int) == 0 )
+                sprintf( header_dt_buf, "%ui", (unsigned)(extra_size/sizeof(int)) );
+            else
+                sprintf( header_dt_buf, "%uu", extra_size );
+            header_dt = header_dt_buf;
+        }
+    }
+
+    if( header_dt )
+    {
+        cvWriteString( fs, "header_dt", header_dt, 0 );
+        cvStartWriteStruct( fs, "header_user_data", CV_NODE_SEQ + CV_NODE_FLOW );
+        cvWriteRawData( fs, (uchar*)seq + sizeof(CvSeq), 1, header_dt );
+        cvEndWriteStruct( fs );
+    }
+}
+
+
+static char*
+icvGetFormat( const CvSeq* seq, const char* dt_key, CvAttrList* attr,
+              int initial_elem_size, char* dt_buf )
+{
+    char* dt = 0;
+    dt = (char*)cvAttrValue( attr, dt_key );
+
+    if( dt )
+    {
+        int dt_elem_size;
+        dt_elem_size = icvCalcElemSize( dt, initial_elem_size );
+        if( dt_elem_size != seq->elem_size )
+            CV_Error( CV_StsUnmatchedSizes,
+            "The size of element calculated from \"dt\" and "
+            "the elem_size do not match" );
+    }
+    else if( CV_MAT_TYPE(seq->flags) != 0 || seq->elem_size == 1 )
+    {
+        int align = CV_MAT_DEPTH(seq->flags) == CV_64F ? sizeof(double) : sizeof(size_t);
+        int full_elem_size = cvAlign(CV_ELEM_SIZE(seq->flags) + initial_elem_size, align);
+        if( seq->elem_size != full_elem_size )
+            CV_Error( CV_StsUnmatchedSizes,
+            "Size of sequence element (elem_size) is inconsistent with seq->flags" );
+        dt = icvEncodeFormat( CV_MAT_TYPE(seq->flags), dt_buf );
+    }
+    else if( seq->elem_size > initial_elem_size )
+    {
+        unsigned extra_elem_size = seq->elem_size - initial_elem_size;
+        // a heuristic to provide nice defaults for sequences of int's & float's
+        if( extra_elem_size % sizeof(int) == 0 )
+            sprintf( dt_buf, "%ui", (unsigned)(extra_elem_size/sizeof(int)) );
+        else
+            sprintf( dt_buf, "%uu", extra_elem_size );
+        dt = dt_buf;
+    }
+
+    return dt;
+}
+
+
+static void
+icvWriteSeq( CvFileStorage* fs, const char* name,
+             const void* struct_ptr,
+             CvAttrList attr, int level )
+{
+    const CvSeq* seq = (CvSeq*)struct_ptr;
+    CvSeqBlock* block;
+    char buf[128];
+    char dt_buf[128], *dt;
+
+    assert( CV_IS_SEQ( seq ));
+    cvStartWriteStruct( fs, name, CV_NODE_MAP, CV_TYPE_NAME_SEQ );
+
+    if( level >= 0 )
+        cvWriteInt( fs, "level", level );
+
+    sprintf( buf, "%08x", seq->flags );
+    cvWriteString( fs, "flags", buf, 1 );
+    cvWriteInt( fs, "count", seq->total );
+    dt = icvGetFormat( seq, "dt", &attr, 0, dt_buf );
+    cvWriteString( fs, "dt", dt, 0 );
+
+    icvWriteHeaderData( fs, seq, &attr, sizeof(CvSeq) );
+    cvStartWriteStruct( fs, "data", CV_NODE_SEQ + CV_NODE_FLOW );
+
+    for( block = seq->first; block; block = block->next )
+    {
+        cvWriteRawData( fs, block->data, block->count, dt );
+        if( block == seq->first->prev )
+            break;
+    }
+    cvEndWriteStruct( fs );
+    cvEndWriteStruct( fs );
+}
+
+
+static void
+icvWriteSeqTree( CvFileStorage* fs, const char* name,
+                 const void* struct_ptr, CvAttrList attr )
+{
+    const CvSeq* seq = (CvSeq*)struct_ptr;
+    const char* recursive_value = cvAttrValue( &attr, "recursive" );
+    int is_recursive = recursive_value &&
+                       strcmp(recursive_value,"0") != 0 &&
+                       strcmp(recursive_value,"false") != 0 &&
+                       strcmp(recursive_value,"False") != 0 &&
+                       strcmp(recursive_value,"FALSE") != 0;
+
+    assert( CV_IS_SEQ( seq ));
+
+    if( !is_recursive )
+    {
+        icvWriteSeq( fs, name, seq, attr, -1 );
+    }
+    else
+    {
+        CvTreeNodeIterator tree_iterator;
+
+        cvStartWriteStruct( fs, name, CV_NODE_MAP, CV_TYPE_NAME_SEQ_TREE );
+        cvStartWriteStruct( fs, "sequences", CV_NODE_SEQ );
+        cvInitTreeNodeIterator( &tree_iterator, seq, INT_MAX );
+
+        for(;;)
+        {
+            if( !tree_iterator.node )
+                break;
+            icvWriteSeq( fs, 0, tree_iterator.node, attr, tree_iterator.level );
+            cvNextTreeNode( &tree_iterator );
+        }
+
+        cvEndWriteStruct( fs );
+        cvEndWriteStruct( fs );
+    }
+}
+
+
+static void*
+icvReadSeq( CvFileStorage* fs, CvFileNode* node )
+{
+    void* ptr = 0;
+    CvSeq* seq;
+    CvSeqBlock* block;
+    CvFileNode *data, *header_node, *rect_node, *origin_node;
+    CvSeqReader reader;
+    int total, flags;
+    int elem_size, header_size = sizeof(CvSeq);
+    int fmt_pairs[CV_FS_MAX_FMT_PAIRS], i, fmt_pair_count;
+    int items_per_elem = 0;
+    const char* flags_str;
+    const char* header_dt;
+    const char* dt;
+    char* endptr = 0;
+
+    flags_str = cvReadStringByName( fs, node, "flags", 0 );
+    total = cvReadIntByName( fs, node, "count", -1 );
+    dt = cvReadStringByName( fs, node, "dt", 0 );
+
+    if( !flags_str || total == -1 || !dt )
+        CV_Error( CV_StsError, "Some of essential sequence attributes are absent" );
+
+    flags = (int)strtol( flags_str, &endptr, 16 );
+    if( endptr == flags_str || (flags & CV_MAGIC_MASK) != CV_SEQ_MAGIC_VAL )
+        CV_Error( CV_StsError, "The sequence flags are invalid" );
+
+    header_dt = cvReadStringByName( fs, node, "header_dt", 0 );
+    header_node = cvGetFileNodeByName( fs, node, "header_user_data" );
+
+    if( (header_dt != 0) ^ (header_node != 0) )
+        CV_Error( CV_StsError,
+        "One of \"header_dt\" and \"header_user_data\" is there, while the other is not" );
+
+    rect_node = cvGetFileNodeByName( fs, node, "rect" );
+    origin_node = cvGetFileNodeByName( fs, node, "origin" );
+
+    if( (header_node != 0) + (rect_node != 0) + (origin_node != 0) > 1 )
+        CV_Error( CV_StsError, "Only one of \"header_user_data\", \"rect\" and \"origin\" tags may occur" );
+
+    if( header_dt )
+    {
+        header_size = icvCalcElemSize( header_dt, header_size );
+    }
+    else if( rect_node )
+        header_size = sizeof(CvPoint2DSeq);
+    else if( origin_node )
+        header_size = sizeof(CvChain);
+
+    elem_size = icvCalcElemSize( dt, 0 );
+    seq = cvCreateSeq( flags, header_size, elem_size, fs->dststorage );
+
+    if( header_node )
+    {
+        cvReadRawData( fs, header_node, (char*)seq + sizeof(CvSeq), header_dt );
+    }
+    else if( rect_node )
+    {
+        CvPoint2DSeq* point_seq = (CvPoint2DSeq*)seq;
+        point_seq->rect.x = cvReadIntByName( fs, rect_node, "x", 0 );
+        point_seq->rect.y = cvReadIntByName( fs, rect_node, "y", 0 );
+        point_seq->rect.width = cvReadIntByName( fs, rect_node, "width", 0 );
+        point_seq->rect.height = cvReadIntByName( fs, rect_node, "height", 0 );
+        point_seq->color = cvReadIntByName( fs, node, "color", 0 );
+    }
+    else if( origin_node )
+    {
+        CvChain* chain = (CvChain*)seq;
+        chain->origin.x = cvReadIntByName( fs, origin_node, "x", 0 );
+        chain->origin.y = cvReadIntByName( fs, origin_node, "y", 0 );
+    }
+
+    cvSeqPushMulti( seq, 0, total, 0 );
+    fmt_pair_count = icvDecodeFormat( dt, fmt_pairs, CV_FS_MAX_FMT_PAIRS );
+    fmt_pair_count *= 2;
+    for( i = 0; i < fmt_pair_count; i += 2 )
+        items_per_elem += fmt_pairs[i];
+
+    data = cvGetFileNodeByName( fs, node, "data" );
+    if( !data )
+        CV_Error( CV_StsError, "The image data is not found in file storage" );
+
+    if( icvFileNodeSeqLen( data ) != total*items_per_elem )
+        CV_Error( CV_StsError, "The number of stored elements does not match to \"count\"" );
+
+    cvStartReadRawData( fs, data, &reader );
+    for( block = seq->first; block; block = block->next )
+    {
+        int delta = block->count*items_per_elem;
+        cvReadRawDataSlice( fs, &reader, delta, block->data, dt );
+        if( block == seq->first->prev )
+            break;
+    }
+
+    ptr = seq;
+    return ptr;
+}
+
+
+static void*
+icvReadSeqTree( CvFileStorage* fs, CvFileNode* node )
+{
+    void* ptr = 0;
+    CvFileNode *sequences_node = cvGetFileNodeByName( fs, node, "sequences" );
+    CvSeq* sequences;
+    CvSeq* root = 0;
+    CvSeq* parent = 0;
+    CvSeq* prev_seq = 0;
+    CvSeqReader reader;
+    int i, total;
+    int prev_level = 0;
+
+    if( !sequences_node || !CV_NODE_IS_SEQ(sequences_node->tag) )
+        CV_Error( CV_StsParseError,
+        "opencv-sequence-tree instance should contain a field \"sequences\" that should be a sequence" );
+
+    sequences = sequences_node->data.seq;
+    total = sequences->total;
+
+    cvStartReadSeq( sequences, &reader, 0 );
+    for( i = 0; i < total; i++ )
+    {
+        CvFileNode* elem = (CvFileNode*)reader.ptr;
+        CvSeq* seq;
+        int level;
+        seq = (CvSeq*)cvRead( fs, elem );
+        level = cvReadIntByName( fs, elem, "level", -1 );
+        if( level < 0 )
+            CV_Error( CV_StsParseError, "All the sequence tree nodes should contain \"level\" field" );
+        if( !root )
+            root = seq;
+        if( level > prev_level )
+        {
+            assert( level == prev_level + 1 );
+            parent = prev_seq;
+            prev_seq = 0;
+            if( parent )
+                parent->v_next = seq;
+        }
+        else if( level < prev_level )
+        {
+            for( ; prev_level > level; prev_level-- )
+                prev_seq = prev_seq->v_prev;
+            parent = prev_seq->v_prev;
+        }
+        seq->h_prev = prev_seq;
+        if( prev_seq )
+            prev_seq->h_next = seq;
+        seq->v_prev = parent;
+        prev_seq = seq;
+        prev_level = level;
+        CV_NEXT_SEQ_ELEM( sequences->elem_size, reader );
+    }
+
+    ptr = root;
+    return ptr;
+}
+
+/******************************* CvGraph ******************************/
+
+static int
+icvIsGraph( const void* ptr )
+{
+    return CV_IS_GRAPH(ptr);
+}
+
+
+static void
+icvReleaseGraph( void** ptr )
+{
+    if( !ptr )
+        CV_Error( CV_StsNullPtr, "NULL double pointer" );
+
+    *ptr = 0; // it's impossible now to release graph, so just clear the pointer
+}
+
+
+static void*
+icvCloneGraph( const void* ptr )
+{
+    return cvCloneGraph( (const CvGraph*)ptr, 0 );
+}
+
+
+static void
+icvWriteGraph( CvFileStorage* fs, const char* name,
+               const void* struct_ptr, CvAttrList attr )
+{
+    int* flag_buf = 0;
+    char* write_buf = 0;
+    const CvGraph* graph = (const CvGraph*)struct_ptr;
+    CvSeqReader reader;
+    char buf[128];
+    int i, k, vtx_count, edge_count;
+    char vtx_dt_buf[128], *vtx_dt;
+    char edge_dt_buf[128], *edge_dt;
+    int write_buf_size;
+
+    assert( CV_IS_GRAPH(graph) );
+    vtx_count = cvGraphGetVtxCount( graph );
+    edge_count = cvGraphGetEdgeCount( graph );
+    flag_buf = (int*)cvAlloc( vtx_count*sizeof(flag_buf[0]));
+
+    // count vertices
+    cvStartReadSeq( (CvSeq*)graph, &reader );
+    for( i = 0, k = 0; i < graph->total; i++ )
+    {
+        if( CV_IS_SET_ELEM( reader.ptr ))
+        {
+            CvGraphVtx* vtx = (CvGraphVtx*)reader.ptr;
+            flag_buf[k] = vtx->flags;
+            vtx->flags = k++;
+        }
+        CV_NEXT_SEQ_ELEM( graph->elem_size, reader );
+    }
+
+    // write header
+    cvStartWriteStruct( fs, name, CV_NODE_MAP, CV_TYPE_NAME_GRAPH );
+
+    sprintf( buf, "%08x", graph->flags );
+    cvWriteString( fs, "flags", buf, 1 );
+
+    cvWriteInt( fs, "vertex_count", vtx_count );
+    vtx_dt = icvGetFormat( (CvSeq*)graph, "vertex_dt",
+                    &attr, sizeof(CvGraphVtx), vtx_dt_buf );
+    if( vtx_dt )
+        cvWriteString( fs, "vertex_dt", vtx_dt, 0 );
+
+    cvWriteInt( fs, "edge_count", edge_count );
+    edge_dt = icvGetFormat( (CvSeq*)graph->edges, "edge_dt",
+                                &attr, sizeof(CvGraphEdge), buf );
+    sprintf( edge_dt_buf, "2if%s", edge_dt ? edge_dt : "" );
+    edge_dt = edge_dt_buf;
+    cvWriteString( fs, "edge_dt", edge_dt, 0 );
+
+    icvWriteHeaderData( fs, (CvSeq*)graph, &attr, sizeof(CvGraph) );
+
+    write_buf_size = MAX( 3*graph->elem_size, 1 << 16 );
+    write_buf_size = MAX( 3*graph->edges->elem_size, write_buf_size );
+    write_buf = (char*)cvAlloc( write_buf_size );
+
+    // as vertices and edges are written in similar way,
+    // do it as a parametrized 2-iteration loop
+    for( k = 0; k < 2; k++ )
+    {
+        const char* dt = k == 0 ? vtx_dt : edge_dt;
+        if( dt )
+        {
+            CvSet* data = k == 0 ? (CvSet*)graph : graph->edges;
+            int elem_size = data->elem_size;
+            int write_elem_size = icvCalcElemSize( dt, 0 );
+            char* src_ptr = write_buf;
+            int write_max = write_buf_size / write_elem_size, write_count = 0;
+
+            // alignment of user part of the edge data following 2if
+            int edge_user_align = sizeof(float);
+
+            if( k == 1 )
+            {
+                int fmt_pairs[CV_FS_MAX_FMT_PAIRS], fmt_pair_count;
+                fmt_pair_count = icvDecodeFormat( dt, fmt_pairs, CV_FS_MAX_FMT_PAIRS );
+                if( fmt_pair_count > 2 || CV_ELEM_SIZE(fmt_pairs[2*2+1]) >= (int)sizeof(double))
+                    edge_user_align = sizeof(double);
+            }
+
+            cvStartWriteStruct( fs, k == 0 ? "vertices" : "edges",
+                                CV_NODE_SEQ + CV_NODE_FLOW );
+            cvStartReadSeq( (CvSeq*)data, &reader );
+            for( i = 0; i < data->total; i++ )
+            {
+                if( CV_IS_SET_ELEM( reader.ptr ))
+                {
+                    if( k == 0 ) // vertices
+                        memcpy( src_ptr, reader.ptr + sizeof(CvGraphVtx), write_elem_size );
+                    else
+                    {
+                        CvGraphEdge* edge = (CvGraphEdge*)reader.ptr;
+                        src_ptr = (char*)cvAlignPtr( src_ptr, sizeof(int) );
+                        ((int*)src_ptr)[0] = edge->vtx[0]->flags;
+                        ((int*)src_ptr)[1] = edge->vtx[1]->flags;
+                        *(float*)(src_ptr + sizeof(int)*2) = edge->weight;
+                        if( elem_size > (int)sizeof(CvGraphEdge) )
+                        {
+                            char* src_ptr2 = (char*)cvAlignPtr( src_ptr + 2*sizeof(int)
+                                                + sizeof(float), edge_user_align );
+                            memcpy( src_ptr2, edge + 1, elem_size - sizeof(CvGraphEdge) );
+                        }
+                    }
+                    src_ptr += write_elem_size;
+                    if( ++write_count >= write_max )
+                    {
+                        cvWriteRawData( fs, write_buf, write_count, dt );
+                        write_count = 0;
+                        src_ptr = write_buf;
+                    }
+                }
+                CV_NEXT_SEQ_ELEM( data->elem_size, reader );
+            }
+
+            if( write_count > 0 )
+                cvWriteRawData( fs, write_buf, write_count, dt );
+            cvEndWriteStruct( fs );
+        }
+    }
+
+    cvEndWriteStruct( fs );
+
+    // final stage. restore the graph flags
+    cvStartReadSeq( (CvSeq*)graph, &reader );
+    vtx_count = 0;
+    for( i = 0; i < graph->total; i++ )
+    {
+        if( CV_IS_SET_ELEM( reader.ptr ))
+            ((CvGraphVtx*)reader.ptr)->flags = flag_buf[vtx_count++];
+        CV_NEXT_SEQ_ELEM( graph->elem_size, reader );
+    }
+
+    cvFree( &write_buf );
+    cvFree( &flag_buf );
+}
+
+
+static void*
+icvReadGraph( CvFileStorage* fs, CvFileNode* node )
+{
+    void* ptr = 0;
+    char* read_buf = 0;
+    CvGraphVtx** vtx_buf = 0;
+    CvGraph* graph;
+    CvFileNode *header_node, *vtx_node, *edge_node;
+    int flags, vtx_count, edge_count;
+    int vtx_size = sizeof(CvGraphVtx), edge_size, header_size = sizeof(CvGraph);
+    int src_vtx_size = 0, src_edge_size;
+    int fmt_pairs[CV_FS_MAX_FMT_PAIRS], fmt_pair_count;
+    int vtx_items_per_elem = 0, edge_items_per_elem = 0;
+    int edge_user_align = sizeof(float);
+    int read_buf_size;
+    int i, k;
+    const char* flags_str;
+    const char* header_dt;
+    const char* vtx_dt;
+    const char* edge_dt;
+    char* endptr = 0;
+
+    flags_str = cvReadStringByName( fs, node, "flags", 0 );
+    vtx_dt = cvReadStringByName( fs, node, "vertex_dt", 0 );
+    edge_dt = cvReadStringByName( fs, node, "edge_dt", 0 );
+    vtx_count = cvReadIntByName( fs, node, "vertex_count", -1 );
+    edge_count = cvReadIntByName( fs, node, "edge_count", -1 );
+
+    if( !flags_str || vtx_count == -1 || edge_count == -1 || !edge_dt )
+        CV_Error( CV_StsError, "Some of essential sequence attributes are absent" );
+
+    flags = (int)strtol( flags_str, &endptr, 16 );
+    if( endptr == flags_str ||
+        (flags & (CV_SEQ_KIND_MASK|CV_MAGIC_MASK)) != (CV_GRAPH|CV_SET_MAGIC_VAL))
+        CV_Error( CV_StsError, "Invalid graph signature" );
+
+    header_dt = cvReadStringByName( fs, node, "header_dt", 0 );
+    header_node = cvGetFileNodeByName( fs, node, "header_user_data" );
+
+    if( (header_dt != 0) ^ (header_node != 0) )
+        CV_Error( CV_StsError,
+        "One of \"header_dt\" and \"header_user_data\" is there, while the other is not" );
+
+    if( header_dt )
+        header_size = icvCalcElemSize( header_dt, header_size );
+
+    if( vtx_dt > 0 )
+    {
+        src_vtx_size = icvCalcElemSize( vtx_dt, 0 );
+        vtx_size = icvCalcElemSize( vtx_dt, vtx_size );
+        fmt_pair_count = icvDecodeFormat( edge_dt,
+                            fmt_pairs, CV_FS_MAX_FMT_PAIRS );
+        fmt_pair_count *= 2;
+        for( i = 0; i < fmt_pair_count; i += 2 )
+            vtx_items_per_elem += fmt_pairs[i];
+    }
+
+    {
+        char dst_edge_dt_buf[128];
+        const char* dst_edge_dt = 0;
+
+        fmt_pair_count = icvDecodeFormat( edge_dt,
+                            fmt_pairs, CV_FS_MAX_FMT_PAIRS );
+        if( fmt_pair_count < 2 ||
+            fmt_pairs[0] != 2 || fmt_pairs[1] != CV_32S ||
+            fmt_pairs[2] < 1 || fmt_pairs[3] != CV_32F )
+            CV_Error( CV_StsBadArg,
+            "Graph edges should start with 2 integers and a float" );
+
+        // alignment of user part of the edge data following 2if
+        if( fmt_pair_count > 2 && CV_ELEM_SIZE(fmt_pairs[5]) >= (int)sizeof(double))
+            edge_user_align = sizeof(double);
+
+        fmt_pair_count *= 2;
+        for( i = 0; i < fmt_pair_count; i += 2 )
+            edge_items_per_elem += fmt_pairs[i];
+
+        if( edge_dt[2] == 'f' || (edge_dt[2] == '1' && edge_dt[3] == 'f') )
+            dst_edge_dt = edge_dt + 3 + isdigit(edge_dt[2]);
+        else
+        {
+            int val = (int)strtol( edge_dt + 2, &endptr, 10 );
+            sprintf( dst_edge_dt_buf, "%df%s", val-1, endptr );
+            dst_edge_dt = dst_edge_dt_buf;
+        }
+
+        edge_size = icvCalcElemSize( dst_edge_dt, sizeof(CvGraphEdge) );
+        src_edge_size = icvCalcElemSize( edge_dt, 0 );
+    }
+
+    graph = cvCreateGraph( flags, header_size, vtx_size, edge_size, fs->dststorage );
+
+    if( header_node )
+        cvReadRawData( fs, header_node, (char*)graph + sizeof(CvGraph), header_dt );
+
+    read_buf_size = MAX( src_vtx_size*3, 1 << 16 );
+    read_buf_size = MAX( src_edge_size*3, read_buf_size );
+    read_buf = (char*)cvAlloc( read_buf_size );
+    vtx_buf = (CvGraphVtx**)cvAlloc( vtx_count * sizeof(vtx_buf[0]) );
+
+    vtx_node = cvGetFileNodeByName( fs, node, "vertices" );
+    edge_node = cvGetFileNodeByName( fs, node, "edges" );
+    if( !edge_node )
+        CV_Error( CV_StsBadArg, "No edges data" );
+    if( vtx_dt && !vtx_node )
+        CV_Error( CV_StsBadArg, "No vertices data" );
+
+    // as vertices and edges are read in similar way,
+    // do it as a parametrized 2-iteration loop
+    for( k = 0; k < 2; k++ )
+    {
+        const char* dt = k == 0 ? vtx_dt : edge_dt;
+        int elem_size = k == 0 ? vtx_size : edge_size;
+        int src_elem_size = k == 0 ? src_vtx_size : src_edge_size;
+        int items_per_elem = k == 0 ? vtx_items_per_elem : edge_items_per_elem;
+        int elem_count = k == 0 ? vtx_count : edge_count;
+        char* dst_ptr = read_buf;
+        int read_max = read_buf_size /MAX(src_elem_size, 1), read_count = 0;
+        CvSeqReader reader;
+        cvStartReadRawData( fs, k == 0 ? vtx_node : edge_node, &reader );
+
+        for( i = 0; i < elem_count; i++ )
+        {
+            if( read_count == 0 && dt )
+            {
+                int count = MIN( elem_count - i, read_max )*items_per_elem;
+                cvReadRawDataSlice( fs, &reader, count, read_buf, dt );
+                read_count = count;
+                dst_ptr = read_buf;
+            }
+
+            if( k == 0 )
+            {
+                CvGraphVtx* vtx;
+                cvGraphAddVtx( graph, 0, &vtx );
+                vtx_buf[i] = vtx;
+                if( dt )
+                    memcpy( vtx + 1, dst_ptr, src_elem_size );
+            }
+            else
+            {
+                CvGraphEdge* edge = 0;
+                int vtx1 = ((int*)dst_ptr)[0];
+                int vtx2 = ((int*)dst_ptr)[1];
+                int result;
+
+                if( (unsigned)vtx1 >= (unsigned)vtx_count ||
+                    (unsigned)vtx2 >= (unsigned)vtx_count )
+                    CV_Error( CV_StsOutOfRange,
+                    "Some of stored vertex indices are out of range" );
+
+                result = cvGraphAddEdgeByPtr( graph,
+                    vtx_buf[vtx1], vtx_buf[vtx2], 0, &edge );
+
+                if( result == 0 )
+                    CV_Error( CV_StsBadArg, "Duplicated edge has occured" );
+
+                edge->weight = *(float*)(dst_ptr + sizeof(int)*2);
+                if( elem_size > (int)sizeof(CvGraphEdge) )
+                {
+                    char* dst_ptr2 = (char*)cvAlignPtr( dst_ptr + sizeof(int)*2 +
+                                                sizeof(float), edge_user_align );
+                    memcpy( edge + 1, dst_ptr2, elem_size - sizeof(CvGraphEdge) );
+                }
+            }
+
+            dst_ptr += src_elem_size;
+            read_count--;
+        }
+    }
+
+    ptr = graph;
+    cvFree( &read_buf );
+    cvFree( &vtx_buf );
+
+    return ptr;
+}
+
+/****************************************************************************************\
+*                                    RTTI Functions                                      *
+\****************************************************************************************/
+
+CvTypeInfo *CvType::first = 0, *CvType::last = 0;
+
+CvType::CvType( const char* type_name,
+                CvIsInstanceFunc is_instance, CvReleaseFunc release,
+                CvReadFunc read, CvWriteFunc write, CvCloneFunc clone )
+{
+    CvTypeInfo _info;
+    _info.flags = 0;
+    _info.header_size = sizeof(_info);
+    _info.type_name = type_name;
+    _info.prev = _info.next = 0;
+    _info.is_instance = is_instance;
+    _info.release = release;
+    _info.clone = clone;
+    _info.read = read;
+    _info.write = write;
+
+    cvRegisterType( &_info );
+    info = first;
+}
+
+
+CvType::~CvType()
+{
+    cvUnregisterType( info->type_name );
+}
+
+
+CvType seq_type( CV_TYPE_NAME_SEQ, icvIsSeq, icvReleaseSeq, icvReadSeq,
+                 icvWriteSeqTree /* this is the entry point for
+                 writing a single sequence too */, icvCloneSeq );
+
+CvType seq_tree_type( CV_TYPE_NAME_SEQ_TREE, icvIsSeq, icvReleaseSeq,
+                      icvReadSeqTree, icvWriteSeqTree, icvCloneSeq );
+
+CvType seq_graph_type( CV_TYPE_NAME_GRAPH, icvIsGraph, icvReleaseGraph,
+                       icvReadGraph, icvWriteGraph, icvCloneGraph );
+
+CvType sparse_mat_type( CV_TYPE_NAME_SPARSE_MAT, icvIsSparseMat,
+                        (CvReleaseFunc)cvReleaseSparseMat, icvReadSparseMat,
+                        icvWriteSparseMat, (CvCloneFunc)cvCloneSparseMat );
+
+CvType image_type( CV_TYPE_NAME_IMAGE, icvIsImage, (CvReleaseFunc)cvReleaseImage,
+                   icvReadImage, icvWriteImage, (CvCloneFunc)cvCloneImage );
+
+CvType mat_type( CV_TYPE_NAME_MAT, icvIsMat, (CvReleaseFunc)cvReleaseMat,
+                 icvReadMat, icvWriteMat, (CvCloneFunc)cvCloneMat );
+
+CvType matnd_type( CV_TYPE_NAME_MATND, icvIsMatND, (CvReleaseFunc)cvReleaseMatND,
+                   icvReadMatND, icvWriteMatND, (CvCloneFunc)cvCloneMatND );
+
+CV_IMPL  void
+cvRegisterType( const CvTypeInfo* _info )
+{
+    CvTypeInfo* info = 0;
+    int i, len;
+    char c;
+
+    //if( !CvType::first )
+    //    icvCreateStandardTypes();
+
+    if( !_info || _info->header_size != sizeof(CvTypeInfo) )
+        CV_Error( CV_StsBadSize, "Invalid type info" );
+
+    if( !_info->is_instance || !_info->release ||
+        !_info->read || !_info->write )
+        CV_Error( CV_StsNullPtr,
+        "Some of required function pointers "
+        "(is_instance, release, read or write) are NULL");
+
+    c = _info->type_name[0];
+    if( !isalpha(c) && c != '_' )
+        CV_Error( CV_StsBadArg, "Type name should start with a letter or _" );
+
+    len = (int)strlen(_info->type_name);
+
+    for( i = 0; i < len; i++ )
+    {
+        c = _info->type_name[i];
+        if( !isalnum(c) && c != '-' && c != '_' )
+            CV_Error( CV_StsBadArg,
+            "Type name should contain only letters, digits, - and _" );
+    }
+
+    info = (CvTypeInfo*)malloc( sizeof(*info) + len + 1 );
+
+    *info = *_info;
+    info->type_name = (char*)(info + 1);
+    memcpy( (char*)info->type_name, _info->type_name, len + 1 );
+
+    info->flags = 0;
+    info->next = CvType::first;
+    info->prev = 0;
+    if( CvType::first )
+        CvType::first->prev = info;
+    else
+        CvType::last = info;
+    CvType::first = info;
+}
+
+
+CV_IMPL void
+cvUnregisterType( const char* type_name )
+{
+    CvTypeInfo* info;
+
+    info = cvFindType( type_name );
+    if( info )
+    {
+        if( info->prev )
+            info->prev->next = info->next;
+        else
+            CvType::first = info->next;
+
+        if( info->next )
+            info->next->prev = info->prev;
+        else
+            CvType::last = info->prev;
+
+        if( !CvType::first || !CvType::last )
+            CvType::first = CvType::last = 0;
+
+        free( info );
+    }
+}
+
+
+CV_IMPL CvTypeInfo*
+cvFirstType( void )
+{
+    return CvType::first;
+}
+
+
+CV_IMPL CvTypeInfo*
+cvFindType( const char* type_name )
+{
+    CvTypeInfo* info = 0;
+
+    for( info = CvType::first; info != 0; info = info->next )
+        if( strcmp( info->type_name, type_name ) == 0 )
+            break;
+
+    return info;
+}
+
+
+CV_IMPL CvTypeInfo*
+cvTypeOf( const void* struct_ptr )
+{
+    CvTypeInfo* info = 0;
+
+    for( info = CvType::first; info != 0; info = info->next )
+        if( info->is_instance( struct_ptr ))
+            break;
+
+    return info;
+}
+
+
+/* universal functions */
+CV_IMPL void
+cvRelease( void** struct_ptr )
+{
+    CvTypeInfo* info;
+
+    if( !struct_ptr )
+        CV_Error( CV_StsNullPtr, "NULL double pointer" );
+
+    if( *struct_ptr )
+    {
+        info = cvTypeOf( *struct_ptr );
+        if( !info )
+            CV_Error( CV_StsError, "Unknown object type" );
+        if( !info->release )
+            CV_Error( CV_StsError, "release function pointer is NULL" );
+
+        info->release( struct_ptr );
+        *struct_ptr = 0;
+    }
+}
+
+
+void* cvClone( const void* struct_ptr )
+{
+    void* struct_copy = 0;
+    CvTypeInfo* info;
+
+    if( !struct_ptr )
+        CV_Error( CV_StsNullPtr, "NULL structure pointer" );
+
+    info = cvTypeOf( struct_ptr );
+    if( !info )
+        CV_Error( CV_StsError, "Unknown object type" );
+    if( !info->clone )
+        CV_Error( CV_StsError, "clone function pointer is NULL" );
+
+    struct_copy = info->clone( struct_ptr );
+    return struct_copy;
+}
+
+
+/* reads matrix, image, sequence, graph etc. */
+CV_IMPL void*
+cvRead( CvFileStorage* fs, CvFileNode* node, CvAttrList* list )
+{
+    void* obj = 0;
+    CV_CHECK_FILE_STORAGE( fs );
+
+    if( !node )
+        return 0;
+
+    if( !CV_NODE_IS_USER(node->tag) || !node->info )
+        CV_Error( CV_StsError, "The node does not represent a user object (unknown type?)" );
+
+    obj = node->info->read( fs, node );
+    if( list )
+        *list = cvAttrList(0,0);
+
+    return obj;
+}
+
+
+/* writes matrix, image, sequence, graph etc. */
+CV_IMPL void
+cvWrite( CvFileStorage* fs, const char* name,
+         const void* ptr, CvAttrList attributes )
+{
+    CvTypeInfo* info;
+
+    CV_CHECK_OUTPUT_FILE_STORAGE( fs );
+
+    if( !ptr )
+        CV_Error( CV_StsNullPtr, "Null pointer to the written object" );
+
+    info = cvTypeOf( ptr );
+    if( !info )
+        CV_Error( CV_StsBadArg, "Unknown object" );
+
+    if( !info->write )
+        CV_Error( CV_StsBadArg, "The object does not have write function" );
+
+    info->write( fs, name, ptr, attributes );
+}
+
+
+/* simple API for reading/writing data */
+CV_IMPL void
+cvSave( const char* filename, const void* struct_ptr,
+        const char* _name, const char* comment, CvAttrList attributes )
+{
+    CvFileStorage* fs = 0;
+
+    if( !struct_ptr )
+        CV_Error( CV_StsNullPtr, "NULL object pointer" );
+
+    fs = cvOpenFileStorage( filename, 0, CV_STORAGE_WRITE );
+    if( !fs )
+        CV_Error( CV_StsError, "Could not open the file storage. Check the path and permissions" );
+
+    cv::String name = _name ? cv::String(_name) : cv::FileStorage::getDefaultObjectName(filename);
+
+    if( comment )
+        cvWriteComment( fs, comment, 0 );
+    cvWrite( fs, name.c_str(), struct_ptr, attributes );
+    cvReleaseFileStorage( &fs );
+}
+
+CV_IMPL void*
+cvLoad( const char* filename, CvMemStorage* memstorage,
+        const char* name, const char** _real_name )
+{
+    void* ptr = 0;
+    const char* real_name = 0;
+    CvFileStorage* fs = 0;
+
+    CvFileNode* node = 0;
+    fs = cvOpenFileStorage( filename, memstorage, CV_STORAGE_READ );
+
+    if( !fs )
+        return 0;
+
+    if( name )
+    {
+        node = cvGetFileNodeByName( fs, 0, name );
+    }
+    else
+    {
+        int i, k;
+        for( k = 0; k < fs->roots->total; k++ )
+        {
+            CvSeq* seq;
+            CvSeqReader reader;
+
+            node = (CvFileNode*)cvGetSeqElem( fs->roots, k );
+            if( !CV_NODE_IS_MAP( node->tag ))
+                EXIT;
+            seq = node->data.seq;
+            node = 0;
+
+            cvStartReadSeq( seq, &reader, 0 );
+
+            // find the first element in the map
+            for( i = 0; i < seq->total; i++ )
+            {
+                if( CV_IS_SET_ELEM( reader.ptr ))
+                {
+                    node = (CvFileNode*)reader.ptr;
+                    goto stop_search;
+                }
+                CV_NEXT_SEQ_ELEM( seq->elem_size, reader );
+            }
+        }
+
+stop_search:
+        ;
+    }
+
+    if( !node )
+        CV_Error( CV_StsObjectNotFound, "Could not find the/an object in file storage" );
+
+    real_name = cvGetFileNodeName( node );
+    ptr = cvRead( fs, node, 0 );
+
+    // sanity check
+    if( !memstorage && (CV_IS_SEQ( ptr ) || CV_IS_SET( ptr )) )
+        CV_Error( CV_StsNullPtr,
+        "NULL memory storage is passed - the loaded dynamic structure can not be stored" );
+
+    if( cvGetErrStatus() < 0 )
+    {
+        cvRelease( (void**)&ptr );
+        real_name = 0;
+    }
+
+    if( _real_name)
+    {
+       if (real_name)
+       {
+           *_real_name = (const char*)cvAlloc(strlen(real_name));
+           memcpy((void*)*_real_name, real_name, strlen(real_name));
+       } else {
+           *_real_name = 0;
+       }
+    }
+exit:
+    cvReleaseFileStorage( &fs );
+
+    return ptr;
+}
+
+
+///////////////////////// new C++ interface for CvFileStorage ///////////////////////////
+
+namespace cv
+{
+
+static void getElemSize( const String& fmt, size_t& elemSize, size_t& cn )
+{
+    const char* dt = fmt.c_str();
+    cn = 1;
+    if( isdigit(dt[0]) )
+    {
+        cn = dt[0] - '0';
+        dt++;
+    }
+    char c = dt[0];
+    elemSize = cn*(c == 'u' || c == 'c' ? sizeof(uchar) : c == 'w' || c == 's' ? sizeof(ushort) :
+        c == 'i' ? sizeof(int) : c == 'f' ? sizeof(float) : c == 'd' ? sizeof(double) :
+        c == 'r' ? sizeof(void*) : (size_t)0);
+}
+
+FileStorage::FileStorage()
+{
+    state = UNDEFINED;
+}
+
+FileStorage::FileStorage(const String& filename, int flags)
+{
+    state = UNDEFINED;
+    open( filename, flags );
+}
+
+FileStorage::FileStorage(CvFileStorage* _fs)
+{
+    fs = Ptr<CvFileStorage>(_fs);
+    state = _fs ? NAME_EXPECTED + INSIDE_MAP : UNDEFINED;
+}
+
+FileStorage::~FileStorage()
+{
+    while( structs.size() > 0 )
+    {
+        cvEndWriteStruct(fs);
+        structs.pop_back();
+    }
+}
+
+bool FileStorage::open(const String& filename, int flags)
+{
+    release();
+    fs = Ptr<CvFileStorage>(cvOpenFileStorage( filename.c_str(), 0, flags ));
+    bool ok = isOpened();
+    state = ok ? NAME_EXPECTED + INSIDE_MAP : UNDEFINED;
+    return ok;
+}
+
+bool FileStorage::isOpened() const
+{
+    return !fs.empty();
+}
+
+void FileStorage::release()
+{
+    fs.release();
+    structs.clear();
+    state = UNDEFINED;
+}
+
+FileNode FileStorage::root(int streamidx) const
+{
+    return isOpened() ? FileNode(fs, cvGetRootFileNode(fs, streamidx)) : FileNode();
+}
+
+FileStorage& operator << (FileStorage& fs, const String& str)
+{
+    enum { NAME_EXPECTED = FileStorage::NAME_EXPECTED,
+        VALUE_EXPECTED = FileStorage::VALUE_EXPECTED,
+        INSIDE_MAP = FileStorage::INSIDE_MAP };
+    const char* _str = str.c_str();
+    if( !fs.isOpened() || !_str )
+        return fs;
+    if( *_str == '}' || *_str == ']' )
+    {
+        if( fs.structs.empty() )
+            CV_Error_( CV_StsError, ("Extra closing '%c'", *_str) );
+        if( (*_str == ']' ? '[' : '{') != fs.structs.back() )
+            CV_Error_( CV_StsError,
+            ("The closing '%c' does not match the opening '%c'", *_str, fs.structs.back()));
+        fs.structs.pop_back();
+        fs.state = fs.structs.empty() || fs.structs.back() == '{' ?
+            INSIDE_MAP + NAME_EXPECTED : VALUE_EXPECTED;
+        cvEndWriteStruct( *fs );
+        fs.elname = String();
+    }
+    else if( fs.state == NAME_EXPECTED + INSIDE_MAP )
+    {
+        if( !isalpha(*_str) )
+            CV_Error_( CV_StsError, ("Incorrect element name %s", _str) );
+        fs.elname = str;
+        fs.state = VALUE_EXPECTED + INSIDE_MAP;
+    }
+    else if( (fs.state & 3) == VALUE_EXPECTED )
+    {
+        if( *_str == '{' || *_str == '[' )
+        {
+            fs.structs.push_back(*_str);
+            int flags = *_str++ == '{' ? CV_NODE_MAP : CV_NODE_SEQ;
+            fs.state = flags == CV_NODE_MAP ? INSIDE_MAP +
+                NAME_EXPECTED : VALUE_EXPECTED;
+            if( *_str == ':' )
+            {
+                flags |= CV_NODE_FLOW;
+                _str++;
+            }
+            cvStartWriteStruct( *fs, fs.elname.size() > 0 ? fs.elname.c_str() : 0,
+                flags, *_str ? _str : 0 );
+            fs.elname = String();
+        }
+        else
+        {
+            write( fs, fs.elname, (_str[0] == '\\' && (_str[1] == '{' || _str[1] == '}' ||
+                _str[1] == '[' || _str[1] == ']')) ? String(_str+1) : str );
+            if( fs.state == INSIDE_MAP + VALUE_EXPECTED )
+                fs.state = INSIDE_MAP + NAME_EXPECTED;
+        }
+    }
+    else
+        CV_Error( CV_StsError, "Invalid fs.state" );
+    return fs;
+}
+
+
+void FileStorage::writeRaw( const String& fmt, const Vector<uchar>& vec )
+{
+    if( !isOpened() )
+        return;
+    size_t elemSize, cn;
+    getElemSize( fmt, elemSize, cn );
+    CV_Assert( vec.size() % elemSize == 0 );
+    cvWriteRawData( fs, &vec[0], (int)(vec.size()/elemSize), fmt.c_str());
+}
+
+
+void FileStorage::writeObj( const String& name, const void* obj )
+{
+    if( !isOpened() )
+        return;
+    cvWrite( fs, name.size() > 0 ? name.c_str() : 0, obj );
+}
+
+
+void* FileNode::readObj() const
+{
+    if( !fs || !node )
+        return 0;
+    return cvRead( (CvFileStorage*)fs, (CvFileNode*)node );
+}
+
+
+FileNodeIterator::FileNodeIterator()
+{
+    fs = 0;
+    container = 0;
+    reader.ptr = 0;
+    remaining = 0;
+}
+
+FileNodeIterator::FileNodeIterator(const CvFileStorage* _fs,
+                                   const CvFileNode* _node, size_t _ofs)
+{
+    if( _fs && _node )
+    {
+        int node_type = _node->tag & FileNode::TYPE_MASK;
+        fs = _fs;
+        container = _node;
+        if( node_type == FileNode::SEQ || node_type == FileNode::MAP )
+        {
+            cvStartReadSeq( _node->data.seq, &reader );
+            remaining = FileNode(_fs, _node).count();
+        }
+        else
+        {
+            reader.ptr = (schar*)_node;
+            reader.seq = 0;
+            remaining = 1;
+        }
+        (*this) += (int)_ofs;
+    }
+    else
+    {
+        fs = 0;
+        container = 0;
+        reader.ptr = 0;
+        remaining = 0;
+    }
+}
+
+FileNodeIterator::FileNodeIterator(const FileNodeIterator& it)
+{
+    fs = it.fs;
+    container = it.container;
+    reader = it.reader;
+    remaining = it.remaining;
+}
+
+FileNodeIterator& FileNodeIterator::operator ++()
+{
+    if( remaining > 0 )
+    {
+        if( reader.seq )
+            CV_NEXT_SEQ_ELEM( reader.seq->elem_size, reader );
+        remaining--;
+    }
+    return *this;
+}
+
+FileNodeIterator FileNodeIterator::operator ++(int)
+{
+    FileNodeIterator it = *this;
+    ++(*this);
+    return it;
+}
+
+FileNodeIterator& FileNodeIterator::operator --()
+{
+    if( remaining < FileNode(fs, container).count() )
+    {
+        if( reader.seq )
+            CV_PREV_SEQ_ELEM( reader.seq->elem_size, reader );
+        remaining++;
+    }
+    return *this;
+}
+
+FileNodeIterator FileNodeIterator::operator --(int)
+{
+    FileNodeIterator it = *this;
+    --(*this);
+    return it;
+}
+
+FileNodeIterator& FileNodeIterator::operator += (int ofs)
+{
+    if( ofs == 0 )
+        return *this;
+    if( ofs > 0 )
+        ofs = std::min(ofs, (int)remaining);
+    else
+    {
+        size_t count = FileNode(fs, container).count();
+        ofs = (int)(remaining - std::min(remaining - ofs, count));
+    }
+    remaining -= ofs;
+    if( reader.seq )
+        cvSetSeqReaderPos( &reader, ofs, 1 );
+    return *this;
+}
+
+FileNodeIterator& FileNodeIterator::operator -= (int ofs)
+{
+    return operator += (-ofs);
+}
+
+
+FileNodeIterator& FileNodeIterator::readRaw( const String& fmt, Vector<uchar>& vec, size_t maxCount )
+{
+    if( fs && container && remaining > 0 )
+    {
+        size_t elem_size, cn;
+        getElemSize( fmt, elem_size, cn );
+        CV_Assert( elem_size > 0 );
+        size_t count = std::min(remaining, maxCount);
+        vec.resize( count*elem_size );
+        
+        if( reader.seq )
+        {
+            cvReadRawDataSlice( fs, &reader, (int)count, &vec[0], fmt.c_str() );
+            remaining -= count*cn;
+        }
+        else
+        {
+            cvReadRawData( fs, container, &vec[0], fmt.c_str() );
+            remaining = 0;
+        }
+    }
+    return *this;
+}
+
+}
+
+/* End of file. */