0

我对以下代码有疑问:

#include "iostream"

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/nonfree/nonfree.hpp>
#include <opencv2/nonfree/features2d.hpp>
#include <opencv2/flann/flann.hpp>
#include "opencv2/flann/miniflann.hpp"
#include <opencv2/legacy/legacy.hpp>
#include "opencv2/contrib/contrib.hpp"
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/imgproc/types_c.h"
#include "opencv2/highgui/highgui_c.h"
#include "opencv2/core/version.hpp"
#include "opencv2/core/operations.hpp"
#include "opencv2/core/mat.hpp"
#include "opencv2/core/types_c.h"
#include <limits>


#include <vector>

#include <iostream>
#include <fstream>

using namespace cv;
using namespace std;

static void readTrainFilenames( const string& filename, string& dirName, vector<string>& trainFilenames )
{
    trainFilenames.clear();

    ifstream file( filename.c_str() );
    if ( !file.is_open() )
        return;

    size_t pos = filename.rfind('\\');
    char dlmtr = '\\';
    if (pos == String::npos)
    {
        pos = filename.rfind('/');
        dlmtr = '/';
    }
    dirName = pos == string::npos ? "" : filename.substr(0, pos) + dlmtr;

    while( !file.eof() )
    {
        string str; getline( file, str );
        if( str.empty() ) break;
        trainFilenames.push_back(str);
    }
    file.close();
}

static bool createDetectorDescriptorMatcher( const string& detectorType, const string& descriptorType, const string& matcherType,
                                      Ptr<FeatureDetector>& featureDetector,
                                      Ptr<DescriptorExtractor>& descriptorExtractor,
                                      Ptr<DescriptorMatcher>& descriptorMatcher )
{
    cout << "< Creating feature detector, descriptor extractor and descriptor matcher ..." << endl;
    featureDetector = FeatureDetector::create( detectorType );
    descriptorExtractor = DescriptorExtractor::create( descriptorType );
    descriptorMatcher = DescriptorMatcher::create( matcherType );
    cout << ">" << endl;

    bool isCreated = !( featureDetector.empty() || descriptorExtractor.empty() || descriptorMatcher.empty() );
    if( !isCreated )
        cout << "Can not create feature detector or descriptor extractor or descriptor matcher of given types." << endl << ">" << endl;

    return isCreated;
}

static bool readImages( const string& queryImageName, const string& trainFilename,
                 Mat& queryImage, vector <Mat>& trainImages, vector<string>& trainImageNames )
{
    cout << "< Reading the images..." << endl;
    queryImage = imread( queryImageName);
    if( queryImage.empty() )
    {
        cout << "Query image can not be read." << endl << ">" << endl;
        return false;
    }
    string trainDirName;
    readTrainFilenames( trainFilename, trainDirName, trainImageNames );
    if( trainImageNames.empty() )
    {
        cout << "Train image filenames can not be read." << endl << ">" << endl;
        return false;
    }
    int readImageCount = 0;
    for( size_t i = 0; i < trainImageNames.size(); i++ )
    {
        string filename = trainDirName + trainImageNames[i];
        Mat img = imread( filename );
        if( img.empty() )
            cout << "Train image " << filename << " can not be read." << endl;
        else {
            readImageCount++;
            double min, max;
            minMaxLoc(img, &min, &max);
            if (min!=max) {
                trainImages.push_back( img );
            }
        }
    }
    if( !readImageCount )
    {
        cout << "All train images can not be read." << endl << ">" << endl;
        return false;
    }
    else
        cout << readImageCount << " train images were read." << endl;
    cout << ">" << endl;

    return true;
}

static void detectKeypoints( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
                      const vector<Mat>& trainImages, vector<vector<KeyPoint> >& trainKeypoints,
                      Ptr<FeatureDetector>& featureDetector )
{
    TickMeter tm;
    tm.start();
    cout << endl << "< Extracting keypoints from images..." << endl;
    featureDetector->detect( queryImage, queryKeypoints );
    featureDetector->detect( trainImages, trainKeypoints  );
    cout << ">" << endl;
    tm.stop();

    double exttime = tm.getTimeMilli();
    cout << "Extraction time: " << exttime << endl;
}

static void computeDescriptors( const Mat& queryImage, vector<KeyPoint>& queryKeypoints, Mat& queryDescriptors,
                         const vector<Mat>& trainImages, vector<vector<KeyPoint> >& trainKeypoints, vector<Mat>& trainDescriptors,
                         Ptr<DescriptorExtractor>& descriptorExtractor )
{
    TickMeter tm;
    tm.start();
    cout << "< Computing descriptors for keypoints..." << endl;
    descriptorExtractor->compute( queryImage, queryKeypoints, queryDescriptors );
    descriptorExtractor->compute( trainImages, trainKeypoints, trainDescriptors );

    int totalTrainDesc = 0;
    for( vector<Mat>::const_iterator tdIter = trainDescriptors.begin(); tdIter != trainDescriptors.end(); tdIter++ )
        totalTrainDesc += tdIter->rows;

    cout << "Query descriptors count: " << queryDescriptors.rows << "; Total train descriptors count: " << totalTrainDesc << endl;
    cout << ">" << endl;

    tm.stop();

    double exttime = tm.getTimeMilli();
    cout << "Description time: " << exttime << endl;
}

