利用深度学习手把手教你实现一个「以图搜图」

文中源码可在微信公众号「01二进制」后台回复「图像检索」获取。

前言

在上一篇文章《图像检索系列——利用 Python 检测图像类似度》中,咱们介绍了一个在图像检索领域很是经常使用的算法——感知哈希算法。这是一个很简单且快速的算法,其原理在于针对每一张图片都生成一个特定的“指纹”,而后采起一种类似度的度量方式得出两张图片的近似程度。html

然而随着深度学习的崛起,极大的推进了图像领域的发展,在提取特征这方面而言,神经网络目前有着不可替代的优点。在上一篇文章中咱们也介绍了图像检索每每是基于图像的特征比较,看特征匹配的程度有多少,从而检索出类似度高的图片。而检测图像特征,VGG16具备得天独厚的优点。python

接下来本文将会经过一个简单的案例来实现一个基于深度学习的图像检索小工具。git

准备工做

老样子,先来准备好咱们这次须要使用到的工具:github

  • IDE:Pycharm
  • Python:3.7
  • Packages:Keras + TensorFlow + Pillow + Numpy

kerasweb

Keras是一个高层神经网络API,Keras由纯Python编写而成并基TensorflowTheano以及CNTK后端。简单来讲,keras就是对TF等框架的再一次封装,使得使用起来更加方便。算法

基于vgg16网络提取图像特征
咱们都知道,vgg网络在图像领域有着普遍的应用,后续许多层次更深,网络更宽的模型都是基于此扩展的,vgg网络能很好的提取到图片的有用特征,本次实现是基于Keras实现的,提取的是最后一层卷积特征。数据库

思路

主要思路是基于CVPR2015的论文《Deep Learning of Binary Hash Codes for Fast Image Retrieval》实现的海量数据下的基于内容图片检索系统。简单说来就是对图片数据库的每张图片抽取特征(通常形式为特征向量),存储于数据库中,对于待检索图片,抽取一样的特征向量,而后并对该向量和数据库中向量的距离(类似度计算),找出最接近的一些特征向量,其对应的图片即为检索结果。以下图所示:后端

用户请求和预处理部分主要是Web服务端应该作的,这里不加以讨论,接下来咱们主要进行红线标注部分的实现。数组

实操

提取图片特征

keras在其中文文档中提供了一个利用VGG16提取特征的demo微信

from keras.applications.vgg16 import VGG16
from keras.preprocessing import image
from keras.applications.vgg16 import preprocess_input
import numpy as np

model = VGG16(weights='imagenet', include_top=False)

img_path = 'elephant.jpg'
img = image.load_img(img_path, target_size=(224, 224))
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
x = preprocess_input(x)

features = model.predict(x)

这里咱们须要对其进行简单修改,封装成一个类以便后期调用。以下图所示:

考虑到篇幅,文中代码图片已删除较多注释,如需了解详细注释信息,可在微信公众号「01二进制」后台回复「图像检索」获取源代码。下同

将特征以及对应的文件名保存为h5文件

什么是 h5 文件

h5文件是层次数据格式第5代的版本(Hierarchical Data Format,HDF5),用以存储和组织大规模数据。

H5将文件结构简化成两个主要的对象类型:

  1. 数据集dataset,就是同一类型数据的多维数组
  2. 组group,是一种容器结构,能够包含数据集和其余组,若一个文件中存放了不一样种类的数据集,这些数据集的管理就用到了group

直观的理解,能够参考咱们的文件系统,不一样的文件存放在不一样的目录下:

目录就是 hdf5 文件中的 group,描述了数据集 DataSet 的分类信息,经过 group 有效的将多种 dataset 进行管理和划分。文件就是 hdf5 文件中的 dataset,表示具体的数据

下图就是数据集和组的关系:

在 Python 中,咱们一般使用 h5py 库对 .h5 文件进行操做,具体的读写方法自行百度,这里不在演示。

抽取数据集中的图像特征保存到 h5 文件中

咱们在项目根目录下命名一个database文件夹做为数据集,而后编写一个获取文件夹内图片的方法:

def get_imlist(path):
    return [os.path.join(path, f) for f in os.listdir(path) if f.endswith('.jpg')]

随后咱们即可以依次读取数据而后,一一提取其特征保存到文件中了。以下图:

至此,咱们就已经算是完成了模型的训练了。

选一张测试图片测试检索效果

通过上述操做,咱们已经将数据集中的全部图片的特征保存到模型中了,剩下的就是抽取待测图片的特征,而后和特征集中的特征一一比较向量间的类似度(余弦类似度),而后按照类似度排序返回给用户便可。

Tips:各类类似度的 Python 表示能够参考 Python Numpy计算各种距离

以某一个包包为测试图片,输出结果以下所示:

在PyCharm中能够很方便的查看matplotlib生成的图片,第一张为测试图片,后面三张为检索图片,能够看出效果至关好了。

Tips:若是想用Resnet或者Densenet提取特征,只需针对上述代码作出相应的修改,去掉注释修改部分代码便可。详见源码。

最后

至此咱们已经利用深度学习实现了一个图片检索的小工具了,如何将其和web/app结合到一块儿就不在本文的讨论范围了,有兴趣能够下载本文源码自行更改,也可扫描下方二维码关注微信公众号「01二进制」与我取得联系。

参考

  1. 深度学习与计算机视觉(11)_基于deep learning的快速图像检索系统
  2. 基于VGG-16的海量图像检索系统(以图搜图升级版)
  3. 基于深度学习实现以图搜图功能
  4. 各类类似度计算的python实现
  5. Application应用
  6. Python Numpy计算各种距离
  7. h5文件简介
相关文章
相关标签/搜索