1

Emgu CV のサンプル セットには、SURFDetector を使用してフィーチャからフィーチャを検出し、Features2DTracker の MatchFeature 呼び出し (KNN を使用しているようです) を使用して「モデル」画像を「観測済み」画像に一致させる方法の例があります。この部分は理にかなっています。

さて、画像のライブラリを構築したい場合、それぞれが画像の SURF 機能を使用して、特定の画像に最適な一致を見つけます。ライブラリ内の各画像に対してブルート フォース マッチを行う代わりに、ツリーを作成できますか? Emgu はある種のツリーを構築しているように見えますが、2 つの画像間のみで混乱しています。

     //Create a SURF Tracker using k-d Tree
     SURFTracker tracker = new SURFTracker(modelFeatures);

この件に関するサイトのほぼすべてのスレッドを読みましたが、開始方法がわかりません。また、ヒストグラム マッチングの使用についても検討しました。つまり、各 RGB チャネルをビンに分割し、正規化されたカウントを比較します。ライブラリ内の各画像へのユークリッド距離を計算する代わりに、RGB カウントに基づいて検索空間を分割したい場合でも、R、G、B のいずれかに分岐することを意味し、構築方法がわかりませんその決定木。

私は数日前にこのトピックについて読み始めたばかりなので、私の素朴さをお詫びします.

4

3 に答える 3

1

このコードは、各画像のマトリックスを作成し、それらをすべて一緒に追加してから、FLANN インデックスを作成し、それに対して KNN 検索を実行してから、一致を返します。すべてのコードは次のとおりです。

/// <summary>
/// Main method.
/// </summary>
public IList<IndecesMapping> Match()
{
    string[] dbImages = {"1.jpg", "2.jpg", "3.jpg"};
    string queryImage = "query.jpg";

    IList<IndecesMapping> imap;

    // compute descriptors for each image
    var dbDescsList = ComputeMultipleDescriptors(dbImages, out imap);

    // concatenate all DB images descriptors into single Matrix
    Matrix<float> dbDescs = ConcatDescriptors(dbDescsList);

    // compute descriptors for the query image
    Matrix<float> queryDescriptors = ComputeSingleDescriptors(queryImage);

    FindMatches(dbDescs, queryDescriptors, ref imap);

    return imap;
}

/// <summary>
/// Computes image descriptors.
/// </summary>
/// <param name="fileName">Image filename.</param>
/// <returns>The descriptors for the given image.</returns>
public Matrix<float> ComputeSingleDescriptors(string fileName)
{
    Matrix<float> descs;

    using (Image<Gray, Byte> img = new Image<Gray, byte>(fileName))
    {
        VectorOfKeyPoint keyPoints = detector.DetectKeyPointsRaw(img, null);
        descs = detector.ComputeDescriptorsRaw(img, null, keyPoints);
    }

    return descs;
}

/// <summary>
/// Convenience method for computing descriptors for multiple images.
/// On return imap is filled with structures specifying which descriptor ranges in the concatenated matrix belong to what image. 
/// </summary>
/// <param name="fileNames">Filenames of images to process.</param>
/// <param name="imap">List of IndecesMapping to hold descriptor ranges for each image.</param>
/// <returns>List of descriptors for the given images.</returns>
public IList<Matrix<float>> ComputeMultipleDescriptors(string[] fileNames, out IList<IndecesMapping> imap)
{
    imap = new List<IndecesMapping>();

    IList<Matrix<float>> descs = new List<Matrix<float>>();

    int r = 0;

    for (int i = 0; i < fileNames.Length; i++)
    {
        var desc = ComputeSingleDescriptors(fileNames[i]);
        descs.Add(desc);

        imap.Add(new IndecesMapping()
        {
            fileName = fileNames[i],
            IndexStart = r,
            IndexEnd = r + desc.Rows - 1
        });

        r += desc.Rows;
    }

    return descs;
}

