当尝试在不同图像之间进行特征匹配时,通常会遇到图像的大小、方向等参数发生改变的问题,简而言之,就是尺度变化的问题。每幅图像在拍摄时与目标物体的距离是不同的,因此要识别的目标物体在图像中自然会存在不同的尺寸。

因此,计算机视觉中引入尺度不变的特征,主要的思想是每个检测到的特征点都伴随对应的尺度因子。1999年David Lowe提出了著名的尺度不变特征检测器SIFT(Scale Invariant Feature Transform)算法,它具有尺度,旋转,仿射,视角,光照不变性。而加速鲁棒特性特征SURF(Speeded Up Robust Features)算法是SIFT的高效变种。这两个算法申请了专利保护,其专利的拥有者为英属哥伦比亚大学。

关于SIFT和SURF的特征介绍,已经有很多的blog对其进行简介了,见参考的blog。由于还没有将2004年那篇原文精细看完,因此这里只能粗浅地分析两种算法,并描述在OpenCV中如何实现这两种算法的特征检测。

一、基本概念

1.1 算法背景

尺度不变特征转换SIFT是一种著名的计算机视觉的算法,主要用来检测图像中的局部特征,通过在图像中寻找极值点特征,并提取出其这些特征点的位置、尺度和旋转不变量等信息。 
其应用范围包含物体辨识、机器人地图感知与导航、影像缝合、3D模型建立、手势辨识、影像追踪和动作比对。

局部影像特征的描述与侦测可以帮助辨识物体,SIFT 特征是基于物体上的一些局部外观的兴趣点而与影像的大小和旋转无关。对于光线、噪声、些微视角改变的容忍度也相当高。基于这些特性,它们是高度显著而且相对容易撷取,在母数庞大的特征数据库中,很容易辨识物体而且鲜有误认。使用 SIFT特征描述对于部分物体遮蔽的侦测率也相当高,甚至只需要3个以上的SIFT物体特征就足以计算出位置与方位。在现今的电脑硬件速度下和小型的特征数据库条件下,辨识速度可接近即时运算。SIFT特征的信息量大,适合在海量数据库中快速准确匹配。(来自百度百科的解释)

1.2 SIFT算法的主要优点

  1. SIFT特征是图像的局部特征,其对旋转、尺度缩放、亮度变化保持不变性,对视角变化、仿射变换、噪声也保持一定程度的稳定性;
  2. 独特性(Distinctiveness)好,信息量丰富,适用于在海量特征数据库中进行快速、准确的匹配;
  3. 多量性,即使少数的几个物体也可以产生大量的SIFT特征向量;
  4. 高速性,经优化的SIFT匹配算法甚至可以达到实时的要求;
  5. 可扩展性,可以很方便的与其他形式的特征向量进行联合。

1.3 SIFT算法的适用环境

目标的自身状态、场景所处的环境和成像器材的成像特性等因素影响图像配准/目标识别跟踪的性能。而SIFT算法在一定程度上可解决:

  1. 目标的旋转、缩放、平移(RST)
  2. 图像仿射/投影变换(视点viewpoint)
  3. 光照影响(illumination)
  4. 目标遮挡(occlusion)
  5. 杂物场景(clutter)
  6. 噪声

SIFT算法的实质是在不同的尺度空间上查找关键点(特征点),并计算出关键点的方向。SIFT所查找到的关键点是一些十分突出,不会因光照,仿射变换和噪音等因素而变化的点,如角点、边缘点、暗区的亮点及亮区的暗点等。

1.4 算法的基本步骤

Lowe将SIFT算法分解为如下四步:

  1. 尺度空间极值检测:搜索所有尺度上的图像位置。通过高斯微分函数来识别潜在的对于尺度和旋转不变的兴趣点。
  2. 关键点定位:在每个候选的位置上,通过一个拟合精细的模型来确定位置和尺度。关键点的选择依据于它们的稳定程度。
  3. 方向确定:基于图像局部的梯度方向,分配给每个关键点位置一个或多个方向。所有后面的对图像数据的操作都相对于关键点的方向、尺度和位置进行变换,从而提供对于这些变换的不变性。
  4. 特征点描述:在每个关键点周围的邻域内,在选定的尺度上测量图像局部的梯度。这些梯度被变换成一种表示,这种表示允许比较大的局部形状的变形和光照变化。

1.5 SIFT算法的缺点

SIFT算法十分强大,精度很高,Mikolajczyk和Schmid曾经针对不同的场景,对光照变化、图像几何变形、分辨率差异、旋转、模糊和图像压缩等6种情况,就多种最具代表性的描述子(如SIFT,矩不变量,互相关等10种描述子)进行了实验和性能比较,结果表明,在以上各种情况下,SIFT描述子的性能最好。但算法的高深同样带来了一些缺点,如:

  1. 实时性不高。
  2. 有时特征点较少。
  3. 对边缘光滑或经过平滑的图像无法准确提取特征点。

针对这些问题,一些改进算法应运而生,SURF就是广为人知的其中一种算法。

2.1 SURF算法介绍

