基于VGG16+Milvus的以图搜图系统实现教程

基于VGG16+Milvus的以图搜图系统实现教程

一、项目简介

以图搜图技术作为计算机视觉领域的热门应用,能够帮助用户快速从海量图片库中找到相似度最高的目标图片。本项目基于VGG16特征提取模型+Milvus向量检索引擎,结合FlaskWeb框架与Docker容器化技术,实现了高效、稳定的以图搜图功能。系统支持上传图片后自动提取特征,通过欧氏距离计算相似度,最终返回Top30相似图片,适用于图片素材管理、版权检索等场景。

二、核心技术栈

1. 特征提取

  • 模型:VGG16(预训练权重imagenet,微调适配图像特征提取)
  • 框架:Keras + TensorFlow(模型搭建与训练)

2. 向量检索与并行计算

  • Milvus:开源向量数据库,高效处理海量特征向量的相似度检索
  • Docker:容器化部署Milvus,保证环境一致性与可移植性

3. 前后端开发

  • 前端:HTML + jQuery(页面布局与交互,图片流展示)
  • 后端:Python Flask(接口开发、请求处理与逻辑调度)

4. 数据存储

  • SQLite:存储图片元信息
  • Milvus:存储图片特征向量

三、环境搭建步骤

1. Docker与Milvus部署

Milvus作为向量检索核心,需通过Docker容器启动,步骤如下:

(1)查看Docker容器状态

打开终端,执行以下命令查看当前Docker中运行的容器:

shell 复制代码
docker ps -a

若出现如下结果,说明Milvus容器已存在但处于退出状态(CONTAINER ID为120aa8c0fd25,名称milvus_cpu):

CONTAINER ID IMAGE STATUS PORTS NAMES
120aa8c0fd25 milvusdb/milvus:0.8.0-cpu-xxx Exited (255) 2min ago 0.0.0.0:9091->9091/tcp, 0.0.0.0:19121->19121/tcp, 0.0.0.0:19530->19530/tcp milvus_cpu
(2)重启Milvus容器

通过容器ID重启Milvus(替换为你的容器ID):

shell 复制代码
docker restart 120aa8c0fd25

重启后再次执行docker ps -a,若STATUS显示为Up,则说明Milvus启动成功。

2. 项目依赖安装

创建Python虚拟环境,安装所需依赖包:

shell 复制代码
# 创建虚拟环境
python -m venv search_env
# 激活环境(Windows)
search_env\Scripts\activate
# 激活环境(Linux/Mac)
source search_env/bin/activate
# 安装依赖
pip install keras tensorflow flask milvus numpy pillow

四、项目启动流程

1. 项目结构(核心文件)

复制代码
SearchImage/
├── model/          # 模型文件目录(VGG16权重)
├── temp/           # 临时图片存储目录(用户上传图片)
├── static/         # 静态资源(CSS/JS)
├── templates/      # 前端模板(image.html)
├── manage.py       # 项目入口文件
└── search_image.py # 特征提取与检索核心逻辑

2. 启动Flask项目

(1)打开核心入口文件

找到项目根目录下的manage.py文件,确保包含Flask应用初始化代码(关键代码示例):

python 复制代码
from flask import Flask, render_template
import os

app = Flask(__name__)
basedir = os.path.abspath(os.path.dirname(__file__))

# 图片搜索接口
@app.route('/search/<string:image>')
def search(image):
    root = os.path.join(basedir, 'temp')
    path = os.path.join(root, image)
    if IsValidImage(path):  # 图片有效性校验函数
        return render_template("image.html", my_list=search_image.search(path))
    else:
        return '请保证图片的完整性!'

if __name__ == '__main__':
    app.run(debug=True)
(2)运行项目

在终端执行:

shell 复制代码
python manage.py

若启动成功,会显示类似日志:

复制代码
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
 * Restarting with stat
(3)访问系统

