1. 程式人生 > >Fast檢測角點算法

Fast檢測角點算法

gui 手冊 所有 cto names [] 使用 是否 show

1.角點定義

  角點是一種局部特征,具有旋轉不變性和不隨光照條件變化而變化的特點,一般將圖像中曲率足夠高或者曲率變化明顯的點作為角點。檢測得到的角點特征通常用於圖像匹配、目標跟蹤、運動估計等方面。

2.Fast檢測角點

1)基本思想

  E.Rosten和T.Drummond兩位大佬在06年一篇文章中提出了FAST特征算法,基本思想十分簡單:以某個像素點為圓心,某半徑的圓周上其他像素點與圓心像素點特性差異達到某種標準時即認為該點就是角點。

2)數學模型

  技術分享

  經過測試發現,選取的圓形半徑為3時可以兼顧檢測結果和效率。如上圖所示,點p與半徑為3的圓周上的16個像素點比較其灰度差,若灰度差絕對值大於某閾值的點數超過設定數目(一般可以取9/10/11/12),則認為該點是角點。

使用小技巧加速該算法,這裏取設定數目為12。

  (1)判斷點1和點9灰度值與點p差值絕對值是否都大於閾值,如果是則繼續;否則pass該點

(2)判斷點1、點5、點9、點13四點與點p灰度值差值大於閾值的數目是否大於2,如果是則繼續;否則pass該點

(3)判斷圓周上16點與點p灰度值差值大於閾值的數目是否不小於12,如果是則認為該點是候選點;否則pass該點

  對圖像中所有像素點進行上述操作後,得到候選點點集。通常使用非極大值抑制過濾局部非極大值點,在這之前需要先計算各候選點的score,score就定義為16個點與中心點灰度值差值的絕對值總和

3.opencv實現

個人使用vs2012+opencv2.4.13作為開發環境,具體實現如下

  1 #include <iostream>
  2 #include <core/core.hpp>
  3 #include <highgui/highgui.hpp>
  4 #include <imgproc/imgproc.hpp>
  5 #include <features2d/features2d.hpp>
  6 
  7 using namespace std;
  8 using namespace cv;
  9 
 10 
 11
