1. 程式人生 > >sift尺度空間的理解以及計算

sift尺度空間的理解以及計算

為了保持尺度不變的特性,作者構建高斯金字塔及差分金字塔的方法來取得極值點。

但是其中的尺度的計算有點不太理解,看了原始碼和網路上的分析後做個筆記

class CV_EXPORTS_W SIFT : public Feature2D
{
public:
    CV_WRAP explicit SIFT( int nfeatures=0, int nOctaveLayers=3,
          double contrastThreshold=0.04, double edgeThreshold=10,
          double sigma=1.6);

下面的一段程式碼是opencv

中關於sift的建構函式的程式碼

可以看到,把組中層數初始化為3,(作者建議3-5),邊緣閾值10,去除邊緣相應的點,sigma01.6,高斯模糊的尺度,這是最模糊的尺度。

然後構建高斯金字塔。

其中組數由下式計算得出

int nOctaves = actualNOctaves > 0 ? actualNOctaves : cvRound(log( (double)std::min( base.cols, base.rows ) ) / log(2.) - 2) - firstOctave;

這個也很好理解,在多解析度的組取樣中,每次按行縮小兩倍,列縮小兩倍,即畫素個數減少為

1/4

sig[0] = sigma;sigma就是一開始賦予的初值

當前層為上層的k倍,即同一組之間的不同層之間的關係。

那有程式碼可以看出,上面的一組的第一副影象是下面一組的倒數第三層的影象的降取樣得到。

關於層數= nOctaveLayers + 3的原因有幾個

  1. 為了保持尺度的連續性

  2. 為了構建S+2層的差分金字塔,其實跟上面差不多

  3. 為了計算極值的時候S層都可以得到計算

那麼組與組之間的尺度連續性體現在哪?

void SIFT::buildGaussianPyramid( const Mat& base, vector<Mat>& pyr, int nOctaves ) const
{
    vector<double> sig(nOctaveLayers + 3);
    pyr.resize(nOctaves*(nOctaveLayers + 3));

    // precompute Gaussian sigmas using the following formula:
    //  \sigma_{total}^2 = \sigma_{i}^2 + \sigma_{i-1}^2
    sig[0] = sigma;
    double k = pow( 2., 1. / nOctaveLayers );
    for( int i = 1; i < nOctaveLayers + 3; i++ )
    {
        double sig_prev = pow(k, (double)(i-1))*sigma;
        double sig_total = sig_prev*k;
        sig[i] = std::sqrt(sig_total*sig_total - sig_prev*sig_prev);
    }
….
….
…
}