视觉和声音是人类固有的感觉输入。我们的大脑是可以迅速进化我们的能力来处理视觉和听觉信号的,一些系统甚至在出生前就对刺激做出反应。另一方面,语言技能是学习得来的。他们需要几个月或几年的时间来掌握。许多人天生就具有视力和听力的天赋,但是我们所有人都必须有意训练我们的大脑去理解和使用语言。
在过去五年中,深度学习模式的突破最终预示着期待已久的图像和语音分析的革命。进展的困难与从相应类型的数据中提取有意义特征的困难直接相关。机器学习模型需要语义上有意义的特征进行语义意义的预测。在文本分析中,特别是对于英语这样的语言,其中一个基本的语义单位(一个词)很容易提取,可以很快地取得进展。另一方面,图像和音频被记录为数字像素或波形。图像中的单个“原子”是像素。在音频数据中,它是波形强度的单一测量。它们包含的语义信息远少于数据文本。因此,在图像和音频上的特征提取和工程任务比文本更具挑战性。
在过去的二十年中,计算机视觉研究已经集中在人工标定上,用于提取良好的图像特征。在一段时间内,图像特征提取器,如 SIFT 和 HOG 是标准步骤。深度学习研究的最新发展已经扩展了传统机器学习模型的范围,将自动特征提取作为基础层。他们本质上取代手动定义的特征图像提取器与手动定义的模型,自动学习和提取特征。人工标定仍然存在,只是进一步深入到建模中去。
最简单的图像特征(为什么他们不好使)
从图像中提取的哪些特征是正确的呢?答案当然取决于我们试图用这些特征来做什么。假设我们的任务是图像检索:我们得到一张图片并要求从图像数据库中得到相似的图片。我们需要决定如何表示每个图像,以及如何测量它们之间的差异。我们可以看看图像中不同颜色的百分比吗?图8-1展示了两幅具有大致相同颜色轮廓但有着非常不同含义的图片;一个看起来像蓝色天空中的白云,另一个是希腊国旗。因此,颜色信息可能不足以表征图像。
另一个比较简单的想法是测量图像之间的像素值差异。首先,调整图像的宽度和高度。每个图像由像素值矩阵表示。矩阵可以通过一行或一列被堆叠成一个长向量。每个像素的颜色(例如,颜色的 RGB 编码)现在是图像的特征。最后,测量长像素向量之间的欧几里得距离。这绝对可以区分希腊国旗和白云。但作为相似性度量,它过于严格。云可以呈现一千种不同的形状,仍然是一朵云。它可以移动到图像的一边,或者一半可能位于阴影中。所有这些转换都会增加欧几里得距离,但是他们不应该改变图片仍然是云的事实。
问题是单个像素不携带足够的图像语义信息。因此,使用它们用于分析结果是非常糟糕的。在 1999 年,计算机视觉研究者想出了一种更好的方法来使用图像的统计数据来表示图像。它叫做 Scale Invariant Feature Transform(SIFT)。
SIFT最初是为对象识别的任务而开发的,它不仅涉及将图像正确地标记为包含对象,而且确定其在图像中的位置。该过程包括在可能的尺度金字塔上分析图像,检测可以指示对象存在的兴趣点,提取关于兴趣点的特征(通常称为计算机视觉中的图像描述符),并确定对象的姿态。
多年来,SIFT 的使用扩展到不仅提取兴趣点,而且遍及整个图像的特征。SIFT 特征提取过程非常类似于另一种称为 Histogram of Oriented Gradients (HOG)的技术。它们都计算梯度方向的直方图。现在我们详细地描述一下。
人工特征提取:SIFT 与 HOG
图像梯度
要比原始像素值做得更好,我们必须以某种方式将像素组织成更多信息单元。相邻像素之间的差异通常是非常有用的特征。通常情况下像素值在对象的边界处是不同,当存在阴影、图案内或纹理表面时。相邻像素之间的差值称为图像梯度。
向量可以通过它的方向和大小来完全描述。梯度的大小等于梯度的欧几里得范数,这表明像素值在像素周围变化得多大。梯度的位置或方向取决于水平方向和垂直方向上的变化的相对大小;图 8-2 说明了这些数学概念。
图 8-2
图8—3展出了由垂直和水平梯度组成的图像梯度的示例。每个示例是一个 9 像素的图像。每个像素用灰度值标记。(较小的数字对应于较深的颜色)中心像素的梯度显示在每个图像下面。左侧的图像包含水平条纹,其中颜色仅垂直变化。因此,水平梯度为零,梯度垂直为非零。中心图像包含垂直条纹,因此水平梯度为零。右边的图像包含对角线条纹,斜率也是对角线。
图 8-3
它们能在真实的图像上发挥作用吗?在例 8-1 中,我们使用图 8-4 所示的猫的水平和垂直梯度上来实验。由于梯度是在原始图像的每个像素位置计算的,所以我们得到两个新的矩阵,每个矩阵可以被可视化为图像。
图 8-4
例 8-1
import matplotlib.pyplot as plt %matplotlib inline from skimage.feature import hog from skimage import data, color, exposure image = color.rgb2gray(data.chelsea()) fd, hog_image = hog( image, orientations=8, pixels_per_cell=(16, 16), cells_per_block=(1, 1), visualise=True) hog_image_rescaled = exposure.rescale_intensity(hog_image, in_range=(0, 0.02)) fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 4), sharex=True, sharey=True) ax1.axis('off') ax1.imshow(image, cmap=plt.cm.gray) ax1.set_title('Input image') ax1.set_adjustable('box-forced') ax2.axis('off') ax2.imshow(hog_image_rescaled, cmap=plt.cm.gray) ax2.set_title('Histogram of Oriented Gradients') ax2.set_adjustable('box') #('box-forced')
注意,水平梯度提取出强烈的垂直模式,如猫眼睛的内边缘,而垂直梯度则提取强的水平模式,如晶须和眼睛的上下眼睑。这乍看起来似乎有些矛盾,如果我们仔细考虑一下,这还是有道理的。水平()梯度识别水平方向上的变化。强的垂直图案在大致相同的位置上跨越多个像素。因此,垂直图案导致像素值的水平差异。这也是我们的眼睛也能察觉到的。
import numpy as np gx = np.empty(image.shape, dtype=np.double) gx[:, 0] = 0 gx[:, -1] = 0 gx[:, 1:-1] = image[:, :-2] - image[:, 2:] gy = np.empty(image.shape, dtype=np.double) gy[0, :] = 0 gy[-1, :] = 0 gy[1:-1, :] = image[:-2, :] - image[2:, :] fig, (ax1, ax2, ax3) = plt.subplots( 1, 3, figsize=(12, 8), sharex=True, sharey=True) ax1.axis('off') ax1.imshow(image, cmap=plt.cm.gray) ax1.set_title('Original image') ax1.set_adjustable('box-forced') ax2.axis('off') ax2.imshow(gx, cmap=plt.cm.gray) ax2.set_title('Horizontal gradients') ax2.set_adjustable('box-forced') ax3.axis('off') ax3.imshow(gy, cmap=plt.cm.gray) ax3.set_title('Vertical gradients') ax3.set_adjustable('box-forced')
梯度方向直方图
单个图像梯度可以识别图像邻域中的微小差异。但是我们的眼睛看到的图案比那更大。例如,我们看到一整只猫的胡须,而不仅仅是一个小部分。人类视觉系统识别区域中的连续模式。因此,我们咋就图像梯度邻域有仍然有很多的工作要做。
我们如何精确地归纳向量?统计学家会回答:“看分布!SIFT 和 HOG 都走这条路。它们计算(正则化)梯度矢量直方图作为图像特征。直方图将数据分成容器并计算每容器中有多少,这是一个(不规范的)经验分布。规范化确保数和为 1,用数学语言描述为它具有单位 L 范数。
图像梯度是矢量,矢量可以由两个分量来表示:方向和幅度。因此,我们仍然需要决定如何设计直方图来表示这两个分量。SIFT 和 HOG 提供了一个解决方案,其中图像梯度被它们的方向角所包括,由每个梯度的大小加权。以下是流程:
- 将 0° - 360° 分成相等大小的容器。
图 8-5
当然,在基本的梯度方向直方图算法中还有许多选项。像通常一样,正确的设置可能高度依赖于想要分析的特定图像。
有多少容器?
他们的跨度是从 0° - 360°(有符号梯度)还是 0° - 180°(无符号梯度)?
具有更多的容器导致梯度方向的细粒度量化,因此会保留更多关于原始梯度的信息。但是,有太多的容器是不必要的,并可能导致过度拟合训练数据。例如,在图像中识别猫可能不依赖于精确地取向在 3° 的猫的晶须。
还有一个问题,容器是否应该跨越 0 - 360°,这将沿轴保持梯度,或跨越 0°- 180°,这将不会保留垂直梯度的符号。Dalal 与 Triggs 是 HOG 论文的最初作者,实验确定从 0 - 180° 跨越的 9 个容器是最好的,而 SIFT 论文推荐了 8 个跨越 0° - 360° 的容器。
使用什么样的权重函数?
HOG 论文比较各种梯度幅度加权方案:其大小本身、平方、平方根、二值化等等。没有改变的平面大小在实验中表现最好。
邻域怎么定义?他们应该怎样覆盖图片?
HOG 和 SIFT 都基于图像邻域的两层表示:首先,将相邻像素组织成单元,然后将相邻单元组织成块。计算每个单元的方向直方图,并将单元直方图矢量连接起来,形成整个块的最终特征描述符。
SIFT 使用16x16
像素的单元,将其组织成 8 个方向的容器,然后通过4x4
单元的块分组,使得图像邻域的4x4x8=128
个特征。
HOG 论文实验用矩形和圆形形状的单元和块。矩形单元称为 R-HOG。最好的 R-HOG 设置为8x8
像素的 9 个定向仓,每个分组为2x2
个单元的块。圆形窗口称为 C-HOG,具有由中心单元的半径确定的变量、单元是否径向分裂、外单元的宽度等。
无论邻域如何组织,它们通常重叠形成整个图像的特征向量。换言之,单元和块在水平方向和垂直方向上横移图像,一次只有几个像素,以覆盖整个图像。
邻域结构的主要组成部分是多层次的组织和重叠的窗口,其在图像上移动。在深度学习网络的设计中使用了相同的成分。
什么样的归一化?
归一化处理出特征描述符,使得它们具有可比的大小。它是缩放的同义词。我们发现,文本特征的特征缩放(以 tf-idf 的形式)对分类精度没有很大影响。图像特征与文字区别很大,其对在自然图像中出现的照明和对比度的变化可能是非常敏感的。例如,在强烈的聚光灯下观察苹果的图像,而不是透过窗户发出柔和的散射光。即使物体是相同的,图像梯度也会有非常不同的幅度。为此,计算机视觉中的图像特征通常从全局颜色归一化开始,以消除照度和对比度方差。对于 SIFT 和 HOG 来说,结果表明,只要我们对特征进行归一化,这种预处理是不必要的。
SIFT 遵循归一化-阈值-归一化方案。首先,块特征向量归一化为单位长度(L2 标准化)。然后,将特征剪辑除以最大值以摆脱极端的照明效果,如从相机的色彩饱和度。最后,将剪切特征再次归一化到单位长度。
HOG 论文实验涉及不同的归一化方案例如 L1 和 L2,包括 SIFT 论文中标归一化-阈值-归一化方案。他们发现L1归一化比其他的方法稍显不靠谱。
SIFT 结构
SIFT 需要相当多的步骤。HOG 稍微简单,但是遵循许多相同的基本步骤,如梯度直方图和归一化。图 8-6 展示了 SIFT 体系结构。从原始图像中的感兴趣区域开始,首先将区域划分为网格。然后将每个网格单元进一步划分为子网格。每个子网格元素包含多个像素,并且每个像素产生梯度。每个子网格元素产生加权梯度估计,其中权重被选择以使得子网格元素之外的梯度可以贡献。然后将这些梯度估计聚合成子网格的方向直方图,其中梯度可以具有如上所述的加权投票。然后将每个子网格的方向直方图连接起来,形成整个网格的长梯度方向直方图。(如果网格被划分为2x2
子网格,那么将有 4 个梯度方向直方图拼接成一个。)这是网格的特征向量。从这开始,它经过一个归一化-阈值-归一化过程。首先,将向量归一化为单位范数。然后,将单个值剪辑除以最大阈值。最后,再次对阈值向量进行归一化处理。这是图像块的最终 SIFT 特征描述。