打开浏览器,输入地址:http://127.0.0.1:5000/,即可进入以图搜图首页。

五、核心功能实现

1. VGG16特征提取模型(STEP1:训练与初始化)

VGG16模型负责将图片转化为高维特征向量,核心代码如下:

python 复制代码
# -*- coding: utf-8 -*-
import keras
import numpy as np
from numpy import linalg as LA
from keras.applications.vgg16 import VGG16
from keras.preprocessing import image
from keras.applications.vgg16 import preprocess_input

class VGGNet:
    def __init__(self):
        keras.backend.clear_session()
        # 模型配置:输入尺寸224x224x3,使用imagenet预训练权重,max pooling
        self.input_shape = (224, 224, 3)
        self.weight = 'imagenet'
        self.pooling = 'max'
        # 初始化VGG16模型(不含顶层全连接层,用于特征提取)
        self.model = VGG16(weights=self.weight,
                          input_shape=(self.input_shape[0], self.input_shape[1], self.input_shape[2]),
                          pooling=self.pooling, include_top=False)
        # 预热模型(可选:加载自定义微调权重)
        # self.model.load_weights(r'./model/vgg16_use6.h5', by_name=True)
        self.model.predict(np.zeros((1, 224, 224, 3)))  # 初始化预测

    # 提取图片特征向量
    def extract_feat(self, img_path):
        img = image.load_img(img_path, target_size=(self.input_shape[0], self.input_shape[1]))
        x = image.img_to_array(img)
        x = np.expand_dims(x, axis=0)
        x = preprocess_input(x)
        feat = self.model.predict(x)  # 特征提取
        norm_feat = feat[0] / LA.norm(feat[0])  # 归一化
        return norm_feat
VGG16特征提取流程详解
  1. 输入图像:尺寸调整为224x224x3(RGB三通道);
  2. 卷积层:经64→128→256→512→512通道的卷积核(3x3)多次卷积,每次卷积后用ReLU激活;
  3. 池化层:每轮卷积后通过2x2 max pooling降维,图像尺寸减半;
  4. 全连接层:最终通过Flatten拉平为25088维向量,经3层全连接层处理;
  5. 特征输出:去除顶层softmax,输出512维特征向量(max pooling后)。

2. 相似度检索(STEP2:Milvus向量匹配)

核心逻辑
  1. 训练集预处理:将所有图片通过VGG16提取特征向量,存入Milvus向量数据库与SQLite(关联图片路径);
  2. 用户上传图片:提取特征向量后,通过Milvus计算与数据库中所有向量的欧氏距离;
  3. 结果排序:按欧氏距离从小到大排序,取前30个相似度最高的结果。
关键代码(search_image.py)
python 复制代码
from milvus import Milvus, IndexType, MetricType
from VGGNet import VGGNet
import sqlite3

# Milvus连接配置
MILVUS_HOST = '127.0.0.1'
MILVUS_PORT = 19530
collection_name = 'image_features'

# 初始化Milvus客户端与VGG模型
milvus = Milvus(MILVUS_HOST, MILVUS_PORT)
vgg_model = VGGNet()

def search(img_path, top_k=30):
    # 提取上传图片特征
    query_feat = vgg_model.extract_feat(img_path)
    # Milvus相似度检索(欧氏距离)
    search_param = {"nprobe": 16}
    results = milvus.search(collection_name=collection_name,
                           query_records=[query_feat],
                           top_k=top_k,
                           params=search_param,
                           metric_type=MetricType.L2)
    # 从SQLite查询图片路径(根据Milvus返回的id关联)
    conn = sqlite3.connect('image_db.sqlite')
    cursor = conn.cursor()
    similar_imgs = []
    for res in results[0]:
        img_id = res.id
        distance = res.distance
        # 计算相似度(距离越小相似度越高,此处映射为百分比)
        similarity = (1 - distance / np.max(results[0][0].distance)) * 100
        cursor.execute("SELECT img_path FROM images WHERE id=?", (img_id,))
        img_path = cursor.fetchone()[0]
        similar_imgs.append({"path": img_path, "similarity": round(similarity, 2)})
    conn.close()
    return similar_imgs

