以图搜图系统工程实践

之前写过一篇概述: 以图搜图系统概述 。

以图搜图系统需要解决的主要问题是:

提取图像特征向量(用特征向量去表示一幅图像)

特征向量的相似度计算(寻找内容相似的图像)

对应的工程实践,具体为:

卷积神经网络 CNN 提取图像特征

向量搜索引擎 Milvus

CNN

使用卷积神经网路 CNN 去提取图像特征是一种主流的方案,具体的模型则可以使用 VGG16 ,技术实现上则使用 Keras + TensorFlow ,参考 Keras 官方示例:

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)

这里提取出来的 feature 就是特性向量。

1、归一化

为了方便后续操作,我们常常会将 feature 进行归一化的处理:

from numpy import linalg as LA

norm_feat = feat[0]/LA.norm(feat[0])

后续实际使用的也是归一化后的 norm_feat 。

2、Image 说明

这里加载图像使用的是 keras.preprocessing 的 image.load_img 方法即:

from keras.preprocessing import image

img_path = 'elephant.jpg'

img = image.load_img(img_path, target_size=(224, 224))

实际上是 Keras 调用的 TensorFlow 的方法,详情见 TensorFlow 官方文档 ,而最后得到的 image 对象其实是一个 PIL Image 实例( TensorFlow 使用的 PIL )。

3、Bytes 转换

实际工程中图像内容常常是通过网络进行传输的,因此相比于从 path 路径加载图片,我们更希望直接将 bytes 数据转换为 image 对象即 PIL Image :

import io

from PIL import Image

# img_bytes: 图片内容 bytes

img = Image.open(io.BytesIO(img_bytes))

img = img.convert('RGB')

img = img.resize((224, 224), Image.NEAREST)

以上 img 与前文中的 image.load_img 得到的结果相同,这里需要注意的是:

必须进行 RGB 转换

必须进行 resize ( load_img 方法的第二个参数也就是 resize )

4、黑边处理

有时候图像会有比较多的黑边部分(例如截屏),而这些黑边的部分即没有实际价值,又会产生比较大的干扰,因此去除黑边也是一项常见的操作。

所谓黑边,本质上就是一行或一列的像素点全部都是 (0, 0, 0) ( RGB 图像),去除黑边就是找到这些行或列,然后删除,实际是一个 numpy 的 3-D Matrix 操作。

移除横向黑边示例:

# -*- coding: utf-8 -*-

import numpy as np

from keras.preprocessing import image

def RemoveBlackEdge(img):

"""移除图片横向黑边

Args:

img: PIL image 实例

Returns:

PIL image 实例

"""

width = img.width

img = image.img_to_array(img)

img_without_black = img[~np.all(img == np.zeros((1, width, 3), np.uint8), axis=(1, 2))]

img = image.array_to_img(img_without_black)

return img

CNN 提取图像特征以及图像的其它相关处理先写这么多,我们再看向量搜索引擎。

向量搜索引擎 Milvus

只有图像的特征向量是远远不够的,我们还需要对这些特征向量进行动态的管理(增删改),以及计算向量的相似度并返回最邻近范围内的向量数据,而开源的向量搜索引擎 Milvus 则很好的完成这些工作。

下文将会讲述具体的实践,以及要注意的地方。

1、对 CPU 有要求

想要使用 Milvus ,首先必须要求你的 CPU 支持 avx2 指令集,如何查看你的 CPU 支持哪些指令集呢?对于 Linux 系统,输入指令

cat /proc/cpuinfo | grep flags

你将会看到形如以下的内容:

flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand lahf_lm abm cpuid_fault epb invpcid_single pti intel_ppin tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid cqm xsaveopt cqm_llc cqm_occup_llc dtherm ida arat pln pts

flags 后面的这一大堆就是你的 CPU 支持的全部指令集,当然内容太多了,我只想看是否支持具体的某个指令集,比如 avx2 , 再加一个 grep 过滤一下即可:

cat /proc/cpuinfo | grep flags | grep avx2

如果执行结果没有内容输出,就是不支持这个指令集,你只能换一台满足要求的机器。

2、容量规划

系统设计时,容量规划是需要首先考虑的地方,我们需要存储多少数据,这些数据需要多少内存以及多大的磁盘空间?

速算,上文中特征向量的每一个维度都是 float32 的数据类型,一个 float32 需要占用 4 byte,那么一个 512 维的向量就需要 2 KB ,依次类推:

一千个 512 维向量需要 2 MB

一百万 512 维向量需要 2 GB

一千万 512 维向量需要 20 GB

一个亿 512 维向量需要 200 GB

