Access violation reading in FeatureDetector OpenCV

2020-07-18 08:59发布

问题:

I tried the sample codes about matching to many images in OpenCV 2.4.5 and I modified that code. I found the error code:

Unhandled exception at 0x585a7090 in testing.exe:
0xC0000005: Access violation reading location 0x00000000.

Its fault is at featureDetector->detect(queryImage, queryKeypoints).

I can't find the solution from that problem. Please help me.

#include <opencv2\highgui\highgui.hpp>
#include <opencv2\features2d\features2d.hpp>
#include <opencv2\contrib\contrib.hpp>
#include <iostream>
#include <fstream>
#include <conio.h>
#include <string>

using namespace std;
using namespace cv;

static void readTrainFilenames(const string& filename, string& dirName, vector<string>& trainFilenames);
static bool readImages(const string& queryImageName,  Mat& queryImage);
static bool readTrainImages(const string& trainFilename, vector<Mat>& trainImages, vector<string>& trainImageNames);
static void detectKeypoints(const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
    const vector<Mat>& trainImages, vector<vector<KeyPoint>>& trainKeypoints, Ptr<FeatureDetector>& featureDetector);


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

    ifstream file(filename.c_str());

    if(!file.is_open())
    {
        cout << "File can't open" << endl;
        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);
    } // end while

    file.close();
} // end void readTrainFilenames


static bool readImages(const string& queryImageName,  Mat& queryImage)
{
    cout << "reading  images..." << endl;
    queryImage = imread(queryImageName, CV_LOAD_IMAGE_GRAYSCALE);
    if(queryImage.empty())
    {
        cout << "query image can not be read. \n";
        return false;
    } // end if


    return true;
}

static bool readTrainImages(const string& trainFilename, vector<Mat>& trainImages, vector<string>& trainImageNames)
{
    cout << "reading training images..." << endl;
    string trainDirName = "D:/matching_to_many_images/";

    readTrainFilenames(trainFilename, trainDirName, trainImageNames);
    if(trainImageNames.empty())
    {
        cout << "Train image filenames can not be read." << endl;
        return false;
    } // end if

    int readImageCount = 0;
    for(size_t i = 0; i < trainImageNames.size(); i++)
    {
        string filename = trainDirName + trainImageNames[i];
        Mat img = imread(filename, CV_LOAD_IMAGE_GRAYSCALE);
        if(img.empty())
        {
            cout << "Train image " << filename << " can not be read." << endl;
        }
        else
        {
            readImageCount++;
        }// end if

        trainImages.push_back(img);
    } // end for

    if(!readImageCount)
    {
        cout << "All train images can not be read." << 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){
    cout << endl << "Extracting keypoints from images..." << endl;

    try{
        featureDetector->detect(queryImage, queryKeypoints);
    }
    catch(Ptr<FeatureDetector> a)
    {
        cout << "hmm" << endl;
    }

    cout << endl;
} // end void detectKeypoints

int main()
{
    const string defaultDetectorType = "SURF";
    const string defaultDescriptorType = "SURF";
    const string defaultMatcherType = "FlannBased";
    const string defaultQueryImageName = "D:/matching_to_many_images/query.png";
    const string defaultFileWithTrainImages = "D:/matching_to_many_images/train/trainImages.txt";
    const string defaultDirToSaveResImages = "D:/matching_to_many_images/results";

    Ptr<FeatureDetector> featureDetector;
    Ptr<DescriptorExtractor> descriptorExtractor;
    Ptr<DescriptorMatcher> descriptorMatcher;

    Mat queryImages;
    vector<Mat> trainImages;
    vector<string> trainImagesNames;

    vector<KeyPoint> queryKeypoints;
    vector<vector<KeyPoint>> trainKeypoints;

    if(!readImages(defaultQueryImageName, queryImages))
    {
        _getch();
        return -1;
    } // end if

    if(!readTrainImages(defaultFileWithTrainImages, trainImages, trainImagesNames))
    {
        _getch();
        return -1;
    }

    detectKeypoints(queryImages, queryKeypoints, trainImages, trainKeypoints, featureDetector);

    cout << "\n done \n";
    _getch();
    return 0;
} // end main method

Update:

#include <opencv2\highgui\highgui.hpp>
#include <opencv2\features2d\features2d.hpp>
#include <opencv2\contrib\contrib.hpp>
#include <iostream>
#include <fstream>
#include <conio.h>
#include <string>

using namespace std;
using namespace cv;

static void readTrainFilenames(const string& filename, string& dirName, vector<string>& trainFilenames);
static bool readImages(const string& queryImageName,  Mat& queryImage);
static bool readTrainImages(const string& trainFilename, vector<Mat>& trainImages, vector<string>& trainImageNames);
static void detectKeypoints(const Mat& queryImage, vector<KeyPoint>& queryKeypoints, Ptr<FeatureDetector>& featureDetector);


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

    ifstream file(filename.c_str());

    if(!file.is_open())
    {
        cout << "File can't open" << endl;
        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);
    } // end while

    file.close();
} // end void readTrainFilenames