3. 前端展示(STEP3:HTML页面渲染)

通过Flask模板将相似度结果渲染到前端,核心代码(templates/image.html):

html 复制代码
<!DOCTYPE html>
<html>
<head>
    <title>以图搜图 - 相似结果</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
    <style>
        .img-item { float: left; margin: 10px; text-align: center; }
        .img-item img { width: 200px; height: auto; border: 1px solid #eee; }
        .similarity { color: red; font-weight: bold; }
    </style>
</head>
<body>
    <h1>相似图片结果(Top30)</h1>
    <div class="img-container">
        {% for item in my_list %}
        <div class="img-item">
            <img src="{{ url_for('static', filename=item.path) }}" alt="相似图片">
            <p>相似度:<span class="similarity">{{ item.similarity }}%</span></p>
        </div>
        {% endfor %}
    </div>
</body>
</html>

六、系统演示

1. 首页界面

访问http://127.0.0.1:5000/,上传本地图片(支持JPG、PNG等格式):

2. 检索结果展示

上传图片后,系统自动跳转至结果页,展示Top30相似图片及对应相似度:

示例结果:

  • 相似度56.90%(最高匹配)
  • 相似度55.65%
  • 相似度50.49%
    ...

七、关键问题与解决方案

1. Milvus容器启动失败

  • 检查端口是否被占用(19530、19121、9091),执行netstat -ano | findstr 19530查看占用进程并关闭;
  • 重新拉取Milvus镜像:docker pull milvusdb/milvus:0.8.0-cpu-d041520-464400

2. 特征提取速度慢

  • 优化:使用GPU加速(替换Milvus GPU版本+TensorFlow GPU版);
  • 批量处理:训练集图片提前提取特征并入库,避免实时计算。

3. 相似度准确率低

  • 微调VGG16模型:使用自定义数据集重新训练顶层全连接层;
  • 调整相似度计算方式:改用余弦相似度(MetricType.IP),需同步修改特征归一化逻辑。

八、项目扩展方向

  1. 支持更多图片格式(WebP、SVG等)与批量上传;
  2. 加入图片预处理(去噪、缩放、旋转不变性优化);
  3. 结合Redis缓存热门查询结果,提升响应速度;
  4. 开发移动端适配界面,支持手机端上传图片检索。

总结

本项目通过VGG16模型实现高效特征提取,结合Milvus向量数据库的快速检索能力,构建了一套完整的以图搜图系统。Docker容器化部署确保了环境一致性,Flask+jQuery简化了前后端开发流程。系统可直接用于小型图片库检索,通过微调模型与优化配置,也可扩展至百万级图片库场景。

相关推荐
工藤学编程3 小时前
零基础学AI大模型之Milvus实战:Attu可视化安装+Python整合全案例
人工智能·python·milvus
天命码喽c8 小时前
GraphRAG-2.7.0整合Milvus-2.5.1
开发语言·python·milvus·graphrag
大猫子的技术日记1 天前
【大模型杂货铺】 阿里云服务器 Milvus 极简安装教程
milvus
小毅&Nora1 天前
【向量数据库】Milvus向量数据库 ③ 深度解析与性能优化实战
数据库·性能优化·milvus
昙鱼5 天前
Markdown文件导入Milvus向量数据库完整指南
数据库·ai·milvus
昙鱼5 天前
embeddingModel操作milvus数据库集合
spring boot·milvus·spring ai
x***J3485 天前
VueWebSocket案例
分布式·milvus·appcompat
6***x5456 天前
C++在计算机视觉中的图像处理
c++·图像处理·计算机视觉·游戏引擎·logback·milvus
weixin_4462608510 天前
Milvus:高效能的云原生向量数据库
数据库·云原生·milvus