diff --git a/modules/features2d/doc/object_categorization.rst b/modules/features2d/doc/object_categorization.rst
index 826919519..7516e356a 100644
--- a/modules/features2d/doc/object_categorization.rst
+++ b/modules/features2d/doc/object_categorization.rst
@@ -124,6 +124,7 @@ The class declaration is the following: ::
         public:
             BOWImgDescriptorExtractor( const Ptr<DescriptorExtractor>& dextractor,
                                        const Ptr<DescriptorMatcher>& dmatcher );
+            BOWImgDescriptorExtractor( const Ptr<DescriptorMatcher>& dmatcher );
             virtual ~BOWImgDescriptorExtractor(){}
 
             void setVocabulary( const Mat& vocabulary );
@@ -132,6 +133,8 @@ The class declaration is the following: ::
                           Mat& imgDescriptor,
                           vector<vector<int> >* pointIdxsOfClusters=0,
                           Mat* descriptors=0 );
+            void compute( const Mat& descriptors, Mat& imgDescriptor,
+                          std::vector<std::vector<int> >* pointIdxsOfClusters=0 );
             int descriptorSize() const;
             int descriptorType() const;
 
@@ -147,6 +150,7 @@ BOWImgDescriptorExtractor::BOWImgDescriptorExtractor
 The constructor.
 
 .. ocv:function:: BOWImgDescriptorExtractor::BOWImgDescriptorExtractor(           const Ptr<DescriptorExtractor>& dextractor,          const Ptr<DescriptorMatcher>& dmatcher )
+.. ocv:function:: BOWImgDescriptorExtractor::BOWImgDescriptorExtractor(           const Ptr<DescriptorMatcher>& dmatcher )
 
     :param dextractor: Descriptor extractor that is used to compute descriptors for an input image and its keypoints.
 
@@ -177,11 +181,14 @@ BOWImgDescriptorExtractor::compute
 Computes an image descriptor using the set visual vocabulary.
 
 .. ocv:function:: void BOWImgDescriptorExtractor::compute( const Mat& image, vector<KeyPoint>& keypoints, Mat& imgDescriptor, vector<vector<int> >* pointIdxsOfClusters=0, Mat* descriptors=0 )
+.. ocv:function:: void BOWImgDescriptorExtractor::compute( const Mat& keypointDescriptors, Mat& imgDescriptor, std::vector<std::vector<int> >* pointIdxsOfClusters=0 )
 
     :param image: Image, for which the descriptor is computed.
 
     :param keypoints: Keypoints detected in the input image.
 
+    :param keypointDescriptors: 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 3655ab813..6aad4beb2 100644
--- a/modules/features2d/include/opencv2/features2d.hpp
+++ b/modules/features2d/include/opencv2/features2d.hpp
@@ -1512,12 +1512,15 @@ class CV_EXPORTS BOWImgDescriptorExtractor
 public:
     BOWImgDescriptorExtractor( const Ptr<DescriptorExtractor>& dextractor,
                                const Ptr<DescriptorMatcher>& dmatcher );
+    BOWImgDescriptorExtractor( const Ptr<DescriptorMatcher>& dmatcher );
     virtual ~BOWImgDescriptorExtractor();
 
     void setVocabulary( const Mat& vocabulary );
     const Mat& getVocabulary() const;
     void compute( const Mat& image, std::vector<KeyPoint>& keypoints, Mat& imgDescriptor,
                   std::vector<std::vector<int> >* pointIdxsOfClusters=0, Mat* descriptors=0 );
+    void compute( const Mat& keypointDescriptors, Mat& imgDescriptor,
+                  std::vector<std::vector<int> >* pointIdxsOfClusters=0 );
     // compute() is not constant because DescriptorMatcher::match is not constant
 
     int descriptorSize() const;
diff --git a/modules/features2d/src/bagofwords.cpp b/modules/features2d/src/bagofwords.cpp
index a3cfb60a9..2836f5272 100644
--- a/modules/features2d/src/bagofwords.cpp
+++ b/modules/features2d/src/bagofwords.cpp
@@ -121,6 +121,10 @@ BOWImgDescriptorExtractor::BOWImgDescriptorExtractor( const Ptr<DescriptorExtrac
     dextractor(_dextractor), dmatcher(_dmatcher)
 {}
 
+BOWImgDescriptorExtractor::BOWImgDescriptorExtractor( const Ptr<DescriptorMatcher>& _dmatcher ) :
+    dmatcher(_dmatcher)
+{}
+
 BOWImgDescriptorExtractor::~BOWImgDescriptorExtractor()
 {}
 
@@ -137,22 +141,44 @@ const Mat& BOWImgDescriptorExtractor::getVocabulary() const
 }
 
 void BOWImgDescriptorExtractor::compute( const Mat& image, std::vector<KeyPoint>& keypoints, Mat& imgDescriptor,
-                                         std::vector<std::vector<int> >* pointIdxsOfClusters, Mat* _descriptors )
+                                         std::vector<std::vector<int> >* pointIdxsOfClusters, Mat* descriptors )
 {
     imgDescriptor.release();
 
     if( keypoints.empty() )
         return;
 
-    int clusterCount = descriptorSize(); // = vocabulary.rows
-
     // Compute descriptors for the image.
-    Mat descriptors;
-    dextractor->compute( image, keypoints, descriptors );
+    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& keypointDescriptors, Mat& imgDescriptor, std::vector<std::vector<int> >* pointIdxsOfClusters )
+{
+    CV_Assert( vocabulary.empty() != false );
+
+    int clusterCount = descriptorSize(); // = vocabulary.rows
 
     // Match keypoint descriptors to cluster center (to vocabulary)
     std::vector<DMatch> matches;
-    dmatcher->match( descriptors, matches );
+    dmatcher->match( keypointDescriptors, matches );
 
     // Compute image descriptor
     if( pointIdxsOfClusters )
@@ -175,22 +201,7 @@ void BOWImgDescriptorExtractor::compute( const Mat& image, std::vector<KeyPoint>
     }
 
     // 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;
+    imgDescriptor /= keypointDescriptors.rows;
 }
 
 }