1. 程式人生 > >FAST特徵點檢測

FAST特徵點檢測

Features From Accelerated Segment Test

1. FAST演算法原理

      部落格中已經介紹了很多影象特徵檢測運算元,我們可以用LoG或者DoG檢測影象中的Blobs(斑點檢測),可以根據影象區域性的自相關函式來求得Harris角點(Harris角點),後面又提到了兩種十分優秀的特徵點及它們的描述方法SIFT特徵SURF特徵。SURF特徵算是為了提高運算效率對SIFT特徵的一種近似,雖然在有些實驗環境中已經達到了實時,但是我們實踐工程應用中,特徵點的提取與匹配只是整個應用演算法中的一部分,所以我們對於特徵點的提取必須有更高的要求,從這一點來看前面介紹的的那些特徵點方法都不可取。

      為了解決這個問題,Edward Rosten和Tom Drummond在2006年發表的“Machine learning for high-speed corner detection[1]”文章中提出了一種FAST特徵,並在2010年對這篇論文作了小幅度的修改後重新發表[2]。FAST的全稱為Features From Accelerated Segment Test。Rosten等人將FAST角點定義為:若某畫素點與其周圍領域內足夠多的畫素點處於不同的區域,則該畫素點可能為角點。也就是某些屬性與眾不同,考慮灰度影象,即若該點的灰度值比其周圍領域內足夠多的畫素點的灰度值大或者小,則該點可能為角點。

2. FAST演算法步驟

  1. 從圖片中選取一個畫素$P$,下面我們將判斷它是否是一個特徵點。我們首先把它的亮度值設為$I_p$。
  2. 設定一個合適的閾值$t$。
  3. 考慮以該畫素點為中心的一個半徑等於3畫素的離散化的Bresenham圓,這個圓的邊界上有16個畫素(如圖1所示)。

    圖1 FAST特徵點示意圖

  4. 現在,如果在這個大小為16個畫素的圓上有$n$個連續的畫素點,它們的畫素值要麼都比$I_p + t$大,要麼都比$I_p - t$小,那麼它就是一個角點。(如圖1中的白色虛線所示)。$n$的值可以設定為12或者9,實驗證明選擇9可能會有更好的效果。

     上面的演算法中,對於影象中的每一個點,我們都要去遍歷其鄰域圓上的16個點的畫素,效率較低。我們下面提出了一種高效的測試(high-speed test)來快速排除一大部分非角點的畫素。該方法僅僅檢查在位置1,9,5和13四個位置的畫素,首先檢測位置1和位置9,如果它們都比閾值暗或比閾值亮,再檢測位置5和位置13。如果$P$是一個角點,那麼上述四個畫素點中至少有3個應該必須都大於$I_p+t$或者小於$I_p-t$,因為若是一個角點,超過四分之三圓的部分應該滿足判斷條件。如果不滿足,那麼$p$不可能是一個角點。對於所有點做上面這一部分初步的檢測後,符合條件的將成為候選的角點,我們再對候選的角點,做完整的測試,即檢測圓上的所有點。

上面的演算法效率實際上是很高的,但是有點一些缺點:

  1. 當我們設定$n<12$時就不能使用快速演算法來過濾非角點的點;
  2. 檢測出來的角點不是最優的,這是因為它的效率取決於問題的排序與角點的分佈;
  3. 對於角點分析的結果被丟棄了;
  4. 多個特徵點容易擠在一起。

