From dd91f867b11731cd02bb057d98e638176e39e80f Mon Sep 17 00:00:00 2001 From: RifeWang Date: Thu, 4 Jul 2024 16:31:57 +0800 Subject: [PATCH] image search system with client model --- .../image-search-use-client-model.md | 155 ++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 content/posts/engineering/image-search-use-client-model.md diff --git a/content/posts/engineering/image-search-use-client-model.md b/content/posts/engineering/image-search-use-client-model.md new file mode 100644 index 00000000..e8c8bf30 --- /dev/null +++ b/content/posts/engineering/image-search-use-client-model.md @@ -0,0 +1,155 @@ ++++ +draft = false +date = 2024-07-04T14:44:38+08:00 +title = "以图搜图架构优化:使用客户端模型提取图像特征" +description = "以图搜图架构优化:使用客户端模型提取图像特征" +slug = "" +authors = [] +tags = ["Engineering"] +categories = ["Engineering"] +externalLink = "" +series = [] +disableComments = true ++++ + +## 序言 + +以图搜图系统指的是从图像内容提取特征向量,然后使用向量数据库进行向量数据的插入、删除、相似性检索等操作,进而提供根据图像内容搜索出具有相似内容的其它图像的功能。 + +## 系统架构 + +典型的搜图系统整体架构时序图如下: + +![](https://raw.githubusercontent.com/RifeWang/images/master/engineering/image-search-system-arch.png) + +图像上传过程: +1. 客户端上传图像到服务端。 +1. 服务端存储图像至对象存储、插入结构化数据至关系型数据库、发送消息至 MQ 消息队列。 +1. 服务端对客户端请求返回响应。 +1. 图像搜索服务接受 MQ 的消息,下载图像内容,使用特定模型提取图像特征向量,然后将特征向量插入到向量数据库。 + +这里使用 MQ 的主要原因有: +- 异步快速响应,因为提取图像特征比较耗时,如果是同步的过程则会对客户端体验不友好。 +- 解耦服务、服务异构,提取图像特征属于计算机视觉领域,编程语言生态基本是 Python ,而后端服务则常见于 Java、Golang、Node.js 等,这在架构上就要求服务异构和解耦。 +- 削峰填谷,由于用户上传图像具有波峰波谷的天然特性,使用 MQ 可以使下游图像计算保持平稳。 + +图像搜索过程: +1. 客户端上传图像到服务端。 +1. 服务端发起调用并将图像传递到图像搜索服务,图像搜索服务提取图像特征向量,然后查询向量数据库进行相似性搜索,最后返回向量搜索结果。 +1. 服务端根据向量搜索结果查询结构化数据,整合数据,最后响应。 + +我们可以看到以上系统中,比较耗时的有两部分: +1. 图像传递链路长:客户端 -> 服务端 -> 对象存储 -> 图像搜索服务。 +1. 图像特征计算比较耗时、且比较消耗服务器资源。 + +## 使用客户端模型优化架构 + +为了进一步优化系统架构,我们可以尝试使用客户端模型进行图像特征提取。 + +![](https://raw.githubusercontent.com/RifeWang/images/master/engineering/image-search-system-arch-client-model.png) + +图像上传过程: +1. 客户端向服务端请求对象存储的直传地址,然后客户端直接将图像内容传递到对象存储(需要对象存储支持直传操作)。 +1. 客户端进行本地计算,提取图像特征向量,然后传递特征向量和结构化数据给服务端。 +1. 服务端对结构化数据和向量数据分别插入到不同的数据库,完成响应。 + +图像搜索过程: +1. 客户端进行本地计算,提取图像特征向量,然后传递特征向量和结构化数据给服务端。 +1. 服务端分别进行向量检索和结构化数据查询,整合数据,完成响应。 + +优化后的架构: +- 图像传递链路短,只有客户端 -> 对象存储。 +- 图像特征计算卸载到了客户端完成,服务器不需要再消耗计算资源。 +- 减少了 MQ 和图像搜索服务这两个构件,架构更加简单、复杂度降低。 + +## 客户端模型的可行性和约束 + +客户端相比于服务端具有硬件资源有限、且不可扩展的特点,因此这就要求客户端使用的模型要更小、计算消耗更少。 + +![](https://raw.githubusercontent.com/RifeWang/images/master/engineering/keras-models.jpg) + +我们根据上图中的模型对比可以看到 mobilenet 这种模型更符合我们的需求(模型的名字就能看出来)。 + +### 示例 + +以下给出一个前端使用 mobilenet 完成图像特征提取的示例: + +```html + + + + + + + + + + +

+
+    
+
+
+```
+
+然后在我的笔记本电脑简单测试的结果:
+
+![](https://raw.githubusercontent.com/RifeWang/images/master/engineering/mobilenet-test.png)
+
+从上图可以看到,在我的客户端处理一张图像可以在一秒内完成,当然实际耗时取决于硬件资源和图像大小。
+
+最后,如果你对此类主题感兴趣,可以阅读我的[其它相关文章](https://lingxu.pages.dev/categories/engineering/)。
+
+---
+
+参考资料:
+
+- *https://keras.io/api/applications/*
+- *https://www.tensorflow.org/js/models*
+- *https://github.com/tensorflow/tfjs-models/tree/master/mobilenet*
\ No newline at end of file