保存和加载FlannBasedMatcher

Fra*_*per 7 c++ opencv

如果训练图像集很大,训练OpenCV DescriptorMatcher可能是一项耗时的操作.因此,似乎将训练好的DescriptorMatcher数据保存到磁盘以便以后重新加载将是一件非常明显的事情.

不幸的是,似乎没有任何明显的解决方案来满足这种需求.

我最接近找到答案的是OpenCV讨论组中的这个主题.该线程始于2009年,人们仍在寻找2011年的答案!

从该线程获取的代码片段看起来应该从文件重新加载索引:

FileStorage fs("data.xml",FileStorage::READ);
Mat data;
fs["mtx"] >> data;
flann::Index idx(data,"index.bin");
Run Code Online (Sandbox Code Playgroud)

但我无法从中找出如何实现完整的保存/加载功能.

万一它是相关的,我正在使用OpenCV 2.3.1.

wal*_*lly 5

我没有在论坛或邮件列表上看到这个答案.我不得不深入研究OpenCV源代码(2.4.5)以了解如何完成这项工作.它需要子类化来获取FlannBasedMatcher的受保护成员.

关键是将算法设置为FLANN_INDEX_SAVED和文件名indexParams.

还要注意:

  • 描述符必须在readIndex()之前传递给add()

  • 对于要构建的索引,必须先对其进行匹配,然后调用write().除了构造匹配器(不提供描述符)之外,train()似乎没有做任何事情

  • 这适用于SURF描述符.对于完整的解决方案,可能还需要保存/恢复匹配器的IndexParams和/或SearchParams.

接下来要做的是压缩索引(使用gzip),它可以小3-4倍,并且解压缩的成本相对较低.这必须是OpenCV中的补丁.

class SaveableMatcher : public cv::FlannBasedMatcher
{
public:
SaveableMatcher()
{
}

virtual ~SaveableMatcher()
{
}

void printParams()
{
    printf("SaveableMatcher::printParams: \n\t"
        "addedDescCount=%d\n\t"
        "flan distance_t=%d\n\t"
        "flan algorithm_t=%d\n",
        addedDescCount,
        flannIndex->getDistance(),
        flannIndex->getAlgorithm());

    vector<std::string> names;
    vector<int> types;
    vector<std::string> strValues;
    vector<double> numValues;

    indexParams->getAll(names, types, strValues, numValues);

    for (size_t i = 0; i < names.size(); i++)
        printf("\tindex param: %s:\t type=%d val=%s %.2f\n",
                names[i].c_str(), types[i],
                strValues[i].c_str(), numValues[i]);

    names.clear();
    types.clear();
    strValues.clear();
    numValues.clear();
    searchParams->getAll(names, types, strValues, numValues);

    for (size_t i = 0; i < names.size(); i++)
        printf("\tsearch param: %s:\t type=%d val=%s %.2f\n",
                names[i].c_str(), types[i],
                strValues[i].c_str(), numValues[i]);
}

void readIndex(const char* filename)
{
    indexParams->setAlgorithm(cvflann::FLANN_INDEX_SAVED);
    indexParams->setString("filename", filename);

    // construct flannIndex now, so printParams works
    train();

    printParams();
}

void writeIndex(const char* filename)
{
    printParams();
    flannIndex->save(filename);
}
};
Run Code Online (Sandbox Code Playgroud)