SURF算法是SIFT算法的高效变种,在满足一定效果的情况下完成两幅图像中物体的匹配,并基本实现了实时处理。SURF也检测空间域和尺度域上的局部极大值作为特征,但是使用的是Hessian行列式响应而不是Laplacian行列式。

SURF的实现如下,首先对每个像素计算Hessian矩阵以得到特征,该矩阵测量一个函数的局部曲率,定义如下:

该矩阵的行列式给出曲率的强度,定义角点为具有较高局部曲率的像素点(即在多个方向都具有高曲率)。由于该函数是由二阶导数组成,因此可以使用不同的尺度的Laplacian Gaussian核进行计算,因此Hessian变成了三个变量的函数。当Hessian的值同时在空间域和尺度域上均达到局部极大值时(需要运行3*3*3的非极大值抑制),可以认为找到了尺度不变的特征。

所有这些不同尺度的运算都很耗时,而SURF算法的目的是尽可能高效。因此会使用近似的高斯核,仅涉及少量整数加法,结构如下图所示:

左侧的核用于估计混合二阶导数,右侧的核则用于估算垂直方向的二阶导数,而其旋转版本则用于估计水平方向的二阶导数。

一旦识别了局部极大值,每个特征点的精确位置可以通过空间域及尺度域上进行插值获取,结果是一组具有亚像素精确度的特征点,以及一个对应的尺度值。

2.2 性能比较

无需赘述,A comparison of SIFT, PCA-SIFT and SURF 一文给出了SIFT和SURF的性能比较,对原图像进行尺度、旋转、模糊、亮度变化、仿射变换等变化后,再与原图像进行匹配,统计匹配的效果,源图片来源于Graffiti dataset。

这里使用的开发平台是Qt5.3.2+OpenCV2.4.9。SURF、SIFT特征在OpenCV中的实现均使用了cv::FeatureDetector接口,OpenCV中的opencv_nonfree模块包含了SURF和SIFT的相关函数,因此在使用时注意添加相关的头文件。在这里,特征点的计算基于浮点核,因此这两种算法相比其他算法在空间和尺度检测上更加精确,但相对耗时。

至于理论部分有待进一步学习。

二、实现SIFT特征检测算法

直接在Qt中创建一个控制台项目,在main函数中添加:

#include <QCoreApplication>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/nonfree/nonfree.hpp>#include <QDebug>int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);// 读入图像cv::Mat image= cv::imread("c:/018.jpg",0);cv::namedWindow("Original Image");cv::imshow("Original Image", image);// 特征点的向量std::vector<cv::KeyPoint>keypoints;// 构造SIFT特征检测器cv::SiftFeatureDetector sift(0.03,  // 特征的阈值10.);  // 用于降低// 检测SIFT特征值sift.detect(image,keypoints);cv::drawKeypoints(image, // 原始图像keypoints, // 特征点的向量featureImage, // 生成图像cv::Scalar(255,255,255), // 特征点的颜色cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS); // 标志位cv::namedWindow("SIFT Features");cv::imshow("SIFT Features",featureImage);return a.exec();
}

效果如下,在函数cv::drawKeypoints中我们使用cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS作为标志位,这样唉使用DRAW_RICH_KEYPOINTS之后每个关键点上圆圈的尺寸与特征的尺度成正比:

三、实现SURF特征检测算法

#include <QCoreApplication>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/nonfree/nonfree.hpp>#include <QDebug>int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);// 读入图像cv::Mat image= cv::imread("c:/018.jpg",0);cv::namedWindow("Original Image");cv::imshow("Original Image", image);// 特征点的向量std::vector<cv::KeyPoint>keypoints;// 构造SURF特征检测器cv::SurfFeatureDetector surf(2500);// 检测SURF特征surf.detect(image,keypoints);cv::Mat featureImage;cv::drawKeypoints(image, // 原始图像keypoints, // 特征点的向量featureImage, // 生成图像cv::Scalar(255,255,255), // 特征点的颜色cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS); // 标志位cv::namedWindow("SURF Features");cv::imshow("SURF Features",featureImage);return a.exec();
}

效果:

从两种算法的输出结果可以看出,SURF与SIFT描述子的区别主要是速度及精度。SURF描述子大部分基于强度的差值,计算更加快捷,而SIFT描述子通常在搜索正确的特征点时更加精确。

参考资料:

David G.Lowe Object Recognition from Local Scale-Invariant Features. 1999.

David G.Lowe Distinctive Image Features from Scale-Invariant Keypoints. January 5, 2004.

SIFT官网的Rob Hess hess@eecs.oregonstate.edu SIFT源码

参考博客:

http://blog.csdn.net/zddblog/article/details/7521424 (个人认为是目前最详尽的SIFT介绍)

http://underthehood.blog.51cto.com/2531780/658350

http://blog.csdn.net/xiaowei_cqu/article/details/8069548

http://www.cnblogs.com/tornadomeet/archive/2012/08/16/2643168.html

