当前位置: 首页 > news >正文

向量检索:基于ResNet预训练模型构建以图搜图系统

1 项目背景介绍

以图搜图是一种向量检索技术,通过上传一张图像来搜索并找到与之相关的其他图像或相关信息。以图搜图技术提供了一种更直观、更高效的信息检索方式。这种技术应用场景和价值非常广泛,经常会用在商品检索及购物、动植物识别、食品识别、知识检索等领域。以图搜图涉及到的技术点如下:

  • 如何对图片数据进行向量编码
  • 如何对海量的向量数据进行存储
  • 如何快速对海量的向量数据进行检索

本项目基于Resnet预训练模型结合Milvus向量数据库,在水果数据集上实现了以图搜图系统,读者可以将数据集扩展到其它领域,构建满足自身业务的以图搜图系统。

2 关键技术介绍

2.1 Resnet网络

ResNet,全称为Residual Network,是深度学习领域中非常重要的卷积神经网络(Convolutional Neural Network,CNN)架构之一。它由Kaiming He等人在2015年提出,并在ImageNet图像分类比赛中取得了显著的成果,在当时获得分类任务,目标检测,图像分割第一名。ResNet的创新之处在于引入了残差连接(residual connections),允许网络在训练过程中更容易地训练深层网络。

在传统的神经网络中,随着网络层数的增加,性能可能会饱和甚至下降。这是因为梯度消失和梯度爆炸等问题会导致训练变得困难。ResNet通过引入残差块(residual block)来解决这个问题。每个残差块包括一个主要的卷积层,其输出与输入之间的差异被称为“残差”,然后将残差添加回来,得到最终的输出。这样的架构允许信息在网络中更容易地传播,即使网络变得非常深。

ResNet的经典网络结构有:ResNet-18、ResNet-34、ResNet-50、ResNet-101、ResNet-152几种,其中,ResNet-18和ResNet-34的基本结构相同,属于相对浅层的网络,后面3种属于更深层的网络,其中RestNet50最为常用。

 ResNet的优点包括:

  • 训练更深的网络: 引入残差连接允许构建非常深的网络,这些网络在训练时更容易收敛。
  • 避免梯度消失和爆炸: 残差连接有助于梯度在网络中更好地传播,减少了梯度消失和爆炸的问题。
  • 更好的特征学习: 残差块允许网络学习残差,即学习更容易捕获到的细粒度特征。

ResNet详细介绍:ResNet

2.2 Milvus向量数据库

Milvus 是一款云原生向量数据库,它具备高可用、高性能、易拓展的特点,用于海量向量数据的实时召回。

Milvus 基于FAISS、Annoy、HNSW 等向量搜索库构建,核心是解决稠密向量相似度检索的问题。在向量检索库的基础上,Milvus 支持数据分区分片、数据持久化、增量数据摄取、标量向量混合查询、time travel 等功能,同时大幅优化了向量检索的性能,可满足任何向量检索场景的应用需求。通常,建议用户使用 Kubernetes 部署 Milvus,以获得最佳可用性和弹性。

Milvus 采用共享存储架构,​存储计算完全分离​,计算节点支持横向扩展。从架构上来看,Milvus 遵循数据流和控制流分离,整体分为了四个层次,分别为接入层(access layer)、协调服务(coordinator service)、执行节点(worker node)和存储层(storage)。各个层次相互独立,独立扩展和容灾。

 Milvus 向量数据库能够帮助用户轻松应对海量非结构化数据(图片/视频/语音/文本)检索。单节点 Milvus 可以在秒内完成十亿级的向量搜索,分布式架构亦能满足用户的水平扩展需求。

milvus特点总结如下:

  • 高性能:性能高超,可对海量数据集进行向量相似度检索。
  • 高可用、高可靠:Milvus 支持在云上扩展,其容灾能力能够保证服务高可用。
  • 混合查询:Milvus 支持在向量相似度检索过程中进行标量字段过滤,实现混合查询。
  • 开发者友好:支持多语言、多工具的 Milvus 生态系统。

Milvus详细介绍:Milvus

3 系统代码实现

3.1 运行环境构建

conda环境准备详见:annoconda

git clone https://gitcode.net/ai-medical/image_image_search.git
cd image_image_searchpip install -r requirements.txt

