Elasticsearch:运用向量搜索通过图像搜索找到你的小狗

作者:ALEX SALGADO

你是否曾经遇到过这样的情况:你在街上发现了一只丢失的小狗,但不知道它是否有主人? 了解如何使用向量搜索或图像搜索来做到这一点。

通过图像搜索找到你的小狗

您是否曾经遇到过这样的情况:你在街上发现了一只丢失的小狗,但不知道它是否有主人? 在 Elasticsearch 中通过图像处理使用向量搜索,此任务可以像漫画一样简单。

想象一下这个场景:在一个喧闹的下午,路易吉,一只活泼的小狗,在 Elastic 周围散步时不小心从皮带上滑落,发现自己独自在繁忙的街道上徘徊。 绝望的主人正在各个角落寻找他,用充满希望和焦虑的声音呼唤着他的名字。 与此同时,在城市的某个地方,一位细心的人注意到这只小狗表情茫然,决定提供帮助。 很快,他们给路易吉拍了一张照片,并利用所在公司的向量图像搜索技术,开始在数据库中进行搜索,希望能找到有关这只小逃亡者主人的线索。

如果你想在阅读时跟踪并执行代码,请访问在 Jupyter Notebook (Google Collab) 上运行的文件 Python 代码。

架构

我们将使用 Jupyter Notebook 来解决这个问题。 首先,我们下载要注册的小狗的图像,然后安装必要的软件包。

注意:要实现此示例,我们需要在使用图像数据填充向量数据库之前在 Elasticsearch 中创建索引。

  • 首先部署 Elasticsearch(我们为你提供 14 天的免费试用期)。
  • 在此过程中,请记住存储要在 Python 代码中使用的凭据(用户名、密码)。
  • 为简单起见,我们将使用在 Jupyter Notebook (Google Colab) 上运行的 Python 代码。

下载代码 zip 文件并安装必要的软件包

!git clone https://github.com/salgado/image-search-01.git
!pip -q install Pillow sentence_transformers elasticsearch

让我们创建 4 个类来帮助我们完成这项任务,它们是:

  • Util 类:负责处理前期任务和 Elasticsearch 索引维护。
  • Dog 类:负责存储我们小狗的属性。
  • DogRepository 类:负责数据持久化任务。
  • DogService 类:它将成为我们的服务层。

Util class

Util 类提供了用于管理 Elasticsearch 索引的实用方法,例如创建和删除索引。

方法

  • create_index():在 Elasticsearch 中创建一个新索引。
  • delete_index():从 Elasticsearch 中删除现有索引。
### Util class
from elasticsearch import Elasticsearch, exceptions as es_exceptions
import getpassclass Util:@staticmethoddef get_index_name():return "dog-image-index"@staticmethoddef get_connection():es_cloud_id = getpass.getpass('Enter Elastic Cloud ID:  ')es_user = getpass.getpass('Enter cluster username:  ')es_pass = getpass.getpass('Enter cluster password:  ')es = Elasticsearch(cloud_id=es_cloud_id,basic_auth=(es_user, es_pass))es.info() # should return cluster inforeturn es@staticmethoddef create_index(es: Elasticsearch, index_name: str):# Specify index configurationindex_config = {"settings": {"index.refresh_interval": "5s","number_of_shards": 1},"mappings": {"properties": {"image_embedding": {"type": "dense_vector","dims": 512,"index": True,"similarity": "cosine"},"dog_id": {"type": "keyword"},"breed": {"type" : "keyword"},"image_path" : {"type" : "keyword"},"owner_name" : {"type" : "keyword"},"exif" : {"properties" : {"location": {"type": "geo_point"},"date": {"type": "date"}}}}}}# Create indexif not es.indices.exists(index=index_name):index_creation = es.indices.create(index=index_name, ignore=400, body=index_config)print("index created: ", index_creation)else:print("Index  already exists.")@staticmethoddef delete_index(es: Elasticsearch, index_name: str):# delete indexes.indices.delete(index=index_name, ignore_unavailable=True)

如果你是自构建的集群,你可以参考文章 “Elasticsearch:关于在 Python 中使用 Elasticsearch 你需要知道的一切 - 8.x” 来了解如何使用客户端来连接 Elasticsearch 集群。

Dog class

Dog 类代表一只狗及其属性,例如 ID、图像路径、品种、所有者姓名和图像嵌入。

属性

  • dog_id:狗的 ID。
  • image_path:狗图像的路径。
  • breed:狗的品种。
  • owner_name:狗的主人的名字。
  • image_embedding:狗的图像嵌入。

