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

基于CLIP和DINOv2实现图像相似性方面的比较

概述

在人工智能领域,CLIP和DINOv2是计算机视觉领域的两大巨头。CLIP彻底改变了图像理解,而DINOv2为自监督学习带来了新的方法。

在本文中,我们将踏上一段旅程,揭示定义CLIP和DINOv2的优势和微妙之处。我们的目标是发现这些模型中哪一个在图像相似性任务的世界中真正表现出色。让我们见证巨头的碰撞,看看哪个模型会脱颖而出。

1 使用CLIP计算图像相似性

使用CLIP计算两张图像之间的相似性是一个简单的过程,只需两步:首先,提取两张图像的特征,然后计算它们的余弦相似度。

首先,确保安装了必要的软件包。建议设置并使用虚拟环境:

# 首先设置虚拟环境
virtualenv venv-similarity
source venv-similarity/bin/activate
# 安装所需软件包
pip install transformers Pillow torch

接下来,计算图像相似性:

import torch
from PIL import Image
from transformers import AutoProcessor, CLIPModel
import torch.nn as nndevice = torch.device('cuda' if torch.cuda.is_available() else "cpu")
processor = AutoProcessor.from_pretrained("openai/clip-vit-base-patch32")
model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32").to(device)# 从image1中提取特征
image1 = Image.open('img1.jpg')
with torch.no_grad():inputs1 = processor(images=image1, return_tensors="pt").to(device)image_features1 = model.get_image_features(**inputs1)# 从image2中提取特征
image2 = Image.open('img2.jpg')
with torch.no_grad():inputs2 = processor(images=image2, return_tensors="pt").to(device)image_features2 = model.get_image_features(**inputs2)# 计算它们的余弦相似度并将其转换为0到1之间的分数
cos = nn.CosineSimilarity(dim=0)
sim = cos(image_features1[0],image_features2[0]).item()
sim = (sim + 1) / 2
print('Similarity:', sim)

使用提供的两张相似图像的示例,获得的相似度分数令人印象深刻,达到了96.4%。

2 使用DINOv2计算图像相似性

使用DINOv2计算两张图像之间的相似性过程与CLIP类似。用DINOv2需要与前面提到的相同的软件包集,无需额外安装:

from transformers import AutoImageProcessor, AutoModel
from PIL import Image
import torch.nn as nndevice = torch.device('cuda' if torch.cuda.is_available() else "cpu")
processor = AutoImageProcessor.from_pretrained('facebook/dinov2-base')
model = AutoModel.from_pretrained('facebook/dinov2-base').to(device)image1 = Image.open('img1.jpg')
with torch.no_grad():inputs1 = processor(images=image1, return_tensors="pt").to(device)outputs1 = model(**inputs1)image_features1 = outputs1.last_hidden_stateimage_features1 = image_features1.mean(dim=1)image2 = Image.open('img2.jpg')
with torch.no_grad():inputs2 = processor(images=image2, return_tensors="pt").to(device)outputs2 = model(**inputs2)image_features2 = outputs2.last_hidden_stateimage_features2 = image_features2.mean(dim=1)cos = nn.CosineSimilarity(dim=0)
sim = cos(image_features1[0],image_features2[0]).item()
sim = (sim + 1) / 2
print('Similarity:', sim)

使用与CLIP示例中相同的一对图像,DINOv2获得的相似度分数为96.4%:
在这里插入图片描述

3. 使用COCO数据集进行测试

在深入评估它们的性能之前,使用COCO数据集中的图像比较CLIP和DINOv2产生的结果。

实现流程:

  1. 遍历数据集以提取所有图像的特征。
  2. 将嵌入存储在FAISS索引中。
  3. 提取输入图像的特征。
  4. 检索最相似的三张图像。

3.1 特征提取和创建

