三种适合初学者的特征提取技术

介绍

您以前是否使用过图像数据?或许您想要建立自己的物体检测模型,或者只是想计算进入大楼的人数。使用计算机视觉技术处理图像的可能性是无穷无尽的。

但我最近观察数据科学发展的趋势,人们坚信,在处理非结构化数据(尤其是图像数据)时,深度学习模型是发展的方向。深度学习技术无疑表现得非常好,但这是处理图像的唯一方法吗?

并非所有人都拥有像Google和Facebook等技术巨头那样的无限资源。那么如果不使用深度学习,我们如何处理图像数据呢?

我们可以借助机器学习的力量!是的,我们可以使用简单的机器学习模型,例如决策树或支持向量机(SVM)。如果我们提供合适的数据和功能,这些机器学习模型可以充分发挥作用,甚至可以用作基准解决方案。

因此,在这篇适合初学者的文章中,我们将了解图像提取特征的不同方式。然后,您可以在自己喜欢的机器学习算法中使用这些方法!

目录

  1. 计算机如何保存图像?
  2. 使用Python读取图像数据
  3. 特征提取方法1:作为特征的灰度像素值
  4. 特征提取方法2:通道平均像素值
  5. 特征提取方法3:边缘提取

计算机如何保存图像?

在学习其他内容之前,了解如何在计算机上读取和存储图像非常重要。首先考虑pd.read_ 函数读取图像。

来看一个简单的例子。看下图:

我们有一个数字8的图像。仔细观察图像,会发现它是由小方框组成的,称为像素。

但是我们是以视觉形式看到的图像,可以轻松区分边缘和颜色,识别图片中的内容。但是计算机很难做到这一点。它们是以数字的形式存储图像。看看下面的图片:

计算机以数字矩阵的形式存储图像。矩阵的大小取决于给定图像中的像素数。

假设矩阵的大小为 180 x 200 或 n x m,基本上就是图像的像素数量(高x宽)。

这些像素值表示像素的强度或亮度。较小的数字(接近零)表示黑色,较大的数字(接近于255)表示白色。

下图的尺寸为 22 x 16:

上面的例子是黑白图像。那彩色图像是什么样子?彩色图像也是以二维矩阵的形式存储的吗?

彩色图像通常由多种颜色组成,几乎所有的颜色都可以从三种基色(红色,绿色和蓝色)生成。

因此,在彩色图像中有三个矩阵(或称为通道),分别表示红色,绿色和蓝色。每个矩阵具有0-255之间的值,表示该像素的颜色强度。观察下面的图像:

左边有一个彩色图像,右边有三个颜色通道矩阵。通过叠加三个通道以形成彩色图像。

注意这里的矩阵并不是给定图像的原始像素值,因为给定图像的矩阵非常大并且难以可视化。另外,还有许多其他的存储图像的格式,其中RGB方式是最受欢迎的,也就是上面的例子。

用Python读取图像数据

把理论知识付诸实践。我们将使用Python加载图像并查看图像矩阵的内容:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from skimage.io import imread, imshow

image = imread('image_8_original.png', as_gray=True)
imshow(image)
#checking image shape 
image.shape, image
(28,28)

矩阵一共有784个值,这里只是完整矩阵的一小部分。

特征提取方法1:像素值作为特征

从图像提取特征的最简单方法是将这些原始像素值作为单独的特征。

以上面图像为例(数字'8'),图像的大小是28 x 28。

你能猜出这张图片的特征数量吗?特征的数量与像素的数量相同!因此,特征数量是784。

那我们如何保存这784个特征?我们可以简单地累加每个像素值来生成特征向量。如下图所示:

使用Python读取图像并使用该方法提取特征:

image = imread('puppy.jpeg', as_gray=True) 
image.shape, imshow(image)
(650,450)

这个图像大小是 650 x 450。因此,它的特征数量应该是 297000。通过使用NumPy中的reshape函数生成特征:

#像素特征

