Adam
Adam

Reputation: 1744

OpenCV SURF class Error

I find that OpenCV's new class SURF does not act the same as SurfFeatureDetector. What's wrong with it?

Some example with two pictures:

..................................img_1..................................................................... img_2...................................

img_1 img_2

use it like ./a.out ./img_1.png ./img_2.png

// STL
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
// C-Standard
#include <cstdio>
#include <ctime>
#include <cstdlib>
// OpenCV
#include <opencv2/opencv.hpp>
#include <opencv2/legacy/legacy.hpp>
#include <opencv2/nonfree/nonfree.hpp>

void print(const std::string & filename, const std::vector<std::vector<cv::DMatch>> & vec) {
    FILE *file = fopen(filename.c_str(), "w");
    fprintf(file, "{\n");
    for(auto & i : vec)
        fprintf(file, "    { {%d,%d,%f}, {,%d,%d,%f} },\n",
                i[0].queryIdx, i[0].trainIdx, i[0].distance,
                i[1].queryIdx, i[1].trainIdx, i[1].distance);
    fprintf(file, "}\n");
    fclose(file);
}

void test1(const std::string & imgf_1, const std::string & imgf_2) {
    cv::Mat img_1;
    cv::Mat img_2;
    std::vector<cv::KeyPoint> keypoints_1, keypoints_2;
    cv::Mat descriptors_1, descriptors_2;
    std::vector<std::vector<cv::DMatch>> matches;

    img_1 = cv::imread(imgf_1);
    img_2 = cv::imread(imgf_2);
    int minhessin = 400;
    cv::SurfFeatureDetector detector(minhessin);
    cv::SurfDescriptorExtractor extractor;
    cv::BFMatcher bfMatcher(cv::NORM_L2);

    keypoints_1.clear(); keypoints_2.clear();
    detector.detect(img_1, keypoints_1);
    extractor.compute(img_1, keypoints_1, descriptors_1);
    detector.detect(img_2, keypoints_2);
    extractor.compute(img_2, keypoints_2, descriptors_2);
    matches.clear();
    bfMatcher.knnMatch(descriptors_1, descriptors_2, matches, 2);

    print("main_bak.log", matches);
}

void test2(const std::string & imgf_1, const std::string & imgf_2) {
    cv::Mat img_1;
    cv::Mat img_2;
    std::vector<cv::KeyPoint> keypoints_1, keypoints_2;
    cv::Mat descriptors_1, descriptors_2;
    std::vector<std::vector<cv::DMatch>> matches;

    img_1 = cv::imread(imgf_1);
    img_2 = cv::imread(imgf_2);
    const double hessianThreshold = 400;
    cv::SURF detector2(hessianThreshold);
    cv::BFMatcher bfMatcher(cv::NORM_L2);

    keypoints_1.clear(); keypoints_2.clear();
    detector2(img_1, cv::Mat(), keypoints_1, descriptors_1);
    detector2(img_2, cv::Mat(), keypoints_2, descriptors_2);
    matches.clear();
    bfMatcher.knnMatch(descriptors_1, descriptors_2, matches, 2);

    print("main.log", matches);
}

int main(int argc, char * argv[])
{
    if(argc < 3) {
        std::cout << "usage: " << argv[0] << " img_1 img_2" << std::endl;
        return 1;
    }
    test1(argv[1], argv[2]);
    test2(argv[1], argv[2]);

    return 0;
}

The log's heading 5 lines are shown here:

main_bak.log:

{
    { {0,0,0.000787}, {,0,2,0.126846} },
    { {1,1,0.001695}, {,1,167,0.353709} },
    { {2,2,0.000860}, {,2,0,0.127105} },
    { {3,3,0.002939}, {,3,5,0.333215} },
    { {4,4,0.001360}, {,4,115,0.294008} },

main.log:

{
    { {0,0,0.000900}, {,0,2,0.143810} },
    { {1,1,0.024048}, {,1,107,0.621702} },
    { {2,2,0.003646}, {,2,0,0.144049} },
    { {3,3,0.032238}, {,3,5,0.604136} },
    { {4,4,0.001449}, {,4,87,0.591502} },

Upvotes: 2

Views: 261

Answers (1)

sgarizvi
sgarizvi

Reputation: 16796

The classes cv::SurfFeatureDetector and cv::SurfDescriptorExtractor are aliases of the class cv::SURF. The difference in results is due to the following reason:

In the function test1, detector and extractor objects are being initialized with different parameters. detector is using minHessian value of 400 while extractor is using the opencv implementation defined default value.

In function test2, keypoint detection and descriptor computation are done using a single cv::SURF object with hessianThreshold value of 400.

To reproduce the results of test2 in test1, initialize both objects with same parameters like this:

int minhessin = 400;
cv::SurfFeatureDetector detector(minhessin);
cv::SurfDescriptorExtractor extractor(minHessian);

Upvotes: 2

Related Questions