前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >手把手教你使用CLIP和VectorDB构建一个以图搜图的工具

手把手教你使用CLIP和VectorDB构建一个以图搜图的工具

作者头像
Color Space
发布于 2024-02-01 04:15:16
发布于 2024-02-01 04:15:16
70900
代码可运行
举报
运行总次数:0
代码可运行

导 读

本文将手把手教你使用CLIP和VectorDB构建一个以图搜图的工具。

背景介绍

图像到图像搜索(以图搜图)是什么意思?

在传统的图像搜索引擎中,您通常使用文本查询来查找图像,搜索引擎根据与这些图像关联的关键字返回结果。另一方面,在图像到图像搜索中,您从图像作为查询开始,系统会检索在视觉上类似于查询图像的图像。

想象你有一幅画,就像一幅美丽的日落图画。现在,你想找到其他与它相似的画作,但你无法用言语来描述它。相反,你向计算机展示你的画作,它会浏览它所知道的所有画作,并找到非常相似的画作,即使它们有不同的名称或描述。这就是图像到图像搜索--也就是以图搜图。

我可以用这个搜索工具做什么?

图像到图像搜索引擎开启了令人兴奋的可能性:

  • 查找特定数据 - 搜索包含要训练模型识别的特定对象的图像。
  • 错误分析——当模型对对象进行错误分类时,搜索视觉上相似的图像也会失败。
  • 模型调试 - 显示包含导致不需要的模型行为的属性或缺陷的其他图像。

实现步骤

CLIP 和 VectorDB:简介

图 1 显示了在矢量数据库中索引图像数据集的步骤。

步骤 1:收集图像数据集(可以是原始/未标记图像)。

步骤 2:CLIP 是一种嵌入模型,用于提取图像的高维向量表示,以捕获其语义和感知特征。参考链接:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
https://arxiv.org/abs/2103.00020

步骤 3:这些图像被编码到嵌入空间中,其中(图像的)嵌入在 Redis 或 Milvus 等矢量数据库中建立索引。

在查询时(图 2),样本图像通过相同的 CLIP 编码器来获取其嵌入。执行向量相似性搜索以有效地找到前 k 个最接近的数据库图像向量。与给定查询具有最高相似度得分的图像将作为视觉上最相似的搜索结果返回。

余弦相似度是 VectorDB 应用程序中最常用的相似度度量:

参考链接:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
https://en.wikipedia.org/wiki/Cosine_similarity

构建图像到图像搜索引擎

【1】数据集——指环王

我们使用Google搜索来查询与关键字“指环王电影场景”相关的图片。在此代码之上,我们创建了一个函数来根据给定的查询检索 100 个 url。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import requests, lxml, re, json, urllib.request
from bs4 import BeautifulSoup

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.114 Safari/537.36"
}

params = {
    "q": "the lord of the rings film scenes", # search query
    "tbm": "isch",                # image results
    "hl": "en",                   # language of the search
    "gl": "us",                   # country where search comes from
    "ijn": "0"                    # page number
}

html = requests.get("https://www.google.com/search", params=params, headers=headers, timeout=30)
soup = BeautifulSoup(html.text, "lxml")

def get_images():

    """
    https://kodlogs.com/34776/json-decoder-jsondecodeerror-expecting-property-name-enclosed-in-double-quotes
    if you try to json.loads() without json.dumps() it will throw an error:
    "Expecting property name enclosed in double quotes"
    """

    google_images = []

    all_script_tags = soup.select("script")

    # # https://regex101.com/r/48UZhY/4
    matched_images_data = "".join(re.findall(r"AF_initDataCallback\(([^<]+)\);", str(all_script_tags)))

    matched_images_data_fix = json.dumps(matched_images_data)
    matched_images_data_json = json.loads(matched_images_data_fix)

    # https://regex101.com/r/VPz7f2/1
    matched_google_image_data = re.findall(r'\"b-GRID_STATE0\"(.*)sideChannel:\s?{}}', matched_images_data_json)

    # https://regex101.com/r/NnRg27/1
    matched_google_images_thumbnails = ", ".join(
        re.findall(r'\[\"(https\:\/\/encrypted-tbn0\.gstatic\.com\/images\?.*?)\",\d+,\d+\]',
                   str(matched_google_image_data))).split(", ")

    thumbnails = [
        bytes(bytes(thumbnail, "ascii").decode("unicode-escape"), "ascii").decode("unicode-escape") for thumbnail in matched_google_images_thumbnails
    ]

    # removing previously matched thumbnails for easier full resolution image matches.
    removed_matched_google_images_thumbnails = re.sub(
        r'\[\"(https\:\/\/encrypted-tbn0\.gstatic\.com\/images\?.*?)\",\d+,\d+\]', "", str(matched_google_image_data))

    # https://regex101.com/r/fXjfb1/4
    # https://stackoverflow.com/a/19821774/15164646
    matched_google_full_resolution_images = re.findall(r"(?:'|,),\[\"(https:|http.*?)\",\d+,\d+\]", removed_matched_google_images_thumbnails)

    full_res_images = [
        bytes(bytes(img, "ascii").decode("unicode-escape"), "ascii").decode("unicode-escape") for img in matched_google_full_resolution_images
    ]

    return full_res_images