features = np.reshape(image, (660*450))

features.shape, features
(297000,)
数组([0.96470588,0.96470588,0.96470588,...,0.96862745,0.96470588, 0.96470588])

我们得到了该图像的特征,是一个长度为 297000的一维数组。

在该例子中,图像只有一个通道。可以将该方法应用在彩色图像上面吗?

特征提取方法 2:通道平均像素值

在上一节中,我们设置了参数 as_gray = True,所以图像只有一个通道,可以很容易地累加像素值。接下来删除参数并再次加载图像:

image = imread('puppy.jpeg') 
image.shape
(660,450,3)

该图像的大小是(660,450,3),其中的3是通道数量。我们可以使用上面的方法提取特征。在这种情况下,特征的数量将是660 * 450 * 3 = 891000。

或者,也可以使用另一种方法:

生成一个三个通道像素的平均值的新矩阵,而不是直接使用三个矩阵的像素值。

如下图所示:

这样处理之后特征的数量将保持不变,并且还考虑了图像的三个通道的像素值。在Python代码中,将创建一个大小为 660 x 450 的新矩阵,值初始化为0。这个矩阵会存储三个通道的平均像素值:

image = imread('puppy.jpeg')
feature_matrix = np.zeros((660,450)) 
feature_matrix.shape
(660,450)

有一个三维矩阵(660 x 450 x 3),其中660是高度,450是宽度,3是通道数。使用for循环获得平均像素值:

for i in range(0,iimage.shape[0]):
    for j in range(0,image.shape[1]):
        feature_matrix[i][j] = ((int(image[i,j,0]) + int(image[i,j,1]) + int(image[i,j,2]))/3)

新矩阵具有相同的高度和宽度,但只有1个通道。然后就可以按照上一节中的方法进行特征提取,累加像素值获得一维数组:

features = np.reshape(feature_matrix, (660*450)) 
features.shape
(297000,)

特征提取方法3:提取边缘特征

观察下面的图像,然后识别图像中的对象:

你可以马上分辨出物体,狗,汽车和猫。在分辨每个物体时你考虑了哪些特征?形状可能是一个重要因素,其次是颜色或大小。计算机可以像我们一样识别形状吗?

类似的想法是将边缘提取为特征作为模型的输入。我们是怎样识别图像的边缘的?边缘一般是颜色急剧变化的地方。如下图:

这里突出了两条边。我们之所以识别出边缘,是因为颜色从白色变为了棕色(右图),棕色变为了黑色(左侧)。正如我们所知,图像是以数字的形式表示,因此可以寻找像素值发生剧烈变化的地方。

假设图像有以下矩阵:

为了识别某个像素是否是边缘,我们可以简单地减去像素相邻的值。对于这个例子,考虑值85,找到值89和78之间的差异,这个差异不是很大,可以认为该像素周围没有边缘。

现在考虑像素125:

由于该像素两侧的值之间的差异很大,因此可以得出结论,在该像素处存在显着的转变,所以它应该是边缘的一部分。

有各种卷积核可以提取图像的边缘。上面的方法可以使用Prewitt核(x轴方向)实现。下面是Prewitt核:

首先获取该像素周围的值,和卷积核(Prewitt核)相乘,获得最终值。由于一列是-1而另一列是1,因此这些值相当于获取差异。

还有其他类型的卷积核,下面是四种最常用的:

接下来使用代码提取图像的边缘特征:

#导入包
import numpy as np
from skimage.io import imread, imshow
from skimage.filters import prewitt_h,prewitt_v
import matplotlib.pyplot as plt
%matplotlib inline

#读取图像
image = imread('puppy.jpeg',as_gray=True)

#使用prewitt提取水平边缘
edges_prewitt_horizontal = prewitt_h(image)
#使用prewitt提取垂直边缘
edges_prewitt_vertical = prewitt_v(image)

imshow(edges_prewitt_vertical, cmap='gray')

你可能感兴趣的:(三种适合初学者的特征提取技术)