目前对于图像识别任务,最有效的方法是使用深度学习,比如卷积神经网络。但实际上,我们也可以通过其他简单的算法如KNN来识别图片,只不过比起卷积神经网络效果会差一些。

    非常经典的数据集叫做CIFAR-10。具体的下载地址可以通过下方链接来获得。 http://www.cs.toronto.edu/~kriz/cifar.html

    图像本身是一个非结构化的数据,而且非结构化数据本身是不能直接用来做模型输入的。

    简单来讲,文本、图片、声音、视频这些都属于非结构化数据,需要做进一步的处理。相反, 结构化的数据指的是存放在数据库里的年龄,身高等这种信息。对于图像来说,此过程相对简单。一般可以通过Python自带的库来读取图片,并把图片数据存放在矩阵(Matrix)或者张量(Tensor)里。

    图片是由像素来构成的,比如256256或者128128。两个值分别代表长宽上的像素。这个值越大图片就会越清晰。另外,对于彩色的图片,一个像素点一般由三维数组来构成,分别代表的是R,G,B三种颜色。除了RGB,其实还有其他常用的色彩空间。如果使用RGB来表示每一个像素点,一个大小为128128像素的图片实际大小为128128*3,是一个三维张量的形式。

    使用几行简单的代码来读取图片中的数据,以及展示图片的内容:

    import matplotlib.pyplot as plt
    # 读取图片的数据,存放到img
    img = plt.imread(‘/home/anaconda/data/RGZNXLY/ch3/sample.jpg’)
    print (img.shape) # 打印图片的大小
    plt.imshow(img) # 展示图片

    KNN模型的核心是计算距离。假设我们把图片转换成数据,之后无非就是计算两个矩阵/张量之间的距离罢了,这很明显不会考虑到遮挡物、形状、大小对图片的影响小以上几个问题,这也是为什么KNN这种方式得出来的效果并不是特别好的主要原因。那如果坚持使用KNN算法,有没有可能在效果上做一些提升呢?
    一种方法就是做图像上的特征工程。 在第二节里我们学会了如何把图片转换成像素值,我们可以把它认为是原始特征。但我们很难通过这些原始特征来理解图片中的一些特性。
    所以,在过去很长的时间里很多学者都在研究如何从图片里提取特征,而且这些特征可以很好地对图像做个总结,并且较好地处理不同环境带来的影响。 比如一个特征很少受图像亮度和角度的影响。第二种特征我们称作是rotation-invariant。

    经典的图像特征:
    搜狗截图20190923202643.png

    搜狗截图20190923202814.png

    颜色特征里最常用的是颜色直方图(color histogram),其实就是对R,G,B三种颜色做了一个统计,比如有百分之多少的R颜色落在[10,20]的区间。对于上面的这幅图,左边所展示的是构建完RGB直方图之后的结果。

    另外,SIFT特征也经常用在图像识别当中,它是一个局部的特征,它会试图去寻找图片中的拐点这类的关键点,然后再通过一系列的处理最终得到一个SIFT向量。

    最后,HOG也是非常重要的图像特征,它通过计算和统计图像局部区域的梯度方向直方图来构建特征。由于HOG是在图像的局部方格单元上操作,所以它对图像几何的和光学的形变都能保持很好的不变性。

    对于后两个特征的理解由于需要一些视觉相关的基础,不在这里详细阐述。现阶段,只需要知道有这类的特征,以及如何使用工具去抽取这些特征就可以了。

    除了这些特征可以较好地总结一个图片,它还有一个非常重要的优点,就是特征的降维。

    对于一个中小型图片,它的大小一般大于2562563。如果把它转换成向量,其实维度的大小已经几十万了。这会导致消耗非常大的计算资源,所以一般情况下我们都会尝试对图片做一些降维操作。其实特征提取过程我们自然地可以理解为是降维过程。

    这种降维操作会更好地保留图片中重要的信息,同时也帮助过滤掉无用的噪声。

    除了特征提取之外,我们还有一种常用的降维工具叫做PCA(Principal Component Analysis), 它是一种无监督的学习方法,可以把高维的向量映射到低维的空间里。它的核心思路是对数据做线性的变换,然后在空间里选择信息量最大的Top K维度作为新的特征值。

    其实PCA也经常用在图像识别任务中,比如人脸识别。另外,我们也可以通过PCA把高维的数据映射到2维或者3维空间里,然后再通过可视化来理解数据。