如果训练图像集很大,则训练OpenCV DescriptorMatcher可能是一项耗时的操作。因此,将训练好的DescriptorMatcher数据保存到磁盘以便稍后重新加载似乎是一件非常明显的事情。
不幸的是,似乎没有任何明显的解决方案来满足这一需求。
我找到的最接近答案的是this thread in the OpenCV discussion group。这个帖子始于2009年,人们仍然在寻找2011年的答案!
从该线程中提取的代码片段看起来应该从文件中重新加载索引:
FileStorage fs("data.xml",FileStorage::READ);
Mat data;
fs["mtx"] >> data;
flann::Index idx(data,"index.bin");但是我还不能想出如何实现完整的保存/加载功能。
以防万一,我使用的是OpenCV 2.3.1。
发布于 2013-12-23 07:50:04
我在论坛或邮件列表上没有看到这个问题的答案。我必须深入研究OpenCV源代码(2.4.5),以了解如何做到这一点。它需要子类化来获取FlannBasedMatcher的受保护成员。
关键是将indexParams上的算法和文件名设置为FLANN_INDEX_SAVED。
同样值得注意的是:
在写入要构建的索引之前,必须将描述符传递给readIndex()
接下来要做的是压缩索引(使用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);
}
};发布于 2012-05-15 06:45:50
在OpenCV 2.4.0 (以及2.3.1a)中,有:
// 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
发布于 2013-05-18 04:40:59
这个问题很久以前就被问过了,所以你可能已经有了答案,但我只是用类似于你所展示的代码实现了一些东西。我没有保存DescriptorMatcher,而是为集合中的每个图像创建了一个descriptors.xml文件,然后将所有这些文件加载到一个向量中,作为train()调用的输入。这将程序的运行时间从2分钟减少到5秒,但将描述符加载到Vector中需要3-4秒。加载整个经过训练的索引会很方便。我仍然在寻找一种方法来做到这一点。
https://stackoverflow.com/questions/9248012
复制相似问题