static bool readImages(const string& queryImageName,  Mat& queryImage)
{
    cout << "reading  images..." << endl;
    queryImage = imread(queryImageName, CV_LOAD_IMAGE_GRAYSCALE);
    if(queryImage.empty())
    {
        cout << "query image can not be read. \n";
        return false;
    } // end if


    return true;
}

static bool readTrainImages(const string& trainFilename, vector<Mat>& trainImages, vector<string>& trainImageNames)
{
    cout << "reading training images..." << endl;
    string trainDirName = "D:/matching_to_many_images/";

    readTrainFilenames(trainFilename, trainDirName, trainImageNames);
    if(trainImageNames.empty())
    {
        cout << "Train image filenames can not be read." << endl;
        return false;
    } // end if

    int readImageCount = 0;
    for(size_t i = 0; i < trainImageNames.size(); i++)
    {
        string filename = trainDirName + trainImageNames[i];
        Mat img = imread(filename, CV_LOAD_IMAGE_GRAYSCALE);
        if(img.empty())
        {
            cout << "Train image " << filename << " can not be read." << endl;
        }
        else
        {
            readImageCount++;
        }// end if

        trainImages.push_back(img);
    } // end for

    if(!readImageCount)
    {
        cout << "All train images can not be read." << endl;
        return false;
    }
    else
    {
        cout << readImageCount << " train images were read." << endl;
    }

    cout << endl;

    return true;
}

static void detectKeypoints(const Mat& queryImage, vector<KeyPoint>& queryKeypoints, Ptr<FeatureDetector>& featureDetector){
    cout << endl << "Extracting keypoints from images..." << endl;

    featureDetector->detect(queryImage, queryKeypoints);


    cout << endl;
} // end void detectKeypoints

int main()
{
    const string defaultDetectorType = "SURF";
    const string defaultDescriptorType = "SURF";
    const string defaultMatcherType = "FlannBased";
    const string defaultQueryImageName = "D:/matching_to_many_images/query.png";
    const string defaultFileWithTrainImages = "D:/matching_to_many_images/train/trainImages.txt";
    const string defaultDirToSaveResImages = "D:/matching_to_many_images/results";

    Ptr<FeatureDetector> featureDetector;
    Ptr<DescriptorExtractor> descriptorExtractor;
    Ptr<DescriptorMatcher> descriptorMatcher;

    Mat queryImages;
    vector<Mat> trainImages;
    vector<string> trainImagesNames;

    vector<KeyPoint> queryKeypoints;
    vector<vector<KeyPoint>> trainKeypoints;

    if(!readImages(defaultQueryImageName, queryImages))
    {
        _getch();
        return -1;
    } // end if

    if(!readTrainImages(defaultFileWithTrainImages, trainImages, trainImagesNames))
    {
        _getch();
        return -1;
    }

    detectKeypoints(queryImages, queryKeypoints, featureDetector);

    cout << "\n done \n";
    _getch();
    return 0;
} // end main method

SOLVED PROBLEMS:

#include <opencv2\highgui\highgui.hpp>
#include <opencv2\features2d\features2d.hpp>
#include <opencv2\contrib\contrib.hpp>
#include <opencv2\nonfree\nonfree.hpp>
#include <iostream>
#include <fstream>
#include <conio.h>
#include <string>

using namespace std;
using namespace cv;

const string defaultDetectorType = "SURF";
const string defaultDescriptorType = "SURF";
const string defaultMatcherType = "FlannBased";
const string defaultQueryImageName = "D:/matching_to_many_images/query.png";
const string defaultFileWithTrainImages = "D:/matching_to_many_images/train/trainImages.txt";
const string defaultDirToSaveResImages = "D:/matching_to_many_images/results";

