图像检索系列——利用 Python 检测图像相似度

本文的代码可在微信公众号「01二进制」后台回复「检测图像相似度」获得。 前言 最近在做一个海量图片检索的项目,可以简单的理解为“以图搜图”,这个功能一开始是搜索引擎带火的,但是后来在电商领域变得非常实用。在制作这个图片检索的项目前,笔者搜索了一些资料,如今项目临近结尾,便在这里做一些简单的分享。本文先介绍图像检索最基础的一部分知识——利用 Python 检测图像相似度。 提到检测“某某”的相似度相信很多人第一想法就是将需要比较的东西构建成两个向量,然后利用余弦相似度来比较两个向量之间的距离,这种方法应用很广泛,例如比较两个用户兴趣的相似度、比较两个文本之间的相似度。但是这个方法在比较图片相似度的时候用到的并不多,原因我之后再说,这里先来介绍下另外两个概念——图像指纹和汉明距离。 图像指纹 图像指纹和人的指纹一样,是身份的象征,而图像指纹简单点来讲,**就是将图像按照一定的哈希算法,经过运算后得出的一组二进制数字。**如下图所示: 在给定的输入的图像中,我们可以使用一个散列函数, 并基于图像视觉上的外观计算它的“图像散列”值,相似的头像,它的散列值应该也是相似的。构建图像指纹的算法被称为感知哈希算法(Perceptual Hash Algorithm)。 汉明距离 通过上述对图像指纹的描述我们知道了可以利用感知哈希算法将图片转换成某种字符串,而比较字符串有一种名为汉明距离的表示方法。以下定义摘自维基百科: 在信息论中,两个等长字符串之间的汉明距离(英语:Hamming distance)是两个字符串对应位置的不同字符的个数。换句话说,它就是将一个字符串变换成另外一个字符串所需要替换的字符个数。 通常用汉明距离来衡量两张图片的差异,汉明距离越小,则代表相似度越高。汉明距离为0,即代表两张图片完全一样。 感知哈希算法 常用的感知哈希算法有三个,分别是平均哈希算法(aHash)、感知哈希算法(pHash)、差异值哈希算法(dHash)。至于这三种哈希算法的介绍和比较很多博客都有写,而且很多库都支持直接计算哈希值,调用一下相关函数就可以了。这里就不多说了,推荐一篇文章👉 《图像相似度中的Hash算法》 代码可在微信公众号「01二进制」后台回复「检测图像相似度」获得 三种哈希算法的实现代码如下: ahash dhash phash 当然,你也可以选择安装ImageHash库,然后调用相应的hash函数来实现计算。 比较两个图片相似度的思路 所以看到这对于比较两张图片的相似度我们就有了一个简单的想法了,只要通过感知哈希算法获得图像的图像指纹,然后比较两个哈希值之间的汉明距离就可以了。 详细的步骤,阮一峰介绍了一个简单的图片搜索原理,可分为下面几步: 缩小尺寸。将图片缩小到 8x8 的尺寸,总共 64 个像素。这一步的作用是去除图片的细节,只保留结构、明暗等基本信息,摒弃不同尺寸、比例带来的图片差异。 简化色彩。将缩小后的图片,转为 64 级灰度。也就是说,所有像素点总共只有 64 种颜色。 计算平均值。计算所有 64 个像素的灰度平均值。 比较像素的灰度。将每个像素的灰度,与平均值进行比较。大于或等于平均值,记为 1 ;小于平均值,记为 0。 计算哈希值。将上一步的比较结果,组合在一起,就构成了一个 64 位的整数,这就是这张图片的指纹。组合的次序并不重要,只要保证所有图片都采用同样次序就行了。 这种方法对于寻找一模一样的图片是有效的,但是搜索「相似图片」的效果很差,也不能局部搜索,因此通常应用在**「检测图片是否侵权」**上。现在诸如谷歌识图、百度识图几乎都是采用深度学习的方式进行相似性检索,这个下篇文章介绍。 为什么余弦相似度不适合用来检测图片相似度 最后我们来讨论下为什么不使用余弦相似度来检测图片的相似度。开篇我们就说过如果需要用余弦相似度来衡量相似性,我们需要先构造两个向量。通常情况下我们会将图片转化为像素向量(基于像素点灰度值的频次),从而计算两个图片的相似度,这种做法其实就是计算两个图片的直方图的相似度,然而这样就只保留了像素的频次信息,丢掉了像素的位置信息,信息损失太大,只在某些场景下适用。用余弦相似度表示图片相似度的代码同样可以微信公众号「01二进制」后台回复「检测图像相似度」获得。 总结 本文介绍的方法都是通过非深度学习的手段来检测图像的相似度,虽然理解起来都很容易,但是每种方法都有局限性。想要制作一个图像检索系统虽然第一步都是比较图像的相似度,但现如今大多数都是通过深度学习的方法提取出图像特征,然后再进行比较,准确率大大提升。之后我将会讲述如何通过深度学习抽取图像特征的方式来比较图片的相似度。 由于能力有限,在整理描述的过程中难免会有些错误,如有建议,可以留言区批评指正🙏

plainify

图像检索系列——利用深度学习实现以图搜图

文中源码可在微信公众号「01 二进制」后台回复「图像检索」获取。 前言 在上一篇文章《图像检索系列——利用 Python 检测图像相似度》中,我们介绍了一个在图像检索领域非常常用的算法——感知哈希算法。这是一个很简单且快速的算法,其原理在于针对每一张图片都生成一个特定的“指纹”,然后采取一种相似度的度量方式得出两张图片的近似程度。 然而随着深度学习的崛起,极大的推动了图像领域的发展,在提取特征这方面而言,神经网络目前有着不可替代的优势。在上一篇文章中我们也介绍了图像检索往往是基于图像的特征比较,看特征匹配的程度有多少,从而检索出相似度高的图片。而检测图像特征,VGG16 具有得天独厚的优势。 接下来本文将会通过一个简单的案例来实现一个基于深度学习的图像检索小工具。 准备工作 老样子,先来准备好我们此次需要使用到的工具: IDE:Pycharm Python:3.7 Packages:Keras + TensorFlow + Pillow + Numpy keras Keras 是一个高层神经网络 API,Keras 由纯 Python 编写而成并基Tensorflow、Theano以及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....