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

作者: 人工智能遇见磐创 | 来源:发表于2019-10-03 19:40 被阅读0次

    介绍

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

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

    并非所有人都拥有像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')
    

    相关文章

      网友评论

        本文标题:三种适合初学者的特征提取技术

        本文链接:https://www.haomeiwen.com/subject/xrzdpctx.html