方法:

  • __init__():初始化一个新的 Dog 对象。
  • generate_embedding():生成狗的图像嵌入。
  • to_dict():将 Dog 对象转换为字典。
import os
from sentence_transformers import SentenceTransformer
from PIL import Image# domain class
class Dog:model = SentenceTransformer('clip-ViT-B-32')def __init__(self, dog_id, image_path, breed, owner_name):self.dog_id = dog_idself.image_path = image_pathself.breed = breedself.image_embedding = Noneself.owner_name = owner_name@staticmethoddef get_embedding(image_path: str):temp_image = Image.open(image_path)return Dog.model.encode(temp_image)def generate_embedding(self):self.image_embedding = Dog.get_embedding(self.image_path)def __repr__(self):return (f"Image(dog_id={self.dog_id}, image_path={self.image_path}, "f"breed={self.breed}, image_embedding={self.image_embedding}, "f"owner_name={self.owner_name})")def to_dict(self):return {'dog_id': self.dog_id,'image_path': self.image_path,'breed': self.breed,'image_embedding': self.image_embedding,'owner_name': self.owner_name}

DogRepository class

DogRepository 类提供了从 Elasticsearch 保存和检索狗数据的方法。

方法

  • insert():将一条新狗插入 Elasticsearch。
  • bulk_insert():将多条狗批量插入到Elasticsearch中。
  • search_by_image():通过图像搜索相似的狗。
from typing import List, Dict
# persistence layer
class DogRepository:def __init__(self, es_client: Elasticsearch, index_name: str = "dog-image-index"):self.es_client = es_clientself._index_name = index_nameUtil.create_index(es_client, index_name)def insert(self, dog: Dog):dog.generate_embedding()document = dog.__dict__self.es_client.index(index=self._index_name, document=document)def bulk_insert(self, dogs: List[Dog]):operations = []for dog in dogs:operations.append({"index": {"_index": self._index_name}})operations.append(dog.__dict__)self.es_client.bulk(body=operations)def search_by_image(self, image_embedding: List[float]):field_key = "image_embedding"knn = {"field": field_key,"k": 2,"num_candidates": 100,"query_vector": image_embedding,"boost": 100}# The fields to retrieve from the matching documentsfields = ["dog_id", "breed", "owner_name","image_path", "image_embedding"]try:resp = self.es_client.search(index=self._index_name,body={"knn": knn,"_source": fields},size=1)# Return the search resultsreturn respexcept Exception as e:print(f"An error occurred: {e}")return {}

DogService Class

DogService 类提供管理狗数据的业务逻辑,例如插入和搜索狗。

方法

  • insert_dog():将一条新狗插入 Elasticsearch。
  • search_dogs_by_image():通过图像搜索相似的狗。

from typing import List, Dict
# persistence layer
class DogRepository:def __init__(self, es_client: Elasticsearch, index_name: str = "dog-image-index"):self.es_client = es_clientself._index_name = index_nameUtil.create_index(es_client, index_name)def insert(self, dog: Dog):dog.generate_embedding()document = dog.__dict__self.es_client.index(index=self._index_name, document=document)def bulk_insert(self, dogs: List[Dog]):operations = []for dog in dogs:operations.append({"index": {"_index": self._index_name}})operations.append(dog.__dict__)self.es_client.bulk(body=operations)def search_by_image(self, image_embedding: List[float]):field_key = "image_embedding"knn = {"field": field_key,"k": 2,"num_candidates": 100,"query_vector": image_embedding,"boost": 100}# The fields to retrieve from the matching documentsfields = ["dog_id", "breed", "owner_name","image_path", "image_embedding"]try:resp = self.es_client.search(index=self._index_name,body={"knn": knn,"_source": fields},size=1)# Return the search resultsreturn respexcept Exception as e:print(f"An error occurred: {e}")return {}

上面介绍的类(classes)为构建狗数据管理系统奠定了坚实的基础。 Util 类提供了用于管理 Elasticsearch 索引的实用方法。 Dog 类代表狗的属性。 DogRepository 类提供了从 Elasticsearch 保存和检索狗数据的方法。 DogService 类提供了高效的狗数据管理的业务逻辑。

主要代码

我们的代码基本上有两个主要流程或阶段:

  • 使用基本信息和图像注册狗。
  • 使用新图像执行搜索以在向量数据库中查找狗。

第一阶段:注册小狗

为了存储有关 Luigi 和其他公司的小狗的信息,我们将使用 Dog 类。