static void readTrainFilenames(const string& filename, string& dirName, vector<string>& trainFilenames);
static bool readImages(const string& queryImageName,  Mat& queryImage);
static bool readTrainImages(const string& trainFilename, vector<Mat>& trainImages, vector<string>& trainImageNames);
static void detectKeypoints(const Mat& queryImage, vector<KeyPoint>& queryKeypoints, Ptr<FeatureDetector>& featureDetector);
static bool createDetectorDescriptorMatcher(const string& detectorType, 
                                        const string& descriptorType, 
                                        const string& matcherType,
                                        Ptr<FeatureDetector>& featureDetector,
                                        Ptr<DescriptorExtractor>& descriptorExtractor,
                                        Ptr<DescriptorMatcher>& descriptorMatcher);

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

    ifstream file(filename.c_str());

    if(!file.is_open())
    {
        cout << "File can't open" << endl;
        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);
    } // end while

    file.close();
} // end void readTrainFilenames


static bool readImages(const string& queryImageName,  Mat& queryImage)
{
    cout << "reading  images..." << endl;
    queryImage = imread(queryImageName, CV_LOAD_IMAGE_GRAYSCALE);
    if(queryImage.empty())
    {
        cout << "query image can not be read. \n";
        return false;
    } // end if


    return true;
}

static bool readTrainImages(const string& trainFilename, vector<Mat>& trainImages, vector<string>& trainImageNames)
{
    cout << "reading training images..." << endl;
    string trainDirName = "D:/matching_to_many_images/";

    readTrainFilenames(trainFilename, trainDirName, trainImageNames);
    if(trainImageNames.empty())
    {
        cout << "Train image filenames can not be read." << endl;
        return false;
    } // end if

    int readImageCount = 0;
    for(size_t i = 0; i < trainImageNames.size(); i++)
    {
        string filename = trainDirName + trainImageNames[i];
        Mat img = imread(filename, CV_LOAD_IMAGE_GRAYSCALE);
        if(img.empty())
        {
            cout << "Train image " << filename << " can not be read." << endl;
        }
        else
        {
            readImageCount++;
        }// end if

        trainImages.push_back(img);
    } // end for

    if(!readImageCount)
    {
        cout << "All train images can not be read." << endl;
        return false;
    }
    else
    {
        cout << readImageCount << " train images were read." << endl;
    }

    cout << endl;

    return true;
}

static void detectKeypoints(const Mat& queryImage, vector<KeyPoint>& queryKeypoints, Ptr<FeatureDetector>& featureDetector){
    cout << endl << "Extracting keypoints from images..." << endl;

    if(queryImage.empty())
    {
        cout << "Query Image EMPTY" << endl;
    } 
    else{
        cout << "Query Image FILLED" << endl;
    }

    featureDetector->detect(queryImage, queryKeypoints);


    cout << endl;
} // end void detectKeypoints

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;

    if(featureDetector.empty())
    {
        cout << "feature detector empty" << endl;
    }

    if(descriptorExtractor.empty())
    {
        cout << "descriptor extractor empty" << endl;
    }

    if(descriptorMatcher.empty())
    {
        cout << "descriptor matcher empty" << 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;
    } // end if

    return isCreated;
} // end void createDetectorDescriptorMatcher

int main()
{
    initModule_nonfree();
    string detectorType = defaultDetectorType;
    string descriptorType = defaultDetectorType;
    string matcherType = defaultMatcherType;
    string queryImageName = defaultQueryImageName;
    string fileWithTrainImages = defaultFileWithTrainImages;
    string dirToSaveResImages = defaultDirToSaveResImages;

    Ptr<FeatureDetector> featureDetector = FeatureDetector::create("SURF");
    Ptr<DescriptorExtractor> descriptorExtractor = DescriptorExtractor::create("SURF");
    Ptr<DescriptorMatcher> descriptorMatcher;

    if(!createDetectorDescriptorMatcher(detectorType, descriptorType, matcherType, featureDetector, descriptorExtractor, descriptorMatcher))
    {

        _getch();
        return -1;
    }


    Mat queryImages;
    vector<Mat> trainImages;
    vector<string> trainImagesNames;

    vector<KeyPoint> queryKeypoints;
    vector<vector<KeyPoint>> trainKeypoints;

    if(!readImages(defaultQueryImageName, queryImages))
    {
        _getch();
        return -1;
    } // end if

    if(!readTrainImages(defaultFileWithTrainImages, trainImages, trainImagesNames))
    {
        _getch();
        return -1;
    }

    detectKeypoints(queryImages, queryKeypoints, featureDetector);

    cout << "\n done \n";
    _getch();
    return 0;
} // end main method

