前面描述角點檢測的時候說到,角點其實也是一種圖像特徵點,對於一張圖像來講,特徵點分爲三種形式包括邊緣,焦點和斑點,在OPENCV中,加上角點檢測,總共提供瞭如下的圖像特徵點檢測方法算法
接下來分別講述這是一種圖像特徵檢測算法,可是首先,須要瞭解OPENCV的一種數據結構, KeyPoint結構,該結構的頭文件定義以下:數據結構
class KeyPoint函數
{測試
Point2f pt; //該圖像特徵點的座標3d
float size; //特徵點鄰域直徑orm
float angle; //特徵點的方向,值爲[零,三百六十),負值表示不使用,有了這個方向,可以讓特徵點擁有更高的辨識度,不然僅僅座標和直徑有時會誤判特徵點視頻
float response;//響應程度,表明該點的強壯程度,也就是該點角點程度,用於後期使用和排序blog
int octave; //特徵點所在的圖像金字塔的組排序
int class_id; //用於聚類的id接口
}
每一個圖像特徵點檢測算法最終的目標之一,而當一張圖像的特徵點被檢測出來以後,就能夠和另外一張圖像的特徵點進行匹配,根據類似級別斷定兩個圖像的類似程度.
好比咱們能夠在圖像中檢測一張人臉的特徵點,從而來檢索在另外一張圖中是否存在類似程度很高的特徵點集,從而確認另外一張圖像中的人臉以及人臉的位置,等,特徵點檢測算法在物體檢測,視覺跟蹤,3D重建的時候都有着重要的做用.
一. 圖像特徵點檢測的通用接口
Opencv爲了方便用戶使用圖像特徵點檢測的相應算法,將所有的特徵點檢測都封在一個相似的API中,名爲Ptr的模板類,也就是說,全部的特徵檢測算法都實現了相同的藉口,detect 檢測圖像特徵點.使用方法相似於
Ptr<相應的特徵點檢測類名>變量名 = 相應的特徵點檢測類::create()
變量名->detect(原圖像,特徵點向量).
使用上面描述的算法,就能夠調用幾乎所有的圖像特徵檢測算法.可是注意,create函數有多個重載函數,若是爲空,每一個圖像檢測算法都會使用本身的一套默認的初始值來初始化類,若是想修改參數,那麼create函數調用的時候須要根據檢測類的不一樣,設置不一樣的初始化變量.
另外,opencv提供而一個快速顯示圖像特徵點的函數,以下
drawKeyPoints(畫布圖像,特徵點向量集,輸出的繪製結果,繪製顏色值,繪製模式)
通常來講,畫布圖像會使用咱們檢測特徵點的原圖像(通常檢測特徵點都是原圖像變換爲灰度圖像以後進行的檢測,簡單算法複雜度).
繪製模式有如下方法能夠選擇,是DrawMatchesFlags枚舉
DEFAULT:只繪製特徵點的座標點,顯示在圖像上就是一個個小圓點,每一個小圓點的圓心座標都是特徵點的座標.
DRAW_OVER_OUTIMG:函數不建立輸出的圖像,而是直接在輸出圖像變量空間繪製,要求自己輸出圖像變量就是一個初始化好了的,size與type都是已經初始化好的變量
NOT_DRAW_SINGLE 單點的特徵點不被繪製
DRAW_RICH_KEYPOINT 繪製特徵點的時候繪製的是一個個帶有方向的圓,這種方法同時顯示圖像的座標,size,和方向,是最能顯示特徵的一種繪製方式,可是缺點就是繪製結果太雜亂.
FAST算法是基於角點檢測的圖像特徵.
一個特徵點檢測的算法的第一步是定義什麼是特徵點,FAST算法定義特徵點是若是某個像素點和他周圍領域足夠多的像素點處於不一樣區域,那麼這個像素點就是特徵點,對於灰度圖像來講,也就是該點的灰度值和其周圍足夠多的像素點的灰度值不一樣,那麼這個像素點就是一個特徵點.
該算法的詳細計算步驟以下
黑點座標爲(0,0),座標step爲1
以上就是快速特徵點檢測的原理,OPENCV中定義的快速特徵點檢測算法的檢測API以下
static Ptr<FastFeatureDetector> create( int threshold=10, bool nonmaxSuppression=true,
int type=FastFeatureDetector::TYPE_9_16 );
threshold是指比較時邊緣軌跡點和中心點的差值,也就是第三步的閾值t, nonmaxSuppression表明是否使用第五步非極大值抑制,若是發現fast檢測的結果有聚簇狀況,那麼能夠考慮採用,第三個參數type的取值來自於FastFeatureDetector枚舉,有以下取值:
綜上所述咱們能夠看出,FAST檢測算法沒有多尺度的問題,因此計算速度相對較快,可是當圖片中的噪點較多的時候,會產生較多的錯誤特徵點,健壯性並很差,而且, 算法的效果還依賴於一個閾值t。並且FAST不產生多尺度特徵並且FAST特徵點沒有方向信息,這樣就會失去旋轉不變性.可是在要求實時性的場合,好比視頻監控的物體識別,是可使用的.
使用代碼以下
//fast int main(int argc,char* argv[]) { Mat srcImage = imread("F:\\opencv\\OpenCVImage\\FeatureDetectSrc1.jpg"); Mat srcGrayImage; if (srcImage.channels() == 3) { cvtColor(srcImage,srcGrayImage,CV_RGB2GRAY); } else { srcImage.copyTo(srcGrayImage); } vector<KeyPoint>detectKeyPoint; Mat keyPointImage1,keyPointImage2; Ptr<FastFeatureDetector> fast = FastFeatureDetector::create(); fast->detect(srcGrayImage,detectKeyPoint); drawKeypoints(srcImage,detectKeyPoint,keyPointImage1,Scalar(0,0,255),DrawMatchesFlags::DRAW_RICH_KEYPOINTS); drawKeypoints(srcImage,detectKeyPoint,keyPointImage2,Scalar(0,0,255),DrawMatchesFlags::DEFAULT); imshow("src image",srcImage); imshow("keyPoint image1",keyPointImage1); imshow("keyPoint image2",keyPointImage2); imwrite("F:\\opencv\\OpenCVImage\\FeatureDetectSrc1FASTKeyPointImageDefault.jpg",keyPointImage2); waitKey(0); return 0; }