图像局部特征提取

  • 2019 年 10 月 3 日
  • 笔记

图像特征可以包括颜色特征、纹理特征、形状特征以及局部特征点等。其中局部特点具有很好的稳定性,不容易受外界环境的干扰。图像特征提取是图像分析与图像识别的前提,它是将高维的图像数据进行简化表达最有效的方式,从一幅图像的的数据矩阵中,我们看不出任何信息,所以我们必须根据这些数据提取出图像中的关键信息,一些基本元件以及它们的关系。

图像局部特征描述的核心问题是不变性(鲁棒性)和可区分性。由于使用局部图像特征描述子的时候,通常是为了鲁棒地处理各种图像变换的情况。因此,在构建/设计特征描述子的时候,不变性问题就是首先需要考虑的问题。在宽基线匹配中,需要考虑特征描述子对于视角变化的不变性、对尺度变化的不变性、对旋转变化的不变性等;在形状识别和物体检索中,需要考虑特征描述子对形状的不变性。

局部特征点是图像特征的局部表达,它只能反应图像上具有的局部特殊性,所以它只适合于对图像进行匹配,检索等应用。对于图像理解则不太适合。而后者更关心一些全局特征,如颜色分布,纹理特征,主要物体的形状等。全局特征容易受到环境的干扰,光照,旋转,噪声等不利因素都会影响全局特征。相比而言,局部特征点,往往对应着图像中的一些线条交叉,明暗变化的结构中,受到的干扰也少。

对于局部特征的检测,通常使用局部图像描述子来进行。

斑点角点是两类局部特征点。斑点通常是指与周围有着颜色和灰度差别的区域,如草原上的一棵树或一栋房子。它是一个区域,所以它比角点的抗噪能力要强,稳定性要好。而角点则是图像中物体的拐角或者线条之间的交叉部分。

斑点检测原理与举例

LoG与DoH

斑点检测的方法主要包括利用高斯拉普拉斯算子检测的方法(LOG),以及利用像素点Hessian矩阵(二阶微分)及其行列式值的方法(DOH)。

DoH方法就是利用图像点二阶微分Hessian矩阵, Hessian矩阵行列式的值,同样也反映了图像局部的结构信息。与LoG相比,DoH对图像中的细长结构的斑点有较好的抑制作用。

无论是LoG还是DoH,它们对图像中的斑点进行检测,其步骤都可以分为以下两步:

  1. 使用不同的生成或模板,并对图像进行卷积运算;
  2. 在图像的位置空间与尺度空间中搜索LoG与DoH响应的峰值。

SIFT(尺度不变特征变换)

尺度不变特征转换(Scale-invariant feature transform或SIFT)是一种电脑视觉的算法用来侦测与描述影像中的局部性特征,它在空间尺度中寻找极值点,并提取出其位置、尺度、旋转不变量。该描述子具有非常强的稳健性。

SIFT算法详细介绍

SIFT算法步骤

  1. 构建DOG尺度空间

    模拟图像数据的多尺度特征,大尺度抓住概貌特征,小尺度注重细节特征。通过构建高斯金字塔(每一层用不同的参数(sigma)做高斯模糊(加权)),保证图像在任何尺度都能有对应的特征点,即保证尺度不变性

  2. 关键点搜索和定位:

    确定是否为关键点,需要将该点与同尺度空间不同(sigma)值的图像中的相邻点比较,如果该点为max或min,则为一个特征点。找到所有特征点后,要去除低对比度和不稳定的边缘效应的点,留下具有代表性的关键点(比如,正方形旋转后变为菱形,如果用边缘做识别,4条边就完全不一样,就会错误;如果用角点识别,则稳定一些)。去除这些点的好处是增强匹配的抗噪能力和稳定性。最后,对离散的点做曲线拟合,得到精确的关键点的位置和尺度信息。

  3. 方向赋值

    为了实现旋转不变性,需要根据检测到的关键点的局部图像结构为特征点赋值。具体做法是用梯度方向直方图。在计算直方图时,每个加入直方图的采样点都使用圆形高斯函数进行加权处理,也就是进行高斯平滑。这主要是因为SIFT算法只考虑了尺度和旋转不变形,没有考虑仿射不变性。通过高斯平滑,可以使关键点附近的梯度幅值有较大权重,从而部分弥补没考虑仿射不变形产生的特征点不稳定。注意,一个关键点可能具有多个关键方向,这有利于增强图像匹配的鲁棒性

  4. 关键点描述子生成

    关键点描述子不但包括关键点,还包括关键点周围对其有贡献的像素点。这样可使关键点有更多的不变特性,提高目标匹配效率。在描述子采样区域时,需要考虑旋转后进行双线性插值,防止因旋转图像出现白点。同时,为了保证旋转不变性,要以特征点为中心,在附近领域内旋转(theta)角,然后计算采样区域的梯度直方图,形成n维SIFT特征矢量(如128-SIFT)。最后,为了去除光照变化的影响,需要对特征矢量进行归一化处理。

SIFT特征提取的优点

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

SIFT特征提取的缺点

  1. 实时性不高,因为要不断地进行下采样和插值等操作;
  2. 有时特征点较少(比如模糊图像);
  3. 对边缘光滑的目标无法准确提取特征(比如边缘平滑的图像,检测出的特征点过少,对圆更是无能为力)。

SIFT特征提取可以解决的问题

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

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

角点检测的原理与举例

角点检测的方法也是极多的,其中具有代表性的算法是Harris算法与FAST算法。
算法原理详解:Harris特征点检测FAST特征检测

Harris角点特征提取

