你可以看到匹配器代码here
训练一个描述符匹配器(例如,flann 索引)。在所有要匹配的方法中,每次匹配前都会运行方法 train()。
是的,从代码中可以看出,train()在匹配函数中被调用。
void DescriptorMatcher::knnMatch( InputArray queryDescriptors, std::vector<std::vector<DMatch> >& matches, int knn,
InputArrayOfArrays masks, bool compactResult )
{
if( empty() || queryDescriptors.empty() )
return;
CV_Assert( knn > 0 );
checkMasks( masks, queryDescriptors.size().height );
train();
knnMatchImpl( queryDescriptors, matches, knn, masks, compactResult );
}
void DescriptorMatcher::radiusMatch( InputArray queryDescriptors, std::vector<std::vector<DMatch> >& matches, float maxDistance,
InputArrayOfArrays masks, bool compactResult )
{
matches.clear();
if( empty() || queryDescriptors.empty() )
return;
CV_Assert( maxDistance > std::numeric_limits<float>::epsilon() );
checkMasks( masks, queryDescriptors.size().height );
train();
radiusMatchImpl( queryDescriptors, matches, maxDistance, masks, compactResult );
}
当你调用match()时,它实际上会调用knnMatch和knn = 1
void DescriptorMatcher::match( InputArray queryDescriptors, std::vector<DMatch>& matches, InputArrayOfArrays masks )
{
std::vector<std::vector<DMatch> > knnMatches;
knnMatch( queryDescriptors, knnMatches, 1, masks, true /*compactResult*/ );
convertMatches( knnMatches, matches );
}
train() 的基本实现什么都不做:
void DescriptorMatcher::train()
{}
仅FlannBasedMatcher重载train():
void FlannBasedMatcher::train()
{
if( !flannIndex || mergedDescriptors.size() < addedDescCount )
{
// FIXIT: Workaround for 'utrainDescCollection' issue (PR #2142)
if (!utrainDescCollection.empty())
{
CV_Assert(trainDescCollection.size() == 0);
for (size_t i = 0; i < utrainDescCollection.size(); ++i)
trainDescCollection.push_back(utrainDescCollection[i].getMat(ACCESS_READ));
}
mergedDescriptors.set( trainDescCollection );
flannIndex = makePtr<flann::Index>( mergedDescriptors.getDescriptors(), *indexParams );
}
}
FlannBasedMatcher的使用示例可以参考OpenCV doc example
你可以参考这个answer来了解在训练阶段做了什么。简而言之,您正在为匹配器构建索引。可以找到源代码here