diff --git a/modules/features2d/doc/object_categorization.rst b/modules/features2d/doc/object_categorization.rst index 73089ce7a..3cde0ec5b 100644 --- a/modules/features2d/doc/object_categorization.rst +++ b/modules/features2d/doc/object_categorization.rst @@ -118,6 +118,7 @@ The class declaration is the following: :: public: BOWImgDescriptorExtractor( const Ptr& dextractor, const Ptr& dmatcher ); + BOWImgDescriptorExtractor( const Ptr& dmatcher ); virtual ~BOWImgDescriptorExtractor(){} void setVocabulary( const Mat& vocabulary ); @@ -126,6 +127,8 @@ The class declaration is the following: :: Mat& imgDescriptor, vector >* pointIdxsOfClusters=0, Mat* descriptors=0 ); + void compute( const Mat& descriptors, Mat& imgDescriptor, + std::vector >* pointIdxsOfClusters=0 ); int descriptorSize() const; int descriptorType() const; @@ -141,6 +144,7 @@ BOWImgDescriptorExtractor::BOWImgDescriptorExtractor The constructor. .. ocv:function:: BOWImgDescriptorExtractor::BOWImgDescriptorExtractor( const Ptr& dextractor, const Ptr& dmatcher ) +.. ocv:function:: BOWImgDescriptorExtractor::BOWImgDescriptorExtractor( const Ptr& dmatcher ) :param dextractor: Descriptor extractor that is used to compute descriptors for an input image and its keypoints. @@ -171,11 +175,14 @@ BOWImgDescriptorExtractor::compute Computes an image descriptor using the set visual vocabulary. .. ocv:function:: void BOWImgDescriptorExtractor::compute( const Mat& image, vector& keypoints, Mat& imgDescriptor, vector >* pointIdxsOfClusters=0, Mat* descriptors=0 ) +.. ocv:function:: void BOWImgDescriptorExtractor::compute( const Mat& descriptors, Mat& imgDescriptor, std::vector >* pointIdxsOfClusters ) :param image: Image, for which the descriptor is computed. :param keypoints: Keypoints detected in the input image. + :param descriptors: Computed descriptors to match with vocabulary. + :param imgDescriptor: Computed output image descriptor. :param pointIdxsOfClusters: Indices of keypoints that belong to the cluster. This means that ``pointIdxsOfClusters[i]`` are keypoint indices that belong to the ``i`` -th cluster (word of vocabulary) returned if it is non-zero. diff --git a/modules/features2d/include/opencv2/features2d.hpp b/modules/features2d/include/opencv2/features2d.hpp index 2474dd594..d189b7e8e 100644 --- a/modules/features2d/include/opencv2/features2d.hpp +++ b/modules/features2d/include/opencv2/features2d.hpp @@ -1502,12 +1502,15 @@ class CV_EXPORTS BOWImgDescriptorExtractor public: BOWImgDescriptorExtractor( const Ptr& dextractor, const Ptr& dmatcher ); + BOWImgDescriptorExtractor( const Ptr& dmatcher ); virtual ~BOWImgDescriptorExtractor(); void setVocabulary( const Mat& vocabulary ); const Mat& getVocabulary() const; void compute( const Mat& image, std::vector& keypoints, Mat& imgDescriptor, std::vector >* pointIdxsOfClusters=0, Mat* descriptors=0 ); + void compute( const Mat& keypointDescriptors, Mat& imgDescriptor, + std::vector >* pointIdxsOfClusters=0 ); // compute() is not constant because DescriptorMatcher::match is not constant int descriptorSize() const; @@ -1519,41 +1522,6 @@ protected: Ptr dmatcher; }; -/* - * Class to match image descriptors using bag of visual words. - */ -class CV_EXPORTS BOWImgDescriptorMatcher -{ -public: - BOWImgDescriptorMatcher( const Ptr& _dmatcher ); - virtual ~BOWImgDescriptorMatcher(); - - /* - * Compute the matching of the current descriptor according to the vocabulary. - * - * vocDescriptor the descriptors to match - * pointIdxsOfClusters vector of matching - */ - void compute( const Mat & descriptors, Mat& vocDescriptor, std::vector< std::vector< int > > * pointIdxsOfClusters = 0 ); - - /* - * Set the vocabulary - */ - void setVocabulary( const Mat& vocabulary ); - const Mat& getVocabulary() const; - - int descriptorSize() const; - int descriptorType() const; - -protected: - Mat vocabulary; - Ptr dmatcher; - -private: - int _type; -}; - - } /* namespace cv */ #endif diff --git a/modules/features2d/src/bagofwords.cpp b/modules/features2d/src/bagofwords.cpp index 5ef8b5c4b..11f8c4ba3 100644 --- a/modules/features2d/src/bagofwords.cpp +++ b/modules/features2d/src/bagofwords.cpp @@ -121,6 +121,10 @@ BOWImgDescriptorExtractor::BOWImgDescriptorExtractor( const Ptr& _dmatcher ) : + dmatcher(_dmatcher) +{} + BOWImgDescriptorExtractor::~BOWImgDescriptorExtractor() {} @@ -144,12 +148,34 @@ void BOWImgDescriptorExtractor::compute( const Mat& image, std::vector if( keypoints.empty() ) return; - int clusterCount = descriptorSize(); // = vocabulary.rows - // Compute descriptors for the image. Mat descriptors; dextractor->compute( image, keypoints, descriptors ); + compute( descriptors, imgDescriptor, pointIdxsOfClusters ); + + // Add the descriptors of image keypoints + if (_descriptors) { + *_descriptors = descriptors.clone(); + } +} + +int BOWImgDescriptorExtractor::descriptorSize() const +{ + return vocabulary.empty() ? 0 : vocabulary.rows; +} + +int BOWImgDescriptorExtractor::descriptorType() const +{ + return CV_32FC1; +} + +void BOWImgDescriptorExtractor::compute( const Mat& descriptors, Mat& imgDescriptor, std::vector >* pointIdxsOfClusters ) +{ + CV_Assert( vocabulary.empty() != false ); + + int clusterCount = descriptorSize(); // = vocabulary.rows + // Match keypoint descriptors to cluster center (to vocabulary) std::vector matches; dmatcher->match( descriptors, matches ); @@ -176,93 +202,6 @@ void BOWImgDescriptorExtractor::compute( const Mat& image, std::vector // Normalize image descriptor. imgDescriptor /= descriptors.rows; - - // Add the descriptors of image keypoints - if (_descriptors) { - *_descriptors = descriptors.clone(); - } -} - -int BOWImgDescriptorExtractor::descriptorSize() const -{ - return vocabulary.empty() ? 0 : vocabulary.rows; -} - -int BOWImgDescriptorExtractor::descriptorType() const -{ - return CV_32FC1; -} - -BOWImgDescriptorMatcher::BOWImgDescriptorMatcher( const Ptr& _dmatcher ) : - dmatcher(_dmatcher), - _type( -1 ) -{} - -BOWImgDescriptorMatcher::~BOWImgDescriptorMatcher() -{} - -void BOWImgDescriptorMatcher::setVocabulary( const Mat& _vocabulary ) -{ - dmatcher->clear(); - CV_Assert( _vocabulary.type() == CV_32F ); - vocabulary = _vocabulary; - dmatcher->add( std::vector(1, vocabulary) ); -} - -const Mat& BOWImgDescriptorMatcher::getVocabulary() const -{ - return vocabulary; -} - -void BOWImgDescriptorMatcher::compute( const Mat & descriptors, Mat& vocDescriptor, std::vector > * pointIdxsOfClusters ) -{ - vocDescriptor.release(); - - int clusterCount = descriptorSize(); // = vocabulary.rows - - _type = descriptors.type(); - - Mat _descriptors; - if( _type != CV_32F ) - descriptors.convertTo( _descriptors, CV_32F ); - else - descriptors.copyTo( _descriptors ); - // Match keypoint descriptors to cluster center (to vocabulary) - std::vector matches; - dmatcher->match( _descriptors, matches ); - - // Compute image descriptor - if( pointIdxsOfClusters ) - { - pointIdxsOfClusters->clear(); - pointIdxsOfClusters->resize(clusterCount); - } - - vocDescriptor = Mat::zeros( 1, clusterCount, descriptorType() ); - float *dptr = (float*)vocDescriptor.data; - for( size_t i = 0; i < matches.size(); i++ ) - { - int queryIdx = matches[i].queryIdx; - int trainIdx = matches[i].trainIdx; // cluster index - CV_Assert( queryIdx == (int)i ); - - dptr[trainIdx] = dptr[trainIdx] + 1.f; - if( pointIdxsOfClusters ) - (*pointIdxsOfClusters)[trainIdx].push_back( queryIdx ); - } - - // Normalize image descriptor. - vocDescriptor /= descriptors.rows; -} - -int BOWImgDescriptorMatcher::descriptorSize() const -{ - return vocabulary.empty() ? 0 : vocabulary.rows; -} - -int BOWImgDescriptorMatcher::descriptorType() const -{ - return _type; } }