基于.NET后端实现图片搜索图片库 核心是计算上传图片与库中图片的特征向量相似度并排序展示结果

发布于:2025-04-17 ⋅ 阅读:(39) ⋅ 点赞:(0)

基于.NET 后端实现图片搜索图片库的方案,核心是计算上传图片与库中图片的特征向量相似度并排序展示结果。

整体思路

  1. 图像特征提取:使用深度学习模型(如 ResNet)提取图片的特征向量。
  2. 特征向量存储:将图片的特征向量存储在数据库中。
  3. 相似度计算:使用余弦相似度算法计算上传图片与库中图片的特征向量相似度。
  4. 结果排序与展示:按相似度从高到低排序,并将相似图像展示给用户。

实现步骤

1. 项目搭建

创建一个新的 .NET Web API 项目,安装必要的 NuGet 包:

  • Microsoft.EntityFrameworkCore.SqlServer:用于与 SQL Server 数据库交互。
  • ML.NET:用于特征提取和相似度计算。
  • ImageSharp:用于图像处理。
2. 图像特征提取

使用 ResNet 模型提取图片的特征向量。以下是一个示例代码:

using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using Microsoft.ML;
using Microsoft.ML.Data;
using Microsoft.ML.Vision;

public class ImageData
{
    [LoadColumn(0)]
    public string ImagePath;
}

public class ImagePrediction
{
    [ColumnName("Score")]
    public float[] Score;
}

public class FeatureExtractor
{
    private readonly MLContext _mlContext;
    private readonly ITransformer _model;

    public FeatureExtractor()
    {
        _mlContext = new MLContext();
        var data = _mlContext.Data.LoadFromEnumerable(new List<ImageData>());
        var pipeline = _mlContext.Transforms.LoadImages(outputColumnName: "input", imageFolder: "", inputColumnName: nameof(ImageData.ImagePath))
            .Append(_mlContext.Transforms.ResizeImages(outputColumnName: "input", imageWidth: 224, imageHeight: 224, inputColumnName: "input"))
            .Append(_mlContext.Transforms.ExtractPixels(outputColumnName: "input"))
            .Append(_mlContext.Model.LoadTensorFlowModel("resnet50.pb")
                .ScoreTensorFlowModel(outputColumnNames: new[] { "output" }, inputColumnNames: new[] { "input" }, addBatchDimensionInput: true));

        _model = pipeline.Fit(data);
    }

    public float[] ExtractFeatures(string imagePath)
    {
        var imageData = new ImageData { ImagePath = imagePath };
        var predictionEngine = _mlContext.Model.CreatePredictionEngine<ImageData, ImagePrediction>(_model);
        var prediction = predictionEngine.Predict(imageData);
        return prediction.Score;
    }
}
3. 数据库设计与存储

创建一个 SQL Server 数据库,包含一个表用于存储图片的路径和特征向量。以下是一个示例表结构:

CREATE TABLE Images (
    Id INT PRIMARY KEY IDENTITY(1,1),
    ImagePath NVARCHAR(255) NOT NULL,
    FeatureVector NVARCHAR(MAX) NOT NULL
);

使用 Entity Framework Core 进行数据库操作:

using Microsoft.EntityFrameworkCore;

public class ImageDbContext : DbContext
{
    public DbSet<ImageEntity> Images { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer("YourConnectionString");
    }
}

public class ImageEntity
{
    public int Id { get; set; }
    public string ImagePath { get; set; }
    public string FeatureVector { get; set; }
}
4. 相似度计算

使用余弦相似度算法计算两个特征向量的相似度:

public static double CosineSimilarity(float[] vectorA, float[] vectorB)
{
    double dotProduct = 0;
    double normA = 0;
    double normB = 0;

    for (int i = 0; i < vectorA.Length; i++)
    {
        dotProduct += vectorA[i] * vectorB[i];
        normA += Math.Pow(vectorA[i], 2);
        normB += Math.Pow(vectorB[i], 2);
    }

    normA = Math.Sqrt(normA);
    normB = Math.Sqrt(normB);

    if (normA == 0 || normB == 0)
    {
        return 0;
    }

    return dotProduct / (normA * normB);
}
5. 图片搜索 API

创建一个 Web API 接口,用于接收上传的图片并返回相似图片列表:

using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Linq;

[ApiController]
[Route("[controller]")]
public class ImageSearchController : ControllerBase
{
    private readonly ImageDbContext _dbContext;
    private readonly FeatureExtractor _featureExtractor;

    public ImageSearchController(ImageDbContext dbContext, FeatureExtractor featureExtractor)
    {
        _dbContext = dbContext;
        _featureExtractor = featureExtractor;
    }

    [HttpPost]
    public IActionResult Search([FromForm] IFormFile image)
    {
        // 保存上传的图片
        var uploadPath = "uploads/" + image.FileName;
        using (var stream = new FileStream(uploadPath, FileMode.Create))
        {
            image.CopyTo(stream);
        }

        // 提取上传图片的特征向量
        var uploadFeatures = _featureExtractor.ExtractFeatures(uploadPath);

        // 从数据库中获取所有图片的特征向量
        var allImages = _dbContext.Images.ToList();

        // 计算相似度并排序
        var similarities = new List<(ImageEntity Image, double Similarity)>();
        foreach (var imageEntity in allImages)
        {
            var features = imageEntity.FeatureVector.Split(',').Select(float.Parse).ToArray();
            var similarity = CosineSimilarity(uploadFeatures, features);
            similarities.Add((imageEntity, similarity));
        }

        similarities = similarities.OrderByDescending(s => s.Similarity).ToList();

        // 返回相似图片列表
        var result = similarities.Select(s => s.Image.ImagePath).ToList();
        return Ok(result);
    }
}

总结

通过以上步骤,你可以实现一个基于 .NET 后端的图片搜索图片库功能。用户上传图片后,系统会提取其特征向量,计算与库中图片的相似度,并按相似度从高到低排序展示相似图片。