2

我正在尝试使用 OpenCV 使用特征包 (BoF) 进行密集 SIFT 特征提取。我们的想法是遵循教程,但只需稍作改动即可使用密集的 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();

}

所以,问题出在第二部分。每当我运行第二部分时,程序就会停止工作“programX.exe 已停止工作”。编译器和控制台不会产生错误。也许我一直在忽略一些东西。欢迎提出建议、评论和帮助。提前致谢。

4

0 回答 0