我正在尝试使用OpenCV使用功能包(BoF)进行密集的SIFT特征提取。我们的想法是遵循this教程,但只需稍加改动即可使用密集的SIFT功能。
如您所知,在BoF范例的第一部分中,我们创建了可视字典。所以带有一些修改的代码是这样的:
#include<iostream>
#include<vector>
#include<dirent.h>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/nonfree/features2d.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/nonfree/nonfree.hpp>
// This is a dense sampling of SIFT descriptors.
using namespace std;
using namespace cv;
void dense_SIFT_BoW(Mat img_raw, Mat &featuresUnclustered);
void SIFT_matcher(Mat img_raw, Mat &dictionary, Mat &bowTry, Ptr<DescriptorMatcher> &matcher);
#define DICTIONARY_BUILD 0
int main()
{
#if DICTIONARY_BUILD == 1
initModule_nonfree();
// Store detected image key points.
Mat featuresUnclustered;
DIR *pDir = nullptr;
string imgDir("D:/WillowActions Backup/Willow 300_200/sample/");// Directory of your images. (Change this according to where you images are)
string imgPath;
pDir = opendir(imgDir.c_str());
string dirName;
Mat img_raw; // Our loaded image.
struct dirent *pent = nullptr; // dirent structure for directory manipulation.
if(pDir == nullptr)
{
cout << "Directory pointer could not be initialized correctly ! " << endl; // Some checking.
return 1;
}
int count = 0;
cout << "Please WAIT..." << endl;
while((pent = readdir(pDir)) != nullptr)
{
if(pent == nullptr)
{
cout << " Dirent struct could not be initialized correctly !" << endl;
return 1;
}
if(!strcmp(pent->d_name,".")||!strcmp(pent->d_name,".."))
{
}
else
{
// LOOP trough the directory to read image one by one and extract their Dense SIFT
dirName = pent->d_name;
imgPath = imgDir+dirName; // Overall image path... feed this to imread();
img_raw = imread(imgPath,1);// read the image to extract denseSIFT features
dense_SIFT_BoW(img_raw, featuresUnclustered);
count++;
}
}
cout << "Number of files in folder: " << count << endl;
cout << featuresUnclustered.size() << endl;
//Construct BOW k-means trainer
// the number of bags
int dictionarySize = 5;
//define term criteria
TermCriteria tc(CV_TERMCRIT_ITER, 100, 0.001);
// retry number
int retries = 1;
//necessary flags
int flags = KMEANS_PP_CENTERS;
//Create the BOW trainer
BOWKMeansTrainer bowTrainer(dictionarySize, tc, retries, flags);
//cluster the feature vectors
Mat dictionary = bowTrainer.cluster(featuresUnclustered);
//store the vocabulary
FileStorage fs("D:/WillowActions Backup/Willow 300_200/Dense.xml", FileStorage::WRITE);
fs << "Vocabulary" << dictionary;
fs.release();
函数dense_SIFT_BoW(img_raw,featuresUnclustered)定义为:
void dense_SIFT_BoW(Mat img_raw,Mat &featuresUnclustered)
{
Mat descriptors; // Store our dense SIFT descriptors.
vector<KeyPoint> keypoints;
DenseFeatureDetector detector(12.f, 1, 0.1f, 10);
detector.detect(img_raw,keypoints);
Ptr<DescriptorExtractor> descriptorExtractor = DescriptorExtractor::create("SIFT");
descriptorExtractor->compute(img_raw,keypoints,descriptors);
descriptors.setTo(0, descriptors < 0);
descriptors = descriptors.reshape(0,1);
featuresUnclustered.push_back(descriptors);
}
它本质上是通过每个图像的文件夹循环,为所有图像提取密集的SIFT特征并进行K-means聚类。这构建了可视字典。
这部分代码对我来说很好。即在包含256个图像文件的文件夹中,我得到一个大小为256 x 76800的字典(逐列:集群中心)。创建字典后。
现在,创建了词典。遵循BoF范例,我们希望再次提取密集的SIFT并与刚刚创建的词典进行匹配。为此,我使用最近的邻居。它本质上也是循环图像的文件夹。这就是我所拥有的:
#else
Mat dictionary;
FileStorage fs("D:/WillowActions Backup/Willow 300_200/Dic_Dense.xml", FileStorage::READ);
fs["Vocabulary"] >> dictionary;
fs.release();
//Create a nearest neighbor matcher
Ptr<DescriptorMatcher> matcher(new FlannBasedMatcher);
//Ptr<DescriptorExtractor> descriptorExtractor = DescriptorExtractor::create("SIFT");
cout << dictionary.size() << endl;
DIR *pDir = nullptr;
string imgDir("D:/WillowActions Backup/Willow 300_200/sample/");// Directory of your images. (Change this according to where you images are)
string imgPath;
pDir = opendir(imgDir.c_str());
string dirName;
Mat img_raw; // Our loaded image.
Mat bowTry;
struct dirent *pent = nullptr; // dirent structure for directory manipulation.
if(pDir == nullptr)
{
cout << "Directory pointer could not be initialized correctly ! " << endl; // Some checking.
return 1;
}
int count = 0;
cout << "Please WAIT..." << endl;
while((pent = readdir(pDir)) != nullptr)
{
if(pent == nullptr)
{
cout << " Dirent struct could not be initialized correctly !" << endl;
return 1;
}
if(!strcmp(pent->d_name,".")||!strcmp(pent->d_name,".."))
{
}
else
{
// LOOP trough the directory to read image one by one and extract dense SIFT
dirName = pent->d_name;
imgPath = imgDir+dirName; // Overall image path... feed this to imread();
img_raw = imread(imgPath,1);// read the image to extract HOG features
SIFT_matcher(img_raw, dictionary, bowTry, matcher);
cout << count << endl;
count++;
}
}
cout << "no of images: " << count << endl;
//open the file to write the resultant descriptor
FileStorage fs1("D:/WillowActions Backup/Willow 300_200/Features_train.xml", FileStorage::WRITE);
//write the new BOF descriptor to the file
fs1 << "Vocabulary" << bowTry;
fs1.release();
#endif
waitKey(0);
return 0;
}
函数SIFT_matcher(img_raw,dictionary,bowTry,matcher)是这样的:
void SIFT_matcher(Mat img_raw, Mat &dictionary, Mat &bowTry, Ptr<DescriptorMatcher> &matcher)
{
Mat descriptors;
vector<KeyPoint> keypoints;
DenseFeatureDetector detector(12.f,1,0.1f,10);
detector.detect(img_raw,keypoints);
Ptr<DescriptorExtractor> descriptorExtractor = DescriptorExtractor::create("SIFT");
//create BOF descriptor extractor
BOWImgDescriptorExtractor bowDE(descriptorExtractor, matcher);
bowDE.setVocabulary(dictionary);
//To store BOF representation of the image
Mat bowDescriptor;
//extract BOF descriptor from given image
bowDE.compute(img_raw,keypoints,bowDescriptor);
bowTry.push_back(bowDescriptor);
bowDescriptor.release();
}
所以,问题在于第二部分。每当我运行第二部分时程序停止工作&#34; programX.exe已停止工作&#34;。编译器和控制台不会生成错误。也许我一直在忽视一些事情。建议,评论和帮助非常受欢迎。提前谢谢。