Error in "BOWImgDescriptorExtractor::setVocabulary"

The code (description of the error below):

#include <iostream>
#include <bits/stdc++.h>
#include "opencv2/core.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/features2d.hpp"
#include "opencv2/xfeatures2d.hpp"


using namespace cv;
using namespace cv::xfeatures2d;
using std::cout;
using std::endl;


#define SURF_EXTRACTOR  0
#define SIFT_EXTRACTOR  1
#define ORB_EXTRACTOR   2
#define BRISK_EXTRACTOR 3

const char* keys =
    "{ help h |                  | Print help message. }"
    "{ input1 | box.png          | Path to input image 1. }"
    "{ input2 | box_in_scene.png | Path to input image 2. }"
    "{ extractor | 0 | Feature extractor utilized. }";


class Timer{
public:
    Timer(){};
    void tic();
    void toc();
    void get_time(std::string instance);
private:
    time_t start;
    time_t end;
};

void Timer::tic(){
    time(&start);
}

void Timer::toc(){
    time(&end);
}

void Timer::get_time(std::string instance){
    double teste = double(end - start);
    std::cout << instance << "execution time is: " << teste << std::setprecision(5) << std::endl;
}

int main( int argc, char* argv[] )
{
    Timer t;
    time_t start,end;
    time(&start);
    std::ios_base::sync_with_stdio(false);
    CommandLineParser parser( argc, argv, keys );
    if (parser.has("help")) {
        parser.printMessage();
        return 0;
    }
    Mat img1 = imread( samples::findFile( parser.get<std::string>("input1") ), IMREAD_GRAYSCALE );
    Mat img2 = imread( samples::findFile( parser.get<std::string>("input2") ), IMREAD_GRAYSCALE );
    if ( img1.empty() || img2.empty() )
    {
        cout << "Could not open or find the image!\n" << endl;
        parser.printMessage();
        return -1;
    }
    
    Ptr<DescriptorExtractor> detector;
    Ptr<DescriptorMatcher> matcher;

    switch (parser.get<int>("extractor"))
    {
    case SURF_EXTRACTOR:
        {
            detector = SURF::create();
            matcher = DescriptorMatcher::create(DescriptorMatcher::BRUTEFORCE);
            break;
        }
    case SIFT_EXTRACTOR:
        {
            detector = SIFT::create();
            matcher = DescriptorMatcher::create(DescriptorMatcher::BRUTEFORCE);
            break;
        }
    case ORB_EXTRACTOR:
        {
            detector = ORB::create();
            matcher = DescriptorMatcher::create(DescriptorMatcher::BRUTEFORCE_HAMMING);
            break;
        }
    case BRISK_EXTRACTOR:
        {
            detector = BRISK::create();
            matcher = DescriptorMatcher::create(DescriptorMatcher::BRUTEFORCE_HAMMING);
            break;
        }
    //todo: insert new extractors
    default:
        throw std::runtime_error("Unrecognized feature extractor");
    }

    
    std::vector<KeyPoint> keypoints1, keypoints2;
    Mat descriptors1, descriptors2, c;
    detector->detectAndCompute( img1, noArray(), keypoints1, descriptors1 );
    detector->detectAndCompute( img2, noArray(), keypoints2, descriptors2 );
    
    //std::vector< DMatch > matches;
    //matcher->match( descriptors1, descriptors2, matches );
    ////-- Draw matches
    //Mat img_matches;
    //drawMatches( img1, keypoints1, img2, keypoints2, matches, img_matches );
    ////-- Show detected matches
    //imshow("Matches", img_matches );
    //waitKey();
    int clusters = 5;
    cv::BOWKMeansTrainer bow(clusters);

    std::cout<< "passei auqi" << std::endl;

    cv::Mat descriptors(1, detector->descriptorSize(), detector->descriptorType());
    descriptors.push_back(descriptors1);
    descriptors.push_back(descriptors2);
    bow.add(descriptors);


    std::cout << bow.descriptorsCount() << std::endl;
    
    std::cout<< "passei auqi" << std::endl;
    BOWImgDescriptorExtractor bowDE(detector, matcher);
    std::cout<< "passei auqi" << std::endl;
    std::vector<std::vector<int>> bow_descriptor;

    Mat dictionary = bow.cluster();
    std::cout << dictionary.size() << std::endl;
    bowDE.setVocabulary(dictionary);
    bowDE.compute(img1, keypoints1, bow_descriptor);

    ...

    return 0;
}

When calling bowDE.setVocabulary(dictionary) in line 139, I get the error:

what():  OpenCV(4.7.0-dev) /home/.../opencv/modules/core/src/matrix_wrap.cpp:1863: error: (-213:The function/feature is not implemented)  in function 'setTo'

I run this code like this: ./teste -input1="../img1.webp" -input2="../img2.jpg" -extractor="1"

It can be with “-extractor=0” as well (using SIFT or SURF).

My code main objective is actually only to try to extract SURF or SIFT features from 2 images and create a vocabulary using OpenCV. Someone could help me please?

no, it’s not meant to work that way. you should collect a dictionary of statistically relevant features from a ton of unrelated images, an offline task.

then you match your image features against that dictionary (instead of the other image), in the hope, to retrieve more significant results

no way. not even with correct DescriptorMatchers.
kmeans clustering is using L2 distance, thus you cannot use binary / bitstring features.

far too less, to be useful
(~2000, maybe, and yes. clustering will take decades …)
remember, that this is the final desc size for the similarity comparison

use an empty Mat to push_back() to, else you have an uninitialized 1st row !

are you sure ? and line 139, is in your prog, no ?
i’d rather think, it’s from the next line, bowDE.compute() , where you got the signature totally wrong, look:

(should be something like:

Mat finaldesc;
bowDE.compute(descriptors1, finaldesc);

)

no, it’s not meant to work that way. you should collect a dictionary of statistically relevant features from a ton of unrelated images, an offline task.

then you match your image features against that dictionary (instead of the other image), in the hope, to retrieve more significant results

Yes, I know.

no way. not even with correct DescriptorMatchers.
kmeans clustering is using L2 distance, thus you cannot use binary / bitstring features.

I am testing only with SURF and SIFT at the moment. If I use ORB and BRISK, it throws different errors and I understand doing this is wrong.

are you sure ? and line 139, is in your prog, no ?

Yes, I am sure. 139 is in my code. The problem is inside bowDE.setVocabulary(dictionary)

hmm, cant find any ‘setTo()’ there. and the error is about assigning something wrong as an ‘OutputArray’ …

will try actual code tomorrow!

if you can debug it, try to get a stacktrace (bt) from gdb …

It was from bowDE.compute(img1, keypoints1, bow_descriptor) indeed. I just didn’t notice it somehow… Thank you for your attention.

1 Like