OpenCV关键点: 角度和八度的信息

9

我想了解更多关于KeyPoints的信息,所以有人能告诉我什么是KeyPoints吗?


KeyPoint::angle

在OpenCV文档中提到角度是关键点的计算方向(如果不适用则为-1)。我无法想象这是什么意思。请问有人能够解释一下或者提供一个小例子吗?


KeyPoint::octave

在OpenCV文档中提到octave是从中提取关键点的金字塔层。我无法想象这是什么意思。请问有人能够解释一下或者提供一个小例子吗?

5个回答

6
如果您真的想了解基础知识,就去了解基础知识:
这是关于图像特征描述/提取的第一篇也是最有影响力的论文之一。您可能会觉得有些难以理解,但它提供了一个复杂问题的良好解释。
链接:http://www.cs.ubc.ca/~lowe/papers/ijcv04.pdf

3
尽管本论文涉及SIFT,但需要注意的是OpenCV还提供其他特征检测算法,如SURF,同样返回这些关键点。其概念仍然相同。 - crizCraig

5

如果有人不想阅读@sammy提到的Lowe的论文,这里是一些简短的摘要:

  • 图像金字塔(见OpenCV文档wikipedia)基本上是基于我们多次降采样和缩小的单个图像而形成的一组图像。高斯金字塔就是这样一个例子。我们在特征检测和匹配中使用金字塔有很多原因。过去已经注意到,将图像降采样和缩小到某个级别并不意味着我们失去了所有需要进行特征匹配的特征,事实上它通常会去除一些噪声。高分辨率(不要与图像的宽度和高度混淆!)也经常不是我们需要的东西,因为(维基百科)更高的分辨率意味着图像中更多的细节,但更多的细节也意味着需要更多的处理能力,如果你在性能和低功耗平台上运行应用程序,如智能手机,这将是致命的。当然,这取决于图像和金字塔层数的数量。正如我们所知道的,降采样以某种方式改变图像中的像素。每个特征都由关键点和描述符描述。由于降采样时像素的变化,特征也会发生变化,因此它们的描述符和关键点也会发生变化。这就是为什么关键点必须存储在图像金字塔中提取时所在的级别的信息。请注意,创建图像金字塔需要相当数量的资源。但是当您开始使用这些图像进行其他操作(例如匹配)时,这种权衡是合理的。
  • 关键点角度与关键点表示的特征的方向有关。关键点实际上不是单个像素,而是特征内的一个小区域(调用.pt.x和.pt.y只返回关键点的中心),因此在改变其方向时,从关键点的视角来看像素位置也会发生变化。想象一下你有一座房子,有门、屋顶等。我们提取了这个房子的一些特征。然后我们把相机倒过来,在完全相同的位置拍摄了一张新照片。如果特征提取器支持方向,我们应该得到(几乎)与我们之前拍摄的图片中相同的特征(也就是相同的关键点)。如果特征提取器不支持方向,我们可能会失去大部分先前检测到的特征和/或获得新的特征。
我建议阅读《学习OpenCV》。虽然在OpenCV的API方面已经过时,但其中讨论的理论非常好地解释了出来。

4
如果有人来到这个问题,想知道为什么keypoint.octave的值会是一个奇怪的数字(例如16253184),那是因为它实际上携带了以下信息:
  • 最低有效字节中的实际octave
  • 次低有效字节中该octave的layer
  • 另一些被SIFT关键点检测打包进第三个最低有效字节的信息,但不会被SIFT描述符使用
通过方法unpackOctave(参见OpenCV实现)将keypoint.octave解压成变量octavelayerscale(其中scale只是1/2 ^ octave)。
为了更好地理解变量octavelayer,下面的图片可能会有所帮助:enter image description here

3

虽然我对角度和八度音符的概念有所了解,但我想知道float angle表示什么意思,于是我查看了OpenCV2.3.1的源代码,在sift.cpp中找到了答案。

inline KeyPoint featureToKeyPoint( const feature& feat )
{
    float size = (float)(feat.scl * SIFT::DescriptorParams::GET_DEFAULT_MAGNIFICATION() * 4); // 4==NBP
    float angle = (float)(feat.ori * a_180divPI);
    return KeyPoint( (float)feat.x, (float)feat.y, size, angle, feat.response, feat.feature_data->octv, feat.class_id );
}

好的,我理解了角度定义,但是feat.oria_180divPI是什么?
后者很容易找到。

const double a_180divPI = 180./CV_PI;

前者需要一些努力,在浏览了几种方法之后,我得到了以下结果

struct feature
{
    double x;                      /**< x coord */
    double y;                      /**< y coord */

    double scl;                    /**< scale of a Lowe-style feature */
    double ori;                    /**< orientation of a Lowe-style feature */

    ...
};

需要计算的feat.ori根据Lowe的论文(http://www.cs.ubc.ca/~lowe/papers/ijcv04.pdf)通过几个步骤来计算,包括计算ori_hist、平滑直方图和添加好的ori特征。
我不确定ori的确切含义,但我强烈怀疑OpenCV已将ori转换为适当的弧度表示法,最终结果angle是正常意义上范围从-180度到180度的角度。证据如下:

1) ori = arctan2( dy, dx)
2) bin = cvRound( n * ( ori * CV_PI ) / PI_2 )
3) new_feat->ori = ( ( PI2 * bin ) / n ) - CV_PI; 

希望能对您有所帮助。


编辑:我使用的是OpenCV2.3.1。对于SIFT,角度在**-180到180度之间。然而,对于SURF,角度在0到360**度之间。我不知道为什么。还要注意,在新文档中,它说如果不适用,则为_-1_ [链接](http://docs.opencv.org/modules/features2d/doc/common_interfaces_of_feature_detectors.html#float angle)。 - vancexu

1

为了了解Octave的用途,可以说它编码了计算描述符所需的特征大小和邻域的“尺度”。 - Micka

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