int getSum(uchar *p, int length) 12 { 13 int sum = 0; 14 for(int i=0;i<length; i++) 15 { 16 sum += *(p+i); 17 } 18 return sum; 19 } 20 21 int main(int argc, char* argv[]) 22 { 23 /* 1.讀入圖像 */ 24 Mat image = imread("../church01.jpg", 0); 25 if(!image.data) 26 return 0; 27 28 namedWindow("Original Image"); 29 imshow("Original Image", image); 30 31 Mat fastImg(image.size(), CV_8U, Scalar(0));//用於保存Fast特征點候選點 32 Mat fastScore(image.size(), CV_32F, Scalar(0));//用於計算候選點score 33 vector<Point> points; 34 int rows, cols, threshold; 35 rows = image.rows; 36 cols = image.cols; 37 threshold = 50; 38 39 /* 2.檢測Fast特征點 */ 40 for(int x = 3; x < rows - 3; x++) 41 { 42 for(int y = 3; y < cols - 3; y++) 43 { 44 uchar delta[16] = {0}; 45 uchar diff[16] = {0}; 46 delta[0] = (diff[0] = abs(image.at<uchar>(x,y) - image.at<uchar>(x, y-3))) > threshold; 47 delta[8] = (diff[8] = abs(image.at<uchar>(x,y) - image.at<uchar>(x, y+3))) > threshold; 48 if(getSum(delta, 16) == 0) 49 continue; 50 else 51 { 52 delta[12] = (diff[12] = abs(image.at<uchar>(x,y) - image.at<uchar>(x-3, y))) > threshold; 53 delta[4] = (diff[4] = abs(image.at<uchar>(x,y) - image.at<uchar>(x+3, y))) > threshold; 54 if(getSum(delta, 16) < 3) 55 continue; 56 57 else 58 { 59 delta[1] = (diff[1] = abs(image.at<uchar>(x,y) - image.at<uchar>(x+1, y-3))) > threshold; 60 delta[2] = (diff[2] = abs(image.at<uchar>(x,y) - image.at<uchar>(x+2, y-2))) > threshold; 61 delta[3] = (diff[3] = abs(image.at<uchar>(x,y) - image.at<uchar>(x+3, y-1))) > threshold; 62 63 delta[5] = (diff[5] = abs(image.at<uchar>(x,y) - image.at<uchar>(x+3, y+1))) > threshold; 64 delta[6] = (diff[6] = abs(image.at<uchar>(x,y) - image.at<uchar>(x+2, y+2))) > threshold; 65 delta[7] = (diff[7] = abs(image.at<uchar>(x,y) - image.at<uchar>(x+1, y+3))) > threshold; 66 67 delta[9] = (diff[9] = abs(image.at<uchar>(x,y) - image.at<uchar>(x-1, y+3))) > threshold; 68 delta[10] = (diff[10] = abs(image.at<uchar>(x,y) - image.at<uchar>(x-2, y+2))) > threshold; 69 delta[11] = (diff[11] = abs(image.at<uchar>(x,y) - image.at<uchar>(x-3, y+1))) > threshold; 70 71 delta[13] = (diff[13] = abs(image.at<uchar>(x,y) - image.at<uchar>(x-3, y-1))) > threshold; 72 delta[14] = (diff[14] = abs(image.at<uchar>(x,y) - image.at<uchar>(x-2, y-2))) > threshold; 73 delta[15] = (diff[15] = abs(image.at<uchar>(x,y) - image.at<uchar>(x-1, y-3))) > threshold; 74 75 if(getSum(delta, 16) >= 12) 76 { 77 points.push_back(Point(y,x)); 78 fastScore.at<float>(x,y) = getSum(diff, 16); 79 fastImg.at<uchar>(x,y) = 255; 80 } 81 } 82 } 83 } 84 85 } 86 87 vector<Point>::const_iterator itp = points.begin(); 88 while(itp != points.end()) 89 { 90 circle(image, *itp, 3, Scalar(255), 1); 91 ++itp; 92 } 93 //未進行非極大值抑制之前的特征點檢測結果 94 namedWindow("Fast Image"); 95 imshow("Fast Image", image); 96 97 /* 3.對特征點候選點進行非極大值抑制 */ 98 image = imread("../church01.jpg", 0); 99 Mat dilated(fastScore.size(), CV_32F, Scalar(0)); 100 Mat localMax; 101 Mat element(7, 7, CV_8U, Scalar(1)); 102 dilate(fastScore, dilated, element); 103 compare(fastScore, dilated, localMax, CMP_EQ); 104 bitwise_and(fastImg, localMax, fastImg); 105 106 for(int x = 0;x < fastImg.cols; x++) 107 { 108 for(int y = 0; y < fastImg.rows; y++) 109 { 110 if(fastImg.at<uchar>(y,x)) 111 { 112 circle(image, Point(x,y), 3, Scalar(255), 1); 113 114 } 115 } 116 } 117 //進行非極大值抑制之後的特征點檢測結果 118 namedWindow("Fast Image2"); 119 imshow("Fast Image2", image); 120 121 waitKey(); 122 return 0; 123 }

  代碼運行結果如下,比較第2/3張圖可以發現,非極大值抑制具有過濾掉局部區域中非極大值角點的作用。

技術分享技術分享技術分享

4.算法小結

該算法思想簡單,運算量很小,適合實時檢測方面的應用。不過也有缺點,主要表現為對於邊緣點與噪點區分能力不強,當然後面也有很多人在此基礎上加以改進提高算法的穩定性。

5.參考文獻

[1]《opencv2計算機視覺編程手冊》

[2]【特征檢測】FAST特征檢測算法(http://blog.csdn.net/hujingshuang/article/details/46898007)

Fast檢測角點算法