2013年5月22日 星期三

EmguCV Image Process: Detecting and Matching Interest Points part4

20101219030.jpg
EmguCV Image Process: Detecting and Matching Interest Points

參考OpenCV 2 Computer Vision Application Programming Cookbook第八章

介紹內容如下:

Detecting Harris corners

Detecting FAST features

Detecting the scale-invariant SURF features

Describing SURF features

上一篇介紹了FAST features detection

而當我們試著要去配對不同影像上的特徵(features)時

會遇到一個問題:尺度(scale)的變化

在不同的影像上

感興趣的物件之間的距離可能有所不同

大小也可能有所不同

如果這時去試著配對不同影像的相同特徵時

由於尺度的變化,以至於在亮度(intensity)上的特徵是無法配對的


為了解決這個問題

許多尺度不變性(scale-invariant)的特徵概念被提出來

而SIFT(Scale-Invariant Feature Transform)就是屬於其中一種

其偵測局部最大值(local maxima)的特徵

並且使用Laplacian filter作為特徵的擷取(blob detection)

在EmguCV 2.4.2上有直接實作此方法
(2.4.0以前的版本建構式的引數有所不同)

使用起來相當簡單

Image<Gray, Byte> image = new Image<Gray, byte>(@"E:\EmguCVBlogImage\chapter8\image.jpg");
//Construct the SIFT feature detector object
SIFTDetector sift = new SIFTDetector(
    0,  //the desired number of features
    3,    //the number of octave layers
    0.04, //feature threshold
    10,   //detector parameter
    1.6); //sigma
//feature point detection
VectorOfKeyPoint keypoints = sift.DetectKeyPointsRaw(image, null);
//draw keypoints on an image
Image<Bgr, byte> result = Features2DToolbox.DrawKeypoints<Gray>(
    image,     //original image
    keypoints, //vector of keypoints 
    new Bgr(255, 255, 255), // keypoint color
    Features2DToolbox.KeypointDrawType.DRAW_RICH_KEYPOINTS); //drawing type
先建立SIFT的類別

建構式帶入的參數分別是:

要偵測的特徵數量(0表示不限制)

octave稱之為高斯影像金字塔,在這裡設定每組金字塔內由多少張影像組成

特徵偵測的閥值,初始值為0.04

邊界偵測的閥值,初始值為10

sigma通常以\sigma做為表示,其實作的意義就是filter的aperture size

這裡還有一點提醒

在Features2DToolbox.DrawKeypoints的方法中

繪圖的類型選擇是:Features2DToolbox.KeypointDrawType.DRAW_RICH_KEYPOINTS

其結果如下:

除了特徵點的位置外,還多了特徵點的方向和大小的表示


而關於SIFT的演算法其實非常的複雜

wiki上有蠻詳細的介紹可以參考

不過我想wiki上的內容是沒多少人看得懂的

而這篇網誌用中文+圖解介紹的SIFT演算法相當清楚,比較適合參考

由於SIFT的演算法的運算量太過複雜

以至於有人提出了SURF(Speeded Up Robust Features)演算法

此方法提升了原本SIFT的效率

原先SIFT在建立高斯影像金字塔時相當耗時

而SURF採用了近似Hessian的矩陣對每一個pixel作摺積(Convolution)

得到近似的高斯模糊的影像,因而提升了速度

使用方法也很簡單

Image<Gray, Byte> image = new Image<Gray, byte>(@"E:\EmguCVBlogImage\chapter8\image.jpg");
//Construct the SURF feature detector object
SURFDetector surf = new SURFDetector(
    5000,   //threshold
    false); //extended descriptors
//Detect the SURF features
VectorOfKeyPoint keypoints = surf.DetectKeyPointsRaw(image, null);
//draw keypoints on an image
Image<Bgr, byte> result = Features2DToolbox.DrawKeypoints<Gray>(
    image,     //original image
    keypoints, //vector of keypoints 
    new Bgr(255, 255, 255), // keypoint color
    Features2DToolbox.KeypointDrawType.DRAW_RICH_KEYPOINTS); //drawing type
SURF建構式的參數只有兩個

一個是threshold,emguCV的文件上說300~500,在這張影像上5000比較適合

第二個參數表示是否要採用擴充的描述子,這個會在下一篇介紹

所以先採用false

出來的結果如下:

所偵測出來的特徵值還蠻多的

為了要測試旋轉、尺度的不變性

所以製作了另一張圖

這裡試著把影像作一些放大和旋轉

一樣帶入程式中

看會得到什麼樣的結果

與原本的結果做比較

大部分的特徵點的位置、大小、方向是雷同的

但也有些許是不一樣的

那如何利用這些特徵點

就等下一篇來介紹嚕!!

4 則留言:

  1. 作者已經移除這則留言。

    回覆刪除
    回覆
    1. 可以不用做預處理,直接把原始影像帶入即可.
      但如果想要有特別被偵測到的特徵值,或許可以考慮先進行預處理的動作.

      刪除
  2. 請問我目前使用C#可以找到特徵點個數,我要怎麼轉換成位置座標或是把特徵點圈或框出來?

    回覆刪除
    回覆
    1. VectorOfKeyPoint keypoints = surf.DetectKeyPointsRaw(image, null);
      出來的keypoints就是一個point的集合,裡面就有包含point的座標位置。

      刪除