OpenCV中的SURF算法介绍
SURF:speed up robust feature,翻译为快速鲁棒特征。首先就其中涉及到的特征点和描述符做一些简单的介绍:
- 特征点和描述符
特征点分为两类:狭义特征点和广义特征点。狭义特征点的位置本身具有常规的属性意义,比如角点、交叉点等等。而广义特征点是基于区域定义的,它本身的位置不具备特征意义,只代表满足一定特征条件的特征区域的位置。广义特征点可以是某特征区域的任一相对位置。这种特征可以不是物理意义上的特征,只要满足一定的数学描述就可以,因而有时是抽象的。因此,从本质上说,广义特征点可以认为是一个抽象的特征区域,它的属性就是特征区域具备的属性;称其为点,是将其抽象为一个位置概念。
特征点既是一个点的位置标识,同时也说明它的局部邻域具有一定的模式特征。事实上,特征点是一个具有一定特征的局部区域的位置标识,称其为点,是将其抽象为一个位置概念,以便于确定两幅图像中同一个位置点的对应关系而进行图像匹配。所以在特征匹配过程中是以该特征点为中心,将邻域的局部特征进行匹配。也就是说在进行特征匹配时首先要为这些特征点(狭义和广义)建立特征描述,这种特征描述通常称之为描述符。
一个好的特征点需要有一个好的描述方法将其表现出来,它涉及到的是图像匹配的一个准确性。因此在基于特征点的图像拼接和图像配准技术中,特征点和描述符同样重要。
更多内容可参考:http://blog.sina.com.cn/s/blog_4b146a9c0100rb18.html
- OpenCv中SURF的demo
#include <stdio.h>
#include <iostream>
#include "opencv2/core/core.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/calib3d/calib3d.hpp" using namespace cv; void readme(); /** @function main */
int main( int argc, char** argv )
{
if( argc != )
{ readme(); return -; } Mat img_object = imread( argv[], CV_LOAD_IMAGE_GRAYSCALE );
Mat img_scene = imread( argv[], CV_LOAD_IMAGE_GRAYSCALE ); if( !img_object.data || !img_scene.data )
{ std::cout<< " --(!) Error reading images " << std::endl; return -; } //-- Step 1: Detect the keypoints using SURF Detector
int minHessian = ; SurfFeatureDetector detector( minHessian ); std::vector<KeyPoint> keypoints_object, keypoints_scene; detector.detect( img_object, keypoints_object );
detector.detect( img_scene, keypoints_scene ); //-- Step 2: Calculate descriptors (feature vectors)
SurfDescriptorExtractor extractor; Mat descriptors_object, descriptors_scene; extractor.compute( img_object, keypoints_object, descriptors_object );
extractor.compute( img_scene, keypoints_scene, descriptors_scene ); //-- Step 3: Matching descriptor vectors using FLANN matcher
FlannBasedMatcher matcher;
std::vector< DMatch > matches;
matcher.match( descriptors_object, descriptors_scene, matches ); double max_dist = ; double min_dist = ; //-- Quick calculation of max and min distances between keypoints
for( int i = ; i < descriptors_object.rows; i++ )
{ double dist = matches[i].distance;
if( dist < min_dist ) min_dist = dist;
if( dist > max_dist ) max_dist = dist;
} printf("-- Max dist : %f \n", max_dist );
printf("-- Min dist : %f \n", min_dist ); //-- Draw only "good" matches (i.e. whose distance is less than 3*min_dist )
std::vector< DMatch > good_matches; for( int i = ; i < descriptors_object.rows; i++ )
{ if( matches[i].distance < *min_dist )
{ good_matches.push_back( matches[i]); }
} Mat img_matches;
drawMatches( img_object, keypoints_object, img_scene, keypoints_scene,
good_matches, img_matches, Scalar::all(-), Scalar::all(-),
vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS ); //-- Localize the object
std::vector<Point2f> obj;
std::vector<Point2f> scene; for( int i = ; i < good_matches.size(); i++ )
{
//-- Get the keypoints from the good matches
obj.push_back( keypoints_object[ good_matches[i].queryIdx ].pt );
scene.push_back( keypoints_scene[ good_matches[i].trainIdx ].pt );
} Mat H = findHomography( obj, scene, CV_RANSAC ); //-- Get the corners from the image_1 ( the object to be "detected" )
std::vector<Point2f> obj_corners();
obj_corners[] = cvPoint(,); obj_corners[] = cvPoint( img_object.cols, );
obj_corners[] = cvPoint( img_object.cols, img_object.rows ); obj_corners[] = cvPoint( , img_object.rows );
std::vector<Point2f> scene_corners(); perspectiveTransform( obj_corners, scene_corners, H); //-- Draw lines between the corners (the mapped object in the scene - image_2 )
line( img_matches, scene_corners[] + Point2f( img_object.cols, ), scene_corners[] + Point2f( img_object.cols, ), Scalar(, , ), );
line( img_matches, scene_corners[] + Point2f( img_object.cols, ), scene_corners[] + Point2f( img_object.cols, ), Scalar( , , ), );
line( img_matches, scene_corners[] + Point2f( img_object.cols, ), scene_corners[] + Point2f( img_object.cols, ), Scalar( , , ), );
line( img_matches, scene_corners[] + Point2f( img_object.cols, ), scene_corners[] + Point2f( img_object.cols, ), Scalar( , , ), ); //-- Show detected matches
imshow( "Good Matches & Object detection", img_matches ); waitKey();
return ;
} /** @function readme */
void readme()
{ std::cout << " Usage: ./SURF_descriptor <img1> <img2>" << std::endl; }
有了对特征点和描述符的简单认识后,对上述代码就能有更好的理解了。
- SURF算法的具体实现过程
整理了网上的一些资料:
- surf算法原理,有一些简单介绍(1)
http://blog.csdn.net/andkobe/article/details/5778739
2. surf算法原理,有一些简单介绍(2)
http://wuzizhang.blog.163.com/blog/static/78001208201138102648854/
3 . 特征点检测学习_2(surf算法)
http://www.cnblogs.com/tornadomeet/archive/2012/08/17/2644903.html
- 其他
// DMatch function
DMatch(int queryIdx, int trainIdx, float distance)
其中 queryIdx 和 trainIdx 对应的特征点索引由match 函数决定,例如:
// 按如下顺序使用
match(descriptor_for_keypoints1, descriptor_for_keypoints2, matches)
则queryIdx 和 trainIdx分别对应keypoints1和keypoints2。
2013-11-05
OpenCV中的SURF算法介绍的更多相关文章
- OpenCV学习(22) opencv中使用kmeans算法
kmeans算法的原理参考:http://www.cnblogs.com/mikewolf2002/p/3368118.html 下面学习一下opencv中kmeans函数的使用. 首先我们 ...
- OpenCV学习(35) OpenCV中的PCA算法
PCA算法的基本原理可以参考:http://www.cnblogs.com/mikewolf2002/p/3429711.html 对一副宽p.高q的二维灰度图,要完整表示该图像,需要m = ...
- Opencv中使用Surf特征实现图像配准及对透视变换矩阵H的平移修正
图像配准需要将一张测试图片按照第二张基准图片的尺寸.角度等形态信息进行透视(仿射)变换匹配,本例通过Surf特征的定位和匹配实现图像配准. 配准流程: 1. 提取两幅图像的Surf特征 2. 对Sur ...
- openCV中直方图均衡化算法的理解
直方图均衡化就是调整灰度直方图的分布,即将原图中的灰度值映射为一个新的值.映射的结果直观表现是灰度图的分布变得均匀,从0到255都有分布,不像原图那样集中.图像上的表现就是对比度变大,亮的更亮,暗的更 ...
- Opencv中K均值算法(K-Means)及其在图像分割中的应用
K均值(K-Means)算法是一种无监督的聚类学习算法,他尝试找到样本数据的自然类别,分类是K由用户自己定义,K均值在不需要任何其他先验知识的情况下,依据算法的迭代规则,把样本划分为K类.K均值是最常 ...
- OpenCV中Delaunay三角网算法例子
#include <opencv2/opencv.hpp> #include <vector> using namespace cv; using namespace std; ...
- c++opencv中线条细化算法
要达到的效果就是将线条尽量细化成单像素,按照论文上的Hilditch算法试了一下,发现效果不好,于是自己尝试着写了一下细化的算法,基本原理就是从上下左右四个方向向内收缩. 1.先是根据图片中的原则确定 ...
- 图像处理之 opencv 学习---opencv 中的常用算法
http://blog.csdn.net/lindazhou2005/article/details/1534234 文中有提到鲁棒性 http://blog.csdn.net/chary8088/a ...
- 在OpenCV for Android 2.4.5中使用SURF(nonfree module)
http://blog.csdn.net/ruifdu/article/details/9120559 在OpenCV4Android中没有nonfree module,因此也就没有了SURF和SIF ...
随机推荐
- 狗日的Javascript中的闭包
前面的话: 闭包,是 javascript 中重要的一个概念,对于初学者来讲,闭包是一个特别抽象的概念,特别是ECMA规范给的定义,如果没有实战经验,你很难从定义去理解它.下面是作者从作用域链慢慢讲到 ...
- inner join, left join ,right join 结果
假设有两个表结构如下: 表table1 表 table 2 内连接: --内连接 select * from table1 inner join table2 on table1.ID = table ...
- iOS开发学习 阶段过程简述
下面就简单介绍一下我iOS开发的感受,也是学习iOS开发的一个体系架构. 1 iOS开发环境 1.1 开发环境 标准的配置是Mac OS X + Xcode. MacOSX的话首选用苹果电脑,macm ...
- .NET中的CTS、CLS、CLR
一.解释1 1.CLR(Common Language Runtime) :公共语言运行库 CLR 是CTS(Common Type System:通用类型系统)的实现, 即是说:CLR是应用程序的执 ...
- solr6.6 配置同义词
1.配置managed-schema <fieldType name="text_mmseg4j_simple" class="solr.TextField&quo ...
- Java ArrayList的模拟实现
package test; import java.util.Arrays; import java.util.Collection; public class MyArrayList<E> ...
- non-compatible bean definition of same name and class
在整合struts2.1.6+spring2.5.6开发中,使用了注解和struts-convention来实现零配置管理.spring也使用注解annotation方式.现在的问题是:我在连个个不同 ...
- Android-RelativeLayout布局技巧(一)
如果有一个需求是这样的,在标题中的右上角有一个button <?xml version="1.0" encoding="utf-8"?> <L ...
- C语言面向对象编程(五):单链表实现(转)
这里实现的单链表,可以存储任意数据类型,支持增.删.改.查找.插入等基本操作.(本文提供的是完整代码,可能有些长.) 下面是头文件: #ifndef SLIST_H #define SLIST_H # ...
- cocos2d-x 3.1.1 学习笔记[11] http请求 + json解析
//http须要引入的头文件和命名空间 #include <network/HttpClient.h> using namespace network; //json须要引入的头文件 #i ...