import torch
from PIL import Image
from transformers import AutoProcessor, CLIPModel, AutoImageProcessor, AutoModel
import faiss
import os
import numpy as npdevice = torch.device('cuda' if torch.cuda.is_available() else "cpu")# 加载CLIP模型和处理器
processor_clip = AutoProcessor.from_pretrained("openai/clip-vit-base-patch32")
model_clip = CLIPModel.from_pretrained("openai/clip-vit-base-patch32").to(device)# 加载DINOv2模型和处理器
processor_dino = AutoImageProcessor.from_pretrained('facebook/dinov2-base')
model_dino = AutoModel.from_pretrained('facebook/dinov2-base').to(device)# 获取所有文件名
images = []
for root, dirs, files in os.walk('./val2017/'):for file in files:if file.endswith('jpg'):images.append(root + '/' + file)# 定义一个函数,用于归一化嵌入并将其添加到索引中
def add_vector_to_index(embedding, index):# 将嵌入转换为numpy数组vector = embedding.detach().cpu().numpy()# 转换为float32 numpy数组vector = np.float32(vector)# 归一化向量:在搜索时避免错误结果很重要faiss.normalize_L2(vector)# 添加到索引中index.add(vector)def extract_features_clip(image):with torch.no_grad():inputs = processor_clip(images=image, return_tensors="pt").to(device)image_features = model_clip.get_image_features(**inputs)return image_featuresdef extract_features_dino(image):with torch.no_grad():inputs = processor_dino(images=image, return_tensors="pt").to(device)outputs = model_dino(**inputs)image_features = outputs.last_hidden_statereturn image_features.mean(dim=1)# 创建两个索引
index_clip = faiss.IndexFlatL2(512)
index_dino = faiss.IndexFlatL2(768)# 遍历数据集以提取特征X2并将特征存储在索引中
for image_path in images:img = Image.open(image_path).convert('RGB')clip_features = extract_features_clip(img)add_vector_to_index(clip_features, index_clip)dino_features = extract_features_dino(img)add_vector_to_index(dino_features, index_dino)# 将索引本地存储
faiss.write_index(index_clip, "clip.index")
faiss.write_index(index_dino, "dino.index")

3.2 图像相似性搜索

import faiss
import numpy as np
import torch
from transformers import AutoImageProcessor, AutoModel, AutoProcessor, CLIPModel
from PIL import Image
import os# 输入图像
source = 'laptop.jpg'
image = Image.open(source)
device = torch.device('cuda' if torch.cuda.is_available() else "cpu")# 加载DINOv2和CLIP的模型和处理器
processor_clip = AutoProcessor.from_pretrained("openai/clip-vit-base-patch32")
model_clip = CLIPModel.from_pretrained("openai/clip-vit-base-patch32").to(device)
processor_dino = AutoImageProcessor.from_pretrained('facebook/dinov2-base')
model_dino = AutoModel.from_pretrained('facebook/dinov2-base').to(device)# 为CLIP提取特征
with torch.no_grad():inputs_clip = processor_clip(images=image, return_tensors="pt").to(device)image_features_clip = model_clip.get_image_features(**inputs_clip)# 为DINOv2提取特征
with torch.no_grad():inputs_dino = processor_dino(images=image, return_tensors="pt").to(device)outputs_dino = model_dino(**inputs_dino)image_features_dino = outputs_dino.last_hidden_stateimage_features_dino = image_features_dino.mean(dim=1)def normalizeL2(embeddings):vector = embeddings.detach().cpu().numpy()vector = np.float32(vector)faiss.normalize_L2(vector)return vectorimage_features_dino = normalizeL2(image_features_dino)
image_features_clip = normalizeL2(image_features_clip)# 搜索最相似的5张图像
index_clip = faiss.read_index("clip.index")
index_dino = faiss.read_index("dino.index")# 获取图像的距离和相关索引
d_dino, i_dino = index_dino.search(image_features_dino, 5)
d_clip, i_clip = index_clip.search(image_features_clip, 5)

结果

使用四张不同的图像作为输入,搜索产生了以下结果:
在这里插入图片描述

4. 在DISC21数据集上进行基准测试

为了比较它们的性能,我们将遵循这篇文章中描述的相同方法。我们还将重用上面的脚本提取特征,然后计算图像相似性。

4.1 数据集

为了对CLIP和DINOv2进行基准测试,我们选择了DISC21数据集,该数据集是专门为图像相似性搜索创建的。由于其大小为350GB,我们将使用其中150,000张图像的子集。

4.2 使用的指标

在指标方面,我们将计算:

  • 准确率:正确预测的图像与图像总数的比率。
  • 前3准确率:在前三张最相似图像中找到正确图像的次数与图像总数的比率。
  • 计算时间:处理整个数据集所需的时间。

