a LOT of obsolete stuff has been moved to the legacy module.
authorVadim Pisarevsky <no@email>
Fri, 30 Mar 2012 12:19:25 +0000 (12:19 +0000)
committerVadim Pisarevsky <no@email>
Fri, 30 Mar 2012 12:19:25 +0000 (12:19 +0000)
42 files changed:
modules/calib3d/include/opencv2/calib3d/calib3d.hpp
modules/calib3d/test/test_stereomatching.cpp
modules/contrib/src/spinimages.cpp
modules/features2d/test/test_nearestneighbors.cpp
modules/imgproc/include/opencv2/imgproc/imgproc.hpp
modules/imgproc/include/opencv2/imgproc/imgproc_c.h
modules/imgproc/src/_imgproc.h [deleted file]
modules/imgproc/src/geometry.cpp
modules/imgproc/src/subdivision2d.cpp
modules/legacy/doc/legacy.rst
modules/legacy/doc/motion_analysis.rst [new file with mode: 0644]
modules/legacy/include/opencv2/legacy/legacy.hpp
modules/legacy/src/_featuretree.h [moved from modules/imgproc/src/_featuretree.h with 100% similarity]
modules/legacy/src/_kdtree.hpp [moved from modules/imgproc/src/_kdtree.hpp with 100% similarity]
modules/legacy/src/bgfg_acmmm2003.cpp [moved from modules/video/src/bgfg_acmmm2003.cpp with 100% similarity]
modules/legacy/src/bgfg_codebook.cpp [moved from modules/video/src/bgfg_codebook.cpp with 100% similarity]
modules/legacy/src/bgfg_common.cpp [moved from modules/video/src/bgfg_common.cpp with 100% similarity]
modules/legacy/src/bgfg_gaussmix.cpp [new file with mode: 0644]
modules/legacy/src/featuretree.cpp [moved from modules/imgproc/src/featuretree.cpp with 100% similarity]
modules/legacy/src/kdtree.cpp [moved from modules/imgproc/src/kdtree.cpp with 100% similarity]
modules/legacy/src/lsh.cpp [moved from modules/imgproc/src/lsh.cpp with 100% similarity]
modules/legacy/src/optflowbm.cpp [moved from modules/video/src/optflowbm.cpp with 100% similarity]
modules/legacy/src/optflowhs.cpp [moved from modules/video/src/optflowhs.cpp with 100% similarity]
modules/legacy/src/optflowlk.cpp [moved from modules/video/src/optflowlk.cpp with 100% similarity]
modules/legacy/src/pyrsegmentation.cpp [moved from modules/imgproc/src/pyrsegmentation.cpp with 100% similarity]
modules/legacy/src/spilltree.cpp [moved from modules/imgproc/src/spilltree.cpp with 100% similarity]
modules/legacy/src/stereogc.cpp [moved from modules/calib3d/src/stereogc.cpp with 100% similarity]
modules/legacy/src/subdiv2.cpp
modules/legacy/test/test_nearestneighbors.cpp [new file with mode: 0644]
modules/legacy/test/test_optflow.cpp [moved from modules/video/test/test_optflow.cpp with 99% similarity]
modules/legacy/test/test_precomp.hpp
modules/legacy/test/test_pyrsegmentation.cpp [moved from modules/imgproc/test/test_pyrsegmentation.cpp with 100% similarity]
modules/legacy/test/test_stereomatching.cpp [new file with mode: 0644]
modules/legacy/test/test_subdivisions.cpp [moved from modules/imgproc/test/test_subdivisions.cpp with 100% similarity]
modules/objdetect/src/planardetect.cpp [deleted file]
modules/video/doc/motion_analysis_and_object_tracking.rst
modules/video/include/opencv2/video/background_segm.hpp
modules/video/include/opencv2/video/tracking.hpp
modules/video/src/bgfg_gaussmix.cpp
modules/video/src/bgfg_gaussmix2.cpp
samples/c/bgfg_codebook.cpp
samples/c/blobtrack_sample.cpp

index cbe1fe5..966fffe 100644 (file)
@@ -361,37 +361,6 @@ CVAPI(void) cvValidateDisparity( CvArr* disparity, const CvArr* cost,
                                  int minDisparity, int numberOfDisparities,
                                  int disp12MaxDiff CV_DEFAULT(1) );  
 
-/* 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) );
-
 /* Reprojects the computed disparity image to the 3D space using the specified 4x4 matrix */
 CVAPI(void)  cvReprojectImageTo3D( const CvArr* disparityImage,
                                    CvArr* _3dImage, const CvMat* Q,
index 649f79a..a2ba91f 100755 (executable)
@@ -706,73 +706,6 @@ protected:
     }
 };
 
-
-//----------------------------------- StereoGC test -----------------------------------------------------
-
-class CV_StereoGCTest : public CV_StereoMatchingTest
-{
-public:
-    CV_StereoGCTest()
-    {
-        name = "stereogc"; 
-        fill(rmsEps.begin(), rmsEps.end(), 3.f);
-        fracEps[0] = 0.05f; // all
-        fracEps[1] = 0.05f; // noOccl
-        fracEps[2] = 0.25f; // occl
-        fracEps[3] = 0.05f; // textured
-        fracEps[4] = 0.10f; // textureless
-        fracEps[5] = 0.10f; // borderedDepthDiscont
-    }
-protected:
-    struct RunParams
-    {
-        int ndisp;
-        int iterCount;
-    };
-    vector<RunParams> caseRunParams;
-
-    virtual int readRunParams( FileStorage& fs )
-    {
-        int code = CV_StereoMatchingTest::readRunParams(fs);
-        FileNode fn = fs.getFirstTopLevelNode();
-        assert(fn.isSeq());
-        for( int i = 0; i < (int)fn.size(); i+=4 )
-        {
-            string caseName = fn[i], datasetName = fn[i+1];
-            RunParams params;
-            string ndisp = fn[i+2]; params.ndisp = atoi(ndisp.c_str());
-            string iterCount = fn[i+3]; params.iterCount = atoi(iterCount.c_str());
-            caseNames.push_back( caseName );
-            caseDatasets.push_back( datasetName );
-            caseRunParams.push_back( params );
-        }
-        return code;
-    }
-
-    virtual int runStereoMatchingAlgorithm( const Mat& _leftImg, const Mat& _rightImg,
-                   Mat& leftDisp, Mat& rightDisp, int caseIdx )
-    {
-        RunParams params = caseRunParams[caseIdx];
-        assert( _leftImg.type() == CV_8UC3 && _rightImg.type() == CV_8UC3 );
-        Mat leftImg, rightImg, tmp;
-        cvtColor( _leftImg, leftImg, CV_BGR2GRAY );
-        cvtColor( _rightImg, rightImg, CV_BGR2GRAY );
-
-        leftDisp.create( leftImg.size(), CV_16SC1 );
-        rightDisp.create( rightImg.size(), CV_16SC1 );
-
-        CvMat _limg = leftImg, _rimg = rightImg, _ldisp = leftDisp, _rdisp = rightDisp;
-        CvStereoGCState *state = cvCreateStereoGCState( params.ndisp, params.iterCount );
-        cvFindStereoCorrespondenceGC( &_limg, &_rimg, &_ldisp, &_rdisp, state );
-        cvReleaseStereoGCState( &state );
-
-        leftDisp = - leftDisp;
-        return 0;
-    }
-
-};
-
-
 //----------------------------------- StereoSGBM test -----------------------------------------------------
 
 class CV_StereoSGBMTest : public CV_StereoMatchingTest
@@ -829,5 +762,4 @@ protected:
 
 
 TEST(Calib3d_StereoBM, regression) { CV_StereoBMTest test; test.safe_run(); }
-TEST(Calib3d_StereoGC, regression) { CV_StereoGCTest test; test.safe_run(); }
 TEST(Calib3d_StereoSGBM, regression) { CV_StereoSGBMTest test; test.safe_run(); }
index 6339684..62f21c6 100644 (file)
@@ -442,6 +442,7 @@ void cv::Mesh3D::clearOctree(){ octree = Octree(); }
 
 float cv::Mesh3D::estimateResolution(float tryRatio)
 {
+    #if 0
     const int neighbors = 3;
     const int minReasonable = 10;
 
@@ -475,8 +476,13 @@ float cv::Mesh3D::estimateResolution(float tryRatio)
     sort(dist, less<double>());
    
     return resolution = (float)dist[ dist.size() / 2 ];
+    #else
+    CV_Error(CV_StsNotImplemented, "");
+    return 1.f;
+    #endif
 }
 
+
 void cv::Mesh3D::computeNormals(float normalRadius, int minNeighbors)
 {
     buildOctree();
index 0a23c52..bdeb8fc 100644 (file)
@@ -156,109 +156,6 @@ void NearestNeighborTest::run( int /*start_from*/ ) {
 }
 
 //--------------------------------------------------------------------------------
-class CV_LSHTest : public NearestNeighborTest
-{
-public:
-    CV_LSHTest() {}
-protected:
-    virtual void createModel( const Mat& data );
-    virtual int findNeighbors( Mat& points, Mat& neighbors );
-    virtual void releaseModel();
-    struct CvLSH* lsh;
-    CvMat desc;
-};
-
-void CV_LSHTest::createModel( const Mat& data )
-{
-    desc = data;
-    lsh = cvCreateMemoryLSH( data.cols, data.rows, 70, 20, CV_32FC1 );
-    cvLSHAdd( lsh, &desc );
-}
-
-int CV_LSHTest::findNeighbors( Mat& points, Mat& neighbors )
-{
-    const int emax = 20;
-    Mat dist( points.rows, neighbors.cols, CV_64FC1);
-    CvMat _dist = dist, _points = points, _neighbors = neighbors;
-    cvLSHQuery( lsh, &_points, &_neighbors, &_dist, neighbors.cols, emax );
-    return cvtest::TS::OK;
-}
-
-void CV_LSHTest::releaseModel()
-{
-    cvReleaseLSH( &lsh );
-}
-
-//--------------------------------------------------------------------------------
-class CV_FeatureTreeTest_C : public NearestNeighborTest
-{
-public:
-    CV_FeatureTreeTest_C() {}
-protected:
-    virtual int findNeighbors( Mat& points, Mat& neighbors );
-    virtual void releaseModel();
-    CvFeatureTree* tr;
-    CvMat desc;
-};
-
-int CV_FeatureTreeTest_C::findNeighbors( Mat& points, Mat& neighbors )
-{
-    const int emax = 20;
-    Mat dist( points.rows, neighbors.cols, CV_64FC1);
-    CvMat _dist = dist, _points = points, _neighbors = neighbors;
-    cvFindFeatures( tr, &_points, &_neighbors, &_dist, neighbors.cols, emax );
-    return cvtest::TS::OK;
-}
-
-void CV_FeatureTreeTest_C::releaseModel()
-{
-    cvReleaseFeatureTree( tr );
-}
-
-//--------------------------------------
-class CV_SpillTreeTest_C : public CV_FeatureTreeTest_C
-{
-public:
-    CV_SpillTreeTest_C() {}
-protected:
-    virtual void createModel( const Mat& data );
-};
-
-void CV_SpillTreeTest_C::createModel( const Mat& data )
-{
-    desc = data;
-    tr = cvCreateSpillTree( &desc );
-}
-
-//--------------------------------------
-class CV_KDTreeTest_C : public CV_FeatureTreeTest_C
-{
-public:
-    CV_KDTreeTest_C() {}
-protected:
-    virtual void createModel( const Mat& data );
-    virtual int checkFindBoxed();
-};
-
-void CV_KDTreeTest_C::createModel( const Mat& data )
-{
-    desc = data;
-    tr = cvCreateKDTree( &desc );
-}
-
-int CV_KDTreeTest_C::checkFindBoxed()
-{
-    Mat min(1, dims, CV_32FC1 ), max(1, dims, CV_32FC1 ), indices( 1, 1, CV_32SC1 );
-    float l = minValue, r = maxValue;
-    min.setTo(Scalar(l)), max.setTo(Scalar(r));
-    CvMat _min = min, _max = max, _indices = indices;
-    // TODO check indices
-    if( cvFindFeaturesBoxed( tr, &_min, &_max, &_indices ) != featuresCount )
-        return cvtest::TS::FAIL_BAD_ACCURACY;
-    return cvtest::TS::OK;
-}
-
-//--------------------------------------------------------------------------------
 class CV_KDTreeTest_CPP : public NearestNeighborTest
 {
 public:
@@ -506,9 +403,6 @@ void CV_FlannSavedIndexTest::createModel(const cv::Mat &data)
     remove( filename.c_str() );
 }
 
-TEST(Features2d_LSH, regression) { CV_LSHTest test; test.safe_run(); }
-TEST(Features2d_SpillTree, regression) { CV_SpillTreeTest_C test; test.safe_run(); }
-TEST(Features2d_KDTree_C, regression) { CV_KDTreeTest_C test; test.safe_run(); }
 TEST(Features2d_KDTree_CPP, regression) { CV_KDTreeTest_CPP test; test.safe_run(); }
 TEST(Features2d_FLANN_Linear, regression) { CV_FlannLinearIndexTest test; test.safe_run(); }
 TEST(Features2d_FLANN_KMeans, regression) { CV_FlannKMeansIndexTest test; test.safe_run(); }
index 1be5cbf..0cc8bbe 100644 (file)
@@ -1142,27 +1142,6 @@ protected:
 
 }
 
-// 2009-01-12, Xavier Delacour <xavier.delacour@gmail.com>
-
-struct lsh_hash {
-  int h1, h2;
-};
-
-struct CvLSHOperations
-{
-  virtual ~CvLSHOperations() {}
-
-  virtual int vector_add(const void* data) = 0;
-  virtual void vector_remove(int i) = 0;
-  virtual const void* vector_lookup(int i) = 0;
-  virtual void vector_reserve(int n) = 0;
-  virtual unsigned int vector_count() = 0;
-
-  virtual void hash_insert(lsh_hash h, int l, int i) = 0;
-  virtual void hash_remove(lsh_hash h, int l, int i) = 0;
-  virtual int hash_lookup(lsh_hash h, int l, int* ret_i, int ret_i_max) = 0;
-};
-
 #endif /* __cplusplus */
 
 #endif