static void matchDescriptors( const Mat& queryDescriptors, const vector<Mat>& trainDescriptors,
                       vector<DMatch>& matches, Ptr<DescriptorMatcher>& descriptorMatcher )
{
    cout << "< Set train descriptors collection in the matcher and match query descriptors to them..." << endl;
    TickMeter tm;

    tm.start();
    descriptorMatcher->add( trainDescriptors );
    descriptorMatcher->train();
    tm.stop();
    double buildTime = tm.getTimeMilli();

    tm.start();
    descriptorMatcher->match( queryDescriptors, matches );
    tm.stop();
    double matchTime = tm.getTimeMilli();

    CV_Assert( queryDescriptors.rows == (int)matches.size() || matches.empty() );

    cout << "Number of matches: " << matches.size() << endl;
    cout << "Build time: " << buildTime << " ms; Match time: " << matchTime << " ms" << endl;
    cout << ">" << endl;
}


int main(int argc, char** argv)
{
    string detectorType = "SURF";
    string descriptorType = "SURF";
    string matcherType = "FlannBased";
    string fileWithTrainImages = "/home/juan/workspace/keypoint/Debug/matching_to_many_images/train/keyframes.txt";
    string dirToSaveResImages = "/home/juan/workspace/keypoint/Debug/matching_to_many_images/results";
    string queryImageName = "/home/juan/workspace/keypoint/Debug/keyframe0.jpg";

    Ptr<FeatureDetector> featureDetector;
    Ptr<DescriptorExtractor> descriptorExtractor;
    Ptr<DescriptorMatcher> descriptorMatcher;
    createDetectorDescriptorMatcher( detectorType, descriptorType, matcherType, featureDetector, descriptorExtractor, descriptorMatcher );

    Mat queryImage;
    vector<Mat> trainImages;
    vector<string> trainImagesNames;
    if( !readImages( queryImageName, fileWithTrainImages, queryImage, trainImages, trainImagesNames ) )
    {
        cout << "Error!!" << endl;
        return -1;
    }

    vector<KeyPoint> queryKeypoints;
    vector<vector<KeyPoint> > trainKeypoints;
    detectKeypoints( queryImage, queryKeypoints, trainImages, trainKeypoints, featureDetector );

    Mat queryDescriptors;
    vector<Mat> trainDescriptors;
    computeDescriptors( queryImage, queryKeypoints, queryDescriptors,
                        trainImages, trainKeypoints, trainDescriptors,
                        descriptorExtractor );

    vector<DMatch> matches;
    matchDescriptors( queryDescriptors, trainDescriptors, matches, descriptorMatcher );


    return 0;
}

该程序的主要功能是:它读取一个查询图像和一组训练图像。然后,它使用建立的检测器类型(SURF、SIFT、FAST...)检测关键点。之后,它使用已建立的描述符类型(FREAK、SIFT...)提取这些关键点的描述符。最后,根据由变量 matcherType (BruteForce, FlannBased...) 建立的匹配器,给出查询图像和整个训练图像集之间的匹配。我的问题是我试图使用 OpenCV 在其方法中提供的所有检测器、描述符和匹配器类型(变量检测器类型、描述符类型、匹配器类型)。但是,我只得到了少数几个结果。例如,Detector-Descriptor-Matcher "SURF-SURF-FlannBased" 组合对我不起作用,

juan@juan-HP-G62-NoteBook-PC:~/workspace/keypoint/Debug$ ./keypoint < 创建特征检测器、描述符提取器和描述符匹配器 ...

无法创建给定类型的特征检测器或描述符提取器或描述符匹配器。< 读取图像... 读取了 77 个火车图像。

< 从图像中提取关键点... Violación de segmento (`core' generado)

但是,FAST-FREAK-BruteForce 组合对我来说效果很好:

< 创建特征检测器、描述符提取器和描述符匹配器...

< 读取图像... 读取了 77 个火车图像。

< 从图像中提取关键点...

提取时间:374.277 <计算关键点的描述符...查询描述符计数:786;火车描述符总数:154417 描述时间:1489.24 <在匹配器中设置火车描述符集合并将查询描述符匹配到它们...匹配数:786 构建时间:0.024077 ms;匹配时间:14292.6 毫秒

我正在使用 OpenCV 2.4.9,Eclipse 作为 IDE,Linux 作为 SO。谁能帮我?我对使用 FlannBased 匹配器处理大型比较数据库非常感兴趣,因为 BruteForce 匹配器运行良好,但在这种情况下速度非常慢。谢谢!

4

0 回答 0