4.3 基准测试结果

  • 特征提取

    • CLIP:每秒70.7张图像
    • DINOv2:每秒69.7张图像
  • 准确率和前3准确率
    在这里插入图片描述

  • 检查结果

    • 两个模型都正确预测图像
      在这里插入图片描述
    • 所有模型都未找到正确图像
      在这里插入图片描述
    • 只有CLIP预测正确图像,DINOv2在其前3中预测到
      在这里插入图片描述
    • 只有DINOv2预测正确图像

    在这里插入图片描述

5. 分析

DINOv2显然是领先者,在极具挑战性的数据集上实现了令人印象深刻的64%的准确率。相比之下,CLIP的准确率较为适中,达到28.45%。

关于计算效率,两个模型的特征提取时间非常相似。这种相似性使得在这方面没有一个模型具有明显优势。

5.1 局限性

虽然这个基准测试提供了有价值的见解,但认识到其局限性很重要。评估是在1448张图像的子集上进行的,而与之对比的是150,000张图像的池。考虑到整个数据集有210万张图像,这种缩小的范围是为了节省资源。

值得注意的是,MetaAI使用DISC21数据集作为其模型的基准,这可能使DINOv2具有有利优势。然而,我们在COCO数据集上的测试揭示了有趣的细微差别:DINOv2显示出更强的识别图像主要元素的能力,而CLIP则擅长关注输入图像中的特定细节(如公交车图像所示)。

最后,必须考虑CLIP和DINOv2之间嵌入维度的差异。CLIP使用的嵌入维度为512,而DINOv2使用的是768。虽然可以选择使用具有匹配嵌入维度的更大的CLIP模型,但值得注意的是,这是以速度为代价的。在一个小子集上的快速测试显示性能略有提升,但没有达到DINOv2所展示的水平。

5.2 结论

DINOv2在图像相似性任务中表现出更高的准确率,展示了其在实际应用中的潜力。CLIP虽然值得称赞,但相比之下有所不足。值得注意的是,CLIP在需要关注小细节的场景中可能特别有用。两个模型的计算效率相似,因此选择取决于具体任务。

原文地址:https://medium.com/aimonks/clip-vs-dinov2-in-image-similarity-6fa5aa7ed8c6

相关文章:

基于CLIP和DINOv2实现图像相似性方面的比较

概述 在人工智能领域,CLIP和DINOv2是计算机视觉领域的两大巨头。CLIP彻底改变了图像理解,而DINOv2为自监督学习带来了新的方法。 在本文中,我们将踏上一段旅程,揭示定义CLIP和DINOv2的优势和微妙之处。我们的目标是发现这些模型…...

利用Python爬虫获取API接口:探索数据的力量

引言 在当今数字化时代,数据已成为企业、研究机构和个人获取信息、洞察趋势和做出决策的重要资源。Python爬虫作为一种高效的数据采集工具,能够帮助我们自动化地从互联网上获取大量的数据。而API接口作为数据获取的重要途径之一,为我们提供了…...

【LeetCode】力扣刷题热题100道(1-5题)附源码 链表 子串 中位数 回文子串(C++)

目录 1.两数之和 2.两数相加-链表 3.无重复字符的最长子串 4.寻找两个正序数组的中位数 5.最长回文子串 1.两数之和 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。…...

Docker启动失败 - 解决方案

Docker启动失败 - 解决方案 问题原因解决方案service问题 问题 重启docker失败: toolchainendurance:~$ sudo systemctl restart docker Job for docker.service failed because:the control process exited with error codesee:"systemctl status docker.se…...

【Duilib】 List控件支持多选和获取选择的多条数据

问题 使用Duilib库写的一个UI页面用到了List控件,功能变动想支持选择多行数据。 分析 1、List控件本身支持使用SetMultiSelect接口设置是否多选: void SetMultiSelect(bool bMultiSel);2、List控件本身支持使用GetNextSelItem接口获取选中的下一个索引…...

android系统的一键编译与非一键编译 拆包 刷机方法

1.从远程仓库下载源码 别人已经帮我下载好了在Ubuntu上。并给我权限:chmod -R ow /data/F200/F200-master/ 2.按照readme.txt步骤操作 安装编译环境: sudo apt-get update sudo apt-get install git-core gnupg flex bison gperf build-essential z…...

SQL语言的函数实现

