1. 程式人生 > >OpenCV特徵點提取----Fast特徵

OpenCV特徵點提取----Fast特徵

1.FASTfeaturesfrom accelerated segment test演算法

特徵點檢測和匹配是計算機視覺中一個很有用的技術。在物體檢測,視覺跟蹤,三維常年關鍵等領域都有很廣泛的應用。很多傳統的演算法都很耗時,而且特徵點檢測演算法只是很多複雜影象處理裡中的第一步,得不償失。FAST特徵點檢測是公認的比較快速的特徵點檢測方法,只利用周圍畫素比較的資訊就可以得到特徵點,簡單,有效。

FAST特徵檢測演算法來源於corner的定義,這個定義基於特徵點周圍的影象灰度值,檢測候選特徵點周圍一圈的畫素值,如果候選點周圍領域內有足夠多的畫素點與該候選點的灰度值差別夠大,則認為該候選點為一個特徵點。

其中Ix)為圓周上任意一點的灰度,Ip)為圓心的灰度,Ed為灰度值差得閾值,如果N大於給定閾值,一般為周圍圓圈點的四分之三,則認為p是一個特徵點。

為了獲得更快的結果,還採用了額外的加速辦法。如果測試了候選點周圍每隔90度角的4個點,應該至少有3個和候選點的灰度值差足夠大,否則則不用再計算其他點,直接認為該候選點不是特徵點。候選點周圍的圓的選取半徑是一個很重要的引數,這裡我為了簡單高效,採用半徑為3,共有16個周邊畫素需要比較。為了提高比較的效率,通常只使用N個周邊畫素來比較,也就是大家經常說的FAST-N。我看很多文獻推薦FAST-9,作者的主頁上有FAST-9FAST-10FAST-11

FAST-12,大家使用比較多的是FAST-9FAST-12。上個圖說明的更形象一些

OpenCV裡對FAST的使用也非常簡單,先宣告一組特徵點,構建FAST特徵檢測,接下來呼叫detect函式檢測影象中的特徵點,最後把特徵點繪製到圖片上。上程式碼說的清楚些

Features From Accelerated Segment Test

1. Fast演算法原理

部落格中已經介紹了很多影象特徵檢測運算元,我們可以用LoG或者DoG檢測影象中的Blobs(斑點檢測),可以根據影象區域性的自相關函式來求得Harris角點(Harris角點),後面又提到了兩種十分優秀的特徵點及它們的描述方法SIFT

特徵與SURF特徵。

SURF特徵算是為了提高運算效率對SIFT特徵的一種近似,雖然在有些實驗環境中已經達到了實時,但是我們實踐工程應用中,特徵點的提取與匹配只是整個應用演算法中的一部分,所以我們對於特徵點的提取必須有更高的要求,從這一點來看前面介紹的的那些特徵點方法都不可取。

為了解決這個問題,Edward RostenTom Drummond2006年發表的“Machine learning for high-speedcorner detection[1]”文章中提出了一種FAST特徵,並在2010年對這篇論文作了小幅度的修改後重新發表[2]FAST的全稱為Features From Accelerated SegmentTestRosten等人將FAST角點定義為:若某畫素點與其周圍領域內足夠多的畫素點處於不同的區域,則該畫素點可能為角點。

也就是某些屬性與眾不同,考慮灰度影象,即若該點的灰度值比其周圍領域內足夠多的畫素點的灰度值大或者小,則該點可能為角點。

2. FAST演算法步驟

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

1 FAST特徵點示意圖

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

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

如果不滿足,那麼$p$不可能是一個角點。對於所有點做上面這一部分初步的檢測後,符合條件的將成為候選的角點,我們再對候選的角點,做完整的測試,即檢測圓上的所有點。

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

  1. $n<12$時不能拒絕許多的候選點;
  2. 檢測出來的角點不是最優的,這是因為它的效率取決於問題的排序與角點的分佈;
  3. 對於角點分析的結果被丟棄了;
  4. 多個特徵點容易擠在一起。

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,boolnonmaxSuppression=true )

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

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

6.總結

FAST演算法比其他已知的角點檢測演算法要快很多倍,但是當圖片中的噪點較多時,它的健壯性並不好,而且演算法的效果還依賴於一個閾值$t$

而且FAST不產生多尺度特徵而且FAST特徵點沒有方向資訊,這樣就會失去旋轉不變性。

[1] Edward Rosten and Tom Drummond, “Machine learning for high speedcorner 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: amachine learning approach to corner detection” in IEEE Trans. Pattern

Analysisand Machine Intelligence, 2010, vol 32, pp. 105-119.

FAST特徵提出之後,實時計算機視覺應用中特徵提取效能才有顯著改善。目前以其高計算效率(computational performance)、高可重複性(high repeatability)成為計算機視覺領域最流行的角點檢測方法。

