使用 BRISK 检测器/描述符 OpenCV 的性能问题
Posted
技术标签:
【中文标题】使用 BRISK 检测器/描述符 OpenCV 的性能问题【英文标题】:Performance issues using BRISK detector/descriptor OpenCV 【发布时间】:2014-07-02 16:32:14 【问题描述】:我在 OpenCV 中使用 BRISK 进行特征检测和描述时遇到性能问题。
基本上我会尝试匹配从这张图片中获得的所有描述符:
我使用基于 flann 的匹配器与 LSH 算法和 BRISK 从图像数据库中获得的所有描述符进行特征检测和描述。
我的图像数据库由 242 张图像组成。在这 242 张图像中,有三张图像对应于上述“复杂”图像查询中分别拍摄的每个对象。
这里是用于 BRISK 检测的参数(默认的 opencv 参数): 阈值:30,八度:4,模式比例:1.0。
在使用最佳匹配技术进行 flann 匹配后(图像查询中的每个描述符都与其在数据库描述符集中的最近邻域相关联),我的算法输出按匹配百分比排序的数据库图像列表。以下是前四个结果:
-
数据库中螺栓对应的图像:4 个匹配/15 个检测到的关键点 => 匹配百分比:26.7%。
数据库中瓶子对应的图像有4个匹配/15个检测到的关键点=>匹配百分比:26.7%。
数据库中螺栓对应的图像有10个匹配/检测到59个关键点=>匹配百分比:16.9%。
与图像查询中不存在的对象对应的图像:1 个匹配/16 个检测到的关键点 => 匹配百分比:16.7%。
我使用 ORB 作为特征检测和描述来比较这个结果。以下是使用的参数:特征数:2000,比例因子:1.2,金字塔层数:8。
这是我得到的结果:
-
数据库中螺栓对应的图像:576 个匹配/752 个检测到的关键点 => 匹配百分比:76.6%。
数据库中瓶子对应的图像有111个匹配/189个检测到的关键点=>匹配百分比:58.7%。
数据库中笔对应的图像有124个匹配/293个检测到的关键点=>匹配百分比:42.3%。
与图像查询中不存在的对象对应的图像:2 个匹配/66 个检测到的关键点 => 匹配百分比:3%。
如您所见,使用 ORB 的结果要好得多。首先,在数据库中的每张图像上检测到更多的关键点,并且对于好的对象,匹配的百分比明显更好。而且好对象的匹配百分比和错误对象的匹配百分比之间的差距更显着。
我想知道为什么 BRISK 检测器检测到的关键点比 ORB 检测器少得多。我进行了不同的测试,以弄清楚如何使用 BRISK 检测器检测更多关键点(降低阈值,降低八度数)。我确实可以检测到更多的关键点,但与 ORB 检测器的区别仍然非常重要。你知道为什么 BRISK 检测器会有这样的行为吗?
我的 OpenCV 版本是 2.4.8,但我根据这些陈述尝试了 2.4.4 和 2.4.9 版本的 BRISK 检测部分:
http://code.opencv.org/issues/2491 和 BRISK feature detector detects zero keypoints 没有改进。
我还尝试将 ORB 检测器与 BRISK 描述结合起来。匹配结果比第一种方法(full BRISK)好,但比第二种方法(full ORB)差:
-
数据库中螺栓对应的图像:529 个匹配 / 708 个检测到的关键点 => 匹配百分比:74.7%。
数据库中瓶子对应的图像有69个匹配/134个检测到的关键点=>匹配百分比:51.5%。
数据库中笔对应的图像有 93 / 247 个检测到的关键点匹配 => 匹配百分比:37.6%。
与图像查询中不存在的对象对应的图像:5 个匹配/50 个检测到的关键点 => 匹配百分比:10%。
请注意,在方法 2 和方法 3 中,在每个图像上检测到的关键点数量并不相同。实际上,当我在测试图像(这里是螺栓的图像)上运行此代码时:
// BRISK parameters
int Threshl=30;
int Octaves=4;
float PatternScales=1.0f;
// ORB parameters
int nFeatures=2000;
float scaleFactor=1.2f;
int nLevels=8;
BRISK BRISKD(Threshl, Octaves, PatternScales);
ORB ORBD(nFeatures, scaleFactor, nLevels);
vector<KeyPoint> kpts;
Mat descriptors;
Mat img = cv::imread("Path to the bolt image", IMREAD_GRAYSCALE );
ORBD.detect(img,kpts); // Number of keypoints detected = 752
BRISKD.compute(img, kpts, descriptors); // Number of descriptors = 708
BRISK 似乎没有计算描述符中检测到的所有关键点(ORB 检测器检测到 752 个关键点 => BRISK 描述符计算了 708 个描述符)。
但是,即使 ORB 检测到的所有关键点都不是在 BRISK 描述符中计算的。从这些结果看来,BRISK 不是比 ORB 更好地描述一个关键点吗?如果我错了,请纠正我,但我很确定应该是相反的......
如果你们有任何可以帮助我理解我的结果的元素,或者如果你已经在 OpenCV 中遇到了 BRISK 的一些问题,请告诉我。任何帮助将不胜感激:)。
【问题讨论】:
【参考方案1】:好的,我想出了如何从 BRISK 获得预期的结果。 我在这里尝试了 BRISK 创建者的代码: https://github.com/calihem/mavhub/tree/master/thirdparty
这是我得到的结果:
-
数据库中螺栓对应的图像:149 个匹配/288 个检测到的关键点 => 匹配百分比:51.7%。
数据库中瓶子对应的图像有27个匹配/57个检测到的关键点=>匹配百分比:47.4%。
数据库中笔对应的图像有38个匹配/101个检测到的关键点=>匹配百分比:37.6%。
与图像查询中不存在的对象对应的图像:5 个匹配/76 个检测到的关键点 => 匹配百分比:6.6%。
这些结果比我以前的要好得多。实际上,对于这个特定的查询图像,它们并不比使用 ORB 获得的更好。但是我尝试了其他查询图像,特别是更复杂的图像,并且 BRISK 优于 ORB。
似乎至少从 2.4.4 版本到当前版本 2.4.9,opencv 中的 BRISK 实现存在问题。我认为这个 bug 应该尽快修复,因为它已经报告给 opencv 社区 (http://code.opencv.org/issues/2491)。
与此同时,我建议您使用 BRISK 创建者编写的代码,效果很好;)。
【讨论】:
您是从 OpenCV 内部还是外部运行原始 BRISK 代码? 我已经从这里运行了原始的 Brisk 代码:github.com/rghunter/BRISK 请注意,您需要 OpenCV 2.2 或更高版本才能运行此代码。您应该能够在 OpenCV 中运行原始 Brisk 代码,但您首先需要找到 Brisk 代码工作的 OpenCV 版本...介于 2.2 和 2.4.4 之间。 您是英雄,非常感谢您指出这一点!这让我快疯了。 github.com/rghunter/BRISK 的代码构建并运行良好。虽然,我看到几周前正在实施修复:code.opencv.org/issues/3976 还有一些戏剧here。我希望它会保留在 3.0 的核心模块中,但似乎它可能会转移到 contrib (xfeatures2d)。 我用的是opencv 2.4.9!你们能解释一下如何将来自该 github 的代码集成到我的 opencv 版本吗?以上是关于使用 BRISK 检测器/描述符 OpenCV 的性能问题的主要内容,如果未能解决你的问题,请参考以下文章
OpenCV 例程 300篇245. 特征检测之 BRISK 算子