为此,我们对序列进行如下的编程:

开始为小狗登记


# Start a connection
es_db = Util.get_connection()
Util.delete_index(es_db, Util.get_index_name())# Register one dog
dog_repo = DogRepository(es_db, Util.get_index_name())
dog_service = DogService(dog_repo)# Visualize the inserted Dog
from IPython.display import display
from IPython.display import Image as ShowImagefilename = "/content/image-search-01/dataset/dogs/Luigi.png"
display(ShowImage(filename=filename, width=300, height=300))

输出:

登记 Luigi

dog = Dog('Luigi', filename, 'Jack Russel/Rat Terrier', 'Ully')dog_service.register_dog(dog)

登记所有其他小狗

import json# JSON data
data = '''
{"dogs": [{"dog_id": "Buddy", "image_path": "", "breed": "Labrador Retriever", "owner_name": "Berlin Red"},{"dog_id": "Bella", "image_path": "", "breed": "German Shepherd", "owner_name": "Tokyo Blue"},{"dog_id": "Charlie", "image_path": "", "breed": "Golden Retriever", "owner_name": "Paris Green"},{"dog_id": "Bigu", "image_path": "", "breed": "Beagle", "owner_name": "Lisbon Yellow"},{"dog_id": "Max", "image_path": "", "breed": "Bulldog", "owner_name": "Canberra Purple"},{"dog_id": "Luna", "image_path": "", "breed": "Poodle", "owner_name": "Wellington Brown"},{"dog_id": "Milo", "image_path": "", "breed": "Rottweiler", "owner_name": "Hanoi Orange"},{"dog_id": "Ruby", "image_path": "", "breed": "Boxer", "owner_name": "Ottawa Pink"},{"dog_id": "Oscar", "image_path": "", "breed": "Dachshund", "owner_name": "Kabul Black"},{"dog_id": "Zoe", "image_path": "", "breed": "Siberian Husky", "owner_name": "Cairo White"}]
}
'''# Convert JSON string to Python dictionary
dogs_data = json.loads(data)# Traverse the list and print dog_id of each dog
image_dogs = "/content/image-search-01/dataset/dogs/"
for dog_info in dogs_data["dogs"]: dog = Dog(dog_info["dog_id"], image_dogs + dog_info["dog_id"] + ".png" , dog_info["breed"], dog_info["owner_name"])dog_service.register_dog(dog)

可视化新狗

# visualize new dogs
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import mathimage_dogs = "/content/image-search-01/dataset/dogs/"
num_dogs = len(dogs_data["dogs"])cols = int(math.sqrt(num_dogs))
rows = int(math.ceil(num_dogs / cols))# Configurar o tamanho da figura
plt.figure(figsize=(5, 5))# Loop para exibir as imagens dos cães
for i, dog_info in enumerate(dogs_data["dogs"]): filename = image_dogs + dog_info["dog_id"] + ".png"img = mpimg.imread(filename)plt.subplot(rows, cols, i+1)  # (número de linhas, número de colunas, índice do subplot)plt.imshow(img)plt.axis('off')plt.show()

输出:

第二阶段:寻找丢失的狗

现在我们已经登记了所有小狗,让我们进行搜索。 我们的开发人员拍了这张丢失小狗的照片。

filename = "/content/image-search-01/dataset/lost-dogs/lost_dog1.png"
display(ShowImage(filename=filename, width=300, height=300))

输出:

看看我们能找到这只可爱的小狗的主人吗?

# find dog by image
result = dog_service.find_dog_by_image(filename)

获取结果

让我们看看我们发现了什么......

filename = result['hits']['hits'][0]['_source']['image_path']
display(ShowImage(filename=filename, width=300, height=300))

输出:

瞧! 我们找到了!!!

但谁将是所有者和他们的名字?

# Print credentials
print(result['hits']['hits'][0]['_source']['dog_id'])
print(result['hits']['hits'][0]['_source']['breed'])
print(result['hits']['hits'][0]['_source']['owner_name'])

输出:

  • Luigi
  • Jack Russel/Rat Terrier
  • Ully

好结局

我们找到了路易吉!!! 我们通知 Ully 吧。

filename = "/content/image-search-01/dataset/lost-dogs/Ully.png"
display(ShowImage(filename=filename, width=300, height=300))

输出:

很快,Ully 和 Luigi 就团聚了。 小狗高兴地摇着尾巴,Ully 紧紧地抱住它,保证再也不会让它离开她的视线。 他们经历了一阵情感旋风,但现在他们在一起了,这才是最重要的。 就这样,Ully 和 Luigi 心中充满了爱和欢乐,从此幸福地生活在一起。

