我正在做一个关于视频图像的人脸识别项目。我提取了这些功能,现在我需要比较一下这个功能。所以我发现FlannBasedMatcher是一个很好的方法,也很快.FlannBasedMatcher已经在opencv中了(我正在使用opencv),但是喜欢在没有任何opencv帮助的情况下自己实现它。请帮助我找到FlannBasedMatcher内部正在发生的事情。任何回复将不胜感激。
答案 0 :(得分:1)
通常使用一些距离度量来比较特征,例如被认为是某些多维空间中的点的特征之间的欧几里德距离;可以使用与矢量缩放无关的两个矢量(即特征矢量)之间的角度;可以使用哼声距离来比较二进制字符串等。最佳方法取决于特征向量的结构和含义。对于面,它可以是通过点积表示的两个向量之间的角度。
现在,flann用于寻找最近邻居,因此它与特征比较没有直接关系,虽然它可以帮助加速找到值得比较的类似特征(flann =最近的快速库)邻居)。因此,您不需要搜索所有向量,尝试选择具有查询向量的最高点积的向量,而是直接将给定的面(向量)与几个最接近的面(向量)进行比较。
最后,解决之前的答案,在某些情况下,可以使用稀疏数组而不是KD树。它们也是openCV的一部分,但可以通过哈希表或树来实现。在稀疏数组中,您可以检查相邻元素的索引,这些索引类似于flann最近邻居。当然,稀疏数组比flann更受限制 - 例如,它们需要在邻域中进行穷举搜索以获得最近邻居列表,但这仍然比全局搜索更快。这是一个例子:
int dims = 3;
int sz[] = {1000, 1000, 1000}; // memory efficient
SparseMat M3d(dims, sz, CV_32F);
Point3i idx_sparse;
Vec3f p;
//set the element of a sparse 3D Mat
M3d.ref<Vec3f>(idx_sparse.x, idx_sparse.y, idx_sparse.z) = p;
// iterate
SparseMatIterator it = M3d.begin();
SparseMatIterator it_end = M3d.end();
for (; it != it_end; ++it) {
// access existing element through iterator
Vec3f vec = it.value<Vec3f>();
// check neighbors if they exist
int* idx = it.node()->index;
idx[0]++; idx[1]--; idx[2]+=2;
if (M3d.find(idx) != M3d.end()) {
Vec3f vec = M3d.ref<Vec3f>(idx);
}
}
答案 1 :(得分:0)
这并不容易。你必须用aproximated最近邻搜索实现kd-tree。 Arya等人在论文“An Optimal Algorithm for Approximate Nearest Neighbor Searching in Fixed Dimensions”中对此进行了描述。
如果您不想从头开始,只想摆脱OpenCV,可以original FLANN implementation。