基于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 nn

device = 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 nn

device = 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_state
    image_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_state
    image_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 np

device = 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_features

def 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_state
        return 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_state
    image_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 vector

image_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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【学习笔记】数据结构(十)

内部排序 文章目录 内部排序10.1 概述10.2 插入排序10.2.1 直接插入排序10.2.2 其他插入排序10.2.2.1 折半插入排序(Binary Insertion Sort)10.2.2.2 2-路插入排序(Two-Way Insertion Sort)10.2.2.3 表插入排序(Table Insertion Sort&#xf…

Unity学习笔记(七)使用状态机重构角色攻击

前言 本文为Udemy课程The Ultimate Guide to Creating an RPG Game in Unity学习笔记 攻击状态重构 首先我们重构攻击状态的动画 之前的动画,我们是使用状态(isAttacking)攻击次数(comboCounter)完成动画的过渡,这样虽然能完成功能,但是如…

Ubuntu20.04中安装ns-3.36及遇到的问题

一、安装虚拟机:VMware 17.5 参考教程:VMware17Pro虚拟机安装教程(超详细)-CSDN博客 博主:七维大脑 遇到的问题: Q1:安装ubuntu系统时,页面看不到”继续“选项,无法进行下一步 A&#xff…

iOS 逆向学习 - iOS Architecture Cocoa Touch Layer

iOS 逆向学习 - iOS Architecture Cocoa Touch Layer 一、Cocoa Touch Layer 简介二、Cocoa Touch Layer 的核心功能1. UIKit2. Event Handling(事件处理)3. Multitasking(多任务处理)4. Push Notifications(推送通知&…

人大金仓实现主键自增.

使用数据库中自带的参数类型 serial 类型(相当于创建一个INT列), 或者bigserial(相当于创建一个BIGINT列. 示例sql: CREATE TABLE ord(id SERIAL,ord_no INT NOT NULL,ord_name VARCHAR(32),CONSTRAINT "ord_PKEY" PRIMARY KEY ("id"));插入时指定自增值…

React Router 向路由组件传state参数浏览器回退历史页面显示效果问题

昨天在看尚硅谷张天禹老师讲的 React教程p90,老师讲到 React路由的 replace模式和push模式,老师的演示效果与自己本地操作不太一样。 老师的效果:点击查看消息1,消息2,消息3 再点回退,可以依次查看到 消息…

selenium无法定位元素的几种解决方案

🍅 点击文末小卡片,免费获取软件测试全套资料,资料在手,涨薪更快 1、frame/iframe表单嵌套 WebDriver只能在一个页面上对元素识别与定位,对于frame/iframe表单内嵌的页面元素无法直接定位。 解决方法: d…

SSM-Spring-IOC/DI注解开发

目录 IOC/DI注解开发 1 注解开发定义bean 2 纯注解开发模式 步骤 Bean的作用范围 Bean生命周期 3 注解开发依赖注入 Autowired 注解实现按照名称注入 简单数据类型注入 注解读取properties配置文件 4 IOC/DI 注解开发管理第三方bean 4.1 步骤(以管理第三…

深入探讨 Android 中的 AlarmManager:定时任务调度及优化实践

引言 在 Android 开发中,AlarmManager 是一个非常重要的系统服务,用于设置定时任务或者周期性任务。无论是设置一个闹钟,还是定时进行数据同步,AlarmManager 都是不可或缺的工具之一。然而,随着 Android 系统的不断演…

接口开发完后,个人对于接下来接口优化的一些思考

优化点 入参的合法性和长度范围&#xff0c;必填项的检查验证 因为没有入参&#xff0c;所以不需要考虑。 批量思想解决N1问题 // 假设要查询100个订单及其对应的用户信息 List<Order> orders orderMapper.selectList(new QueryWrapper<>().last("limit …

Redis内存碎片

什么是内存碎片? 你可以将内存碎片简单地理解为那些不可用的空闲内存。 举个例子&#xff1a;操作系统为你分配了 32 字节的连续内存空间&#xff0c;而你存储数据实际只需要使用 24 字节内存空间&#xff0c;那这多余出来的 8 字节内存空间如果后续没办法再被分配存储其他数…

小程序租赁系统开发的优势与应用前景分析

内容概要 小程序租赁系统是一种新兴的数字化解决方案&#xff0c;旨在为用户提供更加便捷与高效的租赁服务。它通常包括一系列功能&#xff0c;如在线浏览、即时预定、支付功能以及用户反馈机制。这些系统在使用上极为友好&#xff0c;让用户能够轻松选择所需的商品或服务&…

25年1月更新。Windows 上搭建 Python 开发环境:PyCharm 安装全攻略(文中有安装包不用官网下载)

python环境没有安装的可以点击这里先安装好python环境&#xff0c;python环境安装教程 安装 PyCharm IDE 获取 PyCharm PyCharm 提供两种主要版本——社区版&#xff08;免费&#xff09;和专业版&#xff08;付费&#xff09;。对于初学者和个人开发者而言&#xff0c;社区…

RedisTemplate执行lua脚本及Lua 脚本语言详解

使用RedisTemplate执行lua脚本 在开发中&#xff0c;我们经常需要与Redis数据库进行交互&#xff0c;而Redis是一个基于内存的高性能键值存储数据库&#xff0c;它支持多种数据结构&#xff0c;并提供了丰富的命令接口。在某些情况下&#xff0c;我们可能需要执行一些复杂的逻…

基于Python 的宠物管理系统(源码+部署)

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

stm32第一次烧录或者上电运行卡死问题分析

问题描述 单片机烧录代码&#xff08;刚上电&#xff09;无法立即运行&#xff0c;必须要复位一次或多次才能运行&#xff1b;跟踪调试会进入HardFault_Handler中断。 问题分析 烧录配置如下图&#xff0c;首先排除配置问题那么该问题就比较让人头大了&#xff0c;理论上&am…

ESP32-C3 AT WiFi AP 启 TCP Server 被动接收模式 + BLE 共存

TCP 被动接收模式&#xff0c;每次发的数据会先存到缓冲区&#xff0c;参见&#xff1a;ATCIPRECVTYPE 指令说明。 即每包数据不会实时报告 IPD 接收情况&#xff0c;如果需要查询缓冲区的数据&#xff0c;先用 ATCIPRECVLEN? 指令查询被动接收模式下套接字数据的长度 。获取…

【LeetCode Hot100 二分查找】搜索插入位置、搜索二维矩阵、搜索旋转排序数组、寻找两个正序数组的中位数

二分查找 搜索插入位置搜索二维矩阵在排序数组中查找元素的第一个和最后一个位置寻找旋转排序数组中的最小值搜索旋转排序数组寻找两个正序数组的中位数&#xff08;hard&#xff09; 搜索插入位置 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并…

ChatGPT 主流模型GPT-4/GPT-4o mini的参数规模是多大?

微软论文又把 OpenAI 的机密泄露了&#xff1f;&#xff1f;在论文中明晃晃写着&#xff1a; o1-preview 约 300B&#xff1b;o1-mini 约 100BGPT-4o 约 200B&#xff1b;GPT-4o-mini 约 8BClaude 3.5 Sonnet 2024-10-22 版本约 175B微软自己的 Phi-3-7B&#xff0c;这个不用约…

Docker 安装Elasticsearch搜索引擎 搜索优化 词库挂载 拼音分词 插件安装

介绍 允许用户快速索引和搜索大量的文本数据。通过使用倒排索引&#xff0c;它能够在海量数据中高效检索相关信息。提供灵活的查询语言&#xff0c;可以做全文搜索、模糊搜索、数据统计等&#xff0c;用来代替MYSQL的模糊搜索&#xff0c;MYSQL的模糊搜索不支持使用索引从而导…