OPENCV图像特征点检测与FAST检测算法
前面描述角点检测的时候说到,角点其实也是一种图像特征点,对于一张图像来说,特征点分为三种形式包括边缘,焦点和斑点,在OPENCV中,加上角点检测,总共提供了以下的图像特征点检测方法
- FAST
- SURF
- ORB
- BRISK
- KAZE
- AKAZE
- MESR
- GFTT good feature to tack
- Bob斑点
- STAR
- AGAST
接下来分别讲述这是一种图像特征检测算法,但是首先,需要了解OPENCV的一种数据结构, KeyPoint结构,该结构的头文件定义如下:
class KeyPoint
{
Point2f pt; //该图像特征点的坐标
float size; //特征点邻域直径
float angle; //特征点的方向,值为[零,三百六十),负值表示不使用,有了这个方向,能够让特征点拥有更高的辨识度,否则仅仅坐标和直径有时会误判特征点
float response;//响应程度,代表该点的强壮程度,也就是该点角点程度,用于后期使用和排序
int octave; //特征点所在的图像金字塔的组
int class_id; //用于聚类的id
}
每个图像特征点检测算法最终的目标之一,而当一张图像的特征点被检测出来之后,就可以和另一张图像的特征点进行匹配,根据相似级别判定两个图像的相似程度.
比如我们可以在图像中检测一张人脸的特征点,从而来检索在另一张图中是否存在相似程度很高的特征点集,从而确认另一张图像中的人脸以及人脸的位置,等,特征点检测算法在物体检测,视觉跟踪,3D重建的时候都有着重要的作用.
一. 图像特征点检测的通用接口
Opencv为了方便用户使用图像特征点检测的相应算法,将全部的特征点检测都封在一个类似的API中,名为Ptr的模板类,也就是说,所有的特征检测算法都实现了相同的借口,detect 检测图像特征点.使用方法类似于
Ptr<相应的特征点检测类名>变量名 = 相应的特征点检测类::create()
变量名->detect(原图像,特征点向量).
使用上面描述的算法,就可以调用几乎全部的图像特征检测算法.但是注意,create函数有多个重载函数,如果为空,每个图像检测算法都会使用自己的一套默认的初始值来初始化类,如果想修改参数,那么create函数调用的时候需要根据检测类的不同,设置不同的初始化变量.
另外,opencv提供而一个快速显示图像特征点的函数,如下
drawKeyPoints(画布图像,特征点向量集,输出的绘制结果,绘制颜色值,绘制模式)
一般来说,画布图像会使用我们检测特征点的原图像(一般检测特征点都是原图像变换为灰度图像之后进行的检测,简单算法复杂度).
绘制模式有以下方法可以选择,是DrawMatchesFlags枚举
DEFAULT:只绘制特征点的坐标点,显示在图像上就是一个个小圆点,每个小圆点的圆心坐标都是特征点的坐标.
DRAW_OVER_OUTIMG:函数不创建输出的图像,而是直接在输出图像变量空间绘制,要求本身输出图像变量就是一个初始化好了的,size与type都是已经初始化好的变量
NOT_DRAW_SINGLE 单点的特征点不被绘制
DRAW_RICH_KEYPOINT 绘制特征点的时候绘制的是一个个带有方向的圆,这种方法同时显示图像的坐标,size,和方向,是最能显示特征的一种绘制方式,但是缺点就是绘制结果太杂乱.
一. FAST特征点检测算法
FAST算法是基于角点检测的图像特征.
一个特征点检测的算法的第一步是定义什么是特征点,FAST算法定义特征点是如果某个像素点和他周围领域足够多的像素点处于不同区域,那么这个像素点就是特征点,对于灰度图像来说,也就是该点的灰度值和其周围足够多的像素点的灰度值不同,那么这个像素点就是一个特征点.
该算法的详细计算步骤如下
- 从图片中选取一个坐标点,获取该点的像素值,接下来判定该点是否为特征点.
- 选取一个以选取点坐标为圆心的半径等于三的Bresenham圆(一个计算圆的轨迹的离散算法,得到整数级的圆的轨迹点),一般来说,这个圆上有16个点,如下所示

