我在论坛和邮件列表中没有看到这个问题的答案。我不得不深入研究OpenCV源代码(2.4.5),才知道如何完成此操作。需要通过子类化来获取FlannBasedMatcher的protected成员。
关键是将算法设置为
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);
train();
printParams();
}
void writeIndex(const char* filename)
{
printParams();
flannIndex->save(filename);
}
};