Files
FoodClassifier/faiss_vector_db/run_faiss_demo.py
T
2025-10-17 18:24:04 +08:00

244 lines
7.5 KiB
Python

"""
FAISS相似度检索系统快速演示脚本
一键运行完整的索引构建和检索演示
"""
import os
import time
def check_dependencies():
"""检查依赖包"""
required_packages = [
'torch', 'torchvision', 'faiss', 'PIL', 'numpy', 'tqdm', 'matplotlib'
]
missing_packages = []
for package in required_packages:
try:
if package == 'PIL':
import PIL
elif package == 'faiss':
import faiss
else:
__import__(package)
except ImportError:
missing_packages.append(package)
if missing_packages:
print("缺少以下依赖包:")
for pkg in missing_packages:
if pkg == 'faiss':
print(f" {pkg} (安装命令: pip install faiss-cpu)")
else:
print(f" {pkg}")
print("\n请先安装缺少的依赖包")
return False
return True
def check_files():
"""检查必要文件"""
required_files = [
'net/resnet_embedding.py',
'settings/settings.py',
'model/embedding_20250917_145342/best_embedding_model.pth',
'dataset/train'
]
missing_files = []
for file_path in required_files:
if not os.path.exists(file_path):
missing_files.append(file_path)
if missing_files:
print("缺少以下必要文件:")
for file_path in missing_files:
print(f" {file_path}")
return False
return True
def run_index_building():
"""运行索引构建"""
print("=" * 60)
print("步骤 1: 构建FAISS索引")
print("=" * 60)
try:
from faiss_vector_db.build_faiss_index import main as build_main
build_main()
return True
except Exception as e:
print(f"索引构建失败: {e}")
import traceback
traceback.print_exc()
return False
def run_search_demo():
"""运行检索演示"""
print("\n" + "=" * 60)
print("步骤 2: 相似度检索演示")
print("=" * 60)
try:
from faiss_vector_db.build_faiss_index import FAISSSearcher
# 配置参数
index_dir = "DishClassification/faiss_index"
model_path = "../model/embedding_20250917_145342/best_embedding_model.pth"
# 检查索引是否存在
if not os.path.exists(os.path.join(index_dir, 'faiss_index.bin')):
print("错误: FAISS索引不存在,请先构建索引")
return False
# 创建检索器
searcher = FAISSSearcher(index_dir, model_path)
# 显示索引信息
print(f"索引信息:")
print(f" 总向量数: {searcher.index.ntotal}")
print(f" 特征维度: {searcher.embedding_dim}")
print(f" 类别数: {len(searcher.class_names)}")
print(f" 类别: {', '.join(searcher.class_names)}")
# 找一些测试图片
test_images = []
test_dirs = ['dataset/test', 'dataset/val', 'dataset/train']
for test_dir in test_dirs:
if os.path.exists(test_dir):
for root, dirs, files in os.walk(test_dir):
for file in files:
if file.lower().endswith(('.jpg', '.jpeg', '.png')):
test_images.append(os.path.join(root, file))
if len(test_images) >= 3: # 只测试3张图片
break
if len(test_images) >= 3:
break
if len(test_images) >= 3:
break
if not test_images:
print("未找到测试图片")
return False
# 执行相似度检索演示
print(f"\n开始相似度检索演示 (测试 {len(test_images)} 张图片):")
print("-" * 50)
total_time = 0
for i, test_image in enumerate(test_images, 1):
print(f"\n[{i}/{len(test_images)}] 测试图片: {os.path.relpath(test_image)}")
start_time = time.time()
results = searcher.search_similar(test_image, k=5)
search_time = time.time() - start_time
total_time += search_time
print(f"搜索耗时: {search_time:.3f}秒")
print("最相似的5张图片:")
for j, (img_path, class_name, score) in enumerate(results, 1):
rel_path = os.path.relpath(img_path)
print(f" {j}. {os.path.basename(img_path):20s} "
f"类别: {class_name:8s} "
f"相似度: {score:.4f}")
# 统计类别分布
class_counts = {}
for _, class_name, _ in results:
class_counts[class_name] = class_counts.get(class_name, 0) + 1
print(f" 类别分布: {dict(class_counts)}")
print(f"\n演示完成!")
print(f"平均搜索时间: {total_time/len(test_images):.3f}秒")
return True
except Exception as e:
print(f"检索演示失败: {e}")
import traceback
traceback.print_exc()
return False
def show_usage_examples():
"""显示使用示例"""
print("\n" + "=" * 60)
print("使用示例")
print("=" * 60)
print("\n1. 查看索引信息:")
print(" python faiss_similarity_search.py --info")
print("\n2. 单张图片相似度检索:")
print(" python faiss_similarity_search.py --query dataset/test/回锅肉/aug_000.jpg")
print("\n3. 显示检索结果图片:")
print(" python faiss_similarity_search.py --query dataset/test/回锅肉/aug_000.jpg --show_images")
print("\n4. 批量测试:")
print(" python faiss_similarity_search.py --batch_test dataset/test --max_tests 10")
print("\n5. 保存结果图片:")
print(" python faiss_similarity_search.py --query dataset/test/回锅肉/aug_000.jpg --show_images --save_result")
def main():
"""主函数"""
print("FAISS相似度检索系统 - 快速演示")
print("=" * 60)
# 检查依赖
print("检查依赖包...")
if not check_dependencies():
return
print("✓ 依赖包检查通过")
# 检查文件
print("检查必要文件...")
if not check_files():
return
print("✓ 文件检查通过")
# 检查是否已有索引
index_exists = os.path.exists("DishClassification/faiss_index/faiss_index.bin")
if index_exists:
print("✓ 发现已存在的FAISS索引")
# 询问是否重新构建
while True:
choice = input("\n是否重新构建索引? (y/n): ").lower().strip()
if choice in ['y', 'yes', '是']:
if not run_index_building():
return
break
elif choice in ['n', 'no', '否']:
print("跳过索引构建,直接进行检索演示")
break
else:
print("请输入 y 或 n")
else:
print("未发现FAISS索引,开始构建...")
if not run_index_building():
return
# 运行检索演示
if not run_search_demo():
return
# 显示使用示例
show_usage_examples()
print("\n" + "=" * 60)
print("演示完成! 🎉")
print("您现在可以使用 faiss_similarity_search.py 进行更多测试")
print("=" * 60)
if __name__ == "__main__":
main()