/*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*/ #ifndef __OPENCV_LEGACY_HPP__ #define __OPENCV_LEGACY_HPP__ #include "opencv2/imgproc/imgproc_c.h" #include "opencv2/calib3d/calib3d_c.h" #include "opencv2/ml.hpp" #ifdef __cplusplus #include "opencv2/features2d.hpp" extern "C" { #endif CVAPI(CvSeq*) cvSegmentImage( const CvArr* srcarr, CvArr* dstarr, double canny_threshold, double ffill_threshold, CvMemStorage* storage ); /****************************************************************************************\ * Eigen objects * \****************************************************************************************/ typedef int (CV_CDECL * CvCallback)(int index, void* buffer, void* user_data); typedef union { CvCallback callback; void* data; } CvInput; #define CV_EIGOBJ_NO_CALLBACK 0 #define CV_EIGOBJ_INPUT_CALLBACK 1 #define CV_EIGOBJ_OUTPUT_CALLBACK 2 #define CV_EIGOBJ_BOTH_CALLBACK 3 /* Calculates covariation matrix of a set of arrays */ CVAPI(void) cvCalcCovarMatrixEx( int nObjects, void* input, int ioFlags, int ioBufSize, uchar* buffer, void* userData, IplImage* avg, float* covarMatrix ); /* Calculates eigen values and vectors of covariation matrix of a set of arrays */ CVAPI(void) cvCalcEigenObjects( int nObjects, void* input, void* output, int ioFlags, int ioBufSize, void* userData, CvTermCriteria* calcLimit, IplImage* avg, float* eigVals ); /* Calculates dot product (obj - avg) * eigObj (i.e. projects image to eigen vector) */ CVAPI(double) cvCalcDecompCoeff( IplImage* obj, IplImage* eigObj, IplImage* avg ); /* Projects image to eigen space (finds all decomposion coefficients */ CVAPI(void) cvEigenDecomposite( IplImage* obj, int nEigObjs, void* eigInput, int ioFlags, void* userData, IplImage* avg, float* coeffs ); /* Projects original objects used to calculate eigen space basis to that space */ CVAPI(void) cvEigenProjection( void* eigInput, int nEigObjs, int ioFlags, void* userData, float* coeffs, IplImage* avg, IplImage* proj ); /****************************************************************************************\ * 1D/2D HMM * \****************************************************************************************/ typedef struct CvImgObsInfo { int obs_x; int obs_y; int obs_size; float* obs;//consequtive observations int* state;/* arr of pairs superstate/state to which observation belong */ int* mix; /* number of mixture to which observation belong */ } CvImgObsInfo;/*struct for 1 image*/ typedef CvImgObsInfo Cv1DObsInfo; typedef struct CvEHMMState { int num_mix; /*number of mixtures in this state*/ float* mu; /*mean vectors corresponding to each mixture*/ float* inv_var; /* square root of inversed variances corresp. to each mixture*/ float* log_var_val; /* sum of 0.5 (LN2PI + ln(variance[i]) ) for i=1,n */ float* weight; /*array of mixture weights. Summ of all weights in state is 1. */ } CvEHMMState; typedef struct CvEHMM { int level; /* 0 - lowest(i.e its states are real states), ..... */ int num_states; /* number of HMM states */ float* transP;/*transition probab. matrices for states */ float** obsProb; /* if level == 0 - array of brob matrices corresponding to hmm if level == 1 - martix of matrices */ union { CvEHMMState* state; /* if level == 0 points to real states array, if not - points to embedded hmms */ struct CvEHMM* ehmm; /* pointer to an embedded model or NULL, if it is a leaf */ } u; } CvEHMM; /*CVAPI(int) icvCreate1DHMM( CvEHMM** this_hmm, int state_number, int* num_mix, int obs_size ); CVAPI(int) icvRelease1DHMM( CvEHMM** phmm ); CVAPI(int) icvUniform1DSegm( Cv1DObsInfo* obs_info, CvEHMM* hmm ); CVAPI(int) icvInit1DMixSegm( Cv1DObsInfo** obs_info_array, int num_img, CvEHMM* hmm); CVAPI(int) icvEstimate1DHMMStateParams( CvImgObsInfo** obs_info_array, int num_img, CvEHMM* hmm); CVAPI(int) icvEstimate1DObsProb( CvImgObsInfo* obs_info, CvEHMM* hmm ); CVAPI(int) icvEstimate1DTransProb( Cv1DObsInfo** obs_info_array, int num_seq, CvEHMM* hmm ); CVAPI(float) icvViterbi( Cv1DObsInfo* obs_info, CvEHMM* hmm); CVAPI(int) icv1DMixSegmL2( CvImgObsInfo** obs_info_array, int num_img, CvEHMM* hmm );*/ /*********************************** Embedded HMMs *************************************/ /* Creates 2D HMM */ CVAPI(CvEHMM*) cvCreate2DHMM( int* stateNumber, int* numMix, int obsSize ); /* Releases HMM */ CVAPI(void) cvRelease2DHMM( CvEHMM** hmm ); #define CV_COUNT_OBS(roi, win, delta, numObs ) \ { \ (numObs)->width =((roi)->width -(win)->width +(delta)->width)/(delta)->width; \ (numObs)->height =((roi)->height -(win)->height +(delta)->height)/(delta)->height;\ } /* Creates storage for observation vectors */ CVAPI(CvImgObsInfo*) cvCreateObsInfo( CvSize numObs, int obsSize ); /* Releases storage for observation vectors */ CVAPI(void) cvReleaseObsInfo( CvImgObsInfo** obs_info ); /* The function takes an image on input and and returns the sequnce of observations to be used with an embedded HMM; Each observation is top-left block of DCT coefficient matrix */ CVAPI(void) cvImgToObs_DCT( const CvArr* arr, float* obs, CvSize dctSize, CvSize obsSize, CvSize delta ); /* Uniformly segments all observation vectors extracted from image */ CVAPI(void) cvUniformImgSegm( CvImgObsInfo* obs_info, CvEHMM* ehmm ); /* Does mixture segmentation of the states of embedded HMM */ CVAPI(void) cvInitMixSegm( CvImgObsInfo** obs_info_array, int num_img, CvEHMM* hmm ); /* Function calculates means, variances, weights of every Gaussian mixture of every low-level state of embedded HMM */ CVAPI(void) cvEstimateHMMStateParams( CvImgObsInfo** obs_info_array, int num_img, CvEHMM* hmm ); /* Function computes transition probability matrices of embedded HMM given observations segmentation */ CVAPI(void) cvEstimateTransProb( CvImgObsInfo** obs_info_array, int num_img, CvEHMM* hmm ); /* Function computes probabilities of appearing observations at any state (i.e. computes P(obs|state) for every pair(obs,state)) */ CVAPI(void) cvEstimateObsProb( CvImgObsInfo* obs_info, CvEHMM* hmm ); /* Runs Viterbi algorithm for embedded HMM */ CVAPI(float) cvEViterbi( CvImgObsInfo* obs_info, CvEHMM* hmm ); /* Function clusters observation vectors from several images given observations segmentation. Euclidean distance used for clustering vectors. Centers of clusters are given means of every mixture */ CVAPI(void) cvMixSegmL2( CvImgObsInfo** obs_info_array, int num_img, CvEHMM* hmm ); /****************************************************************************************\ * A few functions from old stereo gesture recognition demosions * \****************************************************************************************/ /* Creates hand mask image given several points on the hand */ CVAPI(void) cvCreateHandMask( CvSeq* hand_points, IplImage *img_mask, CvRect *roi); /* Finds hand region in range image data */ CVAPI(void) cvFindHandRegion (CvPoint3D32f* points, int count, CvSeq* indexs, float* line, CvSize2D32f size, int flag, CvPoint3D32f* center, CvMemStorage* storage, CvSeq **numbers); /* Finds hand region in range image data (advanced version) */ CVAPI(void) cvFindHandRegionA( CvPoint3D32f* points, int count, CvSeq* indexs, float* line, CvSize2D32f size, int jc, CvPoint3D32f* center, CvMemStorage* storage, CvSeq **numbers); /* Calculates the cooficients of the homography matrix */ CVAPI(void) cvCalcImageHomography( float* line, CvPoint3D32f* center, float* intrinsic, float* homography ); /****************************************************************************************\ * More operations on sequences * \****************************************************************************************/ /*****************************************************************************************/ #define CV_CURRENT_INT( reader ) (*((int *)(reader).ptr)) #define CV_PREV_INT( reader ) (*((int *)(reader).prev_elem)) #define CV_GRAPH_WEIGHTED_VERTEX_FIELDS() CV_GRAPH_VERTEX_FIELDS()\ float weight; #define CV_GRAPH_WEIGHTED_EDGE_FIELDS() CV_GRAPH_EDGE_FIELDS() typedef struct CvGraphWeightedVtx { CV_GRAPH_WEIGHTED_VERTEX_FIELDS() } CvGraphWeightedVtx; typedef struct CvGraphWeightedEdge { CV_GRAPH_WEIGHTED_EDGE_FIELDS() } CvGraphWeightedEdge; typedef enum CvGraphWeightType { CV_NOT_WEIGHTED, CV_WEIGHTED_VTX, CV_WEIGHTED_EDGE, CV_WEIGHTED_ALL } CvGraphWeightType; /* Calculates histogram of a contour */ CVAPI(void) cvCalcPGH( const CvSeq* contour, CvHistogram* hist ); #define CV_DOMINANT_IPAN 1 /* Finds high-curvature points of the contour */ CVAPI(CvSeq*) cvFindDominantPoints( CvSeq* contour, CvMemStorage* storage, int method CV_DEFAULT(CV_DOMINANT_IPAN), double parameter1 CV_DEFAULT(0), double parameter2 CV_DEFAULT(0), double parameter3 CV_DEFAULT(0), double parameter4 CV_DEFAULT(0)); /*****************************************************************************************/ /*******************************Stereo correspondence*************************************/ typedef struct CvCliqueFinder { CvGraph* graph; int** adj_matr; int N; //graph size // stacks, counters etc/ int k; //stack size int* current_comp; int** All; int* ne; int* ce; int* fixp; //node with minimal disconnections int* nod; int* s; //for selected candidate int status; int best_score; int weighted; int weighted_edges; float best_weight; float* edge_weights; float* vertex_weights; float* cur_weight; float* cand_weight; } CvCliqueFinder; #define CLIQUE_TIME_OFF 2 #define CLIQUE_FOUND 1 #define CLIQUE_END 0 /*CVAPI(void) cvStartFindCliques( CvGraph* graph, CvCliqueFinder* finder, int reverse, int weighted CV_DEFAULT(0), int weighted_edges CV_DEFAULT(0)); CVAPI(int) cvFindNextMaximalClique( CvCliqueFinder* finder, int* clock_rest CV_DEFAULT(0) ); CVAPI(void) cvEndFindCliques( CvCliqueFinder* finder ); CVAPI(void) cvBronKerbosch( CvGraph* graph );*/ /*F/////////////////////////////////////////////////////////////////////////////////////// // // Name: cvSubgraphWeight // Purpose: finds weight of subgraph in a graph // Context: // Parameters: // graph - input graph. // subgraph - sequence of pairwise different ints. These are indices of vertices of subgraph. // weight_type - describes the way we measure weight. // one of the following: // CV_NOT_WEIGHTED - weight of a clique is simply its size // CV_WEIGHTED_VTX - weight of a clique is the sum of weights of its vertices // CV_WEIGHTED_EDGE - the same but edges // CV_WEIGHTED_ALL - the same but both edges and vertices // weight_vtx - optional vector of floats, with size = graph->total. // If weight_type is either CV_WEIGHTED_VTX or CV_WEIGHTED_ALL // weights of vertices must be provided. If weight_vtx not zero // these weights considered to be here, otherwise function assumes // that vertices of graph are inherited from CvGraphWeightedVtx. // weight_edge - optional matrix of floats, of width and height = graph->total. // If weight_type is either CV_WEIGHTED_EDGE or CV_WEIGHTED_ALL // weights of edges ought to be supplied. If weight_edge is not zero // function finds them here, otherwise function expects // edges of graph to be inherited from CvGraphWeightedEdge. // If this parameter is not zero structure of the graph is determined from matrix // rather than from CvGraphEdge's. In particular, elements corresponding to // absent edges should be zero. // Returns: // weight of subgraph. // Notes: //F*/ /*CVAPI(float) cvSubgraphWeight( CvGraph *graph, CvSeq *subgraph, CvGraphWeightType weight_type CV_DEFAULT(CV_NOT_WEIGHTED), CvVect32f weight_vtx CV_DEFAULT(0), CvMatr32f weight_edge CV_DEFAULT(0) );*/ /*F/////////////////////////////////////////////////////////////////////////////////////// // // Name: cvFindCliqueEx // Purpose: tries to find clique with maximum possible weight in a graph // Context: // Parameters: // graph - input graph. // storage - memory storage to be used by the result. // is_complementary - optional flag showing whether function should seek for clique // in complementary graph. // weight_type - describes our notion about weight. // one of the following: // CV_NOT_WEIGHTED - weight of a clique is simply its size // CV_WEIGHTED_VTX - weight of a clique is the sum of weights of its vertices // CV_WEIGHTED_EDGE - the same but edges // CV_WEIGHTED_ALL - the same but both edges and vertices // weight_vtx - optional vector of floats, with size = graph->total. // If weight_type is either CV_WEIGHTED_VTX or CV_WEIGHTED_ALL // weights of vertices must be provided. If weight_vtx not zero // these weights considered to be here, otherwise function assumes // that vertices of graph are inherited from CvGraphWeightedVtx. // weight_edge - optional matrix of floats, of width and height = graph->total. // If weight_type is either CV_WEIGHTED_EDGE or CV_WEIGHTED_ALL // weights of edges ought to be supplied. If weight_edge is not zero // function finds them here, otherwise function expects // edges of graph to be inherited from CvGraphWeightedEdge. // Note that in case of CV_WEIGHTED_EDGE or CV_WEIGHTED_ALL // nonzero is_complementary implies nonzero weight_edge. // start_clique - optional sequence of pairwise different ints. They are indices of // vertices that shall be present in the output clique. // subgraph_of_ban - optional sequence of (maybe equal) ints. They are indices of // vertices that shall not be present in the output clique. // clique_weight_ptr - optional output parameter. Weight of found clique stored here. // num_generations - optional number of generations in evolutionary part of algorithm, // zero forces to return first found clique. // quality - optional parameter determining degree of required quality/speed tradeoff. // Must be in the range from 0 to 9. // 0 is fast and dirty, 9 is slow but hopefully yields good clique. // Returns: // sequence of pairwise different ints. // These are indices of vertices that form found clique. // Notes: // in cases of CV_WEIGHTED_EDGE and CV_WEIGHTED_ALL weights should be nonnegative. // start_clique has a priority over subgraph_of_ban. //F*/ /*CVAPI(CvSeq*) cvFindCliqueEx( CvGraph *graph, CvMemStorage *storage, int is_complementary CV_DEFAULT(0), CvGraphWeightType weight_type CV_DEFAULT(CV_NOT_WEIGHTED), CvVect32f weight_vtx CV_DEFAULT(0), CvMatr32f weight_edge CV_DEFAULT(0), CvSeq *start_clique CV_DEFAULT(0), CvSeq *subgraph_of_ban CV_DEFAULT(0), float *clique_weight_ptr CV_DEFAULT(0), int num_generations CV_DEFAULT(3), int quality CV_DEFAULT(2) );*/ #define CV_UNDEF_SC_PARAM 12345 //default value of parameters #define CV_IDP_BIRCHFIELD_PARAM1 25 #define CV_IDP_BIRCHFIELD_PARAM2 5 #define CV_IDP_BIRCHFIELD_PARAM3 12 #define CV_IDP_BIRCHFIELD_PARAM4 15 #define CV_IDP_BIRCHFIELD_PARAM5 25 #define CV_DISPARITY_BIRCHFIELD 0 /*F/////////////////////////////////////////////////////////////////////////// // // Name: cvFindStereoCorrespondence // Purpose: find stereo correspondence on stereo-pair // Context: // Parameters: // leftImage - left image of stereo-pair (format 8uC1). // rightImage - right image of stereo-pair (format 8uC1). // mode - mode of correspondence retrieval (now CV_DISPARITY_BIRCHFIELD only) // dispImage - destination disparity image // maxDisparity - maximal disparity // param1, param2, param3, param4, param5 - parameters of algorithm // Returns: // Notes: // Images must be rectified. // All images must have format 8uC1. //F*/ CVAPI(void) cvFindStereoCorrespondence( const CvArr* leftImage, const CvArr* rightImage, int mode, CvArr* dispImage, int maxDisparity, double param1 CV_DEFAULT(CV_UNDEF_SC_PARAM), double param2 CV_DEFAULT(CV_UNDEF_SC_PARAM), double param3 CV_DEFAULT(CV_UNDEF_SC_PARAM), double param4 CV_DEFAULT(CV_UNDEF_SC_PARAM), double param5 CV_DEFAULT(CV_UNDEF_SC_PARAM) ); /*****************************************************************************************/ /************ Epiline functions *******************/ typedef struct CvStereoLineCoeff { double Xcoef; double XcoefA; double XcoefB; double XcoefAB; double Ycoef; double YcoefA; double YcoefB; double YcoefAB; double Zcoef; double ZcoefA; double ZcoefB; double ZcoefAB; }CvStereoLineCoeff; typedef struct CvCamera { float imgSize[2]; /* size of the camera view, used during calibration */ float matrix[9]; /* intinsic camera parameters: [ fx 0 cx; 0 fy cy; 0 0 1 ] */ float distortion[4]; /* distortion coefficients - two coefficients for radial distortion and another two for tangential: [ k1 k2 p1 p2 ] */ float rotMatr[9]; float transVect[3]; /* rotation matrix and transition vector relatively to some reference point in the space. */ } CvCamera; typedef struct CvStereoCamera { CvCamera* camera[2]; /* two individual camera parameters */ float fundMatr[9]; /* fundamental matrix */ /* New part for stereo */ CvPoint3D32f epipole[2]; CvPoint2D32f quad[2][4]; /* coordinates of destination quadrangle after epipolar geometry rectification */ double coeffs[2][3][3];/* coefficients for transformation */ CvPoint2D32f border[2][4]; CvSize warpSize; CvStereoLineCoeff* lineCoeffs; int needSwapCameras;/* flag set to 1 if need to swap cameras for good reconstruction */ float rotMatrix[9]; float transVector[3]; } CvStereoCamera; typedef struct CvContourOrientation { float egvals[2]; float egvects[4]; float max, min; // minimum and maximum projections int imax, imin; } CvContourOrientation; #define CV_CAMERA_TO_WARP 1 #define CV_WARP_TO_CAMERA 2 CVAPI(int) icvConvertWarpCoordinates(double coeffs[3][3], CvPoint2D32f* cameraPoint, CvPoint2D32f* warpPoint, int direction); CVAPI(int) icvGetSymPoint3D( CvPoint3D64f pointCorner, CvPoint3D64f point1, CvPoint3D64f point2, CvPoint3D64f *pointSym2); CVAPI(void) icvGetPieceLength3D(CvPoint3D64f point1,CvPoint3D64f point2,double* dist); CVAPI(int) icvCompute3DPoint( double alpha,double betta, CvStereoLineCoeff* coeffs, CvPoint3D64f* point); CVAPI(int) icvCreateConvertMatrVect( double* rotMatr1, double* transVect1, double* rotMatr2, double* transVect2, double* convRotMatr, double* convTransVect); CVAPI(int) icvConvertPointSystem(CvPoint3D64f M2, CvPoint3D64f* M1, double* rotMatr, double* transVect ); CVAPI(int) icvComputeCoeffForStereo( CvStereoCamera* stereoCamera); CVAPI(int) icvGetCrossPieceVector(CvPoint2D32f p1_start,CvPoint2D32f p1_end,CvPoint2D32f v2_start,CvPoint2D32f v2_end,CvPoint2D32f *cross); CVAPI(int) icvGetCrossLineDirect(CvPoint2D32f p1,CvPoint2D32f p2,float a,float b,float c,CvPoint2D32f* cross); CVAPI(float) icvDefinePointPosition(CvPoint2D32f point1,CvPoint2D32f point2,CvPoint2D32f point); CVAPI(int) icvStereoCalibration( int numImages, int* nums, CvSize imageSize, CvPoint2D32f* imagePoints1, CvPoint2D32f* imagePoints2, CvPoint3D32f* objectPoints, CvStereoCamera* stereoparams ); CVAPI(int) icvComputeRestStereoParams(CvStereoCamera *stereoparams); CVAPI(void) cvComputePerspectiveMap( const double coeffs[3][3], CvArr* rectMapX, CvArr* rectMapY ); CVAPI(int) icvComCoeffForLine( CvPoint2D64f point1, CvPoint2D64f point2, CvPoint2D64f point3, CvPoint2D64f point4, double* camMatr1, double* rotMatr1, double* transVect1, double* camMatr2, double* rotMatr2, double* transVect2, CvStereoLineCoeff* coeffs, int* needSwapCameras); CVAPI(int) icvGetDirectionForPoint( CvPoint2D64f point, double* camMatr, CvPoint3D64f* direct); CVAPI(int) icvGetCrossLines(CvPoint3D64f point11,CvPoint3D64f point12, CvPoint3D64f point21,CvPoint3D64f point22, CvPoint3D64f* midPoint); CVAPI(int) icvComputeStereoLineCoeffs( CvPoint3D64f pointA, CvPoint3D64f pointB, CvPoint3D64f pointCam1, double gamma, CvStereoLineCoeff* coeffs); /*CVAPI(int) icvComputeFundMatrEpipoles ( double* camMatr1, double* rotMatr1, double* transVect1, double* camMatr2, double* rotMatr2, double* transVect2, CvPoint2D64f* epipole1, CvPoint2D64f* epipole2, double* fundMatr);*/ CVAPI(int) icvGetAngleLine( CvPoint2D64f startPoint, CvSize imageSize,CvPoint2D64f *point1,CvPoint2D64f *point2); CVAPI(void) icvGetCoefForPiece( CvPoint2D64f p_start,CvPoint2D64f p_end, double *a,double *b,double *c, int* result); /*CVAPI(void) icvGetCommonArea( CvSize imageSize, CvPoint2D64f epipole1,CvPoint2D64f epipole2, double* fundMatr, double* coeff11,double* coeff12, double* coeff21,double* coeff22, int* result);*/ CVAPI(void) icvComputeeInfiniteProject1(double* rotMatr, double* camMatr1, double* camMatr2, CvPoint2D32f point1, CvPoint2D32f *point2); CVAPI(void) icvComputeeInfiniteProject2(double* rotMatr, double* camMatr1, double* camMatr2, CvPoint2D32f* point1, CvPoint2D32f point2); CVAPI(void) icvGetCrossDirectDirect( double* direct1,double* direct2, CvPoint2D64f *cross,int* result); CVAPI(void) icvGetCrossPieceDirect( CvPoint2D64f p_start,CvPoint2D64f p_end, double a,double b,double c, CvPoint2D64f *cross,int* result); CVAPI(void) icvGetCrossPiecePiece( CvPoint2D64f p1_start,CvPoint2D64f p1_end, CvPoint2D64f p2_start,CvPoint2D64f p2_end, CvPoint2D64f* cross, int* result); CVAPI(void) icvGetPieceLength(CvPoint2D64f point1,CvPoint2D64f point2,double* dist); CVAPI(void) icvGetCrossRectDirect( CvSize imageSize, double a,double b,double c, CvPoint2D64f *start,CvPoint2D64f *end, int* result); CVAPI(void) icvProjectPointToImage( CvPoint3D64f point, double* camMatr,double* rotMatr,double* transVect, CvPoint2D64f* projPoint); CVAPI(void) icvGetQuadsTransform( CvSize imageSize, double* camMatr1, double* rotMatr1, double* transVect1, double* camMatr2, double* rotMatr2, double* transVect2, CvSize* warpSize, double quad1[4][2], double quad2[4][2], double* fundMatr, CvPoint3D64f* epipole1, CvPoint3D64f* epipole2 ); CVAPI(void) icvGetQuadsTransformStruct( CvStereoCamera* stereoCamera); CVAPI(void) icvComputeStereoParamsForCameras(CvStereoCamera* stereoCamera); CVAPI(void) icvGetCutPiece( double* areaLineCoef1,double* areaLineCoef2, CvPoint2D64f epipole, CvSize imageSize, CvPoint2D64f* point11,CvPoint2D64f* point12, CvPoint2D64f* point21,CvPoint2D64f* point22, int* result); CVAPI(void) icvGetMiddleAnglePoint( CvPoint2D64f basePoint, CvPoint2D64f point1,CvPoint2D64f point2, CvPoint2D64f* midPoint); CVAPI(void) icvGetNormalDirect(double* direct,CvPoint2D64f point,double* normDirect); CVAPI(double) icvGetVect(CvPoint2D64f basePoint,CvPoint2D64f point1,CvPoint2D64f point2); CVAPI(void) icvProjectPointToDirect( CvPoint2D64f point,double* lineCoeff, CvPoint2D64f* projectPoint); CVAPI(void) icvGetDistanceFromPointToDirect( CvPoint2D64f point,double* lineCoef,double*dist); CVAPI(IplImage*) icvCreateIsometricImage( IplImage* src, IplImage* dst, int desired_depth, int desired_num_channels ); CVAPI(void) cvDeInterlace( const CvArr* frame, CvArr* fieldEven, CvArr* fieldOdd ); /*CVAPI(int) icvSelectBestRt( int numImages, int* numPoints, CvSize imageSize, CvPoint2D32f* imagePoints1, CvPoint2D32f* imagePoints2, CvPoint3D32f* objectPoints, CvMatr32f cameraMatrix1, CvVect32f distortion1, CvMatr32f rotMatrs1, CvVect32f transVects1, CvMatr32f cameraMatrix2, CvVect32f distortion2, CvMatr32f rotMatrs2, CvVect32f transVects2, CvMatr32f bestRotMatr, CvVect32f bestTransVect );*/ /****************************************************************************************\ * Contour Tree * \****************************************************************************************/ /* Contour tree header */ typedef struct CvContourTree { CV_SEQUENCE_FIELDS() CvPoint p1; /* the first point of the binary tree root segment */ CvPoint p2; /* the last point of the binary tree root segment */ } CvContourTree; /* Builds hierarhical representation of a contour */ CVAPI(CvContourTree*) cvCreateContourTree( const CvSeq* contour, CvMemStorage* storage, double threshold ); /* Reconstruct (completelly or partially) contour a from contour tree */ CVAPI(CvSeq*) cvContourFromContourTree( const CvContourTree* tree, CvMemStorage* storage, CvTermCriteria criteria ); /* Compares two contour trees */ enum { CV_CONTOUR_TREES_MATCH_I1 = 1 }; CVAPI(double) cvMatchContourTrees( const CvContourTree* tree1, const CvContourTree* tree2, int method, double threshold ); /****************************************************************************************\ * Contour Morphing * \****************************************************************************************/ /* finds correspondence between two contours */ CvSeq* cvCalcContoursCorrespondence( const CvSeq* contour1, const CvSeq* contour2, CvMemStorage* storage); /* morphs contours using the pre-calculated correspondence: alpha=0 ~ contour1, alpha=1 ~ contour2 */ CvSeq* cvMorphContours( const CvSeq* contour1, const CvSeq* contour2, CvSeq* corr, double alpha, CvMemStorage* storage ); /****************************************************************************************\ * Active Contours * \****************************************************************************************/ #define CV_VALUE 1 #define CV_ARRAY 2 /* Updates active contour in order to minimize its cummulative (internal and external) energy. */ CVAPI(void) cvSnakeImage( const IplImage* image, CvPoint* points, int length, float* alpha, float* beta, float* gamma, int coeff_usage, CvSize win, CvTermCriteria criteria, int calc_gradient CV_DEFAULT(1)); /****************************************************************************************\ * Texture Descriptors * \****************************************************************************************/ #define CV_GLCM_OPTIMIZATION_NONE -2 #define CV_GLCM_OPTIMIZATION_LUT -1 #define CV_GLCM_OPTIMIZATION_HISTOGRAM 0 #define CV_GLCMDESC_OPTIMIZATION_ALLOWDOUBLENEST 10 #define CV_GLCMDESC_OPTIMIZATION_ALLOWTRIPLENEST 11 #define CV_GLCMDESC_OPTIMIZATION_HISTOGRAM 4 #define CV_GLCMDESC_ENTROPY 0 #define CV_GLCMDESC_ENERGY 1 #define CV_GLCMDESC_HOMOGENITY 2 #define CV_GLCMDESC_CONTRAST 3 #define CV_GLCMDESC_CLUSTERTENDENCY 4 #define CV_GLCMDESC_CLUSTERSHADE 5 #define CV_GLCMDESC_CORRELATION 6 #define CV_GLCMDESC_CORRELATIONINFO1 7 #define CV_GLCMDESC_CORRELATIONINFO2 8 #define CV_GLCMDESC_MAXIMUMPROBABILITY 9 #define CV_GLCM_ALL 0 #define CV_GLCM_GLCM 1 #define CV_GLCM_DESC 2 typedef struct CvGLCM CvGLCM; CVAPI(CvGLCM*) cvCreateGLCM( const IplImage* srcImage, int stepMagnitude, const int* stepDirections CV_DEFAULT(0), int numStepDirections CV_DEFAULT(0), int optimizationType CV_DEFAULT(CV_GLCM_OPTIMIZATION_NONE)); CVAPI(void) cvReleaseGLCM( CvGLCM** GLCM, int flag CV_DEFAULT(CV_GLCM_ALL)); CVAPI(void) cvCreateGLCMDescriptors( CvGLCM* destGLCM, int descriptorOptimizationType CV_DEFAULT(CV_GLCMDESC_OPTIMIZATION_ALLOWDOUBLENEST)); CVAPI(double) cvGetGLCMDescriptor( CvGLCM* GLCM, int step, int descriptor ); CVAPI(void) cvGetGLCMDescriptorStatistics( CvGLCM* GLCM, int descriptor, double* average, double* standardDeviation ); CVAPI(IplImage*) cvCreateGLCMImage( CvGLCM* GLCM, int step ); /****************************************************************************************\ * Face eyes&mouth tracking * \****************************************************************************************/ typedef struct CvFaceTracker CvFaceTracker; #define CV_NUM_FACE_ELEMENTS 3 enum CV_FACE_ELEMENTS { CV_FACE_MOUTH = 0, CV_FACE_LEFT_EYE = 1, CV_FACE_RIGHT_EYE = 2 }; CVAPI(CvFaceTracker*) cvInitFaceTracker(CvFaceTracker* pFaceTracking, const IplImage* imgGray, CvRect* pRects, int nRects); CVAPI(int) cvTrackFace( CvFaceTracker* pFaceTracker, IplImage* imgGray, CvRect* pRects, int nRects, CvPoint* ptRotate, double* dbAngleRotate); CVAPI(void) cvReleaseFaceTracker(CvFaceTracker** ppFaceTracker); typedef struct CvFace { CvRect MouthRect; CvRect LeftEyeRect; CvRect RightEyeRect; } CvFaceData; CvSeq * cvFindFace(IplImage * Image,CvMemStorage* storage); CvSeq * cvPostBoostingFindFace(IplImage * Image,CvMemStorage* storage); /****************************************************************************************\ * 3D Tracker * \****************************************************************************************/ typedef unsigned char CvBool; typedef struct Cv3dTracker2dTrackedObject { int id; CvPoint2D32f p; // pgruebele: So we do not loose precision, this needs to be float } Cv3dTracker2dTrackedObject; CV_INLINE Cv3dTracker2dTrackedObject cv3dTracker2dTrackedObject(int id, CvPoint2D32f p) { Cv3dTracker2dTrackedObject r; r.id = id; r.p = p; return r; } typedef struct Cv3dTrackerTrackedObject { int id; CvPoint3D32f p; // location of the tracked object } Cv3dTrackerTrackedObject; CV_INLINE Cv3dTrackerTrackedObject cv3dTrackerTrackedObject(int id, CvPoint3D32f p) { Cv3dTrackerTrackedObject r; r.id = id; r.p = p; return r; } typedef struct Cv3dTrackerCameraInfo { CvBool valid; float mat[4][4]; /* maps camera coordinates to world coordinates */ CvPoint2D32f principal_point; /* copied from intrinsics so this structure */ /* has all the info we need */ } Cv3dTrackerCameraInfo; typedef struct Cv3dTrackerCameraIntrinsics { CvPoint2D32f principal_point; float focal_length[2]; float distortion[4]; } Cv3dTrackerCameraIntrinsics; CVAPI(CvBool) cv3dTrackerCalibrateCameras(int num_cameras, const Cv3dTrackerCameraIntrinsics camera_intrinsics[], /* size is num_cameras */ CvSize etalon_size, float square_size, IplImage *samples[], /* size is num_cameras */ Cv3dTrackerCameraInfo camera_info[]); /* size is num_cameras */ CVAPI(int) cv3dTrackerLocateObjects(int num_cameras, int num_objects, const Cv3dTrackerCameraInfo camera_info[], /* size is num_cameras */ const Cv3dTracker2dTrackedObject tracking_info[], /* size is num_objects*num_cameras */ Cv3dTrackerTrackedObject tracked_objects[]); /* size is num_objects */ /**************************************************************************************** tracking_info is a rectangular array; one row per camera, num_objects elements per row. The id field of any unused slots must be -1. Ids need not be ordered or consecutive. On completion, the return value is the number of objects located; i.e., the number of objects visible by more than one camera. The id field of any unused slots in tracked objects is set to -1. ****************************************************************************************/ /****************************************************************************************\ * Skeletons and Linear-Contour Models * \****************************************************************************************/ typedef enum CvLeeParameters { CV_LEE_INT = 0, CV_LEE_FLOAT = 1, CV_LEE_DOUBLE = 2, CV_LEE_AUTO = -1, CV_LEE_ERODE = 0, CV_LEE_ZOOM = 1, CV_LEE_NON = 2 } CvLeeParameters; #define CV_NEXT_VORONOISITE2D( SITE ) ((SITE)->edge[0]->site[((SITE)->edge[0]->site[0] == (SITE))]) #define CV_PREV_VORONOISITE2D( SITE ) ((SITE)->edge[1]->site[((SITE)->edge[1]->site[0] == (SITE))]) #define CV_FIRST_VORONOIEDGE2D( SITE ) ((SITE)->edge[0]) #define CV_LAST_VORONOIEDGE2D( SITE ) ((SITE)->edge[1]) #define CV_NEXT_VORONOIEDGE2D( EDGE, SITE ) ((EDGE)->next[(EDGE)->site[0] != (SITE)]) #define CV_PREV_VORONOIEDGE2D( EDGE, SITE ) ((EDGE)->next[2 + ((EDGE)->site[0] != (SITE))]) #define CV_VORONOIEDGE2D_BEGINNODE( EDGE, SITE ) ((EDGE)->node[((EDGE)->site[0] != (SITE))]) #define CV_VORONOIEDGE2D_ENDNODE( EDGE, SITE ) ((EDGE)->node[((EDGE)->site[0] == (SITE))]) #define CV_TWIN_VORONOISITE2D( SITE, EDGE ) ( (EDGE)->site[((EDGE)->site[0] == (SITE))]) #define CV_VORONOISITE2D_FIELDS() \ struct CvVoronoiNode2D *node[2]; \ struct CvVoronoiEdge2D *edge[2]; typedef struct CvVoronoiSite2D { CV_VORONOISITE2D_FIELDS() struct CvVoronoiSite2D *next[2]; } CvVoronoiSite2D; #define CV_VORONOIEDGE2D_FIELDS() \ struct CvVoronoiNode2D *node[2]; \ struct CvVoronoiSite2D *site[2]; \ struct CvVoronoiEdge2D *next[4]; typedef struct CvVoronoiEdge2D { CV_VORONOIEDGE2D_FIELDS() } CvVoronoiEdge2D; #define CV_VORONOINODE2D_FIELDS() \ CV_SET_ELEM_FIELDS(CvVoronoiNode2D) \ CvPoint2D32f pt; \ float radius; typedef struct CvVoronoiNode2D { CV_VORONOINODE2D_FIELDS() } CvVoronoiNode2D; #define CV_VORONOIDIAGRAM2D_FIELDS() \ CV_GRAPH_FIELDS() \ CvSet *sites; typedef struct CvVoronoiDiagram2D { CV_VORONOIDIAGRAM2D_FIELDS() } CvVoronoiDiagram2D; /* Computes Voronoi Diagram for given polygons with holes */ CVAPI(int) cvVoronoiDiagramFromContour(CvSeq* ContourSeq, CvVoronoiDiagram2D** VoronoiDiagram, CvMemStorage* VoronoiStorage, CvLeeParameters contour_type CV_DEFAULT(CV_LEE_INT), int contour_orientation CV_DEFAULT(-1), int attempt_number CV_DEFAULT(10)); /* Computes Voronoi Diagram for domains in given image */ CVAPI(int) cvVoronoiDiagramFromImage(IplImage* pImage, CvSeq** ContourSeq, CvVoronoiDiagram2D** VoronoiDiagram, CvMemStorage* VoronoiStorage, CvLeeParameters regularization_method CV_DEFAULT(CV_LEE_NON), float approx_precision CV_DEFAULT(CV_LEE_AUTO)); /* Deallocates the storage */ CVAPI(void) cvReleaseVoronoiStorage(CvVoronoiDiagram2D* VoronoiDiagram, CvMemStorage** pVoronoiStorage); /*********************** Linear-Contour Model ****************************/ struct CvLCMEdge; struct CvLCMNode; typedef struct CvLCMEdge { CV_GRAPH_EDGE_FIELDS() CvSeq* chain; float width; int index1; int index2; } CvLCMEdge; typedef struct CvLCMNode { CV_GRAPH_VERTEX_FIELDS() CvContour* contour; } CvLCMNode; /* Computes hybrid model from Voronoi Diagram */ CVAPI(CvGraph*) cvLinearContorModelFromVoronoiDiagram(CvVoronoiDiagram2D* VoronoiDiagram, float maxWidth); /* Releases hybrid model storage */ CVAPI(int) cvReleaseLinearContorModelStorage(CvGraph** Graph); /* two stereo-related functions */ CVAPI(void) cvInitPerspectiveTransform( CvSize size, const CvPoint2D32f vertex[4], double matrix[3][3], CvArr* rectMap ); /*CVAPI(void) cvInitStereoRectification( CvStereoCamera* params, CvArr* rectMap1, CvArr* rectMap2, int do_undistortion );*/ /*************************** View Morphing Functions ************************/ typedef struct CvMatrix3 { float m[3][3]; } CvMatrix3; /* The order of the function corresponds to the order they should appear in the view morphing pipeline */ /* Finds ending points of scanlines on left and right images of stereo-pair */ CVAPI(void) cvMakeScanlines( const CvMatrix3* matrix, CvSize img_size, int* scanlines1, int* scanlines2, int* lengths1, int* lengths2, int* line_count ); /* Grab pixel values from scanlines and stores them sequentially (some sort of perspective image transform) */ CVAPI(void) cvPreWarpImage( int line_count, IplImage* img, uchar* dst, int* dst_nums, int* scanlines); /* Approximate each grabbed scanline by a sequence of runs (lossy run-length compression) */ CVAPI(void) cvFindRuns( int line_count, uchar* prewarp1, uchar* prewarp2, int* line_lengths1, int* line_lengths2, int* runs1, int* runs2, int* num_runs1, int* num_runs2); /* Compares two sets of compressed scanlines */ CVAPI(void) cvDynamicCorrespondMulti( int line_count, int* first, int* first_runs, int* second, int* second_runs, int* first_corr, int* second_corr); /* Finds scanline ending coordinates for some intermediate "virtual" camera position */ CVAPI(void) cvMakeAlphaScanlines( int* scanlines1, int* scanlines2, int* scanlinesA, int* lengths, int line_count, float alpha); /* Blends data of the left and right image scanlines to get pixel values of "virtual" image scanlines */ CVAPI(void) cvMorphEpilinesMulti( int line_count, uchar* first_pix, int* first_num, uchar* second_pix, int* second_num, uchar* dst_pix, int* dst_num, float alpha, int* first, int* first_runs, int* second, int* second_runs, int* first_corr, int* second_corr); /* Does reverse warping of the morphing result to make it fill the destination image rectangle */ CVAPI(void) cvPostWarpImage( int line_count, uchar* src, int* src_nums, IplImage* img, int* scanlines); /* Deletes Moire (missed pixels that appear due to discretization) */ CVAPI(void) cvDeleteMoire( IplImage* img ); typedef struct CvConDensation { int MP; int DP; float* DynamMatr; /* Matrix of the linear Dynamics system */ float* State; /* Vector of State */ int SamplesNum; /* Number of the Samples */ float** flSamples; /* arr of the Sample Vectors */ float** flNewSamples; /* temporary array of the Sample Vectors */ float* flConfidence; /* Confidence for each Sample */ float* flCumulative; /* Cumulative confidence */ float* Temp; /* Temporary vector */ float* RandomSample; /* RandomVector to update sample set */ struct CvRandState* RandS; /* Array of structures to generate random vectors */ } CvConDensation; /* Creates ConDensation filter state */ CVAPI(CvConDensation*) cvCreateConDensation( int dynam_params, int measure_params, int sample_count ); /* Releases ConDensation filter state */ CVAPI(void) cvReleaseConDensation( CvConDensation** condens ); /* Updates ConDensation filter by time (predict future state of the system) */ CVAPI(void) cvConDensUpdateByTime( CvConDensation* condens); /* Initializes ConDensation filter samples */ CVAPI(void) cvConDensInitSampleSet( CvConDensation* condens, CvMat* lower_bound, CvMat* upper_bound ); CV_INLINE int iplWidth( const IplImage* img ) { return !img ? 0 : !img->roi ? img->width : img->roi->width; } CV_INLINE int iplHeight( const IplImage* img ) { return !img ? 0 : !img->roi ? img->height : img->roi->height; } #ifdef __cplusplus } #endif #ifdef __cplusplus /****************************************************************************************\ * Calibration engine * \****************************************************************************************/ typedef enum CvCalibEtalonType { CV_CALIB_ETALON_USER = -1, CV_CALIB_ETALON_CHESSBOARD = 0, CV_CALIB_ETALON_CHECKERBOARD = CV_CALIB_ETALON_CHESSBOARD } CvCalibEtalonType; class CV_EXPORTS CvCalibFilter { public: /* Constructor & destructor */ CvCalibFilter(); virtual ~CvCalibFilter(); /* Sets etalon type - one for all cameras. etalonParams is used in case of pre-defined etalons (such as chessboard). Number of elements in etalonParams is determined by etalonType. E.g., if etalon type is CV_ETALON_TYPE_CHESSBOARD then: etalonParams[0] is number of squares per one side of etalon etalonParams[1] is number of squares per another side of etalon etalonParams[2] is linear size of squares in the board in arbitrary units. pointCount & points are used in case of CV_CALIB_ETALON_USER (user-defined) etalon. */ virtual bool SetEtalon( CvCalibEtalonType etalonType, double* etalonParams, int pointCount = 0, CvPoint2D32f* points = 0 ); /* Retrieves etalon parameters/or and points */ virtual CvCalibEtalonType GetEtalon( int* paramCount = 0, const double** etalonParams = 0, int* pointCount = 0, const CvPoint2D32f** etalonPoints = 0 ) const; /* Sets number of cameras calibrated simultaneously. It is equal to 1 initially */ virtual void SetCameraCount( int cameraCount ); /* Retrieves number of cameras */ int GetCameraCount() const { return cameraCount; } /* Starts cameras calibration */ virtual bool SetFrames( int totalFrames ); /* Stops cameras calibration */ virtual void Stop( bool calibrate = false ); /* Retrieves number of cameras */ bool IsCalibrated() const { return isCalibrated; } /* Feeds another serie of snapshots (one per each camera) to filter. Etalon points on these images are found automatically. If the function can't locate points, it returns false */ virtual bool FindEtalon( IplImage** imgs ); /* The same but takes matrices */ virtual bool FindEtalon( CvMat** imgs ); /* Lower-level function for feeding filter with already found etalon points. Array of point arrays for each camera is passed. */ virtual bool Push( const CvPoint2D32f** points = 0 ); /* Returns total number of accepted frames and, optionally, total number of frames to collect */ virtual int GetFrameCount( int* framesTotal = 0 ) const; /* Retrieves camera parameters for specified camera. If camera is not calibrated the function returns 0 */ virtual const CvCamera* GetCameraParams( int idx = 0 ) const; virtual const CvStereoCamera* GetStereoParams() const; /* Sets camera parameters for all cameras */ virtual bool SetCameraParams( CvCamera* params ); /* Saves all camera parameters to file */ virtual bool SaveCameraParams( const char* filename ); /* Loads all camera parameters from file */ virtual bool LoadCameraParams( const char* filename ); /* Undistorts images using camera parameters. Some of src pointers can be NULL. */ virtual bool Undistort( IplImage** src, IplImage** dst ); /* Undistorts images using camera parameters. Some of src pointers can be NULL. */ virtual bool Undistort( CvMat** src, CvMat** dst ); /* Returns array of etalon points detected/partally detected on the latest frame for idx-th camera */ virtual bool GetLatestPoints( int idx, CvPoint2D32f** pts, int* count, bool* found ); /* Draw the latest detected/partially detected etalon */ virtual void DrawPoints( IplImage** dst ); /* Draw the latest detected/partially detected etalon */ virtual void DrawPoints( CvMat** dst ); virtual bool Rectify( IplImage** srcarr, IplImage** dstarr ); virtual bool Rectify( CvMat** srcarr, CvMat** dstarr ); protected: enum { MAX_CAMERAS = 3 }; /* etalon data */ CvCalibEtalonType etalonType; int etalonParamCount; double* etalonParams; int etalonPointCount; CvPoint2D32f* etalonPoints; CvSize imgSize; CvMat* grayImg; CvMat* tempImg; CvMemStorage* storage; /* camera data */ int cameraCount; CvCamera cameraParams[MAX_CAMERAS]; CvStereoCamera stereo; CvPoint2D32f* points[MAX_CAMERAS]; CvMat* undistMap[MAX_CAMERAS][2]; CvMat* undistImg; int latestCounts[MAX_CAMERAS]; CvPoint2D32f* latestPoints[MAX_CAMERAS]; CvMat* rectMap[MAX_CAMERAS][2]; /* Added by Valery */ //CvStereoCamera stereoParams; int maxPoints; int framesTotal; int framesAccepted; bool isCalibrated; }; #include #include class CV_EXPORTS CvImage { public: CvImage() : image(0), refcount(0) {} CvImage( CvSize _size, int _depth, int _channels ) { image = cvCreateImage( _size, _depth, _channels ); refcount = image ? new int(1) : 0; } CvImage( IplImage* img ) : image(img) { refcount = image ? new int(1) : 0; } CvImage( const CvImage& img ) : image(img.image), refcount(img.refcount) { if( refcount ) ++(*refcount); } CvImage( const char* filename, const char* imgname=0, int color=-1 ) : image(0), refcount(0) { load( filename, imgname, color ); } CvImage( CvFileStorage* fs, const char* mapname, const char* imgname ) : image(0), refcount(0) { read( fs, mapname, imgname ); } CvImage( CvFileStorage* fs, const char* seqname, int idx ) : image(0), refcount(0) { read( fs, seqname, idx ); } ~CvImage() { if( refcount && !(--*refcount) ) { cvReleaseImage( &image ); delete refcount; } } CvImage clone() { return CvImage(image ? cvCloneImage(image) : 0); } void create( CvSize _size, int _depth, int _channels ) { if( !image || !refcount || image->width != _size.width || image->height != _size.height || image->depth != _depth || image->nChannels != _channels ) attach( cvCreateImage( _size, _depth, _channels )); } void release() { detach(); } void clear() { detach(); } void attach( IplImage* img, bool use_refcount=true ) { if( refcount && --*refcount == 0 ) { cvReleaseImage( &image ); delete refcount; } image = img; refcount = use_refcount && image ? new int(1) : 0; } void detach() { if( refcount && --*refcount == 0 ) { cvReleaseImage( &image ); delete refcount; } image = 0; refcount = 0; } bool load( const char* filename, const char* imgname=0, int color=-1 ); bool read( CvFileStorage* fs, const char* mapname, const char* imgname ); bool read( CvFileStorage* fs, const char* seqname, int idx ); void save( const char* filename, const char* imgname, const int* params=0 ); void write( CvFileStorage* fs, const char* imgname ); void show( const char* window_name ); bool is_valid() { return image != 0; } int width() const { return image ? image->width : 0; } int height() const { return image ? image->height : 0; } CvSize size() const { return image ? cvSize(image->width, image->height) : cvSize(0,0); } CvSize roi_size() const { return !image ? cvSize(0,0) : !image->roi ? cvSize(image->width,image->height) : cvSize(image->roi->width, image->roi->height); } CvRect roi() const { return !image ? cvRect(0,0,0,0) : !image->roi ? cvRect(0,0,image->width,image->height) : cvRect(image->roi->xOffset,image->roi->yOffset, image->roi->width,image->roi->height); } int coi() const { return !image || !image->roi ? 0 : image->roi->coi; } void set_roi(CvRect _roi) { cvSetImageROI(image,_roi); } void reset_roi() { cvResetImageROI(image); } void set_coi(int _coi) { cvSetImageCOI(image,_coi); } int depth() const { return image ? image->depth : 0; } int channels() const { return image ? image->nChannels : 0; } int pix_size() const { return image ? ((image->depth & 255)>>3)*image->nChannels : 0; } uchar* data() { return image ? (uchar*)image->imageData : 0; } const uchar* data() const { return image ? (const uchar*)image->imageData : 0; } int step() const { return image ? image->widthStep : 0; } int origin() const { return image ? image->origin : 0; } uchar* roi_row(int y) { assert(0<=y); assert(!image ? 1 : image->roi ? yroi->height : yheight); return !image ? 0 : !image->roi ? (uchar*)(image->imageData + y*image->widthStep) : (uchar*)(image->imageData + (y+image->roi->yOffset)*image->widthStep + image->roi->xOffset*((image->depth & 255)>>3)*image->nChannels); } const uchar* roi_row(int y) const { assert(0<=y); assert(!image ? 1 : image->roi ? yroi->height : yheight); return !image ? 0 : !image->roi ? (const uchar*)(image->imageData + y*image->widthStep) : (const uchar*)(image->imageData + (y+image->roi->yOffset)*image->widthStep + image->roi->xOffset*((image->depth & 255)>>3)*image->nChannels); } operator const IplImage* () const { return image; } operator IplImage* () { return image; } CvImage& operator = (const CvImage& img) { if( img.refcount ) ++*img.refcount; if( refcount && !(--*refcount) ) cvReleaseImage( &image ); image=img.image; refcount=img.refcount; return *this; } protected: IplImage* image; int* refcount; }; class CV_EXPORTS CvMatrix { public: CvMatrix() : matrix(0) {} CvMatrix( int _rows, int _cols, int _type ) { matrix = cvCreateMat( _rows, _cols, _type ); } CvMatrix( int _rows, int _cols, int _type, CvMat* hdr, void* _data=0, int _step=CV_AUTOSTEP ) { matrix = cvInitMatHeader( hdr, _rows, _cols, _type, _data, _step ); } CvMatrix( int rows, int cols, int type, CvMemStorage* storage, bool alloc_data=true ); CvMatrix( int _rows, int _cols, int _type, void* _data, int _step=CV_AUTOSTEP ) { matrix = cvCreateMatHeader( _rows, _cols, _type ); cvSetData( matrix, _data, _step ); } CvMatrix( CvMat* m ) { matrix = m; } CvMatrix( const CvMatrix& m ) { matrix = m.matrix; addref(); } CvMatrix( const char* filename, const char* matname=0, int color=-1 ) : matrix(0) { load( filename, matname, color ); } CvMatrix( CvFileStorage* fs, const char* mapname, const char* matname ) : matrix(0) { read( fs, mapname, matname ); } CvMatrix( CvFileStorage* fs, const char* seqname, int idx ) : matrix(0) { read( fs, seqname, idx ); } ~CvMatrix() { release(); } CvMatrix clone() { return CvMatrix(matrix ? cvCloneMat(matrix) : 0); } void set( CvMat* m, bool add_ref ) { release(); matrix = m; if( add_ref ) addref(); } void create( int _rows, int _cols, int _type ) { if( !matrix || !matrix->refcount || matrix->rows != _rows || matrix->cols != _cols || CV_MAT_TYPE(matrix->type) != _type ) set( cvCreateMat( _rows, _cols, _type ), false ); } void addref() const { if( matrix ) { if( matrix->hdr_refcount ) ++matrix->hdr_refcount; else if( matrix->refcount ) ++*matrix->refcount; } } void release() { if( matrix ) { if( matrix->hdr_refcount ) { if( --matrix->hdr_refcount == 0 ) cvReleaseMat( &matrix ); } else if( matrix->refcount ) { if( --*matrix->refcount == 0 ) cvFree( &matrix->refcount ); } matrix = 0; } } void clear() { release(); } bool load( const char* filename, const char* matname=0, int color=-1 ); bool read( CvFileStorage* fs, const char* mapname, const char* matname ); bool read( CvFileStorage* fs, const char* seqname, int idx ); void save( const char* filename, const char* matname, const int* params=0 ); void write( CvFileStorage* fs, const char* matname ); void show( const char* window_name ); bool is_valid() { return matrix != 0; } int rows() const { return matrix ? matrix->rows : 0; } int cols() const { return matrix ? matrix->cols : 0; } CvSize size() const { return !matrix ? cvSize(0,0) : cvSize(matrix->rows,matrix->cols); } int type() const { return matrix ? CV_MAT_TYPE(matrix->type) : 0; } int depth() const { return matrix ? CV_MAT_DEPTH(matrix->type) : 0; } int channels() const { return matrix ? CV_MAT_CN(matrix->type) : 0; } int pix_size() const { return matrix ? CV_ELEM_SIZE(matrix->type) : 0; } uchar* data() { return matrix ? matrix->data.ptr : 0; } const uchar* data() const { return matrix ? matrix->data.ptr : 0; } int step() const { return matrix ? matrix->step : 0; } void set_data( void* _data, int _step=CV_AUTOSTEP ) { cvSetData( matrix, _data, _step ); } uchar* row(int i) { return !matrix ? 0 : matrix->data.ptr + i*matrix->step; } const uchar* row(int i) const { return !matrix ? 0 : matrix->data.ptr + i*matrix->step; } operator const CvMat* () const { return matrix; } operator CvMat* () { return matrix; } CvMatrix& operator = (const CvMatrix& _m) { _m.addref(); release(); matrix = _m.matrix; return *this; } protected: CvMat* matrix; }; /****************************************************************************************\ * CamShiftTracker * \****************************************************************************************/ class CV_EXPORTS CvCamShiftTracker { public: CvCamShiftTracker(); virtual ~CvCamShiftTracker(); /**** Characteristics of the object that are calculated by track_object method *****/ float get_orientation() const // orientation of the object in degrees { return m_box.angle; } float get_length() const // the larger linear size of the object { return m_box.size.height; } float get_width() const // the smaller linear size of the object { return m_box.size.width; } CvPoint2D32f get_center() const // center of the object { return m_box.center; } CvRect get_window() const // bounding rectangle for the object { return m_comp.rect; } /*********************** Tracking parameters ************************/ int get_threshold() const // thresholding value that applied to back project { return m_threshold; } int get_hist_dims( int* dims = 0 ) const // returns number of histogram dimensions and sets { return m_hist ? cvGetDims( m_hist->bins, dims ) : 0; } int get_min_ch_val( int channel ) const // get the minimum allowed value of the specified channel { return m_min_ch_val[channel]; } int get_max_ch_val( int channel ) const // get the maximum allowed value of the specified channel { return m_max_ch_val[channel]; } // set initial object rectangle (must be called before initial calculation of the histogram) bool set_window( CvRect window) { m_comp.rect = window; return true; } bool set_threshold( int threshold ) // threshold applied to the histogram bins { m_threshold = threshold; return true; } bool set_hist_bin_range( int dim, int min_val, int max_val ); bool set_hist_dims( int c_dims, int* dims );// set the histogram parameters bool set_min_ch_val( int channel, int val ) // set the minimum allowed value of the specified channel { m_min_ch_val[channel] = val; return true; } bool set_max_ch_val( int channel, int val ) // set the maximum allowed value of the specified channel { m_max_ch_val[channel] = val; return true; } /************************ The processing methods *********************************/ // update object position virtual bool track_object( const IplImage* cur_frame ); // update object histogram virtual bool update_histogram( const IplImage* cur_frame ); // reset histogram virtual void reset_histogram(); /************************ Retrieving internal data *******************************/ // get back project image virtual IplImage* get_back_project() { return m_back_project; } float query( int* bin ) const { return m_hist ? (float)cvGetRealND(m_hist->bins, bin) : 0.f; } protected: // internal method for color conversion: fills m_color_planes group virtual void color_transform( const IplImage* img ); CvHistogram* m_hist; CvBox2D m_box; CvConnectedComp m_comp; float m_hist_ranges_data[CV_MAX_DIM][2]; float* m_hist_ranges[CV_MAX_DIM]; int m_min_ch_val[CV_MAX_DIM]; int m_max_ch_val[CV_MAX_DIM]; int m_threshold; IplImage* m_color_planes[CV_MAX_DIM]; IplImage* m_back_project; IplImage* m_temp; IplImage* m_mask; }; /****************************************************************************************\ * Expectation - Maximization * \****************************************************************************************/ struct CV_EXPORTS_W_MAP CvEMParams { CvEMParams(); CvEMParams( int nclusters, int cov_mat_type=cv::EM::COV_MAT_DIAGONAL, int start_step=cv::EM::START_AUTO_STEP, CvTermCriteria term_crit=cvTermCriteria(CV_TERMCRIT_ITER+CV_TERMCRIT_EPS, 100, FLT_EPSILON), const CvMat* probs=0, const CvMat* weights=0, const CvMat* means=0, const CvMat** covs=0 ); CV_PROP_RW int nclusters; CV_PROP_RW int cov_mat_type; CV_PROP_RW int start_step; const CvMat* probs; const CvMat* weights; const CvMat* means; const CvMat** covs; CV_PROP_RW CvTermCriteria term_crit; }; class CV_EXPORTS_W CvEM : public CvStatModel { public: // Type of covariation matrices enum { COV_MAT_SPHERICAL=cv::EM::COV_MAT_SPHERICAL, COV_MAT_DIAGONAL =cv::EM::COV_MAT_DIAGONAL, COV_MAT_GENERIC =cv::EM::COV_MAT_GENERIC }; // The initial step enum { START_E_STEP=cv::EM::START_E_STEP, START_M_STEP=cv::EM::START_M_STEP, START_AUTO_STEP=cv::EM::START_AUTO_STEP }; CV_WRAP CvEM(); CvEM( const CvMat* samples, const CvMat* sampleIdx=0, CvEMParams params=CvEMParams(), CvMat* labels=0 ); virtual ~CvEM(); virtual bool train( const CvMat* samples, const CvMat* sampleIdx=0, CvEMParams params=CvEMParams(), CvMat* labels=0 ); virtual float predict( const CvMat* sample, CV_OUT CvMat* probs ) const; CV_WRAP CvEM( const cv::Mat& samples, const cv::Mat& sampleIdx=cv::Mat(), CvEMParams params=CvEMParams() ); CV_WRAP virtual bool train( const cv::Mat& samples, const cv::Mat& sampleIdx=cv::Mat(), CvEMParams params=CvEMParams(), CV_OUT cv::Mat* labels=0 ); CV_WRAP virtual float predict( const cv::Mat& sample, CV_OUT cv::Mat* probs=0 ) const; CV_WRAP virtual double calcLikelihood( const cv::Mat &sample ) const; CV_WRAP int getNClusters() const; CV_WRAP cv::Mat getMeans() const; CV_WRAP void getCovs(CV_OUT std::vector& covs) const; CV_WRAP cv::Mat getWeights() const; CV_WRAP cv::Mat getProbs() const; CV_WRAP inline double getLikelihood() const { return emObj.isTrained() ? logLikelihood : DBL_MAX; } CV_WRAP virtual void clear(); int get_nclusters() const; const CvMat* get_means() const; const CvMat** get_covs() const; const CvMat* get_weights() const; const CvMat* get_probs() const; inline double get_log_likelihood() const { return getLikelihood(); } virtual void read( CvFileStorage* fs, CvFileNode* node ); virtual void write( CvFileStorage* fs, const char* name ) const; protected: void set_mat_hdrs(); cv::EM emObj; cv::Mat probs; double logLikelihood; CvMat meansHdr; std::vector covsHdrs; std::vector covsPtrs; CvMat weightsHdr; CvMat probsHdr; }; namespace cv { typedef CvEMParams EMParams; typedef CvEM ExpectationMaximization; /*! The Patch Generator class */ 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& matT, Mat& buf, CV_OUT Mat& warped, int border, RNG& rng) const; void generateRandomTransform(Point2f srcCenter, Point2f dstCenter, CV_OUT Mat& transform, RNG& rng, bool inverse=false) const; void setAffineParam(double lambda, double theta, double phi); 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, CV_OUT std::vector& keypoints, int maxCount=0, bool scaleCoords=true) const; void operator()(const std::vector& pyr, CV_OUT std::vector& keypoints, int maxCount=0, bool scaleCoords=true) const; void getMostStable2D(const Mat& image, CV_OUT std::vector& 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; }; typedef LDetector YAPE; class CV_EXPORTS FernClassifier { public: FernClassifier(); FernClassifier(const FileNode& node); FernClassifier(const std::vector >& points, const std::vector& refimgs, const std::vector >& labels=std::vector >(), 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 std::vector& 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 std::vector >& points, const std::vector& refimgs, const std::vector >& labels=std::vector >(), 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, std::vector& signature) const; virtual int operator()(const Mat& patch, std::vector& signature) const; virtual void clear(); virtual bool empty() const; 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 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; std::vector features; std::vector classCounters; std::vector posteriors; }; /****************************************************************************************\ * Calonder Classifier * \****************************************************************************************/ struct RTreeNode; struct CV_EXPORTS BaseKeypoint { int x; int y; IplImage* image; BaseKeypoint() : x(0), y(0), image(NULL) {} BaseKeypoint(int _x, int _y, IplImage* _image) : x(_x), y(_y), image(_image) {} }; class CV_EXPORTS RandomizedTree { public: friend class RTreeClassifier; static const uchar PATCH_SIZE = 32; static const int DEFAULT_DEPTH = 9; static const int DEFAULT_VIEWS = 5000; static const size_t DEFAULT_REDUCED_NUM_DIM = 176; static float GET_LOWER_QUANT_PERC() { return .03f; } static float GET_UPPER_QUANT_PERC() { return .92f; } RandomizedTree(); ~RandomizedTree(); void train(std::vector const& base_set, RNG &rng, int depth, int views, size_t reduced_num_dim, int num_quant_bits); void train(std::vector const& base_set, RNG &rng, PatchGenerator &make_patch, int depth, int views, size_t reduced_num_dim, int num_quant_bits); // following two funcs are EXPERIMENTAL (do not use unless you know exactly what you do) static void quantizeVector(float *vec, int dim, int N, float bnds[2], int clamp_mode=0); static void quantizeVector(float *src, int dim, int N, float bnds[2], uchar *dst); // patch_data must be a 32x32 array (no row padding) float* getPosterior(uchar* patch_data); const float* getPosterior(uchar* patch_data) const; uchar* getPosterior2(uchar* patch_data); const uchar* getPosterior2(uchar* patch_data) const; void read(const char* file_name, int num_quant_bits); void read(std::istream &is, int num_quant_bits); void write(const char* file_name) const; void write(std::ostream &os) const; int classes() { return classes_; } int depth() { return depth_; } //void setKeepFloatPosteriors(bool b) { keep_float_posteriors_ = b; } void discardFloatPosteriors() { freePosteriors(1); } inline void applyQuantization(int num_quant_bits) { makePosteriors2(num_quant_bits); } // debug void savePosteriors(String url, bool append=false); void savePosteriors2(String url, bool append=false); private: int classes_; int depth_; int num_leaves_; std::vector nodes_; float **posteriors_; // 16-bytes aligned posteriors uchar **posteriors2_; // 16-bytes aligned posteriors std::vector leaf_counts_; void createNodes(int num_nodes, RNG &rng); void allocPosteriorsAligned(int num_leaves, int num_classes); void freePosteriors(int which); // which: 1=posteriors_, 2=posteriors2_, 3=both void init(int classes, int depth, RNG &rng); void addExample(int class_id, uchar* patch_data); void finalize(size_t reduced_num_dim, int num_quant_bits); int getIndex(uchar* patch_data) const; inline float* getPosteriorByIndex(int index); inline const float* getPosteriorByIndex(int index) const; inline uchar* getPosteriorByIndex2(int index); inline const uchar* getPosteriorByIndex2(int index) const; //void makeRandomMeasMatrix(float *cs_phi, PHI_DISTR_TYPE dt, size_t reduced_num_dim); void convertPosteriorsToChar(); void makePosteriors2(int num_quant_bits); void compressLeaves(size_t reduced_num_dim); void estimateQuantPercForPosteriors(float perc[2]); }; inline uchar* getData(IplImage* image) { return reinterpret_cast(image->imageData); } inline float* RandomizedTree::getPosteriorByIndex(int index) { return const_cast(const_cast(this)->getPosteriorByIndex(index)); } inline const float* RandomizedTree::getPosteriorByIndex(int index) const { return posteriors_[index]; } inline uchar* RandomizedTree::getPosteriorByIndex2(int index) { return const_cast(const_cast(this)->getPosteriorByIndex2(index)); } inline const uchar* RandomizedTree::getPosteriorByIndex2(int index) const { return posteriors2_[index]; } struct CV_EXPORTS RTreeNode { short offset1, offset2; RTreeNode() {} RTreeNode(uchar x1, uchar y1, uchar x2, uchar y2) : offset1(y1*RandomizedTree::PATCH_SIZE + x1), offset2(y2*RandomizedTree::PATCH_SIZE + x2) {} //! Left child on 0, right child on 1 inline bool operator() (uchar* patch_data) const { return patch_data[offset1] > patch_data[offset2]; } }; class CV_EXPORTS RTreeClassifier { public: static const int DEFAULT_TREES = 48; static const size_t DEFAULT_NUM_QUANT_BITS = 4; RTreeClassifier(); void train(std::vector const& base_set, RNG &rng, int num_trees = RTreeClassifier::DEFAULT_TREES, int depth = RandomizedTree::DEFAULT_DEPTH, int views = RandomizedTree::DEFAULT_VIEWS, size_t reduced_num_dim = RandomizedTree::DEFAULT_REDUCED_NUM_DIM, int num_quant_bits = DEFAULT_NUM_QUANT_BITS); void train(std::vector const& base_set, RNG &rng, PatchGenerator &make_patch, int num_trees = RTreeClassifier::DEFAULT_TREES, int depth = RandomizedTree::DEFAULT_DEPTH, int views = RandomizedTree::DEFAULT_VIEWS, size_t reduced_num_dim = RandomizedTree::DEFAULT_REDUCED_NUM_DIM, int num_quant_bits = DEFAULT_NUM_QUANT_BITS); // sig must point to a memory block of at least classes()*sizeof(float|uchar) bytes void getSignature(IplImage *patch, uchar *sig) const; void getSignature(IplImage *patch, float *sig) const; void getSparseSignature(IplImage *patch, float *sig, float thresh) const; // TODO: deprecated in favor of getSignature overload, remove void getFloatSignature(IplImage *patch, float *sig) const { getSignature(patch, sig); } static int countNonZeroElements(float *vec, int n, double tol=1e-10); static inline void safeSignatureAlloc(uchar **sig, int num_sig=1, int sig_len=176); static inline uchar* safeSignatureAlloc(int num_sig=1, int sig_len=176); inline int classes() const { return classes_; } inline int original_num_classes() const { return original_num_classes_; } void setQuantization(int num_quant_bits); void discardFloatPosteriors(); void read(const char* file_name); void read(std::istream &is); void write(const char* file_name) const; void write(std::ostream &os) const; // experimental and debug void saveAllFloatPosteriors(String file_url); void saveAllBytePosteriors(String file_url); void setFloatPosteriorsFromTextfile_176(String url); float countZeroElements(); std::vector trees_; private: int classes_; int num_quant_bits_; mutable uchar **posteriors_; mutable unsigned short *ptemp_; int original_num_classes_; bool keep_floats_; }; /****************************************************************************************\ * One-Way Descriptor * \****************************************************************************************/ // CvAffinePose: defines a parameterized affine transformation of an image patch. // An image patch is rotated on angle phi (in degrees), then scaled lambda1 times // along horizontal and lambda2 times along vertical direction, and then rotated again // on angle (theta - phi). class CV_EXPORTS CvAffinePose { public: float phi; float theta; float lambda1; float lambda2; }; class CV_EXPORTS OneWayDescriptor { public: OneWayDescriptor(); ~OneWayDescriptor(); // allocates memory for given descriptor parameters void Allocate(int pose_count, CvSize size, int nChannels); // GenerateSamples: generates affine transformed patches with averaging them over small transformation variations. // If external poses and transforms were specified, uses them instead of generating random ones // - pose_count: the number of poses to be generated // - frontal: the input patch (can be a roi in a larger image) // - norm: if nonzero, normalizes the output patch so that the sum of pixel intensities is 1 void GenerateSamples(int pose_count, IplImage* frontal, int norm = 0); // GenerateSamplesFast: generates affine transformed patches with averaging them over small transformation variations. // Uses precalculated transformed pca components. // - frontal: the input patch (can be a roi in a larger image) // - pca_hr_avg: pca average vector // - pca_hr_eigenvectors: pca eigenvectors // - pca_descriptors: an array of precomputed descriptors of pca components containing their affine transformations // pca_descriptors[0] corresponds to the average, pca_descriptors[1]-pca_descriptors[pca_dim] correspond to eigenvectors void GenerateSamplesFast(IplImage* frontal, CvMat* pca_hr_avg, CvMat* pca_hr_eigenvectors, OneWayDescriptor* pca_descriptors); // sets the poses and corresponding transforms void SetTransforms(CvAffinePose* poses, CvMat** transforms); // Initialize: builds a descriptor. // - pose_count: the number of poses to build. If poses were set externally, uses them rather than generating random ones // - frontal: input patch. Can be a roi in a larger image // - feature_name: the feature name to be associated with the descriptor // - norm: if 1, the affine transformed patches are normalized so that their sum is 1 void Initialize(int pose_count, IplImage* frontal, const char* feature_name = 0, int norm = 0); // InitializeFast: builds a descriptor using precomputed descriptors of pca components // - pose_count: the number of poses to build // - frontal: input patch. Can be a roi in a larger image // - feature_name: the feature name to be associated with the descriptor // - pca_hr_avg: average vector for PCA // - pca_hr_eigenvectors: PCA eigenvectors (one vector per row) // - pca_descriptors: precomputed descriptors of PCA components, the first descriptor for the average vector // followed by the descriptors for eigenvectors void InitializeFast(int pose_count, IplImage* frontal, const char* feature_name, CvMat* pca_hr_avg, CvMat* pca_hr_eigenvectors, OneWayDescriptor* pca_descriptors); // ProjectPCASample: unwarps an image patch into a vector and projects it into PCA space // - patch: input image patch // - avg: PCA average vector // - eigenvectors: PCA eigenvectors, one per row // - pca_coeffs: output PCA coefficients void ProjectPCASample(IplImage* patch, CvMat* avg, CvMat* eigenvectors, CvMat* pca_coeffs) const; // InitializePCACoeffs: projects all warped patches into PCA space // - avg: PCA average vector // - eigenvectors: PCA eigenvectors, one per row void InitializePCACoeffs(CvMat* avg, CvMat* eigenvectors); // EstimatePose: finds the closest match between an input patch and a set of patches with different poses // - patch: input image patch // - pose_idx: the output index of the closest pose // - distance: the distance to the closest pose (L2 distance) void EstimatePose(IplImage* patch, int& pose_idx, float& distance) const; // EstimatePosePCA: finds the closest match between an input patch and a set of patches with different poses. // The distance between patches is computed in PCA space // - patch: input image patch // - pose_idx: the output index of the closest pose // - distance: distance to the closest pose (L2 distance in PCA space) // - avg: PCA average vector. If 0, matching without PCA is used // - eigenvectors: PCA eigenvectors, one per row void EstimatePosePCA(CvArr* patch, int& pose_idx, float& distance, CvMat* avg, CvMat* eigenvalues) const; // GetPatchSize: returns the size of each image patch after warping (2 times smaller than the input patch) CvSize GetPatchSize() const { return m_patch_size; } // GetInputPatchSize: returns the required size of the patch that the descriptor is built from // (2 time larger than the patch after warping) CvSize GetInputPatchSize() const { return cvSize(m_patch_size.width*2, m_patch_size.height*2); } // GetPatch: returns a patch corresponding to specified pose index // - index: pose index // - return value: the patch corresponding to specified pose index IplImage* GetPatch(int index); // GetPose: returns a pose corresponding to specified pose index // - index: pose index // - return value: the pose corresponding to specified pose index CvAffinePose GetPose(int index) const; // Save: saves all patches with different poses to a specified path void Save(const char* path); // ReadByName: reads a descriptor from a file storage // - fs: file storage // - parent: parent node // - name: node name // - return value: 1 if succeeded, 0 otherwise int ReadByName(CvFileStorage* fs, CvFileNode* parent, const char* name); // ReadByName: reads a descriptor from a file node // - parent: parent node // - name: node name // - return value: 1 if succeeded, 0 otherwise int ReadByName(const FileNode &parent, const char* name); // Write: writes a descriptor into a file storage // - fs: file storage // - name: node name void Write(CvFileStorage* fs, const char* name); // GetFeatureName: returns a name corresponding to a feature const char* GetFeatureName() const; // GetCenter: returns the center of the feature CvPoint GetCenter() const; void SetPCADimHigh(int pca_dim_high) {m_pca_dim_high = pca_dim_high;}; void SetPCADimLow(int pca_dim_low) {m_pca_dim_low = pca_dim_low;}; int GetPCADimLow() const; int GetPCADimHigh() const; CvMat** GetPCACoeffs() const {return m_pca_coeffs;} protected: int m_pose_count; // the number of poses CvSize m_patch_size; // size of each image IplImage** m_samples; // an array of length m_pose_count containing the patch in different poses IplImage* m_input_patch; IplImage* m_train_patch; CvMat** m_pca_coeffs; // an array of length m_pose_count containing pca decomposition of the patch in different poses CvAffinePose* m_affine_poses; // an array of poses CvMat** m_transforms; // an array of affine transforms corresponding to poses String m_feature_name; // the name of the feature associated with the descriptor CvPoint m_center; // the coordinates of the feature (the center of the input image ROI) int m_pca_dim_high; // the number of descriptor pca components to use for generating affine poses int m_pca_dim_low; // the number of pca components to use for comparison }; // OneWayDescriptorBase: encapsulates functionality for training/loading a set of one way descriptors // and finding the nearest closest descriptor to an input feature class CV_EXPORTS OneWayDescriptorBase { public: // creates an instance of OneWayDescriptor from a set of training files // - patch_size: size of the input (large) patch // - pose_count: the number of poses to generate for each descriptor // - train_path: path to training files // - pca_config: the name of the file that contains PCA for small patches (2 times smaller // than patch_size each dimension // - pca_hr_config: the name of the file that contains PCA for large patches (of patch_size size) // - pca_desc_config: the name of the file that contains descriptors of PCA components OneWayDescriptorBase(CvSize patch_size, int pose_count, const char* train_path = 0, const char* pca_config = 0, const char* pca_hr_config = 0, const char* pca_desc_config = 0, int pyr_levels = 1, int pca_dim_high = 100, int pca_dim_low = 100); OneWayDescriptorBase(CvSize patch_size, int pose_count, const String &pca_filename, const String &train_path = String(), const String &images_list = String(), float _scale_min = 0.7f, float _scale_max=1.5f, float _scale_step=1.2f, int pyr_levels = 1, int pca_dim_high = 100, int pca_dim_low = 100); virtual ~OneWayDescriptorBase(); void clear (); // Allocate: allocates memory for a given number of descriptors void Allocate(int train_feature_count); // AllocatePCADescriptors: allocates memory for pca descriptors void AllocatePCADescriptors(); // returns patch size CvSize GetPatchSize() const {return m_patch_size;}; // returns the number of poses for each descriptor int GetPoseCount() const {return m_pose_count;}; // returns the number of pyramid levels int GetPyrLevels() const {return m_pyr_levels;}; // returns the number of descriptors int GetDescriptorCount() const {return m_train_feature_count;}; // CreateDescriptorsFromImage: creates descriptors for each of the input features // - src: input image // - features: input features // - pyr_levels: the number of pyramid levels void CreateDescriptorsFromImage(IplImage* src, const std::vector& features); // CreatePCADescriptors: generates descriptors for PCA components, needed for fast generation of feature descriptors void CreatePCADescriptors(); // returns a feature descriptor by feature index const OneWayDescriptor* GetDescriptor(int desc_idx) const {return &m_descriptors[desc_idx];}; // FindDescriptor: finds the closest descriptor // - patch: input image patch // - desc_idx: output index of the closest descriptor to the input patch // - pose_idx: output index of the closest pose of the closest descriptor to the input patch // - distance: distance from the input patch to the closest feature pose // - _scales: scales of the input patch for each descriptor // - scale_ranges: input scales variation (float[2]) void FindDescriptor(IplImage* patch, int& desc_idx, int& pose_idx, float& distance, float* _scale = 0, float* scale_ranges = 0) const; // - patch: input image patch // - n: number of the closest indexes // - desc_idxs: output indexes of the closest descriptor to the input patch (n) // - pose_idx: output indexes of the closest pose of the closest descriptor to the input patch (n) // - distances: distance from the input patch to the closest feature pose (n) // - _scales: scales of the input patch // - scale_ranges: input scales variation (float[2]) void FindDescriptor(IplImage* patch, int n, std::vector& desc_idxs, std::vector& pose_idxs, std::vector& distances, std::vector& _scales, float* scale_ranges = 0) const; // FindDescriptor: finds the closest descriptor // - src: input image // - pt: center of the feature // - desc_idx: output index of the closest descriptor to the input patch // - pose_idx: output index of the closest pose of the closest descriptor to the input patch // - distance: distance from the input patch to the closest feature pose void FindDescriptor(IplImage* src, cv::Point2f pt, int& desc_idx, int& pose_idx, float& distance) const; // InitializePoses: generates random poses void InitializePoses(); // InitializeTransformsFromPoses: generates 2x3 affine matrices from poses (initializes m_transforms) void InitializeTransformsFromPoses(); // InitializePoseTransforms: subsequently calls InitializePoses and InitializeTransformsFromPoses void InitializePoseTransforms(); // InitializeDescriptor: initializes a descriptor // - desc_idx: descriptor index // - train_image: image patch (ROI is supported) // - feature_label: feature textual label void InitializeDescriptor(int desc_idx, IplImage* train_image, const char* feature_label); void InitializeDescriptor(int desc_idx, IplImage* train_image, const KeyPoint& keypoint, const char* feature_label); // InitializeDescriptors: load features from an image and create descriptors for each of them void InitializeDescriptors(IplImage* train_image, const std::vector& features, const char* feature_label = "", int desc_start_idx = 0); // Write: writes this object to a file storage // - fs: output filestorage void Write (FileStorage &fs) const; // Read: reads OneWayDescriptorBase object from a file node // - fn: input file node void Read (const FileNode &fn); // LoadPCADescriptors: loads PCA descriptors from a file // - filename: input filename int LoadPCADescriptors(const char* filename); // LoadPCADescriptors: loads PCA descriptors from a file node // - fn: input file node int LoadPCADescriptors(const FileNode &fn); // SavePCADescriptors: saves PCA descriptors to a file // - filename: output filename void SavePCADescriptors(const char* filename); // SavePCADescriptors: saves PCA descriptors to a file storage // - fs: output file storage void SavePCADescriptors(CvFileStorage* fs) const; // GeneratePCA: calculate and save PCA components and descriptors // - img_path: path to training PCA images directory // - images_list: filename with filenames of training PCA images void GeneratePCA(const char* img_path, const char* images_list, int pose_count=500); // SetPCAHigh: sets the high resolution pca matrices (copied to internal structures) void SetPCAHigh(CvMat* avg, CvMat* eigenvectors); // SetPCALow: sets the low resolution pca matrices (copied to internal structures) void SetPCALow(CvMat* avg, CvMat* eigenvectors); int GetLowPCA(CvMat** avg, CvMat** eigenvectors) { *avg = m_pca_avg; *eigenvectors = m_pca_eigenvectors; return m_pca_dim_low; }; int GetPCADimLow() const {return m_pca_dim_low;}; int GetPCADimHigh() const {return m_pca_dim_high;}; void ConvertDescriptorsArrayToTree(); // Converting pca_descriptors array to KD tree // GetPCAFilename: get default PCA filename static String GetPCAFilename () { return "pca.yml"; } virtual bool empty() const { return m_train_feature_count <= 0 ? true : false; } protected: CvSize m_patch_size; // patch size int m_pose_count; // the number of poses for each descriptor int m_train_feature_count; // the number of the training features OneWayDescriptor* m_descriptors; // array of train feature descriptors CvMat* m_pca_avg; // PCA average Vector for small patches CvMat* m_pca_eigenvectors; // PCA eigenvectors for small patches CvMat* m_pca_hr_avg; // PCA average Vector for large patches CvMat* m_pca_hr_eigenvectors; // PCA eigenvectors for large patches OneWayDescriptor* m_pca_descriptors; // an array of PCA descriptors cv::flann::Index* m_pca_descriptors_tree; CvMat* m_pca_descriptors_matrix; CvAffinePose* m_poses; // array of poses CvMat** m_transforms; // array of affine transformations corresponding to poses int m_pca_dim_high; int m_pca_dim_low; int m_pyr_levels; float scale_min; float scale_max; float scale_step; // SavePCAall: saves PCA components and descriptors to a file storage // - fs: output file storage void SavePCAall (FileStorage &fs) const; // LoadPCAall: loads PCA components and descriptors from a file node // - fn: input file node void LoadPCAall (const FileNode &fn); }; class CV_EXPORTS OneWayDescriptorObject : public OneWayDescriptorBase { public: // creates an instance of OneWayDescriptorObject from a set of training files // - patch_size: size of the input (large) patch // - pose_count: the number of poses to generate for each descriptor // - train_path: path to training files // - pca_config: the name of the file that contains PCA for small patches (2 times smaller // than patch_size each dimension // - pca_hr_config: the name of the file that contains PCA for large patches (of patch_size size) // - pca_desc_config: the name of the file that contains descriptors of PCA components OneWayDescriptorObject(CvSize patch_size, int pose_count, const char* train_path, const char* pca_config, const char* pca_hr_config = 0, const char* pca_desc_config = 0, int pyr_levels = 1); OneWayDescriptorObject(CvSize patch_size, int pose_count, const String &pca_filename, const String &train_path = String (), const String &images_list = String (), float _scale_min = 0.7f, float _scale_max=1.5f, float _scale_step=1.2f, int pyr_levels = 1); virtual ~OneWayDescriptorObject(); // Allocate: allocates memory for a given number of features // - train_feature_count: the total number of features // - object_feature_count: the number of features extracted from the object void Allocate(int train_feature_count, int object_feature_count); void SetLabeledFeatures(const std::vector& features) {m_train_features = features;}; std::vector& GetLabeledFeatures() {return m_train_features;}; const std::vector& GetLabeledFeatures() const {return m_train_features;}; std::vector _GetLabeledFeatures() const; // IsDescriptorObject: returns 1 if descriptor with specified index is positive, otherwise 0 int IsDescriptorObject(int desc_idx) const; // MatchPointToPart: returns the part number of a feature if it matches one of the object parts, otherwise -1 int MatchPointToPart(CvPoint pt) const; // GetDescriptorPart: returns the part number of the feature corresponding to a specified descriptor // - desc_idx: descriptor index int GetDescriptorPart(int desc_idx) const; void InitializeObjectDescriptors(IplImage* train_image, const std::vector& features, const char* feature_label, int desc_start_idx = 0, float scale = 1.0f, int is_background = 0); // GetObjectFeatureCount: returns the number of object features int GetObjectFeatureCount() const {return m_object_feature_count;}; protected: int* m_part_id; // contains part id for each of object descriptors std::vector m_train_features; // train features int m_object_feature_count; // the number of the positive features }; /* * OneWayDescriptorMatcher */ class OneWayDescriptorMatcher; typedef OneWayDescriptorMatcher OneWayDescriptorMatch; class CV_EXPORTS OneWayDescriptorMatcher : public GenericDescriptorMatcher { public: class CV_EXPORTS Params { public: static const int POSE_COUNT = 500; static const int PATCH_WIDTH = 24; static const int PATCH_HEIGHT = 24; static float GET_MIN_SCALE() { return 0.7f; } static float GET_MAX_SCALE() { return 1.5f; } static float GET_STEP_SCALE() { return 1.2f; } Params( int poseCount = POSE_COUNT, Size patchSize = Size(PATCH_WIDTH, PATCH_HEIGHT), String pcaFilename = String(), String trainPath = String(), String trainImagesList = String(), float minScale = GET_MIN_SCALE(), float maxScale = GET_MAX_SCALE(), float stepScale = GET_STEP_SCALE() ); int poseCount; Size patchSize; String pcaFilename; String trainPath; String trainImagesList; float minScale, maxScale, stepScale; }; OneWayDescriptorMatcher( const Params& params=Params() ); virtual ~OneWayDescriptorMatcher(); void initialize( const Params& params, const Ptr& base=Ptr() ); // Clears keypoints storing in collection and OneWayDescriptorBase virtual void clear(); virtual void train(); virtual bool isMaskSupported(); virtual void read( const FileNode &fn ); virtual void write( FileStorage& fs ) const; virtual bool empty() const; virtual Ptr clone( bool emptyTrainData=false ) const; protected: // Matches a set of keypoints from a single image of the training set. A rectangle with a center in a keypoint // and size (patch_width/2*scale, patch_height/2*scale) is cropped from the source image for each // keypoint. scale is iterated from DescriptorOneWayParams::min_scale to DescriptorOneWayParams::max_scale. // The minimum distance to each training patch with all its affine poses is found over all scales. // The class ID of a match is returned for each keypoint. The distance is calculated over PCA components // loaded with DescriptorOneWay::Initialize, kd tree is used for finding minimum distances. virtual void knnMatchImpl( InputArray queryImage, std::vector& queryKeypoints, std::vector >& matches, int k, InputArrayOfArrays masks, bool compactResult ); virtual void radiusMatchImpl( InputArray queryImage, std::vector& queryKeypoints, std::vector >& matches, float maxDistance, InputArrayOfArrays masks, bool compactResult ); Ptr base; Params params; int prevTrainCount; }; /* * FernDescriptorMatcher */ class FernDescriptorMatcher; typedef FernDescriptorMatcher FernDescriptorMatch; class CV_EXPORTS FernDescriptorMatcher : public GenericDescriptorMatcher { public: class CV_EXPORTS Params { public: Params( int nclasses=0, int patchSize=FernClassifier::PATCH_SIZE, int signatureSize=FernClassifier::DEFAULT_SIGNATURE_SIZE, int nstructs=FernClassifier::DEFAULT_STRUCTS, int structSize=FernClassifier::DEFAULT_STRUCT_SIZE, int nviews=FernClassifier::DEFAULT_VIEWS, int compressionMethod=FernClassifier::COMPRESSION_NONE, const PatchGenerator& patchGenerator=PatchGenerator() ); Params( const String& filename ); int nclasses; int patchSize; int signatureSize; int nstructs; int structSize; int nviews; int compressionMethod; PatchGenerator patchGenerator; String filename; }; FernDescriptorMatcher( const Params& params=Params() ); virtual ~FernDescriptorMatcher(); virtual void clear(); virtual void train(); virtual bool isMaskSupported(); virtual void read( const FileNode &fn ); virtual void write( FileStorage& fs ) const; virtual bool empty() const; virtual Ptr clone( bool emptyTrainData=false ) const; protected: virtual void knnMatchImpl( InputArray queryImage, std::vector& queryKeypoints, std::vector >& matches, int k, InputArrayOfArrays masks, bool compactResult ); virtual void radiusMatchImpl( InputArray queryImage, std::vector& queryKeypoints, std::vector >& matches, float maxDistance, InputArrayOfArrays masks, bool compactResult ); void trainFernClassifier(); void calcBestProbAndMatchIdx( const Mat& image, const Point2f& pt, float& bestProb, int& bestMatchIdx, std::vector& signature ); Ptr classifier; Params params; int prevTrainCount; }; /* * CalonderDescriptorExtractor */ template class CV_EXPORTS CalonderDescriptorExtractor : public DescriptorExtractor { public: CalonderDescriptorExtractor( const String& classifierFile ); virtual void read( const FileNode &fn ); virtual void write( FileStorage &fs ) const; virtual int descriptorSize() const { return classifier_.classes(); } virtual int descriptorType() const { return DataType::type; } virtual int defaultNorm() const { return NORM_L1; } virtual bool empty() const; protected: virtual void computeImpl( InputArray image, std::vector& keypoints, OutputArray descriptors ) const; RTreeClassifier classifier_; static const int BORDER_SIZE = 16; }; template CalonderDescriptorExtractor::CalonderDescriptorExtractor(const String& classifier_file) { classifier_.read( classifier_file.c_str() ); } template void CalonderDescriptorExtractor::computeImpl( InputArray _image, std::vector& keypoints, OutputArray _descriptors) const { Mat image = _image.getMat(), descriptors; // Cannot compute descriptors for keypoints on the image border. KeyPointsFilter::runByImageBorder(keypoints, image.size(), BORDER_SIZE); /// @todo Check 16-byte aligned _descriptors.create((int)keypoints.size(), classifier_.classes(), cv::DataType::type); descriptors = _descriptors.getMat(); int patchSize = RandomizedTree::PATCH_SIZE; int offset = patchSize / 2; for (size_t i = 0; i < keypoints.size(); ++i) { cv::Point2f pt = keypoints[i].pt; IplImage ipl = image( Rect((int)(pt.x - offset), (int)(pt.y - offset), patchSize, patchSize) ); classifier_.getSignature( &ipl, descriptors.ptr((int)i)); } } template void CalonderDescriptorExtractor::read( const FileNode& ) {} template void CalonderDescriptorExtractor::write( FileStorage& ) const {} template bool CalonderDescriptorExtractor::empty() const { return classifier_.trees_.empty(); } ////////////////////// Brute Force Matcher ////////////////////////// template class CV_EXPORTS BruteForceMatcher : public BFMatcher { public: BruteForceMatcher( Distance d = Distance() ) : BFMatcher(Distance::normType, false) {(void)d;} virtual ~BruteForceMatcher() {} }; /****************************************************************************************\ * Planar Object Detection * \****************************************************************************************/ class CV_EXPORTS PlanarObjectDetector { public: PlanarObjectDetector(); PlanarObjectDetector(const FileNode& node); PlanarObjectDetector(const std::vector& 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 std::vector& 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 std::vector& pyr, const std::vector& 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; std::vector 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, CV_OUT Mat& H, CV_OUT std::vector& corners) const; bool operator()(const std::vector& pyr, const std::vector& keypoints, CV_OUT Mat& H, CV_OUT std::vector& corners, CV_OUT std::vector* pairs=0) const; protected: bool verbose; Rect modelROI; std::vector modelPoints; LDetector ldetector; FernClassifier fernClassifier; }; } // 2009-01-12, Xavier Delacour 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 #ifdef __cplusplus extern "C" { #endif /* Splits color or grayscale image into multiple connected components of nearly the same color/brightness using modification of Burt algorithm. comp with contain a pointer to sequence (CvSeq) of connected components (CvConnectedComp) */ CVAPI(void) cvPyrSegmentation( IplImage* src, IplImage* dst, CvMemStorage* storage, CvSeq** comp, int level, double threshold1, double threshold2 ); /****************************************************************************************\ * Planar subdivisions * \****************************************************************************************/ typedef size_t CvSubdiv2DEdge; #define CV_QUADEDGE2D_FIELDS() \ int flags; \ struct CvSubdiv2DPoint* pt[4]; \ CvSubdiv2DEdge next[4]; #define CV_SUBDIV2D_POINT_FIELDS()\ int flags; \ CvSubdiv2DEdge first; \ CvPoint2D32f pt; \ int id; #define CV_SUBDIV2D_VIRTUAL_POINT_FLAG (1 << 30) typedef struct CvQuadEdge2D { CV_QUADEDGE2D_FIELDS() } CvQuadEdge2D; typedef struct CvSubdiv2DPoint { CV_SUBDIV2D_POINT_FIELDS() } CvSubdiv2DPoint; #define CV_SUBDIV2D_FIELDS() \ CV_GRAPH_FIELDS() \ int quad_edges; \ int is_geometry_valid; \ CvSubdiv2DEdge recent_edge; \ CvPoint2D32f topleft; \ CvPoint2D32f bottomright; typedef struct CvSubdiv2D { CV_SUBDIV2D_FIELDS() } CvSubdiv2D; typedef enum CvSubdiv2DPointLocation { CV_PTLOC_ERROR = -2, CV_PTLOC_OUTSIDE_RECT = -1, CV_PTLOC_INSIDE = 0, CV_PTLOC_VERTEX = 1, CV_PTLOC_ON_EDGE = 2 } CvSubdiv2DPointLocation; typedef enum CvNextEdgeType { CV_NEXT_AROUND_ORG = 0x00, CV_NEXT_AROUND_DST = 0x22, CV_PREV_AROUND_ORG = 0x11, CV_PREV_AROUND_DST = 0x33, CV_NEXT_AROUND_LEFT = 0x13, CV_NEXT_AROUND_RIGHT = 0x31, CV_PREV_AROUND_LEFT = 0x20, CV_PREV_AROUND_RIGHT = 0x02 } CvNextEdgeType; /* get the next edge with the same origin point (counterwise) */ #define CV_SUBDIV2D_NEXT_EDGE( edge ) (((CvQuadEdge2D*)((edge) & ~3))->next[(edge)&3]) /* Initializes Delaunay triangulation */ CVAPI(void) cvInitSubdivDelaunay2D( CvSubdiv2D* subdiv, CvRect rect ); /* Creates new subdivision */ CVAPI(CvSubdiv2D*) cvCreateSubdiv2D( int subdiv_type, int header_size, int vtx_size, int quadedge_size, CvMemStorage* storage ); /************************* high-level subdivision functions ***************************/ /* Simplified Delaunay diagram creation */ CV_INLINE CvSubdiv2D* cvCreateSubdivDelaunay2D( CvRect rect, CvMemStorage* storage ) { CvSubdiv2D* subdiv = cvCreateSubdiv2D( CV_SEQ_KIND_SUBDIV2D, sizeof(*subdiv), sizeof(CvSubdiv2DPoint), sizeof(CvQuadEdge2D), storage ); cvInitSubdivDelaunay2D( subdiv, rect ); return subdiv; } /* Inserts new point to the Delaunay triangulation */ CVAPI(CvSubdiv2DPoint*) cvSubdivDelaunay2DInsert( CvSubdiv2D* subdiv, CvPoint2D32f pt); /* Locates a point within the Delaunay triangulation (finds the edge the point is left to or belongs to, or the triangulation point the given point coinsides with */ CVAPI(CvSubdiv2DPointLocation) cvSubdiv2DLocate( CvSubdiv2D* subdiv, CvPoint2D32f pt, CvSubdiv2DEdge* edge, CvSubdiv2DPoint** vertex CV_DEFAULT(NULL) ); /* Calculates Voronoi tesselation (i.e. coordinates of Voronoi points) */ CVAPI(void) cvCalcSubdivVoronoi2D( CvSubdiv2D* subdiv ); /* Removes all Voronoi points from the tesselation */ CVAPI(void) cvClearSubdivVoronoi2D( CvSubdiv2D* subdiv ); /* Finds the nearest to the given point vertex in subdivision. */ CVAPI(CvSubdiv2DPoint*) cvFindNearestPoint2D( CvSubdiv2D* subdiv, CvPoint2D32f pt ); /************ Basic quad-edge navigation and operations ************/ CV_INLINE CvSubdiv2DEdge cvSubdiv2DNextEdge( CvSubdiv2DEdge edge ) { return CV_SUBDIV2D_NEXT_EDGE(edge); } CV_INLINE CvSubdiv2DEdge cvSubdiv2DRotateEdge( CvSubdiv2DEdge edge, int rotate ) { return (edge & ~3) + ((edge + rotate) & 3); } CV_INLINE CvSubdiv2DEdge cvSubdiv2DSymEdge( CvSubdiv2DEdge edge ) { return edge ^ 2; } CV_INLINE CvSubdiv2DEdge cvSubdiv2DGetEdge( CvSubdiv2DEdge edge, CvNextEdgeType type ) { CvQuadEdge2D* e = (CvQuadEdge2D*)(edge & ~3); edge = e->next[(edge + (int)type) & 3]; return (edge & ~3) + ((edge + ((int)type >> 4)) & 3); } CV_INLINE CvSubdiv2DPoint* cvSubdiv2DEdgeOrg( CvSubdiv2DEdge edge ) { CvQuadEdge2D* e = (CvQuadEdge2D*)(edge & ~3); return (CvSubdiv2DPoint*)e->pt[edge & 3]; } CV_INLINE CvSubdiv2DPoint* cvSubdiv2DEdgeDst( CvSubdiv2DEdge edge ) { CvQuadEdge2D* e = (CvQuadEdge2D*)(edge & ~3); return (CvSubdiv2DPoint*)e->pt[(edge + 2) & 3]; } /****************************************************************************************\ * Additional operations on Subdivisions * \****************************************************************************************/ // paints voronoi diagram: just demo function CVAPI(void) icvDrawMosaic( CvSubdiv2D* subdiv, IplImage* src, IplImage* dst ); // checks planar subdivision for correctness. It is not an absolute check, // but it verifies some relations between quad-edges CVAPI(int) icvSubdiv2DCheck( CvSubdiv2D* subdiv ); // returns squared distance between two 2D points with floating-point coordinates. CV_INLINE double icvSqDist2D32f( CvPoint2D32f pt1, CvPoint2D32f pt2 ) { double dx = pt1.x - pt2.x; double dy = pt1.y - pt2.y; return dx*dx + dy*dy; } CV_INLINE double cvTriangleArea( CvPoint2D32f a, CvPoint2D32f b, CvPoint2D32f c ) { return ((double)b.x - a.x) * ((double)c.y - a.y) - ((double)b.y - a.y) * ((double)c.x - a.x); } /* Constructs kd-tree from set of feature descriptors */ CVAPI(struct CvFeatureTree*) cvCreateKDTree(CvMat* desc); /* Constructs spill-tree from set of feature descriptors */ CVAPI(struct CvFeatureTree*) cvCreateSpillTree( const CvMat* raw_data, const int naive CV_DEFAULT(50), const double rho CV_DEFAULT(.7), const double tau CV_DEFAULT(.1) ); /* Release feature tree */ CVAPI(void) cvReleaseFeatureTree(struct CvFeatureTree* tr); /* Searches feature tree for k nearest neighbors of given reference points, searching (in case of kd-tree/bbf) at most emax leaves. */ CVAPI(void) cvFindFeatures(struct CvFeatureTree* tr, const CvMat* query_points, CvMat* indices, CvMat* dist, int k, int emax CV_DEFAULT(20)); /* Search feature tree for all points that are inlier to given rect region. Only implemented for kd trees */ CVAPI(int) cvFindFeaturesBoxed(struct CvFeatureTree* tr, CvMat* bounds_min, CvMat* bounds_max, CvMat* out_indices); /* Construct a Locality Sensitive Hash (LSH) table, for indexing d-dimensional vectors of given type. Vectors will be hashed L times with k-dimensional p-stable (p=2) functions. */ CVAPI(struct CvLSH*) cvCreateLSH(struct CvLSHOperations* ops, int d, int L CV_DEFAULT(10), int k CV_DEFAULT(10), int type CV_DEFAULT(CV_64FC1), double r CV_DEFAULT(4), int64 seed CV_DEFAULT(-1)); /* Construct in-memory LSH table, with n bins. */ CVAPI(struct CvLSH*) cvCreateMemoryLSH(int d, int n, int L CV_DEFAULT(10), int k CV_DEFAULT(10), int type CV_DEFAULT(CV_64FC1), double r CV_DEFAULT(4), int64 seed CV_DEFAULT(-1)); /* Free the given LSH structure. */ CVAPI(void) cvReleaseLSH(struct CvLSH** lsh); /* Return the number of vectors in the LSH. */ CVAPI(unsigned int) LSHSize(struct CvLSH* lsh); /* Add vectors to the LSH structure, optionally returning indices. */ CVAPI(void) cvLSHAdd(struct CvLSH* lsh, const CvMat* data, CvMat* indices CV_DEFAULT(0)); /* Remove vectors from LSH, as addressed by given indices. */ CVAPI(void) cvLSHRemove(struct CvLSH* lsh, const CvMat* indices); /* Query the LSH n times for at most k nearest points; data is n x d, indices and dist are n x k. At most emax stored points will be accessed. */ CVAPI(void) cvLSHQuery(struct CvLSH* lsh, const CvMat* query_points, CvMat* indices, CvMat* dist, int k, int emax); /* Kolmogorov-Zabin stereo-correspondence algorithm (a.k.a. KZ1) */ #define CV_STEREO_GC_OCCLUDED SHRT_MAX typedef struct CvStereoGCState { int Ithreshold; int interactionRadius; float K, lambda, lambda1, lambda2; int occlusionCost; int minDisparity; int numberOfDisparities; int maxIters; CvMat* left; CvMat* right; CvMat* dispLeft; CvMat* dispRight; CvMat* ptrLeft; CvMat* ptrRight; CvMat* vtxBuf; CvMat* edgeBuf; } CvStereoGCState; CVAPI(CvStereoGCState*) cvCreateStereoGCState( int numberOfDisparities, int maxIters ); CVAPI(void) cvReleaseStereoGCState( CvStereoGCState** state ); CVAPI(void) cvFindStereoCorrespondenceGC( const CvArr* left, const CvArr* right, CvArr* disparityLeft, CvArr* disparityRight, CvStereoGCState* state, int useDisparityGuess CV_DEFAULT(0) ); /* Calculates optical flow for 2 images using classical Lucas & Kanade algorithm */ CVAPI(void) cvCalcOpticalFlowLK( const CvArr* prev, const CvArr* curr, CvSize win_size, CvArr* velx, CvArr* vely ); /* Calculates optical flow for 2 images using block matching algorithm */ CVAPI(void) cvCalcOpticalFlowBM( const CvArr* prev, const CvArr* curr, CvSize block_size, CvSize shift_size, CvSize max_range, int use_previous, CvArr* velx, CvArr* vely ); /* Calculates Optical flow for 2 images using Horn & Schunck algorithm */ CVAPI(void) cvCalcOpticalFlowHS( const CvArr* prev, const CvArr* curr, int use_previous, CvArr* velx, CvArr* vely, double lambda, CvTermCriteria criteria ); /****************************************************************************************\ * Background/foreground segmentation * \****************************************************************************************/ /* We discriminate between foreground and background pixels * by building and maintaining a model of the background. * Any pixel which does not fit this model is then deemed * to be foreground. * * At present we support two core background models, * one of which has two variations: * * o CV_BG_MODEL_FGD: latest and greatest algorithm, described in * * Foreground Object Detection from Videos Containing Complex Background. * Liyuan Li, Weimin Huang, Irene Y.H. Gu, and Qi Tian. * ACM MM2003 9p * * o CV_BG_MODEL_FGD_SIMPLE: * A code comment describes this as a simplified version of the above, * but the code is in fact currently identical * * o CV_BG_MODEL_MOG: "Mixture of Gaussians", older algorithm, described in * * Moving target classification and tracking from real-time video. * A Lipton, H Fujijoshi, R Patil * Proceedings IEEE Workshop on Application of Computer Vision pp 8-14 1998 * * Learning patterns of activity using real-time tracking * C Stauffer and W Grimson August 2000 * IEEE Transactions on Pattern Analysis and Machine Intelligence 22(8):747-757 */ #define CV_BG_MODEL_FGD 0 #define CV_BG_MODEL_MOG 1 /* "Mixture of Gaussians". */ #define CV_BG_MODEL_FGD_SIMPLE 2 struct CvBGStatModel; typedef void (CV_CDECL * CvReleaseBGStatModel)( struct CvBGStatModel** bg_model ); typedef int (CV_CDECL * CvUpdateBGStatModel)( IplImage* curr_frame, struct CvBGStatModel* bg_model, double learningRate ); #define CV_BG_STAT_MODEL_FIELDS() \ int type; /*type of BG model*/ \ CvReleaseBGStatModel release; \ CvUpdateBGStatModel update; \ IplImage* background; /*8UC3 reference background image*/ \ IplImage* foreground; /*8UC1 foreground image*/ \ IplImage** layers; /*8UC3 reference background image, can be null */ \ int layer_count; /* can be zero */ \ CvMemStorage* storage; /*storage for foreground_regions*/ \ CvSeq* foreground_regions /*foreground object contours*/ typedef struct CvBGStatModel { CV_BG_STAT_MODEL_FIELDS(); } CvBGStatModel; // // Releases memory used by BGStatModel CVAPI(void) cvReleaseBGStatModel( CvBGStatModel** bg_model ); // Updates statistical model and returns number of found foreground regions CVAPI(int) cvUpdateBGStatModel( IplImage* current_frame, CvBGStatModel* bg_model, double learningRate CV_DEFAULT(-1)); // Performs FG post-processing using segmentation // (all pixels of a region will be classified as foreground if majority of pixels of the region are FG). // parameters: // segments - pointer to result of segmentation (for example MeanShiftSegmentation) // bg_model - pointer to CvBGStatModel structure CVAPI(void) cvRefineForegroundMaskBySegm( CvSeq* segments, CvBGStatModel* bg_model ); /* Common use change detection function */ CVAPI(int) cvChangeDetection( IplImage* prev_frame, IplImage* curr_frame, IplImage* change_mask ); /* Interface of ACM MM2003 algorithm */ /* Default parameters of foreground detection algorithm: */ #define CV_BGFG_FGD_LC 128 #define CV_BGFG_FGD_N1C 15 #define CV_BGFG_FGD_N2C 25 #define CV_BGFG_FGD_LCC 64 #define CV_BGFG_FGD_N1CC 25 #define CV_BGFG_FGD_N2CC 40 /* Background reference image update parameter: */ #define CV_BGFG_FGD_ALPHA_1 0.1f /* stat model update parameter * 0.002f ~ 1K frame(~45sec), 0.005 ~ 18sec (if 25fps and absolutely static BG) */ #define CV_BGFG_FGD_ALPHA_2 0.005f /* start value for alpha parameter (to fast initiate statistic model) */ #define CV_BGFG_FGD_ALPHA_3 0.1f #define CV_BGFG_FGD_DELTA 2 #define CV_BGFG_FGD_T 0.9f #define CV_BGFG_FGD_MINAREA 15.f #define CV_BGFG_FGD_BG_UPDATE_TRESH 0.5f /* See the above-referenced Li/Huang/Gu/Tian paper * for a full description of these background-model * tuning parameters. * * Nomenclature: 'c' == "color", a three-component red/green/blue vector. * We use histograms of these to model the range of * colors we've seen at a given background pixel. * * 'cc' == "color co-occurrence", a six-component vector giving * RGB color for both this frame and preceding frame. * We use histograms of these to model the range of * color CHANGES we've seen at a given background pixel. */ typedef struct CvFGDStatModelParams { int Lc; /* Quantized levels per 'color' component. Power of two, typically 32, 64 or 128. */ int N1c; /* Number of color vectors used to model normal background color variation at a given pixel. */ int N2c; /* Number of color vectors retained at given pixel. Must be > N1c, typically ~ 5/3 of N1c. */ /* Used to allow the first N1c vectors to adapt over time to changing background. */ int Lcc; /* Quantized levels per 'color co-occurrence' component. Power of two, typically 16, 32 or 64. */ int N1cc; /* Number of color co-occurrence vectors used to model normal background color variation at a given pixel. */ int N2cc; /* Number of color co-occurrence vectors retained at given pixel. Must be > N1cc, typically ~ 5/3 of N1cc. */ /* Used to allow the first N1cc vectors to adapt over time to changing background. */ int is_obj_without_holes;/* If TRUE we ignore holes within foreground blobs. Defaults to TRUE. */ int perform_morphing; /* Number of erode-dilate-erode foreground-blob cleanup iterations. */ /* These erase one-pixel junk blobs and merge almost-touching blobs. Default value is 1. */ float alpha1; /* How quickly we forget old background pixel values seen. Typically set to 0.1 */ float alpha2; /* "Controls speed of feature learning". Depends on T. Typical value circa 0.005. */ float alpha3; /* Alternate to alpha2, used (e.g.) for quicker initial convergence. Typical value 0.1. */ float delta; /* Affects color and color co-occurrence quantization, typically set to 2. */ float T; /* "A percentage value which determines when new features can be recognized as new background." (Typically 0.9).*/ float minArea; /* Discard foreground blobs whose bounding box is smaller than this threshold. */ } CvFGDStatModelParams; typedef struct CvBGPixelCStatTable { float Pv, Pvb; uchar v[3]; } CvBGPixelCStatTable; typedef struct CvBGPixelCCStatTable { float Pv, Pvb; uchar v[6]; } CvBGPixelCCStatTable; typedef struct CvBGPixelStat { float Pbc; float Pbcc; CvBGPixelCStatTable* ctable; CvBGPixelCCStatTable* cctable; uchar is_trained_st_model; uchar is_trained_dyn_model; } CvBGPixelStat; typedef struct CvFGDStatModel { CV_BG_STAT_MODEL_FIELDS(); CvBGPixelStat* pixel_stat; IplImage* Ftd; IplImage* Fbd; IplImage* prev_frame; CvFGDStatModelParams params; } CvFGDStatModel; /* Creates FGD model */ CVAPI(CvBGStatModel*) cvCreateFGDStatModel( IplImage* first_frame, CvFGDStatModelParams* parameters CV_DEFAULT(NULL)); /* Interface of Gaussian mixture algorithm "An improved adaptive background mixture model for real-time tracking with shadow detection" P. KadewTraKuPong and R. Bowden, Proc. 2nd European Workshp on Advanced Video-Based Surveillance Systems, 2001." http://personal.ee.surrey.ac.uk/Personal/R.Bowden/publications/avbs01/avbs01.pdf */ /* Note: "MOG" == "Mixture Of Gaussians": */ #define CV_BGFG_MOG_MAX_NGAUSSIANS 500 /* default parameters of gaussian background detection algorithm */ #define CV_BGFG_MOG_BACKGROUND_THRESHOLD 0.7 /* threshold sum of weights for background test */ #define CV_BGFG_MOG_STD_THRESHOLD 2.5 /* lambda=2.5 is 99% */ #define CV_BGFG_MOG_WINDOW_SIZE 200 /* Learning rate; alpha = 1/CV_GBG_WINDOW_SIZE */ #define CV_BGFG_MOG_NGAUSSIANS 5 /* = K = number of Gaussians in mixture */ #define CV_BGFG_MOG_WEIGHT_INIT 0.05 #define CV_BGFG_MOG_SIGMA_INIT 30 #define CV_BGFG_MOG_MINAREA 15.f #define CV_BGFG_MOG_NCOLORS 3 typedef struct CvGaussBGStatModelParams { int win_size; /* = 1/alpha */ int n_gauss; double bg_threshold, std_threshold, minArea; double weight_init, variance_init; }CvGaussBGStatModelParams; typedef struct CvGaussBGValues { int match_sum; double weight; double variance[CV_BGFG_MOG_NCOLORS]; double mean[CV_BGFG_MOG_NCOLORS]; } CvGaussBGValues; typedef struct CvGaussBGPoint { CvGaussBGValues* g_values; } CvGaussBGPoint; typedef struct CvGaussBGModel { CV_BG_STAT_MODEL_FIELDS(); CvGaussBGStatModelParams params; CvGaussBGPoint* g_point; int countFrames; void* mog; } CvGaussBGModel; /* Creates Gaussian mixture background model */ CVAPI(CvBGStatModel*) cvCreateGaussianBGModel( IplImage* first_frame, CvGaussBGStatModelParams* parameters CV_DEFAULT(NULL)); typedef struct CvBGCodeBookElem { struct CvBGCodeBookElem* next; int tLastUpdate; int stale; uchar boxMin[3]; uchar boxMax[3]; uchar learnMin[3]; uchar learnMax[3]; } CvBGCodeBookElem; typedef struct CvBGCodeBookModel { CvSize size; int t; uchar cbBounds[3]; uchar modMin[3]; uchar modMax[3]; CvBGCodeBookElem** cbmap; CvMemStorage* storage; CvBGCodeBookElem* freeList; } CvBGCodeBookModel; CVAPI(CvBGCodeBookModel*) cvCreateBGCodeBookModel( void ); CVAPI(void) cvReleaseBGCodeBookModel( CvBGCodeBookModel** model ); CVAPI(void) cvBGCodeBookUpdate( CvBGCodeBookModel* model, const CvArr* image, CvRect roi CV_DEFAULT(cvRect(0,0,0,0)), const CvArr* mask CV_DEFAULT(0) ); CVAPI(int) cvBGCodeBookDiff( const CvBGCodeBookModel* model, const CvArr* image, CvArr* fgmask, CvRect roi CV_DEFAULT(cvRect(0,0,0,0)) ); CVAPI(void) cvBGCodeBookClearStale( CvBGCodeBookModel* model, int staleThresh, CvRect roi CV_DEFAULT(cvRect(0,0,0,0)), const CvArr* mask CV_DEFAULT(0) ); CVAPI(CvSeq*) cvSegmentFGMask( CvArr *fgmask, int poly1Hull0 CV_DEFAULT(1), float perimScale CV_DEFAULT(4.f), CvMemStorage* storage CV_DEFAULT(0), CvPoint offset CV_DEFAULT(cvPoint(0,0))); #ifdef __cplusplus } #endif #endif /* End of file. */