我一直在Android智能手机上制作应用程序,可以比较2张图像(一张在SD卡上,一张在相机上)。在那里,我在有限数量的关键点上使用FREAK描述符(我根据响应过滤掉了500个最佳关键点)。当我尝试将它与BRUTEFORCE_SL2匹配时,它返回0匹配。
这是因为FREAK和Bruteforce不能很好地协同工作吗?或者我在代码中做错了什么?
与
匹配MatOfDMatch matches = new MatOfDMatch();
matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_SL2);
matcher.match(descriptors,descriptors1,matches);
MatOfDMatch goedematches = new MatOfDMatch();
double max_dist = 0;
double min_dist = 100;
//if (descriptors.cols() == descriptors1.cols())
//{
for( int i = 0; i < descriptors.rows(); i++ )
{ double dist = matches.toArray()[i].distance;
if( dist < min_dist ) min_dist = dist;
if( dist > max_dist ) max_dist = dist;
}
// should only draw good matches
for( int i = 0; i < descriptors.rows(); i++ )
{ MatOfDMatch temp = new MatOfDMatch();
if( matches.toArray()[i].distance < 3*min_dist )
{ temp.fromArray(matches.toArray()[i]);
goedematches.push_back(temp);
}
// }
}
Log.d("LOG!", "Number of good matches= " + goedematches.size());
当我做
时matcher.match(descriptors,descriptors1,matches);
并用
读出比赛Log.d("LOG!", "Number of good matches= " + matches.size());
即使我拍摄的照片看起来不像我的照片,我也会得到450左右。
答案 0 :(得分:2)
首先,FREAK会创建二进制描述符。因此,你应该使用汉明距离而不是欧几里德距离(这里没有意义):
matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING);
汉明距离实际上会计算从一个描述符到另一个描述符的不同位数。
然后,重要的是要知道匹配器只为descriptors
中的每个描述符找到最佳对应 。因此,如果您获得的匹配数少于预期,则需要查看之前的步骤(特征检测和描述符提取)。
编辑:即使图像可能完全不同,您也会获得每个描述符的最佳匹配(即使这种匹配实际上是错误的)。文档中的示例代码通过测试距离是否大于3*min_dist
来过滤掉更糟糕的匹配。但这不会消除错误的比赛!考虑有两个完全不同的图像;算法会找到best
可能的匹配项,即使实际上这些都是错误的匹配......如果你真的想保持“正确”的匹配,你将不得不使用更先进的过滤技术(但是这是另一个问题)。
我想提到的最后一件事(为了理解匹配器)是matcher.match()
不对称:
matcher.match(descriptors,descriptors1,matches);
将为descriptors
中的每个描述符找到,descriptors1
中的最佳对应关系。可能是逆的情况不正确(你可能会试着说服自己)。
以下是“非对称”的更详细示例:假设您在图像Ai
上有一个描述符A
,并且您将图像A
与图像{{1 }}。您将获得B
,这将是Bi
B
中最佳的对应关系。
现在,如果您将图片Ai
与图片B
相匹配,您将获得A
A
的最佳通信。Bi
但可能存在Aj
,与Ai
不同,Bi
与Aj
更相似。
在这种情况下,将A
与B
匹配,会在Ai <-> Bi
与B
匹配时给出通信A
Bi <-> Aj
这显然是不一样的。