【2】用CLIP获取嵌入向量

注意:找到所有库和辅助函数来运行此Colab 笔记本中的代码。

提取我们图像集的所有嵌入。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def get_all_image_embeddings_from_urls(dataset, processor, model, device, num_images=100):
    embeddings = []

    # Limit the number of images to process
    dataset = dataset[:num_images]
    working_urls = []

    #for image_url in dataset['image_url']:
    for image_url in dataset:
      if check_valid_URL(image_url):
          try:
              # Download the image
              response = requests.get(image_url)
              image = Image.open(BytesIO(response.content)).convert("RGB")
              # Get the embedding for the image
              embedding = get_single_image_embedding(image, processor, model, device)
              #embedding = get_single_image_embedding(image)
              embeddings.append(embedding)
              working_urls.append(image_url)
          except Exception as e:
              print(f"Error processing image from {image_url}: {e}")
      else:
          print(f"Invalid or inaccessible image URL: {image_url}")

    return embeddings, working_urls
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
LOR_embeddings, valid_urls = get_all_image_embeddings_from_urls(list_image_urls, processor, model, device, num_images=100)
Invalid or inaccessible image URL: https://blog.frame.io/wp-content/uploads/2021/12/lotr-forced-perspective-cart-bilbo-gandalf.jpg
Invalid or inaccessible image URL: https://www.cineworld.co.uk/static/dam/jcr:9389da12-c1ea-4ef6-9861-d55723e4270e/Screenshot%202020-08-07%20at%2008.48.49.png
Invalid or inaccessible image URL: https://upload.wikimedia.org/wikipedia/en/3/30/Ringwraithpic.JPG

100 个网址中有 97 个包含有效图像。

【3】将我们的嵌入存储在 Pinecone 中

在本文中,我们将使用 Pinecone 作为 VectorDB 的示例,但您也可以使用各种其他 VectorDB 的提供程序,例如:QDrant、Milvus、Mongo 或 Redis。

您可以在我们关于 VectorDB 的文章中找到这些矢量数据库服务的很好的比较。

要将我们的嵌入存储在 Pinecone [2] 中,您首先需要创建一个Pinecone帐户。之后,创建一个名为“image-to-image”的索引。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
pinecone.init(
   api_key = "YOUR-API-KEY",
   environment="gcp-starter"  # find next to API key in console
)

my_index_name = "image-to-image"
vector_dim = LOR_embeddings[0].shape[1]

if my_index_name not in pinecone.list_indexes():
  print("Index not present")

# Connect to the index
my_index = pinecone.Index(index_name = my_index_name)

创建一个函数来将数据存储在 Pinecone 索引中。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def create_data_to_upsert_from_urls(dataset,  embeddings, num_images):
  metadata = []
  image_IDs = []
  for index in range(len(dataset)):
    metadata.append({
        'ID': index,
        'image': dataset[index]
    })
    image_IDs.append(str(index))
  image_embeddings = [arr.tolist() for arr in embeddings]
  data_to_upsert = list(zip(image_IDs, image_embeddings, metadata))
  return data_to_upsert

运行上述函数得到:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
LOR_data_to_upsert = create_data_to_upsert_from_urls(valid_urls, 
                                LOR_embeddings, len(valid_urls))

my_index.upsert(vectors = LOR_data_to_upsert)
# {'upserted_count': 97}

my_index.describe_index_stats()
# {'dimension': 512,
# 'index_fullness': 0.00097,
# 'namespaces': {'': {'vector_count': 97}},
# 'total_vector_count': 97

【4】测试我们的图像到图像搜索工具

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# For a random image
n = random.randint(0,len(valid_urls)-1)
print(f"Sample image with index {n} in {valid_urls[n]}")
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Sample image with index 47 in 
https://www.intofilm.org/intofilm-production/scaledcropped/870x489https%3A/s3-eu-west-1.amazonaws.com/images.cdn.filmclub.org/film__3930-the-lord-of-the-rings-the-fellowship-of-the-ring--hi_res-a207bd11.jpg/film__3930-the-lord-of-the-rings-the-fellowship-of-the-ring--hi_res-a207bd11.jpg
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 1. Get the image from url
LOR_image_query = get_image(valid_urls[n])
# 2. Obtain embeddings (via CLIP) for the given image
LOR_query_embedding = get_single_image_embedding(LOR_image_query, processor, model, device).tolist()
# 3. Search on Vector DB index for similar images to "LOR_query_embedding"
LOR_results = my_index.query(LOR_query_embedding, top_k=3, include_metadata=True)
# 4. See the results
plot_top_matches_seaborn(LOR_results)

