Adding class for BOW image matcher (Feature #3005).
authorMathieu Barnachon <mathieu.barnachon@gmail.com>
Sat, 17 Aug 2013 23:32:04 +0000 (11:32 +1200)
committerMathieu Barnachon <mathieu.barnachon@gmail.com>
Sat, 17 Aug 2013 23:32:04 +0000 (11:32 +1200)
Same prototype as BOWImgDescriptorExtractor, but do only the matching.
If the feature is accepted, the BOWImgDescriptorExtractor and BOWImgDescriptorMatcher should probably refactor with inheritance.
Add a class to compute the keypoints, descriptors and matching from an image should be added to.

modules/features2d/include/opencv2/features2d.hpp
modules/features2d/src/bagofwords.cpp

index 1f0a92c..2474dd5 100644 (file)
@@ -1519,6 +1519,41 @@ protected:
     Ptr<DescriptorMatcher> dmatcher;
 };
 
+/*
+ * Class to match image descriptors using bag of visual words.
+ */
+class CV_EXPORTS BOWImgDescriptorMatcher
+{
+public:
+    BOWImgDescriptorMatcher( const Ptr<DescriptorMatcher>& _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<DescriptorMatcher> dmatcher;
+
+private:
+    int _type;
+};
+
+
 } /* namespace cv */
 
 #endif
index 4307983..5ef8b5c 100644 (file)
@@ -193,4 +193,76 @@ int BOWImgDescriptorExtractor::descriptorType() const
     return CV_32FC1;
 }
 
+BOWImgDescriptorMatcher::BOWImgDescriptorMatcher( const Ptr<DescriptorMatcher>& _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<Mat>(1, vocabulary) );
+}
+
+const Mat& BOWImgDescriptorMatcher::getVocabulary() const
+{
+    return vocabulary;
+}
+
+void BOWImgDescriptorMatcher::compute( const Mat & descriptors, Mat& vocDescriptor, std::vector<std::vector<int> > * 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<DMatch> 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;
+}
+
 }