OpenCV4学习笔记(39)——特征提取与描述之SIFT特征提取描述算法

今天开始,要整理一下之前看过的一些特征提取描述算法,并记录下自己的总结。由于这些算法往深处探索的时候都涉及到了非常多与数学相关的内容,而这些内容对于像我一样数学功底不够深厚的人来说是比较难完全理解的,所以我的笔记只记录个人对每个算法大致流程的理解。下面就开始吧!!!

对于一幅图像中的内容,存在各种各样的特征,例如有点特征、线特征和块特征等等。其中,特征点是图像中非常重要的一个局部特征,它集中了很多的形状信息,特征点反映的是二维图像中灰度变化极其剧烈的点,或者是图像边缘曲线中曲率极大值的点,如角点。而当我们需要对图像中的内容进行分析时,这些特征就派上了很大的用场,能够帮助我们比较好的找出我们的目标对象,对目标对象进行识别和分析等操作。特征点广泛应用在目标检测与识别、图像重构、图像匹配等方面。

那么,想要通过目标的特征来进行下一步操作,首先就是要找出目标的特征,这里主要可以分为两个步骤,第一个是目标特征的提取,第二个就是对目标特征进行描述。

所谓特征提取,就是在图像中根据像素点的梯度、灰度值、邻域像素关系等因素,来将某些与其他像素点具有明显差异的像素点区分出来,并将这些像素点提取出来作为一个点集,这就是我们找到的候补特征点集。这些特征点一般是在图像中梯度比较大、或者灰度值变化比较大的区域,通过进一步地筛选,我们能够得到位于我们的目标区域中的候选特征点,从而进一步提取出我们目标对象的特征点。

既然我们找到了目标对象的特征点,那就要给这些特征点都起一个名字,这样我们就能够通过它们的名字来区分它们。例如图像A中存在一只猫作为我们的目标对象,我们在这只猫的区域中提取到的特征点给它命名为“喵”,随后再给出一张图像B,当我们获取图像B中的所有特征点后通过比对这些特征点中是否存在名为“喵”的特征点,如果存在则证明图像B中很可能也包含了一只猫的内容,如果不存在则证明图像B中很可能不包含有猫的内容。

于是对特征点进行命名的过程,我们就说这是特征描述。我们通过某种编码的格式来对得到的特征点进行编码,从而得到一个特征描述子,下一步就可以通过这个描述子来比对不同图像的内容了。

特征提取与描述的主要步骤可以归结如下:
1、 找到同一目标物体在不同成像条件、视角变化和存在噪声的情况下都能够可靠定位的一组独特关键点KeyPoints,也叫特征点;
2、以比例或仿射不变的方式在每个特征点周围定义一个区域,也就是选取特征点的邻域;
3、提取并通过某种方式来规范化每个特征点邻域的内容;
4、从规范化的每个特征点邻域的内容中来计算该特征点的描述子;
5、将计算得到的一系列目标对象的特征描述子与模板的特征描述子相对比,进行特征匹配。