COMPLETE SAMPLE CODES MATCHING TO MANY IMAGES:

#include <opencv2\highgui\highgui.hpp>
#include <opencv2\features2d\features2d.hpp>
#include <opencv2\contrib\contrib.hpp>
#include <opencv2\nonfree\nonfree.hpp>
#include <iostream>
#include <fstream>
#include <conio.h>
#include <string>

using namespace std;
using namespace cv;

const string defaultDetectorType = "SURF";
const string defaultDescriptorType = "SURF";
const string defaultMatcherType = "FlannBased";
const string defaultQueryImageName = "D:/matching_to_many_images/query.png";
const string defaultFileWithTrainImages = "D:/matching_to_many_images/train/trainImages.txt";
const string defaultDirToSaveResImages = "D:/matching_to_many_images/results";

static void readTrainFilenames(const string& filename, string& dirName, vector<string>& trainFilenames);
static bool readImages(const string& queryImageName,  Mat& queryImage);
static bool readTrainImages(const string& trainFilename, vector<Mat>& trainImages, vector<string>& trainImageNames);
static void detectKeypoints(const Mat& queryImage, vector<KeyPoint>& queryKeypoints, const vector<Mat>& trainImages, vector<vector<KeyPoint>>& trainKeypoints, Ptr<FeatureDetector>& featureDetector);
static bool createDetectorDescriptorMatcher(const string& detectorType, 
                                        const string& descriptorType, 
                                        const string& matcherType,
                                        Ptr<FeatureDetector>& featureDetector,
                                        Ptr<DescriptorExtractor>& descriptorExtractor,
                                        Ptr<DescriptorMatcher>& descriptorMatcher);
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);
static void matchDescriptors(const Mat& queryDescriptors, const vector<Mat>& trainDescriptors, vector<DMatch>& matches, Ptr<DescriptorMatcher>& descriptorMatcher);
static void maskMatchesByTrainImgIdx(const vector<DMatch>& matches, int trainImgIdx, vector<char>& mask);

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

    ifstream file(filename.c_str());

    if(!file.is_open())
    {
        cout << "File can't open" << endl;
        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);
    } // end while

    file.close();
} // end void readTrainFilenames


static bool readImages(const string& queryImageName,  Mat& queryImage)
{
    cout << "reading  images..." << endl;
    queryImage = imread(queryImageName, CV_LOAD_IMAGE_GRAYSCALE);
    if(queryImage.empty())
    {
        cout << "query image can not be read. \n";
        return false;
    } // end if


    return true;
}

static bool readTrainImages(const string& trainFilename, vector<Mat>& trainImages, vector<string>& trainImageNames)
{
    cout << "reading training images..." << endl;
    string trainDirName = "D:/matching_to_many_images/";

    readTrainFilenames(trainFilename, trainDirName, trainImageNames);
    if(trainImageNames.empty())
    {
        cout << "Train image filenames can not be read." << endl;
        return false;
    } // end if

    int readImageCount = 0;
    for(size_t i = 0; i < trainImageNames.size(); i++)
    {
        string filename = trainDirName + trainImageNames[i];
        Mat img = imread(filename, CV_LOAD_IMAGE_GRAYSCALE);
        if(img.empty())
        {
            cout << "Train image " << filename << " can not be read." << endl;
        }
        else
        {
            readImageCount++;
        }// end if

        trainImages.push_back(img);
    } // end for

    if(!readImageCount)
    {
        cout << "All train images can not be read." << 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){
    cout << endl << "Extracting keypoints from images..." << endl;

    if(queryImage.empty())
    {
        cout << "Query Image EMPTY" << endl;
    } 
    else{
        cout << "Query Image FILLED" << endl;
    }

    featureDetector->detect(queryImage, queryKeypoints);
    featureDetector->detect(trainImages, trainKeypoints);

    cout << endl;
} // end void detectKeypoints

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;

    if(featureDetector.empty())
    {
        cout << "feature detector empty" << endl;
    }

    if(descriptorExtractor.empty())
    {
        cout << "descriptor extractor empty" << endl;
    }

    if(descriptorMatcher.empty())
    {
        cout << "descriptor matcher empty" << 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;
    } // end if

    return isCreated;
} // end void createDetectorDescriptorMatcher

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)
{
    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;
} // end void computeDescriptors

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;
} // end void matchDescriptors

