自分だけのクイズを作成しよう - Quipha
スポンサーリンク

【OpenCvSharp】画像の特徴点と類似度を取得

OpenCV

当サイトではアフィリエイト広告を利用しています。

スポンサーリンク

はじめに

今回は、OpenCvSharpを使用して、画像の特徴点類似度を取得してみます。

全く同じ画像かどうかの比較ではなく、似ているかどうかを判定してみます。
画像に対して特徴量を取得し、比較するやり方です。

OpenCvSharpのインストールや、サンプルアプリの作成は以下の記事を参考にしてください。

Visual Studio 2022のインストールにつきましては、以下の記事にまとめましたので参考ください。

使用するバージョン
  • Windows 11 / 10
  • Visual Studio 2022 (2019)

他にも私のブログで、OpenCVについて解説している記事がありますのでご覧ください。

画像の特徴点の検出

まずは画像を用意します。
以下のフリー素材を使用しました。

猫 ねこ ネコ 猫アップ 猫の顔
猫 大きい目が可愛いトラ猫のアップ(No: 4085695)の無料写真素材を提供する「写真AC」のフリー写真素材は、個人、商用を問わず無料でお使いいただけます。クレジット表記やリンクは一切不要です。Web、DTP、動画などの写真素材としてお...

私は以下の場所に画像を保存しました。

D:\project\img\cat1.jpg

画像の特徴点をAKAZEを使用して、検出してみます。

特徴点を検出するアルゴリズムは、SURFSIFTなどがあります。

フォームにボタンを配置し、クリックイベントに以下のように実装しました。

private void button9_Click(object sender, EventArgs e)
{
    using (var mat = new Mat(@"D:\project\img\cat1.jpg"))
    using (var descriptors = new Mat())
    using (var drowKeyPoint = new Mat())
    {
        var akaze = AKAZE.Create();

        // キーポイントを検出
        akaze.DetectAndCompute(mat, null, out KeyPoint[] keyPoints, descriptors);

        // 画像に描画
        Cv2.DrawKeypoints(mat, keyPoints, drowKeyPoint);
        Cv2.ImShow("image", drowKeyPoint);
    }
}

keyPointsについては、outパラメーター修飾子で参照渡しにし、検出結果を受け取っています。

実行してみると、以下のように画像の特徴点を取得することができました。

スポンサーリンク

画像の類似度の取得

比較1

次に、画像の類似度を取得してみます。
先程抽出した、画像の特徴点同士のマッチングを行い、類似度を取得します。

比較対象として、先程の画像と似ている、以下のフリー素材を使用しました。

見つめるトラ猫の可愛いアップ猫画像
猫 ねこ 見つめるトラ猫の可愛いアップ (No: 4085698)の無料写真素材を提供する「写真AC」のフリー写真素材は、個人、商用を問わず無料でお使いいただけます。クレジット表記やリンクは一切不要です。Web、DTP、動画などの写真素材と...

私は以下の場所に画像を保存しました。

D:\project\img\cat2.jpg

今回は特徴量のマッチングとして、BFMatcher(Brute Force)を使用しました。
その名の通り、総当たりです。

他にもFlannBasedMatcherなどがあります。

実用的に使用できるように関数を作成しました。
引数に、比較したい画像を2つ指定します。
また、比較結果の画像を表示するかどうかのフラグを設けました。

/// <summary>
/// 2つの画像の類似度をチェックする
/// </summary>
/// <param name="mat1"></param>
/// <param name="mat2"></param>
/// <param name="show">画像を表示するかのフラグ</param>
/// <returns></returns>
private float ImageMatch(Mat mat1, Mat mat2, bool show)
{

    using (var descriptors1 = new Mat())
    using (var descriptors2 = new Mat())
    {

        // 特徴点を検出
        var akaze = AKAZE.Create();

        // キーポイントを検出
        akaze.DetectAndCompute(mat1, null, out KeyPoint[] keyPoints1, descriptors1);
        akaze.DetectAndCompute(mat2, null, out KeyPoint[] keyPoints2, descriptors2);

        // それぞれの特徴量をマッチング
        var matcher = new BFMatcher(NormTypes.Hamming, false);
        var matches = matcher.Match(descriptors1, descriptors2);

        // 2つの画像のマッチング結果を表示
        if (show)
        {
            using (var drowMatch = new Mat())
            {
                Cv2.DrawMatches(mat1, keyPoints1, mat2, keyPoints2, matches, drowMatch);
                Cv2.ImShow("image match", drowMatch);
            }
        }

        // 平均距離を返却(小さい方が類似度が高い)
        var sum = matches.Sum(x => x.Distance);
        return sum / matches.Length;

    }

}

類似度として、特徴量マッチングの距離の平均を取得しました。
全く同じであれば0であり、値が小さいほど、画像は似ていることになります。

呼び出し方は以下です。

private void button8_Click(object sender, EventArgs e)
{
    using (var mat1 = new Mat(@"D:\project\img\cat1.jpg"))
    using (var mat2 = new Mat(@"D:\project\img\cat2.jpg"))
    {
        // 2つの画像を比較(平均距離をスコアとした)
        float score = ImageMatch(mat1, mat2, true);
        Console.WriteLine("score:" + score);
    }
}	

実行してみた結果は以下です。
左右に二枚の画像が配置しており、それぞれの特徴量を線で引いています。

スコアは以下になりました。(コンソールに出力されています)

score:100.8207

比較2

折角なので、もう一枚比較してみましょう。

バーニーズマウンテンドッグ
バーニーズマウンテンドッグ(No: 4207210)の無料写真素材を提供する「写真AC」のフリー写真素材は、個人、商用を問わず無料でお使いいただけます。クレジット表記やリンクは一切不要です。Web、DTP、動画などの写真素材としてお使いくだ...

比較結果は以下です。

スコアは先程よりは少し上がりました。
先程の猫同士のほうが似ていることになりますね。

score:121.8167

さいごに

今回は画像の類似度を求めてみました。
OpenCvSharpで簡単にできるので、ぜひ試してみてくださいね😊

他にも私のブログで、OpenCVについて解説している記事がありますのでご覧ください。

\オススメ/

コメント

タイトルとURLをコピーしました