3.2 数据集下载

下载地址:

第一个数据包:package01

第二个数据包:package01

在数据集目录下,存放着10个文件夹,文件夹名称为水果类型,每个文件夹包含几百到几千张此类水果的图片,如下图所示:

 以apple文件夹为例,内容如下:

下载后进行解压,保存到D:/dataset/fruit目录下,查看显示如下

# ll fruit/
总用量 508
drwxr-xr-x 2 root root 36864 8月   2 16:35 apple
drwxr-xr-x 2 root root 24576 8月   2 16:36 apricot
drwxr-xr-x 2 root root 40960 8月   2 16:36 banana
drwxr-xr-x 2 root root 20480 8月   2 16:36 blueberry
drwxr-xr-x 2 root root 45056 8月   2 16:37 cherry
drwxr-xr-x 2 root root 12288 8月   2 16:37 citrus
drwxr-xr-x 2 root root 49152 8月   2 16:38 grape
drwxr-xr-x 2 root root 16384 8月   2 16:38 lemon
drwxr-xr-x 2 root root 36864 8月   2 16:39 litchi
drwxr-xr-x 2 root root 49152 8月   2 16:39 mango

3.3 预训练模型下载

 'resnet18': 'https://download.pytorch.org/models/resnet18-f37072fd.pth','resnet34': 'https://download.pytorch.org/models/resnet34-b627a593.pth','resnet50': 'https://download.pytorch.org/models/resnet50-0676ba61.pth','resnet101': 'https://download.pytorch.org/models/resnet101-63fe2227.pth','resnet152': 'https://download.pytorch.org/models/resnet152-394f9c45.pth','resnext50_32x4d': 'https://download.pytorch.org/models/resnext50_32x4d-7cdf4587.pth','resnext101_32x8d': 'https://download.pytorch.org/models/resnext101_32x8d-8ba56ff5.pth','wide_resnet50_2': 'https://download.pytorch.org/models/wide_resnet50_2-95faca4d.pth','wide_resnet101_2': 'https://download.pytorch.org/models/wide_resnet101_2-32ee1156.pth',

下载resnet50的预训练模型:resnet50,存放到D:/models目录下

3.4 代码实现

3.4.1 创建database

from pymilvus import connections, dbconn = connections.connect(host="192.168.1.156", port=19530)
database = db.create_database("image_vector_db")db.using_database("image_vector_db")
print(db.list_database())

3.4.2 创建collection

from pymilvus import CollectionSchema, FieldSchema, DataType
from pymilvus import Collection, db, connectionsconn = connections.connect(host="192.168.1.156", port=19530)
db.using_database("image_vector_db")m_id = FieldSchema(name="m_id", dtype=DataType.INT64, is_primary=True,)
embeding = FieldSchema(name="embeding", dtype=DataType.FLOAT_VECTOR, dim=2048,)
path = FieldSchema(name="path", dtype=DataType.VARCHAR, max_length=256,)
schema = CollectionSchema(fields=[m_id, embeding, path],description="image to image embeding search",enable_dynamic_field=True
)collection_name = "fruit_vector"
collection = Collection(name=collection_name, schema=schema, using='default', shards_num=2)

 

3.4.3 创建index

from pymilvus import Collection, utility, connections, dbconn = connections.connect(host="192.168.1.156", port=19530)
db.using_database("image_vector_db")index_params = {"metric_type": "L2","index_type": "IVF_FLAT","params": {"nlist": 1024}
}collection = Collection("fruit_vector")
collection.create_index(field_name="embeding",index_params=index_params
)utility.index_building_progress("fruit_vector")

3.4.4 数据加载到milvus

from restnet_embeding import restnet_embeding
from milvus_operator import restnet_image, MilvusOperator
from PIL import Image, ImageSequence
import osdef update_image_vector(data_path, operator: MilvusOperator):idxs, embedings, paths = [], [], []total_count = 0for dir_name in os.listdir(data_path):sub_dir = os.path.join(data_path, dir_name)for file in os.listdir(sub_dir):image = Image.open(os.path.join(sub_dir, file)).convert('RGB')embeding = restnet_embeding.embeding(image)idxs.append(total_count)embedings.append(embeding[0].detach().numpy().tolist())paths.append(os.path.join(sub_dir, file))total_count += 1if total_count % 50 == 0:data = [idxs, embedings, paths]operator.insert_data(data)print(f'success insert {operator.coll_name} items:{len(idxs)}')idxs, embedings, paths = [], [], []if len(idxs):data = [idxs, embedings, paths]operator.insert_data(data)print(f'success insert {operator.coll_name} items:{len(idxs)}')print(f'finish update {operator.coll_name} items: {total_count}')if __name__ == '__main__':data_dir = 'D:/dataset/fruit'update_image_vector(data_dir, restnet_image)