index 1bc8f2c..440490c 100644 (file)
@@ -121,15 +121,6 @@ CVAPI(CvMat**) cvCreatePyramid( const CvArr* img, int extra_layers, double rate,
 CVAPI(void)  cvReleasePyramid( CvMat*** pyramid, int extra_layers );
 
 
-/* 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 );
-
 /* Filters image using meanshift algorithm */
 CVAPI(void) cvPyrMeanShiftFiltering( const CvArr* src, CvArr* dst,
     double sp, double sr, int max_level CV_DEFAULT(1),
@@ -351,99 +342,6 @@ CVAPI(void) cvStartReadChainPoints( CvChain* chain, CvChainPtReader* reader );
 /* Retrieves the next chain point */
 CVAPI(CvPoint) cvReadChainPoint( CvChainPtReader* reader );
 
-/****************************************************************************************\
-*                              Planar subdivisions                                       *
-\****************************************************************************************/
-
-/* 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];
-}
-
-
-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);
-}
-
 
 /****************************************************************************************\
 *                            Contour Processing and Shape Analysis                       *
@@ -718,61 +616,6 @@ CVAPI(CvSeq*) cvHoughCircles( CvArr* image, void* circle_storage,
 CVAPI(void)  cvFitLine( const CvArr* points, int dist_type, double param,
                         double reps, double aeps, float* line );
 
-
-/* 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);
-
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/modules/imgproc/src/_imgproc.h b/modules/imgproc/src/_imgproc.h
deleted file mode 100644 (file)
index 9800a4e..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*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 _CV_IMG_PROC_H_
-#define _CV_IMG_PROC_H_
-
-
-
-#endif /*_CV_INTERNAL_H_*/
index 95aa540..8c82e64 100644 (file)
@@ -109,22 +109,6 @@ icvIntersectLines( double x1, double dx1, double y1, double dy1,
 
 
 void
-icvCreateCenterNormalLine( CvSubdiv2DEdge edge, double *_a, double *_b, double *_c )
-{
-    CvPoint2D32f org = cvSubdiv2DEdgeOrg( edge )->pt;
-    CvPoint2D32f dst = cvSubdiv2DEdgeDst( edge )->pt;
-
-    double a = dst.x - org.x;
-    double b = dst.y - org.y;
-    double c = -(a * (dst.x + org.x) + b * (dst.y + org.y));
-
-    *_a = a + a;
-    *_b = b + b;
-    *_c = c;
-}
-
-
-void
 icvIntersectLines3( double *a0, double *b0, double *c0,
                     double *a1, double *b1, double *c1, CvPoint2D32f * point )
 {
index 2331d6c..2cfc489 100644 (file)
 //M*/
 #include "precomp.hpp"
 
-CV_IMPL CvSubdiv2D *
-cvCreateSubdiv2D( int subdiv_type, int header_size,
-                  int vtx_size, int quadedge_size, CvMemStorage * storage )
-{
-    if( !storage )
-        CV_Error( CV_StsNullPtr, "" );
-
-    if( header_size < (int)sizeof( CvSubdiv2D ) ||
-        quadedge_size < (int)sizeof( CvQuadEdge2D ) ||
-        vtx_size < (int)sizeof( CvSubdiv2DPoint ))
-        CV_Error( CV_StsBadSize, "" );
-
-    return (CvSubdiv2D *)cvCreateGraph( subdiv_type, header_size,
-                                        vtx_size, quadedge_size, storage );
-}
-
-
-/****************************************************************************************\
-*                                    Quad Edge  algebra                                  *
-\****************************************************************************************/
-
-static CvSubdiv2DEdge
-cvSubdiv2DMakeEdge( CvSubdiv2D * subdiv )
-{
-    if( !subdiv )
-        CV_Error( CV_StsNullPtr, "" );
-
-    CvQuadEdge2D* edge = (CvQuadEdge2D*)cvSetNew( (CvSet*)subdiv->edges );
-    memset( edge->pt, 0, sizeof( edge->pt ));
-    CvSubdiv2DEdge edgehandle = (CvSubdiv2DEdge) edge;
-
-    edge->next[0] = edgehandle;
-    edge->next[1] = edgehandle + 3;
-    edge->next[2] = edgehandle + 2;
-    edge->next[3] = edgehandle + 1;
-
-    subdiv->quad_edges++;
-    return edgehandle;
-}
-
-
-static CvSubdiv2DPoint *
-cvSubdiv2DAddPoint( CvSubdiv2D * subdiv, CvPoint2D32f pt, int is_virtual )
-{
-    CvSubdiv2DPoint* subdiv_point = (CvSubdiv2DPoint*)cvSetNew( (CvSet*)subdiv );
-    if( subdiv_point )
-    {
-        memset( subdiv_point, 0, subdiv->elem_size );
-        subdiv_point->pt = pt;
-        subdiv_point->first = 0;
-        subdiv_point->flags |= is_virtual ? CV_SUBDIV2D_VIRTUAL_POINT_FLAG : 0;
-               subdiv_point->id = -1;
-    }
-
-    return subdiv_point;
-}
-
-
-static void
-cvSubdiv2DSplice( CvSubdiv2DEdge edgeA, CvSubdiv2DEdge edgeB )
-{
-    CvSubdiv2DEdge *a_next = &CV_SUBDIV2D_NEXT_EDGE( edgeA );
-    CvSubdiv2DEdge *b_next = &CV_SUBDIV2D_NEXT_EDGE( edgeB );
-    CvSubdiv2DEdge a_rot = cvSubdiv2DRotateEdge( *a_next, 1 );
-    CvSubdiv2DEdge b_rot = cvSubdiv2DRotateEdge( *b_next, 1 );
-    CvSubdiv2DEdge *a_rot_next = &CV_SUBDIV2D_NEXT_EDGE( a_rot );
-    CvSubdiv2DEdge *b_rot_next = &CV_SUBDIV2D_NEXT_EDGE( b_rot );
-    CvSubdiv2DEdge t;
-
-    CV_SWAP( *a_next, *b_next, t );
-    CV_SWAP( *a_rot_next, *b_rot_next, t );
-}
-
-
-static void
-cvSubdiv2DSetEdgePoints( CvSubdiv2DEdge edge,
-                         CvSubdiv2DPoint * org_pt, CvSubdiv2DPoint * dst_pt )
-{
-    CvQuadEdge2D *quadedge = (CvQuadEdge2D *) (edge & ~3);
-
-    if( !quadedge )
-        CV_Error( CV_StsNullPtr, "" );
-
-    quadedge->pt[edge & 3] = org_pt;
-    quadedge->pt[(edge + 2) & 3] = dst_pt;
-}
-
-
-static void
-cvSubdiv2DDeleteEdge( CvSubdiv2D * subdiv, CvSubdiv2DEdge edge )
-{
-    CvQuadEdge2D *quadedge = (CvQuadEdge2D *) (edge & ~3);
-
-    if( !subdiv || !quadedge )
-        CV_Error( CV_StsNullPtr, "" );
-
-    cvSubdiv2DSplice( edge, cvSubdiv2DGetEdge( edge, CV_PREV_AROUND_ORG ));
-
-    CvSubdiv2DEdge sym_edge = cvSubdiv2DSymEdge( edge );
-    cvSubdiv2DSplice( sym_edge, cvSubdiv2DGetEdge( sym_edge, CV_PREV_AROUND_ORG ));
-
-    cvSetRemoveByPtr( (CvSet*)(subdiv->edges), quadedge );
-    subdiv->quad_edges--;
-}
-
-
-static CvSubdiv2DEdge
-cvSubdiv2DConnectEdges( CvSubdiv2D * subdiv, CvSubdiv2DEdge edgeA, CvSubdiv2DEdge edgeB )
-{
-    if( !subdiv )
-        CV_Error( CV_StsNullPtr, "" );
-
-    CvSubdiv2DEdge new_edge = cvSubdiv2DMakeEdge( subdiv );
-
-    cvSubdiv2DSplice( new_edge, cvSubdiv2DGetEdge( edgeA, CV_NEXT_AROUND_LEFT ));
-    cvSubdiv2DSplice( cvSubdiv2DSymEdge( new_edge ), edgeB );
-
-    CvSubdiv2DPoint* dstA = cvSubdiv2DEdgeDst( edgeA );
-    CvSubdiv2DPoint* orgB = cvSubdiv2DEdgeOrg( edgeB );
-    cvSubdiv2DSetEdgePoints( new_edge, dstA, orgB );
-
-    return new_edge;
-}
-
-
-static void
-cvSubdiv2DSwapEdges( CvSubdiv2DEdge edge )
-{
-    CvSubdiv2DEdge sym_edge = cvSubdiv2DSymEdge( edge );
-    CvSubdiv2DEdge a = cvSubdiv2DGetEdge( edge, CV_PREV_AROUND_ORG );
-    CvSubdiv2DEdge b = cvSubdiv2DGetEdge( sym_edge, CV_PREV_AROUND_ORG );
-    CvSubdiv2DPoint *dstB, *dstA;
-
-    cvSubdiv2DSplice( edge, a );
-    cvSubdiv2DSplice( sym_edge, b );
-
-    dstA = cvSubdiv2DEdgeDst( a );
-    dstB = cvSubdiv2DEdgeDst( b );
-    cvSubdiv2DSetEdgePoints( edge, dstA, dstB );
-
-    cvSubdiv2DSplice( edge, cvSubdiv2DGetEdge( a, CV_NEXT_AROUND_LEFT ));
-    cvSubdiv2DSplice( sym_edge, cvSubdiv2DGetEdge( b, CV_NEXT_AROUND_LEFT ));
-}
-
-
-static int
-icvIsRightOf( CvPoint2D32f& pt, CvSubdiv2DEdge edge )
-{
-    CvSubdiv2DPoint *org = cvSubdiv2DEdgeOrg(edge), *dst = cvSubdiv2DEdgeDst(edge);
-    double cw_area = cvTriangleArea( pt, dst->pt, org->pt );
-
-    return (cw_area > 0) - (cw_area < 0);
-}
-
-
-CV_IMPL CvSubdiv2DPointLocation
-cvSubdiv2DLocate( CvSubdiv2D * subdiv, CvPoint2D32f pt,
-                  CvSubdiv2DEdge * _edge, CvSubdiv2DPoint ** _point )
-{
-    CvSubdiv2DPoint *point = 0;
-    int right_of_curr = 0;
-
-    if( !subdiv )
-        CV_Error( CV_StsNullPtr, "" );
-
-    if( !CV_IS_SUBDIV2D(subdiv) )
-        CV_Error( CV_StsBadFlag, "" );
-
-    int i, max_edges = subdiv->quad_edges * 4;
-    CvSubdiv2DEdge edge = subdiv->recent_edge;
-
-    if( max_edges == 0 )
-        CV_Error( CV_StsBadSize, "" );
-    CV_Assert(edge != 0);
-
-    if( pt.x < subdiv->topleft.x || pt.y < subdiv->topleft.y ||
-        pt.x >= subdiv->bottomright.x || pt.y >= subdiv->bottomright.y )
-        CV_Error( CV_StsOutOfRange, "" );
-
-    CvSubdiv2DPointLocation location = CV_PTLOC_ERROR;
-
-    right_of_curr = icvIsRightOf( pt, edge );
-    if( right_of_curr > 0 )
-    {
-        edge = cvSubdiv2DSymEdge( edge );
-        right_of_curr = -right_of_curr;
-    }
-
-    for( i = 0; i < max_edges; i++ )
-    {
-        CvSubdiv2DEdge onext_edge = cvSubdiv2DNextEdge( edge );
-        CvSubdiv2DEdge dprev_edge = cvSubdiv2DGetEdge( edge, CV_PREV_AROUND_DST );
-
-        int right_of_onext = icvIsRightOf( pt, onext_edge );
-        int right_of_dprev = icvIsRightOf( pt, dprev_edge );
-
-        if( right_of_dprev > 0 )
-        {
-            if( right_of_onext > 0 || (right_of_onext == 0 && right_of_curr == 0) )
-            {
-                location = CV_PTLOC_INSIDE;
-                goto exit;
-            }
-            else
-            {
-                right_of_curr = right_of_onext;
-                edge = onext_edge;
-            }
-        }
-        else
-        {
-            if( right_of_onext > 0 )
-            {
-                if( right_of_dprev == 0 && right_of_curr == 0 )
-                {
-                    location = CV_PTLOC_INSIDE;
-                    goto exit;
-                }
-                else
-                {
-                    right_of_curr = right_of_dprev;
-                    edge = dprev_edge;
-                }
-            }
-            else if( right_of_curr == 0 &&
-                     icvIsRightOf( cvSubdiv2DEdgeDst( onext_edge )->pt, edge ) >= 0 )
-            {
-                edge = cvSubdiv2DSymEdge( edge );
-            }
-            else
-            {
-                right_of_curr = right_of_onext;
-                edge = onext_edge;
-            }
-        }
-    }
-exit:
-    
-    subdiv->recent_edge = edge;
-
-    if( location == CV_PTLOC_INSIDE )
-    {
-        double t1, t2, t3;
-        CvPoint2D32f org_pt = cvSubdiv2DEdgeOrg( edge )->pt;
-        CvPoint2D32f dst_pt = cvSubdiv2DEdgeDst( edge )->pt;
-
-        t1 = fabs( pt.x - org_pt.x );
-        t1 += fabs( pt.y - org_pt.y );
-        t2 = fabs( pt.x - dst_pt.x );
-        t2 += fabs( pt.y - dst_pt.y );
-        t3 = fabs( org_pt.x - dst_pt.x );
-        t3 += fabs( org_pt.y - dst_pt.y );
-
-        if( t1 < FLT_EPSILON )
-        {
-            location = CV_PTLOC_VERTEX;
-            point = cvSubdiv2DEdgeOrg( edge );
-            edge = 0;
-        }
-        else if( t2 < FLT_EPSILON )
-        {
-            location = CV_PTLOC_VERTEX;
-            point = cvSubdiv2DEdgeDst( edge );
-            edge = 0;
-        }
-        else if( (t1 < t3 || t2 < t3) &&
-                 fabs( cvTriangleArea( pt, org_pt, dst_pt )) < FLT_EPSILON )
-        {
-            location = CV_PTLOC_ON_EDGE;
-            point = 0;
-        }
-    }
-
-    if( location == CV_PTLOC_ERROR )
-    {
-        edge = 0;
-        point = 0;
-    }
-
-    if( _edge )
-        *_edge = edge;
-    if( _point )
-        *_point = point;
-
-    return location;
-}
-
-
-CV_INLINE int
-icvIsPtInCircle3( CvPoint2D32f pt, CvPoint2D32f a, CvPoint2D32f b, CvPoint2D32f c )
-{
-    const double eps = FLT_EPSILON*0.125;
-    double val = ((double)a.x * a.x + (double)a.y * a.y) * cvTriangleArea( b, c, pt );
-    val -= ((double)b.x * b.x + (double)b.y * b.y) * cvTriangleArea( a, c, pt );
-    val += ((double)c.x * c.x + (double)c.y * c.y) * cvTriangleArea( a, b, pt );
-    val -= ((double)pt.x * pt.x + (double)pt.y * pt.y) * cvTriangleArea( a, b, c );
-
-    return val > eps ? 1 : val < -eps ? -1 : 0;
-}
-
-
-CV_IMPL CvSubdiv2DPoint *
-cvSubdivDelaunay2DInsert( CvSubdiv2D * subdiv, CvPoint2D32f pt )
-{
-    CvSubdiv2DPointLocation location = CV_PTLOC_ERROR;
-
-    CvSubdiv2DPoint *curr_point = 0, *first_point = 0;
-    CvSubdiv2DEdge curr_edge = 0, deleted_edge = 0, base_edge = 0;
-    int i, max_edges;
-
-    if( !subdiv )
-        CV_Error( CV_StsNullPtr, "" );
-
-    if( !CV_IS_SUBDIV2D(subdiv) )
-        CV_Error( CV_StsBadFlag, "" );
-
-    location = cvSubdiv2DLocate( subdiv, pt, &curr_edge, &curr_point );
-
-    switch (location)
-    {
-    case CV_PTLOC_ERROR:
-        CV_Error( CV_StsBadSize, "" );
-
-    case CV_PTLOC_OUTSIDE_RECT:
-        CV_Error( CV_StsOutOfRange, "" );
-
-    case CV_PTLOC_VERTEX:
-        break;
-
-    case CV_PTLOC_ON_EDGE:
-        deleted_edge = curr_edge;
-        subdiv->recent_edge = curr_edge = cvSubdiv2DGetEdge( curr_edge, CV_PREV_AROUND_ORG );
-        cvSubdiv2DDeleteEdge( subdiv, deleted_edge );
-        /* no break */
-
-    case CV_PTLOC_INSIDE:
-
-        assert( curr_edge != 0 );
-        subdiv->is_geometry_valid = 0;
-
-        curr_point = cvSubdiv2DAddPoint( subdiv, pt, 0 );
-        base_edge = cvSubdiv2DMakeEdge( subdiv );
-        first_point = cvSubdiv2DEdgeOrg( curr_edge );
-        cvSubdiv2DSetEdgePoints( base_edge, first_point, curr_point );
-        cvSubdiv2DSplice( base_edge, curr_edge );
-
-        do
-        {
-            base_edge = cvSubdiv2DConnectEdges( subdiv, curr_edge,
-                                                cvSubdiv2DSymEdge( base_edge ));
-            curr_edge = cvSubdiv2DGetEdge( base_edge, CV_PREV_AROUND_ORG );
-        }
-        while( cvSubdiv2DEdgeDst( curr_edge ) != first_point );
-
-        curr_edge = cvSubdiv2DGetEdge( base_edge, CV_PREV_AROUND_ORG );
-
-        max_edges = subdiv->quad_edges * 4;
-
-        for( i = 0; i < max_edges; i++ )
-        {
-            CvSubdiv2DPoint *temp_dst = 0, *curr_org = 0, *curr_dst = 0;
-            CvSubdiv2DEdge temp_edge = cvSubdiv2DGetEdge( curr_edge, CV_PREV_AROUND_ORG );
-
-            temp_dst = cvSubdiv2DEdgeDst( temp_edge );
-            curr_org = cvSubdiv2DEdgeOrg( curr_edge );
-            curr_dst = cvSubdiv2DEdgeDst( curr_edge );
-
-            if( icvIsRightOf( temp_dst->pt, curr_edge ) > 0 &&
-                icvIsPtInCircle3( curr_org->pt, temp_dst->pt,
-                                  curr_dst->pt, curr_point->pt ) < 0 )
-            {
-                cvSubdiv2DSwapEdges( curr_edge );
-                curr_edge = cvSubdiv2DGetEdge( curr_edge, CV_PREV_AROUND_ORG );
-            }
-            else if( curr_org == first_point )
-            {
-                break;
-            }
-            else
-            {
-                curr_edge = cvSubdiv2DGetEdge( cvSubdiv2DNextEdge( curr_edge ),
-                                               CV_PREV_AROUND_LEFT );
-            }
-        }
-        break;
-    default:
-        CV_Error_(CV_StsError, ("cvSubdiv2DLocate returned invalid location = %d", location) );
-    }
-
-    return curr_point;
-}
-
-
-CV_IMPL void
-cvInitSubdivDelaunay2D( CvSubdiv2D * subdiv, CvRect rect )
-{
-    float big_coord = 3.f * MAX( rect.width, rect.height );
-    CvPoint2D32f ppA, ppB, ppC;
-    CvSubdiv2DPoint *pA, *pB, *pC;
-    CvSubdiv2DEdge edge_AB, edge_BC, edge_CA;
-    float rx = (float) rect.x;
-    float ry = (float) rect.y;
-
-    if( !subdiv )
-        CV_Error( CV_StsNullPtr, "" );
-
-    cvClearSet( (CvSet *) (subdiv->edges) );
-    cvClearSet( (CvSet *) subdiv );
-
-    subdiv->quad_edges = 0;
-    subdiv->recent_edge = 0;
-    subdiv->is_geometry_valid = 0;
-
-    subdiv->topleft = cvPoint2D32f( rx, ry );
-    subdiv->bottomright = cvPoint2D32f( rx + rect.width, ry + rect.height );
-
-    ppA = cvPoint2D32f( rx + big_coord, ry );
-    ppB = cvPoint2D32f( rx, ry + big_coord );
-    ppC = cvPoint2D32f( rx - big_coord, ry - big_coord );
-
-    pA = cvSubdiv2DAddPoint( subdiv, ppA, 0 );
-    pB = cvSubdiv2DAddPoint( subdiv, ppB, 0 );
-    pC = cvSubdiv2DAddPoint( subdiv, ppC, 0 );
-
-    edge_AB = cvSubdiv2DMakeEdge( subdiv );
-    edge_BC = cvSubdiv2DMakeEdge( subdiv );
-    edge_CA = cvSubdiv2DMakeEdge( subdiv );
-
-    cvSubdiv2DSetEdgePoints( edge_AB, pA, pB );
-    cvSubdiv2DSetEdgePoints( edge_BC, pB, pC );
-    cvSubdiv2DSetEdgePoints( edge_CA, pC, pA );
-
-    cvSubdiv2DSplice( edge_AB, cvSubdiv2DSymEdge( edge_CA ));
-    cvSubdiv2DSplice( edge_BC, cvSubdiv2DSymEdge( edge_AB ));
-    cvSubdiv2DSplice( edge_CA, cvSubdiv2DSymEdge( edge_BC ));
-
-    subdiv->recent_edge = edge_AB;
-}
-
-
-CV_IMPL void
-cvClearSubdivVoronoi2D( CvSubdiv2D * subdiv )
-{
-    int elem_size;
-    int i, total;
-    CvSeqReader reader;
-
-    if( !subdiv )
-        CV_Error( CV_StsNullPtr, "" );
-
-    /* clear pointers to voronoi points */
-    total = subdiv->edges->total;
-    elem_size = subdiv->edges->elem_size;
-
-    cvStartReadSeq( (CvSeq *) (subdiv->edges), &reader, 0 );
-
-    for( i = 0; i < total; i++ )
-    {
-        CvQuadEdge2D *quadedge = (CvQuadEdge2D *) reader.ptr;
-
-        quadedge->pt[1] = quadedge->pt[3] = 0;
-        CV_NEXT_SEQ_ELEM( elem_size, reader );
-    }
-
-    /* remove voronoi points */
-    total = subdiv->total;
-    elem_size = subdiv->elem_size;
-
-    cvStartReadSeq( (CvSeq *) subdiv, &reader, 0 );
-
-    for( i = 0; i < total; i++ )
-    {
-        CvSubdiv2DPoint *pt = (CvSubdiv2DPoint *) reader.ptr;
-
-        /* check for virtual point. it is also check that the point exists */
-        if( pt->flags & CV_SUBDIV2D_VIRTUAL_POINT_FLAG )
-        {
-            cvSetRemoveByPtr( (CvSet*)subdiv, pt );
-        }
-        CV_NEXT_SEQ_ELEM( elem_size, reader );
-    }
-
-    subdiv->is_geometry_valid = 0;
-}
-
-
-CV_IMPL void
-cvCalcSubdivVoronoi2D( CvSubdiv2D * subdiv )
-{
-    CvSeqReader reader;
-    int i, total, elem_size;
-
-    if( !subdiv )
-        CV_Error( CV_StsNullPtr, "" );
-
-    /* check if it is already calculated */
-    if( subdiv->is_geometry_valid )
-        return;
-
-    total = subdiv->edges->total;
-    elem_size = subdiv->edges->elem_size;
-
-    cvClearSubdivVoronoi2D( subdiv );
-
-    cvStartReadSeq( (CvSeq *) (subdiv->edges), &reader, 0 );
-
-    if( total <= 3 )
-        return;
-
-    /* skip first three edges (bounding triangle) */
-    for( i = 0; i < 3; i++ )
-        CV_NEXT_SEQ_ELEM( elem_size, reader );
-
-    /* loop through all quad-edges */
-    for( ; i < total; i++ )
-    {
-        CvQuadEdge2D *quadedge = (CvQuadEdge2D *) (reader.ptr);
-
-        if( CV_IS_SET_ELEM( quadedge ))
-        {
-            CvSubdiv2DEdge edge0 = (CvSubdiv2DEdge) quadedge, edge1, edge2;
-            double a0, b0, c0, a1, b1, c1;
-            CvPoint2D32f virt_point;
-            CvSubdiv2DPoint *voronoi_point;
-
-            if( !quadedge->pt[3] )
-            {
-                edge1 = cvSubdiv2DGetEdge( edge0, CV_NEXT_AROUND_LEFT );
-                edge2 = cvSubdiv2DGetEdge( edge1, CV_NEXT_AROUND_LEFT );
-
-                icvCreateCenterNormalLine( edge0, &a0, &b0, &c0 );
-                icvCreateCenterNormalLine( edge1, &a1, &b1, &c1 );
-
-                icvIntersectLines3( &a0, &b0, &c0, &a1, &b1, &c1, &virt_point );
-                if( fabs( virt_point.x ) < FLT_MAX * 0.5 &&
-                    fabs( virt_point.y ) < FLT_MAX * 0.5 )
-                {
-                    voronoi_point = cvSubdiv2DAddPoint( subdiv, virt_point, 1 );
-
-                    quadedge->pt[3] =
-                        ((CvQuadEdge2D *) (edge1 & ~3))->pt[3 - (edge1 & 2)] =
-                        ((CvQuadEdge2D *) (edge2 & ~3))->pt[3 - (edge2 & 2)] = voronoi_point;
-                }
-            }
-
-            if( !quadedge->pt[1] )
-            {
-                edge1 = cvSubdiv2DGetEdge( edge0, CV_NEXT_AROUND_RIGHT );
-                edge2 = cvSubdiv2DGetEdge( edge1, CV_NEXT_AROUND_RIGHT );
-
-                icvCreateCenterNormalLine( edge0, &a0, &b0, &c0 );
-                icvCreateCenterNormalLine( edge1, &a1, &b1, &c1 );
-
-                icvIntersectLines3( &a0, &b0, &c0, &a1, &b1, &c1, &virt_point );
-
-                if( fabs( virt_point.x ) < FLT_MAX * 0.5 &&
-                    fabs( virt_point.y ) < FLT_MAX * 0.5 )
-                {
-                    voronoi_point = cvSubdiv2DAddPoint( subdiv, virt_point, 1 );
-
-                    quadedge->pt[1] =
-                        ((CvQuadEdge2D *) (edge1 & ~3))->pt[1 + (edge1 & 2)] =
-                        ((CvQuadEdge2D *) (edge2 & ~3))->pt[1 + (edge2 & 2)] = voronoi_point;
-                }
-            }
-        }
-
-        CV_NEXT_SEQ_ELEM( elem_size, reader );
-    }
-
-    subdiv->is_geometry_valid = 1;
-}
-
-
-static int
-icvIsRightOf2( const CvPoint2D32f& pt, const CvPoint2D32f& org, const CvPoint2D32f& diff )
-{
-    double cw_area = ((double)org.x - pt.x)*diff.y - ((double)org.y - pt.y)*diff.x;
-    return (cw_area > 0) - (cw_area < 0);
-}
-
-
-CV_IMPL CvSubdiv2DPoint*
-cvFindNearestPoint2D( CvSubdiv2D* subdiv, CvPoint2D32f pt )
-{
-    CvSubdiv2DPoint* point = 0;
-    CvPoint2D32f start;
-    CvPoint2D32f diff;
-    CvSubdiv2DPointLocation loc;
-    CvSubdiv2DEdge edge; 
-    int i;
-    
-    if( !subdiv )
-        CV_Error( CV_StsNullPtr, "" );
-
-    if( !CV_IS_SUBDIV2D( subdiv ))
-        CV_Error( CV_StsNullPtr, "" );
-    
-    if( subdiv->edges->active_count <= 3 )
-        return 0;
-
-    if( !subdiv->is_geometry_valid )
-        cvCalcSubdivVoronoi2D( subdiv );
-
-    loc = cvSubdiv2DLocate( subdiv, pt, &edge, &point );
-
-    switch( loc )
-    {
-    case CV_PTLOC_ON_EDGE:
-    case CV_PTLOC_INSIDE:
-        break;
-    default:
-        return point;
-    }
-
-    point = 0;
-
-    start = cvSubdiv2DEdgeOrg( edge )->pt;
-    diff.x = pt.x - start.x;
-    diff.y = pt.y - start.y;
-
-    edge = cvSubdiv2DRotateEdge( edge, 1 );
-
-    for( i = 0; i < subdiv->total; i++ )
-    {
-        CvPoint2D32f t;
-        
-        for(;;)
-        {
-            assert( cvSubdiv2DEdgeDst( edge ));
-            
-            t = cvSubdiv2DEdgeDst( edge )->pt;
-            if( icvIsRightOf2( t, start, diff ) >= 0 )
-                break;
-
-            edge = cvSubdiv2DGetEdge( edge, CV_NEXT_AROUND_LEFT );
-        }
-
-        for(;;)
-        {
-            assert( cvSubdiv2DEdgeOrg( edge ));
-
-            t = cvSubdiv2DEdgeOrg( edge )->pt;
-            if( icvIsRightOf2( t, start, diff ) < 0 )
-                break;
-
-            edge = cvSubdiv2DGetEdge( edge, CV_PREV_AROUND_LEFT );
-        }
-
-        {
-            CvPoint2D32f tempDiff = cvSubdiv2DEdgeDst( edge )->pt;
-            t = cvSubdiv2DEdgeOrg( edge )->pt;
-            tempDiff.x -= t.x;
-            tempDiff.y -= t.y;
-
-            if( icvIsRightOf2( pt, t, tempDiff ) >= 0 )
-            {
-                point = cvSubdiv2DEdgeOrg( cvSubdiv2DRotateEdge( edge, 3 ));
-                break;
-            }
-        }
-
-        edge = cvSubdiv2DSymEdge( edge );
-    }
-
-    return point;
-}
-
-
 namespace cv
 {
     
@@ -879,17 +210,21 @@ void Subdiv2D::swapEdges( int edge )
     splice(sedge, getEdge(b, NEXT_AROUND_LEFT));
 }
 
+static double triangleArea( Point2f a, Point2f b, Point2f c )
+{
+    return ((double)b.x - a.x) * ((double)c.y - a.y) - ((double)b.y - a.y) * ((double)c.x - a.x);
+} 
+    
 int Subdiv2D::isRightOf(Point2f pt, int edge) const
 {
     Point2f org, dst;
     edgeOrg(edge, &org);
     edgeDst(edge, &dst);
-    double cw_area = cvTriangleArea( pt, dst, org );
+    double cw_area = triangleArea( pt, dst, org );
     
     return (cw_area > 0) - (cw_area < 0);
 }
 
-
 int Subdiv2D::newEdge()
 {
     if( freeQEdge <= 0 )
@@ -1039,7 +374,7 @@ int Subdiv2D::locate(Point2f pt, int& _edge, int& _vertex)
             edge = 0;
         }
         else if( (t1 < t3 || t2 < t3) &&
-                fabs( cvTriangleArea( pt, org_pt, dst_pt )) < FLT_EPSILON )
+                fabs( triangleArea( pt, org_pt, dst_pt )) < FLT_EPSILON )
         {
             location = PTLOC_ON_EDGE;
             vertex = 0;
@@ -1063,10 +398,10 @@ inline int
 isPtInCircle3( Point2f pt, Point2f a, Point2f b, Point2f c)
 {
     const double eps = FLT_EPSILON*0.125;
-    double val = ((double)a.x * a.x + (double)a.y * a.y) * cvTriangleArea( b, c, pt );
-    val -= ((double)b.x * b.x + (double)b.y * b.y) * cvTriangleArea( a, c, pt );
-    val += ((double)c.x * c.x + (double)c.y * c.y) * cvTriangleArea( a, b, pt );
-    val -= ((double)pt.x * pt.x + (double)pt.y * pt.y) * cvTriangleArea( a, b, c );
+    double val = ((double)a.x * a.x + (double)a.y * a.y) * triangleArea( b, c, pt );
+    val -= ((double)b.x * b.x + (double)b.y * b.y) * triangleArea( a, c, pt );
+    val += ((double)c.x * c.x + (double)c.y * c.y) * triangleArea( a, b, pt );
+    val -= ((double)pt.x * pt.x + (double)pt.y * pt.y) * triangleArea( a, b, c );
     
     return val > eps ? 1 : val < -eps ? -1 : 0;
 }
index 3692abf..12cfdb8 100644 (file)
@@ -6,3 +6,5 @@ legacy. Deprecated stuff
 
 .. toctree::
     :maxdepth: 2
+
+    motion_analysis
diff --git a/modules/legacy/doc/motion_analysis.rst b/modules/legacy/doc/motion_analysis.rst
new file mode 100644 (file)
index 0000000..b4f9da2
--- /dev/null
@@ -0,0 +1,88 @@
+Motion Analysis
+===============
+
+.. highlight:: cpp
+
+
+CalcOpticalFlowBM
+-----------------
+Calculates the optical flow for two images by using the block matching method.
+
+.. ocv:cfunction:: void cvCalcOpticalFlowBM( const CvArr* prev, const CvArr* curr, CvSize blockSize, CvSize shiftSize, CvSize maxRange, int usePrevious, CvArr* velx, CvArr* vely )
+
+.. ocv:pyoldfunction:: cv.CalcOpticalFlowBM(prev, curr, blockSize, shiftSize, maxRange, usePrevious, velx, vely)-> None
+
+        :param prev: First image, 8-bit, single-channel 
+
+        :param curr: Second image, 8-bit, single-channel 
+
+        :param blockSize: Size of basic blocks that are compared 
+
+        :param shiftSize: Block coordinate increments 
+
+        :param maxRange: Size of the scanned neighborhood in pixels around the block 
+
+        :param usePrevious: Flag that specifies whether to use the input velocity as initial approximations or not.
+
+        :param velx: Horizontal component of the optical flow of
+
+            .. math::
+
+                \left \lfloor   \frac{\texttt{prev->width} - \texttt{blockSize.width}}{\texttt{shiftSize.width}}   \right \rfloor \times \left \lfloor   \frac{\texttt{prev->height} - \texttt{blockSize.height}}{\texttt{shiftSize.height}}   \right \rfloor 
+
+            size, 32-bit floating-point, single-channel 
+
+        :param vely: Vertical component of the optical flow of the same size  ``velx`` , 32-bit floating-point, single-channel 
+
+
+The function calculates the optical flow for overlapped blocks ``blockSize.width x blockSize.height`` pixels each, thus the velocity fields are smaller than the original images. For every block in  ``prev``
+the functions tries to find a similar block in ``curr`` in some neighborhood of the original block or shifted by ``(velx(x0,y0), vely(x0,y0))`` block as has been calculated by previous function call (if ``usePrevious=1``)
+
+
+CalcOpticalFlowHS
+-----------------
+Calculates the optical flow for two images using Horn-Schunck algorithm.
+
+.. ocv:cfunction:: void cvCalcOpticalFlowHS(const CvArr* prev, const CvArr* curr, int usePrevious, CvArr* velx, CvArr* vely, double lambda, CvTermCriteria criteria)
+
+.. ocv:pyoldfunction:: cv.CalcOpticalFlowHS(prev, curr, usePrevious, velx, vely, lambda, criteria)-> None
+
+    :param prev: First image, 8-bit, single-channel 
+
+    :param curr: Second image, 8-bit, single-channel 
+
+    :param usePrevious: Flag that specifies whether to use the input velocity as initial approximations or not.
+
+    :param velx: Horizontal component of the optical flow of the same size as input images, 32-bit floating-point, single-channel 
+
+    :param vely: Vertical component of the optical flow of the same size as input images, 32-bit floating-point, single-channel 
+
+    :param lambda: Smoothness weight. The larger it is, the smoother optical flow map you get.
+
+    :param criteria: Criteria of termination of velocity computing 
+
+The function computes the flow for every pixel of the first input image using the Horn and Schunck algorithm [Horn81]_. The function is obsolete. To track sparse features, use :ocv:func:`calcOpticalFlowPyrLK`. To track all the pixels, use :ocv:func:`calcOpticalFlowFarneback`.
+
+
+CalcOpticalFlowLK
+-----------------
+
+Calculates the optical flow for two images using Lucas-Kanade algorithm.
+
+.. ocv:cfunction:: void cvCalcOpticalFlowLK( const CvArr* prev, const CvArr* curr, CvSize winSize, CvArr* velx, CvArr* vely )
+
+.. ocv:pyoldfunction:: cv.CalcOpticalFlowLK(prev, curr, winSize, velx, vely)-> None
+
+    :param prev: First image, 8-bit, single-channel 
+
+    :param curr: Second image, 8-bit, single-channel 
+
+    :param winSize: Size of the averaging window used for grouping pixels 
+
+    :param velx: Horizontal component of the optical flow of the same size as input images, 32-bit floating-point, single-channel 
+
+    :param vely: Vertical component of the optical flow of the same size as input images, 32-bit floating-point, single-channel 
+
+The function computes the flow for every pixel of the first input image using the Lucas and Kanade algorithm [Lucas81]_. The function is obsolete. To track sparse features, use :ocv:func:`calcOpticalFlowPyrLK`. To track all the pixels, use :ocv:func:`calcOpticalFlowFarneback`.
+
+
index c0d1872..8eec455 100644 (file)
@@ -2797,8 +2797,529 @@ protected:
     
 }
 
+// 2009-01-12, Xavier Delacour <xavier.delacour@gmail.com>
 
-//#include "cvvidsurv.hpp"
+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                                       *
+\****************************************************************************************/
+
+/* 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];
+}
+
+
+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;
+} 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();
+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
diff --git a/modules/legacy/src/bgfg_gaussmix.cpp b/modules/legacy/src/bgfg_gaussmix.cpp
new file mode 100644 (file)
index 0000000..f3cb98c
--- /dev/null
@@ -0,0 +1,1376 @@
+/*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
+//
+// Copyright (C) 2000, Intel Corporation, all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+//   * Redistribution's of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//
+//   * Redistribution's in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//
+//   * The name of Intel Corporation may not be used to endorse or promote products
+//     derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+#include "precomp.hpp"
+
+/////////////////////////////////////// MOG model //////////////////////////////////////////
+
+static void CV_CDECL
+icvReleaseGaussianBGModel( CvGaussBGModel** bg_model )
+{
+    if( !bg_model )
+        CV_Error( CV_StsNullPtr, "" );
+    
+    if( *bg_model )
+    {
+        delete (cv::Mat*)((*bg_model)->g_point);
+        cvReleaseImage( &(*bg_model)->background );
+        cvReleaseImage( &(*bg_model)->foreground );
+        cvReleaseMemStorage(&(*bg_model)->storage);
+        memset( *bg_model, 0, sizeof(**bg_model) );
+        delete *bg_model;
+        *bg_model = 0;
+    }
+}
+
+
+static int CV_CDECL
+icvUpdateGaussianBGModel( IplImage* curr_frame, CvGaussBGModel*  bg_model, double learningRate )
+{
+    int region_count = 0;
+    
+    cv::Mat image = cv::cvarrToMat(curr_frame), mask = cv::cvarrToMat(bg_model->foreground);
+    
+    cv::BackgroundSubtractorMOG mog;
+    mog.bgmodel = *(cv::Mat*)bg_model->g_point;
+    mog.frameSize = mog.bgmodel.data ? cv::Size(cvGetSize(curr_frame)) : cv::Size();
+    mog.frameType = image.type();
+    
+    mog.nframes = bg_model->countFrames;
+    mog.history = bg_model->params.win_size;
+    mog.nmixtures = bg_model->params.n_gauss;
+    mog.varThreshold = bg_model->params.std_threshold*bg_model->params.std_threshold;
+    mog.backgroundRatio = bg_model->params.bg_threshold;
+    
+    mog(image, mask, learningRate);
+    
+    bg_model->countFrames = mog.nframes;
+    if( ((cv::Mat*)bg_model->g_point)->data != mog.bgmodel.data )
+        *((cv::Mat*)bg_model->g_point) = mog.bgmodel;
+    
+    //foreground filtering
+    
+    //filter small regions
+    cvClearMemStorage(bg_model->storage);
+    
+    //cvMorphologyEx( bg_model->foreground, bg_model->foreground, 0, 0, CV_MOP_OPEN, 1 );
+    //cvMorphologyEx( bg_model->foreground, bg_model->foreground, 0, 0, CV_MOP_CLOSE, 1 );
+    
+#if 0
+    CvSeq *first_seq = NULL, *prev_seq = NULL, *seq = NULL;
+    cvFindContours( bg_model->foreground, bg_model->storage, &first_seq, sizeof(CvContour), CV_RETR_LIST );
+    for( seq = first_seq; seq; seq = seq->h_next )
+    {
+        CvContour* cnt = (CvContour*)seq;
+        if( cnt->rect.width * cnt->rect.height < bg_model->params.minArea )
+        {
+            //delete small contour
+            prev_seq = seq->h_prev;
+            if( prev_seq )
+            {
+                prev_seq->h_next = seq->h_next;
+                if( seq->h_next ) seq->h_next->h_prev = prev_seq;
+            }
+            else
+            {
+                first_seq = seq->h_next;
+                if( seq->h_next ) seq->h_next->h_prev = NULL;
+            }
+        }
+        else
+        {
+            region_count++;
+        }
+    }
+    bg_model->foreground_regions = first_seq;
+    cvZero(bg_model->foreground);
+    cvDrawContours(bg_model->foreground, first_seq, CV_RGB(0, 0, 255), CV_RGB(0, 0, 255), 10, -1);
+#endif
+    
+    CvMat _mask = mask;
+    cvCopy(&_mask, bg_model->foreground);
+    
+    return region_count;
+}
+
+CV_IMPL CvBGStatModel*
+cvCreateGaussianBGModel( IplImage* first_frame, CvGaussBGStatModelParams* parameters )
+{
+    CvGaussBGStatModelParams params;
+    
+    CV_Assert( CV_IS_IMAGE(first_frame) );
+    
+    //init parameters
+    if( parameters == NULL )
+    {                        // These constants are defined in cvaux/include/cvaux.h
+        params.win_size      = CV_BGFG_MOG_WINDOW_SIZE;
+        params.bg_threshold  = CV_BGFG_MOG_BACKGROUND_THRESHOLD;
+        
+        params.std_threshold = CV_BGFG_MOG_STD_THRESHOLD;
+        params.weight_init   = CV_BGFG_MOG_WEIGHT_INIT;
+        
+        params.variance_init = CV_BGFG_MOG_SIGMA_INIT*CV_BGFG_MOG_SIGMA_INIT;
+        params.minArea       = CV_BGFG_MOG_MINAREA;
+        params.n_gauss       = CV_BGFG_MOG_NGAUSSIANS;
+    }
+    else
+        params = *parameters;
+    
+    CvGaussBGModel* bg_model = new CvGaussBGModel;
+    memset( bg_model, 0, sizeof(*bg_model) );
+    bg_model->type = CV_BG_MODEL_MOG;
+    bg_model->release = (CvReleaseBGStatModel)icvReleaseGaussianBGModel;
+    bg_model->update = (CvUpdateBGStatModel)icvUpdateGaussianBGModel;
+    
+    bg_model->params = params;
+    
+    //prepare storages
+    bg_model->g_point = (CvGaussBGPoint*)new cv::Mat();
+    
+    bg_model->background = cvCreateImage(cvSize(first_frame->width,
+                                                first_frame->height), IPL_DEPTH_8U, first_frame->nChannels);
+    bg_model->foreground = cvCreateImage(cvSize(first_frame->width,
+                                                first_frame->height), IPL_DEPTH_8U, 1);
+    
+    bg_model->storage = cvCreateMemStorage();
+    
+    bg_model->countFrames = 0;
+    
+    icvUpdateGaussianBGModel( first_frame, bg_model, 1 );
+    
+    return (CvBGStatModel*)bg_model;
+}
+
+
+//////////////////////////////////////////// MOG2 //////////////////////////////////////////////
+
+/*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
+ //
+ // 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*/
+
+/*//Implementation of the Gaussian mixture model background subtraction from:
+ //
+ //"Improved adaptive Gausian mixture model for background subtraction"
+ //Z.Zivkovic 
+ //International Conference Pattern Recognition, UK, August, 2004
+ //http://www.zoranz.net/Publications/zivkovic2004ICPR.pdf
+ //The code is very fast and performs also shadow detection. 
+ //Number of Gausssian components is adapted per pixel.
+ //
+ // and
+ //
+ //"Efficient Adaptive Density Estimapion per Image Pixel for the Task of Background Subtraction"
+ //Z.Zivkovic, F. van der Heijden 
+ //Pattern Recognition Letters, vol. 27, no. 7, pages 773-780, 2006.
+ //
+ //The algorithm similar to the standard Stauffer&Grimson algorithm with
+ //additional selection of the number of the Gaussian components based on:
+ //
+ //"Recursive unsupervised learning of finite mixture models "
+ //Z.Zivkovic, F.van der Heijden 
+ //IEEE Trans. on Pattern Analysis and Machine Intelligence, vol.26, no.5, pages 651-656, 2004
+ //http://www.zoranz.net/Publications/zivkovic2004PAMI.pdf
+ //
+ //
+ //Example usage with as cpp class
+ // BackgroundSubtractorMOG2 bg_model;
+ //For each new image the model is updates using: 
+ // bg_model(img, fgmask);
+ //
+ //Example usage as part of the CvBGStatModel:
+ // CvBGStatModel* bg_model = cvCreateGaussianBGModel2( first_frame );
+ //
+ // //update for each frame
+ // cvUpdateBGStatModel( tmp_frame, bg_model );//segmentation result is in bg_model->foreground
+ //
+ // //release at the program termination
+ // cvReleaseBGStatModel( &bg_model );
+ //
+ //Author: Z.Zivkovic, www.zoranz.net
+ //Date: 7-April-2011, Version:1.0
+ ///////////*/
+
+#include "precomp.hpp"
+
+
+/*
+ Interface of Gaussian mixture algorithm from:
+ "Improved adaptive Gausian mixture model for background subtraction"
+ Z.Zivkovic
+ International Conference Pattern Recognition, UK, August, 2004
+ http://www.zoranz.net/Publications/zivkovic2004ICPR.pdf
+ Advantages:
+ -fast - number of Gausssian components is constantly adapted per pixel.
+ -performs also shadow detection (see bgfg_segm_test.cpp example)
+ */
+
+
+#define CV_BG_MODEL_MOG2            3                 /* "Mixture of Gaussians 2".  */
+
+
+/* default parameters of gaussian background detection algorithm */
+#define CV_BGFG_MOG2_STD_THRESHOLD            4.0f     /* lambda=2.5 is 99% */
+#define CV_BGFG_MOG2_WINDOW_SIZE              500      /* Learning rate; alpha = 1/CV_GBG_WINDOW_SIZE */
+#define CV_BGFG_MOG2_BACKGROUND_THRESHOLD     0.9f     /* threshold sum of weights for background test */
+#define CV_BGFG_MOG2_STD_THRESHOLD_GENERATE   3.0f     /* lambda=2.5 is 99% */
+#define CV_BGFG_MOG2_NGAUSSIANS               5        /* = K = number of Gaussians in mixture */
+#define CV_BGFG_MOG2_VAR_INIT                 15.0f    /* initial variance for new components*/
+#define CV_BGFG_MOG2_VAR_MIN                    4.0f
+#define CV_BGFG_MOG2_VAR_MAX                      5*CV_BGFG_MOG2_VAR_INIT
+#define CV_BGFG_MOG2_MINAREA                  15.0f    /* for postfiltering */
+
+/* additional parameters */
+#define CV_BGFG_MOG2_CT                               0.05f     /* complexity reduction prior constant 0 - no reduction of number of components*/
+#define CV_BGFG_MOG2_SHADOW_VALUE             127       /* value to use in the segmentation mask for shadows, sot 0 not to do shadow detection*/
+#define CV_BGFG_MOG2_SHADOW_TAU               0.5f      /* Tau - shadow threshold, see the paper for explanation*/
+
+typedef struct CvGaussBGStatModel2Params
+{
+    //image info
+    int nWidth;
+    int nHeight;
+    int nND;//number of data dimensions (image channels)
+    
+    bool bPostFiltering;//defult 1 - do postfiltering - will make shadow detection results also give value 255 
+    double  minArea; // for postfiltering
+    
+    bool bInit;//default 1, faster updates at start
+    
+    /////////////////////////
+    //very important parameters - things you will change
+    ////////////////////////
+    float fAlphaT;
+    //alpha - speed of update - if the time interval you want to average over is T
+    //set alpha=1/T. It is also usefull at start to make T slowly increase
+    //from 1 until the desired T
+    float fTb;
+    //Tb - threshold on the squared Mahalan. dist. to decide if it is well described
+    //by the background model or not. Related to Cthr from the paper.
+    //This does not influence the update of the background. A typical value could be 4 sigma
+    //and that is Tb=4*4=16;
+    
+    /////////////////////////
+    //less important parameters - things you might change but be carefull
+    ////////////////////////
+    float fTg;
+    //Tg - threshold on the squared Mahalan. dist. to decide
+    //when a sample is close to the existing components. If it is not close
+    //to any a new component will be generated. I use 3 sigma => Tg=3*3=9.
+    //Smaller Tg leads to more generated components and higher Tg might make
+    //lead to small number of components but they can grow too large
+    float fTB;//1-cf from the paper
+    //TB - threshold when the component becomes significant enough to be included into
+    //the background model. It is the TB=1-cf from the paper. So I use cf=0.1 => TB=0.
+    //For alpha=0.001 it means that the mode should exist for approximately 105 frames before
+    //it is considered foreground
+    float fVarInit;
+    float fVarMax;
+    float fVarMin;
+    //initial standard deviation  for the newly generated components.
+    //It will will influence the speed of adaptation. A good guess should be made.
+    //A simple way is to estimate the typical standard deviation from the images.
+    //I used here 10 as a reasonable value
+    float fCT;//CT - complexity reduction prior
+    //this is related to the number of samples needed to accept that a component
+    //actually exists. We use CT=0.05 of all the samples. By setting CT=0 you get
+    //the standard Stauffer&Grimson algorithm (maybe not exact but very similar)
+    
+    //even less important parameters
+    int nM;//max number of modes - const - 4 is usually enough
+    
+    //shadow detection parameters
+    bool bShadowDetection;//default 1 - do shadow detection
+    unsigned char nShadowDetection;//do shadow detection - insert this value as the detection result
+    float fTau;
+    // Tau - shadow threshold. The shadow is detected if the pixel is darker
+    //version of the background. Tau is a threshold on how much darker the shadow can be.
+    //Tau= 0.5 means that if pixel is more than 2 times darker then it is not shadow
+    //See: Prati,Mikic,Trivedi,Cucchiarra,"Detecting Moving Shadows...",IEEE PAMI,2003.
+} CvGaussBGStatModel2Params;
+
+#define CV_BGFG_MOG2_NDMAX 3
+
+typedef struct CvPBGMMGaussian
+{
+    float weight;
+    float mean[CV_BGFG_MOG2_NDMAX];
+    float variance;
+}CvPBGMMGaussian;
+
+typedef struct CvGaussBGStatModel2Data
+{ 
+    CvPBGMMGaussian* rGMM; //array for the mixture of Gaussians
+    unsigned char* rnUsedModes;//number of Gaussian components per pixel (maximum 255)
+} CvGaussBGStatModel2Data;
+
+
+/*
+ //only foreground image is updated
+ //no filtering included
+ typedef struct CvGaussBGModel2
+ {
+ CV_BG_STAT_MODEL_FIELDS();
+ CvGaussBGStatModel2Params params;
+ CvGaussBGStatModel2Data   data;
+ int                       countFrames;
+ } CvGaussBGModel2;
+ CVAPI(CvBGStatModel*) cvCreateGaussianBGModel2( IplImage* first_frame,
+ CvGaussBGStatModel2Params* params CV_DEFAULT(NULL) );
+ */ 
+
+//shadow detection performed per pixel
+// should work for rgb data, could be usefull for gray scale and depth data as well
+//  See: Prati,Mikic,Trivedi,Cucchiarra,"Detecting Moving Shadows...",IEEE PAMI,2003.
+CV_INLINE int _icvRemoveShadowGMM(float* data, int nD,
+                                  unsigned char nModes, 
+                                  CvPBGMMGaussian* pGMM,
+                                  float m_fTb,
+                                  float m_fTB,    
+                                  float m_fTau)
+{
+    float tWeight = 0;
+    float numerator, denominator;
+    // check all the components  marked as background:
+    for (int iModes=0;iModes<nModes;iModes++)
+    {
+        
+        CvPBGMMGaussian g=pGMM[iModes];
+        
+        numerator = 0.0f;
+        denominator = 0.0f;
+        for (int iD=0;iD<nD;iD++)
+        {
+            numerator   += data[iD]  * g.mean[iD];
+            denominator += g.mean[iD]* g.mean[iD];
+        }
+        
+        // no division by zero allowed
+        if (denominator == 0)
+        {
+            return 0;
+        };
+        float a = numerator / denominator;
+        
+        // if tau < a < 1 then also check the color distortion
+        if ((a <= 1) && (a >= m_fTau))
+        {
+            
+            float dist2a=0.0f;
+            
+            for (int iD=0;iD<nD;iD++)
+            {
+                float dD= a*g.mean[iD] - data[iD];
+                dist2a += (dD*dD);
+            }
+            
+            if (dist2a<m_fTb*g.variance*a*a)
+            {
+                return 2;
+            }
+        };
+        
+        tWeight += g.weight;
+        if (tWeight > m_fTB)
+        {
+            return 0;
+        };
+    };
+    return 0;
+}
+
+//update GMM - the base update function performed per pixel
+//
+//"Efficient Adaptive Density Estimapion per Image Pixel for the Task of Background Subtraction"
+//Z.Zivkovic, F. van der Heijden 
+//Pattern Recognition Letters, vol. 27, no. 7, pages 773-780, 2006.
+//
+//The algorithm similar to the standard Stauffer&Grimson algorithm with
+//additional selection of the number of the Gaussian components based on:
+//
+//"Recursive unsupervised learning of finite mixture models "
+//Z.Zivkovic, F.van der Heijden 
+//IEEE Trans. on Pattern Analysis and Machine Intelligence, vol.26, no.5, pages 651-656, 2004
+//http://www.zoranz.net/Publications/zivkovic2004PAMI.pdf
+
+CV_INLINE int _icvUpdateGMM(float* data, int nD,
+                            unsigned char* pModesUsed, 
+                            CvPBGMMGaussian* pGMM,
+                            int m_nM,
+                            float m_fAlphaT,
+                            float m_fTb,
+                            float m_fTB,    
+                            float m_fTg,
+                            float m_fVarInit,
+                            float m_fVarMax,
+                            float m_fVarMin,
+                            float m_fPrune)
+{
+    //calculate distances to the modes (+ sort)
+    //here we need to go in descending order!!! 
+    bool bBackground=0;//return value -> true - the pixel classified as background
+    
+    //internal:
+    bool bFitsPDF=0;//if it remains zero a new GMM mode will be added   
+    float m_fOneMinAlpha=1-m_fAlphaT;
+    unsigned char nModes=*pModesUsed;//current number of modes in GMM
+    float totalWeight=0.0f;
+    
+    //////
+    //go through all modes
+    int iMode=0;
+    CvPBGMMGaussian* pGauss=pGMM;
+    for (;iMode<nModes;iMode++,pGauss++)
+    {
+        float weight = pGauss->weight;//need only weight if fit is found
+        weight=m_fOneMinAlpha*weight+m_fPrune;
+        
+        ////
+        //fit not found yet
+        if (!bFitsPDF)
+        {
+            //check if it belongs to some of the remaining modes
+            float var=pGauss->variance;
+            
+            //calculate difference and distance
+            float dist2=0.0f;
+#if (CV_BGFG_MOG2_NDMAX==1)
+            float dData=pGauss->mean[0]-data[0];
+            dist2=dData*dData;
+#else           
+            float dData[CV_BGFG_MOG2_NDMAX];
+            
+            for (int iD=0;iD<nD;iD++)
+            {
+                dData[iD]=pGauss->mean[iD]-data[iD];
+                dist2+=dData[iD]*dData[iD];
+            }
+#endif      
+            //background? - m_fTb - usually larger than m_fTg
+            if ((totalWeight<m_fTB)&&(dist2<m_fTb*var))
+                bBackground=1;
+            
+            //check fit
+            if (dist2<m_fTg*var)
+            {
+                /////
+                //belongs to the mode - bFitsPDF becomes 1
+                bFitsPDF=1;
+                
+                //update distribution               
+                
+                //update weight
+                weight+=m_fAlphaT;
+                
+                float k = m_fAlphaT/weight;
+                
+                //update mean
+#if (CV_BGFG_MOG2_NDMAX==1)
+                pGauss->mean[0]-=k*dData;
+#else               
+                for (int iD=0;iD<nD;iD++)
+                {
+                    pGauss->mean[iD]-=k*dData[iD];
+                }
+#endif
+                
+                //update variance
+                float varnew = var + k*(dist2-var);
+                //limit the variance                
+                pGauss->variance = MIN(m_fVarMax,MAX(varnew,m_fVarMin));
+                
+                //sort
+                //all other weights are at the same place and 
+                //only the matched (iModes) is higher -> just find the new place for it             
+                for (int iLocal = iMode;iLocal>0;iLocal--)
+                {
+                    //check one up
+                    if (weight < (pGMM[iLocal-1].weight))
+                    {
+                        break;
+                    }
+                    else
+                    {
+                        //swap one up
+                        CvPBGMMGaussian temp = pGMM[iLocal];
+                        pGMM[iLocal] = pGMM[iLocal-1];
+                        pGMM[iLocal-1] = temp;
+                        pGauss--;
+                    }
+                }
+                //belongs to the mode - bFitsPDF becomes 1
+                /////
+            }
+        }//!bFitsPDF)
+        
+        //check prune
+        if (weight<-m_fPrune)
+        {
+            weight=0.0;
+            nModes--;
+        }
+        
+        pGauss->weight=weight;//update weight by the calculated value
+        totalWeight+=weight;
+    }
+    //go through all modes
+    //////
+    
+    //renormalize weights
+    for (iMode = 0; iMode < nModes; iMode++)
+    {
+        pGMM[iMode].weight = pGMM[iMode].weight/totalWeight;
+    }
+    
+    //make new mode if needed and exit
+    if (!bFitsPDF)
+    {
+        if (nModes==m_nM)
+        {
+            //replace the weakest
+            pGauss=pGMM+m_nM-1;
+        }
+        else
+        {
+            //add a new one
+            pGauss=pGMM+nModes;
+            nModes++;
+        }
+        
+        if (nModes==1)
+        {
+            pGauss->weight=1;
+        }
+        else
+        {
+            pGauss->weight=m_fAlphaT;
+            
+            //renormalize all weights
+            for (iMode = 0; iMode < nModes-1; iMode++)
+            {
+                pGMM[iMode].weight *=m_fOneMinAlpha;
+            }
+        }
+        
+        //init 
+        memcpy(pGauss->mean,data,nD*sizeof(float));
+        pGauss->variance=m_fVarInit;
+        
+        //sort
+        //find the new place for it
+        for (int iLocal = nModes-1;iLocal>0;iLocal--)
+        {
+            //check one up
+            if (m_fAlphaT < (pGMM[iLocal-1].weight))
+            {
+                break;
+            }
+            else
+            {
+                //swap one up
+                CvPBGMMGaussian temp = pGMM[iLocal];
+                pGMM[iLocal] = pGMM[iLocal-1];
+                pGMM[iLocal-1] = temp;
+            }
+        }
+    }
+    
+    //set the number of modes
+    *pModesUsed=nModes;
+    
+    return bBackground;
+}
+
+// a bit more efficient implementation for common case of 3 channel (rgb) images
+CV_INLINE int _icvUpdateGMM_C3(float r,float g, float b,
+                               unsigned char* pModesUsed, 
+                               CvPBGMMGaussian* pGMM,
+                               int m_nM,
+                               float m_fAlphaT,
+                               float m_fTb,
+                               float m_fTB,    
+                               float m_fTg,
+                               float m_fVarInit,
+                               float m_fVarMax,
+                               float m_fVarMin,
+                               float m_fPrune)
+{
+    //calculate distances to the modes (+ sort)
+    //here we need to go in descending order!!! 
+    bool bBackground=0;//return value -> true - the pixel classified as background
+    
+    //internal:
+    bool bFitsPDF=0;//if it remains zero a new GMM mode will be added   
+    float m_fOneMinAlpha=1-m_fAlphaT;
+    unsigned char nModes=*pModesUsed;//current number of modes in GMM
+    float totalWeight=0.0f;
+    
+    //////
+    //go through all modes
+    int iMode=0;
+    CvPBGMMGaussian* pGauss=pGMM;
+    for (;iMode<nModes;iMode++,pGauss++)
+    {
+        float weight = pGauss->weight;//need only weight if fit is found
+        weight=m_fOneMinAlpha*weight+m_fPrune;
+        
+        ////
+        //fit not found yet
+        if (!bFitsPDF)
+        {
+            //check if it belongs to some of the remaining modes
+            float var=pGauss->variance;
+            
+            //calculate difference and distance
+            float muR = pGauss->mean[0];
+            float muG = pGauss->mean[1];
+            float muB = pGauss->mean[2];
+            
+            float dR=muR - r;
+            float dG=muG - g;
+            float dB=muB - b;
+            
+            float dist2=(dR*dR+dG*dG+dB*dB);        
+            
+            //background? - m_fTb - usually larger than m_fTg
+            if ((totalWeight<m_fTB)&&(dist2<m_fTb*var))
+                bBackground=1;
+            
+            //check fit
+            if (dist2<m_fTg*var)
+            {
+                /////
+                //belongs to the mode - bFitsPDF becomes 1
+                bFitsPDF=1;
+                
+                //update distribution               
+                
+                //update weight
+                weight+=m_fAlphaT;
+                
+                float k = m_fAlphaT/weight;
+                
+                //update mean
+                pGauss->mean[0] = muR - k*(dR);
+                pGauss->mean[1] = muG - k*(dG);
+                pGauss->mean[2] = muB - k*(dB);
+                
+                //update variance
+                float varnew = var + k*(dist2-var);
+                //limit the variance                
+                pGauss->variance = MIN(m_fVarMax,MAX(varnew,m_fVarMin));
+                
+                //sort
+                //all other weights are at the same place and 
+                //only the matched (iModes) is higher -> just find the new place for it             
+                for (int iLocal = iMode;iLocal>0;iLocal--)
+                {
+                    //check one up
+                    if (weight < (pGMM[iLocal-1].weight))
+                    {
+                        break;
+                    }
+                    else
+                    {
+                        //swap one up
+                        CvPBGMMGaussian temp = pGMM[iLocal];
+                        pGMM[iLocal] = pGMM[iLocal-1];
+                        pGMM[iLocal-1] = temp;
+                        pGauss--;
+                    }
+                }
+                //belongs to the mode - bFitsPDF becomes 1
+                /////
+            }   
+            
+        }//!bFitsPDF)
+        
+        //check prunning
+        if (weight<-m_fPrune)
+        {
+            weight=0.0;
+            nModes--;
+        }
+        
+        pGauss->weight=weight;
+        totalWeight+=weight;
+    }
+    //go through all modes
+    //////
+    
+    //renormalize weights
+    for (iMode = 0; iMode < nModes; iMode++)
+    {
+        pGMM[iMode].weight = pGMM[iMode].weight/totalWeight;
+    }
+    
+    //make new mode if needed and exit
+    if (!bFitsPDF)
+    {
+        if (nModes==m_nM)
+        {
+            //replace the weakest
+            pGauss=pGMM+m_nM-1;
+        }
+        else
+        {
+            //add a new one
+            pGauss=pGMM+nModes;
+            nModes++;
+        }
+        
+        if (nModes==1)
+        {
+            pGauss->weight=1;
+        }
+        else
+        {
+            pGauss->weight=m_fAlphaT;
+            
+            //renormalize all weights
+            for (iMode = 0; iMode < nModes-1; iMode++)
+            {
+                pGMM[iMode].weight *=m_fOneMinAlpha;
+            }
+        }
+        
+        //init 
+        pGauss->mean[0]=r;
+        pGauss->mean[1]=g;
+        pGauss->mean[2]=b;
+        
+        pGauss->variance=m_fVarInit;
+        
+        //sort
+        //find the new place for it
+        for (int iLocal = nModes-1;iLocal>0;iLocal--)
+        {
+            //check one up
+            if (m_fAlphaT < (pGMM[iLocal-1].weight))
+            {
+                break;
+            }
+            else
+            {
+                //swap one up
+                CvPBGMMGaussian temp = pGMM[iLocal];
+                pGMM[iLocal] = pGMM[iLocal-1];
+                pGMM[iLocal-1] = temp;
+            }
+        }
+    }
+    
+    //set the number of modes
+    *pModesUsed=nModes;
+    
+    return bBackground;
+}
+
+//the main function to update the background model
+void icvUpdatePixelBackgroundGMM2( const CvArr* srcarr, CvArr* dstarr ,
+                                  CvPBGMMGaussian *pGMM,
+                                  unsigned char *pUsedModes,
+                                  //CvGaussBGStatModel2Params* pGMMPar,
+                                  int nM,
+                                  float fTb, 
+                                  float fTB, 
+                                  float fTg, 
+                                  float fVarInit,
+                                  float fVarMax,
+                                  float fVarMin,
+                                  float fCT,
+                                  float fTau,
+                                  bool bShadowDetection,
+                                  unsigned char  nShadowDetection,
+                                  float alpha)
+{
+    CvMat sstub, *src = cvGetMat(srcarr, &sstub);
+    CvMat dstub, *dst = cvGetMat(dstarr, &dstub);
+    CvSize size = cvGetMatSize(src);
+    int nD=CV_MAT_CN(src->type);
+    
+    //reshape if possible
+    if( CV_IS_MAT_CONT(src->type & dst->type) )
+    {
+        size.width *= size.height;
+        size.height = 1;
+    }
+    
+    int x, y;
+    float data[CV_BGFG_MOG2_NDMAX];
+    float prune=-alpha*fCT;
+    
+    //general nD
+    
+    if (nD!=3)
+    {
+        switch (CV_MAT_DEPTH(src->type))
+        {
+            case CV_8U:
+                for( y = 0; y < size.height; y++ )
+                {
+                    uchar* sptr = src->data.ptr + src->step*y;
+                    uchar* pDataOutput = dst->data.ptr + dst->step*y;
+                    for( x = 0; x < size.width; x++,
+                        pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD)
+                    {
+                        //convert data
+                        for (int iD=0;iD<nD;iD++) data[iD]=float(sptr[iD]);
+                        //update GMM model
+                        int result = _icvUpdateGMM(data,nD,pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune);
+                        //detect shadows in the foreground
+                        if (bShadowDetection)
+                            if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau);
+                        //generate output
+                        (* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255; 
+                    }
+                }
+                break;
+            case CV_16S:
+                for( y = 0; y < size.height; y++ )
+                {
+                    short* sptr = src->data.s + src->step*y;
+                    uchar* pDataOutput = dst->data.ptr + dst->step*y;
+                    for( x = 0; x < size.width; x++,
+                        pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD)
+                    {
+                        //convert data
+                        for (int iD=0;iD<nD;iD++) data[iD]=float(sptr[iD]);
+                        //update GMM model
+                        int result = _icvUpdateGMM(data,nD,pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune);
+                        //detect shadows in the foreground
+                        if (bShadowDetection)
+                            if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau);
+                        //generate output
+                        (* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255; 
+                    }
+                }
+                break;
+            case CV_16U:
+                for( y = 0; y < size.height; y++ )
+                {
+                    unsigned short* sptr = (unsigned short*) (src->data.s + src->step*y);
+                    uchar* pDataOutput = dst->data.ptr + dst->step*y;
+                    for( x = 0; x < size.width; x++,
+                        pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD)
+                    {
+                        //convert data
+                        for (int iD=0;iD<nD;iD++) data[iD]=float(sptr[iD]);
+                        //update GMM model
+                        int result = _icvUpdateGMM(data,nD,pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune);
+                        //detect shadows in the foreground
+                        if (bShadowDetection)
+                            if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau);
+                        //generate output
+                        (* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255; 
+                    }
+                }
+                break;
+            case CV_32S:
+                for( y = 0; y < size.height; y++ )
+                {
+                    int* sptr = src->data.i + src->step*y;
+                    uchar* pDataOutput = dst->data.ptr + dst->step*y;
+                    for( x = 0; x < size.width; x++,
+                        pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD)
+                    {
+                        //convert data
+                        for (int iD=0;iD<nD;iD++) data[iD]=float(sptr[iD]);
+                        //update GMM model
+                        int result = _icvUpdateGMM(data,nD,pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune);
+                        //detect shadows in the foreground
+                        if (bShadowDetection)
+                            if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau);
+                        //generate output
+                        (* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255; 
+                    }
+                }
+                break;
+            case CV_32F:
+                for( y = 0; y < size.height; y++ )
+                {
+                    float* sptr = src->data.fl + src->step*y;
+                    uchar* pDataOutput = dst->data.ptr + dst->step*y;
+                    for( x = 0; x < size.width; x++,
+                        pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD)
+                    {
+                        //update GMM model
+                        int result = _icvUpdateGMM(sptr,nD,pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune);
+                        //detect shadows in the foreground
+                        if (bShadowDetection)
+                            if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau);
+                        //generate output
+                        (* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255; 
+                    }
+                }
+                break;
+            case CV_64F:
+                for( y = 0; y < size.height; y++ )
+                {
+                    double* sptr = src->data.db + src->step*y;
+                    uchar* pDataOutput = dst->data.ptr + dst->step*y;
+                    for( x = 0; x < size.width; x++,
+                        pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD)
+                    {
+                        //convert data
+                        for (int iD=0;iD<nD;iD++) data[iD]=float(sptr[iD]);
+                        //update GMM model
+                        int result = _icvUpdateGMM(data,nD,pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune);
+                        //detect shadows in the foreground
+                        if (bShadowDetection)
+                            if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau);
+                        //generate output
+                        (* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255; 
+                    }
+                }
+                break;
+        }
+    }else ///if (nD==3) - a bit faster
+    {
+        switch (CV_MAT_DEPTH(src->type))
+        {
+            case CV_8U:
+                for( y = 0; y < size.height; y++ )
+                {
+                    uchar* sptr = src->data.ptr + src->step*y;
+                    uchar* pDataOutput = dst->data.ptr + dst->step*y;
+                    for( x = 0; x < size.width; x++,
+                        pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD)
+                    {
+                        //convert data
+                        data[0]=float(sptr[0]),data[1]=float(sptr[1]),data[2]=float(sptr[2]);
+                        //update GMM model
+                        int result = _icvUpdateGMM_C3(data[0],data[1],data[2],pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune);
+                        //detect shadows in the foreground
+                        if (bShadowDetection)
+                            if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau);
+                        //generate output
+                        (* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255; 
+                    }
+                }
+                break;
+            case CV_16S:
+                for( y = 0; y < size.height; y++ )
+                {
+                    short* sptr = src->data.s + src->step*y;
+                    uchar* pDataOutput = dst->data.ptr + dst->step*y;
+                    for( x = 0; x < size.width; x++,
+                        pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD)
+                    {
+                        //convert data
+                        data[0]=float(sptr[0]),data[1]=float(sptr[1]),data[2]=float(sptr[2]);
+                        //update GMM model
+                        int result = _icvUpdateGMM_C3(data[0],data[1],data[2],pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune);
+                        //detect shadows in the foreground
+                        if (bShadowDetection)
+                            if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau);
+                        //generate output
+                        (* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255; 
+                    }
+                }
+                break;
+            case CV_16U:
+                for( y = 0; y < size.height; y++ )
+                {
+                    unsigned short* sptr = (unsigned short*) src->data.s + src->step*y;
+                    uchar* pDataOutput = dst->data.ptr + dst->step*y;
+                    for( x = 0; x < size.width; x++,
+                        pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD)
+                    {
+                        //convert data
+                        data[0]=float(sptr[0]),data[1]=float(sptr[1]),data[2]=float(sptr[2]);
+                        //update GMM model
+                        int result = _icvUpdateGMM_C3(data[0],data[1],data[2],pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune);
+                        //detect shadows in the foreground
+                        if (bShadowDetection)
+                            if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau);
+                        //generate output
+                        (* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255; 
+                    }
+                }
+                break;
+            case CV_32S:
+                for( y = 0; y < size.height; y++ )
+                {
+                    int* sptr = src->data.i + src->step*y;
+                    uchar* pDataOutput = dst->data.ptr + dst->step*y;
+                    for( x = 0; x < size.width; x++,
+                        pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD)
+                    {
+                        //convert data
+                        data[0]=float(sptr[0]),data[1]=float(sptr[1]),data[2]=float(sptr[2]);
+                        //update GMM model
+                        int result = _icvUpdateGMM_C3(data[0],data[1],data[2],pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune);
+                        //detect shadows in the foreground
+                        if (bShadowDetection)
+                            if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau);
+                        //generate output
+                        (* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255; 
+                    }
+                }
+                break;
+            case CV_32F:
+                for( y = 0; y < size.height; y++ )
+                {
+                    float* sptr = src->data.fl + src->step*y;
+                    uchar* pDataOutput = dst->data.ptr + dst->step*y;
+                    for( x = 0; x < size.width; x++,
+                        pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD)
+                    {
+                        //update GMM model
+                        int result = _icvUpdateGMM_C3(sptr[0],sptr[1],sptr[2],pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune);
+                        //detect shadows in the foreground
+                        if (bShadowDetection)
+                            if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau);
+                        //generate output
+                        (* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255; 
+                    }
+                }
+                break;
+            case CV_64F:
+                for( y = 0; y < size.height; y++ )
+                {
+                    double* sptr = src->data.db + src->step*y;
+                    uchar* pDataOutput = dst->data.ptr + dst->step*y;
+                    for( x = 0; x < size.width; x++,
+                        pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD)
+                    {
+                        //convert data
+                        data[0]=float(sptr[0]),data[1]=float(sptr[1]),data[2]=float(sptr[2]);
+                        //update GMM model
+                        int result = _icvUpdateGMM_C3(data[0],data[1],data[2],pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune);
+                        //detect shadows in the foreground
+                        if (bShadowDetection)
+                            if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau);
+                        //generate output
+                        (* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255; 
+                    }
+                }
+                break;
+        }
+    }//a bit faster for nD=3; 
+}
+
+
+//only foreground image is updated
+//no filtering included
+typedef struct CvGaussBGModel2
+{
+    CV_BG_STAT_MODEL_FIELDS();
+    CvGaussBGStatModel2Params params;
+    CvGaussBGStatModel2Data   data;
+    int                       countFrames;
+} CvGaussBGModel2;
+
+CVAPI(CvBGStatModel*) cvCreateGaussianBGModel2( IplImage* first_frame,
+                                               CvGaussBGStatModel2Params* params CV_DEFAULT(NULL) );
+
+//////////////////////////////////////////////
+//implementation as part of the CvBGStatModel
+static void CV_CDECL icvReleaseGaussianBGModel2( CvGaussBGModel2** bg_model );
+static int CV_CDECL icvUpdateGaussianBGModel2( IplImage* curr_frame, CvGaussBGModel2*  bg_model );
+
+
+CV_IMPL CvBGStatModel*
+cvCreateGaussianBGModel2( IplImage* first_frame, CvGaussBGStatModel2Params* parameters )
+{
+    CvGaussBGModel2* bg_model = 0;
+    int w,h;
+    
+    CV_FUNCNAME( "cvCreateGaussianBGModel2" );
+    
+    __BEGIN__;
+    
+    CvGaussBGStatModel2Params params;
+    
+    if( !CV_IS_IMAGE(first_frame) )
+        CV_ERROR( CV_StsBadArg, "Invalid or NULL first_frame parameter" );
+    
+    if( first_frame->nChannels>CV_BGFG_MOG2_NDMAX )
+        CV_ERROR( CV_StsBadArg, "Maxumum number of channels in the image is excedded (change CV_BGFG_MOG2_MAXBANDS constant)!" );
+    
+    
+    CV_CALL( bg_model = (CvGaussBGModel2*)cvAlloc( sizeof(*bg_model) ));
+    memset( bg_model, 0, sizeof(*bg_model) );
+    bg_model->type    = CV_BG_MODEL_MOG2;
+    bg_model->release = (CvReleaseBGStatModel) icvReleaseGaussianBGModel2;
+    bg_model->update  = (CvUpdateBGStatModel)  icvUpdateGaussianBGModel2;
+    
+    //init parameters   
+    if( parameters == NULL )
+    {                        
+        memset(&params, 0, sizeof(params));
+        
+        // These constants are defined in cvaux/include/cvaux.h
+        params.bShadowDetection = 1;
+        params.bPostFiltering=0;
+        params.minArea=CV_BGFG_MOG2_MINAREA;
+        
+        //set parameters
+        // K - max number of Gaussians per pixel
+        params.nM = CV_BGFG_MOG2_NGAUSSIANS;//4;            
+        // Tb - the threshold - n var
+        //pGMM->fTb = 4*4;
+        params.fTb = CV_BGFG_MOG2_STD_THRESHOLD*CV_BGFG_MOG2_STD_THRESHOLD;
+        // Tbf - the threshold
+        //pGMM->fTB = 0.9f;//1-cf from the paper 
+        params.fTB = CV_BGFG_MOG2_BACKGROUND_THRESHOLD;
+        // Tgenerate - the threshold
+        params.fTg = CV_BGFG_MOG2_STD_THRESHOLD_GENERATE*CV_BGFG_MOG2_STD_THRESHOLD_GENERATE;//update the mode or generate new
+        //pGMM->fSigma= 11.0f;//sigma for the new mode
+        params.fVarInit = CV_BGFG_MOG2_VAR_INIT;
+        params.fVarMax = CV_BGFG_MOG2_VAR_MAX;
+        params.fVarMin = CV_BGFG_MOG2_VAR_MIN;
+        // alpha - the learning factor
+        params.fAlphaT = 1.0f/CV_BGFG_MOG2_WINDOW_SIZE;//0.003f;
+        // complexity reduction prior constant
+        params.fCT = CV_BGFG_MOG2_CT;//0.05f;
+        
+        //shadow
+        // Shadow detection
+        params.nShadowDetection = (unsigned char)CV_BGFG_MOG2_SHADOW_VALUE;//value 0 to turn off
+        params.fTau = CV_BGFG_MOG2_SHADOW_TAU;//0.5f;// Tau - shadow threshold
+    }
+    else
+    {
+        params = *parameters;
+    }
+    
+    bg_model->params = params;
+    
+    //image data 
+    w = first_frame->width;
+    h = first_frame->height;
+    
+    bg_model->params.nWidth = w;
+    bg_model->params.nHeight = h;
+    
+    bg_model->params.nND = first_frame->nChannels;
+    
+    
+    //allocate GMM data
+    
+    //GMM for each pixel
+    bg_model->data.rGMM = (CvPBGMMGaussian*) malloc(w*h * params.nM * sizeof(CvPBGMMGaussian));
+    //used modes per pixel
+    bg_model->data.rnUsedModes = (unsigned char* ) malloc(w*h);
+    memset(bg_model->data.rnUsedModes,0,w*h);//no modes used
+    
+    //prepare storages    
+    CV_CALL( bg_model->background = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U, first_frame->nChannels));
+    CV_CALL( bg_model->foreground = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U, 1));
+    
+    //for eventual filtering
+    CV_CALL( bg_model->storage = cvCreateMemStorage());
+    
+    bg_model->countFrames = 0;
+    
+    __END__;
+    
+    if( cvGetErrStatus() < 0 )
+    {
+        CvBGStatModel* base_ptr = (CvBGStatModel*)bg_model;
+        
+        if( bg_model && bg_model->release )
+            bg_model->release( &base_ptr );
+        else
+            cvFree( &bg_model );
+        bg_model = 0;
+    }
+    
+    return (CvBGStatModel*)bg_model;
+}
+
+
+static void CV_CDECL
+icvReleaseGaussianBGModel2( CvGaussBGModel2** _bg_model )
+{
+    CV_FUNCNAME( "icvReleaseGaussianBGModel2" );
+    
+    __BEGIN__;
+    
+    if( !_bg_model )
+        CV_ERROR( CV_StsNullPtr, "" );
+    
+    if( *_bg_model )
+    {
+        CvGaussBGModel2* bg_model = *_bg_model;
+        
+        free (bg_model->data.rGMM);
+        free (bg_model->data.rnUsedModes);
+        
+        cvReleaseImage( &bg_model->background );
+        cvReleaseImage( &bg_model->foreground );
+        cvReleaseMemStorage(&bg_model->storage);
+        memset( bg_model, 0, sizeof(*bg_model) );
+        cvFree( _bg_model );
+    }
+    
+    __END__;
+}
+
+
+static int CV_CDECL
+icvUpdateGaussianBGModel2( IplImage* curr_frame, CvGaussBGModel2*  bg_model )
+{ 
+    //checks    
+    if ((curr_frame->height!=bg_model->params.nHeight)||(curr_frame->width!=bg_model->params.nWidth)||(curr_frame->nChannels!=bg_model->params.nND))
+        CV_Error( CV_StsBadSize, "the image not the same size as the reserved GMM background model");
+    
+    float alpha=bg_model->params.fAlphaT;
+    bg_model->countFrames++;
+    
+    //faster initial updates - increase value of alpha
+    if (bg_model->params.bInit){
+        float alphaInit=(1.0f/(2*bg_model->countFrames+1));
+        if (alphaInit>alpha)
+        {
+            alpha = alphaInit;
+        }
+        else
+        {
+            bg_model->params.bInit = 0;
+        }
+    }
+    
+    //update background
+    //icvUpdatePixelBackgroundGMM2( curr_frame, bg_model->foreground, bg_model->data.rGMM,bg_model->data.rnUsedModes,&(bg_model->params),alpha);
+    icvUpdatePixelBackgroundGMM2( curr_frame, bg_model->foreground, bg_model->data.rGMM,bg_model->data.rnUsedModes,
+                                 bg_model->params.nM,
+                                 bg_model->params.fTb,
+                                 bg_model->params.fTB,
+                                 bg_model->params.fTg,
+                                 bg_model->params.fVarInit,
+                                 bg_model->params.fVarMax,
+                                 bg_model->params.fVarMin,
+                                 bg_model->params.fCT,
+                                 bg_model->params.fTau,
+                                 bg_model->params.bShadowDetection,
+                                 bg_model->params.nShadowDetection,
+                                 alpha);
+    
+    //foreground filtering
+    if (bg_model->params.bPostFiltering==1)
+    {
+        int region_count = 0;
+        CvSeq *first_seq = NULL, *prev_seq = NULL, *seq = NULL;
+        
+        
+        //filter small regions
+        cvClearMemStorage(bg_model->storage);
+        
+        cvMorphologyEx( bg_model->foreground, bg_model->foreground, 0, 0, CV_MOP_OPEN, 1 );
+        cvMorphologyEx( bg_model->foreground, bg_model->foreground, 0, 0, CV_MOP_CLOSE, 1 );
+        
+        cvFindContours( bg_model->foreground, bg_model->storage, &first_seq, sizeof(CvContour), CV_RETR_LIST );
+        for( seq = first_seq; seq; seq = seq->h_next )
+        {
+            CvContour* cnt = (CvContour*)seq;
+            if( cnt->rect.width * cnt->rect.height < bg_model->params.minArea )
+            {
+                //delete small contour
+                prev_seq = seq->h_prev;
+                if( prev_seq )
+                {
+                    prev_seq->h_next = seq->h_next;
+                    if( seq->h_next ) seq->h_next->h_prev = prev_seq;
+                }
+                else
+                {
+                    first_seq = seq->h_next;
+                    if( seq->h_next ) seq->h_next->h_prev = NULL;
+                }
+            }
+            else
+            {
+                region_count++;
+            }
+        }
+        bg_model->foreground_regions = first_seq;
+        cvZero(bg_model->foreground);
+        cvDrawContours(bg_model->foreground, first_seq, CV_RGB(0, 0, 255), CV_RGB(0, 0, 255), 10, -1);
+        
+        return region_count; 
+    }
+    
+    return 1;
+}
+
+/* End of file. */
+
index 4f44dd9..c940c65 100644 (file)
 
 #include "precomp.hpp"
 
+CV_IMPL CvSubdiv2D *
+cvCreateSubdiv2D( int subdiv_type, int header_size,
+                  int vtx_size, int quadedge_size, CvMemStorage * storage )
+{
+    if( !storage )
+        CV_Error( CV_StsNullPtr, "" );
+
+    if( header_size < (int)sizeof( CvSubdiv2D ) ||
+        quadedge_size < (int)sizeof( CvQuadEdge2D ) ||
+        vtx_size < (int)sizeof( CvSubdiv2DPoint ))
+        CV_Error( CV_StsBadSize, "" );
+
+    return (CvSubdiv2D *)cvCreateGraph( subdiv_type, header_size,
+                                        vtx_size, quadedge_size, storage );
+}
+
+
+/****************************************************************************************\
+*                                    Quad Edge  algebra                                  *
+\****************************************************************************************/
+
+static CvSubdiv2DEdge
+cvSubdiv2DMakeEdge( CvSubdiv2D * subdiv )
+{
+    if( !subdiv )
+        CV_Error( CV_StsNullPtr, "" );
+
+    CvQuadEdge2D* edge = (CvQuadEdge2D*)cvSetNew( (CvSet*)subdiv->edges );
+    memset( edge->pt, 0, sizeof( edge->pt ));
+    CvSubdiv2DEdge edgehandle = (CvSubdiv2DEdge) edge;
+
+    edge->next[0] = edgehandle;
+    edge->next[1] = edgehandle + 3;
+    edge->next[2] = edgehandle + 2;
+    edge->next[3] = edgehandle + 1;
+
+    subdiv->quad_edges++;
+    return edgehandle;
+}
+
+
+static CvSubdiv2DPoint *
+cvSubdiv2DAddPoint( CvSubdiv2D * subdiv, CvPoint2D32f pt, int is_virtual )
+{
+    CvSubdiv2DPoint* subdiv_point = (CvSubdiv2DPoint*)cvSetNew( (CvSet*)subdiv );
+    if( subdiv_point )
+    {
+        memset( subdiv_point, 0, subdiv->elem_size );
+        subdiv_point->pt = pt;
+        subdiv_point->first = 0;
+        subdiv_point->flags |= is_virtual ? CV_SUBDIV2D_VIRTUAL_POINT_FLAG : 0;
+               subdiv_point->id = -1;
+    }
+
+    return subdiv_point;
+}
+
+
+static void
+cvSubdiv2DSplice( CvSubdiv2DEdge edgeA, CvSubdiv2DEdge edgeB )
+{
+    CvSubdiv2DEdge *a_next = &CV_SUBDIV2D_NEXT_EDGE( edgeA );
+    CvSubdiv2DEdge *b_next = &CV_SUBDIV2D_NEXT_EDGE( edgeB );
+    CvSubdiv2DEdge a_rot = cvSubdiv2DRotateEdge( *a_next, 1 );
+    CvSubdiv2DEdge b_rot = cvSubdiv2DRotateEdge( *b_next, 1 );
+    CvSubdiv2DEdge *a_rot_next = &CV_SUBDIV2D_NEXT_EDGE( a_rot );
+    CvSubdiv2DEdge *b_rot_next = &CV_SUBDIV2D_NEXT_EDGE( b_rot );
+    CvSubdiv2DEdge t;
+
+    CV_SWAP( *a_next, *b_next, t );
+    CV_SWAP( *a_rot_next, *b_rot_next, t );
+}
+
+
+static void
+cvSubdiv2DSetEdgePoints( CvSubdiv2DEdge edge,
+                         CvSubdiv2DPoint * org_pt, CvSubdiv2DPoint * dst_pt )
+{
+    CvQuadEdge2D *quadedge = (CvQuadEdge2D *) (edge & ~3);
+
+    if( !quadedge )
+        CV_Error( CV_StsNullPtr, "" );
+
+    quadedge->pt[edge & 3] = org_pt;
+    quadedge->pt[(edge + 2) & 3] = dst_pt;
+}
+
+
+static void
+cvSubdiv2DDeleteEdge( CvSubdiv2D * subdiv, CvSubdiv2DEdge edge )
+{
+    CvQuadEdge2D *quadedge = (CvQuadEdge2D *) (edge & ~3);
+
+    if( !subdiv || !quadedge )
+        CV_Error( CV_StsNullPtr, "" );
+
+    cvSubdiv2DSplice( edge, cvSubdiv2DGetEdge( edge, CV_PREV_AROUND_ORG ));
+
+    CvSubdiv2DEdge sym_edge = cvSubdiv2DSymEdge( edge );
+    cvSubdiv2DSplice( sym_edge, cvSubdiv2DGetEdge( sym_edge, CV_PREV_AROUND_ORG ));
+
+    cvSetRemoveByPtr( (CvSet*)(subdiv->edges), quadedge );
+    subdiv->quad_edges--;
+}
+
+
+static CvSubdiv2DEdge
+cvSubdiv2DConnectEdges( CvSubdiv2D * subdiv, CvSubdiv2DEdge edgeA, CvSubdiv2DEdge edgeB )
+{
+    if( !subdiv )
+        CV_Error( CV_StsNullPtr, "" );
+
+    CvSubdiv2DEdge new_edge = cvSubdiv2DMakeEdge( subdiv );
+
+    cvSubdiv2DSplice( new_edge, cvSubdiv2DGetEdge( edgeA, CV_NEXT_AROUND_LEFT ));
+    cvSubdiv2DSplice( cvSubdiv2DSymEdge( new_edge ), edgeB );
+
+    CvSubdiv2DPoint* dstA = cvSubdiv2DEdgeDst( edgeA );
+    CvSubdiv2DPoint* orgB = cvSubdiv2DEdgeOrg( edgeB );
+    cvSubdiv2DSetEdgePoints( new_edge, dstA, orgB );
+
+    return new_edge;
+}
+
+
+static void
+cvSubdiv2DSwapEdges( CvSubdiv2DEdge edge )
+{
+    CvSubdiv2DEdge sym_edge = cvSubdiv2DSymEdge( edge );
+    CvSubdiv2DEdge a = cvSubdiv2DGetEdge( edge, CV_PREV_AROUND_ORG );
+    CvSubdiv2DEdge b = cvSubdiv2DGetEdge( sym_edge, CV_PREV_AROUND_ORG );
+    CvSubdiv2DPoint *dstB, *dstA;
+
+    cvSubdiv2DSplice( edge, a );
+    cvSubdiv2DSplice( sym_edge, b );
+
+    dstA = cvSubdiv2DEdgeDst( a );
+    dstB = cvSubdiv2DEdgeDst( b );
+    cvSubdiv2DSetEdgePoints( edge, dstA, dstB );
+
+    cvSubdiv2DSplice( edge, cvSubdiv2DGetEdge( a, CV_NEXT_AROUND_LEFT ));
+    cvSubdiv2DSplice( sym_edge, cvSubdiv2DGetEdge( b, CV_NEXT_AROUND_LEFT ));
+}
+
+
+static int
+icvIsRightOf( CvPoint2D32f& pt, CvSubdiv2DEdge edge )
+{
+    CvSubdiv2DPoint *org = cvSubdiv2DEdgeOrg(edge), *dst = cvSubdiv2DEdgeDst(edge);
+    double cw_area = cvTriangleArea( pt, dst->pt, org->pt );
+
+    return (cw_area > 0) - (cw_area < 0);
+}
+
+
+CV_IMPL CvSubdiv2DPointLocation
+cvSubdiv2DLocate( CvSubdiv2D * subdiv, CvPoint2D32f pt,
+                  CvSubdiv2DEdge * _edge, CvSubdiv2DPoint ** _point )
+{
+    CvSubdiv2DPoint *point = 0;
+    int right_of_curr = 0;
+
+    if( !subdiv )
+        CV_Error( CV_StsNullPtr, "" );
+
+    if( !CV_IS_SUBDIV2D(subdiv) )
+        CV_Error( CV_StsBadFlag, "" );
+
+    int i, max_edges = subdiv->quad_edges * 4;
+    CvSubdiv2DEdge edge = subdiv->recent_edge;
+
+    if( max_edges == 0 )
+        CV_Error( CV_StsBadSize, "" );
+    CV_Assert(edge != 0);
+
+    if( pt.x < subdiv->topleft.x || pt.y < subdiv->topleft.y ||
+        pt.x >= subdiv->bottomright.x || pt.y >= subdiv->bottomright.y )
+        CV_Error( CV_StsOutOfRange, "" );
+
+    CvSubdiv2DPointLocation location = CV_PTLOC_ERROR;
+
+    right_of_curr = icvIsRightOf( pt, edge );
+    if( right_of_curr > 0 )
+    {
+        edge = cvSubdiv2DSymEdge( edge );
+        right_of_curr = -right_of_curr;
+    }
+
+    for( i = 0; i < max_edges; i++ )
+    {
+        CvSubdiv2DEdge onext_edge = cvSubdiv2DNextEdge( edge );
+        CvSubdiv2DEdge dprev_edge = cvSubdiv2DGetEdge( edge, CV_PREV_AROUND_DST );
+
+        int right_of_onext = icvIsRightOf( pt, onext_edge );
+        int right_of_dprev = icvIsRightOf( pt, dprev_edge );
+
+        if( right_of_dprev > 0 )
+        {
+            if( right_of_onext > 0 || (right_of_onext == 0 && right_of_curr == 0) )
+            {
+                location = CV_PTLOC_INSIDE;
+                goto exit;
+            }
+            else
+            {
+                right_of_curr = right_of_onext;
+                edge = onext_edge;
+            }
+        }
+        else
+        {
+            if( right_of_onext > 0 )
+            {
+                if( right_of_dprev == 0 && right_of_curr == 0 )
+                {
+                    location = CV_PTLOC_INSIDE;
+                    goto exit;
+                }
+                else
+                {
+                    right_of_curr = right_of_dprev;
+                    edge = dprev_edge;
+                }
+            }
+            else if( right_of_curr == 0 &&
+                     icvIsRightOf( cvSubdiv2DEdgeDst( onext_edge )->pt, edge ) >= 0 )
+            {
+                edge = cvSubdiv2DSymEdge( edge );
+            }
+            else
+            {
+                right_of_curr = right_of_onext;
+                edge = onext_edge;
+            }
+        }
+    }
+exit:
+    
+    subdiv->recent_edge = edge;
+
+    if( location == CV_PTLOC_INSIDE )
+    {
+        double t1, t2, t3;
+        CvPoint2D32f org_pt = cvSubdiv2DEdgeOrg( edge )->pt;
+        CvPoint2D32f dst_pt = cvSubdiv2DEdgeDst( edge )->pt;
+
+        t1 = fabs( pt.x - org_pt.x );
+        t1 += fabs( pt.y - org_pt.y );
+        t2 = fabs( pt.x - dst_pt.x );
+        t2 += fabs( pt.y - dst_pt.y );
+        t3 = fabs( org_pt.x - dst_pt.x );
+        t3 += fabs( org_pt.y - dst_pt.y );
+
+        if( t1 < FLT_EPSILON )
+        {
+            location = CV_PTLOC_VERTEX;
+            point = cvSubdiv2DEdgeOrg( edge );
+            edge = 0;
+        }
+        else if( t2 < FLT_EPSILON )
+        {
+            location = CV_PTLOC_VERTEX;
+            point = cvSubdiv2DEdgeDst( edge );
+            edge = 0;
+        }
+        else if( (t1 < t3 || t2 < t3) &&
+                 fabs( cvTriangleArea( pt, org_pt, dst_pt )) < FLT_EPSILON )
+        {
+            location = CV_PTLOC_ON_EDGE;
+            point = 0;
+        }
+    }
+
+    if( location == CV_PTLOC_ERROR )
+    {
+        edge = 0;
+        point = 0;
+    }
+
+    if( _edge )
+        *_edge = edge;
+    if( _point )
+        *_point = point;
+
+    return location;
+}
+
+
+CV_INLINE int
+icvIsPtInCircle3( CvPoint2D32f pt, CvPoint2D32f a, CvPoint2D32f b, CvPoint2D32f c )
+{
+    const double eps = FLT_EPSILON*0.125;
+    double val = ((double)a.x * a.x + (double)a.y * a.y) * cvTriangleArea( b, c, pt );
+    val -= ((double)b.x * b.x + (double)b.y * b.y) * cvTriangleArea( a, c, pt );
+    val += ((double)c.x * c.x + (double)c.y * c.y) * cvTriangleArea( a, b, pt );
+    val -= ((double)pt.x * pt.x + (double)pt.y * pt.y) * cvTriangleArea( a, b, c );
+
+    return val > eps ? 1 : val < -eps ? -1 : 0;
+}
+
+
+CV_IMPL CvSubdiv2DPoint *
+cvSubdivDelaunay2DInsert( CvSubdiv2D * subdiv, CvPoint2D32f pt )
+{
+    CvSubdiv2DPointLocation location = CV_PTLOC_ERROR;
+
+    CvSubdiv2DPoint *curr_point = 0, *first_point = 0;
+    CvSubdiv2DEdge curr_edge = 0, deleted_edge = 0, base_edge = 0;
+    int i, max_edges;
+
+    if( !subdiv )
+        CV_Error( CV_StsNullPtr, "" );
+
+    if( !CV_IS_SUBDIV2D(subdiv) )
+        CV_Error( CV_StsBadFlag, "" );
+
+    location = cvSubdiv2DLocate( subdiv, pt, &curr_edge, &curr_point );
+
+    switch (location)
+    {
+    case CV_PTLOC_ERROR:
+        CV_Error( CV_StsBadSize, "" );
+
+    case CV_PTLOC_OUTSIDE_RECT:
+        CV_Error( CV_StsOutOfRange, "" );
+
+    case CV_PTLOC_VERTEX:
+        break;
+
+    case CV_PTLOC_ON_EDGE:
+        deleted_edge = curr_edge;
+        subdiv->recent_edge = curr_edge = cvSubdiv2DGetEdge( curr_edge, CV_PREV_AROUND_ORG );
+        cvSubdiv2DDeleteEdge( subdiv, deleted_edge );
+        /* no break */
+
+    case CV_PTLOC_INSIDE:
+
+        assert( curr_edge != 0 );
+        subdiv->is_geometry_valid = 0;
+
+        curr_point = cvSubdiv2DAddPoint( subdiv, pt, 0 );
+        base_edge = cvSubdiv2DMakeEdge( subdiv );
+        first_point = cvSubdiv2DEdgeOrg( curr_edge );
+        cvSubdiv2DSetEdgePoints( base_edge, first_point, curr_point );
+        cvSubdiv2DSplice( base_edge, curr_edge );
+
+        do
+        {
+            base_edge = cvSubdiv2DConnectEdges( subdiv, curr_edge,
+                                                cvSubdiv2DSymEdge( base_edge ));
+            curr_edge = cvSubdiv2DGetEdge( base_edge, CV_PREV_AROUND_ORG );
+        }
+        while( cvSubdiv2DEdgeDst( curr_edge ) != first_point );
+
+        curr_edge = cvSubdiv2DGetEdge( base_edge, CV_PREV_AROUND_ORG );
+
+        max_edges = subdiv->quad_edges * 4;
+
+        for( i = 0; i < max_edges; i++ )
+        {
+            CvSubdiv2DPoint *temp_dst = 0, *curr_org = 0, *curr_dst = 0;
+            CvSubdiv2DEdge temp_edge = cvSubdiv2DGetEdge( curr_edge, CV_PREV_AROUND_ORG );
+
+            temp_dst = cvSubdiv2DEdgeDst( temp_edge );
+            curr_org = cvSubdiv2DEdgeOrg( curr_edge );
+            curr_dst = cvSubdiv2DEdgeDst( curr_edge );
+
+            if( icvIsRightOf( temp_dst->pt, curr_edge ) > 0 &&
+                icvIsPtInCircle3( curr_org->pt, temp_dst->pt,
+                                  curr_dst->pt, curr_point->pt ) < 0 )
+            {
+                cvSubdiv2DSwapEdges( curr_edge );
+                curr_edge = cvSubdiv2DGetEdge( curr_edge, CV_PREV_AROUND_ORG );
+            }
+            else if( curr_org == first_point )
+            {
+                break;
+            }
+            else
+            {
+                curr_edge = cvSubdiv2DGetEdge( cvSubdiv2DNextEdge( curr_edge ),
+                                               CV_PREV_AROUND_LEFT );
+            }
+        }
+        break;
+    default:
+        CV_Error_(CV_StsError, ("cvSubdiv2DLocate returned invalid location = %d", location) );
+    }
+
+    return curr_point;
+}
+
+
+CV_IMPL void
+cvInitSubdivDelaunay2D( CvSubdiv2D * subdiv, CvRect rect )
+{
+    float big_coord = 3.f * MAX( rect.width, rect.height );
+    CvPoint2D32f ppA, ppB, ppC;
+    CvSubdiv2DPoint *pA, *pB, *pC;
+    CvSubdiv2DEdge edge_AB, edge_BC, edge_CA;
+    float rx = (float) rect.x;
+    float ry = (float) rect.y;
+
+    if( !subdiv )
+        CV_Error( CV_StsNullPtr, "" );
+
+    cvClearSet( (CvSet *) (subdiv->edges) );
+    cvClearSet( (CvSet *) subdiv );
+
+    subdiv->quad_edges = 0;
+    subdiv->recent_edge = 0;
+    subdiv->is_geometry_valid = 0;
+
+    subdiv->topleft = cvPoint2D32f( rx, ry );
+    subdiv->bottomright = cvPoint2D32f( rx + rect.width, ry + rect.height );
+
+    ppA = cvPoint2D32f( rx + big_coord, ry );
+    ppB = cvPoint2D32f( rx, ry + big_coord );
+    ppC = cvPoint2D32f( rx - big_coord, ry - big_coord );
+
+    pA = cvSubdiv2DAddPoint( subdiv, ppA, 0 );
+    pB = cvSubdiv2DAddPoint( subdiv, ppB, 0 );
+    pC = cvSubdiv2DAddPoint( subdiv, ppC, 0 );
+
+    edge_AB = cvSubdiv2DMakeEdge( subdiv );
+    edge_BC = cvSubdiv2DMakeEdge( subdiv );
+    edge_CA = cvSubdiv2DMakeEdge( subdiv );
+
+    cvSubdiv2DSetEdgePoints( edge_AB, pA, pB );
+    cvSubdiv2DSetEdgePoints( edge_BC, pB, pC );
+    cvSubdiv2DSetEdgePoints( edge_CA, pC, pA );
+
+    cvSubdiv2DSplice( edge_AB, cvSubdiv2DSymEdge( edge_CA ));
+    cvSubdiv2DSplice( edge_BC, cvSubdiv2DSymEdge( edge_AB ));
+    cvSubdiv2DSplice( edge_CA, cvSubdiv2DSymEdge( edge_BC ));
+
+    subdiv->recent_edge = edge_AB;
+}
+
+
+CV_IMPL void
+cvClearSubdivVoronoi2D( CvSubdiv2D * subdiv )
+{
+    int elem_size;
+    int i, total;
+    CvSeqReader reader;
+
+    if( !subdiv )
+        CV_Error( CV_StsNullPtr, "" );
+
+    /* clear pointers to voronoi points */
+    total = subdiv->edges->total;
+    elem_size = subdiv->edges->elem_size;
+
+    cvStartReadSeq( (CvSeq *) (subdiv->edges), &reader, 0 );
+
+    for( i = 0; i < total; i++ )
+    {
+        CvQuadEdge2D *quadedge = (CvQuadEdge2D *) reader.ptr;
+
+        quadedge->pt[1] = quadedge->pt[3] = 0;
+        CV_NEXT_SEQ_ELEM( elem_size, reader );
+    }
+
+    /* remove voronoi points */
+    total = subdiv->total;
+    elem_size = subdiv->elem_size;
+
+    cvStartReadSeq( (CvSeq *) subdiv, &reader, 0 );
+
+    for( i = 0; i < total; i++ )
+    {
+        CvSubdiv2DPoint *pt = (CvSubdiv2DPoint *) reader.ptr;
+
+        /* check for virtual point. it is also check that the point exists */
+        if( pt->flags & CV_SUBDIV2D_VIRTUAL_POINT_FLAG )
+        {
+            cvSetRemoveByPtr( (CvSet*)subdiv, pt );
+        }
+        CV_NEXT_SEQ_ELEM( elem_size, reader );
+    }
+
+    subdiv->is_geometry_valid = 0;
+}
+
+
+static void
+icvCreateCenterNormalLine( CvSubdiv2DEdge edge, double *_a, double *_b, double *_c )
+{
+    CvPoint2D32f org = cvSubdiv2DEdgeOrg( edge )->pt;
+    CvPoint2D32f dst = cvSubdiv2DEdgeDst( edge )->pt;
+    
+    double a = dst.x - org.x;
+    double b = dst.y - org.y;
+    double c = -(a * (dst.x + org.x) + b * (dst.y + org.y));
+    
+    *_a = a + a;
+    *_b = b + b;
+    *_c = c;
+}
+
+
+static void
+icvIntersectLines3( double *a0, double *b0, double *c0,
+                   double *a1, double *b1, double *c1, CvPoint2D32f * point )
+{
+    double det = a0[0] * b1[0] - a1[0] * b0[0];
+    
+    if( det != 0 )
+    {
+        det = 1. / det;
+        point->x = (float) ((b0[0] * c1[0] - b1[0] * c0[0]) * det);
+        point->y = (float) ((a1[0] * c0[0] - a0[0] * c1[0]) * det);
+    }
+    else
+    {
+        point->x = point->y = FLT_MAX;
+    }
+}
+
+
+CV_IMPL void
+cvCalcSubdivVoronoi2D( CvSubdiv2D * subdiv )
+{
+    CvSeqReader reader;
+    int i, total, elem_size;
+
+    if( !subdiv )
+        CV_Error( CV_StsNullPtr, "" );
+
+    /* check if it is already calculated */
+    if( subdiv->is_geometry_valid )
+        return;
+
+    total = subdiv->edges->total;
+    elem_size = subdiv->edges->elem_size;
+
+    cvClearSubdivVoronoi2D( subdiv );
+
+    cvStartReadSeq( (CvSeq *) (subdiv->edges), &reader, 0 );
+
+    if( total <= 3 )
+        return;
+
+    /* skip first three edges (bounding triangle) */
+    for( i = 0; i < 3; i++ )
+        CV_NEXT_SEQ_ELEM( elem_size, reader );
+
+    /* loop through all quad-edges */
+    for( ; i < total; i++ )
+    {
+        CvQuadEdge2D *quadedge = (CvQuadEdge2D *) (reader.ptr);
+
+        if( CV_IS_SET_ELEM( quadedge ))
+        {
+            CvSubdiv2DEdge edge0 = (CvSubdiv2DEdge) quadedge, edge1, edge2;
+            double a0, b0, c0, a1, b1, c1;
+            CvPoint2D32f virt_point;
+            CvSubdiv2DPoint *voronoi_point;
+
+            if( !quadedge->pt[3] )
+            {
+                edge1 = cvSubdiv2DGetEdge( edge0, CV_NEXT_AROUND_LEFT );
+                edge2 = cvSubdiv2DGetEdge( edge1, CV_NEXT_AROUND_LEFT );
+
+                icvCreateCenterNormalLine( edge0, &a0, &b0, &c0 );
+                icvCreateCenterNormalLine( edge1, &a1, &b1, &c1 );
+
+                icvIntersectLines3( &a0, &b0, &c0, &a1, &b1, &c1, &virt_point );
+                if( fabs( virt_point.x ) < FLT_MAX * 0.5 &&
+                    fabs( virt_point.y ) < FLT_MAX * 0.5 )
+                {
+                    voronoi_point = cvSubdiv2DAddPoint( subdiv, virt_point, 1 );
+
+                    quadedge->pt[3] =
+                        ((CvQuadEdge2D *) (edge1 & ~3))->pt[3 - (edge1 & 2)] =
+                        ((CvQuadEdge2D *) (edge2 & ~3))->pt[3 - (edge2 & 2)] = voronoi_point;
+                }
+            }
+
+            if( !quadedge->pt[1] )
+            {
+                edge1 = cvSubdiv2DGetEdge( edge0, CV_NEXT_AROUND_RIGHT );
+                edge2 = cvSubdiv2DGetEdge( edge1, CV_NEXT_AROUND_RIGHT );
+
+                icvCreateCenterNormalLine( edge0, &a0, &b0, &c0 );
+                icvCreateCenterNormalLine( edge1, &a1, &b1, &c1 );
+
+                icvIntersectLines3( &a0, &b0, &c0, &a1, &b1, &c1, &virt_point );
+
+                if( fabs( virt_point.x ) < FLT_MAX * 0.5 &&
+                    fabs( virt_point.y ) < FLT_MAX * 0.5 )
+                {
+                    voronoi_point = cvSubdiv2DAddPoint( subdiv, virt_point, 1 );
+
+                    quadedge->pt[1] =
+                        ((CvQuadEdge2D *) (edge1 & ~3))->pt[1 + (edge1 & 2)] =
+                        ((CvQuadEdge2D *) (edge2 & ~3))->pt[1 + (edge2 & 2)] = voronoi_point;
+                }
+            }
+        }
+
+        CV_NEXT_SEQ_ELEM( elem_size, reader );
+    }
+
+    subdiv->is_geometry_valid = 1;
+}
+
+
+static int
+icvIsRightOf2( const CvPoint2D32f& pt, const CvPoint2D32f& org, const CvPoint2D32f& diff )
+{
+    double cw_area = ((double)org.x - pt.x)*diff.y - ((double)org.y - pt.y)*diff.x;
+    return (cw_area > 0) - (cw_area < 0);
+}
+
+
+CV_IMPL CvSubdiv2DPoint*
+cvFindNearestPoint2D( CvSubdiv2D* subdiv, CvPoint2D32f pt )
+{
+    CvSubdiv2DPoint* point = 0;
+    CvPoint2D32f start;
+    CvPoint2D32f diff;
+    CvSubdiv2DPointLocation loc;
+    CvSubdiv2DEdge edge; 
+    int i;
+    
+    if( !subdiv )
+        CV_Error( CV_StsNullPtr, "" );
+
+    if( !CV_IS_SUBDIV2D( subdiv ))
+        CV_Error( CV_StsNullPtr, "" );
+    
+    if( subdiv->edges->active_count <= 3 )
+        return 0;
+
+    if( !subdiv->is_geometry_valid )
+        cvCalcSubdivVoronoi2D( subdiv );
+
+    loc = cvSubdiv2DLocate( subdiv, pt, &edge, &point );
+
+    switch( loc )
+    {
+    case CV_PTLOC_ON_EDGE:
+    case CV_PTLOC_INSIDE:
+        break;
+    default:
+        return point;
+    }
+
+    point = 0;
+
+    start = cvSubdiv2DEdgeOrg( edge )->pt;
+    diff.x = pt.x - start.x;
+    diff.y = pt.y - start.y;
+
+    edge = cvSubdiv2DRotateEdge( edge, 1 );
+
+    for( i = 0; i < subdiv->total; i++ )
+    {
+        CvPoint2D32f t;
+        
+        for(;;)
+        {
+            assert( cvSubdiv2DEdgeDst( edge ));
+            
+            t = cvSubdiv2DEdgeDst( edge )->pt;
+            if( icvIsRightOf2( t, start, diff ) >= 0 )
+                break;
+
+            edge = cvSubdiv2DGetEdge( edge, CV_NEXT_AROUND_LEFT );
+        }
+
+        for(;;)
+        {
+            assert( cvSubdiv2DEdgeOrg( edge ));
+
+            t = cvSubdiv2DEdgeOrg( edge )->pt;
+            if( icvIsRightOf2( t, start, diff ) < 0 )
+                break;
+
+            edge = cvSubdiv2DGetEdge( edge, CV_PREV_AROUND_LEFT );
+        }
+
+        {
+            CvPoint2D32f tempDiff = cvSubdiv2DEdgeDst( edge )->pt;
+            t = cvSubdiv2DEdgeOrg( edge )->pt;
+            tempDiff.x -= t.x;
+            tempDiff.y -= t.y;
+
+            if( icvIsRightOf2( pt, t, tempDiff ) >= 0 )
+            {
+                point = cvSubdiv2DEdgeOrg( cvSubdiv2DRotateEdge( edge, 3 ));
+                break;
+            }
+        }
+
+        edge = cvSubdiv2DSymEdge( edge );
+    }
+
+    return point;
+}
+
 CV_IMPL int
 icvSubdiv2DCheck( CvSubdiv2D* subdiv )
 {
diff --git a/modules/legacy/test/test_nearestneighbors.cpp b/modules/legacy/test/test_nearestneighbors.cpp
new file mode 100644 (file)
index 0000000..b3e4735
--- /dev/null
@@ -0,0 +1,264 @@
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+//  By downloading, copying, installing or using the software you agree to this license.
+//  If you do not agree to this license, do not download, install,
+//  copy or use the software.
+//
+//
+//                           License Agreement
+//                For Open Source Computer Vision Library
+//
+// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
+// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+//   * Redistribution's of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//
+//   * Redistribution's in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//
+//   * The name of the copyright holders may not be used to endorse or promote products
+//     derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+#include "test_precomp.hpp"
+
+#include <algorithm>
+#include <vector>
+#include <iostream>
+
+using namespace cv;
+using namespace cv::flann;
+
+//--------------------------------------------------------------------------------
+class NearestNeighborTest : public cvtest::BaseTest
+{
+public:
+    NearestNeighborTest() {}
+protected:
+    static const int minValue = 0;
+    static const int maxValue = 1;
+    static const int dims = 30;
+    static const int featuresCount = 2000;
+    static const int K = 1; // * should also test 2nd nn etc.?
+
+
+    virtual void run( int start_from );
+    virtual void createModel( const Mat& data ) = 0;
+    virtual int findNeighbors( Mat& points, Mat& neighbors ) = 0;
+    virtual int checkGetPoins( const Mat& data );
+    virtual int checkFindBoxed();
+    virtual int checkFind( const Mat& data );
+    virtual void releaseModel() = 0;
+};
+
+int NearestNeighborTest::checkGetPoins( const Mat& )
+{
+   return cvtest::TS::OK;
+}
+
+int NearestNeighborTest::checkFindBoxed()
+{
+    return cvtest::TS::OK;
+}
+
+int NearestNeighborTest::checkFind( const Mat& data )
+{
+    int code = cvtest::TS::OK;
+    int pointsCount = 1000;
+    float noise = 0.2f;
+
+    RNG rng;
+    Mat points( pointsCount, dims, CV_32FC1 );
+    Mat results( pointsCount, K, CV_32SC1 );
+
+    std::vector<int> fmap( pointsCount );
+    for( int pi = 0; pi < pointsCount; pi++ )
+    {
+        int fi = rng.next() % featuresCount;
+        fmap[pi] = fi;
+        for( int d = 0; d < dims; d++ )
+            points.at<float>(pi, d) = data.at<float>(fi, d) + rng.uniform(0.0f, 1.0f) * noise;
+    }
+
+    code = findNeighbors( points, results );
+
+    if( code == cvtest::TS::OK )
+    {
+        int correctMatches = 0;
+        for( int pi = 0; pi < pointsCount; pi++ )
+        {
+            if( fmap[pi] == results.at<int>(pi, 0) )
+                correctMatches++;
+        }
+
+        double correctPerc = correctMatches / (double)pointsCount;
+        if (correctPerc < .75)
+        {
+            ts->printf( cvtest::TS::LOG, "correct_perc = %d\n", correctPerc );
+            code = cvtest::TS::FAIL_BAD_ACCURACY;
+        }
+    }
+
+    return code;
+}
+
+void NearestNeighborTest::run( int /*start_from*/ ) {
+    int code = cvtest::TS::OK, tempCode;
+    Mat desc( featuresCount, dims, CV_32FC1 );
+    randu( desc, Scalar(minValue), Scalar(maxValue) );
+
+    createModel( desc );
+    
+    tempCode = checkGetPoins( desc );
+    if( tempCode != cvtest::TS::OK )
+    {
+        ts->printf( cvtest::TS::LOG, "bad accuracy of GetPoints \n" );
+        code = tempCode;
+    }
+
+    tempCode = checkFindBoxed();
+    if( tempCode != cvtest::TS::OK )
+    {
+        ts->printf( cvtest::TS::LOG, "bad accuracy of FindBoxed \n" );
+        code = tempCode;
+    }
+
+    tempCode = checkFind( desc );
+    if( tempCode != cvtest::TS::OK )
+    {
+        ts->printf( cvtest::TS::LOG, "bad accuracy of Find \n" );
+        code = tempCode;
+    }
+    
+    releaseModel();
+    
+    ts->set_failed_test_info( code );
+}
+
+//--------------------------------------------------------------------------------
+class CV_LSHTest : public NearestNeighborTest
+{
+public:
+    CV_LSHTest() {}
+protected:
+    virtual void createModel( const Mat& data );
+    virtual int findNeighbors( Mat& points, Mat& neighbors );
+    virtual void releaseModel();
+    struct CvLSH* lsh;
+    CvMat desc;
+};
+
+void CV_LSHTest::createModel( const Mat& data )
+{
+    desc = data;
+    lsh = cvCreateMemoryLSH( data.cols, data.rows, 70, 20, CV_32FC1 );
+    cvLSHAdd( lsh, &desc );
+}
+
+int CV_LSHTest::findNeighbors( Mat& points, Mat& neighbors )
+{
+    const int emax = 20;
+    Mat dist( points.rows, neighbors.cols, CV_64FC1);
+    CvMat _dist = dist, _points = points, _neighbors = neighbors;
+    cvLSHQuery( lsh, &_points, &_neighbors, &_dist, neighbors.cols, emax );
+    return cvtest::TS::OK;
+}
+
+void CV_LSHTest::releaseModel()
+{
+    cvReleaseLSH( &lsh );
+}
+
+//--------------------------------------------------------------------------------
+class CV_FeatureTreeTest_C : public NearestNeighborTest
+{
+public:
+    CV_FeatureTreeTest_C() {}
+protected:
+    virtual int findNeighbors( Mat& points, Mat& neighbors );
+    virtual void releaseModel();
+    CvFeatureTree* tr;
+    CvMat desc;
+};
+
+int CV_FeatureTreeTest_C::findNeighbors( Mat& points, Mat& neighbors )
+{
+    const int emax = 20;
+    Mat dist( points.rows, neighbors.cols, CV_64FC1);
+    CvMat _dist = dist, _points = points, _neighbors = neighbors;
+    cvFindFeatures( tr, &_points, &_neighbors, &_dist, neighbors.cols, emax );
+    return cvtest::TS::OK;
+}
+
+void CV_FeatureTreeTest_C::releaseModel()
+{
+    cvReleaseFeatureTree( tr );
+}
+
+//--------------------------------------
+class CV_SpillTreeTest_C : public CV_FeatureTreeTest_C
+{
+public:
+    CV_SpillTreeTest_C() {}
+protected:
+    virtual void createModel( const Mat& data );
+};
+
+void CV_SpillTreeTest_C::createModel( const Mat& data )
+{
+    desc = data;
+    tr = cvCreateSpillTree( &desc );
+}
+
+//--------------------------------------
+class CV_KDTreeTest_C : public CV_FeatureTreeTest_C
+{
+public:
+    CV_KDTreeTest_C() {}
+protected:
+    virtual void createModel( const Mat& data );
+    virtual int checkFindBoxed();
+};
+
+void CV_KDTreeTest_C::createModel( const Mat& data )
+{
+    desc = data;
+    tr = cvCreateKDTree( &desc );
+}
+
+int CV_KDTreeTest_C::checkFindBoxed()
+{
+    Mat min(1, dims, CV_32FC1 ), max(1, dims, CV_32FC1 ), indices( 1, 1, CV_32SC1 );
+    float l = minValue, r = maxValue;
+    min.setTo(Scalar(l)), max.setTo(Scalar(r));
+    CvMat _min = min, _max = max, _indices = indices;
+    // TODO check indices
+    if( cvFindFeaturesBoxed( tr, &_min, &_max, &_indices ) != featuresCount )
+        return cvtest::TS::FAIL_BAD_ACCURACY;
+    return cvtest::TS::OK;
+}
+
+
+TEST(Features2d_LSH, regression) { CV_LSHTest test; test.safe_run(); }
+TEST(Features2d_SpillTree, regression) { CV_SpillTreeTest_C test; test.safe_run(); }
+TEST(Features2d_KDTree_C, regression) { CV_KDTreeTest_C test; test.safe_run(); }
similarity index 99%
rename from modules/video/test/test_optflow.cpp
rename to modules/legacy/test/test_optflow.cpp
index 38a24a8..2ff1330 100644 (file)
@@ -41,6 +41,7 @@
 //M*/
 
 #include "test_precomp.hpp"
+#include "opencv2/video/tracking.hpp"
 
 #include <string>
 #include <iostream>
index f28d167..06b45a7 100644 (file)
@@ -6,6 +6,7 @@
 #include "opencv2/imgproc/imgproc_c.h"
 #include "opencv2/highgui/highgui.hpp"
 #include "opencv2/highgui/highgui_c.h"
+#include "opencv2/legacy/legacy.hpp"
 #include <iostream>
 
 #endif
diff --git a/modules/legacy/test/test_stereomatching.cpp b/modules/legacy/test/test_stereomatching.cpp
new file mode 100644 (file)
index 0000000..21834b0
--- /dev/null
@@ -0,0 +1,722 @@
+/*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*/
+
+/*
+  This is a regression test for stereo matching algorithms. This test gets some quality metrics
+  discribed in "A Taxonomy and Evaluation of Dense Two-Frame Stereo Correspondence Algorithms".
+  Daniel Scharstein, Richard Szeliski
+*/
+
+#include "test_precomp.hpp"
+#include <limits>
+#include <cstdio>
+
+using namespace std;
+using namespace cv;
+
+const float EVAL_BAD_THRESH = 1.f;
+const int EVAL_TEXTURELESS_WIDTH = 3;
+const float EVAL_TEXTURELESS_THRESH = 4.f;
+const float EVAL_DISP_THRESH = 1.f;
+const float EVAL_DISP_GAP = 2.f;
+const int EVAL_DISCONT_WIDTH = 9;
+const int EVAL_IGNORE_BORDER = 10;
+
+const int ERROR_KINDS_COUNT = 6;
+
+//============================== quality measuring functions =================================================
+
+/*
+  Calculate textureless regions of image (regions where the squared horizontal intensity gradient averaged over
+  a square window of size=evalTexturelessWidth is below a threshold=evalTexturelessThresh) and textured regions.
+*/
+void computeTextureBasedMasks( const Mat& _img, Mat* texturelessMask, Mat* texturedMask,
+             int texturelessWidth = EVAL_TEXTURELESS_WIDTH, float texturelessThresh = EVAL_TEXTURELESS_THRESH )
+{
+    if( !texturelessMask && !texturedMask )
+        return;
+    if( _img.empty() )
+        CV_Error( CV_StsBadArg, "img is empty" );
+
+    Mat img = _img;
+    if( _img.channels() > 1)
+    {
+        Mat tmp; cvtColor( _img, tmp, CV_BGR2GRAY ); img = tmp;
+    }
+    Mat dxI; Sobel( img, dxI, CV_32FC1, 1, 0, 3 );
+    Mat dxI2; pow( dxI / 8.f/*normalize*/, 2, dxI2 );
+    Mat avgDxI2; boxFilter( dxI2, avgDxI2, CV_32FC1, Size(texturelessWidth,texturelessWidth) );
+
+    if( texturelessMask )
+        *texturelessMask = avgDxI2 < texturelessThresh;
+    if( texturedMask )
+        *texturedMask = avgDxI2 >= texturelessThresh;
+}
+
+void checkTypeAndSizeOfDisp( const Mat& dispMap, const Size* sz )
+{
+    if( dispMap.empty() )
+        CV_Error( CV_StsBadArg, "dispMap is empty" );
+    if( dispMap.type() != CV_32FC1 )
+        CV_Error( CV_StsBadArg, "dispMap must have CV_32FC1 type" );
+    if( sz && (dispMap.rows != sz->height || dispMap.cols != sz->width) )
+        CV_Error( CV_StsBadArg, "dispMap has incorrect size" );
+}
+
+void checkTypeAndSizeOfMask( const Mat& mask, Size sz )
+{
+    if( mask.empty() )
+        CV_Error( CV_StsBadArg, "mask is empty" );
+    if( mask.type() != CV_8UC1 )
+        CV_Error( CV_StsBadArg, "mask must have CV_8UC1 type" );
+    if( mask.rows != sz.height || mask.cols != sz.width )
+        CV_Error( CV_StsBadArg, "mask has incorrect size" );
+}
+
+void checkDispMapsAndUnknDispMasks( const Mat& leftDispMap, const Mat& rightDispMap,
+                                    const Mat& leftUnknDispMask, const Mat& rightUnknDispMask )
+{
+    // check type and size of disparity maps
+    checkTypeAndSizeOfDisp( leftDispMap, 0 );
+    if( !rightDispMap.empty() )
+    {
+        Size sz = leftDispMap.size();
+        checkTypeAndSizeOfDisp( rightDispMap, &sz );
+    }
+
+    // check size and type of unknown disparity maps
+    if( !leftUnknDispMask.empty() )
+        checkTypeAndSizeOfMask( leftUnknDispMask, leftDispMap.size() );
+    if( !rightUnknDispMask.empty() )
+        checkTypeAndSizeOfMask( rightUnknDispMask, rightDispMap.size() );
+
+    // check values of disparity maps (known disparity values musy be positive)
+    double leftMinVal = 0, rightMinVal = 0;
+    if( leftUnknDispMask.empty() )
+        minMaxLoc( leftDispMap, &leftMinVal );
+    else
+        minMaxLoc( leftDispMap, &leftMinVal, 0, 0, 0, ~leftUnknDispMask );
+    if( !rightDispMap.empty() )
+    {
+        if( rightUnknDispMask.empty() )
+            minMaxLoc( rightDispMap, &rightMinVal );
+        else
+            minMaxLoc( rightDispMap, &rightMinVal, 0, 0, 0, ~rightUnknDispMask );
+    }
+    if( leftMinVal < 0 || rightMinVal < 0)
+        CV_Error( CV_StsBadArg, "known disparity values must be positive" );
+}
+
+/*
+  Calculate occluded regions of reference image (left image) (regions that are occluded in the matching image (right image),
+  i.e., where the forward-mapped disparity lands at a location with a larger (nearer) disparity) and non occluded regions.
+*/
+void computeOcclusionBasedMasks( const Mat& leftDisp, const Mat& _rightDisp,
+                             Mat* occludedMask, Mat* nonOccludedMask,
+                             const Mat& leftUnknDispMask = Mat(), const Mat& rightUnknDispMask = Mat(),
+                             float dispThresh = EVAL_DISP_THRESH )
+{
+    if( !occludedMask && !nonOccludedMask )
+        return;
+    checkDispMapsAndUnknDispMasks( leftDisp, _rightDisp, leftUnknDispMask, rightUnknDispMask );
+
+    Mat rightDisp;
+    if( _rightDisp.empty() )
+    {
+        if( !rightUnknDispMask.empty() )
+           CV_Error( CV_StsBadArg, "rightUnknDispMask must be empty if _rightDisp is empty" );
+        rightDisp.create(leftDisp.size(), CV_32FC1);
+        rightDisp.setTo(Scalar::all(0) );
+        for( int leftY = 0; leftY < leftDisp.rows; leftY++ )
+        {
+            for( int leftX = 0; leftX < leftDisp.cols; leftX++ )
+            {
+                if( !leftUnknDispMask.empty() && leftUnknDispMask.at<uchar>(leftY,leftX) )
+                    continue;
+                float leftDispVal = leftDisp.at<float>(leftY, leftX);
+                int rightX = leftX - cvRound(leftDispVal), rightY = leftY;
+                if( rightX >= 0)
+                    rightDisp.at<float>(rightY,rightX) = max(rightDisp.at<float>(rightY,rightX), leftDispVal);
+            }
+        }
+    }
+    else
+        _rightDisp.copyTo(rightDisp);
+
+    if( occludedMask )
+    {
+        occludedMask->create(leftDisp.size(), CV_8UC1);
+        occludedMask->setTo(Scalar::all(0) );
+    }
+    if( nonOccludedMask )
+    {
+        nonOccludedMask->create(leftDisp.size(), CV_8UC1);
+        nonOccludedMask->setTo(Scalar::all(0) );
+    }
+    for( int leftY = 0; leftY < leftDisp.rows; leftY++ )
+    {
+        for( int leftX = 0; leftX < leftDisp.cols; leftX++ )
+        {
+            if( !leftUnknDispMask.empty() && leftUnknDispMask.at<uchar>(leftY,leftX) )
+                continue;
+            float leftDispVal = leftDisp.at<float>(leftY, leftX);
+            int rightX = leftX - cvRound(leftDispVal), rightY = leftY;
+            if( rightX < 0 && occludedMask )
+                occludedMask->at<uchar>(leftY, leftX) = 255;
+            else
+            {
+                if( !rightUnknDispMask.empty() && rightUnknDispMask.at<uchar>(rightY,rightX) )
+                    continue;
+                float rightDispVal = rightDisp.at<float>(rightY, rightX);
+                if( rightDispVal > leftDispVal + dispThresh )
+                {
+                    if( occludedMask )
+                        occludedMask->at<uchar>(leftY, leftX) = 255;
+                }
+                else
+                {
+                    if( nonOccludedMask )
+                        nonOccludedMask->at<uchar>(leftY, leftX) = 255;
+                }
+            }
+        }
+    }
+}
+
+/*
+  Calculate depth discontinuty regions: pixels whose neiboring disparities differ by more than
+  dispGap, dilated by window of width discontWidth.
+*/
+void computeDepthDiscontMask( const Mat& disp, Mat& depthDiscontMask, const Mat& unknDispMask = Mat(),
+                                 float dispGap = EVAL_DISP_GAP, int discontWidth = EVAL_DISCONT_WIDTH )
+{
+    if( disp.empty() )
+        CV_Error( CV_StsBadArg, "disp is empty" );
+    if( disp.type() != CV_32FC1 )
+        CV_Error( CV_StsBadArg, "disp must have CV_32FC1 type" );
+    if( !unknDispMask.empty() )
+        checkTypeAndSizeOfMask( unknDispMask, disp.size() );
+
+    Mat curDisp; disp.copyTo( curDisp );
+    if( !unknDispMask.empty() )
+        curDisp.setTo( Scalar(numeric_limits<float>::min()), unknDispMask );
+    Mat maxNeighbDisp; dilate( curDisp, maxNeighbDisp, Mat(3, 3, CV_8UC1, Scalar(1)) );
+    if( !unknDispMask.empty() )
+        curDisp.setTo( Scalar(numeric_limits<float>::max()), unknDispMask );
+    Mat minNeighbDisp; erode( curDisp, minNeighbDisp, Mat(3, 3, CV_8UC1, Scalar(1)) );
+    depthDiscontMask = max( (Mat)(maxNeighbDisp-disp), (Mat)(disp-minNeighbDisp) ) > dispGap;
+    if( !unknDispMask.empty() )
+        depthDiscontMask &= ~unknDispMask;
+    dilate( depthDiscontMask, depthDiscontMask, Mat(discontWidth, discontWidth, CV_8UC1, Scalar(1)) );
+}
+
+/*
+   Get evaluation masks excluding a border.
+*/
+Mat getBorderedMask( Size maskSize, int border = EVAL_IGNORE_BORDER )
+{
+    CV_Assert( border >= 0 );
+    Mat mask(maskSize, CV_8UC1, Scalar(0));
+    int w = maskSize.width - 2*border, h = maskSize.height - 2*border;
+    if( w < 0 ||  h < 0 )
+        mask.setTo(Scalar(0));
+    else
+        mask( Rect(Point(border,border),Size(w,h)) ).setTo(Scalar(255));
+    return mask;
+}
+
+/*
+  Calculate root-mean-squared error between the computed disparity map (computedDisp) and ground truth map (groundTruthDisp).
+*/
+float dispRMS( const Mat& computedDisp, const Mat& groundTruthDisp, const Mat& mask )
+{
+    checkTypeAndSizeOfDisp( groundTruthDisp, 0 );
+    Size sz = groundTruthDisp.size();
+    checkTypeAndSizeOfDisp( computedDisp, &sz );
+
+    int pointsCount = sz.height*sz.width;
+    if( !mask.empty() )
+    {
+        checkTypeAndSizeOfMask( mask, sz );
+        pointsCount = countNonZero(mask);
+    }
+    return 1.f/sqrt((float)pointsCount) * (float)norm(computedDisp, groundTruthDisp, NORM_L2, mask);
+}
+
+/*
+  Calculate fraction of bad matching pixels.
+*/
+float badMatchPxlsFraction( const Mat& computedDisp, const Mat& groundTruthDisp, const Mat& mask,
+                            float _badThresh = EVAL_BAD_THRESH )
+{
+    int badThresh = cvRound(_badThresh);
+    checkTypeAndSizeOfDisp( groundTruthDisp, 0 );
+    Size sz = groundTruthDisp.size();
+    checkTypeAndSizeOfDisp( computedDisp, &sz );
+
+    Mat badPxlsMap;
+    absdiff( computedDisp, groundTruthDisp, badPxlsMap );
+    badPxlsMap = badPxlsMap > badThresh;
+    int pointsCount = sz.height*sz.width;
+    if( !mask.empty() )
+    {
+        checkTypeAndSizeOfMask( mask, sz );
+        badPxlsMap = badPxlsMap & mask;
+        pointsCount = countNonZero(mask);
+    }
+    return 1.f/pointsCount * countNonZero(badPxlsMap);
+}
+
+//===================== regression test for stereo matching algorithms ==============================
+
+const string ALGORITHMS_DIR = "stereomatching/algorithms/";
+const string DATASETS_DIR = "stereomatching/datasets/";
+const string DATASETS_FILE = "datasets.xml";
+
+const string RUN_PARAMS_FILE = "_params.xml";
+const string RESULT_FILE = "_res.xml";
+
+const string LEFT_IMG_NAME = "im2.png";
+const string RIGHT_IMG_NAME = "im6.png";
+const string TRUE_LEFT_DISP_NAME = "disp2.png";
+const string TRUE_RIGHT_DISP_NAME = "disp6.png";
+
+string ERROR_PREFIXES[] = { "borderedAll",
+                            "borderedNoOccl",
+                            "borderedOccl",
+                            "borderedTextured",
+                            "borderedTextureless",
+                            "borderedDepthDiscont" }; // size of ERROR_KINDS_COUNT
+
+
+const string RMS_STR = "RMS";
+const string BAD_PXLS_FRACTION_STR = "BadPxlsFraction";
+
+class QualityEvalParams
+{
+public:
+    QualityEvalParams() { setDefaults(); }
+    QualityEvalParams( int _ignoreBorder )
+    {
+        setDefaults();
+        ignoreBorder = _ignoreBorder;
+    }
+    void setDefaults()
+    {
+        badThresh = EVAL_BAD_THRESH;
+        texturelessWidth = EVAL_TEXTURELESS_WIDTH;
+        texturelessThresh = EVAL_TEXTURELESS_THRESH;
+        dispThresh = EVAL_DISP_THRESH;
+        dispGap = EVAL_DISP_GAP;
+        discontWidth = EVAL_DISCONT_WIDTH;
+        ignoreBorder = EVAL_IGNORE_BORDER;
+    }
+    float badThresh;
+    int texturelessWidth;
+    float texturelessThresh;
+    float dispThresh;
+    float dispGap;
+    int discontWidth;
+    int ignoreBorder;
+};
+
+class CV_StereoMatchingTest : public cvtest::BaseTest
+{
+public:
+    CV_StereoMatchingTest()
+    { rmsEps.resize( ERROR_KINDS_COUNT, 0.01f );  fracEps.resize( ERROR_KINDS_COUNT, 1.e-6f ); }
+protected:
+    // assumed that left image is a reference image
+    virtual int runStereoMatchingAlgorithm( const Mat& leftImg, const Mat& rightImg,
+                   Mat& leftDisp, Mat& rightDisp, int caseIdx ) = 0; // return ignored border width
+
+    int readDatasetsParams( FileStorage& fs );
+    virtual int readRunParams( FileStorage& fs );
+    void writeErrors( const string& errName, const vector<float>& errors, FileStorage* fs = 0 );
+    void readErrors( FileNode& fn, const string& errName, vector<float>& errors );
+    int compareErrors( const vector<float>& calcErrors, const vector<float>& validErrors,
+                       const vector<float>& eps, const string& errName );
+    int processStereoMatchingResults( FileStorage& fs, int caseIdx, bool isWrite,
+                  const Mat& leftImg, const Mat& rightImg,
+                  const Mat& trueLeftDisp, const Mat& trueRightDisp,
+                  const Mat& leftDisp, const Mat& rightDisp,
+                  const QualityEvalParams& qualityEvalParams  );
+    void run( int );
+
+    vector<float> rmsEps;
+    vector<float> fracEps;
+
+    struct DatasetParams
+    {
+        int dispScaleFactor;
+        int dispUnknVal;
+    };
+    map<string, DatasetParams> datasetsParams;
+
+    vector<string> caseNames;
+    vector<string> caseDatasets;
+};
+
+void CV_StereoMatchingTest::run(int)
+{
+    string dataPath = ts->get_data_path();
+    string algorithmName = name;
+    assert( !algorithmName.empty() );
+    if( dataPath.empty() )
+    {
+        ts->printf( cvtest::TS::LOG, "dataPath is empty" );
+        ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ARG_CHECK );
+        return;
+    }
+
+    FileStorage datasetsFS( dataPath + DATASETS_DIR + DATASETS_FILE, FileStorage::READ );
+    int code = readDatasetsParams( datasetsFS );
+    if( code != cvtest::TS::OK )
+    {
+        ts->set_failed_test_info( code );
+        return;
+    }
+    FileStorage runParamsFS( dataPath + ALGORITHMS_DIR + algorithmName + RUN_PARAMS_FILE, FileStorage::READ );
+    code = readRunParams( runParamsFS );
+    if( code != cvtest::TS::OK )
+    {
+        ts->set_failed_test_info( code );
+        return;
+    }
+    
+    string fullResultFilename = dataPath + ALGORITHMS_DIR + algorithmName + RESULT_FILE;
+    FileStorage resFS( fullResultFilename, FileStorage::READ );
+    bool isWrite = true; // write or compare results
+    if( resFS.isOpened() )
+        isWrite = false;
+    else
+    {
+        resFS.open( fullResultFilename, FileStorage::WRITE );
+        if( !resFS.isOpened() )
+        {
+            ts->printf( cvtest::TS::LOG, "file %s can not be read or written\n", fullResultFilename.c_str() );
+            ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ARG_CHECK );
+            return;
+        }
+        resFS << "stereo_matching" << "{";
+    }
+
+    int progress = 0, caseCount = (int)caseNames.size();
+    for( int ci = 0; ci < caseCount; ci++)
+    {
+        progress = update_progress( progress, ci, caseCount, 0 );
+        printf("progress: %d%%\n", progress);
+        fflush(stdout);
+        string datasetName = caseDatasets[ci];
+        string datasetFullDirName = dataPath + DATASETS_DIR + datasetName + "/";
+        Mat leftImg = imread(datasetFullDirName + LEFT_IMG_NAME);
+        Mat rightImg = imread(datasetFullDirName + RIGHT_IMG_NAME);
+        Mat trueLeftDisp = imread(datasetFullDirName + TRUE_LEFT_DISP_NAME, 0);
+        Mat trueRightDisp = imread(datasetFullDirName + TRUE_RIGHT_DISP_NAME, 0);
+
+        if( leftImg.empty() || rightImg.empty() || trueLeftDisp.empty() )
+        {
+            ts->printf( cvtest::TS::LOG, "images or left ground-truth disparities of dataset %s can not be read", datasetName.c_str() );
+            code = cvtest::TS::FAIL_INVALID_TEST_DATA;
+            continue;
+        }
+        int dispScaleFactor = datasetsParams[datasetName].dispScaleFactor;
+        Mat tmp; trueLeftDisp.convertTo( tmp, CV_32FC1, 1.f/dispScaleFactor ); trueLeftDisp = tmp; tmp.release();
+        if( !trueRightDisp.empty() )
+            trueRightDisp.convertTo( tmp, CV_32FC1, 1.f/dispScaleFactor ); trueRightDisp = tmp; tmp.release();
+
+        Mat leftDisp, rightDisp;
+        int ignBorder = max(runStereoMatchingAlgorithm(leftImg, rightImg, leftDisp, rightDisp, ci), EVAL_IGNORE_BORDER);
+        leftDisp.convertTo( tmp, CV_32FC1 ); leftDisp = tmp; tmp.release();
+        rightDisp.convertTo( tmp, CV_32FC1 ); rightDisp = tmp; tmp.release();
+
+        int tempCode = processStereoMatchingResults( resFS, ci, isWrite,
+                   leftImg, rightImg, trueLeftDisp, trueRightDisp, leftDisp, rightDisp, QualityEvalParams(ignBorder));
+        code = tempCode==cvtest::TS::OK ? code : tempCode;
+    }
+
+    if( isWrite )
+        resFS << "}"; // "stereo_matching"
+
+    ts->set_failed_test_info( code );
+}
+
+void calcErrors( const Mat& leftImg, const Mat& /*rightImg*/,
+                 const Mat& trueLeftDisp, const Mat& trueRightDisp,
+                 const Mat& trueLeftUnknDispMask, const Mat& trueRightUnknDispMask,
+                 const Mat& calcLeftDisp, const Mat& /*calcRightDisp*/,
+                 vector<float>& rms, vector<float>& badPxlsFractions,
+                 const QualityEvalParams& qualityEvalParams )
+{
+    Mat texturelessMask, texturedMask;
+    computeTextureBasedMasks( leftImg, &texturelessMask, &texturedMask,
+                              qualityEvalParams.texturelessWidth, qualityEvalParams.texturelessThresh );
+    Mat occludedMask, nonOccludedMask;
+    computeOcclusionBasedMasks( trueLeftDisp, trueRightDisp, &occludedMask, &nonOccludedMask,
+                                trueLeftUnknDispMask, trueRightUnknDispMask, qualityEvalParams.dispThresh);
+    Mat depthDiscontMask;
+    computeDepthDiscontMask( trueLeftDisp, depthDiscontMask, trueLeftUnknDispMask,
+                             qualityEvalParams.dispGap, qualityEvalParams.discontWidth);
+
+    Mat borderedKnownMask = getBorderedMask( leftImg.size(), qualityEvalParams.ignoreBorder ) & ~trueLeftUnknDispMask;
+
+    nonOccludedMask &= borderedKnownMask;
+    occludedMask &= borderedKnownMask;
+    texturedMask &= nonOccludedMask; // & borderedKnownMask
+    texturelessMask &= nonOccludedMask; // & borderedKnownMask
+    depthDiscontMask &= nonOccludedMask; // & borderedKnownMask
+
+    rms.resize(ERROR_KINDS_COUNT);
+    rms[0] = dispRMS( calcLeftDisp, trueLeftDisp, borderedKnownMask );
+    rms[1] = dispRMS( calcLeftDisp, trueLeftDisp, nonOccludedMask );
+    rms[2] = dispRMS( calcLeftDisp, trueLeftDisp, occludedMask );
+    rms[3] = dispRMS( calcLeftDisp, trueLeftDisp, texturedMask );
+    rms[4] = dispRMS( calcLeftDisp, trueLeftDisp, texturelessMask );
+    rms[5] = dispRMS( calcLeftDisp, trueLeftDisp, depthDiscontMask );
+
+    badPxlsFractions.resize(ERROR_KINDS_COUNT);
+    badPxlsFractions[0] = badMatchPxlsFraction( calcLeftDisp, trueLeftDisp, borderedKnownMask, qualityEvalParams.badThresh );
+    badPxlsFractions[1] = badMatchPxlsFraction( calcLeftDisp, trueLeftDisp, nonOccludedMask, qualityEvalParams.badThresh );
+    badPxlsFractions[2] = badMatchPxlsFraction( calcLeftDisp, trueLeftDisp, occludedMask, qualityEvalParams.badThresh );
+    badPxlsFractions[3] = badMatchPxlsFraction( calcLeftDisp, trueLeftDisp, texturedMask, qualityEvalParams.badThresh );
+    badPxlsFractions[4] = badMatchPxlsFraction( calcLeftDisp, trueLeftDisp, texturelessMask, qualityEvalParams.badThresh );
+    badPxlsFractions[5] = badMatchPxlsFraction( calcLeftDisp, trueLeftDisp, depthDiscontMask, qualityEvalParams.badThresh );
+}
+
+int CV_StereoMatchingTest::processStereoMatchingResults( FileStorage& fs, int caseIdx, bool isWrite,
+              const Mat& leftImg, const Mat& rightImg,
+              const Mat& trueLeftDisp, const Mat& trueRightDisp,
+              const Mat& leftDisp, const Mat& rightDisp,
+              const QualityEvalParams& qualityEvalParams )
+{
+    // rightDisp is not used in current test virsion
+    int code = cvtest::TS::OK;
+    assert( fs.isOpened() );
+    assert( trueLeftDisp.type() == CV_32FC1 && trueRightDisp.type() == CV_32FC1 );
+    assert( leftDisp.type() == CV_32FC1 && rightDisp.type() == CV_32FC1 );
+
+    // get masks for unknown ground truth disparity values
+    Mat leftUnknMask, rightUnknMask;
+    DatasetParams params = datasetsParams[caseDatasets[caseIdx]];
+    absdiff( trueLeftDisp, Scalar(params.dispUnknVal), leftUnknMask );
+    leftUnknMask = leftUnknMask < numeric_limits<float>::epsilon();
+    assert(leftUnknMask.type() == CV_8UC1);
+    if( !trueRightDisp.empty() )
+    {
+        absdiff( trueRightDisp, Scalar(params.dispUnknVal), rightUnknMask );
+        rightUnknMask = rightUnknMask < numeric_limits<float>::epsilon();
+        assert(leftUnknMask.type() == CV_8UC1);
+    }
+
+    // calculate errors
+    vector<float> rmss, badPxlsFractions;
+    calcErrors( leftImg, rightImg, trueLeftDisp, trueRightDisp, leftUnknMask, rightUnknMask,
+                leftDisp, rightDisp, rmss, badPxlsFractions, qualityEvalParams );
+
+    if( isWrite )
+    {
+        fs << caseNames[caseIdx] << "{";
+        cvWriteComment( fs.fs, RMS_STR.c_str(), 0 );
+        writeErrors( RMS_STR, rmss, &fs );
+        cvWriteComment( fs.fs, BAD_PXLS_FRACTION_STR.c_str(), 0 );
+        writeErrors( BAD_PXLS_FRACTION_STR, badPxlsFractions, &fs );
+        fs << "}"; // datasetName
+    }
+    else // compare
+    {
+        ts->printf( cvtest::TS::LOG, "\nquality of case named %s\n", caseNames[caseIdx].c_str() );
+        ts->printf( cvtest::TS::LOG, "%s\n", RMS_STR.c_str() );
+        writeErrors( RMS_STR, rmss );
+        ts->printf( cvtest::TS::LOG, "%s\n", BAD_PXLS_FRACTION_STR.c_str() );
+        writeErrors( BAD_PXLS_FRACTION_STR, badPxlsFractions );
+
+        FileNode fn = fs.getFirstTopLevelNode()[caseNames[caseIdx]];
+        vector<float> validRmss, validBadPxlsFractions;
+
+        readErrors( fn, RMS_STR, validRmss );
+        readErrors( fn, BAD_PXLS_FRACTION_STR, validBadPxlsFractions );
+        int tempCode = compareErrors( rmss, validRmss, rmsEps, RMS_STR );
+        code = tempCode==cvtest::TS::OK ? code : tempCode;
+        tempCode = compareErrors( badPxlsFractions, validBadPxlsFractions, fracEps, BAD_PXLS_FRACTION_STR );
+        code = tempCode==cvtest::TS::OK ? code : tempCode;
+    }
+    return code;
+}
+
+int CV_StereoMatchingTest::readDatasetsParams( FileStorage& fs )
+{
+    if( !fs.isOpened() )
+    {
+        ts->printf( cvtest::TS::LOG, "datasetsParams can not be read " );
+        return cvtest::TS::FAIL_INVALID_TEST_DATA;
+    }
+    datasetsParams.clear();
+    FileNode fn = fs.getFirstTopLevelNode();
+    assert(fn.isSeq());
+    for( int i = 0; i < (int)fn.size(); i+=3 )
+    {
+        string name = fn[i];
+        DatasetParams params;
+        string sf = fn[i+1]; params.dispScaleFactor = atoi(sf.c_str());
+        string uv = fn[i+2]; params.dispUnknVal = atoi(uv.c_str());
+        datasetsParams[name] = params;
+    }
+    return cvtest::TS::OK;
+}
+
+int CV_StereoMatchingTest::readRunParams( FileStorage& fs )
+{
+    if( !fs.isOpened() )
+    {
+        ts->printf( cvtest::TS::LOG, "runParams can not be read " );
+        return cvtest::TS::FAIL_INVALID_TEST_DATA;
+    }
+    caseNames.clear();;
+    caseDatasets.clear();
+    return cvtest::TS::OK;
+}
+
+void CV_StereoMatchingTest::writeErrors( const string& errName, const vector<float>& errors, FileStorage* fs )
+{
+    assert( (int)errors.size() == ERROR_KINDS_COUNT );
+    vector<float>::const_iterator it = errors.begin();
+    if( fs )
+        for( int i = 0; i < ERROR_KINDS_COUNT; i++, ++it )
+            *fs << ERROR_PREFIXES[i] + errName << *it;
+    else
+        for( int i = 0; i < ERROR_KINDS_COUNT; i++, ++it )
+            ts->printf( cvtest::TS::LOG, "%s = %f\n", string(ERROR_PREFIXES[i]+errName).c_str(), *it );
+}
+
+void CV_StereoMatchingTest::readErrors( FileNode& fn, const string& errName, vector<float>& errors )
+{
+    errors.resize( ERROR_KINDS_COUNT );
+    vector<float>::iterator it = errors.begin();
+    for( int i = 0; i < ERROR_KINDS_COUNT; i++, ++it )
+        fn[ERROR_PREFIXES[i]+errName] >> *it;
+}
+
+int CV_StereoMatchingTest::compareErrors( const vector<float>& calcErrors, const vector<float>& validErrors,
+                   const vector<float>& eps, const string& errName )
+{
+    assert( (int)calcErrors.size() == ERROR_KINDS_COUNT );
+    assert( (int)validErrors.size() == ERROR_KINDS_COUNT );
+    assert( (int)eps.size() == ERROR_KINDS_COUNT );
+    vector<float>::const_iterator calcIt = calcErrors.begin(),
+                                  validIt = validErrors.begin(),
+                                  epsIt = eps.begin();
+    bool ok = true;
+    for( int i = 0; i < ERROR_KINDS_COUNT; i++, ++calcIt, ++validIt, ++epsIt )
+        if( *calcIt - *validIt > *epsIt )
+        {
+            ts->printf( cvtest::TS::LOG, "bad accuracy of %s (valid=%f; calc=%f)\n", string(ERROR_PREFIXES[i]+errName).c_str(), *validIt, *calcIt );
+            ok = false;
+        }
+    return ok ? cvtest::TS::OK : cvtest::TS::FAIL_BAD_ACCURACY;
+}
+
+//----------------------------------- StereoGC test -----------------------------------------------------
+
+class CV_StereoGCTest : public CV_StereoMatchingTest
+{
+public:
+    CV_StereoGCTest()
+    {
+        name = "stereogc"; 
+        fill(rmsEps.begin(), rmsEps.end(), 3.f);
+        fracEps[0] = 0.05f; // all
+        fracEps[1] = 0.05f; // noOccl
+        fracEps[2] = 0.25f; // occl
+        fracEps[3] = 0.05f; // textured
+        fracEps[4] = 0.10f; // textureless
+        fracEps[5] = 0.10f; // borderedDepthDiscont
+    }
+protected:
+    struct RunParams
+    {
+        int ndisp;
+        int iterCount;
+    };
+    vector<RunParams> caseRunParams;
+
+    virtual int readRunParams( FileStorage& fs )
+    {
+        int code = CV_StereoMatchingTest::readRunParams(fs);
+        FileNode fn = fs.getFirstTopLevelNode();
+        assert(fn.isSeq());
+        for( int i = 0; i < (int)fn.size(); i+=4 )
+        {
+            string caseName = fn[i], datasetName = fn[i+1];
+            RunParams params;
+            string ndisp = fn[i+2]; params.ndisp = atoi(ndisp.c_str());
+            string iterCount = fn[i+3]; params.iterCount = atoi(iterCount.c_str());
+            caseNames.push_back( caseName );
+            caseDatasets.push_back( datasetName );
+            caseRunParams.push_back( params );
+        }
+        return code;
+    }
+
+    virtual int runStereoMatchingAlgorithm( const Mat& _leftImg, const Mat& _rightImg,
+                   Mat& leftDisp, Mat& rightDisp, int caseIdx )
+    {
+        RunParams params = caseRunParams[caseIdx];
+        assert( _leftImg.type() == CV_8UC3 && _rightImg.type() == CV_8UC3 );
+        Mat leftImg, rightImg, tmp;
+        cvtColor( _leftImg, leftImg, CV_BGR2GRAY );
+        cvtColor( _rightImg, rightImg, CV_BGR2GRAY );
+
+        leftDisp.create( leftImg.size(), CV_16SC1 );
+        rightDisp.create( rightImg.size(), CV_16SC1 );
+
+        CvMat _limg = leftImg, _rimg = rightImg, _ldisp = leftDisp, _rdisp = rightDisp;
+        CvStereoGCState *state = cvCreateStereoGCState( params.ndisp, params.iterCount );
+        cvFindStereoCorrespondenceGC( &_limg, &_rimg, &_ldisp, &_rdisp, state );
+        cvReleaseStereoGCState( &state );
+
+        leftDisp = - leftDisp;
+        return 0;
+    }
+
+};
+
+
+TEST(Calib3d_StereoGC, regression) { CV_StereoGCTest test; test.safe_run(); }
diff --git a/modules/objdetect/src/planardetect.cpp b/modules/objdetect/src/planardetect.cpp
deleted file mode 100644 (file)
index 2fcbff7..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*M///////////////////////////////////////////////////////////////////////////////////////
-//
-//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
-//
-//  By downloading, copying, installing or using the software you agree to this license.
-//  If you do not agree to this license, do not download, install,
-//  copy or use the software.
-//
-//
-//                           License Agreement
-//                For Open Source Computer Vision Library
-//
-// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
-// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
-// Third party copyrights are property of their respective owners.
-//
-// Redistribution and use in source and binary forms, with or without modification,
-// are permitted provided that the following conditions are met:
-//
-//   * Redistribution's of source code must retain the above copyright notice,
-//     this list of conditions and the following disclaimer.
-//
-//   * Redistribution's in binary form must reproduce the above copyright notice,
-//     this list of conditions and the following disclaimer in the documentation
-//     and/or other materials provided with the distribution.
-//
-//   * The name of the copyright holders may not be used to endorse or promote products
-//     derived from this software without specific prior written permission.
-//
-// This software is provided by the copyright holders and contributors "as is" and
-// any express or implied warranties, including, but not limited to, the implied
-// warranties of merchantability and fitness for a particular purpose are disclaimed.
-// In no event shall the Intel Corporation or contributors be liable for any direct,
-// indirect, incidental, special, exemplary, or consequential damages
-// (including, but not limited to, procurement of substitute goods or services;
-// loss of use, data, or profits; or business interruption) however caused
-// and on any theory of liability, whether in contract, strict liability,
-// or tort (including negligence or otherwise) arising in any way out of
-// the use of this software, even if advised of the possibility of such damage.
-//
-//M*/
-
-#include "precomp.hpp"
-#include <stdio.h>
-
-namespace cv
-{
-
-}
index 4c66367..e9178bd 100644 (file)
@@ -4,7 +4,6 @@ Motion Analysis and Object Tracking
 .. highlight:: cpp
 
 
