opencv-python 详解图像特征(二)

目录

本篇内容目的:详解SIFT尺度不变特征变换

尺度空间的极值检测:

谈一下计算机模拟人眼:

先图像金字塔生成多尺度图片:

再用唯一线性模糊之高斯滤波来模拟视觉远近:

生成高斯差分金字塔DoG

最后再做DoG空间极值检测

特征关键点定位:

阈值化、曲线拟合找极值点

首先剔除低对比度的特征点

其次剔除不稳定的边缘响应点

方向赋值求->取特征点的主方向

目的: 为了实现图像旋转不变性

过程:

高斯函数平滑对距离特征点远近加权:

 生成特征描述


本篇内容目的:详解SIFT尺度不变特征变换

SIFT尺度不变特征变换,之所以称其为尺度不变,是因为其不受图片放缩以及旋转的影响。

        一些像Harris这样的拐角检测器。它们是旋转不变的,这意味着即使图像旋转了,我们也可以找到相同的角。很明显,因为转角在旋转的图像中也仍然是转角。但是缩放呢?如果缩放图像,则拐角可能不是角。例如,检查下面的简单图像。在同一窗口中放大小窗口中小图像中的拐角时,该角是平坦的,因此,Harris拐角不是尺度不变的。 

opencv-python 详解图像特征(二)_第1张图片

         尺度不变特征变换(SIFT)算法提取关键点并计算其描述算符。 SIFT算法主要包括四个步骤:

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

尺度空间的极值检测:

谈一下计算机模拟人眼:

         一般人眼可以分辨物体大小,然而计算机要有相同的能力却不是那么的容易,在未知的场景中,计算机视觉并不能提供物体的尺度大小,其中的一种方法是把物体不同尺度下的图像都提供给机器,让机器能够对物体在不同的尺度下有一个统一的认知。在建立统一认知的过程中,要考虑的就是在图像在不同的尺度下都存在的特征点。

先图像金字塔生成多尺度图片:

         在早期图像的多尺度通常使用图像金字塔表示形式。图像金字塔是同一图像在不同的分辨率下得到的一组结果,其生成过程的两个步骤

1.对原始图像进行平滑

2.对处理后的图像进行降采样(通常是水平、垂直方向的1/2)

        降采样缺点:

         降采样后得到一系列不断尺寸缩小的图像。显然,一个传统的金字塔中,每一层的图像是其上一层图像长、高的各一半。多分辨率的图像金字塔虽然生成简单,但其本质是降采样,图像的局部特征则难以保持,也就是降采样无法保持特征的尺度不变性

再用唯一线性模糊之高斯滤波来模拟视觉远近:

        可以通过图像的模糊程度来模拟人在距离物体由远到近时物体在视网膜上成像过程,距离物体越近其尺寸越大图像也越模糊,这就是高斯尺度空间,使用不同的参数模糊图像(分辨率不变),是尺度空间的另一种表现形式。
        我们知道图像和高斯函数进行卷积运算能够对图像进行模糊,使用不同的“高斯核”可得到不同模糊程度的图像。一副图像其高斯尺度空间可由其和不同的高斯卷积得到:

其中,G(x,y,σ)是高斯核函数。

        σ称为尺度空间因子,它是高斯正态分布的标准差,反映了图像被模糊的程度,其值越大图像越模糊,对应的尺度也就越大。L(x,y,σ)代表着图像的高斯尺度空间。
        构建尺度空间的目的是为了检测出在不同的尺度下都存在的特征点,而检测特征点较好的算子是Δ2G(高斯拉普拉斯,LoG),

        使用LoG虽然能较好的检测到图像中的特征点,但是LoG运算量过大,通常可使用DoG(差分高斯,Difference of Gaussina)来近似计算LoG。

        (LoG和DoG算子这个解释的挺好: https://zhuanlan.zhihu.com/p/49447503)

        设k为相邻两个高斯尺度空间的比例因子,则DoG的定义为

        其中,L(x,y,σ)是图像的高斯尺度空间。

生成高斯差分金字塔DoG

        从上式可以知道,将相邻的两个高斯空间的图像相减就得到了DoG的响应图像。为了得到DoG图像,先要构建高斯尺度空间,而高斯的尺度空间可以在图像金字塔降采样的基础上加上高斯滤波得到,也就是对图像金字塔的每层图像使用不同的参数σ进行高斯模糊,使每层金字塔有多张高斯模糊过的图像。降采样时,金字塔上边一组图像的第一张是由其下面一组图像倒数第三张降采样得到。

        同时我们也可以知道,高斯金字塔有多组(降采样数目),每组又有多层(不同高斯核滤波的数目),一组中的多个层之间使用的高斯参数σ是不同的。上一组图像的最底层图像是由下一组中尺度为2σ的图像进行因子为2的降采样得到的(高斯金字塔先从底层建立)。高斯金字塔构建完成后,将相邻的高斯金字塔相减就得到了DoG金字塔

opencv-python 详解图像特征(二)_第2张图片

整体流程是这样:

opencv-python 详解图像特征(二)_第3张图片

 高斯金字塔的组数O一般是:O = [ log2( min( M,N ) ) ] - 3

        O表示高斯金字塔的组数,M,N分别是图像的行和列。减去的系数a可以在0−log2min(M,N)之间的任意值,和具体需要的金字塔的顶组图像的大小有关。

高斯金字塔的层数S一般是:S = n +3 ,这里的n不是上边的N,是我们想每组提几层特征。

        高斯模糊参数σ(尺度空间),可由下面关系式得到:

        其中o为所在的组,s为所在的层,σ0为初始的尺度,S为每组的层数。

        在Lowe的算法实现中:

        就是首先将原图像的长和宽各扩展一倍。

        从上面可以得知同一组内相邻层的图像尺度关系:

         相邻组之间的尺度关系:

最后再做DoG空间极值检测

        为了寻找尺度空间的极值点,每个像素点要和其图像域(同一尺度空间)和尺度域(相邻的尺度空间)的所有相邻点进行比较,当其大于(或者小于)所有相邻点时,改点就是极值点。如图所示,中间的检测点要和其所在图像的3×3邻域8个像素点,以及其相邻的上下两层的3×3领域18个像素点,共26个像素点进行比较。
        从上面的描述中可以知道,每组图像的第一层和最后一层是无法进行比较取得极值的。为了满足尺度变换的连续性,在每一组图像的顶层继续使用高斯模糊生成3幅图像,高斯金字塔每组有S+3层图像,DoG金字塔的每组有S+2组图像。

opencv-python 详解图像特征(二)_第4张图片

特征关键点定位:

阈值化、曲线拟合找极值点

        通过比较检测得到的DoG的局部极值点实在离散的空间搜索得到的,由于离散空间是对连续空间采样得到的结果,因此在离散空间找到的极值点不一定是真正意义上的极值点,因此要设法将不满足条件的点剔除掉。

        阈值化去除部分噪点:

        这里T是经验参数,推荐 0.04,n就是每组想提取几张图片的特征的数量。

        然后通过尺度空间DoG函数进行曲线拟合通过差值寻找极值点,这一步的本质是去掉DoG局部曲率非常不对称的点。

opencv-python 详解图像特征(二)_第5张图片

         接下来剔除掉的不符合要求的点主要有两种:

  • 低对比度的特征点
  • 不稳定的边缘响应点

首先剔除低对比度的特征点

        候选特征点x,其偏移量定义为Δx,其对比度为D(x)的绝对值∣D(x)∣,对D(x)应用三元二阶泰勒展开式:

opencv-python 详解图像特征(二)_第6张图片

        这里用矢量形式表示: 

         由于x是D(x)的极值点,所以对上式求导并令其为0,得到:

         然后再把求得的Δx代入到D(x)的泰勒展开式中:

         设对比度的阈值为T(上边阈值化提到的0.04经验值),若∣D(x^)∣≥ T / n,则该特征点保留,否则剔除掉,n依然是我们每组想提取特征的图片个数。

其次剔除不稳定的边缘响应点

        在边缘梯度的方向上主曲率值比较大,而沿着边缘方向则主曲率值较小。候选特征点的DoG函数D(x)的主曲率与2×2Hessian矩阵H的特征值成正比。

         为了避免求具体的值,可以使用H特征值得比例。设α=λmax为H的最大特征值,β=λmin为H的最小特征值,则:

        (注:Tr(H)为矩阵H的迹,Det(H)为矩阵H的行列式)
        设γ=α/β 表示最大特征值和最小特征值的比值,则:

        上式的结果与两个特征值的比例有关,和具体的大小无关,当两个特征值想等时其值最小,并且随着γ的增大而增大。因此为了检测主曲率是否在某个阈值Tγ下,只需检测:

         如果上式成立,则剔除该特征点,否则保留。

方向赋值求->取特征点的主方向

目的: 为了实现图像旋转不变性

过程:

        为了实现图像旋转不变性,需要给特征点的方向进行赋值。利用特征点邻域像素的梯度分布特性来确定其方向参数,再利用图像的梯度直方图求取关键点局部结构的稳定方向。
        找到了特征点,也就可以得到该特征点的尺度σσ,也就可以得到特征点所在的尺度图像

        计算以特征点为中心、以3×1.5σ为半径的区域图像的幅角幅值,每个点L(x,y)的梯度的模m(x,y)以及方向θ(x,y)可通过下面公司求得:

opencv-python 详解图像特征(二)_第7张图片

        计算得到梯度方向后,就要使用直方图统计特征点邻域内像素对应的梯度方向和幅值。梯度方向的直方图的横轴是梯度方向的角度(梯度方向的范围是0到360度,直方图每45度一个柱共8个柱,论文中是10度36柱),纵轴是梯度方向对应梯度幅值的累加,在直方图的峰值就是特征点的主方向。

opencv-python 详解图像特征(二)_第8张图片

高斯函数平滑对距离特征点远近加权:

        在Lowe的论文还提到了使用高斯函数对直方图进行平滑以增强特征点近的邻域点对关键点方向的作用,并减少突变的影响。为了得到更精确的方向,通常还可以对离散的梯度直方图进行插值拟合。具体而言,关键点的方向可以由和主峰值最近的三个柱值通过抛物线插值得到。在梯度直方图中,当存在一个相当于主峰值80%能量的柱值时,则可以将这个方向认为是该特征点辅助方向。所以,一个特征点可能检测到多个方向(也可以理解为,一个特征点可能产生多个坐标、尺度相同,但是方向不同的特征点)。Lowe在论文中指出:15%的关键点具有多方向,而且这些点对匹配的稳定性很关键。

        得到特征点的主方向后,对于每个特征点可以得到三个信息(x,y,σ,θ),即位置、尺度和方向由此可以确定一个SIFT特征区域,一个SIFT特征区域由三个值表示,中心表示特征点位置,半径表示关键点的尺度,箭头表示主方向。具有多个方向的关键点可以被复制成多份,然后将方向值分别赋给复制后的特征点,一个特征点就产生了多个坐标、尺度相等,但是方向不同的特征点。

opencv-python 详解图像特征(二)_第9张图片

 生成特征描述

        通过以上的步骤已经找到了SIFT特征点位置、尺度和方向信息,下面就需要使用一组向量来描述关键点也就是生成特征点描述子,这个描述符不只包含特征点,也含有特征点周围对其有贡献的像素点。描述子应具有较高的独立性,以保证匹配率。
特征描述符的生成大致有三个步骤:

  • 校正旋转主方向,确保旋转不变性。
  • 生成描述子,最终形成一个128维的特征向量
  •  归一化处理,将特征向量长度进行归一化处理,进一步去除光照的影响。

        为了保证特征矢量的旋转不变性,要以特征点为中心,在附近邻域内将坐标轴旋转θ(特征点的主方向)角度,即将坐标轴旋转为特征点的主方向。旋转后邻域内像素的新坐标为:

        旋转后以主方向为中心取 8×8的窗口。下图所示,左图的中央为当前关键点的位置,每个小格代表为关键点邻域所在尺度空间的一个像素,求取每个像素的梯度幅值与梯度方向,箭头方向代表该像素的梯度方向,长度代表梯度幅值,然后利用高斯窗口对其进行加权运算。最后在每个4×4的小块上绘制8个方向的梯度直方图,计算每个梯度方向的累加值,即可形成一个种子点,如图所示。每个特征点由4个种子点组成,每个种子点有8个方向的向量信息。这种邻域方向性信息联合增强了算法的抗噪声能力,同时对于含有定位误差的特征匹配也提供了比较理性的容错性。

opencv-python 详解图像特征(二)_第10张图片

        与求主方向不同,此时每个种子区域的梯度直方图在0-360之间划分为8个方向区间,每个区间为45度,即每个种子点有8个方向的梯度强度信息。在实际的计算过程中,为了增强匹配的稳健性,Lowe建议:对每个关键点使用4×4共16个种子点来描述,这样一个关键点就可以产生128维的SIFT特征向量。 

opencv-python 详解图像特征(二)_第11张图片

        通过对特征点周围的像素进行分块,计算块内梯度直方图,生成具有独特性的向量,这个向量是该区域图像信息的一种抽象,具有唯一性。

你可能感兴趣的:(opencv-python,图像处理,机器视觉,opencv,python)