黑点坐标为(0,0),坐标step为1
- 现在选取一个阈值,假设为t,关键步骤,假设这16个点中,有N个连续的像素点,他们的亮度值与中心点的像素值的差大于或者小于t,那么这个点就是一个特征点.(n的取值一般取值12或者9,实验证明9可以取得更好的效果,因为可以获取更多的特征点,后面进行处理时,数据样本额相对多一些).
- 加入每个轨迹点都需要遍历的话,那么需要的时间比较长,有一种比较简单的方法可以选择,那就是仅仅检查在位置1,9,5和13四个位置的像素,首先检测位置1和位置9,如果它们都比阈值暗或比阈值亮,再检测位置5和位置13, 如果P" role="presentation" style="word-wrap: normal; max-width: none; max-height: none; min-width: 0px; min-height: 0px; float: none;" id="MathJax-Element-8-Frame">中心点是一个角点,那么上述四个像素点中至少有3个应该必须都大于Ip+t" role="presentation" style="word-wrap: normal; max-width: none; max-height: none; min-width: 0px; min-height: 0px; float: none;" id="MathJax-Element-9-Frame">中心点亮度值+阈值或者小于Ip−t" role="presentation" style="word-wrap: normal; max-width: none; max-height: none; min-width: 0px; min-height: 0px; float: none;" id="MathJax-Element-10-Frame">中心点亮度值-阈值,因为若是一个角点,超过四分之三圆的部分应该满足判断条件。如果不满足,那么p" role="presentation" style="word-wrap: normal; max-width: none; max-height: none; min-width: 0px; min-height: 0px; float: none;" id="MathJax-Element-11-Frame">中心点不可能是一个角点。对于所有点做上面这一部分初步的检测后,符合条件的将成为候选的角点,我们再对候选的角点,做完整的测试,即检测圆上的所有点.
- 但是,这种检测方法会带来一个问题,就是造成特征点的聚簇效应,多个特征点在图像的某一块重复高频率的出现,FAST算法提出了一种非极大值抑制的办法来消除这种情况,具体办法如下.
- 为每一个检测到的特征点计算它的响应大小(score function)VV。这里VV定义为中心点和它周围16个像素点的绝对偏差的和.
- 考虑两个相邻的特征点,并比较它们的VV值
- VV值较低的点将会被删除
以上就是快速特征点检测的原理,OPENCV中定义的快速特征点检测算法的检测API如下
static Ptr<FastFeatureDetector> create( int threshold=10, bool nonmaxSuppression=true,
int type=FastFeatureDetector::TYPE_9_16 );
threshold是指比较时边缘轨迹点和中心点的差值,也就是第三步的阈值t, nonmaxSuppression代表是否使用第五步非极大值抑制,如果发现fast检测的结果有聚簇情况,那么可以考虑采用,第三个参数type的取值来自于FastFeatureDetector枚举,有如下取值:
- TYPE_5_8 从轨迹中取8个点,当有5个点满足条件,就是特征点.
- TYPE_7_12 取轨迹12个点,7个满足条件,就是特征点.
- TYPE_9_16 取轨迹16个点,当9个满足条件,就是特征点.
综上所述我们可以看出,FAST检测算法没有多尺度的问题,所以计算速度相对较快,但是当图片中的噪点较多的时候,会产生较多的错误特征点,健壮性并不好,并且, 算法的效果还依赖于一个阈值t。而且FAST不产生多尺度特征而且FAST特征点没有方向信息,这样就会失去旋转不变性.但是在要求实时性的场合,比如视频监控的物体识别,是可以使用的.
使用代码如下
//fast
int main(int argc,char* argv[])
{
Mat srcImage = imread("F:\\opencv\\OpenCVImage\\FeatureDetectSrc1.jpg");
Mat srcGrayImage;
if (srcImage.channels() == 3)
{
cvtColor(srcImage,srcGrayImage,CV_RGB2GRAY);
}
else
{
srcImage.copyTo(srcGrayImage);
}
vector<KeyPoint>detectKeyPoint;
Mat keyPointImage1,keyPointImage2; Ptr<FastFeatureDetector> fast = FastFeatureDetector::create();
fast->detect(srcGrayImage,detectKeyPoint);
drawKeypoints(srcImage,detectKeyPoint,keyPointImage1,Scalar(0,0,255),DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
drawKeypoints(srcImage,detectKeyPoint,keyPointImage2,Scalar(0,0,255),DrawMatchesFlags::DEFAULT); imshow("src image",srcImage);
imshow("keyPoint image1",keyPointImage1);
imshow("keyPoint image2",keyPointImage2); imwrite("F:\\opencv\\OpenCVImage\\FeatureDetectSrc1FASTKeyPointImageDefault.jpg",keyPointImage2); waitKey(0);
return 0;
}

OPENCV图像特征点检测与FAST检测算法的更多相关文章
- Opencv 特征提取与检测-图像特征描述
图像特征描述 什么是图像特征 可以表达图像中对象的主要信息.并且以此为依据可以从其它未知图像中检测出相似或者相同对象 常见的图像特征 常见的图像特征 边缘 角点 纹理 图像特征描述 描 ...
- opencv图像特征检测之斑点检测
前面说过,图像特征点检测包括角点和斑点,今天来说说斑点,斑点是指二维图像中和周围颜色有颜色差异和灰度差异的区域,因为斑点代表的是一个区域,所以其相对于单纯的角点,具有更好的稳定性和更好的抗干扰能力. ...
- 【OpenCV文档】用于角点检测的Fast算法
原文地址:http://docs.opencv.org/trunk/doc/py_tutorials/py_feature2d/py_fast/py_fast.html#fast-algorithm- ...
- SLAM: 图像角点检测的Fast算法(OpenCV文档)
官方链接:http://docs.opencv.org/trunk/doc/py_tutorials/py_feature2d/py_fast/py_fast.html#fast-algorithm- ...
- 使用OpenCV对图片进行特征点检测和匹配(C++)
背景 最近从不同网站下载了非常多的动漫壁纸,其中有一些内容相同,但是大小.背景颜色.色调.主人公的位置不同(例子如下).正因为如此,基础的均方误差.直方图检测等方法很难识别出这些相似的图片. 思路 O ...
- OpenCV图像轮廓检测
轮廓检测: 轮廓检测的原理通俗的说就是掏空内部点,比如原图中有3*3的矩形点.那么就可以将中间的那一点去掉. 一.关键函数1.1 cvFindContours函数功能:对图像进行轮廓检测,这个函数将 ...
- OpenCV图像Surf与flann特征点(转载)
Surf(Speed Up Robust Feature) Surf算法的原理 ...
- opencv中的SIFT,SURF,ORB,FAST 特征描叙算子比较
opencv中的SIFT,SURF,ORB,FAST 特征描叙算子比较 参考: http://wenku.baidu.com/link?url=1aDYAJBCrrK-uk2w3sSNai7h52x_ ...
- 第三十节,目标检测算法之Fast R-CNN算法详解
Girshick, Ross. “Fast r-cnn.” Proceedings of the IEEE International Conference on Computer Vision. 2 ...
随机推荐
- C# 垃圾回收机制(转)
摘要:今天我们漫谈C#中的垃圾回收机制,本文将从垃圾回收机制的原理讲起,希望对大家有所帮助. GC的前世与今生 虽然本文是以.NET作为目标来讲述GC,但是GC的概念并非才诞生不久.早在1958年,由 ...
- selenium2.0集成测试案例
webDriver模拟点击对web工程测试还是挺方便的. package suite; import java.util.concurrent.TimeUnit; import org.junit.A ...
- MFC DLL中导出函数模板
//my.h struct AFX_EXT_CLASS B { }; struct AFX_EXT_CLASS C { }; class AFX_EXT_CLASS A { public: templ ...
- 4位开锁<dfs>
题意: 有一个四位密码的锁,每一位是1~9的密码,1跟9相连.并且相邻的连个密码位可以交换.每改变一位耗时1s,给出锁的当前状态和密码,求最少解锁时间. 思路: 用bfs枚举出所有相邻交换的情况,并记 ...
- 内联函数 inline 漫谈
内联函数存在的结论是: 引入内联函数是为了解决函数调用效率的问题 由于函数之间的调用,会从一个内存地址调到另外一个内存地址,当函数调用完毕之后还会返回原来函数执行的地址.函数调用会有一定的时间开销,引 ...
- UUID 浅析
在2013年3月21日苹果已经通知开发者,从2013年5月1日起,访问UIDID的应用将不再能通过审核,替代的方案是开发者应该使用“在iOS 6中介绍的Vendor或Advertising标示符”. ...
- 快学Scala-第三章 数组相关操作
知识点: 1.定长数组 Array val nums = new Array[Int](10) //10个整数的数组,所有元素初始化为0 val a = new Array[String](10) / ...
- [转]动态添加Fragments
本章节翻译自<Beginning-Android-4-Application-Development>,如有翻译不当的地方,敬请指出. 原书购买地址http://www.amazon.co ...
- GetClientRect
这个函数好像就是对应于视口的,获取视口的宽高 #include <windows.h> LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPAR ...
- cocos2d-x 3.3 显示中文
Resources文件夹下的strings.xml: <dict> <key>targetScore</key> <string>目标分数</st ...