Поиск изображения внутри другого изображения

Я пытаюсь создать приложение, которое решает головоломку (пытается разработать алгоритм графа), и я не хочу все время вводить выборочный ввод вручную.

Изменить: Я не пытаюсь создать игру. Я пытаюсь создать агента, который играет в игру "SpellSeeker"

Скажем, у меня есть изображение (см. вложение) на экране с номерами в нем, и я знаю расположение ящиков, и у меня есть точные изображения для этих номеров. Что я хочу сделать, это просто сказать, какое изображение (номер) находится в соответствующем поле.

Numbers

Так что я думаю, мне нужно реализовать

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;
}

Но он возвращает ложь при поиске черной точки на этом изображении.

Как я могу это реализовать?

Ответ 1

Я отвечаю на свой вопрос, так как нашел решение:

это > разработано для меня:

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 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)

Ответ 2

Лучший подход заключается в создании пользовательского класса, который содержит всю необходимую информацию, а не полагается на само изображение.

Например:

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

Таким образом вы можете "перемещать" класс плитки и читать значение из поля Value вместо анализа изображения. Вы просто рисуете любое изображение, удерживаемое классом, в текущем положении.

Плитки могут храниться в массиве вроде:

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

Расширьте класс по мере необходимости (и не забудьте удалить эти изображения, когда они больше не нужны).

если вы действительно хотите увидеть, есть ли изображение внутри изображения, вы можете проверить это расширение, которое я написал для другого сообщения (хотя в коде VB):
Vb.Net Проверка наличия изображения на другом изображении