Opencv圖像識別從零到精通(34)---SIFI

一、理論知識

  Scale Invariant Feature Transform,尺度不變特徵變換匹配算法,對於算法的理論介紹,可以參考這篇文章http://blog.csdn.net/qq_20823641/article/details/51692415,裏面很詳細,可以更好的學習。這裏就不多介紹。後面就挑選重點的來說

二、SIFT 主要思想

  SIFT算法是一種提取局部特徵的算法,在尺度空間尋找極值點,提取位置,尺度,旋轉不變量。

三、SIFT算法的主要特點:

 a) SIFT特徵是圖像的局部特徵,其對旋轉、尺度縮放、亮度變化保持不變性,對視角變化、仿射變換、噪聲也保持一定程度的穩定性。

b) 獨特性(Distinctiveness)好,信息量豐富,適用於在海量特徵數據庫中進行快速、準確的匹配[23]

c) 多量性,即使少數的幾個物體也可以產生大量SIFT特徵向量。

d) 高速性,經優化的SIFT匹配算法甚至可以達到實時的要求。

e) 可擴展性,可以很方便的與其他形式的特徵向量進行聯合。

四、SIFT算法步驟:

1)檢測尺度空間極值點

2)精確定位極值點

3)爲每個關鍵點指定方向參數

4)關鍵點描述子的生成

五、程序過程

  • 使用SiftFeatureDetector的detect方法檢測特徵存入一個向量裏,並使用drawKeypoints在圖中標識出來
  • SiftDescriptorExtractor 的compute方法提取特徵描述符,特徵描述符是一個矩陣
  • 使用匹配器matcher對描述符進行匹配,匹配結果保存由DMatch的組成的向量裏
  • 設置距離閾值,使得匹配的向量距離小於最小距離的2被才能進入最終的結果,用DrawMatch可以顯示 
六、函數簡介
SIFT::SIFT(int nfeatures=0, int nOctaveLayers=3, double contrastThreshold=0.04, double edgeThreshold=  10, double sigma=1.6)  

  • nfeatures:特徵點數目(算法對檢測出的特徵點排名,返回最好的nfeatures個特徵點)。
  • nOctaveLayers:金字塔中每組的層數(算法中會自己計算這個值,後面會介紹)。
  • contrastThreshold:過濾掉較差的特徵點的對閾值。contrastThreshold越大,返回的特徵點越少。
  • edgeThreshold:過濾掉邊緣效應的閾值。edgeThreshold越大,特徵點越多(被多濾掉的越少)。
  • sigma:金字塔第0層圖像高斯濾波係數,也就是σ。

void SIFT::operator()(InputArray img, InputArray mask, vector<KeyPoint>& keypoints, OutputArray  
descriptors, bool useProvidedKeypoints=false)

  • img:8bit灰度圖像
  • mask:圖像檢測區域(可選)
  • keypoints:特徵向量矩陣
  • descipotors:特徵點描述的輸出向量(如果不需要輸出,需要傳cv::noArray())。
  • useProvidedKeypoints:是否進行特徵點檢測。ture,則檢測特徵點;false,只計算圖像特徵描述
<p>class keyPoint{<span style="font-family: Arial;">Point2f pt;</span><span style="font-family: Arial;">float size;</span><span style="font-family: Arial;">float angle;</span><span style="font-family: Arial;">float response;i</span><span style="font-family: Arial;">nt octave;</span><span style="font-family: Arial;">int class_id;</span><span style="font-family: Arial;">}</span></p>

<span style="font-size:18px;">void drawMatches(const Mat&img1, const vector<KeyPoint>&keypoints1, const Mat&img2, const vector<KeyPoint>&keypoints2, 
const vector<DMatch>&matches1to2, Mat&outImg, const Scalar&matchColor=Scalar::all(-1), 
const Scalar&singlePointColor=Scalar::all(-1), const vector<char>&matchesMask=vector<char>(), 
intflags=DrawMatchesFlags::DEFAULT)</span>