结论

在这篇博文中,我们探索了如何使用 Elasticsearch 通过向量搜索来寻找丢失的小狗。 我们演示了如何生成狗的图像嵌入,在 Elasticsearch 中对其进行索引,然后使用查询图像搜索相似的狗。 该技术可用于寻找丢失的宠物,以及识别图像中其他感兴趣的物体。

向量搜索是一个强大的工具,可用于多种应用。 它特别适合需要根据外观搜索相似对象的任务,例如图像检索和对象识别。

我们希望这篇博文能够提供丰富的信息,并且你会发现我们讨论的技术对你自己的项目很有用。

原文:Finding your puppy with Image Search — Elastic Search Labs

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/145306.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

V10服务器安装virt-manage

kvm是什么 KVM(Kernel-based Virtual Machine, 即内核级虚拟机) 是一个开源的系统虚拟化模块。它使用Linux自身的调度器进行管理,所以相对于Xen,其核心源码很少。目前KVM已成为学术界的主流VMM之一,它包含一个为处理器提供底层虚拟化 可加载…

概率论和数理统计(三)数理统计基本概念

前言 “概率论”是给定一个随机变量X的分布F(x),然后求某事件A概率 P ( x ∈ A ) P(x \in A) P(x∈A)或者随机变量X的数字特征.“统计”是已知一组样本数据 { x 1 , x 2 , . . . x n } \{x_1,x_2,...x_n\} {x1​,x2​,...xn​},去求分布F(x) 统计的基本概念 在统计中&#x…

Vue3-admin-template 框架实现表单身份证获取到 出生年月、性别

一. 首先需效验输入身份证信息是否正确&#xff1a; const sfzhChange () > {// 效验身份证号格式const reg /^[1-9]\d{5}(19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/; }; 二.绑定输入框 input 事件&#xff1a; <el-form-item label&q…

监控直流防雷浪涌保护器综合方案

监控系统是一种广泛应用于安防、交通、工业、军事等领域的信息系统&#xff0c;它通过摄像机、传输线路、监控中心等设备&#xff0c;实现对目标区域的实时监视和控制。然而&#xff0c;监控系统也面临着雷电的威胁&#xff0c;雷电可能通过直击雷、感应雷、雷电波侵入等途径&a…

Linux服务器安装Dotnet8

1. 下载dotnet8 sdk 下载 .NET 8.0 SDK (v8.0.100) - Linux x64 Binaries 拿到 dotnet-sdk-8.0.100-linux-x64.tar.gz 文件 2. 把文件上传到 /usr/local/software 目录 mkdir -p /usr/local/software/dotnet8 把文件拷贝过去 mv dotnet-sdk-8.0.100-linux-x64.tar.gz /usr/loc…

安装SSL证书有什么意义?

在当今的数字化时代&#xff0c;网络安全已经成为了一个重要的议题。为了保护网站和用户数据的安全&#xff0c;许多网站都选择了安装SSL证书。同时&#xff0c;很多用户不明白安装SSL证书到底有什么意义&#xff1f; 一、网站实现加密传输 用户通过http协议访问网站时&#x…

vue使用navigator.mediaDevices.getUserMedia调用相机功能

目录 前言&#xff1a; API&#xff1a; API简单示例&#xff1a; 拍照功能 实现效果&#xff1a; 前言&#xff1a; 本文将介绍Vue中如何使用navigator.mediaDevices.getUserMedia调用相机功能&#xff0c;实现拍照使用实例&#xff0c;需要的朋友可以参考一下。 注意…

深度学习YOLOv5车辆颜色识别检测 - python opencv 计算机竞赛

文章目录 1 前言2 实现效果3 CNN卷积神经网络4 Yolov56 数据集处理及模型训练5 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **基于深度学习YOLOv5车辆颜色识别检测 ** 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0…

linux高级篇基础理论一(详细文档、Apache,网站,MySQL、MySQL备份工具)

♥️作者&#xff1a;小刘在C站 ♥️个人主页&#xff1a; 小刘主页 ♥️不能因为人生的道路坎坷,就使自己的身躯变得弯曲;不能因为生活的历程漫长,就使求索的 脚步迟缓。 ♥️学习两年总结出的运维经验&#xff0c;以及思科模拟器全套网络实验教程。专栏&#xff1a;云计算技…

VS2022升级之后,原有项目出现异常

