首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >保存和加载FlannBasedMatcher

保存和加载FlannBasedMatcher
EN

Stack Overflow用户
提问于 2012-02-12 18:16:50
回答 4查看 2.6K关注 0票数 8

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

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

我找到的最接近答案的是this thread in the OpenCV discussion group。这个帖子始于2009年,人们仍然在寻找2011年的答案!

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

代码语言:javascript
复制
FileStorage fs("data.xml",FileStorage::READ);
Mat data;
fs["mtx"] >> data;
flann::Index idx(data,"index.bin");

但是我还不能想出如何实现完整的保存/加载功能。

以防万一,我使用的是OpenCV 2.3.1。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-12-23 07:50:04

我在论坛或邮件列表上没有看到这个问题的答案。我必须深入研究OpenCV源代码(2.4.5),以了解如何做到这一点。它需要子类化来获取FlannBasedMatcher的受保护成员。

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

同样值得注意的是:

在写入要构建的索引之前,必须将描述符传递给readIndex()

  • For (),您必须先对其进行匹配,然后调用()。train()似乎除了构造匹配器之外什么也不做(不给它提供数据,descriptors)
  • This使用SURF描述符。对于完整的解决方案,可能还需要保存/恢复匹配器的IndexParams和/或SearchParams。

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

代码语言:javascript
复制
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);
}
};
票数 6
EN

Stack Overflow用户

发布于 2012-05-15 06:45:50

在OpenCV 2.4.0 (以及2.3.1a)中,有:

代码语言:javascript
复制
// Reads matcher object from a file node
virtual void read( const FileNode& );
// Writes matcher object to a file storage
virtual void write( FileStorage& ) const;

至少是为FlannDescriptorMatcher实现的,但该实现似乎只保存了匹配器的IndexParams。相反,flann::Index_有一个save和load方法(在2.3.1中有save,而load似乎可以使用SavedIndexParams

票数 3
EN

Stack Overflow用户

发布于 2013-05-18 04:40:59

这个问题很久以前就被问过了,所以你可能已经有了答案,但我只是用类似于你所展示的代码实现了一些东西。我没有保存DescriptorMatcher,而是为集合中的每个图像创建了一个descriptors.xml文件,然后将所有这些文件加载到一个向量中,作为train()调用的输入。这将程序的运行时间从2分钟减少到5秒,但将描述符加载到Vector中需要3-4秒。加载整个经过训练的索引会很方便。我仍然在寻找一种方法来做到这一点。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9248012

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档