3.4.5 基于Resnet预训练模型构建编码网络

加载预训练模型,去掉全连接层,是的Resnet编码输出特征维度为2048

from torchvision.models import resnet50
import torch
from torchvision import transforms
from torch import nnclass RestnetEmbeding:pretrained_model = 'D:/models/resnet50-0676ba61.pth'def __init__(self):self.model = resnet50()self.model.load_state_dict(torch.load(self.pretrained_model))# delete fc layerself.model.fc = nn.Sequential()self.transform = transforms.Compose([transforms.Resize((224, 224)),transforms.ToTensor(),transforms.Normalize(mean=[0.48145466, 0.4578275, 0.40821073],std=[0.26862954, 0.26130258, 0.27577711])])def embeding(self, image):trans_image = self.transform(image)trans_image = trans_image.unsqueeze_(0)return self.model(trans_image)restnet_embeding = RestnetEmbeding()

 3.4.6 构建检索web

import gradio as gr
import torch
import numpy as np
import argparse
from net_helper import net_helper
from PIL import Image
from restnet_embeding import restnet_embeding
from milvus_operator import restnet_imagedef image_search(image):if image is None:return Noneimage = image.convert("RGB")# restnet编码imput_embeding = restnet_embeding.embeding(image)imput_embeding = imput_embeding[0].detach().cpu().numpy()results = restnet_image.search_data(imput_embeding)pil_images = [Image.open(result['path']) for result in results]return pil_imagesif __name__ == "__main__":parser = argparse.ArgumentParser()parser.add_argument("--share", action="store_true",default=False, help="share gradio app")args = parser.parse_args()device = torch.device("cuda" if torch.cuda.is_available() else "cpu")app = gr.Blocks(theme='default', title="image",css=".gradio-container, .gradio-container button {background-color: #009FCC} ""footer {visibility: hidden}")with app:with gr.Tabs():with gr.TabItem("image search"):with gr.Row():with gr.Column():image = gr.inputs.Image(type="pil", source='upload')btn = gr.Button(label="search")with gr.Column():with gr.Row():output_images = [gr.outputs.Image(type="pil", label=None) for _ in range(16)]btn.click(image_search, inputs=[image], outputs=output_images, show_progress=True)ip_addr = net_helper.get_host_ip()app.queue(concurrency_count=3).launch(show_api=False, share=True, server_name=ip_addr, server_port=9099)

4 总结

本项目基于Resnet预训练模型及milvus向量数据库两个关键技术,构建了以图搜图的图像检索系统;在构建过程中,对Resnet网络模型进行了改造,去掉了全连接层,经过Restnet编码后每个图片输出向量维度为2048,存入milvus向量数据库;为保证图像检索的效率,通过脚本在milvus向量数据库中构建了向量索引。此项目可作为参考,在实际开发类似的以图搜图项目中直接使用。

项目完整代码地址:code

相关文章:

向量检索:基于ResNet预训练模型构建以图搜图系统

1 项目背景介绍 以图搜图是一种向量检索技术,通过上传一张图像来搜索并找到与之相关的其他图像或相关信息。以图搜图技术提供了一种更直观、更高效的信息检索方式。这种技术应用场景和价值非常广泛,经常会用在商品检索及购物、动植物识别、食品识别、知…...

SpringBoot 响应头添加版本号、打包项目后缀添加版本号和时间

文章目录 响应头添加版本号获取版本号添加响应处理器请求结果 打包项目后缀添加版本号和时间实现打包结果 响应头添加版本号 获取版本号 在 pom.xml 中,在 project.version 下定义版本号 在 application.yml 获取 pom.xml 中 project.version 中的信息 添加响应处…...

优化指南:带宽限制的可行策略