SQL语言的函数实现 引言 随着大数据时代的到来,数据的存储和管理变得越来越复杂。SQL(结构化查询语言)作为关系数据库的标准语言,其重要性不言而喻。在SQL语言中,函数是一个重要的组成部分,可以有效地帮助…...

OSPF - 2、3类LSA(Network-LSA、NetWork-Sunmmary-LSA)

前篇博客有对常用LSA的总结 2类LSA(Network-LSA) DR产生泛洪范围为本区域 作用:  描述MA网络拓扑信息和网络信息,拓扑信息主要描述当前MA网络中伪节点连接着哪几台路由。网络信息描述当前网络的 掩码和DR接口IP地址。 影响邻居建立中说到…...

运动相机拍摄的视频打不开怎么办

3-10 GoPro和大疆DJI运动相机的特点,小巧、高清、续航长、拍摄稳定,很多人会在一些重要场合用来拍摄视频,比如可以用来拿在手里拍摄快速运动中的人等等。 但是毕竟是电子产品,有时候是会出点问题的,比如意外断电、摔重…...

SpringBoot | 使用Apache POI库读取Excel文件介绍

关注WX:CodingTechWork 介绍 在日常开发中,我们经常需要处理Excel文件中的数据。无论是从数据库导入数据、处理数据报表,还是批量生成数据,都可能会遇到需要读取和操作Excel文件的场景。本文将详细介绍如何使用Java中的Apache PO…...

从configure.ac到构建环境:解析Mellanox OFED内核模块构建脚本

在软件开发过程中,特别是在处理复杂的内核模块如Mellanox OFED(OpenFabrics Enterprise Distribution)时,构建一个可移植且高效的构建系统至关重要。Autoconf和Automake等工具在此过程中扮演着核心角色。本文将深入解析一个用于准备Mellanox OFED内核模块构建环境的Autocon…...

c#使用SevenZipSharp实现压缩文件和目录

封装了一个类,方便使用SevenZipSharp,支持加入进度显示事件。 双重加密压缩工具范例: using SevenZip; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.…...

【从0带做】基于Springboot3+Vue3的高校食堂点餐系统

大家好,我是武哥,最近给大家手撸了一个基于SpringBoot3Vue3的高校食堂点餐系统,可用于毕业设计、课程设计、练手学习,系统全部原创,如有遇到网上抄袭站长的,欢迎联系博主~ 详细介绍 https://www.javaxm.c…...

2025年01月09日Github流行趋势

1. 项目名称:khoj 项目地址url:https://github.com/khoj-ai/khoj项目语言:Python历史star数:22750今日star数:1272项目维护者:debanjum, sabaimran, MythicalCow, aam-at, eltociear项目简介:你…...

PostgreSQL学习笔记(二):PostgreSQL基本操作

PostgreSQL 是一个功能强大的开源关系型数据库管理系统 (RDBMS),支持标准的 SQL 语法,并扩展了许多功能强大的操作语法. 数据类型 数值类型 数据类型描述存储大小示例值SMALLINT小范围整数,范围:-32,768 到 32,7672 字节-123INTE…...

关于内网外网,ABC类地址,子网掩码划分

本文的三个关键字是:内网外网,ABC类地址,子网掩码划分。围绕以下问题展开: 如何从ip区分外网、内网?win和linux系统中,如何查询自己的内网ip和外网ip。开发视角看内外网更多是处于安全考虑,接口…...

nginx 配置 本地启动

1.nginx下载地址:nginx: download nginx详解:Nginx配置终极版指南(全网最详细)_nginx_脚本之家 2.vue 项目打包生成dist文件里面的文件复制到下载好的nginx的html目录下 3.配置nginx配置文件 打包生成的dist前端包都是属于生产环…...

UE5 打包要点

------------------------- 1、需要环境 win sdk ,大约3G VS,大约10G 不安装就无法打包,就是这么简单。 ----------------------- 2、打包设置 编译类型,开发、调试、发行 项目设置-地图和模式,默认地图 项目…...

OneFlow的简单介绍

OneFlow 是北京一流科技有限公司旗下的采用全新架构设计的开源工业级通用深度学习框架。以下是关于 OneFlow 的详细介绍: 本篇文章的目录 特点 功能 应用场景 发展历程 特点 简洁易用的接口:为深度学习相关的算法工程师提供一套简洁易用的用户接口…...