static void saveResultImages(const Mat& queryImage, const vector<KeyPoint>& queryKeypoints,
    const vector<Mat>& trainImages, const vector<vector<KeyPoint>> &trainKeypoints, const vector<DMatch>& matches, 
    const vector<string>& trainImageNames, const string& resultDir)
{
    cout << "Save results..." << endl;
    Mat drawImg;
    vector<char> mask;
    for(size_t i = 0; i < trainImages.size(); i++)
    {
        if(!trainImages[i].empty())
        {
            maskMatchesByTrainImgIdx(matches, (int)i, mask);
            drawMatches(queryImage, queryKeypoints, trainImages[i], trainKeypoints[i], matches, drawImg, Scalar(255, 0, 0), Scalar(0, 255, 255), mask);
            string filename = resultDir + "/res_" + trainImageNames[i];
            if(!imwrite(filename, drawImg))
            {
                cout << "Image " << filename << " can not be saved (may be because directory " << resultDir << " does not exist" << endl;
            } // end if
        } // end if
    }
} // end void saveResultImages

static void maskMatchesByTrainImgIdx(const vector<DMatch>& matches, int trainImgIdx, vector<char>& mask)
{
    mask.resize(matches.size());
    fill(mask.begin(), mask.end(), 0);
    for(size_t i = 0; i < matches.size(); i++)
    {
        if(matches[i].imgIdx == trainImgIdx)
        {
            mask[i] = 1;
        }
    }
} // end void maskMatchesByTrainImgIdx

int main()
{
    initModule_nonfree();
    string detectorType = defaultDetectorType;
    string descriptorType = defaultDetectorType;
    string matcherType = defaultMatcherType;
    string queryImageName = defaultQueryImageName;
    string fileWithTrainImages = defaultFileWithTrainImages;
    string dirToSaveResImages = defaultDirToSaveResImages;

    Ptr<FeatureDetector> featureDetector = FeatureDetector::create("SURF");
    Ptr<DescriptorExtractor> descriptorExtractor = DescriptorExtractor::create("SURF");
    Ptr<DescriptorMatcher> descriptorMatcher;

    if(!createDetectorDescriptorMatcher(detectorType, descriptorType, matcherType, featureDetector, descriptorExtractor, descriptorMatcher))
    {

        _getch();
        return -1;
    }

    Mat queryImages;
    vector<Mat> trainImages;
    vector<string> trainImagesNames;

    vector<KeyPoint> queryKeypoints;
    vector<vector<KeyPoint>> trainKeypoints;

    if(!readImages(defaultQueryImageName, queryImages))
    {
        _getch();
        return -1;
    } // end if

    if(!readTrainImages(defaultFileWithTrainImages, trainImages, trainImagesNames))
    {
        _getch();
        return -1;
    }

    detectKeypoints(queryImages, queryKeypoints, trainImages, trainKeypoints, featureDetector);

    Mat queryDescriptors;
    vector<Mat> trainDescriptors;

    computeDescriptors(queryImages, queryKeypoints, queryDescriptors, trainImages, trainKeypoints, trainDescriptors, descriptorExtractor);

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

    saveResultImages(queryImages, queryKeypoints, trainImages, trainKeypoints, matches, trainImagesNames, dirToSaveResImages);

    cout << "\n done \n";
    _getch();
    return 0;
} // end main method

回答1:

The documentation for class FeatureDetector says, that it is an abstract base class, which means that you should not be able to create an instance of that class. It is OpenCV's fault, that the compiler is not complaining!

Try adding:

Ptr<FeatureDetector> featureDetector = FeatureDetector::create(defaultDetectorType);

Update:

My next suggestion would be to reduce complexity. Simplify the main program until you have a minimal working version:

int main()
{
    cv::initModule_nonfree(); // to load SURF/SIFT etc.
    std::vector<cv::KeyPoint> queryKeypoints;
    cv::Mat queryImage = cv::imread(FILENAME, CV_LOAD_IMAGE_GRAYSCALE);
    cv::Ptr<FeatureDetector> featureDetector = cv::FeatureDetector::create("SURF");
    featureDetector->detect(queryImage, queryKeypoints);
}

If the above version works, start adding more functionality (slowly), until you arrive at your current version. The moment the error comes back, you know that the last added part is the culprit and you can focus on that.

If the above version does not work, you have at least created a SSCCE, which you can try to fix (with the help of others).

BTW: The error message is telling you, that your program is trying to read memory location 0x00000000 which is an indicator, that you are using an uninitialized data structure, but I am not sure where the problem is in your program.



回答2:

It seems that you did not initialize Ptr<FeatureDetector> featureDetector; anywhere, it is an abstract class