十个亿 512 维向量需要 2 TB

如果我们希望能将数据全部存在内存中,那么系统就至少需要对应大小的内存容量。

这里推荐你使用官方的大小计算工具: milvus tools

实际上我们的内存可能并没有那么大(内存不够没关系,milvus 会将数据自动刷写到磁盘上),另外除了这些原始的向量数据之外,还会有一些其他的数据例如日志等的存储也是我们需要考虑的地方。

3、系统配置

关于系统配置,官方文档有比较详细的说明:

4、数据库设计

collection & partition

在 Milvus 中,数据会按照 collection 和 partition 进行划分:

collection 就是我们理解的表。

partition 则是 collection 的分区,也就是某个表内部的分区。

partition 分区在底层实现上其实与 collection 集合是一致的,只是前者从属于后者,但是有了分区之后,数据的组织方式变得更加灵活,我们也可以指定集合中某个特定分区进行查询,从而达到一个更高的查询性能,更多内容参考 分区表详细说明 。

我们可以使用多少个 collection 和 partition ?

由于 collection 和 partition 的基本信息都属于元数据,而 milvus 内部进行元数据管理需要使用 SQLite( milvus 内部集成)或者 MySQL (需要外部连接) 其中之一,如果你使用默认的 SQLite 去管理元数据的话,当集合和分区的数量过多时,性能损耗会很严重,因此集合和分区总数不要超过 50000 ( 0.8.0 及以后版本将会限制为 4096 ) ,需要设置更多的数量则建议使用外接 MySQL 的方式。

Milvus 的 collection 和 partition 内部支持的数据结构非常简单,只支持 ID + vector ,换句话说,表只有两列,一列是 ID ,一列是向量数据。

注意:

ID 目前只支持整数类型

我们需要保证 ID 在 collection 的层面是唯一的,而不是 partition 。

条件过滤

我们使用一些传统的数据库时,往往可以指定字段进行条件过滤,但是 Milvus 并不能直接支持这项功能,然而我们是可以通过集合和分区的设计去实现简单的条件过滤,例如,我们有很多图片数据,但是这些图片数据都明确的属于具体的用户,那么我们就可以按照用户去划分 partition ,这样查询的时候以用户作为过滤条件其实就是指定 partition 即可。

结构化数据与向量的映射

由于 milvus 只支持 ID + vector 的数据结构,而实际业务上我们最终需要的往往是具有业务意义的结构化数据,也就是说,我们需要通过 vector 向量最终找到结构化数据,因此我们需要通过 ID 去维护结构化数据与向量之间的映射关系:

结构化数据 ID 映射表 Milvus ID

索引类型选择

请参考以下文档:

5、搜索结果处理

Milvus 的搜索结果是 ID + distance 的集合:

ID : collection 中的 ID 。

distance : 0 ~ 1 的距离值,表示相似性程度,越小越相似。

过滤 ID 为 -1 的数据

当数据集过少的时候,搜索结果可能会包含 ID 为 -1 的数据,我们需要自己去过滤掉。

翻页

向量的搜索比较特别,查询的结果是按照相似性顺序,从最相似开始往后选取 topK 个数据( topK 需要搜索时由用户指定)。

Milvus 的搜索不支持翻页,如果我们希望在业务上实现这个功能,那么只能由我们自己去处理,比如,我想要每页 10 条数据,只显示第 3 页的数据,那么我们需要去取 topK = 30 的数据,然后只返回最后 10 条。

业务上的相似性阈值

两张图片的特征向量的距离 distance 范围是 0 ~ 1 ,有些时候我们需要在业务上去判定两张图片是否相似,这时就需要我们自己去设置一个距离的阈值,当 distance 小于阈值时就可以判定为相似,大于阈值时判定为不相似,这个也是需要根据具体的业务自己去处理。

结语

本文讲述了以图搜图系统进行工程实践时比较常见的内容,最后强烈推荐一下 Milvus 。

