OpenCV中feature2D學習——FAST特徵點檢測

    在前面的文章《OpenCV中feature2D學習——SURF和SIFT算子實現特徵點檢測》中講了利用SIFT和SURF算子進行特徵點檢測,這裏嘗試使用FAST算子來進行特徵點檢測。

    FAST的全名是:Features from Accelerated Segment Test,主要特點值計算速度快,比已知的其他特徵點檢測算法要快很多倍,可用於計算機視覺應用的實時場景。目前以其高計算效率(computational performance)、高可重複性(highrepeatability)成爲計算機視覺領域最流行的特徵點檢測方法。其缺點在於當圖片中的噪點較多時,FAST算子的健壯性不好且算法的效果還依賴於一個閾值threshold,此外FAST算子不產生多尺度特徵而且沒有方向信息,這樣就會失去旋轉不變性。

    FAST特徵點檢測的詳細原理和過程可以參考:FAST特徵點檢測圖像處理特徵不變算子系列之FAST算子(四)。相關論文:

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

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

I、採用FAST函數進行特徵檢測

OpenCV中的FAST/FASTX函數用於FAST特徵點檢測。函數原型如下:

C++: 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)

參數:

·image – 輸入灰度圖像。

·keypoints – 檢測到的特徵點。

·threshold – 中心像素的像素值和該像素周圍的像素值之差的閾值。

·nonmaxSuppression – 是否對特徵點採用極大值抑制。

·type – 像素鄰域圓的三種類型:FastFeatureDetector::TYPE_9_16,FastFeatureDetector::TYPE_7_12, FastFeatureDetector::TYPE_5_8。

函數基本使用例子如下:

/**
* @概述: 使用FAST進行特徵點檢測
* @類和函數: FAST函數,FastFeatureDetector類
* @author: holybin
*/
#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_in_scene.png");

	vector<KeyPoint> keypoints; 
	FAST(img, keypoints, 20); 

	//-- 繪製特徵點
	Mat img_keypoints; 
	drawKeypoints(img, keypoints, img_keypoints, Scalar::all(-1), DrawMatchesFlags::DEFAULT); 
	//-- 顯示特徵點
	imshow("Keypoints", img_keypoints);
	imwrite("fast_detection_result.png", img_keypoints);

	waitKey(0); 
	return 0; 
}

運行結果如圖:



II、使用FastFeatureDetector進行FAST特徵點檢測

FastFeatureDetector繼承自2D圖像特徵檢測的虛基類FeatureDetector,專用於FAST特徵檢測,類似的還有如下類:


FastFeatureDetector的類定義如下:

class FastFeatureDetector : public FeatureDetector
{
public:
FastFeatureDetector( int threshold=1, bool nonmaxSuppression=true, type=FastFeatureDetector::TYPE_9_16 );
//可以看出FastFeatureDetector的構造函數默認的閾值爲1,進行非極大值抑制,以及圓周像素爲16個。
    virtual void read( const FileNode& fn );
virtual void write( FileStorage& fs ) const;
	//注意detect函數是定義於虛基類FeatureDetector中的。
protected:
    ...
};

FastFeatureDetector類的具體使用例子如下:

/**
* @概述: 使用FAST進行特徵點檢測
* @類和函數: FAST函數,FastFeatureDetector類
* @author: holybin
*/
#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_in_scene.png");

	vector<KeyPoint> keypoints; 
	FastFeatureDetector fast(20);
	fast.detect(img,keypoints);

	//-- 繪製特徵點
	Mat img_keypoints; 
	drawKeypoints(img, keypoints, img_keypoints, Scalar::all(-1), DrawMatchesFlags::DEFAULT); 
	//-- 顯示特徵點
	imshow("Keypoints", img_keypoints);
	imwrite("fast_detection_result.png", img_keypoints);

	waitKey(0); 
	return 0; 
}

運行結果如圖:



這裏注意到兩種方法出來的效果不同,究其原因,在使用detect函數進行特徵點檢測時,實際調用的是FeatureDetector的各個派生類(這裏是FastFeatureDetector類)中的detectImpl函數,參考detect函數源代碼(位置 \OpenCV2.4.0\modules\features2d\src\detectors.cpp):

void FeatureDetector::detect( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask ) const
{
    keypoints.clear();

    if( image.empty() )
        return;

    CV_Assert( mask.empty() || (mask.type() == CV_8UC1 && mask.size() == image.size()) );

    detectImpl( image, keypoints, mask );//實際調用派生類的該函數
}

而派生類FastFeatureDetector中的detectImpl函數的源代碼如下(位置 \OpenCV2.4.0\modules\features2d\src\fast.cpp):

void FastFeatureDetector::detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask ) const
{
    Mat grayImage = image;
    if( image.type() != CV_8U ) cvtColor( image, grayImage, CV_BGR2GRAY );
    FAST( grayImage, keypoints, threshold, nonmaxSuppression );//調用FAST函數
    KeyPointsFilter::runByPixelsMask( keypoints, mask );
}

可以看到detectImpl函數調用了FAST函數來做特徵點檢測,而隨後調用了runByPixelsMask函數來進行一些別的處理,因爲所有的傳入參數都是一致的,可以斷定就是這些操作使得最後的檢測結果不一樣。但是具體操作我還不清楚,如果有大神知道望賜教。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章