C++/SIFT/SQL - 是否有一种有效的方法可以比较图像的SIFT描述符与SQL数据库中的SIFT描述符?

4
我希望找到一种方法,可以比较图像(查询)的SIFT描述符和SQL数据库中包含不同图片的许多描述符的描述符。
实际上,我的最终目的是开发一个应用程序,可以将一个图片与数据库中的许多图片进行比较(不在我的设备中,而是在SQL数据库中)。
我最初想到的是将每个描述符存储在SQL数据库中,并使用Brute Force方法或FlanneBased方法将每个描述符与另一个描述符进行比较。问题在于,在SQL数据库中,由于匹配背后的“数学”(例如欧几里得距离是sqrt(a²+b²+...)),计算匹配需要很长时间,而且无法在大型数据库中进行这种比较。
例如,如果我没记错的话,一个SIFT描述符包含128个数字,因此想象一下比较每个描述符的每个数字所需的时间。
是否有其他方法来完成这项工作?我知道在SQL数据库中,当您使用类似“SELECT a FROM b WHERE ...”之类的东西时,请求是有效的。
因此,我想知道是否有一种有效地存储SIFT描述符的方法?例如,我考虑将描述符“加密”成一种大字符串链,并且每个链都是唯一的,因此我可以将它们相互比较,但我不知道这是否是一个好的解决方案。
我已经阅读了这篇文章:Comparing SIFT features stored in a mysql database,但它没有帮助我。谢谢。

可能是比较存储在MySQL数据库中的SIFT特征的重复问题。 - marol
1
尝试使用局部敏感哈希:https://www.ceremade.dauphine.fr/~cohen/mypapers/auclairAMR07.pdf 或其他哈希方法。 - Micka
请看这个链接:https://dev59.com/rW025IYBdhLWcg3w3J5H - Micka
Marol,是的,我看到了这篇文章,但它并没有帮助我。关于这篇论文,我会阅读它的。哈希允许我做我想做的事情吗? - lilouch
2个回答

1
如果我是你,我更倾向于在代码中比较描述符,而不是在SQL中比较。 SQL并不适用于此。 我会按照以下步骤进行:-
1. Pre-load N descriptors from SQL onto memory.
2. Compare distances to query descriptor, descriptor by descriptor.
3. If distance<threshold, push to possiblematches.
4. When you reach N/2 descriptors, push the next N.
5. Compare all matches, choose the best one or the best D descriptors, as per your requirement.

然而,对于这个问题,我更愿意使用OpenCV内置的FileStorage类,它提供了对XML和YAML文件的I/O操作;它解决了手动解析描述符值的麻烦。

它快吗? 因为我正在开发一个应用程序,我想以更快的方式比较服务器中的图片而不是在“设备”内部。 例如,我拍照,计算其描述符,然后从SQL预加载描述符?就这样? - lilouch
速度取决于您数据库中描述符的数量。然而,OpenCV还具有不同的近似距离测量方法,例如FLANN(比仅计算欧几里得距离更快)。如果您非常关注在服务器上运行它,您可以编写一个简单的PHP脚本来完成相同的工作。由于您只是在计算距离,所以这并不是很困难。 - The Nomadic Coder
好的。如果我按照你的算法,我不理解这部分:“但是,为此,我宁愿使用OpenCV内置的FileStorage类,它提供了对XML和YAML文件的I/O;它解决了手动解析描述符值的问题”。我为什么需要一个XML文件?抱歉,我有点困惑。 - lilouch
那是在我意识到你想在服务器上运行它之前。如果您想将数据推送到服务器,SQL可能是最佳选择(因为它可以自动处理速度/安全性等)。OpenCV的文件存储模块(http://docs.opencv.org/modules/core/doc/xml_yaml_persistence.html)只是提供了一种简单的方法来持久保存OpenCV结构。 - The Nomadic Coder

0

使用SQL数据库比较SIFT并不是最优选择。OpenCV提供了一些关键点匹配器,更加高效。您可以在./samples/cpp/matcher_simple.cpp中找到一个使用SURF描述符的示例,该示例很容易适应于SIFT。基本上,核心代码如下:

BFMatcher matcher(NORM_L2);
vector<DMatch> matches;
matcher.match(descriptors1, descriptors2, matches);

据我所记,一些匹配器(例如Flann)只能处理特定类型的描述符(CV_32F)。

1
你可以在服务器内部进行匹配,这是最有效的方法。例如,可以参考http://lear.inrialpes.fr/pubs/2008/JDS08/jegou_hewgc08.pdf。对于非常大的数据库,可以将SIFT聚合成VLAD,压缩它们并在压缩域中使用不对称搜索:http://hal.inria.fr/inria-00633013/PDF/jegou_aggregate.pdf。对于平均大小的数据库,可以使用具有大词汇量的倒排索引(然后使用SQL数据库来实现倒排索引):http://www.robots.ox.ac.uk/~vgg/publications/2007/Philbin07/philbin07.pdf。 - xiawi
我认为你尝试的是检索,而不是分类(但带标签的检索等效于KNN)。无论如何,关于哈希,它取决于你将什么视为哈希:该论文(Jegou et al, PAMI 2012)为每个图像生成一个哈希,该哈希结果来自局部描述符的聚合(和压缩)。如果压缩得足够多,甚至不需要反向索引。此外,请查看此帖子的第三个答案(Stephan)[(https://dev59.com/T3I95IYBdhLWcg3w-C9b)]。 - xiawi
是的,我想要进行图像检索,但是BoW是用于分类的,对吗?这就是为什么当我使用BoW时,我必须为我的类别进行训练。但也许我错了,如果我想要进行检索,我不需要任何类别,只需使用所有数据库计算BoW即可?实际上,我有一个大描述符和一个哈希允许将描述符缩小为字符串(例如长度为10),然后我可以轻松地计算所有“指纹”之间的汉明距离。 - lilouch
BoW可以用于分类,但倒排索引的检索依赖于BoW描述(即BoW是隐式的“正向索引”)。关于哈希,您需要一个不受“雪崩效应”影响的“感知哈希”。 - xiawi
好的,你能给我解释一下如何使用BoW框架来检索图片吗?因为我知道如何用它进行分类,但对于检索,我有些困难。我是否需要为整个数据库计算所有描述符,然后将它们放入一个大的cv::Mat中?之后,对查询也做同样的处理,最后使用最近邻算法吗? - lilouch
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接