]> rtime.felk.cvut.cz Git - opencv.git/commitdiff
repaired MoG background subtraction algorithm (tickets #32, #246) ; added camera...
authorvp153 <vp153@73c94f0f-984f-4a5f-82bc-2d8db8d8ee08>
Thu, 1 Apr 2010 23:06:23 +0000 (23:06 +0000)
committervp153 <vp153@73c94f0f-984f-4a5f-82bc-2d8db8d8ee08>
Thu, 1 Apr 2010 23:06:23 +0000 (23:06 +0000)
git-svn-id: https://code.ros.org/svn/opencv/trunk@2968 73c94f0f-984f-4a5f-82bc-2d8db8d8ee08

opencv/include/opencv/cvaux.hpp
opencv/samples/c/bgfg_segm.cpp
opencv/src/cvaux/cvbgfg_gaussmix.cpp

index 77aae3b8f9085270e0da70c16f26646fc27c1516..f5ba5991e00cf900db0f5522243146f438d6f60c 100644 (file)
@@ -1449,7 +1449,7 @@ class CV_EXPORTS BackgroundSubtractorMOG : public BackgroundSubtractor
 {
 public:
     BackgroundSubtractorMOG();
-    BackgroundSubtractorMOG(int history, int nmixtures, double backgroundRatio);
+    BackgroundSubtractorMOG(int history, int nmixtures, double backgroundRatio, double noiseSigma=0);
     virtual ~BackgroundSubtractorMOG();
     virtual void operator()(const Mat& image, Mat& fgmask, double learningRate=0);
     
@@ -1463,363 +1463,364 @@ public:
     int nmixtures;
     double varThreshold;
     double backgroundRatio;
+    double noiseSigma;
 };
  
 
-    // CvAffinePose: defines a parameterized affine transformation of an image patch.
-    // An image patch is rotated on angle phi (in degrees), then scaled lambda1 times
-    // along horizontal and lambda2 times along vertical direction, and then rotated again
-    // on angle (theta - phi).
-    class CvAffinePose
-        {
-        public:
-            float phi;
-            float theta;
-            float lambda1;
-            float lambda2;
-        };
+// CvAffinePose: defines a parameterized affine transformation of an image patch.
+// An image patch is rotated on angle phi (in degrees), then scaled lambda1 times
+// along horizontal and lambda2 times along vertical direction, and then rotated again
+// on angle (theta - phi).
+class CV_EXPORTS CvAffinePose
+{
+public:
+    float phi;
+    float theta;
+    float lambda1;
+    float lambda2;
+};
+
+
+class CV_EXPORTS OneWayDescriptor
+{
+public:
+    OneWayDescriptor();
+    ~OneWayDescriptor();
     
+    // allocates memory for given descriptor parameters
+    void Allocate(int pose_count, CvSize size, int nChannels);
     
-    class CV_EXPORTS OneWayDescriptor
-        {
-        public:
-            OneWayDescriptor();
-            ~OneWayDescriptor();
-            
-            // allocates memory for given descriptor parameters
-            void Allocate(int pose_count, CvSize size, int nChannels);
-            
-            // GenerateSamples: generates affine transformed patches with averaging them over small transformation variations.
-            // If external poses and transforms were specified, uses them instead of generating random ones
-            // - pose_count: the number of poses to be generated
-            // - frontal: the input patch (can be a roi in a larger image)
-            // - norm: if nonzero, normalizes the output patch so that the sum of pixel intensities is 1
-            void GenerateSamples(int pose_count, IplImage* frontal, int norm = 0);
-            
-            // GenerateSamplesFast: generates affine transformed patches with averaging them over small transformation variations.
-            // Uses precalculated transformed pca components.
-            // - frontal: the input patch (can be a roi in a larger image)
-            // - pca_hr_avg: pca average vector
-            // - pca_hr_eigenvectors: pca eigenvectors
-            // - pca_descriptors: an array of precomputed descriptors of pca components containing their affine transformations
-            //   pca_descriptors[0] corresponds to the average, pca_descriptors[1]-pca_descriptors[pca_dim] correspond to eigenvectors
-            void GenerateSamplesFast(IplImage* frontal, CvMat* pca_hr_avg,
-                                     CvMat* pca_hr_eigenvectors, OneWayDescriptor* pca_descriptors);
-            
-            // sets the poses and corresponding transforms
-            void SetTransforms(CvAffinePose* poses, CvMat** transforms);
-            
-            // Initialize: builds a descriptor.
-            // - pose_count: the number of poses to build. If poses were set externally, uses them rather than generating random ones
-            // - frontal: input patch. Can be a roi in a larger image
-            // - feature_name: the feature name to be associated with the descriptor
-            // - norm: if 1, the affine transformed patches are normalized so that their sum is 1
-            void Initialize(int pose_count, IplImage* frontal, const char* feature_name = 0, int norm = 0);
-            
-            // InitializeFast: builds a descriptor using precomputed descriptors of pca components
-            // - pose_count: the number of poses to build
-            // - frontal: input patch. Can be a roi in a larger image
-            // - feature_name: the feature name to be associated with the descriptor
-            // - pca_hr_avg: average vector for PCA
-            // - pca_hr_eigenvectors: PCA eigenvectors (one vector per row)
-            // - pca_descriptors: precomputed descriptors of PCA components, the first descriptor for the average vector
-            // followed by the descriptors for eigenvectors
-            void InitializeFast(int pose_count, IplImage* frontal, const char* feature_name,
-                                CvMat* pca_hr_avg, CvMat* pca_hr_eigenvectors, OneWayDescriptor* pca_descriptors);
-            
-            // ProjectPCASample: unwarps an image patch into a vector and projects it into PCA space
-            // - patch: input image patch
-            // - avg: PCA average vector
-            // - eigenvectors: PCA eigenvectors, one per row
-            // - pca_coeffs: output PCA coefficients
-            void ProjectPCASample(IplImage* patch, CvMat* avg, CvMat* eigenvectors, CvMat* pca_coeffs) const;
-            
-            // InitializePCACoeffs: projects all warped patches into PCA space
-            // - avg: PCA average vector
-            // - eigenvectors: PCA eigenvectors, one per row
-            void InitializePCACoeffs(CvMat* avg, CvMat* eigenvectors);
-            
-            // EstimatePose: finds the closest match between an input patch and a set of patches with different poses
-            // - patch: input image patch
-            // - pose_idx: the output index of the closest pose
-            // - distance: the distance to the closest pose (L2 distance)
-            void EstimatePose(IplImage* patch, int& pose_idx, float& distance) const;
-            
-            // EstimatePosePCA: finds the closest match between an input patch and a set of patches with different poses.
-            // The distance between patches is computed in PCA space
-            // - patch: input image patch
-            // - pose_idx: the output index of the closest pose
-            // - distance: distance to the closest pose (L2 distance in PCA space)
-            // - avg: PCA average vector. If 0, matching without PCA is used
-            // - eigenvectors: PCA eigenvectors, one per row
-            void EstimatePosePCA(CvArr* patch, int& pose_idx, float& distance, CvMat* avg, CvMat* eigenvalues) const;
-            
-            // GetPatchSize: returns the size of each image patch after warping (2 times smaller than the input patch)
-            CvSize GetPatchSize() const
-            {
-                return m_patch_size;
-            }
-            
-            // GetInputPatchSize: returns the required size of the patch that the descriptor is built from
-            // (2 time larger than the patch after warping)
-            CvSize GetInputPatchSize() const
-            {
-                return cvSize(m_patch_size.width*2, m_patch_size.height*2);
-            }
-            
-            // GetPatch: returns a patch corresponding to specified pose index
-            // - index: pose index
-            // - return value: the patch corresponding to specified pose index
-            IplImage* GetPatch(int index);
-            
-            // GetPose: returns a pose corresponding to specified pose index
-            // - index: pose index
-            // - return value: the pose corresponding to specified pose index
-            CvAffinePose GetPose(int index) const;
-            
-            // Save: saves all patches with different poses to a specified path
-            void Save(const char* path);
-            
-            // ReadByName: reads a descriptor from a file storage
-            // - fs: file storage
-            // - parent: parent node
-            // - name: node name
-            // - return value: 1 if succeeded, 0 otherwise
-            int ReadByName(CvFileStorage* fs, CvFileNode* parent, const char* name);
-            
-            // Write: writes a descriptor into a file storage
-            // - fs: file storage
-            // - name: node name
-            void Write(CvFileStorage* fs, const char* name);
-            
-            // GetFeatureName: returns a name corresponding to a feature
-            const char* GetFeatureName() const;
-            
-            // GetCenter: returns the center of the feature
-            CvPoint GetCenter() const;
-            
-            void SetPCADimHigh(int pca_dim_high) {m_pca_dim_high = pca_dim_high;};
-            void SetPCADimLow(int pca_dim_low) {m_pca_dim_low = pca_dim_low;};
-            
-            int GetPCADimLow() const;
-            int GetPCADimHigh() const;
-            
-            CvMat** GetPCACoeffs() const {return m_pca_coeffs;}
-            
-        protected:
-            int m_pose_count; // the number of poses
-            CvSize m_patch_size; // size of each image
-            IplImage** m_samples; // an array of length m_pose_count containing the patch in different poses
-            IplImage* m_input_patch;
-            IplImage* m_train_patch;
-            CvMat** m_pca_coeffs; // an array of length m_pose_count containing pca decomposition of the patch in different poses
-            CvAffinePose* m_affine_poses; // an array of poses
-            CvMat** m_transforms; // an array of affine transforms corresponding to poses
-            
-            std::string m_feature_name; // the name of the feature associated with the descriptor
-            CvPoint m_center; // the coordinates of the feature (the center of the input image ROI)
-            
-            int m_pca_dim_high; // the number of descriptor pca components to use for generating affine poses
-            int m_pca_dim_low; // the number of pca components to use for comparison
-        };
+    // GenerateSamples: generates affine transformed patches with averaging them over small transformation variations.
+    // If external poses and transforms were specified, uses them instead of generating random ones
+    // - pose_count: the number of poses to be generated
+    // - frontal: the input patch (can be a roi in a larger image)
+    // - norm: if nonzero, normalizes the output patch so that the sum of pixel intensities is 1
+    void GenerateSamples(int pose_count, IplImage* frontal, int norm = 0);
     
+    // GenerateSamplesFast: generates affine transformed patches with averaging them over small transformation variations.
+    // Uses precalculated transformed pca components.
+    // - frontal: the input patch (can be a roi in a larger image)
+    // - pca_hr_avg: pca average vector
+    // - pca_hr_eigenvectors: pca eigenvectors
+    // - pca_descriptors: an array of precomputed descriptors of pca components containing their affine transformations
+    //   pca_descriptors[0] corresponds to the average, pca_descriptors[1]-pca_descriptors[pca_dim] correspond to eigenvectors
+    void GenerateSamplesFast(IplImage* frontal, CvMat* pca_hr_avg,
+                             CvMat* pca_hr_eigenvectors, OneWayDescriptor* pca_descriptors);
     
-    // OneWayDescriptorBase: encapsulates functionality for training/loading a set of one way descriptors
-    // and finding the nearest closest descriptor to an input feature
-    class CV_EXPORTS OneWayDescriptorBase
-        {
-        public:
-            
-            // creates an instance of OneWayDescriptor from a set of training files
-            // - patch_size: size of the input (large) patch
-            // - pose_count: the number of poses to generate for each descriptor
-            // - train_path: path to training files
-            // - pca_config: the name of the file that contains PCA for small patches (2 times smaller
-            // than patch_size each dimension
-            // - pca_hr_config: the name of the file that contains PCA for large patches (of patch_size size)
-            // - pca_desc_config: the name of the file that contains descriptors of PCA components
-            OneWayDescriptorBase(CvSize patch_size, int pose_count, const char* train_path = 0, const char* pca_config = 0,
-                                 const char* pca_hr_config = 0, const char* pca_desc_config = 0, int pyr_levels = 1,
-                                 int pca_dim_high = 100, int pca_dim_low = 100);
-            
-            ~OneWayDescriptorBase();
-            
-            // Allocate: allocates memory for a given number of descriptors
-            void Allocate(int train_feature_count);
-            
-            // AllocatePCADescriptors: allocates memory for pca descriptors
-            void AllocatePCADescriptors();
-            
-            // returns patch size
-            CvSize GetPatchSize() const {return m_patch_size;};
-            // returns the number of poses for each descriptor
-            int GetPoseCount() const {return m_pose_count;};
-            
-            // returns the number of pyramid levels
-            int GetPyrLevels() const {return m_pyr_levels;};
-            
-            // returns the number of descriptors
-            int GetDescriptorCount() const {return m_train_feature_count;};
-            
-            // CreateDescriptorsFromImage: creates descriptors for each of the input features
-            // - src: input image
-            // - features: input features
-            // - pyr_levels: the number of pyramid levels
-            void CreateDescriptorsFromImage(IplImage* src, const std::vector<cv::KeyPoint>& features);
-            
-            // CreatePCADescriptors: generates descriptors for PCA components, needed for fast generation of feature descriptors
-            void CreatePCADescriptors();
-            
-            // returns a feature descriptor by feature index
-            const OneWayDescriptor* GetDescriptor(int desc_idx) const {return &m_descriptors[desc_idx];};
-            
-            // FindDescriptor: finds the closest descriptor
-            // - patch: input image patch
-            // - desc_idx: output index of the closest descriptor to the input patch
-            // - pose_idx: output index of the closest pose of the closest descriptor to the input patch
-            // - distance: distance from the input patch to the closest feature pose
-            // - _scales: scales of the input patch for each descriptor
-            // - scale_ranges: input scales variation (float[2])
-            void FindDescriptor(IplImage* patch, int& desc_idx, int& pose_idx, float& distance, float* _scale = 0, float* scale_ranges = 0) const;
-            
-            // - patch: input image patch
-            // - n: number of the closest indexes
-            // - desc_idxs: output indexes of the closest descriptor to the input patch (n)
-            // - pose_idx: output indexes of the closest pose of the closest descriptor to the input patch (n)
-            // - distances: distance from the input patch to the closest feature pose (n)
-            // - _scales: scales of the input patch
-            // - scale_ranges: input scales variation (float[2])
-            void FindDescriptor(IplImage* patch, int n, std::vector<int>& desc_idxs, std::vector<int>& pose_idxs,
-                                std::vector<float>& distances, std::vector<float>& _scales, float* scale_ranges = 0) const;
-            
-            // FindDescriptor: finds the closest descriptor
-            // - src: input image
-            // - pt: center of the feature
-            // - desc_idx: output index of the closest descriptor to the input patch
-            // - pose_idx: output index of the closest pose of the closest descriptor to the input patch
-            // - distance: distance from the input patch to the closest feature pose
-            void FindDescriptor(IplImage* src, cv::Point2f pt, int& desc_idx, int& pose_idx, float& distance) const;
-            
-            // InitializePoses: generates random poses
-            void InitializePoses();
-            
-            // InitializeTransformsFromPoses: generates 2x3 affine matrices from poses (initializes m_transforms)
-            void InitializeTransformsFromPoses();
-            
-            // InitializePoseTransforms: subsequently calls InitializePoses and InitializeTransformsFromPoses
-            void InitializePoseTransforms();
-            
-            // InitializeDescriptor: initializes a descriptor
-            // - desc_idx: descriptor index
-            // - train_image: image patch (ROI is supported)
-            // - feature_label: feature textual label
-            void InitializeDescriptor(int desc_idx, IplImage* train_image, const char* feature_label);
-            
-            void InitializeDescriptor(int desc_idx, IplImage* train_image, const cv::KeyPoint& keypoint, const char* feature_label);
-            
-            // InitializeDescriptors: load features from an image and create descriptors for each of them
-            void InitializeDescriptors(IplImage* train_image, const vector<cv::KeyPoint>& features,
-                                       const char* feature_label = "", int desc_start_idx = 0);
-            
-            // LoadPCADescriptors: loads PCA descriptors from a file
-            // - filename: input filename
-            int LoadPCADescriptors(const char* filename);
-            
-            // SavePCADescriptors: saves PCA descriptors to a file
-            // - filename: output filename
-            void SavePCADescriptors(const char* filename);
-            
-            // SetPCAHigh: sets the high resolution pca matrices (copied to internal structures)
-            void SetPCAHigh(CvMat* avg, CvMat* eigenvectors);
-            
-            // SetPCALow: sets the low resolution pca matrices (copied to internal structures)
-            void SetPCALow(CvMat* avg, CvMat* eigenvectors);
-            
-            int GetLowPCA(CvMat** avg, CvMat** eigenvectors)
-            {
-                *avg = m_pca_avg;
-                *eigenvectors = m_pca_eigenvectors;
-                return m_pca_dim_low;
-            };
-            
-            void ConvertDescriptorsArrayToTree(); // Converting pca_descriptors array to KD tree
-            
-            
-        protected:
-            CvSize m_patch_size; // patch size
-            int m_pose_count; // the number of poses for each descriptor
-            int m_train_feature_count; // the number of the training features
-            OneWayDescriptor* m_descriptors; // array of train feature descriptors
-            CvMat* m_pca_avg; // PCA average Vector for small patches
-            CvMat* m_pca_eigenvectors; // PCA eigenvectors for small patches
-            CvMat* m_pca_hr_avg; // PCA average Vector for large patches
-            CvMat* m_pca_hr_eigenvectors; // PCA eigenvectors for large patches
-            OneWayDescriptor* m_pca_descriptors; // an array of PCA descriptors
-            
-            cv::flann::Index* m_pca_descriptors_tree;
-            CvMat* m_pca_descriptors_matrix;
-            
-            CvAffinePose* m_poses; // array of poses
-            CvMat** m_transforms; // array of affine transformations corresponding to poses
-            
-            int m_pca_dim_high;
-            int m_pca_dim_low;
-            
-            int m_pyr_levels;
-            
-        };
+    // sets the poses and corresponding transforms
+    void SetTransforms(CvAffinePose* poses, CvMat** transforms);
     
-    class OneWayDescriptorObject : public OneWayDescriptorBase
-        {
-        public:
-            // creates an instance of OneWayDescriptorObject from a set of training files
-            // - patch_size: size of the input (large) patch
-            // - pose_count: the number of poses to generate for each descriptor
-            // - train_path: path to training files
-            // - pca_config: the name of the file that contains PCA for small patches (2 times smaller
-            // than patch_size each dimension
-            // - pca_hr_config: the name of the file that contains PCA for large patches (of patch_size size)
-            // - pca_desc_config: the name of the file that contains descriptors of PCA components
-            OneWayDescriptorObject(CvSize patch_size, int pose_count, const char* train_path, const char* pca_config,
-                                   const char* pca_hr_config = 0, const char* pca_desc_config = 0, int pyr_levels = 1);
-            
-            ~OneWayDescriptorObject();
-            
-            // Allocate: allocates memory for a given number of features
-            // - train_feature_count: the total number of features
-            // - object_feature_count: the number of features extracted from the object
-            void Allocate(int train_feature_count, int object_feature_count);
-            
-            
-            void SetLabeledFeatures(const vector<cv::KeyPoint>& features) {m_train_features = features;};
-            vector<cv::KeyPoint>& GetLabeledFeatures() {return m_train_features;};
-            const vector<cv::KeyPoint>& GetLabeledFeatures() const {return m_train_features;};
-            vector<cv::KeyPoint> _GetLabeledFeatures() const;
-            
-            // IsDescriptorObject: returns 1 if descriptor with specified index is positive, otherwise 0
-            int IsDescriptorObject(int desc_idx) const;
-            
-            // MatchPointToPart: returns the part number of a feature if it matches one of the object parts, otherwise -1
-            int MatchPointToPart(CvPoint pt) const;
-            
-            // GetDescriptorPart: returns the part number of the feature corresponding to a specified descriptor
-            // - desc_idx: descriptor index
-            int GetDescriptorPart(int desc_idx) const;
-            
-            
-            void InitializeObjectDescriptors(IplImage* train_image, const vector<cv::KeyPoint>& features,
-                                             const char* feature_label, int desc_start_idx = 0, float scale = 1.0f,
-                                             int is_background = 0);
-            
-            // GetObjectFeatureCount: returns the number of object features
-            int GetObjectFeatureCount() const {return m_object_feature_count;};
-            
-        protected:
-            int* m_part_id; // contains part id for each of object descriptors
-            vector<cv::KeyPoint> m_train_features; // train features
-            int m_object_feature_count; // the number of the positive features
-            
-        };
+    // Initialize: builds a descriptor.
+    // - pose_count: the number of poses to build. If poses were set externally, uses them rather than generating random ones
+    // - frontal: input patch. Can be a roi in a larger image
+    // - feature_name: the feature name to be associated with the descriptor
+    // - norm: if 1, the affine transformed patches are normalized so that their sum is 1
+    void Initialize(int pose_count, IplImage* frontal, const char* feature_name = 0, int norm = 0);
+    
+    // InitializeFast: builds a descriptor using precomputed descriptors of pca components
+    // - pose_count: the number of poses to build
+    // - frontal: input patch. Can be a roi in a larger image
+    // - feature_name: the feature name to be associated with the descriptor
+    // - pca_hr_avg: average vector for PCA
+    // - pca_hr_eigenvectors: PCA eigenvectors (one vector per row)
+    // - pca_descriptors: precomputed descriptors of PCA components, the first descriptor for the average vector
+    // followed by the descriptors for eigenvectors
+    void InitializeFast(int pose_count, IplImage* frontal, const char* feature_name,
+                        CvMat* pca_hr_avg, CvMat* pca_hr_eigenvectors, OneWayDescriptor* pca_descriptors);
+    
+    // ProjectPCASample: unwarps an image patch into a vector and projects it into PCA space
+    // - patch: input image patch
+    // - avg: PCA average vector
+    // - eigenvectors: PCA eigenvectors, one per row
+    // - pca_coeffs: output PCA coefficients
+    void ProjectPCASample(IplImage* patch, CvMat* avg, CvMat* eigenvectors, CvMat* pca_coeffs) const;
+    
+    // InitializePCACoeffs: projects all warped patches into PCA space
+    // - avg: PCA average vector
+    // - eigenvectors: PCA eigenvectors, one per row
+    void InitializePCACoeffs(CvMat* avg, CvMat* eigenvectors);
+    
+    // EstimatePose: finds the closest match between an input patch and a set of patches with different poses
+    // - patch: input image patch
+    // - pose_idx: the output index of the closest pose
+    // - distance: the distance to the closest pose (L2 distance)
+    void EstimatePose(IplImage* patch, int& pose_idx, float& distance) const;
+    
+    // EstimatePosePCA: finds the closest match between an input patch and a set of patches with different poses.
+    // The distance between patches is computed in PCA space
+    // - patch: input image patch
+    // - pose_idx: the output index of the closest pose
+    // - distance: distance to the closest pose (L2 distance in PCA space)
+    // - avg: PCA average vector. If 0, matching without PCA is used
+    // - eigenvectors: PCA eigenvectors, one per row
+    void EstimatePosePCA(CvArr* patch, int& pose_idx, float& distance, CvMat* avg, CvMat* eigenvalues) const;
+    
+    // GetPatchSize: returns the size of each image patch after warping (2 times smaller than the input patch)
+    CvSize GetPatchSize() const
+    {
+        return m_patch_size;
+    }
+    
+    // GetInputPatchSize: returns the required size of the patch that the descriptor is built from
+    // (2 time larger than the patch after warping)
+    CvSize GetInputPatchSize() const
+    {
+        return cvSize(m_patch_size.width*2, m_patch_size.height*2);
+    }
+    
+    // GetPatch: returns a patch corresponding to specified pose index
+    // - index: pose index
+    // - return value: the patch corresponding to specified pose index
+    IplImage* GetPatch(int index);
+    
+    // GetPose: returns a pose corresponding to specified pose index
+    // - index: pose index
+    // - return value: the pose corresponding to specified pose index
+    CvAffinePose GetPose(int index) const;
+    
+    // Save: saves all patches with different poses to a specified path
+    void Save(const char* path);
+    
+    // ReadByName: reads a descriptor from a file storage
+    // - fs: file storage
+    // - parent: parent node
+    // - name: node name
+    // - return value: 1 if succeeded, 0 otherwise
+    int ReadByName(CvFileStorage* fs, CvFileNode* parent, const char* name);
+    
+    // Write: writes a descriptor into a file storage
+    // - fs: file storage
+    // - name: node name
+    void Write(CvFileStorage* fs, const char* name);
+    
+    // GetFeatureName: returns a name corresponding to a feature
+    const char* GetFeatureName() const;
+    
+    // GetCenter: returns the center of the feature
+    CvPoint GetCenter() const;
+    
+    void SetPCADimHigh(int pca_dim_high) {m_pca_dim_high = pca_dim_high;};
+    void SetPCADimLow(int pca_dim_low) {m_pca_dim_low = pca_dim_low;};
+    
+    int GetPCADimLow() const;
+    int GetPCADimHigh() const;
+    
+    CvMat** GetPCACoeffs() const {return m_pca_coeffs;}
+    
+protected:
+    int m_pose_count; // the number of poses
+    CvSize m_patch_size; // size of each image
+    IplImage** m_samples; // an array of length m_pose_count containing the patch in different poses
+    IplImage* m_input_patch;
+    IplImage* m_train_patch;
+    CvMat** m_pca_coeffs; // an array of length m_pose_count containing pca decomposition of the patch in different poses
+    CvAffinePose* m_affine_poses; // an array of poses
+    CvMat** m_transforms; // an array of affine transforms corresponding to poses
+    
+    std::string m_feature_name; // the name of the feature associated with the descriptor
+    CvPoint m_center; // the coordinates of the feature (the center of the input image ROI)
+    
+    int m_pca_dim_high; // the number of descriptor pca components to use for generating affine poses
+    int m_pca_dim_low; // the number of pca components to use for comparison
+};
+
+
+// OneWayDescriptorBase: encapsulates functionality for training/loading a set of one way descriptors
+// and finding the nearest closest descriptor to an input feature
+class CV_EXPORTS OneWayDescriptorBase
+{
+public:
+    
+    // creates an instance of OneWayDescriptor from a set of training files
+    // - patch_size: size of the input (large) patch
+    // - pose_count: the number of poses to generate for each descriptor
+    // - train_path: path to training files
+    // - pca_config: the name of the file that contains PCA for small patches (2 times smaller
+    // than patch_size each dimension
+    // - pca_hr_config: the name of the file that contains PCA for large patches (of patch_size size)
+    // - pca_desc_config: the name of the file that contains descriptors of PCA components
+    OneWayDescriptorBase(CvSize patch_size, int pose_count, const char* train_path = 0, const char* pca_config = 0,
+                         const char* pca_hr_config = 0, const char* pca_desc_config = 0, int pyr_levels = 1,
+                         int pca_dim_high = 100, int pca_dim_low = 100);
+    
+    ~OneWayDescriptorBase();
+    
+    // Allocate: allocates memory for a given number of descriptors
+    void Allocate(int train_feature_count);
+    
+    // AllocatePCADescriptors: allocates memory for pca descriptors
+    void AllocatePCADescriptors();
+    
+    // returns patch size
+    CvSize GetPatchSize() const {return m_patch_size;};
+    // returns the number of poses for each descriptor
+    int GetPoseCount() const {return m_pose_count;};
+    
+    // returns the number of pyramid levels
+    int GetPyrLevels() const {return m_pyr_levels;};
+    
+    // returns the number of descriptors
+    int GetDescriptorCount() const {return m_train_feature_count;};
+    
+    // CreateDescriptorsFromImage: creates descriptors for each of the input features
+    // - src: input image
+    // - features: input features
+    // - pyr_levels: the number of pyramid levels
+    void CreateDescriptorsFromImage(IplImage* src, const std::vector<cv::KeyPoint>& features);
+    
+    // CreatePCADescriptors: generates descriptors for PCA components, needed for fast generation of feature descriptors
+    void CreatePCADescriptors();
+    
+    // returns a feature descriptor by feature index
+    const OneWayDescriptor* GetDescriptor(int desc_idx) const {return &m_descriptors[desc_idx];};
+    
+    // FindDescriptor: finds the closest descriptor
+    // - patch: input image patch
+    // - desc_idx: output index of the closest descriptor to the input patch
+    // - pose_idx: output index of the closest pose of the closest descriptor to the input patch
+    // - distance: distance from the input patch to the closest feature pose
+    // - _scales: scales of the input patch for each descriptor
+    // - scale_ranges: input scales variation (float[2])
+    void FindDescriptor(IplImage* patch, int& desc_idx, int& pose_idx, float& distance, float* _scale = 0, float* scale_ranges = 0) const;
+    
+    // - patch: input image patch
+    // - n: number of the closest indexes
+    // - desc_idxs: output indexes of the closest descriptor to the input patch (n)
+    // - pose_idx: output indexes of the closest pose of the closest descriptor to the input patch (n)
+    // - distances: distance from the input patch to the closest feature pose (n)
+    // - _scales: scales of the input patch
+    // - scale_ranges: input scales variation (float[2])
+    void FindDescriptor(IplImage* patch, int n, std::vector<int>& desc_idxs, std::vector<int>& pose_idxs,
+                        std::vector<float>& distances, std::vector<float>& _scales, float* scale_ranges = 0) const;
+    
+    // FindDescriptor: finds the closest descriptor
+    // - src: input image
+    // - pt: center of the feature
+    // - desc_idx: output index of the closest descriptor to the input patch
+    // - pose_idx: output index of the closest pose of the closest descriptor to the input patch
+    // - distance: distance from the input patch to the closest feature pose
+    void FindDescriptor(IplImage* src, cv::Point2f pt, int& desc_idx, int& pose_idx, float& distance) const;
+    
+    // InitializePoses: generates random poses
+    void InitializePoses();
+    
+    // InitializeTransformsFromPoses: generates 2x3 affine matrices from poses (initializes m_transforms)
+    void InitializeTransformsFromPoses();
+    
+    // InitializePoseTransforms: subsequently calls InitializePoses and InitializeTransformsFromPoses
+    void InitializePoseTransforms();
+    
+    // InitializeDescriptor: initializes a descriptor
+    // - desc_idx: descriptor index
+    // - train_image: image patch (ROI is supported)
+    // - feature_label: feature textual label
+    void InitializeDescriptor(int desc_idx, IplImage* train_image, const char* feature_label);
+    
+    void InitializeDescriptor(int desc_idx, IplImage* train_image, const cv::KeyPoint& keypoint, const char* feature_label);
+    
+    // InitializeDescriptors: load features from an image and create descriptors for each of them
+    void InitializeDescriptors(IplImage* train_image, const vector<cv::KeyPoint>& features,
+                               const char* feature_label = "", int desc_start_idx = 0);
+    
+    // LoadPCADescriptors: loads PCA descriptors from a file
+    // - filename: input filename
+    int LoadPCADescriptors(const char* filename);
+    
+    // SavePCADescriptors: saves PCA descriptors to a file
+    // - filename: output filename
+    void SavePCADescriptors(const char* filename);
+    
+    // SetPCAHigh: sets the high resolution pca matrices (copied to internal structures)
+    void SetPCAHigh(CvMat* avg, CvMat* eigenvectors);
+    
+    // SetPCALow: sets the low resolution pca matrices (copied to internal structures)
+    void SetPCALow(CvMat* avg, CvMat* eigenvectors);
+    
+    int GetLowPCA(CvMat** avg, CvMat** eigenvectors)
+    {
+        *avg = m_pca_avg;
+        *eigenvectors = m_pca_eigenvectors;
+        return m_pca_dim_low;
+    };
+    
+    void ConvertDescriptorsArrayToTree(); // Converting pca_descriptors array to KD tree
+    
+    
+protected:
+    CvSize m_patch_size; // patch size
+    int m_pose_count; // the number of poses for each descriptor
+    int m_train_feature_count; // the number of the training features
+    OneWayDescriptor* m_descriptors; // array of train feature descriptors
+    CvMat* m_pca_avg; // PCA average Vector for small patches
+    CvMat* m_pca_eigenvectors; // PCA eigenvectors for small patches
+    CvMat* m_pca_hr_avg; // PCA average Vector for large patches
+    CvMat* m_pca_hr_eigenvectors; // PCA eigenvectors for large patches
+    OneWayDescriptor* m_pca_descriptors; // an array of PCA descriptors
+    
+    cv::flann::Index* m_pca_descriptors_tree;
+    CvMat* m_pca_descriptors_matrix;
+    
+    CvAffinePose* m_poses; // array of poses
+    CvMat** m_transforms; // array of affine transformations corresponding to poses
+    
+    int m_pca_dim_high;
+    int m_pca_dim_low;
+    
+    int m_pyr_levels;
+    
+};
+
+class OneWayDescriptorObject : public OneWayDescriptorBase
+{
+public:
+    // creates an instance of OneWayDescriptorObject from a set of training files
+    // - patch_size: size of the input (large) patch
+    // - pose_count: the number of poses to generate for each descriptor
+    // - train_path: path to training files
+    // - pca_config: the name of the file that contains PCA for small patches (2 times smaller
+    // than patch_size each dimension
+    // - pca_hr_config: the name of the file that contains PCA for large patches (of patch_size size)
+    // - pca_desc_config: the name of the file that contains descriptors of PCA components
+    OneWayDescriptorObject(CvSize patch_size, int pose_count, const char* train_path, const char* pca_config,
+                           const char* pca_hr_config = 0, const char* pca_desc_config = 0, int pyr_levels = 1);
+    
+    ~OneWayDescriptorObject();
+    
+    // Allocate: allocates memory for a given number of features
+    // - train_feature_count: the total number of features
+    // - object_feature_count: the number of features extracted from the object
+    void Allocate(int train_feature_count, int object_feature_count);
+    
+    
+    void SetLabeledFeatures(const vector<cv::KeyPoint>& features) {m_train_features = features;};
+    vector<cv::KeyPoint>& GetLabeledFeatures() {return m_train_features;};
+    const vector<cv::KeyPoint>& GetLabeledFeatures() const {return m_train_features;};
+    vector<cv::KeyPoint> _GetLabeledFeatures() const;
+    
+    // IsDescriptorObject: returns 1 if descriptor with specified index is positive, otherwise 0
+    int IsDescriptorObject(int desc_idx) const;
+    
+    // MatchPointToPart: returns the part number of a feature if it matches one of the object parts, otherwise -1
+    int MatchPointToPart(CvPoint pt) const;
+    
+    // GetDescriptorPart: returns the part number of the feature corresponding to a specified descriptor
+    // - desc_idx: descriptor index
+    int GetDescriptorPart(int desc_idx) const;
+    
+    
+    void InitializeObjectDescriptors(IplImage* train_image, const vector<cv::KeyPoint>& features,
+                                     const char* feature_label, int desc_start_idx = 0, float scale = 1.0f,
+                                     int is_background = 0);
+    
+    // GetObjectFeatureCount: returns the number of object features
+    int GetObjectFeatureCount() const {return m_object_feature_count;};
+    
+protected:
+    int* m_part_id; // contains part id for each of object descriptors
+    vector<cv::KeyPoint> m_train_features; // train features
+    int m_object_feature_count; // the number of the positive features
+    
+};
     
 
 }
