c++ - OpenCV SIFT 描述符关键点半径

标签 c++ opencv sift

我正在深入研究 OpenCV's implementation of SIFT descriptor extraction .我遇到了一些令人费解的代码来获取兴趣点邻域的半径。下面是带注释的代码,变量名更改为更具描述性:

// keep octave below 256 (255 is 1111 1111)
int octave = kpt.octave & 255;
// if octave is >= 128, ...????
octave = octave < 128 ? octave : (-128 | octave);
// 1/2^absval(octave)
float scale = octave >= 0 ? 1.0f/(1 << octave) : (float)(1 << -octave);
// multiply the point's radius by the calculated scale
float scl = kpt.size * 0.5f * scale;
// the constant sclFactor is 3 and has the following comment:
// determines the size of a single descriptor orientation histogram
float histWidth = sclFactor * scl;
// descWidth is the number of histograms on one side of the descriptor
// the long float is sqrt(2)
int radius = (int)(histWidth * 1.4142135623730951f * (descWidth + 1) * 0.5f);

我知道这与转换为获取兴趣点的比例有关(我已阅读 Lowe 的论文),但我无法将这些点与代码联系起来。具体来说,我不明白前 3 行和最后一行。

我需要理解这一点才能为运动创建类似的局部点描述符。

最佳答案

I don't understand the first 3 lines

事实上,这个 SIFT 实现编码 KeyPoint 中的几个值octave属性。如果您引用 line 439你可以看到:

kpt.octave = octv + (layer << 8) + (cvRound((xi + 0.5)*255) << 16);

这意味着 Octave 音阶存储在第一个字节 block 中,层存储在第二个字节 block 中,依此类推。

所以 kpt.octave & 255 (可以在 unpackOctave 方法中找到)只是屏蔽关键点 Octave 以检索有效 Octave 值。

此外:此 SIFT 实现使用负的第一个 Octave 音阶 (int firstOctave = -1) 来处理更高分辨率的图像。由于 Octave 索引从 0 开始,因此计算映射:

octave index = 0 => 255
octave index = 1 => 0
octave index = 2 => 1
...

此映射是在 line 790 处计算的:

kpt.octave = (kpt.octave & ~255) | ((kpt.octave + firstOctave) & 255);

因此上面的第二行只是映射回这些值的一种方式:

octave = 255 => -1
octave = 0   => 0
octave = 1   => 1
..

第三行只是一种计算音阶的方法,考虑到负 Octave 音阶给出的音阶 > 1,例如 1 << -octaveoctave = -1 给出 2这意味着它的大小增加了一倍。

[I don't understand] last line.

基本上它对应于包裹尺寸为 D 的方形 block 的圆的半径,因此 sqrt(2)和除以 2。D通过乘法计算:

  • 关键点尺度,
  • 放大倍数 = 3,
  • 描述符直方图的宽度 = 4,四舍五入到下一个整数(因此为 +1)

您确实可以在vlfeat's SIFT implementation 中找到详细说明。 :

The support of each spatial bin has an extension of SBP = 3sigma pixels, where sigma is the scale of the keypoint. Thus all the bins together have a support SBP x NBP pixels wide. Since weighting and interpolation of pixel is used, the support extends by another half bin. Therefore, the support is a square window of SBP x (NBP + 1) pixels. Finally, since the patch can be arbitrarily rotated, we need to consider a window 2W += sqrt(2) x SBP x (NBP + 1) pixels wide.

最后强烈推荐大家引用这个vlfeat SIFT documentation .

关于c++ - OpenCV SIFT 描述符关键点半径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17015995/

相关文章:

c++ - C++:根据Stroustrup的示例播种随机数

c++ - 在 Ubuntu 上为 Raspberry Pi 交叉编译 opencv 项目

c++ - OpenCV 改变亮度和对比度

python - Eclipse中Python的OpenCV 2.3的配置

c# - 如何从特征提取中找到匹配的数量?

c++ - 调用 setItemWidget 时崩溃

c++ - 将 C++ 模板参数限制为相同值类型的容器

opencv - 使用 SIFT/SURF 的特征匹配可以用于相似对象的分类吗?

C++ 尝试设置指向新对象的指针

python - 筛选比较,计算相似度得分,python