Parameters:
  • img1 – 源圖像1
  • keypoints1 –源圖像1的特徵點.
  • img2 – 源圖像2.
  • keypoints2 – 源圖像2的特徵點
  • matches1to2 – 源圖像1的特徵點匹配源圖像2的特徵點[matches[i]] .
  • outImg – 輸出圖像具體由flags決定.
  • matchColor – 匹配的顏色(特徵點和連線),若matchColor==Scalar::all(-1),顏色隨機.
  • singlePointColor – 單個點的顏色,即未配對的特徵點,若matchColor==Scalar::all(-1),顏色隨機.
  • matchesMask – Mask決定哪些點將被畫出,若爲空,則畫出所有匹配點.
  • flags – Fdefined by DrawMatchesFlags.

七、函數注意事項

1.生成一個SiftFeatureDetector的對象,這個對象顧名思義就是SIFT特徵的探測器,用它來探測衣服圖片中SIFT點的特徵,存到一個KeyPoint類型的vector中,keypoint只是保存了opencv的sift庫檢測到的特徵點的一些基本信息,但sift所提取出來的特徵向量其實不是在這個裏面,特徵向量通過SiftDescriptorExtractor 提取,結果放在一個Mat的數據結構中。這個數據結構才真正保存了該特徵點所對應的特徵向量。
2.keypoint只是達到了關鍵點的位置,方向等信息,並無該特徵點的特徵向量,要想提取得到特徵向量就還要進行SiftDescriptorExtractor 的工作,建立了SiftDescriptorExtractor 對象後,通過該對象,對之前SIFT產生的特徵點進行遍歷,找到該特徵點所對應的128維特徵向量

八、示例

<span style="font-size:18px;">#include <opencv2/opencv.hpp>
#include <opencv2/features2d/features2d.hpp>
#include<opencv2/nonfree/nonfree.hpp>
#include<opencv2/legacy/legacy.hpp>
#include<vector>
using namespace std;
using namespace cv;
int main(int argc,uchar* argv[])
{
    const char* imagename = "hand1.jpg";
    //從文件中讀入圖像
    Mat img = imread(imagename);
    Mat img2=imread("hand3.jpg");
    //如果讀入圖像失敗
    if(img.empty())
    {
            fprintf(stderr, "Can not load image %s\n", imagename);
            return -1;
    }
    if(img2.empty())
    {
            fprintf(stderr, "Can not load image %s\n", imagename);
            return -1;
    }
    //顯示圖像
    imshow("image before", img);
    imshow("image2 before",img2);
     //sift特徵檢測
    SiftFeatureDetector  siftdtc;
    vector<KeyPoint>kp1,kp2;
    siftdtc.detect(img,kp1);
    Mat outimg1;
    drawKeypoints(img,kp1,outimg1);
    imshow("image1 keypoints",outimg1);
    KeyPoint kp;
    siftdtc.detect(img2,kp2);
    Mat outimg2;
    drawKeypoints(img2,kp2,outimg2);
    imshow("image2 keypoints",outimg2);
    SiftDescriptorExtractor extractor;
    Mat descriptor1,descriptor2;
    BruteForceMatcher<L2<float>> matcher;
    vector<DMatch> matches;
    Mat img_matches;
    extractor.compute(img,kp1,descriptor1);
    extractor.compute(img2,kp2,descriptor2);
    matcher.match(descriptor1,descriptor2,matches);
    drawMatches(img,kp1,img2,kp2,matches,img_matches);
    imshow("matches",img_matches);
    //此函數等待按鍵,按鍵盤任意鍵就返回
    waitKey();
    return 0;
}</span>




九、matlab

Demo Software: SIFT Keypoint Detector 代碼參考大牛的,網址如下

http://www.cs.ubc.ca/~lowe/keypoints/

i1=imread('hand1.jpg');  
i2=imread('hand3.jpg');  
i11=rgb2gray(i1);  
i22=rgb2gray(i2);  
imwrite(i11,'v1.jpg','quality',80);  
imwrite(i22,'v2.jpg','quality',80);  
match('v1.jpg','v2.jpg');  


http://www.cnblogs.com/cj695/p/4041478.html

http://blog.csdn.net/xiaowei_cqu/article/details/8069548
圖像識別算法交流 QQ羣:145076161,歡迎圖像識別與圖像算法,共同學習與交流


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