在特征提取与描述算法中,最经典的应该算是SIFT(Scale-invariant feature transform-尺度不变特征转换)特征检测算法,在SIFT算法的基础上还演化出了不少的改进版本。在我的理解中,SIFT算法可以分为以下这几个步骤:

  1. 构建尺度空间的高斯图像金字塔
    将原图像作为底层图像进行多尺度的高斯模糊(使用不同的高斯标准差sigam进行高斯滤波,得到一组多张同分辨率不同尺度的图像,模拟人眼对于同一物体在不同距离下的视觉效果,在这里的尺度空间就是以sigam为自变量进行高斯滤波而得到的不同图像结果),得到一组自底向顶的多尺度图像。选择一组多尺度图像中的倒数第三张图像作为下一层的第一张图像,再进行多尺度高斯模糊,构建金字塔后一层的一组不同尺度的图像。
    并对每一层重复上述操作,最终得到一个尺度空间内的高斯图像金字塔,该金字塔的每一层是一组不同尺度的高斯滤波图像。
  2. 构建尺度空间的高斯差分(DOG)金字塔
    将尺度空间的高斯图像金字塔中每一层的一组图像中的相邻图像进行相减,相邻图像相减得到一张高斯差分图像,最终得到该层的高斯差分图像组。对金字塔逐层进行相减处理后,最终得到一个尺度空间的高斯差分图像金字塔。高斯差分图像金字塔的每一层都是一组高斯差分图像。
  3. 尺度空间极值检测
    在尺度空间中的高斯差分图像金字塔中每一层的一组图像中选择极值点,该极值点需要满足它在这一组高斯差分图像中所在图像的邻域内和在该组的不同张图像的同一位置邻域内都是像素值最大或最小的,那么该极值点就是通过高斯微分函数来识别出的潜在的对于尺度和旋转不变的候补特征点。
  4. 特征点定位
    在每个候选特征点的位置上,通过对尺度空间的DOG函数进行曲线拟合来确定候选特征点在原图像(最底层图像组)中的位置和尺度,同时过滤掉因为噪声而变得稳定性差的部分候选特征点,最终剩下来的点就是SIFT算法提取出的特征点。
  5. 方向确定
    基于图像局部的梯度方向,分配给每个特征点一个或多个方向。所有后续对图像的操作都相对于特征点的方向、尺度和位置进行变换,从而为特征点提供旋转不变性、尺度不变性和空间不变性。
  6. 特征点描述
    在每个特征点周围的16x16邻域内,在选定的尺度上测量图像局部的梯度,并将邻域划分为4个4x4的区域block,按照每个block内的像素点梯度构建梯度直方图并做归一化处理,根据梯度直方图获得每个block的描述子,再将4个block的描述子组合起来得到该特征点的描述子。这种描述子具有旋转不变性、尺度不变性、光照不变性、空间不变性,对视角变化、仿射变换、噪声也保持一定程度的稳定性。

至此就是SIFT算法的大致流程了,当然其中还包含了许多的细节部分和数学内容,如果对算法的细节部分感兴趣的话可以看这篇博文《Scale Invariant Feature Transform(SIFT)——尺度不变特征变换匹配算法详解》,这个博主很厉害几乎把SIFT算法的paper给摸透了。

而在OpenCV中,原本是提供了SIFT算法的API实现,但是由于专利的问题,在之前的某一个版本以后已经把这个算法给移出到了xfeature2d模块,也就是非正式模块。如果想要使用这种算法的话,就得去OpenCV官网自己下载xfeature2d模块的源文件,然后进行编译。本来我是打算操作一波的,连带着cuda、openVINO和xfeature2d一起进行编译,然而由于Github那令人感动的网速,一直下载不了那两份代码,修改了系统host文件后进度条也还是一动不动(进度条:我不敢动。。不敢动。。)
罢了罢了,所以今天的笔记就没有代码演示了,不过在OpenCV中特征算法的使用都大同小异,以后整理其他特征算法的时候再做代码演示吧~
今天的笔记到到此为止,谢谢阅读~

补充OpenCV中SIFT算法的调用演示:

	auto sift = SIFT::create();
	Mat tem = imread("D:\\opencv_c++\\opencv_tutorial\\data\\images\\dog.jpg");
	vector<KeyPoint>keyPoints;
	Mat descriptors;
	sift->detectAndCompute(tem, Mat(), keyPoints, descriptors);
	drawKeypoints(tem, keyPoints, tem, Scalar::all(-1), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
	imshow("tem", tem);

OpenCV4学习笔记(39)——特征提取与描述之SIFT特征提取描述算法_第1张图片

PS:本人的注释比较杂,既有自己的心得体会也有网上查阅资料时摘抄下的知识内容,所以如有雷同,纯属我向前辈学习的致敬,如果有前辈觉得我的笔记内容侵犯了您的知识产权,请和我联系,我会将涉及到的博文内容删除,谢谢!

你可能感兴趣的:(学习笔记,计算机视觉,opencv)