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算法步驟
- 從圖片中選取一個像素$P$,下面我們將判斷它是否是一個特征點。我們首先把它的亮度值設為$I_p$。
- 設定一個合適的閾值$t$。
- 考慮以該像素點為中心的一個半徑等於3像素的離散化的Bresenham圓,這個圓的邊界上有16個像素(如圖1所示)。
圖1 FAST特征點示意圖
-
現在,如果在這個大小為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$不可能是一個角點。對於所有點做上面這一部分初步的檢測后,符合條件的將成為候選的角點,我們再對候選的角點,做完整的測試,即檢測圓上的所有點。
上面的算法效率實際上是很高的,但是有點一些缺點:
-
當我們設置$n<12$時就不能使用快速算法來過濾非角點的點;
-
檢測出來的角點不是最優的,這是因為它的效率取決於問題的排序與角點的分布;
-
對於角點分析的結果被丟棄了;
-
多個特征點容易擠在一起。
3. 使用機器學習做一個角點分類器
- 首先選取你進行角點提取的應用場景下很多張的測試圖片。
- 運行FAST角點檢測算法來獲取測試圖片集上的所有角點特征。
- 對於每個角點,我們把它鄰域圓上的16個點存儲下來保存在一個vector內,處理所有步驟2中得到的角點,並把它們存儲在$P$中。
- 對於圖像上的點$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}$$
- 設$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$下亮於中心像素。
- 定義一個新的布爾變量$K_p$,如果$p$是一個角點,那些$K_p$為值,否則為假。
- 使用ID3算法(決策樹分類器)來查詢每一個子集。
- 遞歸計算所有的子集直到$K_p$的熵為0;
- 被創建的決策樹就用於於其他圖片的FAST檢測。
4. 非極大值抑制
從鄰近的位置選取了多個特征點是另一個問題,我們可以使用Non-Maximal Suppression來解決。
- 為每一個檢測到的特征點計算它的響應大小(score function)$V$。這里$V$定義為點$p$和它周圍16個像素點的絕對偏差的和。
- 考慮兩個相鄰的特征點,並比較它們的$V$值。
- $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; }
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.