ORB在opencv 2.4.9中无法检测到关键点

10

我正在尝试使用ORB检测关键点,一切都很好,直到我切换到OpenCV 2.4.9。

首先,似乎关键点的数量减少了,对于一些图像,没有检测到关键点:

这是我的代码编译两个版本: (2.3.1 和 2.4.9)

#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/features2d/features2d.hpp>


using namespace cv;


int main(int argc, char **argv){

  Mat img = imread(argv[1]);

  std::vector<KeyPoint> kp;

  OrbFeatureDetector detector;
  detector.detect(img, kp);
  std::cout << "Found " << kp.size() << " Keypoints " << std::endl;

  Mat out;
  drawKeypoints(img, kp, out, Scalar::all(255));

  imshow("Kpts", out);

  waitKey(0);
  return 0;
}

结果: 2.3.1: 发现152个关键点

检测到的kp

2.4.9: 发现0个关键点

零个kpts

我还尝试了不同的ORB构造器,但是得到了相同的结果,没有KPts。与2.3.1默认构造器相同的构造器值:
2.4.9定制构造器:

#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/features2d/features2d.hpp>


using namespace cv;


int main(int argc, char **argv){

  Mat img = imread(argv[1]);

  std::vector<KeyPoint> kp;

  // default in 2.4.9 is : ORB(700, 1.2f, 3, 31, 0);
  OrbFeatureDetector detector(500, 1.2f, 8, 31, 0); // default values of 2.3.1
  detector.detect(img, kp);
  std::cout << "Found " << kp.size() << " Keypoints " << std::endl;
  Mat out;
  drawKeypoints(img, kp, out, Scalar::all(255));

  imshow("Kpts", out);

  waitKey(0);
  return 0;
}

你有任何想法这是怎么发生的吗?我该如何修复它?

谢谢。


你得到任何解决方案了吗? - Rafael Ruiz Muñoz
在其他图像中,您也发现了0个关键点吗?还是只比使用openCV 2.3.1时少一些关键点? - Whysmerhill
2个回答

10

在OpenCV的2.3.1版本和2.4.9版本之间,ORB的实现方式发生了相当大的改变。很难确定具体是哪个变化造成了你所观察到的行为。

但是,通过改变边缘阈值的值,你可以再次增加检测到的特征数量。

以下是对你的代码进行了修改以说明我的意思(请注意,我只能使用OpenCV 3.0.0测试它,但我想你明白我的意思)。

#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/features2d.hpp>

using namespace cv;

int main(int argc, char **argv){

    Mat img = imread(argv[1]);

    std::vector<KeyPoint> kp;

    // Default parameters of ORB
    int nfeatures=500;
    float scaleFactor=1.2f;
    int nlevels=8;
    int edgeThreshold=15; // Changed default (31);
    int firstLevel=0;
    int WTA_K=2;
    int scoreType=ORB::HARRIS_SCORE;
    int patchSize=31;
    int fastThreshold=20;

    Ptr<ORB> detector = ORB::create(
    nfeatures,
    scaleFactor,
    nlevels,
    edgeThreshold,
    firstLevel,
    WTA_K,
    scoreType,
    patchSize,
    fastThreshold );

    detector->detect(img, kp);
    std::cout << "Found " << kp.size() << " Keypoints " << std::endl;

    Mat out;
    drawKeypoints(img, kp, out, Scalar::all(255));

    imshow("Kpts", out);

    waitKey(0);
    return 0;
}

4
在OpenCV 3.1中,edgeThreshold参数实际上是“特征不被检测的边界大小”。一种检测额外特征的方法是减小fastThreshold参数。这个名称有些误导人,因为即使在使用Harris关键点时(即ORB::HARRIS_SCORE),这个阈值也会影响检测到的角落数量,而不仅仅是快速关键点(FAST keypoints),这可能让你根据参数名称认为。这个名称也有些误导人,因为edgeThreshold本身听起来像是Harris角点检测的阈值,而不是用于检测点的图像部分的阈值。

参见:http://docs.opencv.org/trunk/db/d95/classcv_1_1ORB.html#gsc.tab=0.

此外,增加金字塔级别的数量nlevels可以给您更多的关键点,尽管如果您的图像大小相同,唯一的区别是您的OpenCV版本,那么它对这里的帮助不大。

我遇到了同样的问题,以下是有效的代码:
std::vector<KeyPoint> kpts1; Mat desc1; Ptr<ORB> orb = ORB::create(100, 2, 8, 31, 0, 2, ORB::HARRIS_SCORE, 31, 20); orb->detectAndCompute(input_image, Mat(), kpts1, desc1);

上面的最后一个参数(20)是要减小的fastThreshold

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