1997年,Simth提出了SUSAN角點檢測方法[1]。網址SUSAN方法的基礎上,2005, Rosten在論文[2]中提出基於The segment test criterion的角點檢測方法,全稱“Features fromAccelerated Segment Test”,簡稱FAST



2006

年,Rosten[3]中使用機器學習對FAST的一些缺點進行改進,他的主頁提供的FAST實現即基於此論文。後續在2009年提出效能增強(可重複性增強、計算效率下降)FAST-ER[4]



2010

年,MairECCV會議論文[5]中提出AGAST特徵。對FAST底層的the accelerated segment test進行改進,通過在擴充套件配置空間尋找最優決策樹,使用特定樹的組合獲得自適應並且通用的accelerated segment test。對FAST 9-16 detector提速約13%,對FAST 7-12 detector提速最高30%,對FAST 5-8 detector提速最高50%AGAST專案網址



2011

年,S. LeuteneggerBRISK描述子[6]中提出multi-scale AGAST detector, 並用實驗證明與SURF detector有等效的可重複性(equivalentrepeatability)。對Graffiti序列的第一幅圖檢測時間為17.20ms,約為SURF detector消耗時間的16%SIFT detector消耗時間的1%.BRISK專案地址

參考文獻:
[1]S. M. Simth, J. M. Brady, Susan - a new approach to low level imageprocessing. International Journal of Computer Vision 23, 1997.
[2]E. Rosten, T. Drummond, Fusing points and lines for high performancetracking. IEEE International Conference on Computer Vision, 2005.
[3]E. Rosten, T. Drummond, Machine learning for high-speed corner detection,ECCV 2006.
[4]E. Rosten, R. Porter, T. Drummond, Faster and better: A machine learningapproach to corner detection, IEEE PAMI, 2009.
[5]E. Mair, G. D. Hager, Adaptive and generic corner detection based on theaccelerated segment test, ECCV 2010.
[6]S. Leutenegger, et.al. Brisk:Binary robust invariant scalable keypoints,ICCV 2011.

程式碼:

<span style="font-family:SimSun;font-size:24px;">// feature_detection.cpp : 定義控制檯應用程式的入口點。
//

#include "stdafx.h"
#include <iostream>

#include <opencv2/core/core.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/nonfree/nonfree.hpp>             //  sift特徵在這個標頭檔案中  

#include <vector>

#pragma comment(lib,"opencv_core2410d.lib")              
#pragma comment(lib,"opencv_highgui2410d.lib")              
#pragma comment(lib,"opencv_imgproc2410d.lib") 
#pragma comment(lib,"opencv_features2d2410d.lib") 
#pragma comment(lib,"opencv_nonfree2410d.lib") 

using namespace std;
using namespace cv;

//struct DrawMatchesFlags
//{   
//	enum    {
//		DEFAULT = 0, // 輸出影象將被建立(Mat::create),
//		// 只畫出特徵點,而不畫出周圍的circle包含特徵點的大小和方向.
//		DRAW_OVER_OUTIMG = 1, // 輸出影象將被建立(using Mat::create),匹配點將被畫在輸出影象的內容上.
//		NOT_DRAW_SINGLE_POINTS = 2, // 單個的點不畫出.
//		DRAW_RICH_KEYPOINTS = 4 // 對每個特徵點周圍的circle,包含特徵點的大小和方向將被畫出.    
//	};
//};
void fast_feature()
{
	Mat image;
	image = imread("swan.jpg");
	// vector of keyPoints
	std::vector<KeyPoint> keyPoints;
	// construction of the fast feature detector object
	FastFeatureDetector fast(80);	// 檢測的閾值為80
	// feature point detection
	fast.detect(image,keyPoints);
	drawKeypoints(image, keyPoints, image, Scalar::all(-1), DrawMatchesFlags::DRAW_OVER_OUTIMG);
	imshow("FAST feature", image);
	//cvWaitKey(0);
}



bool sift_feature()
{
	Mat image = imread("swan.jpg", 1);
	if(!image.data)
	{
		cout << "Fail to load image" << endl;
		return 0;
		
	}
	vector<KeyPoint> keypoints;          //  存放關鍵點

	// 其中0.03代表特徵的閥值:用於去除低對比度的關鍵點   10是用於降低直線敏感度的閥值:去除不穩點的邊緣響應點
	SiftFeatureDetector sift(0.03, 10.0);   
	sift.detect(image, keypoints);

	drawKeypoints(image, keypoints, image, Scalar(255,255,255), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
	namedWindow("sift");
	imshow("sift", image);
	
	
}

void main()
{
	sift_feature();
	fast_feature();

	waitKey(0);
	
}</span>

參考文獻: