【问题标题】:Finding an Image Inside Another Image在另一个图像中查找图像
【发布时间】:2012-11-19 14:27:53
【问题描述】:

我正在尝试构建一个解决难题的应用程序(尝试开发图形算法),我不想一直手动输入示例输入。

编辑:我不是要开发游戏。我正在尝试构建一个玩“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。

我该如何实现?

【问题讨论】:

  • 一些数独或井字游戏?
  • 您在similar ground 上看到过其他问题吗?
  • 这是一款名为“spellseeker”的游戏。但我只想构建算法来解决这样的问题并不重要。是的,实际上我在其他问题中找到了这个解决方案,但他们没有帮助我。原谅我的懒惰,但我真的认为应该有一个更简单的方法:)
  • +1 有趣的问题。 :-) 假设您锁定了原始拼图。所以你知道哪个块在哪里 - 就像它的整个网格点一样。当用户点击某些东西时,您不必查找图像,而是相应的点。您可以基于该点移动(复制/粘贴)子图像块。只是一个想法。
  • 嗨 bonCodigo,我不知道我是否正确理解了您的评论,但我只想从图像中获取数字,而不是其他方式。这样我就可以初始化我的图形节点了。

标签: c# image search aforge


【解决方案1】:

自从我找到解决方案后,我正在回答我的问题:

this 为我解决了:

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)

【讨论】:

    【解决方案2】:

    更好的方法是构建一个自定义类,它包含您需要的所有信息,而不是依赖图像本身。

    例如:

    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

    【讨论】:

    • 感谢您的回答。我已经有一个类似的课程。我有一个带有值的 Node 类(在文本框中),以及一个具有 Node 数组的 Tile 类。但是初始化所有节点的问题仍然存在。我可以将它们输入到文本框中,但这仍然意味着我必须手动输入约 60 个数字,运行时间为 2 秒。所以我正在寻找一种使用打印屏幕图像初始化它们的方法。
    猜你喜欢
    • 1970-01-01
    • 2013-12-15
    • 2020-11-22
    • 1970-01-01
    • 2012-01-15
    • 2023-03-12
    • 1970-01-01
    • 1970-01-01
    • 2011-01-29
    相关资源
    最近更新 更多