4. BLIP视觉编码器特征提取

任务说明

本案例使用BLIP模型的视觉编码器(ViT-B/16)对一组图像提取全局特征([CLS] 对应的输出向量),并基于余弦相似度实现图像检索。输入为本地图像目录,输出为查询图像的Top-K相似图像列表及相似度分数。

实现方案

利用HuggingFace transformers库中的BlipModel,该模型包含独立的视觉编码器。通过get_image_features方法直接获取归一化后的全局特征向量,无需额外池化层。检索时计算查询特征与库特征的余弦相似度(特征已归一化,点积即余弦相似度),按降序返回Top-K结果。

代码实现

import torch
import torch.nn.functional as F
from PIL import Image
from transformers import BlipModel, BlipProcessor
import os
import glob

# ========== 配置 ==========
MODEL_NAME = "Salesforce/blip-image-captioning-base"
IMAGE_DIR = "./images"          # 图像库目录(支持jpg/png)
QUERY_IMAGE = "./query.jpg"     # 查询图像
TOP_K = 3                       # 返回最相似的K张

# ========== 初始化模型 ==========
device = "cuda" if torch.cuda.is_available() else "cpu"
processor = BlipProcessor.from_pretrained(MODEL_NAME)
model = BlipModel.from_pretrained(MODEL_NAME).to(device).eval()

# ========== 提取单张图像特征 ==========
def extract_feature(image_path):
    image = Image.open(image_path).convert("RGB")
    inputs = processor(images=image, return_tensors="pt").to(device)
    with torch.no_grad():
        # 返回归一化的图像特征 [1, 256]
        feature = model.get_image_features(**inputs)
    return feature.cpu().squeeze(0)  # [256]

# ========== 构建图像库特征 ==========
image_paths = sorted(glob.glob(os.path.join(IMAGE_DIR, "*.jpg")) +
                     glob.glob(os.path.join(IMAGE_DIR, "*.png")))
assert len(image_paths) > 0, f"图像目录 {IMAGE_DIR} 中没有jpg/png文件"

gallery_features = []
for path in image_paths:
    feat = extract_feature(path)
    gallery_features.append(feat)
gallery_features = torch.stack(gallery_features)  # [N, 256]

# ========== 图像检索 ==========
query_feat = extract_feature(QUERY_IMAGE)
# 特征已归一化,点积即余弦相似度
similarities = torch.mv(gallery_features, query_feat)  # [N]
topk_scores, topk_indices = torch.topk(similarities, k=min(TOP_K, len(image_paths)))

# ========== 输出结果 ==========
print(f"查询图像: {QUERY_IMAGE}")
print(f"图像库数量: {len(image_paths)}")
print(f"Top-{len(topk_indices)} 检索结果:")
for rank, (idx, score) in enumerate(zip(topk_indices, topk_scores), 1):
    print(f"  {rank}. {image_paths[idx]}  相似度: {score.item():.4f}")

运行与验证

依赖安装:

pip install torch torchvision transformers pillow

准备数据:创建./images目录并放入至少3张不同类别的图片(如猫、狗、汽车各一张),将查询图片命名为query.jpg放在项目根目录(查询图片可以是图像库中的任意一张,用于验证检索正确性)。

运行:

python blip_retrieval.py

判定标准:

  1. 程序正常输出Top-K结果,无报错;
  2. 若查询图片来自图像库,则自身应出现在结果中且相似度最高(接近1.0);
  3. 相似度分数均在0~1之间,且同类图片的相似度明显高于不同类图片。
BLIP视觉编码器图像检索流程 图像库 (N张) 查询图像 BLIP视觉编码器 (ViT-B/16) 库特征矩阵 [N, 256] 归一化 查询特征 [256] 归一化 逐张 [N,256] [256] 余弦相似度 点积 (已归一化) Top-K 排序输出 相似度降序

关键说明

  • get_image_features返回的向量已做L2归一化,因此点积结果即为余弦相似度,取值范围[-1,1];
  • 模型首次运行会自动下载权重(约990MB),需保持网络畅通;
  • 若图像库包含查询图自身,其相似度应为1.0(浮点误差范围内),这是验证特征提取正确性的关键指标。