10

私はパズルを解くアプリケーションを構築しようとしています (グラフ アルゴリズムを開発しようとしています)。サンプル入力を常に手で入力したくありません。

編集: ゲームを構築しようとしているわけではありません。ゲーム「SpellSeeker」をプレイするエージェントを構築しようとしています

画面に数字が入った画像 (添付ファイルを参照) があり、ボックスの位置を知っていて、これらの数字の正確な画像があるとします。私がやりたいことは、対応するボックスにある画像 (番号) を単純に伝えることです。

数字

だから私は実装する必要があると思います

bool isImageInsideImage(Bitmap numberImage,Bitmap Portion_Of_ScreenCap)またはそのようなもの。

私が試したのは(AForgeライブラリを使用)

public static bool Contains(this Bitmap template, Bitmap bmp)
{
    const Int32 divisor = 4;
    const Int32 epsilon = 10;

    ExhaustiveTemplateMatching etm = new ExhaustiveTemplateMatching(0.9f);

    TemplateMatch[] tm = etm.ProcessImage(
        new ResizeNearestNeighbor(template.Width / divisor, template.Height / divisor).Apply(template),
        new ResizeNearestNeighbor(bmp.Width / divisor, bmp.Height / divisor).Apply(bmp)
        );

    if (tm.Length == 1)
    {
        Rectangle tempRect = tm[0].Rectangle;

        if (Math.Abs(bmp.Width / divisor - tempRect.Width) < epsilon
            &&
            Math.Abs(bmp.Height / divisor - tempRect.Height) < epsilon)
        {
            return true;
        }
    }

    return false;
}

しかし、この画像で黒い点を検索すると false が返されます。

どうすればこれを実装できますか?

4

2 に答える 2

5

解決策を見つけたので、質問に答えています:

これは私にとってはうまくいきました:

System.Drawing.Bitmap sourceImage = (Bitmap)Bitmap.FromFile(@"C:\SavedBMPs\1.jpg");
            System.Drawing.Bitmap template = (Bitmap)Bitmap.FromFile(@"C:\SavedBMPs\2.jpg");
            // create template matching algorithm's instance
            // (set similarity threshold to 92.5%)

           ExhaustiveTemplateMatching tm = new ExhaustiveTemplateMatching(0.921f);
                // find all matchings with specified above similarity

                TemplateMatch[] matchings = tm.ProcessImage(sourceImage, template);
                // highlight found matchings

           BitmapData data = sourceImage.LockBits(
                new Rectangle(0, 0, sourceImage.Width, sourceImage.Height),
                ImageLockMode.ReadWrite, sourceImage.PixelFormat);
            foreach (TemplateMatch m in matchings)
            {

                    Drawing.Rectangle(data, m.Rectangle, Color.White);

                MessageBox.Show(m.Rectangle.Location.ToString());
                // do something else with matching
            }
            sourceImage.UnlockBits(data);

唯一の問題は、そのゲームのすべての (58) ボックスを見つけることでした。しかし、値 0.921f を 0.98 に変更すると完璧になりました。つまり、指定された番号の画像 (テンプレート) のみが検出されます。

編集:実際には、異なる写真に対して異なる類似性のしきい値を入力する必要があります。試して最適化された値を見つけました。最終的には次のような関数があります

float getSimilarityThreshold(int number)
于 2012-12-02T18:35:01.683 に答える
1

より良いアプローチは、イメージ自体に依存するのではなく、必要なすべての情報を保持するカスタム クラスを構築することです。

例えば:

public class MyTile
{
    public Bitmap TileBitmap;
    public Location CurrentPosition;
    public int Value;
}

Valueこのようにして、画像を分析する代わりに、タイル クラスを「移動」して、フィールドから値を読み取ることができます。クラスが保持しているイメージを、現在保持している位置に描画するだけです。

タイルは次のような配列で保持できます。

private list<MyTile> MyTiles = new list<MyTile>();

必要に応じてクラスを拡張します (不要になった画像は破棄することを忘れないでください)。

画像内に画像があるかどうかを本当に確認したい場合は、私が別の投稿用に書いたこの拡張機能をチェックしてください (VB コードですが):
Vb.Net Check If Image Existing In Another Image

于 2012-12-01T16:28:10.390 に答える