From 13b535ac19d537416e98c93f6c19d96d7241e181 Mon Sep 17 00:00:00 2001 From: Maria Dimashova Date: Thu, 30 Sep 2010 14:21:22 +0000 Subject: [PATCH] added BOWTrainer::add() --- .../include/opencv2/features2d/features2d.hpp | 38 +++++++---- modules/features2d/src/bagofwords.cpp | 64 +++++++++++++++++-- modules/features2d/src/detectors.cpp | 6 +- 3 files changed, 88 insertions(+), 20 deletions(-) diff --git a/modules/features2d/include/opencv2/features2d/features2d.hpp b/modules/features2d/include/opencv2/features2d/features2d.hpp index 37969f9cf9..ac48591fee 100644 --- a/modules/features2d/include/opencv2/features2d/features2d.hpp +++ b/modules/features2d/include/opencv2/features2d/features2d.hpp @@ -1356,7 +1356,7 @@ protected: CV_EXPORTS Ptr createFeatureDetector( const string& detectorType ); -class DenseFeatureDetector : public FeatureDetector +class CV_EXPORTS DenseFeatureDetector : public FeatureDetector { public: DenseFeatureDetector() : initFeatureScale(1), featureScaleLevels(1), featureScaleMul(0.1f), @@ -1368,7 +1368,7 @@ public: protected: - virtual void detectImpl( const Mat& image, const Mat& mask, vector& keypoints ) const = 0; + virtual void detectImpl( const Mat& image, const Mat& mask, vector& keypoints ) const; float initFeatureScale; int featureScaleLevels; @@ -1379,7 +1379,6 @@ protected: bool varyXyStepWithScale; bool varyImgBoundWithScale; - }; /* @@ -2240,31 +2239,47 @@ CV_EXPORTS void evaluateGenericDescriptorMatcher( const Mat& img1, const Mat& im /* * Abstract base class for training of a 'bag of visual words' vocabulary from a set of descriptors */ -class BOWTrainer +class CV_EXPORTS BOWTrainer { public: + void add( const Mat& descriptors ); + const vector& getDescriptors() const { return descriptors; } + int descripotorsCount() const { return descriptors.empty() ? 0 : size; } + + virtual void clear(); + /* * Train visual words vocabulary, that is cluster training descriptors and * compute cluster centers. + * Returns cluster centers. * * descriptors Training descriptors computed on images keypoints. - * vocabulary Vocabulary is cluster centers. */ - virtual void cluster( const Mat& descriptors, Mat& vocabulary ) = 0; + virtual Mat cluster() const = 0; + virtual Mat cluster( const Mat& descriptors ) const = 0; + +protected: + vector descriptors; + int size; }; /* * This is BOWTrainer using cv::kmeans to get vocabulary. */ -class BOWKMeansTrainer : public BOWTrainer +class CV_EXPORTS BOWKMeansTrainer : public BOWTrainer { public: BOWKMeansTrainer( int clusterCount, const TermCriteria& termcrit=TermCriteria(), int attempts=3, int flags=KMEANS_PP_CENTERS ); - virtual void cluster( const Mat& descriptors, Mat& vocabulary ); + + + // Returns trained vocabulary (i.e. cluster centers). + virtual Mat cluster() const; + virtual Mat cluster( const Mat& descriptors ) const; protected: + int clusterCount; TermCriteria termcrit; int attempts; @@ -2274,14 +2289,15 @@ protected: /* * Class to compute image descriptor using bad of visual words. */ -class BOWImgDescriptorExtractor +class CV_EXPORTS BOWImgDescriptorExtractor { public: BOWImgDescriptorExtractor( const Ptr& dextractor, const Ptr& dmatcher ); - void set( const Mat& vocabulary ); + void setVocabulary( const Mat& vocabulary ); + const Mat& getVocabulary() const { return vocabulary; } void compute( const Mat& image, vector& keypoints, Mat& imgDescriptor, - vector >& pointIdxsInClusters ); + vector >* pointIdxsInClusters=0 ) const; int descriptorSize() const { return vocabulary.empty() ? 0 : vocabulary.rows; } int descriptorType() const { return CV_32FC1; } diff --git a/modules/features2d/src/bagofwords.cpp b/modules/features2d/src/bagofwords.cpp index 5b158389ac..3c55c18904 100755 --- a/modules/features2d/src/bagofwords.cpp +++ b/modules/features2d/src/bagofwords.cpp @@ -46,15 +46,56 @@ using namespace std; namespace cv { +void BOWTrainer::add( const Mat& _descriptors ) +{ + CV_Assert( !_descriptors.empty() ); + if( !descriptors.empty() ) + { + CV_Assert( descriptors[0].cols == _descriptors.cols ); + CV_Assert( descriptors[0].type() == _descriptors.type() ); + size += _descriptors.rows; + } + else + { + size = _descriptors.rows; + } + + descriptors.push_back(_descriptors); +} + +void BOWTrainer::clear() +{ + descriptors.clear(); +} + BOWKMeansTrainer::BOWKMeansTrainer( int _clusterCount, const TermCriteria& _termcrit, int _attempts, int _flags ) : clusterCount(_clusterCount), termcrit(_termcrit), attempts(_attempts), flags(_flags) {} -void BOWKMeansTrainer::cluster( const Mat& descriptors, Mat& vocabulary ) +Mat BOWKMeansTrainer::cluster() const { - Mat labels; + CV_Assert( !descriptors.empty() ); + + int descCount = 0; + for( size_t i = 0; i < descriptors.size(); i++ ) + descCount += descriptors[i].rows; + + Mat mergedDescriptors( descCount, descriptors[0].cols, descriptors[0].type() ); + for( size_t i = 0, start = 0; i < descriptors.size(); i++ ) + { + Mat submut = mergedDescriptors.rowRange(start, descriptors[i].rows); + descriptors[i].copyTo(submut); + start += descriptors[i].rows; + } + return cluster( mergedDescriptors ); +} + +Mat BOWKMeansTrainer::cluster( const Mat& descriptors ) const +{ + Mat labels, vocabulary; kmeans( descriptors, clusterCount, labels, termcrit, attempts, flags, &vocabulary ); + return vocabulary; } @@ -63,7 +104,7 @@ BOWImgDescriptorExtractor::BOWImgDescriptorExtractor( const Ptrclear(); vocabulary = _vocabulary; @@ -71,8 +112,13 @@ void BOWImgDescriptorExtractor::set( const Mat& _vocabulary ) } void BOWImgDescriptorExtractor::compute( const Mat& image, vector& keypoints, Mat& imgDescriptor, - vector >& pointIdxsInClusters ) + vector >* pointIdxsOfClusters ) const { + imgDescriptor.release(); + + if( keypoints.empty() ) + return; + int clusterCount = descriptorSize(); // = vocabulary.rows // Compute descriptors for the image. @@ -84,7 +130,12 @@ void BOWImgDescriptorExtractor::compute( const Mat& image, vector& key dmatcher->match( descriptors, matches ); // Compute image descriptor - pointIdxsInClusters = vector >(clusterCount); + if( pointIdxsOfClusters ) + { + pointIdxsOfClusters->clear(); + pointIdxsOfClusters->resize(clusterCount); + } + imgDescriptor = Mat( 1, clusterCount, descriptorType(), Scalar::all(0.0) ); float *dptr = (float*)imgDescriptor.data; for( size_t i = 0; i < matches.size(); i++ ) @@ -94,7 +145,8 @@ void BOWImgDescriptorExtractor::compute( const Mat& image, vector& key CV_Assert( queryIdx == (int)i ); dptr[trainIdx] = dptr[trainIdx] + 1.f; - pointIdxsInClusters[trainIdx].push_back( queryIdx ); + if( pointIdxsOfClusters ) + (*pointIdxsOfClusters)[trainIdx].push_back( queryIdx ); } // Normalize image descriptor. diff --git a/modules/features2d/src/detectors.cpp b/modules/features2d/src/detectors.cpp index 9ce4ae7556..61540a7fbf 100644 --- a/modules/features2d/src/detectors.cpp +++ b/modules/features2d/src/detectors.cpp @@ -335,7 +335,7 @@ void SurfFeatureDetector::detectImpl( const Mat& image, const Mat& mask, } /* - * GridAdaptedFeatureDetector + * DenseFeatureDetector */ void DenseFeatureDetector::detectImpl( const Mat& image, const Mat& mask, vector& keypoints ) const { @@ -461,7 +461,7 @@ Ptr createFeatureDetector( const string& detectorType ) FeatureDetector* fd = 0; if( !detectorType.compare( "FAST" ) ) { - fd = new FastFeatureDetector( 10/*threshold*/, true/*nonmax_suppression*/ ); + fd = new FastFeatureDetector( 30/*threshold*/, true/*nonmax_suppression*/ ); } else if( !detectorType.compare( "STAR" ) ) { @@ -475,7 +475,7 @@ Ptr createFeatureDetector( const string& detectorType ) } else if( !detectorType.compare( "SURF" ) ) { - fd = new SurfFeatureDetector( 400./*hessian_threshold*/, 3 /*octaves*/, 4/*octave_layers*/ ); + fd = new SurfFeatureDetector( 500./*hessian_threshold*/, 3 /*octaves*/, 4/*octave_layers*/ ); } else if( !detectorType.compare( "MSER" ) ) {