-
 calcOpticalFlowPyrLK
 ------------------------
 Calculates an optical flow for a sparse feature set using the iterative Lucas-Kanade method with pyramids.
@@ -86,89 +85,6 @@ The function finds an optical flow for each ``prevImg`` pixel using the [Farneba
     \texttt{prevImg} (y,x)  \sim \texttt{nextImg} ( y + \texttt{flow} (y,x)[1],  x + \texttt{flow} (y,x)[0])
 
 
-
-CalcOpticalFlowBM
------------------
-Calculates the optical flow for two images by using the block matching method.
-
-.. ocv:cfunction:: void cvCalcOpticalFlowBM( const CvArr* prev, const CvArr* curr, CvSize blockSize, CvSize shiftSize, CvSize maxRange, int usePrevious, CvArr* velx, CvArr* vely )
-
-.. ocv:pyoldfunction:: cv.CalcOpticalFlowBM(prev, curr, blockSize, shiftSize, maxRange, usePrevious, velx, vely)-> None
-
-        :param prev: First image, 8-bit, single-channel 
-
-        :param curr: Second image, 8-bit, single-channel 
-
-        :param blockSize: Size of basic blocks that are compared 
-
-        :param shiftSize: Block coordinate increments 
-
-        :param maxRange: Size of the scanned neighborhood in pixels around the block 
-
-        :param usePrevious: Flag that specifies whether to use the input velocity as initial approximations or not.
-
-        :param velx: Horizontal component of the optical flow of
-
-            .. math::
-
-                \left \lfloor   \frac{\texttt{prev->width} - \texttt{blockSize.width}}{\texttt{shiftSize.width}}   \right \rfloor \times \left \lfloor   \frac{\texttt{prev->height} - \texttt{blockSize.height}}{\texttt{shiftSize.height}}   \right \rfloor 
-
-            size, 32-bit floating-point, single-channel 
-
-        :param vely: Vertical component of the optical flow of the same size  ``velx`` , 32-bit floating-point, single-channel 
-
-
-The function calculates the optical flow for overlapped blocks ``blockSize.width x blockSize.height`` pixels each, thus the velocity fields are smaller than the original images. For every block in  ``prev``
-the functions tries to find a similar block in ``curr`` in some neighborhood of the original block or shifted by ``(velx(x0,y0), vely(x0,y0))`` block as has been calculated by previous function call (if ``usePrevious=1``)
-
-
-CalcOpticalFlowHS
------------------
-Calculates the optical flow for two images using Horn-Schunck algorithm.
-
-.. ocv:cfunction:: void cvCalcOpticalFlowHS(const CvArr* prev, const CvArr* curr, int usePrevious, CvArr* velx, CvArr* vely, double lambda, CvTermCriteria criteria)
-
-.. ocv:pyoldfunction:: cv.CalcOpticalFlowHS(prev, curr, usePrevious, velx, vely, lambda, criteria)-> None
-
-    :param prev: First image, 8-bit, single-channel 
-
-    :param curr: Second image, 8-bit, single-channel 
-
-    :param usePrevious: Flag that specifies whether to use the input velocity as initial approximations or not.
-
-    :param velx: Horizontal component of the optical flow of the same size as input images, 32-bit floating-point, single-channel 
-
-    :param vely: Vertical component of the optical flow of the same size as input images, 32-bit floating-point, single-channel 
-
-    :param lambda: Smoothness weight. The larger it is, the smoother optical flow map you get.
-
-    :param criteria: Criteria of termination of velocity computing 
-
-The function computes the flow for every pixel of the first input image using the Horn and Schunck algorithm [Horn81]_. The function is obsolete. To track sparse features, use :ocv:func:`calcOpticalFlowPyrLK`. To track all the pixels, use :ocv:func:`calcOpticalFlowFarneback`.
-
-
-CalcOpticalFlowLK
------------------
-
-Calculates the optical flow for two images using Lucas-Kanade algorithm.
-
-.. ocv:cfunction:: void cvCalcOpticalFlowLK( const CvArr* prev, const CvArr* curr, CvSize winSize, CvArr* velx, CvArr* vely )
-
-.. ocv:pyoldfunction:: cv.CalcOpticalFlowLK(prev, curr, winSize, velx, vely)-> None
-
-    :param prev: First image, 8-bit, single-channel 
-
-    :param curr: Second image, 8-bit, single-channel 
-
-    :param winSize: Size of the averaging window used for grouping pixels 
-
-    :param velx: Horizontal component of the optical flow of the same size as input images, 32-bit floating-point, single-channel 
-
-    :param vely: Vertical component of the optical flow of the same size as input images, 32-bit floating-point, single-channel 
-
-The function computes the flow for every pixel of the first input image using the Lucas and Kanade algorithm [Lucas81]_. The function is obsolete. To track sparse features, use :ocv:func:`calcOpticalFlowPyrLK`. To track all the pixels, use :ocv:func:`calcOpticalFlowFarneback`.
-
-
 estimateRigidTransform
 --------------------------
 Computes an optimal affine transformation between two 2D point sets.
index 6a1b313..7f81d6c 100644 (file)
 
 #include "opencv2/core/core.hpp"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/****************************************************************************************\
-*                           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;
-} 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();
-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
-}
-
 namespace cv
 {
 
@@ -483,6 +185,5 @@ public:
 };         
     
 }
