{
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);
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
+
+};
}
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()
{
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;
history = _history > 0 ? _history : defaultHistory;
varThreshold = defaultVarThreshold;
backgroundRatio = min(_backgroundRatio > 0 ? _backgroundRatio : 0.95, 1.);
+ noiseSigma = _noiseSigma <= 0 ? defaultNoiseSigma : _noiseSigma;
}
BackgroundSubtractorMOG::~BackgroundSubtractorMOG()
// 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);
}
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);
}
}
}
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);
}
}
}
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 );
//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;
}
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;
}
}
/* End of file. */
+