Harris角点检测是一种基于图像灰度的一阶导数矩阵检测方法。检测器的主要思想是局部自相似性/自相关性,即在某个局部窗口内图像块与在各个方向微小移动后的窗口内图像块的相似性。该算法认为像素周围显示存在多余一个方向的边,便认为该点为兴趣点,即称为角点。

Harris算法步骤

  1. 利用水平、竖直差分算子对图像每个像素进行滤波以求得(I_x, I_y),进而求得图像域中点(x)上的对称半正定矩阵(M_I = M_I(x))
    [ M_I=nabla I nabla I^T=left[ begin{array}{c} I_x \ I_y end{array} right] left[ begin{array}{c} I_x & I_y end{array}right] = left[ begin{array}{cc} I_x^2 & I_x I_y \ I_x I_y & I_y^2 end{array} right] ]
  2. 选择权重矩阵(W)(通常为高斯滤波器(G))对(M)进行滤波
    [ W = exp(- frac{x^2+y^2}{2sigma^2}) ]
    [ M_I = W * M_I ]
  3. 利用(M)计算对应于每个像素的角点量(cim)(R):
    [ cim = frac{I_x^2*I_y^2-(I_xI_y)^2}{I_x^2+I_y^2} ]
  4. 在矩阵 (cim) 中,同时满足 (cim) 大于一阙值 (thresh)(cim) 是某领域内的局部极大值,这两个条件的点被认为是角点。

    提高阙值,则提取的角点数目变少,降低阙值,则提取的角点数目变多
    另外求局部极大值的领域大小也会影响提取角点的数目和容忍度

Harris角点性质

  1. 该算法算子对亮度和对比度的变化不敏感。

    这是因为在进行Harris角点检测时,使用了微分算子对图像进行微分运算,而微分运算对图像密度的拉升或收缩和对亮度的抬高或下降不敏感。换言之,对亮度和对比度的仿射变换并不改变Harris响应的极值点出现的位置,但是,由于阈值的选择,可能会影响角点检测的数量。

  2. 算子具有旋转不变性。

    Harris角点检测算子使用的是角点附近的区域灰度二阶矩矩阵。而二阶矩矩阵可以表示成一个椭圆,椭圆的长短轴正是二阶矩矩阵特征值平方根的倒数。当特征椭圆转动时,特征值并不发生变化,所以判断角点响应值也不发生变化,由此说明Harris角点检测算子具有旋转不变性。

  3. 算子不具有尺度不变性。

Harris算法实现

import numpy as np  import matplotlib.pyplot as plt  from PIL import Image  from scipy.ndimage import filters      class Harris:      def __init__(self, img_path):          self.img_path = img_path          self.grayImg = None          self.Ix = None          self.Iy = None          self.Ix_mul_Ix = None          self.Ix_mul_Iy = None          self.Iy_mul_Iy = None          self.cim = None          self.filtered_coords = None        def _rgb2gray(self):          self.grayImg = Image.open(self.img_path).convert('L')          self.grayImg = np.array(self.grayImg)        def _cal_ix_iy(self, sigma=3):          # 计算导数          self.Ix = np.zeros(self.grayImg.shape)          filters.gaussian_filter(self.grayImg, (sigma, sigma), (0, 1), self.Ix)          self.Iy = np.zeros(self.grayImg.shape)          filters.gaussian_filter(self.grayImg, (sigma, sigma), (1, 0), self.Iy)        def _cal_para(self):          # 计算Ix^2,Iy^2和Ix*Iy并加入高斯滤波          self.Ix_mul_Ix = filters.gaussian_filter(self.Ix*self.Ix, 3)          self.Iy_mul_Iy = filters.gaussian_filter(self.Iy*self.Iy, 3)          self.Ix_mul_Iy = filters.gaussian_filter(self.Ix*self.Iy, 3)        def _cal_cim(self):          self.cim = (self.Ix_mul_Ix*self.Iy_mul_Iy - 2*self.Ix_mul_Iy) / (self.Ix_mul_Ix + self.Iy_mul_Iy)        def cal_harris(self, min_dist=10, threshold=0.1):          self._rgb2gray()          self._cal_ix_iy()          self._cal_para()          self._cal_cim()          conner_threshold = self.cim.max()*threshold          self.cim = (self.cim > conner_threshold) * 1          coords = np.array(self.cim.nonzero()).T          candidate_values = [self.cim[c[0], c[1]] for c in coords]          index = np.argsort(candidate_values)          allowed_locations = np.zeros(self.cim.shape)          allowed_locations[min_dist:-min_dist, min_dist:-min_dist] = 1          self.filtered_coords = []          for i in index:              if allowed_locations[coords[i, 0], coords[i, 1]] == 1:                  self.filtered_coords.append(coords[i])                  allowed_locations[(coords[i, 0] - min_dist):(coords[i, 0] + min_dist),                  (coords[i, 1] - min_dist):(coords[i, 1] + min_dist)] = 0  # 此处保证min_dist*min_dist只有一个harris特征点          return self.filtered_coords        def plot_harris_point(self):          plt.figure()          plt.gray()          plt.imshow(Image.open(self.img_path).convert('L'))          plt.plot([p[1] for p in self.filtered_coords], [p[0] for p in self.filtered_coords], '*')          plt.axis('off')          plt.show()      if __name__ == '__main__':      img_path = "./imgs/3.jpg"      harris = Harris(img_path)      harris.cal_harris()      harris.plot_harris_point()

结果演示

参考文献

python计算机视觉编程第2章
图像处理之特征提取
python计算机视觉编程之局部图像描述子
图像局部特征点检测算法综述
斑点检测
SIFT定位算法关键步骤的说明
SIFT算法详解
sift特征提取算法
Harris特征点检测
FAST特征检测
特征点提取之Harris角点提取法
Harris角点检测(一)