-#endif
 
 #endif
index 5dd6ce2..91d332c 100644 (file)
@@ -60,21 +60,6 @@ extern "C" {
 
 /************************************ optical flow ***************************************/
 
-/* 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 );
-
 #define  CV_LKFLOW_PYR_A_READY       1
 #define  CV_LKFLOW_PYR_B_READY       2
 #define  CV_LKFLOW_INITIAL_GUESSES   4
index 5407c25..8a7c355 100644 (file)
@@ -67,11 +67,12 @@ void BackgroundSubtractor::getBackgroundImage(OutputArray) const
 {
 }
 
-static const int defaultNMixtures = CV_BGFG_MOG_NGAUSSIANS;
-static const int defaultHistory = CV_BGFG_MOG_WINDOW_SIZE;
-static const double defaultBackgroundRatio = CV_BGFG_MOG_BACKGROUND_THRESHOLD;
-static const double defaultVarThreshold = CV_BGFG_MOG_STD_THRESHOLD*CV_BGFG_MOG_STD_THRESHOLD;
-static const double defaultNoiseSigma = CV_BGFG_MOG_SIGMA_INIT*0.5;
+static const int defaultNMixtures = 5;
+static const int defaultHistory = 200;
+static const double defaultBackgroundRatio = 0.7;
+static const double defaultVarThreshold = 2.5*2.5;
+static const double defaultNoiseSigma = 30*0.5;
+static const double defaultInitialWeight = 0.05;
     
 BackgroundSubtractorMOG::BackgroundSubtractorMOG()
 {
@@ -140,9 +141,9 @@ static void process8uC1( BackgroundSubtractorMOG& obj, const Mat& image, Mat& fg
     int K = obj.nmixtures;
     MixData<float>* mptr = (MixData<float>*)obj.bgmodel.data;
     
-    const float w0 = (float)CV_BGFG_MOG_WEIGHT_INIT;
-    const float sk0 = (float)(w0/CV_BGFG_MOG_SIGMA_INIT);
-    const float var0 = (float)(CV_BGFG_MOG_SIGMA_INIT*CV_BGFG_MOG_SIGMA_INIT);
+    const float w0 = (float)defaultInitialWeight;
+    const float sk0 = (float)(w0/(defaultNoiseSigma*2));
+    const float var0 = (float)(defaultNoiseSigma*defaultNoiseSigma*4);
     const float minVar = (float)(obj.noiseSigma*obj.noiseSigma);
     
     for( y = 0; y < rows; y++ )
@@ -264,9 +265,9 @@ static void process8uC3( BackgroundSubtractorMOG& obj, const Mat& image, Mat& fg
     float alpha = (float)learningRate, T = (float)obj.backgroundRatio, vT = (float)obj.varThreshold;
     int K = obj.nmixtures;
     
-    const float w0 = (float)CV_BGFG_MOG_WEIGHT_INIT;
-    const float sk0 = (float)(w0/(CV_BGFG_MOG_SIGMA_INIT*sqrt(3.)));
-    const float var0 = (float)(CV_BGFG_MOG_SIGMA_INIT*CV_BGFG_MOG_SIGMA_INIT);
+    const float w0 = (float)defaultInitialWeight;
+    const float sk0 = (float)(w0/(defaultNoiseSigma*2*sqrt(3.)));
+    const float var0 = (float)(defaultNoiseSigma*defaultNoiseSigma*4);
     const float minVar = (float)(obj.noiseSigma*obj.noiseSigma);
     MixData<Vec3f>* mptr = (MixData<Vec3f>*)obj.bgmodel.data;
     
@@ -411,140 +412,5 @@ void BackgroundSubtractorMOG::operator()(InputArray _image, OutputArray _fgmask,
     
 }
 
-
-static void CV_CDECL
-icvReleaseGaussianBGModel( CvGaussBGModel** bg_model )
-{
-    if( !bg_model )
-        CV_Error( CV_StsNullPtr, "" );
-    
-    if( *bg_model )
-    {
-        delete (cv::Mat*)((*bg_model)->g_point);
-        cvReleaseImage( &(*bg_model)->background );
-        cvReleaseImage( &(*bg_model)->foreground );
-        cvReleaseMemStorage(&(*bg_model)->storage);
-        memset( *bg_model, 0, sizeof(**bg_model) );
-        delete *bg_model;
-        *bg_model = 0;
-    }
-}
-
-
-static int CV_CDECL
-icvUpdateGaussianBGModel( IplImage* curr_frame, CvGaussBGModel*  bg_model, double learningRate )
-{
-    int region_count = 0;
-    
-    cv::Mat image = cv::cvarrToMat(curr_frame), mask = cv::cvarrToMat(bg_model->foreground);
-    
-    cv::BackgroundSubtractorMOG mog;
-    mog.bgmodel = *(cv::Mat*)bg_model->g_point;
-    mog.frameSize = mog.bgmodel.data ? cv::Size(cvGetSize(curr_frame)) : cv::Size();
-    mog.frameType = image.type();
-
-    mog.nframes = bg_model->countFrames;
-    mog.history = bg_model->params.win_size;
-    mog.nmixtures = bg_model->params.n_gauss;
-    mog.varThreshold = bg_model->params.std_threshold*bg_model->params.std_threshold;
-    mog.backgroundRatio = bg_model->params.bg_threshold;
-    
-    mog(image, mask, learningRate);
-    
-    bg_model->countFrames = mog.nframes;
-    if( ((cv::Mat*)bg_model->g_point)->data != mog.bgmodel.data )
-        *((cv::Mat*)bg_model->g_point) = mog.bgmodel;
-    
-    //foreground filtering
-    
-    //filter small regions
-    cvClearMemStorage(bg_model->storage);
-    
-    //cvMorphologyEx( bg_model->foreground, bg_model->foreground, 0, 0, CV_MOP_OPEN, 1 );
-    //cvMorphologyEx( bg_model->foreground, bg_model->foreground, 0, 0, CV_MOP_CLOSE, 1 );
-    
-    /*
-    CvSeq *first_seq = NULL, *prev_seq = NULL, *seq = NULL;
-    cvFindContours( bg_model->foreground, bg_model->storage, &first_seq, sizeof(CvContour), CV_RETR_LIST );
-    for( seq = first_seq; seq; seq = seq->h_next )
-    {
-        CvContour* cnt = (CvContour*)seq;
-        if( cnt->rect.width * cnt->rect.height < bg_model->params.minArea )
-        {
-            //delete small contour
-            prev_seq = seq->h_prev;
-            if( prev_seq )
-            {
-                prev_seq->h_next = seq->h_next;
-                if( seq->h_next ) seq->h_next->h_prev = prev_seq;
-            }
-            else
-            {
-                first_seq = seq->h_next;
-                if( seq->h_next ) seq->h_next->h_prev = NULL;
-            }
-        }
-        else
-        {
-            region_count++;
-        }
-    }
-    bg_model->foreground_regions = first_seq;
-    cvZero(bg_model->foreground);
-    cvDrawContours(bg_model->foreground, first_seq, CV_RGB(0, 0, 255), CV_RGB(0, 0, 255), 10, -1);*/
-    CvMat _mask = mask;
-    cvCopy(&_mask, bg_model->foreground);
-    
-    return region_count;
-}
-
-CV_IMPL CvBGStatModel*
-cvCreateGaussianBGModel( IplImage* first_frame, CvGaussBGStatModelParams* parameters )
-{
-    CvGaussBGStatModelParams params;
-    
-    CV_Assert( CV_IS_IMAGE(first_frame) );
-    
-    //init parameters
-    if( parameters == NULL )
-    {                        /* These constants are defined in cvaux/include/cvaux.h: */
-        params.win_size      = CV_BGFG_MOG_WINDOW_SIZE;
-        params.bg_threshold  = CV_BGFG_MOG_BACKGROUND_THRESHOLD;
-
-        params.std_threshold = CV_BGFG_MOG_STD_THRESHOLD;
-        params.weight_init   = CV_BGFG_MOG_WEIGHT_INIT;
-
-        params.variance_init = CV_BGFG_MOG_SIGMA_INIT*CV_BGFG_MOG_SIGMA_INIT;
-        params.minArea       = CV_BGFG_MOG_MINAREA;
-        params.n_gauss       = CV_BGFG_MOG_NGAUSSIANS;
-    }
-    else
-        params = *parameters;
-    
-    CvGaussBGModel* bg_model = new CvGaussBGModel;
-    memset( bg_model, 0, sizeof(*bg_model) );
-    bg_model->type = CV_BG_MODEL_MOG;
-    bg_model->release = (CvReleaseBGStatModel)icvReleaseGaussianBGModel;
-    bg_model->update = (CvUpdateBGStatModel)icvUpdateGaussianBGModel;
-    
-    bg_model->params = params;
-    
-    //prepare storages
-    bg_model->g_point = (CvGaussBGPoint*)new cv::Mat();
-    
-    bg_model->background = cvCreateImage(cvSize(first_frame->width,
-        first_frame->height), IPL_DEPTH_8U, first_frame->nChannels);
-    bg_model->foreground = cvCreateImage(cvSize(first_frame->width,
-        first_frame->height), IPL_DEPTH_8U, 1);
-    
-    bg_model->storage = cvCreateMemStorage();
-    
-    bg_model->countFrames = 0;
-    
-    icvUpdateGaussianBGModel( first_frame, bg_model, 1 );
-    
-    return (CvBGStatModel*)bg_model;
-}
-
 /* End of file. */
 