OpenCV2学习笔记(十二):特征提取算法SIFT与SURF相关推荐

  1. 数字图像处理学习笔记(二):SIFT(尺度不变特征变换)算法

    数字图像处理学习笔记(二):SIFT(尺度不变特征变换)算法 一.概述: 提到特征点算法,首先就是大名鼎鼎的SIFT算法了.SIFT的全称是Scale Invariant Feature Transf ...

  2. 吴恩达《机器学习》学习笔记十二——机器学习系统

    吴恩达<机器学习>学习笔记十二--机器学习系统 一.设计机器学习系统的思想 1.快速实现+绘制学习曲线--寻找重点优化的方向 2.误差分析 3.数值估计 二.偏斜类问题(类别不均衡) 三. ...

  3. Python语言入门这一篇就够了-学习笔记(十二万字)

    Python语言入门这一篇就够了-学习笔记(十二万字) 友情提示:先关注收藏,再查看,12万字保姆级 Python语言从入门到精通教程. 文章目录 Python语言入门这一篇就够了-学习笔记(十二万字 ...

  4. OpenCV学习笔记(十二)——图像分割与提取

    在图像处理的过程中,经常需要从图像中将前景对象作为目标图像分割或者提取出来.例如,在视频监控中,观测到的是固定背景下的视频内容,而我们对背景本身并无兴趣,感兴趣的是背景中出现的车辆.行人或者其他对象. ...

  5. ROS学习笔记十二:使用roswtf

    ROS学习笔记十二:使用roswtf 在使用ROS过程中,roswtf工具可以为我们提供ROS系统是否正常工作的检查作用. 注意:在进行下列操作之前,请确保roscore没有运行. 检查ROS是否安装 ...

  6. Polyworks脚本开发学习笔记(十二)-输出和读取文本文件

    Polyworks脚本开发学习笔记(十二)-输出和读取文本文件 Polyworks作为一个测量工具,将测量的数据方便的导出到文本文件则是一项必须的功能.在DATA_FILE这个命令下提供了很多子命令用 ...

  7. Boost库学习笔记(二)算法模块-C++11标准

    Boost库学习笔记(二)算法模块-C++11标准 一.综述 Boost.Algorithm是一系列人通用推荐算法的集合,虽然有用的通用算法很多,但是为了保证质量和体积,并不会将太多通用算法通过审查测 ...

  8. 【现代机器人学】学习笔记十二:轮式移动机器人

    目录 轮式机器人类型 全向轮式机器人 建模 单个全向轮是怎么运动的 多个全向轮是如何带动底盘运动的 运动规划和反馈控制 非完整约束轮式移动机器人 建模 独轮车 差速驱动机器人 车型机器人 非完整移动机 ...

  9. Programming Computer Vision with Python (学习笔记十二)

    ORB(Oriented FAST and Rotated BRIEF)可用来替代SIFT(或SURF),它对图像更具有抗噪特性,是一种特征检测高效算法,其速度满足实时要求,可用于增强图像匹配应用. ...

最新文章

  1. 5个在线代码编辑器,供云计算爱好者
  2. 天线的安装对通信效果有什么影响?
  3. R语言学习笔记(三)多元数据的数据特征、相关分析与图形表示
  4. MyBatis -- 对表进行增删改查(基于注解的实现)
  5. 【CocoStudio游戏开发之一】制作多分辨率UI布局
  6. c语言读取含特定开头的文件,C#中获取指定路径下特定开头和后缀的所有文件
  7. 计算机硬件开票几个点,财务税控开票电脑装机配置清单和价格介绍
  8. linux 小度 驱动_arm-linux移植MT7601Uusb无线网卡(小度wifi,360随身WIFI 2代)
  9. 局域网怎么修改其它计算机ip,电脑局域网怎么更改ip
  10. protected使用总结
  11. 【转载】【《Real-Time Rendering 3rd》 提炼总结】(九) 第十章 · 游戏开发中基于图像的渲染技术总结
  12. python送程序员收入_程序员学Python后惊叹,这么丰厚的收入是Java给不了的!
  13. html5 indexeddb,关于使用HTML5提供的indexedDB的一下心得
  14. .avi文件转为.mp4
  15. 上海沙龙回顾 | ​字节跳动在Spark SQL上的核心优化实践
  16. 10.(leaflet之家)leaflet暗色系地图样式地图(滤镜实现,反色滤镜)
  17. spring security原理和机制 | Spring Boot 35
  18. mysql中返回上级_MySql 获取当前节点及递归所有上级节点
  19. 深度学习模型实战-深度学习模型在各大公司实际生产环境的应用讲解文章
  20. bpcs uploader.php,linux 百度云bpcs_uploader上传 下载 删除等操作

热门文章

  1. CSS3 3D旋转动画
  2. 读书随记——《傲慢与偏见》(2)
  3. hive窗口函数之排名函数row_number、rank和dense_rank
  4. C语言 计算e及e的次方的近似值
  5. Dreamweaver第一天 - 网站前期企划篇 - 网站企划概念
  6. GoView 开源,一个好用的 Vue3 低代码开发数据大屏系统
  7. rknn-toolkit 国内源链接
  8. HttpClient - fluent-hc 工具类
  9. matlab fis编辑器在哪,基本FIS编辑器
  10. MYSQl逻辑运算符(与运算、或运算、非运算、异或运算)