OpenCV (Python) 解压 SIFT Octave

OpenCV (Python) unpack SIFT Octave

我刚刚发现 SIFT 写了 Octave as packed value(八度、层和音阶)。
我需要解压这个值,因为我必须将 SIFT 检测器与其他描述符(ORB、BRIEF、SURF、BRISK)结合使用。 Here你可以找到类似的问题。
我已经尝试了不同的解决方案(参见下面的代码),但 none 似乎在 python 中有效(this one 也有效)。
有什么建议吗?

unpackOctave(keypoints[i], octave, layer, scale)     

或:

unpackOctave(const KeyPoint& kpt, int& octave, int& layer, float& scale){    
    octave = kpt.octave & 255;    
    layer = (kpt.octave >> 8) & 255;    
    octave = octave < 128 ? octave : (-128 | octave);    
    scale = octave >= 0 ? 1.f/(1 << octave) : (float)(1 << -octave);    
}

我定义了一个 Python 函数来解压 SIFT Octave:

#!/usr/bin/python3
## 2018.01.23 11:12:30 CST
## created by Silencer

def unpackSIFTOctave(kpt):
    """unpackSIFTOctave(kpt)->(octave,layer,scale)
    @created by Silencer at 2018.01.23 11:12:30 CST
    @brief Unpack Sift Keypoint by Silencer
    @param kpt: cv2.KeyPoint (of SIFT)
    """
    _octave = kpt.octave
    octave = _octave&0xFF
    layer  = (_octave>>8)&0xFF
    if octave>=128:
        octave |= -128
    if octave>=0:
        scale = float(1/(1<<octave))
    else:
        scale = float(1<<-octave)
    return (octave, layer, scale)

比如我在panda上检测到sift kpts

使用unpackSiftOctave解压sift kpts,得到(八度、层、比例)的列表。部分解压结果。

[(0, 3, 1.0),
 (1, 3, 0.5),
 (-1, 3, 2.0),
 (-1, 3, 2.0),
 (2, 1, 0.25),
 (2, 1, 0.25),
 (-1, 1, 2.0),
 (-1, 1, 2.0),
 (0, 2, 1.0),
 (1, 3, 0.5),
 ...
]

Kinght 的回答似乎是正确的,但我只想补充一点,我能够在 Github repository that implements the whole SIFT algorithm for keypoint detection and description in Python. It is very good for understanding SIFT and getting your hands dirty with it (if you're familiar with Python), and it comes with a two part 教程中找到 unpackOctave(keypoint) 方法的良好实现。

这就是他们实现 unpackOctave(keypoint) 方法的方式——与最初的 C 实现非常相似(也与 Kinght 的回答相似)。

def unpackOctave(keypoint):
    """Compute octave, layer, and scale from a keypoint
    """
    octave = keypoint.octave & 255
    layer = (keypoint.octave >> 8) & 255
    if octave >= 128:
        octave = octave | -128
    scale = 1 / float32(1 << octave) if octave >= 0 else float32(1 << -octave)
    return octave, layer, scale