index 65d646c..fd42253 100644 (file)
@@ -196,18 +196,8 @@ typedef struct CvGaussBGStatModel2Data
     unsigned char* rnUsedModes;//number of Gaussian components per pixel (maximum 255)
 } CvGaussBGStatModel2Data;
 
-//only foreground image is updated
-//no filtering included
-typedef struct CvGaussBGModel2
-{
-    CV_BG_STAT_MODEL_FIELDS();
-    CvGaussBGStatModel2Params params;
-    CvGaussBGStatModel2Data   data;
-    int                       countFrames;
-} CvGaussBGModel2;
-
-CVAPI(CvBGStatModel*) cvCreateGaussianBGModel2( IplImage* first_frame,
-                                                CvGaussBGStatModel2Params* params CV_DEFAULT(NULL) );
+
+
 //shadow detection performed per pixel
 // should work for rgb data, could be usefull for gray scale and depth data as well
 //  See: Prati,Mikic,Trivedi,Cucchiarra,"Detecting Moving Shadows...",IEEE PAMI,2003.
@@ -941,239 +931,6 @@ void icvUpdatePixelBackgroundGMM2( const CvArr* srcarr, CvArr* dstarr ,
 }
 
 
-
-//////////////////////////////////////////////
-//implementation as part of the CvBGStatModel
-static void CV_CDECL icvReleaseGaussianBGModel2( CvGaussBGModel2** bg_model );
-static int CV_CDECL icvUpdateGaussianBGModel2( IplImage* curr_frame, CvGaussBGModel2*  bg_model );
-
-
-CV_IMPL CvBGStatModel*
-cvCreateGaussianBGModel2( IplImage* first_frame, CvGaussBGStatModel2Params* parameters )
-{
-    CvGaussBGModel2* bg_model = 0;
-    int w,h;
-    
-    CV_FUNCNAME( "cvCreateGaussianBGModel2" );
-    
-    __BEGIN__;
-
-    CvGaussBGStatModel2Params params;
-    
-    if( !CV_IS_IMAGE(first_frame) )
-        CV_ERROR( CV_StsBadArg, "Invalid or NULL first_frame parameter" );
-
-    if( first_frame->nChannels>CV_BGFG_MOG2_NDMAX )
-        CV_ERROR( CV_StsBadArg, "Maxumum number of channels in the image is excedded (change CV_BGFG_MOG2_MAXBANDS constant)!" );
-
-
-    CV_CALL( bg_model = (CvGaussBGModel2*)cvAlloc( sizeof(*bg_model) ));
-    memset( bg_model, 0, sizeof(*bg_model) );
-    bg_model->type    = CV_BG_MODEL_MOG2;
-    bg_model->release = (CvReleaseBGStatModel) icvReleaseGaussianBGModel2;
-    bg_model->update  = (CvUpdateBGStatModel)  icvUpdateGaussianBGModel2;
-
-    //init parameters   
-    if( parameters == NULL )
-    {                        
-        memset(&params, 0, sizeof(params));
-        
-        /* These constants are defined in cvaux/include/cvaux.h: */
-        params.bShadowDetection = 1;
-        params.bPostFiltering=0;
-        params.minArea=CV_BGFG_MOG2_MINAREA;
-
-        //set parameters
-        // K - max number of Gaussians per pixel
-        params.nM = CV_BGFG_MOG2_NGAUSSIANS;//4;            
-        // Tb - the threshold - n var
-        //pGMM->fTb = 4*4;
-        params.fTb = CV_BGFG_MOG2_STD_THRESHOLD*CV_BGFG_MOG2_STD_THRESHOLD;
-        // Tbf - the threshold
-        //pGMM->fTB = 0.9f;//1-cf from the paper 
-        params.fTB = CV_BGFG_MOG2_BACKGROUND_THRESHOLD;
-        // Tgenerate - the threshold
-        params.fTg = CV_BGFG_MOG2_STD_THRESHOLD_GENERATE*CV_BGFG_MOG2_STD_THRESHOLD_GENERATE;//update the mode or generate new
-        //pGMM->fSigma= 11.0f;//sigma for the new mode
-        params.fVarInit = CV_BGFG_MOG2_VAR_INIT;
-        params.fVarMax = CV_BGFG_MOG2_VAR_MAX;
-        params.fVarMin = CV_BGFG_MOG2_VAR_MIN;
-        // alpha - the learning factor
-        params.fAlphaT = 1.0f/CV_BGFG_MOG2_WINDOW_SIZE;//0.003f;
-        // complexity reduction prior constant
-        params.fCT = CV_BGFG_MOG2_CT;//0.05f;
-
-        //shadow
-        // Shadow detection
-        params.nShadowDetection = (unsigned char)CV_BGFG_MOG2_SHADOW_VALUE;//value 0 to turn off
-        params.fTau = CV_BGFG_MOG2_SHADOW_TAU;//0.5f;// Tau - shadow threshold
-    }
-    else
-    {
-        params = *parameters;
-    }
-
-    bg_model->params = params;
-
-    //image data 
-    w = first_frame->width;
-    h = first_frame->height;
-
-    bg_model->params.nWidth = w;
-    bg_model->params.nHeight = h;
-
-    bg_model->params.nND = first_frame->nChannels;
-
-
-    //allocate GMM data
-
-    //GMM for each pixel
-    bg_model->data.rGMM = (CvPBGMMGaussian*) malloc(w*h * params.nM * sizeof(CvPBGMMGaussian));
-    //used modes per pixel
-    bg_model->data.rnUsedModes = (unsigned char* ) malloc(w*h);
-    memset(bg_model->data.rnUsedModes,0,w*h);//no modes used
-  
-    //prepare storages    
-    CV_CALL( bg_model->background = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U, first_frame->nChannels));
-    CV_CALL( bg_model->foreground = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U, 1));
-    
-    //for eventual filtering
-    CV_CALL( bg_model->storage = cvCreateMemStorage());
-    
-    bg_model->countFrames = 0;
-
-    __END__;
-    
-    if( cvGetErrStatus() < 0 )
-    {
-        CvBGStatModel* base_ptr = (CvBGStatModel*)bg_model;
-        
-        if( bg_model && bg_model->release )
-            bg_model->release( &base_ptr );
-        else
-            cvFree( &bg_model );
-        bg_model = 0;
-    }
-    
-    return (CvBGStatModel*)bg_model;
-}
-
-
-static void CV_CDECL
-icvReleaseGaussianBGModel2( CvGaussBGModel2** _bg_model )
-{
-    CV_FUNCNAME( "icvReleaseGaussianBGModel2" );
-
-    __BEGIN__;
-    
-    if( !_bg_model )
-        CV_ERROR( CV_StsNullPtr, "" );
-
-    if( *_bg_model )
-    {
-        CvGaussBGModel2* bg_model = *_bg_model;
-
-        free (bg_model->data.rGMM);
-        free (bg_model->data.rnUsedModes);
-
-        cvReleaseImage( &bg_model->background );
-        cvReleaseImage( &bg_model->foreground );
-        cvReleaseMemStorage(&bg_model->storage);
-        memset( bg_model, 0, sizeof(*bg_model) );
-        cvFree( _bg_model );
-    }
-
-    __END__;
-}
-
-
-static int CV_CDECL
-icvUpdateGaussianBGModel2( IplImage* curr_frame, CvGaussBGModel2*  bg_model )
-{ 
-    //checks    
-    if ((curr_frame->height!=bg_model->params.nHeight)||(curr_frame->width!=bg_model->params.nWidth)||(curr_frame->nChannels!=bg_model->params.nND))
-        CV_Error( CV_StsBadSize, "the image not the same size as the reserved GMM background model");
-
-    float alpha=bg_model->params.fAlphaT;
-    bg_model->countFrames++;
-    
-    //faster initial updates - increase value of alpha
-    if (bg_model->params.bInit){
-        float alphaInit=(1.0f/(2*bg_model->countFrames+1));
-        if (alphaInit>alpha)
-        {
-            alpha = alphaInit;
-        }
-        else
-        {
-            bg_model->params.bInit = 0;
-        }
-    }
-
-    //update background
-    //icvUpdatePixelBackgroundGMM2( curr_frame, bg_model->foreground, bg_model->data.rGMM,bg_model->data.rnUsedModes,&(bg_model->params),alpha);
-    icvUpdatePixelBackgroundGMM2( curr_frame, bg_model->foreground, bg_model->data.rGMM,bg_model->data.rnUsedModes,
-        bg_model->params.nM,
-        bg_model->params.fTb,
-        bg_model->params.fTB,
-        bg_model->params.fTg,
-        bg_model->params.fVarInit,
-        bg_model->params.fVarMax,
-        bg_model->params.fVarMin,
-        bg_model->params.fCT,
-        bg_model->params.fTau,
-        bg_model->params.bShadowDetection,
-        bg_model->params.nShadowDetection,
-        alpha);
-
-    //foreground filtering
-    if (bg_model->params.bPostFiltering==1)
-    {
-        int region_count = 0;
-        CvSeq *first_seq = NULL, *prev_seq = NULL, *seq = NULL;
-
-
-        //filter small regions
-        cvClearMemStorage(bg_model->storage);
-
-        cvMorphologyEx( bg_model->foreground, bg_model->foreground, 0, 0, CV_MOP_OPEN, 1 );
-        cvMorphologyEx( bg_model->foreground, bg_model->foreground, 0, 0, CV_MOP_CLOSE, 1 );
-
-        cvFindContours( bg_model->foreground, bg_model->storage, &first_seq, sizeof(CvContour), CV_RETR_LIST );
-        for( seq = first_seq; seq; seq = seq->h_next )
-        {
-            CvContour* cnt = (CvContour*)seq;
-            if( cnt->rect.width * cnt->rect.height < bg_model->params.minArea )
-            {
-                //delete small contour
-                prev_seq = seq->h_prev;
-                if( prev_seq )
-                {
-                    prev_seq->h_next = seq->h_next;
-                    if( seq->h_next ) seq->h_next->h_prev = prev_seq;
-                }
-                else
-                {
-                    first_seq = seq->h_next;
-                    if( seq->h_next ) seq->h_next->h_prev = NULL;
-                }
-            }
-            else
-            {
-                region_count++;
-            }
-        }
-        bg_model->foreground_regions = first_seq;
-        cvZero(bg_model->foreground);
-        cvDrawContours(bg_model->foreground, first_seq, CV_RGB(0, 0, 255), CV_RGB(0, 0, 255), 10, -1);
-
-        return region_count; 
-    }
-
-    return 1;
-}
-
-
 namespace cv
 {
 
index 83c82d4..48df51c 100644 (file)
@@ -24,6 +24,7 @@
 #include "opencv2/video/background_segm.hpp"
 #include "opencv2/imgproc/imgproc_c.h"
 #include "opencv2/highgui/highgui.hpp"
+#include "opencv2/legacy/legacy.hpp"
 
 #include <stdio.h>
 #include <stdlib.h>
index a7b7866..7020b1b 100644 (file)
@@ -1,5 +1,6 @@
 #include "opencv2/video/background_segm.hpp"
 #include "opencv2/legacy/blobtrack.hpp"
+#include "opencv2/legacy/legacy.hpp"
 #include "opencv2/highgui/highgui.hpp"
 #include <opencv2/imgproc/imgproc_c.h>