You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Milvus的图像相似性搜索无结果问题求助

图像相似性搜索无结果排查问题

我参考图像反向搜索的Notebook开发相似性搜索功能,目前遇到搜索无结果的问题,但验证同一张图的向量余弦相似度接近1,说明向量存储是正确的,不清楚问题出在哪。

我的实现代码

初始化参数与索引创建

import csv
from glob import glob
from pathlib import Path
from statistics import mean

from towhee import pipe, ops, DataCollection
from pymilvus import connections, FieldSchema, CollectionSchema, DataType, Collection, utility


# Towhee parameters
MODEL = 'resnet50'

# Milvus parameters
HOST = [MY_HOST]
PORT = [MY_PORT]
TOPK = 5
DIM = 2048 
COLLECTION_NAME = 'images'
INDEX_TYPE = 'IVF_FLAT'
METRIC_TYPE = 'L2'

index_params = {
    'metric_type': METRIC_TYPE,
    'index_type': INDEX_TYPE,
    'params': {"nlist": 2048}
}

collection.create_index(field_name='image', index_params=index_params, index_name = "image_index")

图像向量化与数据插入

# Load image path
def load_image(x):
    if x.endswith('csv'):
        with open(x) as f:
            reader = csv.reader(f)
            next(reader)
            for item in reader:
                yield item[1]
    else:
        for item in glob(x):
            yield item
            
# Embedding pipeline
p_embed = (
    pipe.input('src')
        .flat_map('src', 'img_path', load_image)
        .map('img_path', 'img', ops.image_decode())
        .map('img', 'vec', ops.image_embedding.timm(model_name=MODEL))
)


image_save_dir = [MY_IMAGE_PATH]
p_display = p_embed.output('img_path', 'img', 'vec') 
result = DataCollection(p_display(image_save_dir))

# check result
result.show()
print(result[0]['img_path'])
print(result[0]['vec'])    

connections.connect(alias='default', host=HOST, port=PORT)
collection_name = "clothes"
collection = Collection(name = collection_name)

for i, r in enumerate(result):
    vector = r['vec']
    collection.insert([
        {
            "clothes_id" : i,
            "category" : "top",
            "color" : "black",
            "image" : vector,
            "gender" : ["F"],
            "style" : ["casual"],
            "thickness" : [],
            "season" : ["spring"]
        }
    ])

搜索代码(无结果)

p_search_pre = (
        p_embed.map('vec', ('search_res'), ops.ann_search.milvus_client(
                    host=HOST, port=PORT, limit=5,
                    collection_name="clothes"))
               .map('search_res', 'pred', lambda x: [y[0] for y in x]) # get id
)

p_search = p_search_pre.output('img_path', 'pred') 

# Search for example query image(s)
collection.load()
dc = p_search('[MY_IMAGE_PATH]/test37.png')

# Display search results with image paths
DataCollection(dc).show()

验证代码(余弦相似度接近1)

from numpy import dot
from numpy.linalg import norm
import numpy as np

def cos_similarity(A, B):
    return dot(A, B) / (norm(A) * norm(B))

test_image = '[MY_IMAGE_PATH]/test38.png'
p_display = p_embed.output('img_path', 'img', 'vec') 
result = DataCollection(p_display(image_save_dir))

collection_name = 'clothes' 
collection = Collection(name=collection_name)

# get image vector where clothes_id=38
save_results = collection.query(
    expr="clothes_id == 38",
    output_fields=["clothes_id", "category", "color", "gender", "style", "thickness", "season", "image"]
)

if save_results:
    saved_image_vector = save_results[0]["image"]
    result_vector = np.array(result[0]['vec'])
    saved_image_vector = np.array(saved_image_vector)

    # get similarity
    similarity = cos_similarity(result_vector, saved_image_vector)
    print(f"cosine similarity : {similarity}")
else:
    print("there is no images")

问题点

  • 执行搜索时无任何结果返回,但验证同一张图像的向量余弦相似度约为1,说明向量存储正确。
  • 不清楚搜索无结果的原因。

可能的原因与解决方案

1. 索引创建时机错误

代码开头直接调用collection.create_index时,collection还未连接到Milvus或指定目标clothes集合,这行代码并未对实际使用的集合生效。
解决:在数据插入完成后,对clothes集合创建索引并加载:

# 插入数据后添加以下代码
collection.create_index(field_name='image', index_params=index_params, index_name="image_index")
collection.load()

2. IVF_FLAT索引缺少搜索参数

IVF_FLAT索引搜索时需要指定nprobe参数(默认值过小会导致无法命中数据),当前搜索算子未配置该参数。
解决:在搜索算子中添加search_params={"nprobe": 10}(可根据nlist调整,一般设为nlist的1/10~1/20):

p_search_pre = (
        p_embed.map('vec', ('search_res'), ops.ann_search.milvus_client(
                    host=HOST, port=PORT, limit=5,
                    collection_name="clothes",
                    search_params={"nprobe": 10}))
               .map('search_res', 'pred', lambda x: [y[0] for y in x])
)

3. 搜索结果解析逻辑错误

Milvus搜索结果格式可能因版本不同有差异,当前lambda x: [y[0] for y in x]的解析逻辑可能不正确。
解决:先打印search_res查看实际结构,再调整解析逻辑:

p_search_pre = (
        p_embed.map('vec', ('search_res'), ops.ann_search.milvus_client(
                    host=HOST, port=PORT, limit=5,
                    collection_name="clothes"))
               .map('search_res', 'pred', lambda x: print(x)) # 先打印结果结构
)

4. 集合字段维度不匹配

确认clothes集合中image字段的维度是否为2048(resnet50输出的向量维度),维度不匹配会导致搜索无结果。
解决:通过print(collection.schema)查看字段定义,确保image字段的dim参数为2048。


内容的提问来源于stack exchange,提问作者Rashad Tockey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 15:44:55