-/*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. */
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 */
-/*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_*/
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
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); }
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)
-/*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. */
-/*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. */
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, "" );
+}
}
--- /dev/null
+/*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;
+}
+
+}
-/*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 "" );\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 ' or >" );\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 (' and ")\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 "" );
+ ++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 ' or >" );
+ }
+ 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 (' and ")
+ // 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. */