OpenCV检测图像SURF特征

来源:互联网 发布:画卡通头像的软件 编辑:程序博客网 时间:2024/04/30 20:14

SURF特征

SURF特征——speeded up robust features 加速鲁棒特征。具有尺度不变性,计算相对高效。
所谓尺度不变性,在特征点匹配上,个人比较白话的理解是:
相同内容的不同尺度的两张图片(例,图像1:张三的正面照。图像2:张三正面照缩小一半。)。
假设两张图片上张三的鼻子中心是一个特征点,那么这两张图片,在该点处的SURF特征,应该相互匹配(确切说是SURF特征描述子匹配)。也就是说,大小变化,特征匹配不变。不管物体大小如何变化,同一物体在不同大小下具有的SURF特征,这些特征点(描述子)相互匹配。
SURF特征,具有尺寸和方向,使其具有方向不变性和尺寸不变性。
该博客讲了SURF特征原理,可以参看。
http://www.cnblogs.com/tornadomeet/archive/2012/08/17/2644903.html
这里只简单讲下,SURF特征,大体是怎么回事

SURF特征,定义特征点为具有较高局部曲率的点。
怎么计算局部曲率?通过Hessian矩阵。
这里写图片描述
该矩阵的行列式给出了曲率的强度,也就是,矩阵的行列式越大,曲率强度越高。具体计算特征点时,要考虑用不同尺寸高斯核滤波产生的金塔字上下层的曲率值,用当前层某点的曲率值,和本层、上层、下层一定范围进行比较。(说起来好麻烦,具体的看SURF算法,网上很多资料)。
特征怎么具有尺寸不变性?
SURF,通过对图片用不同尺寸的高斯核滤波,然后计算其Hessian矩阵(类似高斯金字塔,但图像的尺寸不变)。实际应用中,为了加快计算速度,常常用近似的高斯核,直接计算Hessian矩阵中的值。
对y二阶导相当于:
这里写图片描述
对xy二阶导相当于:
这里写图片描述
这样,不同尺寸高斯核下的Hessian矩阵,便计算出来。
为了说明白尺寸不变,以下是个人的简单理解,可能跟算法实际过程不同(仅为好理解,勿喷)
1、一张图片,在尺寸为NxN的高斯核下,检测到了一个SURF特征点。那么这个检测到的特征点,与N成正比,也可以说特征点的尺寸与N成正比。
2、假设,图片缩小一半,拍摄角度不变。那么在尺寸为(N/2)的高斯核下,检测到一个SURF特征点(同1,为同一物体的同一点)。该特征点的尺寸与N/2成正比。
也就是说,当图像缩减一半时,该特征点的尺寸也缩减一半。那么在匹配这两个不同尺度的特征点时,由于考虑到了尺寸的变化(原来的1/2),那么匹配时,他们的强度模版就不会出错。(再简单的理解,计算特征点的描述子时,由于不了解物体尺寸的变换,所以往往会出错。但是,SURF特征包含了尺寸变化的信息,从而让同一物体的同一点在不同尺寸下的SURF特征(点)描述子(向量)相互匹配)
这里,只讲了SURF个人的大体理解,其实我看该算法时也挺蒙,有些地方来回看了几遍。个人理解肯定由疏漏、不准确的地方,推荐去系统学习一下SURF详细原理。
示例:

#include<opencv2\core\core.hpp>#include<opencv2\imgproc\imgproc.hpp>#include<opencv2\highgui\highgui.hpp>#include<opencv2\features2d\features2d.hpp>#include <opencv2/nonfree/features2d.hpp>#include<opencv2\legacy\legacy.hpp>#include <opencv2/nonfree/nonfree.hpp>#include<iostream>int main(){    //两张同一物体,不同尺寸的图片    cv::Mat image = cv::imread("D:/images/church01.jpg");    cv::Mat image1 = cv::imread("D:/images/church03.jpg");    ///计算SURF特征点    std::vector<cv::KeyPoint> pts;    std::vector<cv::KeyPoint> pts1;    //定义SURF特征检测类 对象,阈值设置为2500    cv::SurfFeatureDetector surf(2500.);    surf.detect(image, pts);    surf.detect(image1, pts1);    ///提取SURF特征点的描述子    cv::SurfDescriptorExtractor surfD;    //特征点集合的描述子以矩阵形式保存    cv::Mat descri;    cv::Mat descri1;    surfD.compute(image, pts, descri);    surfD.compute(image1, pts1, descri1);    //利用描述子,匹配两张图像中的SURF特点    cv::BruteForceMatcher<cv::L2<float>>mather;    std::vector<cv::DMatch>matches;    //matches,保存匹配结果    mather.match(descri, descri1, matches);    //选取匹配值最高的25个点    std::nth_element(matches.begin(), matches.begin() + 24, matches.end());    matches.erase(matches.begin() + 25, matches.end());    //画出匹配图像    cv::Mat imageMatches;    cv::drawMatches(image, pts, image1, pts1,        matches, imageMatches, cv::Scalar(255, 0, 0));    //显示结果    cv::namedWindow("Match", CV_WINDOW_FREERATIO);    cv::imshow("Match", imageMatches);    cv::waitKey(0);    return 0;}

这里写图片描述

0 0
原创粉丝点击