Opencv图像识别从零到精通(34)---SIFI

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_20823641/article/details/52300214

一、理论知识

  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,欢迎图像识别与图像算法,共同学习与交流


猜你喜欢

转载自blog.csdn.net/qq_20823641/article/details/52300214