はじめに
- 必要なライブラリをインポート
- ONNXモデルをロード
- VectorizeImage メソッドで画像をベクトル化
- CompareImages メソッドで2つの画像のベクトルを比較し、類似度を計算
- CosineSimilarity メソッドでコサイン類似度を計算
このコードを使用するには、以下の準備が必要です:
NuGetパッケージマネージャーを使用して、Microsoft.ML.OnnxRuntimeとSystem.Drawing.Commonパッケージをインストールします。
CLIPモデル(または同等の画像ベクトル化モデル)をONNX形式に変換し、path/to/model.onnxに配置します。
Program
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using Microsoft.ML.OnnxRuntime;
using Microsoft.ML.OnnxRuntime.Tensors;
class Program
{
static InferenceSession session;
static void Main(string[] args)
{
// ONNXモデルのロード
session = new InferenceSession("path/to/model.onnx");
string imagePath1 = "path/to/image1.jpg";
string imagePath2 = "path/to/image2.jpg";
float similarity = CompareImages(imagePath1, imagePath2);
Console.WriteLine($"画像の類似度: {similarity}");
}
static float[] VectorizeImage(string imagePath)
{
using (var image = new Bitmap(Image.FromFile(imagePath)))
{
// 画像の前処理
var resizedImage = new Bitmap(image, new Size(224, 224));
var inputTensor = new DenseTensor<float>(new[] { 1, 3, 224, 224 });
for (int y = 0; y < 224; y++)
{
for (int x = 0; x < 224; x++)
{
var pixel = resizedImage.GetPixel(x, y);
inputTensor[0, 0, y, x] = (pixel.R / 255f - 0.485f) / 0.229f;
inputTensor[0, 1, y, x] = (pixel.G / 255f - 0.456f) / 0.224f;
inputTensor[0, 2, y, x] = (pixel.B / 255f - 0.406f) / 0.225f;
}
}
// モデルの実行
var inputs = new List<NamedOnnxValue> { NamedOnnxValue.CreateFromTensor("input", inputTensor) };
using (var results = session.Run(inputs))
{
return results.First().AsTensor<float>().ToArray();
}
}
}
static float CompareImages(string imagePath1, string imagePath2)
{
var vector1 = VectorizeImage(imagePath1);
var vector2 = VectorizeImage(imagePath2);
return CosineSimilarity(vector1, vector2);
}
static float CosineSimilarity(float[] v1, float[] v2)
{
float dotProduct = 0;
float magnitude1 = 0;
float magnitude2 = 0;
for (int i = 0; i < v1.Length; i++)
{
dotProduct += v1[i] * v2[i];
magnitude1 += v1[i] * v1[i];
magnitude2 += v2[i] * v2[i];
}
magnitude1 = (float)Math.Sqrt(magnitude1);
magnitude2 = (float)Math.Sqrt(magnitude2);
if (magnitude1 > 0 && magnitude2 > 0)
{
return dotProduct / (magnitude1 * magnitude2);
}
else
{
return 0;
}
}
}