上图显示了我们的图像到图像搜索工具获得的结果。所有这些都描绘了至少两个人物在开放的背景中行走。类似风景。具体来说,ID 47 的样本获得最高相似度得分 1.0。这并不奇怪,因为我们的数据集包含查询中使用的原始图像(图 3)。接下来最相似的样本是平局:ID 63 和 ID 30 的得分均为 0.77。

【5】如果有100万张甚至1亿张图片我该怎么办?

您可能已经意识到,构建一个工具通过从 Google 搜索中查询一些图像来进行图像到图像搜索是很有趣的。但是,如果您实际上拥有超过 1 亿张图像的数据集怎么办?🤔

在这种情况下,您可能会构建一个系统而不是一个工具。然而,建立一个可扩展的系统并不是一件容易的事。此外,还涉及许多成本(例如,存储成本、维护、编写实际代码)。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-01-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 OpenCV与AI深度学习 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
CLIP与DINOv2的图像相似度对比
在计算机视觉领域有两个主要的自监督模型:CLIP和DINOv2。CLIP彻底改变了图像理解并且成为图片和文字之间的桥梁,而DINOv2带来了一种新的自监督学习方法。
deephub
2023/10/06
1.8K0
CLIP与DINOv2的图像相似度对比
利用OpenAI CLIP、Claude Sonnet 3.5和pgvector构建一个AI图库
本文探讨了使用 OpenAI CLIP、Claude Sonnet 3.5 和 pgvector 构建 AI 驱动的图片库的 RAG 应用挑战。
云云众生s
2024/10/01
1540
利用OpenAI CLIP、Claude Sonnet 3.5和pgvector构建一个AI图库
智谱免费GLM-4V-Flash助力多模态RAG实现
多模态检索增强生成(RAG)技术正快速发展,但部署成本较高。智谱科技开放的GLM-4V-Flash作为免费多模态大模型,具备图文理解、知识检索等能力,为构建RAG系统提供了经济实惠的选择。
致Great
2024/12/28
5320
智谱免费GLM-4V-Flash助力多模态RAG实现
手把手教你在Python中实现文本分类(附代码、数据集)
文本分类是商业问题中常见的自然语言处理任务,目标是自动将文本文件分到一个或多个已定义好的类别中。文本分类的一些例子如下:
数据派THU
2018/07/30
12.7K2
手把手教你在Python中实现文本分类(附代码、数据集)
使用CLIP和LLM构建多模态RAG系统
在本文中我们将探讨使用开源大型语言多模态模型(Large Language Multi-Modal)构建检索增强生成(RAG)系统。本文的重点是在不依赖LangChain或LLlama index的情况下实现这一目标,这样可以避免更多的框架依赖。
deephub
2024/01/17
1.9K0
使用CLIP和LLM构建多模态RAG系统
【腾讯云云上实验室】《手把手带你 5 分钟构建以图搜图系统》
向量在数学中是一个可以表示多个维度或特性的对象。在我们日常生活中,也可以用来描述一个物体的多个属性。
码农学习联盟
2023/11/24
7650
【腾讯云云上实验室】《手把手带你 5 分钟构建以图搜图系统》
使用CLIP构建视频搜索引擎
CLIP(Contrastive Language-Image Pre-training)是一种机器学习技术,它可以准确理解和分类图像和自然语言文本,这对图像和语言处理具有深远的影响,并且已经被用作流行的扩散模型DALL-E的底层机制。在这篇文章中,我们将介绍如何调整CLIP来辅助视频搜索。
deephub
2023/02/01
9540
手把手教你使用 Towhee 进行 fine-tune
Towhee 是一个将图像、文本、语音、视频等非结构化数据编码为嵌入 embedding 向量的开源工具。
Zilliz RDS
2023/01/10
1.6K0
手把手教你使用 Towhee 进行 fine-tune
手把手搭建视频查重系统
如今,短视频平台对各类搬运视频的检测力度和精确度越来越高了。无论是影视号的剪辑,还是从油管搬运,即使做了各类复杂的视频变换,都很容易被检测出来。作者都会收到提醒,严重的甚至被封号。
Zilliz RDS
2023/01/10
2.6K0
手把手搭建视频查重系统
手把手教你从零起步构建自己的图像搜索模型
很多的产品是基于我们的感知来吸引我们的。比如在浏览服装网站上的服装,寻找 Airbnb 上的假期租房,或者领养宠物时,物品的颜值往往是我们做决定的重要因素。想要预测我们喜欢什么样的东西,看看我们对于事物的感知方法大概就能知道了,因此,这也是一个非常有价值的考量。
AI研习社
2018/08/06
6800
手把手教你从零起步构建自己的图像搜索模型
【腾讯云云上实验室】向量数据库+LangChain+LLM搭建智慧辅导系统实践
得益于深度学习的快速发展和数据规模的不断扩大,以GPT、混元、T5等为代表的大语言模型具备了前所未有的自然语言处理和生成能力,然而,在实际应用中,大语言模型的高效存储、检索和推理成为了一个新的挑战。
中杯可乐多加冰
2023/11/25
1.7K1
LLM在智能应用中的新突破:最新技术趋势解析
大型语言模型(LLM)作为人工智能领域的重大突破,正在彻底改变我们与技术互动的方式。从简单的文本生成到如今的多模态交互、实时处理以及跨领域协作,LLM的能力正以前所未有的速度扩展。本文将深入探讨LLM在智能应用中的最新技术趋势,并通过实际的代码示例展示这些创新如何在现实世界中发挥作用。
江南清风起
2025/03/20
1440
如何构建Embedding?如何构建一个智能文档查询助手?
嵌入(embedding)是指将高维数据映射为低维表示的过程。在机器学习和自然语言处理中,嵌入通常用于将离散的符号或对象表示为连续的向量空间中的点。
山行AI
2023/08/10
1.1K0
如何构建Embedding?如何构建一个智能文档查询助手?
Java开发者的Python快速实战指南:探索向量数据库之图像相似搜索-文字版
首先,我要向大家道个歉。原本我计划今天向大家展示如何将图片和视频等形式转换为向量并存储在向量数据库中,但是当我查看文档时才发现,腾讯的向量数据库尚未完全开发完成。因此,今天我将用文本形式来演示相似图片搜索。如果您对腾讯的产品动态不太了解,可以查看官方网址:https://cloud.tencent.com/document/product/1709/95477
努力的小雨
2023/12/05
4712
构建高效的LinkedIn图像爬取工具
然而,LinkedIn对爬虫有一定的限制,直接爬取数据可能会触发反爬虫机制。因此,我们需要使用代理服务器和高效的爬虫技术来规避这些限制。本项目的目标是构建一个高效的LinkedIn图像爬取工具,能够根据指定的搜索条件(如职位名称)爬取用户头像的URL。
小白学大数据
2025/03/20
1050
手把手教你实战汉字书法识别
由TinyMind发起的 #第一届汉字书法识别挑战赛# 正在火热进行中,比赛才开始2周,便有数只黑马冲进榜单。目前TOP16全部为90分以上,可谓竞争激烈,高手如林。No.1微胖君(microfat_htu)目前以99.01高分领衔榜首,还未报名的同学欢迎点击"原文链接"参赛,向这些同学发起挑战~~ 4.20榜单 本次比赛主要是以学习交流为目的,吸引了不少萌新们报名参赛~虽是入门级别的赛题,对于没动手实战过的同学,还是有些不知所措。为此TinyMind特邀战场中奋勇拼搏的两名前锋,为大家整理了一些经验心得,
用户1737318
2018/06/05
5.5K0
利用深度学习手把手教你实现一个「以图搜图」
在上一篇文章《图像检索系列——利用 Python 检测图像相似度》中,我们介绍了一个在图像检索领域非常常用的算法——感知哈希算法。这是一个很简单且快速的算法,其原理在于针对每一张图片都生成一个特定的“指纹”,然后采取一种相似度的度量方式得出两张图片的近似程度。
出其东门
2019/09/03
2.9K0
利用深度学习手把手教你实现一个「以图搜图」
CLIP-图文预训练模型
CLIP: Contrastive LanguageImage Pre-training
iResearch666
2023/09/13
6860
CLIP-图文预训练模型
向量搜索与ClickHouse-Part II
这篇博文延续了我们关于向量搜索的系列文章,建立在前一篇文章的基础上,我们概述了向量搜索是什么,它与历史上基于倒排索引的方法的关系,它目前提供价值的可能用例,以及一些高级实现方法。在这篇文章中,我们通过实际示例详细探讨了向量搜索与ClickHouse的关系,并回答了“我什么时候应该使用ClickHouse进行向量搜索?”
用户3578099
2023/09/01
1K0
向量搜索与ClickHouse-Part II
在 Elasticsearch 中实施图片相似度搜索
本文将帮助你了解如何快速在 Elastic 中实施图像相似度搜索。你仅需要:要创建应用程序环境,然后导入 NLP 模型,最后针对您的图像集完成嵌入的生成工作。就这么简单!
点火三周
2023/05/19
1.9K0
在 Elasticsearch 中实施图片相似度搜索
推荐阅读
相关推荐
CLIP与DINOv2的图像相似度对比
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验