/// <summary>
/// Computes 'similarity' value (IndecesMapping.Similarity) for each image in the collection against our query image.
/// </summary>
/// <param name="dbDescriptors">Query image descriptor.</param>
/// <param name="queryDescriptors">Consolidated db images descriptors.</param>
/// <param name="images">List of IndecesMapping to hold the 'similarity' value for each image in the collection.</param>
public void FindMatches(Matrix<float> dbDescriptors, Matrix<float> queryDescriptors, ref IList<IndecesMapping> imap)
{
    var indices = new Matrix<int>(queryDescriptors.Rows, 2); // matrix that will contain indices of the 2-nearest neighbors found
    var dists = new Matrix<float>(queryDescriptors.Rows, 2); // matrix that will contain distances to the 2-nearest neighbors found

    // create FLANN index with 4 kd-trees and perform KNN search over it look for 2 nearest neighbours
    var flannIndex = new Index(dbDescriptors, 4);
    flannIndex.KnnSearch(queryDescriptors, indices, dists, 2, 24);

    for (int i = 0; i < indices.Rows; i++)
    {
        // filter out all inadequate pairs based on distance between pairs
        if (dists.Data[i, 0] < (0.6 * dists.Data[i, 1]))
        {
            // find image from the db to which current descriptor range belongs and increment similarity value.
            // in the actual implementation this should be done differently as it's not very efficient for large image collections.
            foreach (var img in imap)
            {
                if (img.IndexStart <= i && img.IndexEnd >= i)
                {
                    img.Similarity++;
                    break;
                }
            }
        }
    }
}

/// <summary>
/// Concatenates descriptors from different sources (images) into single matrix.
/// </summary>
/// <param name="descriptors">Descriptors to concatenate.</param>
/// <returns>Concatenated matrix.</returns>
public Matrix<float> ConcatDescriptors(IList<Matrix<float>> descriptors)
{
    int cols = descriptors[0].Cols;
    int rows = descriptors.Sum(a => a.Rows);

    float[,] concatedDescs = new float[rows, cols];

    int offset = 0;

    foreach (var descriptor in descriptors)
    {
        // append new descriptors
        Buffer.BlockCopy(descriptor.ManagedArray, 0, concatedDescs, offset, sizeof(float) * descriptor.ManagedArray.Length);
        offset += sizeof(float) * descriptor.ManagedArray.Length;
    }

    return new Matrix<float>(concatedDescs);
}

public class IndecesMapping
{
  public int IndexStart { get; set; }
  public int IndexEnd { get; set; }
  public int Similarity { get; set; }
  public string fileName { get; set; }
}

private const double surfHessianThresh = 300;
private const bool surfExtendedFlag = true;
private SURFDetector detector = new SURFDetector(surfHessianThresh, surfExtendedFlag);
于 2015-04-28T18:27:58.287 に答える
1

SURFTracker は、OpenCV に付属している FLANN (Fast Library forapproximate Nearest Neighbors) ライブラリを使用しているようです (Emgu バインディングもあります)。

  • テンプレート画像から抽出された記述子からツリーを構築します (サンプルのポイントをテンプレートのポイントに一致させる方が高速です)。したがって、ツリーは 1 つのイメージ (テンプレート) のみに対して構築されます。
  • サンプルが与えられると、記述子を抽出し、一致 (テンプレートと画像記述子の間のペアリング) を計算し、一致点の空間的一貫性も考慮します (右側から右側へ、左側から左側へ)。

単純にすべての画像に対して上記の手順を実行するよりも高速にしたい場合、すべての画像のすべての記述子から1 つのツリーを構築し、それを FLANN インデックスに入れ、どの記述子がどの画像から来たかを追跡する必要があります。 (おそらく別の配列にあります)。

画像を指定すると、そこからすべての記述子を抽出し、それらを 1 つずつ FLANN ツリーに一致させることができます (これは、テンプレート記述子コレクションごとに異なるツリーで行うよりも高速です)。したがって、サンプル内の記述子 X ごとに、画像 Z から得られる最も類似した記述子 Y が得られます。これらは類似画像の投票として使用できます ( http://en.wikipedia.org/wiki/Bag_of_words_modelを参照)。

ただし、この方法ではポイントの空間的一貫性は考慮されません...しかし、投票した上位 k 個の画像についても確認できます (k << N、その中のすべての画像の数システム)。

于 2011-03-05T21:28:49.257 に答える
1

EMGU CV の TrafficSignRecognition を見ることができます。これは SURFFeature の例と同じですが、実際に適用されます。与えられた画像が与えられた画像と一致するかどうか、およびそれらがいくつあるかを検出できます。私はそれを試してみました。あなたはそれを見ることができます。

于 2011-02-12T02:50:19.473 に答える