大家好!作为一名专业的爬虫程序员,我们经常面临的一个挑战就是带宽限制。尤其是在需要快速采集大量数据时,带宽限制成为了我们提升爬虫速度的一大阻碍。今天,我将和大家分享一些解决带宽限制的可行策略,希望能帮助大家…...

计算机提示mfc120u.dll缺失(找不到)怎么解决

在计算机领域,mfc120u.dll是一个重要的动态链接库文件。它包含了Microsoft Foundation Class (MFC) 库的特定版本,用于支持Windows操作系统中的应用程序开发。修复mfc120u.dll可能涉及到解决与该库相关的问题或错误。这可能包括程序崩溃、运行时错误或其…...

Java基于SpringBoot+Vue实现酒店客房管理系统(2.0 版本)

文章目录 一、前言介绍二、系统结构三、系统详细实现3.1用户信息管理3.2会员信息管理3.3客房信息管理3.4收藏客房管理3.5用户入住管理3.6客房清扫管理 四、部分核心代码 博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W,Csdn博客专家、掘金/华为云/阿里云…...

微服务架构2.0--云原生时代

云原生 云原生(Cloud Native)是一种关注于在云环境中构建、部署和管理应用程序的方法和理念。云原生应用能够最大程度地利用云计算基础设施的优势,如弹性、自动化、可伸缩性和高可用性。这个概念涵盖了许多方面,包括架构、开发、…...

C++day2作业(2023.8.22)

1.定义一个学生的结构体,包含学生的姓名,年龄,成绩,性别,学生的成绩,姓名,定义为私有权限;定义一个学生类型的结构体变量,设置公有函数用于给学生的成绩和名字进行赋值&a…...

在 Spring Boot 中使用 OpenAI ChatGPT API

1、开始咯 我们来看看如何在 Spring Boot 中调用 OpenAI ChatGPT API。 我们将创建一个 Spring Boot 应用程序,该应用程序将通过调用 OpenAI ChatGPT API 生成对提示的响应。 2、OpenAI ChatGPT API 在开始具体讲解之前,让我们先探讨一下我们将在本教…...

【leetcode】225.用队列实现栈

分析: 队列遵循先入先出的原则,栈遵循后入先出的原则 也就是说,使用队列实现栈时,入队操作正常,但是出队要模拟出栈的操作,我们需要访问的是队尾的元素;题目允许使用两个队列,我们可…...

机器学习中XGBoost算法调参技巧

本文将详细解释XGBoost中十个最常用超参数的介绍,功能和值范围,及如何使用Optuna进行超参数调优。 对于XGBoost来说,默认的超参数是可以正常运行的,但是如果你想获得最佳的效果,那么就需要自行调整一些超参数来匹配你…...

第1章:计算机网络体系结构

文章目录 1.1 计算机网络 概述1.概念2.组成3.功能4.分类5.性能指标1.2 计算机网络 体系结构&参考模型1.分层结构2.协议、接口、服务3.ISO/OSI模型4.TCP/IP模型1.1 计算机网络 概述 1.概念 2.组成 1.组成部分&...

【Java 动态数据统计图】动态数据统计思路Demo(动态,排序,containsKey)三(115)

上代码&#xff1a; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map;public class day10 {public static void main(String[] args) {List<Map<String,O…...

【游戏评测】河洛群侠传一周目玩后感

总游戏时长接近100小时&#xff0c;刚好一个月。 这两天费了点劲做了些成就&#xff0c;刷了等级&#xff0c;把最终决战做了。 总体感觉还是不错的。游戏是开放世界3D游戏&#xff0c;Unity引擎&#xff0c;瑕疵很多&#xff0c;但胜在剧情扎实&#xff0c;天赋系统、秘籍功法…...

java新特性之Lambda表达式

函数式编程 关注做什么&#xff0c;不关心是怎么实现的。为了实现该思想&#xff0c;java有了一种新的语法格式&#xff0c;Lambda表达式。Lambda本质是匿名内部类对象&#xff0c;是一个函数式接口。函数式接口表示接口内部只有一个抽象方法。使用该语法可以大大简化代码。 …...

【考研数学】线形代数第三章——向量 | 2)向量组相关性与线性表示的性质,向量组的等价、极大线性无关组与秩