3. 使用機器學習做一個角點分類器

  1. 首先選取你進行角點提取的應用場景下很多張的測試圖片。
  2. 執行FAST角點檢測演算法來獲取測試圖片集上的所有角點特徵。
  3. 對於每個角點,我們把它鄰域圓上的16個點儲存下來儲存在一個vector內,處理所有步驟2中得到的角點,並把它們儲存在$P$中。
  4. 對於影象上的點$p$,它周圍鄰域圓上位置為$x,x\in\{1\dots16\}$的點表示為$p\to x$,可以用下面的判斷公式將該點$p\to x$分為3類: $$S_{p\to x} =\begin{cases} d,& I_{p \to x}\le I_p –t &(darker)\\ s,&I_p-t\le I_{p\to x}<I_p+t&(similar)\\b,&I_p+t\le I_{p\to x}&(brighter)\end{cases}$$
  5. 設$P$為訓練影象集中所有畫素點的集合,我們任意16個位置中的一個位置$x$,可以把集合$P$分為三個部分$P_d,P_s$和$P_b$,其中$P_d$的定義如下,$P_s$和$P_b$的定義與其類似$$P_b=\{p\in P:S_{p\to x} = b\}$$ 換句話說,對於任意給定的位置$x$,它都可以把所有影象中的點分為三類,第一類$P_d$包括了所有位置$x$處的畫素在閾值$t$下暗於中心畫素,第二類$P_s$包括了所有位置$x$處的畫素在閾值$t$下近似於中心畫素,$P_b$包括了所有位置$x$處的畫素在閾值$t$下亮於中心畫素。
  6. 定義一個新的布林變數$K_p$,如果$p$是一個角點,那些$K_p$為值,否則為假。
  7. 使用ID3演算法(決策樹分類器)來查詢每一個子集。
  8. 遞迴計算所有的子集直到$K_p$的熵為0;
  9. 被建立的決策樹就用於於其他圖片的FAST檢測。

4. 非極大值抑制

從鄰近的位置選取了多個特徵點是另一個問題,我們可以使用Non-Maximal Suppression來解決。

  1. 為每一個檢測到的特徵點計算它的響應大小(score function)$V$。這裡$V$定義為點$p$和它周圍16個畫素點的絕對偏差的和。
  2. 考慮兩個相鄰的特徵點,並比較它們的$V$值。
  3. $V$值較低的點將會被刪除。

5. OpenCV中進行FAST特徵檢測

在OpenCV中進行FAST特徵提取的函式為FAST。它一共有4個引數,第一個引數是輸入的影象,第二個是返回的特徵點,第三個是定義的閾值,第四個決定是否使用非極大值抑制。

void FAST(InputArray image, vector<KeyPoint>& keypoints, int threshold, bool nonmaxSuppression=true )

C++: void FASTX(InputArray image, vector<KeyPoint>& keypoints, int threshold, bool nonmaxSuppression, int type)

另外還有一個介面為FASTX,它提供了第五個引數type用來指定FAST檢測中畫素鄰域圓的引數:TYPE_9_16、TYPE_7_12、TYPE_5_8。

#include <opencv2/core/core.hpp> 
#include <opencv2/highgui/highgui.hpp> 
#include <opencv2/imgproc/imgproc.hpp> 
#include <opencv2/features2d/features2d.hpp>

using namespace cv; 
using namespace std;

int main(int argc, char** argv) 
{ 
    Mat img = imread("box.png"); 
    std::vector<KeyPoint> keypoints; 
    FAST(img, keypoints, 20); 
    //-- Draw keypoints 
    Mat img_keypoints; 
    drawKeypoints(img, keypoints, img_keypoints, Scalar::all(-1), DrawMatchesFlags::DEFAULT); 
    //-- Show detected (drawn) keypoints 
    imshow("Keypoints", img_keypoints);

    waitKey(0); 
    return 0; 
}

 image    image

6. 總結

FAST演算法比其他已知的角點檢測演算法要快很多倍,但是當圖片中的噪點較多時,它的健壯性並不好,而且演算法的效果還依賴於一個閾值$t$。而且FAST不產生多尺度特徵而且FAST特徵點沒有方向資訊,這樣就會失去旋轉不變性。

[1] Edward Rosten and Tom Drummond, “Machine learning for high speed corner detection” in 9th European Conference on Computer Vision, vol. 1, 2006, pp. 430–443.

[2] Edward Rosten, Reid Porter, and Tom Drummond, “Faster and better: a machine learning approach to corner detection” in IEEE Trans. Pattern Analysis and Machine Intelligence, 2010, vol 32, pp. 105-119.