I tried a lot of image matching code samples in OpenCV 2.4.5 , and I changed that code. I found the error code:
Unhandled exception at 0x585a7090 in testing.exe: 0xC0000005: Access violation reading location 0x00000000.
Its error in featureDetector->detect(queryImage, queryKeypoints) .
I can not find a solution to this 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
FULL SAMPLE CODES CONNECTED 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