文章目录 引言二、向量组的相关性与线性表示2.3 向量组相关性与线性表示的性质 三、向量组等价、向量组的极大线性无关组与秩3.1 基本概念 写在最后 引言 承接前文&#xff0c;我们来学习学习向量组相关性与线性表示的相关性质 二、向量组的相关性与线性表示 2.3 向量组相关性…...

Java中调用Linux脚本

在Java中&#xff0c;可以使用ProcessBuilder类来调用Linux脚本。以下是一个简单的示例&#xff0c;展示了如何在Java中调用Linux脚本&#xff1a; 创建一个Linux脚本文件&#xff08;例如&#xff1a;myscript.sh&#xff09;&#xff0c;并在其中编写需要执行的命令。确保脚…...

Nexus 如何配置 Python 的私有仓库

Nexus 可作为一个代理来使用。 针对一些网络环境不好的公司&#xff0c;可以通过配置 Nexus 来作为远程的代理。 Group 概念 Nexus 有一个 Group 的概念&#xff0c;我们可以认为一个 Nexus 仓库的 Group 就是很多不同的仓库的集合。 从下面的配置中我们可以看到&#xff0…...

Maven 配置文件修改及导入第三方jar包

设置java和maven的环境变量 修改maven配置文件 &#xff08;D:\app\apache-maven-3.5.0\conf\settings.xml&#xff0c;1中环境变量对应的maven包下的conf&#xff09; 修改131行左右的mirror&#xff0c;设置阿里云的仓库地址 <mirror> <id>alimaven</id&g…...

jmeter CSV 数据文件设置

创建一个CSV数据文件&#xff1a;使用任何文本编辑器创建一个CSV文件&#xff0c;将测试数据按照逗号分隔的格式写入文件中。例如&#xff1a; room_id,arrival_date,depature_date,bussiness_date,order_status,order_child_room_id,guest_name,room_price 20032,2023-8-9 14:…...

【SA8295P 源码分析】20 - GVM Android Kernel NFS Support 配置

【SA8295P 源码分析】20 - GVM Android Kernel NFS Support 配置 系列文章汇总见:《【SA8295P 源码分析】00 - 系列文章链接汇总》 本文链接:《【SA8295P 源码分析】20 - GVM Android Kernel NFS Support 配置》 # make menuconfigFile systems ---> [*] Network File Sy…...

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API&#xff0c;用于在函数组件中使用 state 和其他 React 特性&#xff08;例如生命周期方法、context 等&#xff09;。Hooks 通过简洁的函数接口&#xff0c;解决了状态与 UI 的高度解耦&#xff0c;通过函数式编程范式实现更灵活 Rea…...

零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?

一、核心优势&#xff1a;专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发&#xff0c;是一款收费低廉但功能全面的Windows NAS工具&#xff0c;主打“无学习成本部署” 。与其他NAS软件相比&#xff0c;其优势在于&#xff1a; 无需硬件改造&#xff1a;将任意W…...

React Native 开发环境搭建(全平台详解)

React Native 开发环境搭建&#xff08;全平台详解&#xff09; 在开始使用 React Native 开发移动应用之前&#xff0c;正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南&#xff0c;涵盖 macOS 和 Windows 平台的配置步骤&#xff0c;如何在 Android 和 iOS…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:

一、属性动画概述NETX 作用&#xff1a;实现组件通用属性的渐变过渡效果&#xff0c;提升用户体验。支持属性&#xff1a;width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项&#xff1a; 布局类属性&#xff08;如宽高&#xff09;变化时&#…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

SpringTask-03.入门案例

一.入门案例 启动类&#xff1a; package com.sky;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCach…...

什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南

文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/55aefaea8a9f477e86d065227851fe3d.pn…...

Swagger和OpenApi的前世今生

Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章&#xff0c;二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑&#xff1a; &#x1f504; 一、起源与初创期&#xff1a;Swagger的诞生&#xff08;2010-2014&#xff09; 核心…...

Device Mapper 机制

Device Mapper 机制详解 Device Mapper&#xff08;简称 DM&#xff09;是 Linux 内核中的一套通用块设备映射框架&#xff0c;为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程&#xff0c;并配以详细的…...

Python ROS2【机器人中间件框架】 简介

销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...