图片查重从设计到实现(6) :图片特征的存储逻辑与实现

接上篇,本文主要介绍 Milvus 数据库的连接方法,以及图片相关数据(向量+元数据)的保存程序逻辑实现 。

一、Milvus 数据库连接

1. 安装 Milvus

首先需要安装 pymilvus 库,确保版本与 Milvus 服务端兼容(建议使用最新稳定版):

pip install pymilvus==2.4.5 # 版本需与 Milvus 服务端匹配,可根据实际情况调整
2. 初始化连接

连接 Milvus 需指定服务端的 主机地址(host)gRPC 端口(默认 19530)。如果 Milvus 启用了认证,还需要提供用户名和密码。

from pymilvus import connections


# 连接 Milvus 服务
connections.connect(
    alias="default",  # 连接别名(可自定义,用于后续操作)
    host="localhost",  # Milvus 服务的主机地址,如远程服务器则填IP
    port="19530",     # 默认 gRPC 端口,HTTP 端口为 9091(较少用)
    # 若启用认证,需添加以下参数
    # user="username",
    # password="password"
)

# 验证连接是否成功
print("连接状态:", connections.has_connection("default"))  # 输出 True 表示连接成功
  • 注意:连接前需确保 Milvus 服务已启
3. 关闭连接(可选)

操作完成后,可关闭连接释放资源:

connections.disconnect("default")  # 关闭指定别名的连接

二、图片在 Milvus 中的保存逻辑

Milvus 不直接存储图片文件,而是存储图片的特征向量(通过模型提取的高维向量)和关联的元数据(如图片 ID、路径、描述等)通过元数据与 Milvus 中的向量关联。

完整流程:图片加载 → 特征向量提取 → 创建 Milvus 集合 → 插入向量+元数据

1. 图片加载与特征向量提取

需使用预训练模型(如 ResNet、CLIP 等)将图片转换为向量。以下以 ResNet50 为例(需安装 torchtorchvisionPIL):

import torch
from torchvision import models, transforms
from PIL import Image
import numpy as np

# 加载预训练的 ResNet50 模型(用于提取图片特征)
model = models.resnet50(pretrained=True)
# 移除最后一层分类层,保留特征提取部分
feature_extractor = torch.nn.Sequential(*list(model.children())[:-1])
feature_extractor.eval()  # 切换到评估模式

# 图片预处理(与模型训练时的预处理一致)
preprocess = transforms.Compose([
    transforms.Resize(256),
    transforms.CenterCrop(224),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
])

def extract_image_vector(image_path):
    """将图片转换为特征向量"""
    # 加载图片
    img = Image.open(image_path).convert('RGB')
    # 预处理
    img_tensor = preprocess(img).unsqueeze(0)  # 增加 batch 维度
    # 提取特征(关闭梯度计算加速)
    with torch.no_grad():
        features = feature_extractor(img_tensor)
    # 转换为一维向量(ResNet50 输出为 2048 维)
    vector = features.squeeze().numpy()  # 形状为 (2048,)
    return vector

# 示例:提取一张图片的向量
image_path = "test.jpg"
vector = extract_image_vector(image_path)
print("向量维度:", vector.shape)  # 输出 (2048,)
2. 创建 Milvus 集合(Collection)

集合是 Milvus 中存储数据的基本单元,需定义** schema **(包含字段名、类型、是否为主键等)。对于图片向量,通常需要:

  • 主键字段(如 image_id,用于唯一标识图片);
  • 向量字段(如 vector,存储图片的特征向量,需指定维度);
  • 元数据字段(如 image_path,存储原始图片的路径,方便后续关联)。
from pymilvus import Collection, FieldSchema, CollectionSchema, DataType

# 1. 定义字段
fields = [
    # 主键字段:整数类型,自增(可选,也可手动指定)
    FieldSchema(name="image_id", dtype=DataType.INT64, is_primary=True, auto_id=True),
    # 向量字段:浮点型向量,维度需与提取的向量一致(如 ResNet50 为 2048 维)
    FieldSchema(name="vector", dtype=DataType.FLOAT_VECTOR, dim=2048),
    # 元数据字段:存储图片路径(字符串类型)
    FieldSchema(name="image_path", dtype=DataType.VARCHAR, max_length=255)
]

# 2. 定义集合 schema
schema = CollectionSchema(fields=fields, description="存储图片特征向量及元数据的集合")

# 3. 创建集合(若已存在可跳过)
collection_name = "image_features"
collection = Collection(name=collection_name, schema=schema)

# 4. 加载集合到内存(Milvus 操作前需加载集合)
collection.load()
3. 插入图片向量及元数据

将提取的向量与元数据(如图片路径)一起插入到集合中:

# 准备插入的数据(可批量插入,效率更高)
# 格式:[ [向量1, 向量2, ...], [图片路径1, 图片路径2, ...] ]
data = [
    [vector],  # 向量列表(此处为单张图片,批量可传入多个向量)
    [image_path]  # 对应的图片路径列表
]

# 插入数据
insert_result = collection.insert(data)
print("插入的主键 ID:", insert_result.primary_keys)  # 输出自动生成的 image_id

# 插入后建议创建索引(加速后续检索,可选但推荐)
# 以 IVF_FLAT 索引为例(适用于中小规模数据)
index_params = {
    "index_type": "IVF_FLAT",
    "metric_type": "L2",  # 距离度量方式(L2 为欧氏距离,IP 为内积)
    "params": {"nlist": 128}  # 聚类数量,根据数据量调整
}
collection.create_index(field_name="vector", index_params=index_params)
print("索引创建完成")

三、关键注意事项

  1. 向量维度匹配:提取的图片向量维度必须与集合中定义的 dim 一致,否则插入会失败。
  2. 原始图片存储:Milvus 仅存储向量和元数据,原始图片需单独存储(如本地文件夹、S3、OSS 等),通过 image_path 或其他元数据关联。
  3. 批量操作优先:批量插入/查询的效率远高于单条操作,实际应用中建议批量处理图片。
  4. 索引选择:根据数据量和检索需求选择合适的索引(如 IVF_FLAT、HNSW 等),并合理调整参数。
  5. 连接管理:生产环境中需处理连接超时、重连等问题,避免频繁创建/关闭连接。
4. 通过Milvus Web UI工具查看

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值