聊一聊 C#异步 任务延续的三种底层玩法

一:背景 1. 讲故事 最近聊了不少和异步相关的话题,有点疲倦了,今天再写最后一篇作为近期这类话题的一个封笔吧,下篇继续写我熟悉的 生产故障 系列,突然亲切感油然而生,哈哈,免费给别人看程序故…...

USB PD芯片选型指南:从核心需求到方案对比的工程实践

1. 项目概述:为什么PD芯片选型是个技术活最近在做一个需要USB Type-C接口供电的项目,核心需求是实现完整的PD(Power Delivery)协议通信。这听起来像是个标准化的活儿,市面上芯片那么多,随便选一个不就行了&…...

关联查询,左连接,inner join笔记,BNL,NLJ

文章目录left join的最大值和最小值3个表的inner join关联查询时的is_del处理cross join(full join)NLJ 性能高BNL 性能低blj会导致什么问题?left join的最大值和最小值 假设左表m条,右表n条 最小值是m: 当一条也匹配不到右表时,或者右表中…...

5分钟上手TegraRcmGUI:Windows平台最简单的Switch注入工具终极指南

5分钟上手TegraRcmGUI:Windows平台最简单的Switch注入工具终极指南 【免费下载链接】TegraRcmGUI C GUI for TegraRcmSmash (Fuse Gele exploit for Nintendo Switch) 项目地址: https://gitcode.com/gh_mirrors/te/TegraRcmGUI TegraRcmGUI是专为Nintendo S…...

Ai会不会让越来越多的开发者失去工作机会?

我不知道写这篇Log会不会太激进,可能会让人浮想联翩,对号入座。想想还是要写的,咱们不聊别的,仅仅是讨论一下AI是否真的会让我们这些写了20多年的代码的开发者失业,这还真是一个“悲伤”的讨论。朋友跟我说&#xff1a…...

智慧树自动刷课插件终极指南:5分钟快速上手,告别手动刷课烦恼

智慧树自动刷课插件终极指南:5分钟快速上手,告别手动刷课烦恼 【免费下载链接】zhihuishu 智慧树刷课插件,自动播放下一集、1.5倍速度、无声 项目地址: https://gitcode.com/gh_mirrors/zh/zhihuishu 还在为智慧树平台繁琐的视频操作而…...

基于STM32的智能空调控制器设计:从环境感知到PID控制

1. 项目概述:从传统遥控到智能感知的跨越几年前,我还在为一个老旧的壁挂式空调发愁。每次回家,都得在闷热的房间里摸索遥控器,或者忍受着固定风向的直吹。后来接触了智能家居,发现市面上的智能空调要么价格昂贵&#x…...

终极指南:如何用PowerShell一键安装Windows包管理器Winget [特殊字符]

终极指南:如何用PowerShell一键安装Windows包管理器Winget 🚀 【免费下载链接】winget-install Install WinGet using PowerShell! Prerequisites automatically installed. Works on Windows 10/11 and Server 2019/2022. 项目地址: https://gitcode.…...

深入GD32F427的ENET外设:如何为你的LAN8720 PHY芯片选择正确的RMII时钟模式(REF_CLK In vs Out)

深入解析GD32F427与LAN8720的RMII时钟架构设计 在嵌入式以太网开发中,时钟信号的稳定性往往决定着整个通信系统的可靠性。当GD32F427微控制器通过RMII接口与LAN8720 PHY芯片协同工作时,REF_CLK时钟模式的选择不仅影响硬件成本,更直接关系到信…...

昇腾CANN ascend-boost-comm:M×N 算子复用是怎么做到的

CANN 生态里 50 多个仓库,每个仓库有十几到几十个算子。这些算子之间存在大量公共功能:内存搬运算子需要数据切分、通信算子需要拓扑发现、融合算子需要 shape 推导。如果每个仓库各自实现一遍,代码膨胀的同时,任何一个公共功能的…...

仓库盘点、物流交接?用UniApp+PDA扫码提升效率的实战配置与避坑指南

UniAppPDA扫码在仓储物流中的实战配置与效率提升指南 当仓储管理员小李第一次使用传统扫码枪配合PC系统进行月度盘点时,他需要反复核对Excel表格与实物位置,8小时的工作量常常延长到深夜。而现在,通过UniApp开发的移动端应用配合工业级PDA设备…...