1. 程式人生 > >【特徵檢測】FAST特徵點檢測演算法

【特徵檢測】FAST特徵點檢測演算法

簡介

        在區域性特徵點檢測快速發展的時候,人們對於特徵的認識也越來越深入,近幾年來許多學者提出了許許多多的特徵檢測演算法及其改進演算法,在眾多的特徵提取演算法中,不乏湧現出佼佼者。

        從最早期的Moravec,到Harris,再到SIFT、SUSAN、GLOH、SURF演算法,可以說特徵提取演算法層出不窮。各種改進演算法PCA-SIFT、ICA-SIFT、P-ASURF、R-ASURF、Radon-SIFT等也是搞得如火如荼,不亦樂乎。上面的演算法如SIFT、SURF提取到的特徵也是非常優秀(有較強的不變性),但是時間消耗依然很大,而在一個系統中,特徵提取僅僅是一部分,還要進行諸如配準、提純、融合等後續演算法。這使得實時性不好,降繫了統效能。

        Edward Rosten和Tom Drummond兩位大神經過研究,於2006年在《Machine learning for high-speed corner detection》中提出了一種FAST特徵點,並在2010年稍作修改後發表了《Features From Accelerated Segment Test》,簡稱FAST注意:FAST只是一種特徵點檢測演算法,並不涉及特徵點的特徵描述。

FAST詳解

FAST特徵的定義

      FAST的提出者Rosten等將FAST角點定義為:若某畫素與其周圍鄰域內足夠多的畫素點相差較大,則該畫素可能是角點。

FAST演算法的步驟


1、上圖所示,一個以畫素p為中心,半徑為3的圓上,有16個畫素點(p1、p2、...、p16)。

2、定義一個閾值。計算p1、p9、p5、p13與中心p的畫素差,若它們的絕對值有至少3個超過閾值,則當做候選角點,再進行下一步考察;否則,不可能是角點;

3、若p是候選點,則計算p1到p16這16個點與中心p的畫素差,若它們有至少連續9個超過閾值,則是角點;否則,不可能是角點。

4、對影象進行非極大值抑制:計算特徵點出的FAST得分值(即score值,也即s值),判斷以特徵點p為中心的一個鄰域(如3x3或5x5)內,計算若有多個特徵點,則判斷每個特徵點的s值(16個點與中心差值的絕對值總和),若p是鄰域所有特徵點中響應值最大的,則保留;否則,抑制。若鄰域內只有一個特徵點(角點),則保留。得分計算公式如下(公式中用V表示得分,t表示閾值):


       上面是FAST-9,當然FAST-10、FAST-11、FAST-12也是一樣的,只是步驟3中,超過閾值的個數不一樣。FAST演算法實現起來簡單,尤其是以速度快著稱。

       以上便是FAST特徵檢測的過程,清晰明瞭,而對於角點的定義也是做到了返璞歸真,大師就是大師,還原本質的能力很強,估計以前這種簡單想法被很多人忽略了。

實驗

opencv程式碼

#include <opencv2/core/core.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <cv.h>
#include <vector>

using namespace cv;
using namespace std;

int main()
{
	Mat frame=imread("lena.jpg", 1);
	double t = getTickCount();//當前滴答數
	std::vector<KeyPoint> keyPoints;
	FastFeatureDetector fast(50);	// 檢測的閾值為50

	fast.detect(frame, keyPoints);
	drawKeypoints(frame, keyPoints, frame, Scalar(0,0,255), DrawMatchesFlags::DRAW_OVER_OUTIMG);
	
	t = ((double)getTickCount() - t)/getTickFrequency();
	cout<<"演算法用時:"<<t<<"秒"<<endl;

	imshow("FAST特徵點", frame);
	cvWaitKey(0);

	return 0;
}
輸出結果:

MATLAB程式碼

再上一個自己編寫的MATLAB程式碼,沒有進行非極大值抑制,效果不及opencv,而且檢測出的角點有一定的出入,應該是opencv內部做了一定的優化。

clear all;
close all;
%%
pic=imread('lena.jpg');
img=pic;
[M N D]=size(pic);
if D==3
    pic=rgb2gray(pic);
end
%%
mask=[0 0 1 1 1 0 0;...
      0 1 0 0 0 1 0;...
      1 0 0 0 0 0 1;...
      1 0 0 0 0 0 1;...
      1 0 0 0 0 0 1;...
      0 1 0 0 0 1 0;...
      0 0 1 1 1 0 0];
mask=uint8(mask);
threshold=50;
figure;imshow(img);title('FAST角點檢測');hold on;
tic;
for i=4:M-3
    for j=4:N-3%若I1、I9與中心I0的差均小於閾值,則不是候選點
        delta1=abs(pic(i-3,j)-pic(i,j))>threshold;
        delta9=abs(pic(i+3,j)-pic(i,j))>threshold;
        delta5=abs(pic(i,j+3)-pic(i,j))>threshold;
        delta13=abs(pic(i,j-3)-pic(i,j))>threshold;
        if sum([delta1 delta9 delta5 delta13])>=3
            block=pic(i-3:i+3,j-3:j+3);
            block=block.*mask;%提取圓周16個點
            pos=find(block);
            block1=abs(block(pos)-pic(i,j))/threshold;
            block2=floor(block1);
            res=find(block2);
            if size(res,1)>=12
                plot(j,i,'ro');
            end
        end
    end
end
toc;
%%
輸出結果:


參考文獻

1、Machine learning for high-speed corner detection[J],2006.

2、Features From Accelerated Segment Test[J],2010.

3、基於自適應閾值的FAST特徵點提取演算法[J],2013