python tensorflow 以图搜图_以图搜图系统工程实践相关推荐

  1. arcgis批量出图python代码_【GIS进阶】ArcGIS批量出图_定义出图

    今天的文章是浩哥投稿!!! 下图是我欢呼雀跃的样子~~~~~ 本文亮点: 所有步骤都是用ArcGIS中各种工具和软件操作组合,未使用Arcpy与Python等需要使用代码的工具! 这次的这个批量出图又 ...

  2. twitter如何以图搜图_没有完整图时,如何使用图深度学习?你需要了解流形学习2.0版本...

    原标题:没有完整图时,如何使用图深度学习?你需要了解流形学习版本 流形学习,自 2000 年在著名的科学杂志<Science>被首次提出以来,已成为信息科学领域的研究热点.可能很多人会问, ...

  3. python多个箱线图_箱线图Python

    1) 箱线图,又称箱形图(boxplot)或盒式图,不同于一般的折线图.柱状图或饼图等传统图表,只是数据大小.占比.趋势等等的呈现,其包含一些统计学的均值.分位数.极值等等统计量,因此,该图信息量较大 ...

  4. 计算机及网络应用基础思维导图_思维导图在生物教学中的应用

    思维导图又叫心智图,是由一个中心向周围有层次的发散的图形,由词汇.图形.线条.编号等构成,应用不同颜色的笔画出各级分支,既是一种思维工具又是一种学习方法.生物学科中含有大量的概念.生物分类.生物特征等 ...

  5. vue pc端 商品轮播图_轮播图高点击商品图

    轮播图由背景,商品图,文案三大部分组成,其中商品图是轮播图的主体内容,在轮播主图中,能不能通过一张商品图呈现出商品信息或者卖点,是影响点击率高低的重要因素.本期内容,我们将从商品图出发,为大家讲解的轮 ...

  6. 4米乘以12米CAD图_设备时序图的绘制方法

    每日一省:你觉得工作上还有哪些需要改进的地方? 在方案说明书中常用C/T来作为设备性能参数,说明设备的生产能力.C/T是指设备完成一个完整动作周期所需要的时间.设备的理论C/T是通过时序图的分析得到的 ...

  7. 关于主机的思维导图_思维导图正流行,现在教孩子还不晚(实操篇)

      清华爸+南大妈的育儿思考自留地 点击上方蓝字,即可成功订阅 *作者:小延妈,家有一年级男宝,南京大学新闻系毕业,资深文艺青年,古文爱好者.前几天,在一个"鸡娃"群中,有宝妈分享 ...

  8. mysql er 图_数据库ER图基础概念整理

    ER图分为实体.属性.关系三个核心部分 图形表示分别是 长方形,椭圆形,菱形 一,组成部分介绍 1,实体(entity):数据模型中的数据对像,每个实体都有自己的实体成员或者说实体对象,例如学生实体包 ...

  9. python以图搜图_以图搜图(一):Python实现dHash算法(转)

    近期研究了一下以图搜图这个炫酷的东西.百度和谷歌都有提供以图搜图的功能,有兴趣可以找一下.当然,不是很深入.深入的话,得运用到深度学习这货.Python深度学习当然不在话下. 这个功能最核心的东西就是 ...

  10. 公众号python搜题_免费搜题公众号python

    免费搜题公众号python 科技新闻 2020-09-16 23:12128未知admin 免费搜题公众号python 更多相关问题 [单选题]大灯的种类有很多,功能可分为疝气大灯和普通大灯;外观可分 ...

最新文章

  1. css3弹性盒子模型之box-flex
  2. 【STSRM13】绵津见
  3. php 文档输出,PHP输出
  4. Netflix 如何使用机器学习来提升流媒体质量
  5. boost::hana::remove_if用法的测试程序
  6. LeetCode 997. 找到小镇的法官(图的出度和入度)
  7. jdk1.8新特性之lambda表达式及在Android Studio中的使用举例
  8. javascript基础知识系列:eval()
  9. 数据包络分析(DEA)
  10. HttpClientHelper
  11. 取次花丛懒回顾,半缘修道半缘君。
  12. 通过耳道形状来验证用户身份?苹果:未来,AirPods可能实现
  13. MID-TERM EXAMINATION 1
  14. 解锁iPhone密码锁?
  15. 给RTL8111网卡固定MAC地址的一种方法
  16. 什么样的男人才算成熟男人?
  17. 二维码登录原理+Web端即时通讯技术
  18. Towards Spatio-Temporal Aware Traffic Time Series Forecasting
  19. 剑指offer面试题(31-40)——java实现
  20. cct考试模拟试题c语言,计算机一级(CCT)考试模拟题

热门文章

  1. shanzhi -接小球游戏2.0
  2. matlab 马氏距离 实例,MATLAB求马氏距离(Mahalanobis distance)
  3. 使用canvas 画钟表
  4. 计算机设置开机密码时间屏保,电脑屏幕保护密码设置方法
  5. jquery ztree 皮肤(官网介绍)
  6. Excel批注教学:一键添加多个不同批注
  7. 组态王通过Modbus TCP与ESP32通讯
  8. Qt VS Tools插件官方下载及安装
  9. refresh()方法
  10. Python—字典的操作