最近对VS2022做了升级&#xff0c;发现之前开发的WebApi&#xff08;使用Net5&#xff09;调试运行报错&#xff1a; 根据提示的错误信息也在网上查找了一些资料&#xff0c;均无法正常解决&#xff0c;偶然发现问题是因为VS2022升级之后&#xff0c;不再支持Net5&#xff0c;…

【开源】基于Vue和SpringBoot的固始鹅块销售系统

项目编号&#xff1a; S 060 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S060&#xff0c;文末获取源码。} 项目编号&#xff1a;S060&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 鹅块类型模块2.3 固…

论文技巧2

目录 1 找基准模型2 找模块小论文的三个实验怎么做对比试验Sota的挑选对⽐论⽂结果的获取3 消融实验什么是消融实验怎么做消融实验4 实例分析怎么做实例分析小论文必备三张图1 找基准模型 2 找模块 小论文的三个实验 怎么做对比试验

高性能音乐流媒体服务Diosic

什么是 Diosic ? Diosic 是一个开源的基于网络的音乐收集服务器和流媒体。主要适合需要部署在硬件规格不高的服务器上的用户。Diosic 是使用 Rust 开发的&#xff0c;具有低内存使用率和高性能以及用于流媒体音乐的非常干净的界面。 安装 在群晖上以 Docker 方式安装。 在注…

基于JavaWeb+SpringBoot+Vue医疗器械商城微信小程序系统的设计和实现

基于JavaWebSpringBootVue医疗器械商城微信小程序系统的设计和实现 源码获取入口前言主要技术系统设计功能截图Lun文目录订阅经典源码专栏Java项目精品实战案例《500套》 源码获取 源码获取入口 前言 摘 要 目前医疗器械行业作为医药行业的一个分支&#xff0c;发展十分迅速。…

Sql Prompt 10下载安装图文教程

在操作过程中&#xff0c;请暂时关闭你的防病毒软件&#xff0c;以免其误报导致操作失败。 资源 SQL Prompt 10 https://www.aliyundrive.com/s/QuMWkvE1Sv6 点击链接保存&#xff0c;或者复制本段内容&#xff0c;打开「阿里云盘」APP &#xff0c;无需下载极速在线查看&…

【数据结构】树与二叉树(十六):二叉树的基础操作:插入结点(算法Insert)

文章目录 5.2.1 二叉树二叉树性质引理5.1&#xff1a;二叉树中层数为i的结点至多有 2 i 2^i 2i个&#xff0c;其中 i ≥ 0 i \geq 0 i≥0。引理5.2&#xff1a;高度为k的二叉树中至多有 2 k 1 − 1 2^{k1}-1 2k1−1个结点&#xff0c;其中 k ≥ 0 k \geq 0 k≥0。引理5.3&…

通讯录实现之进阶版将通讯录数据保存在文件中(完整代码)

我们在之前的博客中已经写过两版通讯录了&#xff1a; 第一版是用C语言实现了通讯录&#xff0c;但是通讯录的存储人数信息是固定的&#xff0c;用完就没有了 感兴趣的可以转到对应博客看一下&#xff0c;附带链接&#xff1a;第一版通讯录 第二版是在第一版的基础上动态开辟…

三大开源向量数据库大比拼

向量数据库具有一系列广泛的好处&#xff0c;特别是在生成式人工智能方面&#xff0c;更具体地说&#xff0c;是在大语言模型&#xff08;LLM&#xff09;方面。这些好处包括先进的索引和精确的相似度搜索&#xff0c;有助于交付强大的先进项目。 本文将对三种开源向量数据库&…

“开源 vs. 闭源:大模型的未来发展趋势预测“——探讨大模型未来的发展方向

文章目录 每日一句正能量前言什么是大模型的开源与闭源开源与闭源的定义和特点开源的意义开源和闭源的优劣势比较不同的大模型企业&#xff0c;开源、闭源的策略不尽相同。企业在开发垂类模型时选择开源还是闭源大模型开源vs 闭源&#xff1a;两者并非选择题后记 每日一句正能量…

【网络】TCP协议的相关实验

TCP协议的相关实验 一、理解listen的第二个参数1、实验现象2、TCP 半连接队列和全连接队列3、关于listen的第二个参数的一些问题4、SYN洪水Ⅰ、什么是SYN洪水攻击Ⅱ、如何解决SYN洪水攻击&#xff1f; 二、使用Wireshark分析TCP通信流程 一、理解listen的第二个参数 在编写TCP…