index 15778f8b1284258b439332f31341f9cdb0fa4c5e..348f48e2ebaca72ddb101b8ce03e761c4c6e2987 100644 (file)
@@ -7,38 +7,51 @@ int main(int argc, char** argv)
 {
     IplImage*       tmp_frame = NULL;
     CvCapture*      cap = NULL;
+    bool update_bg_model = true;
 
     if( argc < 2 )
+        cap = cvCaptureFromCAM(0);
+    else
+        cap = cvCaptureFromFile(argv[1]);
+    
+    if( !cap )
     {
-        printf("please specify video file name \n");
-        exit(0);
+        printf("can not open camera or video file\n");
+        return -1;
     }
-
-    cap = cvCaptureFromFile(argv[1]);
+    
     tmp_frame = cvQueryFrame(cap);
     if(!tmp_frame)
     {
-        printf("bad video \n");
-        exit(0);
+        printf("can not read data from the video source\n");
+        return -1;
     }
 
     cvNamedWindow("BG", 1);
     cvNamedWindow("FG", 1);
 
-    //create BG model
-    CvBGStatModel* bg_model = cvCreateFGDStatModel( tmp_frame );
+    CvBGStatModel* bg_model = 0;
     
     for( int fr = 1;tmp_frame; tmp_frame = cvQueryFrame(cap), fr++ )
     {
+        if(!bg_model)
+        {
+            //create BG model
+            bg_model = cvCreateGaussianBGModel( tmp_frame );
+            //bg_model = cvCreateFGDStatModel( temp );
+            continue;
+        }
+        
         double t = (double)cvGetTickCount();
-        cvUpdateBGStatModel( tmp_frame, bg_model );
+        cvUpdateBGStatModel( tmp_frame, bg_model, update_bg_model ? -1 : 0 );
         t = (double)cvGetTickCount() - t;
-        printf( "%.1f\n", t/(cvGetTickFrequency()*1000.) );
+        printf( "%d. %.1f\n", fr, t/(cvGetTickFrequency()*1000.) );
         cvShowImage("BG", bg_model->background);
         cvShowImage("FG", bg_model->foreground);
         char k = cvWaitKey(5);
         if( k == 27 ) break;
-        //printf("frame# %d \r", fr);
+        if( k == ' ' )
+            update_bg_model = !update_bg_model;
     }
 
 
index 3be167beece98a3ea59b16cba82c2dfc3c38b27b..fbd768e7044fbde28051823866a7bb53732a1364 100644 (file)
@@ -67,6 +67,7 @@ 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;
     
 BackgroundSubtractorMOG::BackgroundSubtractorMOG()
 {
@@ -78,9 +79,12 @@ BackgroundSubtractorMOG::BackgroundSubtractorMOG()
     history = defaultHistory;
     varThreshold = defaultVarThreshold;
     backgroundRatio = defaultBackgroundRatio;
+    noiseSigma = defaultNoiseSigma;
 }
     
-BackgroundSubtractorMOG::BackgroundSubtractorMOG(int _history, int _nmixtures, double _backgroundRatio)
+BackgroundSubtractorMOG::BackgroundSubtractorMOG(int _history, int _nmixtures,
+                                                 double _backgroundRatio,
+                                                 double _noiseSigma)
 {
     frameSize = Size(0,0);
     frameType = 0;
@@ -90,6 +94,7 @@ BackgroundSubtractorMOG::BackgroundSubtractorMOG(int _history, int _nmixtures, d
     history = _history > 0 ? _history : defaultHistory;
     varThreshold = defaultVarThreshold;
     backgroundRatio = min(_backgroundRatio > 0 ? _backgroundRatio : 0.95, 1.);
+    noiseSigma = _noiseSigma <= 0 ? defaultNoiseSigma : _noiseSigma;
 }
     
 BackgroundSubtractorMOG::~BackgroundSubtractorMOG()
@@ -110,30 +115,8 @@ void BackgroundSubtractorMOG::initialize(Size _frameSize, int _frameType)
     // the mixture sort key (w/sum_of_variances), the mixture weight (w),
     // the mean (nchannels values) and
     // the diagonal covariance matrix (another nchannels values)
-    bgmodel.create( frameSize.height, frameSize.width*nmixtures*(2 + 2*nchannels), CV_32F );
-    const float w0 = (float)CV_BGFG_MOG_WEIGHT_INIT;
-    const float var0 = (float)(CV_BGFG_MOG_SIGMA_INIT*CV_BGFG_MOG_SIGMA_INIT);
-    const float sk0 = (float)(CV_BGFG_MOG_WEIGHT_INIT/(CV_BGFG_MOG_SIGMA_INIT*sqrt((double)nchannels)));
-    
-    for( int y = 0; y < frameSize.height; y++ )
-    {
-        float* mptr = bgmodel.ptr<float>(y);
-        for( int x = 0; x < frameSize.width; x++ )
-        {
-            for( int k = 0; k < nmixtures; k++ )
-            {
-                mptr[0] = sk0;
-                mptr[1] = w0;
-                mptr += 2;
-                for( int c = 0; c < nchannels; c++ )
-                {
-                    mptr[c] = 0;
-                    mptr[c + nchannels] = var0;
-                }
-                mptr += nchannels*2;
-            }
-        }
-    }
+    bgmodel.create( 1, frameSize.height*frameSize.width*nmixtures*(2 + 2*nchannels), CV_32F );
+    bgmodel = Scalar::all(0);
 }
 
     
@@ -151,66 +134,121 @@ static void process8uC1( BackgroundSubtractorMOG& obj, const Mat& image, Mat& fg
     int x, y, k, k1, rows = image.rows, cols = image.cols;
     float alpha = (float)learningRate, T = (float)obj.backgroundRatio, vT = (float)obj.varThreshold;
     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)(CV_BGFG_MOG_WEIGHT_INIT/CV_BGFG_MOG_SIGMA_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 minVar = (float)(obj.noiseSigma*obj.noiseSigma);
     
     for( y = 0; y < rows; y++ )
     {
         const uchar* src = image.ptr<uchar>(y);
         uchar* dst = fgmask.ptr<uchar>(y);
-        MixData<float>* mptr = (MixData<float>*)obj.bgmodel.ptr(y);
         
-        for( x = 0; x < cols; x++, mptr += K )
+        if( alpha > 0 )
         {
-            float wsum = 0, dw = 0;
-            float pix = src[x];
-            for( k = 0; k < K; k++ )
+            for( x = 0; x < cols; x++, mptr += K )
             {
-                float w = mptr[k].weight;
-                float mu = mptr[k].mean;
-                float var = mptr[k].var;
-                float diff = pix - mu, d2 = diff*diff;
-                if( d2 < vT*var )
+                float wsum = 0;
+                float pix = src[x];
+                int kHit = -1, kForeground = -1;
+                
+                for( k = 0; k < K; k++ )
                 {
-                    dw = alpha*(1.f - w);
-                    mptr[k].weight = w + dw;
-                    mptr[k].mean = mu + alpha*diff;
-                    mptr[k].var = var = max(var + alpha*(d2 - var), FLT_EPSILON);
-                    mptr[k].sortKey = w/sqrt(var);
-                    
-                    for( k1 = k-1; k1 >= 0; k1-- )
+                    float w = mptr[k].weight;
+                    wsum += w;
+                    if( w < FLT_EPSILON )
+                        break;
+                    float mu = mptr[k].mean;
+                    float var = mptr[k].var;
+                    float diff = pix - mu;
+                    float d2 = diff*diff;
+                    if( d2 < vT*var )
                     {
-                        if( mptr[k1].sortKey > mptr[k1+1].sortKey )
-                            break;
-                        std::swap( mptr[k1], mptr[k1+1] );
+                        wsum -= w;
+                        float dw = alpha*(1.f - w);
+                        mptr[k].weight = w + dw;
+                        mptr[k].mean = mu + alpha*diff;
+                        var = max(var + alpha*(d2 - var), minVar);
+                        mptr[k].var = var;
+                        mptr[k].sortKey = w/sqrt(var);
+                        
+                        for( k1 = k-1; k1 >= 0; k1-- )
+                        {
+                            if( mptr[k1].sortKey >= mptr[k1+1].sortKey )
+                                break;
+                            std::swap( mptr[k1], mptr[k1+1] );
+                        }
+                        
+                        kHit = k1+1;
+                        break;
                     }
-                    break;
                 }
-                wsum += w;
-            }
-            
-            dst[x] = (uchar)(-(wsum >= T));
-            wsum += dw;
-            
-            if( k == K ) // no appropriate gaussian mixture found at all, remove the weakest mixture and create a new one
-            {
-                wsum += w0 - mptr[K-1].weight;
-                mptr[K-1].weight = w0;
-                mptr[K-1].mean = pix;
-                mptr[K-1].var = var0;
-                mptr[K-1].sortKey = sk0;
+                
+                if( kHit < 0 ) // no appropriate gaussian mixture found at all, remove the weakest mixture and create a new one
+                {
+                    kHit = k = min(k, K-1);
+                    wsum += w0 - mptr[k].weight;
+                    mptr[k].weight = w0;
+                    mptr[k].mean = pix;
+                    mptr[k].var = var0;
+                    mptr[k].sortKey = sk0;
+                }
+                else
+                    for( ; k < K; k++ )
+                        wsum += mptr[k].weight;
+                
+                float wscale = 1.f/wsum;
+                wsum = 0;
+                for( k = 0; k < K; k++ )
+                {
+                    wsum += mptr[k].weight *= wscale;
+                    mptr[k].sortKey *= wscale;
+                    if( wsum > T && kForeground < 0 )
+                        kForeground = k+1;
+                }
+                
+                dst[x] = (uchar)(-(kHit >= kForeground));
             }
-            else
-                for( ; k < K; k++ )
-                    wsum += mptr[k].weight;
-            
-            dw = 1.f/wsum;
-            for( k = 0; k < K; k++ )
+        }
+        else
+        {
+            for( x = 0; x < cols; x++, mptr += K )
             {
-                mptr[k].weight *= dw;
-                mptr[k].sortKey *= dw;
+                float pix = src[x];
+                int kHit = -1, kForeground = -1;
+                
+                for( k = 0; k < K; k++ )
+                {
+                    if( mptr[k].weight < FLT_EPSILON )
+                        break;
+                    float mu = mptr[k].mean;
+                    float var = mptr[k].var;
+                    float diff = pix - mu;
+                    float d2 = diff*diff;
+                    if( d2 < vT*var )
+                    {
+                        kHit = k;
+                        break;
+                    }
+                }
+                
+                if( kHit >= 0 )
+                {
+                    float wsum = 0;
+                    for( k = 0; k < K; k++ )
+                    {
+                        wsum += mptr[k].weight;
+                        if( wsum > T )
+                        {
+                            kForeground = k+1;
+                            break;
+                        }
+                    }
+                }
+                
+                dst[x] = (uchar)(kHit < 0 || kHit >= kForeground ? 255 : 0);
             }
         }
     }
@@ -223,68 +261,121 @@ static void process8uC3( BackgroundSubtractorMOG& obj, const Mat& image, Mat& fg
     int K = obj.nmixtures;
     
     const float w0 = (float)CV_BGFG_MOG_WEIGHT_INIT;
-    const float sk0 = (float)(CV_BGFG_MOG_WEIGHT_INIT/CV_BGFG_MOG_SIGMA_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 minVar = (float)(obj.noiseSigma*obj.noiseSigma);
+    MixData<Vec3f>* mptr = (MixData<Vec3f>*)obj.bgmodel.data;
     
     for( y = 0; y < rows; y++ )
     {
         const uchar* src = image.ptr<uchar>(y);
         uchar* dst = fgmask.ptr<uchar>(y);
-        MixData<Vec3f>* mptr = (MixData<Vec3f>*)obj.bgmodel.ptr(y);
         
-        for( x = 0; x < cols; x++, mptr += K )
+        if( alpha > 0 )
         {
-            float wsum = 0, dw = 0;
-            Vec3f pix(src[x*3], src[x*3+1], src[x*3+2]);
-            for( k = 0; k < K; k++ )
+            for( x = 0; x < cols; x++, mptr += K )
             {
-                float w = mptr[k].weight;
-                Vec3f mu = mptr[k].mean[0];
-                Vec3f var = mptr[k].var[0];
-                Vec3f diff = pix - mu;
-                float d2 = diff.dot(diff);
-                if( d2 < vT*(var[0] + var[1] + var[2]) )
+                float wsum = 0;
+                Vec3f pix(src[x*3], src[x*3+1], src[x*3+2]);
+                int kHit = -1, kForeground = -1;
+                
+                for( k = 0; k < K; k++ )
                 {
-                    dw = alpha*(1.f - w);
-                    mptr[k].weight = w + dw;
-                    mptr[k].mean = mu + alpha*diff;
-                    var = Vec3f(max(var[0] + alpha*(diff[0]*diff[0] - var[0]), FLT_EPSILON),
-                                max(var[1] + alpha*(diff[1]*diff[1] - var[1]), FLT_EPSILON),
-                                max(var[2] + alpha*(diff[2]*diff[2] - var[2]), FLT_EPSILON));
-                    mptr[k].var = var;
-                    mptr[k].sortKey = w/sqrt(var[0] + var[1] + var[2]);
-                    
-                    for( k1 = k-1; k1 >= 0; k1-- )
+                    float w = mptr[k].weight;
+                    wsum += w;
+                    if( w < FLT_EPSILON )
+                        break;
+                    Vec3f mu = mptr[k].mean;
+                    Vec3f var = mptr[k].var;
+                    Vec3f diff = pix - mu;
+                    float d2 = diff.dot(diff);
+                    if( d2 < vT*(var[0] + var[1] + var[2]) )
                     {
-                        if( mptr[k1].sortKey > mptr[k1+1].sortKey )
-                            break;
-                        std::swap( mptr[k1], mptr[k1+1] );
+                        wsum -= w;
+                        float dw = alpha*(1.f - w);
+                        mptr[k].weight = w + dw;
+                        mptr[k].mean = mu + alpha*diff;
+                        var = Vec3f(max(var[0] + alpha*(diff[0]*diff[0] - var[0]), minVar),
+                                    max(var[1] + alpha*(diff[1]*diff[1] - var[1]), minVar),
+                                    max(var[2] + alpha*(diff[2]*diff[2] - var[2]), minVar));
+                        mptr[k].var = var;
+                        mptr[k].sortKey = w/sqrt(var[0] + var[1] + var[2]);
+                        
+                        for( k1 = k-1; k1 >= 0; k1-- )
+                        {
+                            if( mptr[k1].sortKey >= mptr[k1+1].sortKey )
+                                break;
+                            std::swap( mptr[k1], mptr[k1+1] );
+                        }
+                        
+                        kHit = k1+1;
+                        break;
                     }
-                    break;
                 }
-                wsum += w;
-            }
-            
-            dst[x] = (uchar)(-(wsum >= T));
-            wsum += dw;
+                
+                if( kHit < 0 ) // no appropriate gaussian mixture found at all, remove the weakest mixture and create a new one
+                {
+                    kHit = k = min(k, K-1);
+                    wsum += w0 - mptr[k].weight;
+                    mptr[k].weight = w0;
+                    mptr[k].mean = pix;
+                    mptr[k].var = Vec3f(var0, var0, var0);
+                    mptr[k].sortKey = sk0;
+                }
+                else
+                    for( ; k < K; k++ )
+                        wsum += mptr[k].weight;
             
-            if( k == K ) // no appropriate gaussian mixture found at all, remove the weakest mixture and create a new one
-            {
-                wsum += w0 - mptr[K-1].weight;
-                mptr[K-1].weight = w0;
-                mptr[K-1].mean = pix;
-                mptr[K-1].var = Vec3f(var0, var0, var0);
-                mptr[K-1].sortKey = sk0;
+                float wscale = 1.f/wsum;
+                wsum = 0;
+                for( k = 0; k < K; k++ )
+                {
+                    wsum += mptr[k].weight *= wscale;
+                    mptr[k].sortKey *= wscale;
+                    if( wsum > T && kForeground < 0 )
+                        kForeground = k+1;
+                }
+                
+                dst[x] = (uchar)(-(kHit >= kForeground));
             }
-            else
-                for( ; k < K; k++ )
-                    wsum += mptr[k].weight;
-            
-            dw = 1.f/wsum;
-            for( k = 0; k < K; k++ )
+        }
+        else
+        {
+            for( x = 0; x < cols; x++, mptr += K )
             {
-                mptr[k].weight *= dw;
-                mptr[k].sortKey *= dw;
+                Vec3f pix(src[x*3], src[x*3+1], src[x*3+2]);
+                int kHit = -1, kForeground = -1;
+                
+                for( k = 0; k < K; k++ )
+                {
+                    if( mptr[k].weight < FLT_EPSILON )
+                        break;
+                    Vec3f mu = mptr[k].mean;
+                    Vec3f var = mptr[k].var;
+                    Vec3f diff = pix - mu;
+                    float d2 = diff.dot(diff);
+                    if( d2 < vT*(var[0] + var[1] + var[2]) )
+                    {
+                        kHit = k;
+                        break;
+                    }
+                }
+                if( kHit >= 0 )
+                {
+                    float wsum = 0;
+                    for( k = 0; k < K; k++ )
+                    {
+                        wsum += mptr[k].weight;
+                        if( wsum > T )
+                        {
+                            kForeground = k+1;
+                            break;
+                        }
+                    }
+                }
+                
+                dst[x] = (uchar)(kHit < 0 || kHit >= kForeground ? 255 : 0);
             }
         }
     }
@@ -295,13 +386,14 @@ void BackgroundSubtractorMOG::operator()(const Mat& image, Mat& fgmask, double l
     bool needToInitialize = nframes == 0 || learningRate >= 1 || image.size() != frameSize || image.type() != frameType;
     
     if( needToInitialize )
-        initialize(frameSize, frameType);
+        initialize(image.size(), image.type());
     
     CV_Assert( image.depth() == CV_8U );
     fgmask.create( image.size(), CV_8U );
     
     ++nframes;
     learningRate = learningRate >= 0 && nframes > 1 ? learningRate : 1./min( nframes, history );
+    CV_Assert(learningRate >= 0);
     
     if( image.type() == CV_8UC1 )
         process8uC1( *this, image, fgmask, learningRate );
@@ -366,7 +458,7 @@ icvUpdateGaussianBGModel( IplImage* curr_frame, CvGaussBGModel*  bg_model, doubl
     //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 );
+    /*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;
@@ -392,7 +484,9 @@ icvUpdateGaussianBGModel( IplImage* curr_frame, CvGaussBGModel*  bg_model, doubl
     }
     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);
+    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;
 }
@@ -446,3 +540,4 @@ cvCreateGaussianBGModel( IplImage* first_frame, CvGaussBGStatModelParams* parame
 }
 
 /* End of file. */
+