【问题标题】:How to find one image inside of another?如何在另一个图像中找到一个图像?
【发布时间】:2011-01-29 04:06:30
【问题描述】:

我有 2 张 bmp 图片。 ImageA 是屏幕截图(示例) ImageB 是其中的一个子集。例如,一个图标。

我想在 ImageA 中找到 ImageB 的 X、Y 坐标(如果存在的话)。

知道我会怎么做吗?

【问题讨论】:

  • 你能把两张BMP图片贴在这里吗?

标签: c# image image-processing


【解决方案1】:

这是一个快速示例,但速度很慢,大约需要 4-6 秒,但它完全符合您的要求,我知道这篇文章很旧,但如果最近有其他人访问这篇文章 你可以看看这个东西 你需要 .NET AForge 命名空间或框架谷歌它并安装它 在您的项目中包含 AForge 名称空间,仅此而已 它找到另一张图片并给出坐标。

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.1%)

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

【讨论】:

  • 谢谢,这正是我想要的。有没有办法减少6秒的时间?这对我正在做的事情来说有点太高了
  • 这对我也有用。我首先将 sourceImage 和模板都缩小到原始大小的 40%,从而减少了时间。 (选择适合您的尺寸。) bitmap = new ResizeBicubic((int)(bitmap.Width * 0.4), (int)(bitmap.Height * 0.4)).Apply(bitmap);
  • 现在在 2020 年,您只需要安装 nugetAForge.Imaging,解决命名空间 (using AForge.Imaging; / using System.Drawing;) 并且代码可以快速运行。 (-:
【解决方案2】:

如果图像 B 是图像 A 的 exact 子集(意思是像素值完全相同),这不是图像处理问题,它只是 2D 中的字符串匹配。在 99% 的情况下,从 B 的中间取一条线并将其与 A 的每一行相匹配,就能达到你想要的效果,而且速度超快……我猜 C# 有一个功能。在你得到你的匹配之后(通常是几个),只需检查整个 B 和 A 的适当部分。

我能看到的唯一问题是,在某些情况下你会得到太多的匹配。例如。如果 A 是您的桌面,B 是一个图标,那么您很不幸在 B 中选择了仅包含背景的一行。这个问题很容易解决(您必须更仔细地从 B 中选择行),但这取决于您的问题的具体情况。

【讨论】:

  • 如何进行完整的二维字符串搜索,而不是只搜索一行?
  • 我会从 B 中找到所有有效的像素颜色,以及最大的连续/不透明矩形区域,然后我可以使用它来跳过大图像并限制我测试的区域。跨度>
【解决方案3】:
  1. 那么 ImageA 中的 ImageB 是否有任何变形?
  2. 图像有多“精确”,例如逐个像素,它们会相同吗?
  3. 您有多少计算能力?

如果前两个问题的答案是,那么你有一个简单的问题。了解Q3的答案也很有帮助。

更新:

基本思路是这样的:不是将 imageB 中每个像素周围的窗口与 imageA 中的每个像素匹配并检查相关性,而是在两个图像中识别出可可跟踪的兴趣点(或特征) >。所以看起来拐角确实是可追踪的,因为它周围的区域有点相似(不详述) - 因此,让我们在两张图像中找到一些非常strong的拐角并搜索看起来最相似的拐角。

这减少了用 A 搜索 B 中的每个像素的问题,例如搜索 B 中的 500 个角和 A 中的 1000 个角(或类似的东西) - 更快。

很棒的是,OpenCV 中有几个这样的角落检测器可供您使用。如果您不喜欢使用emguCV(C# 变体),请使用FAST 检测器来查找匹配的角点,从而定位图像之间的多个特征。一旦你有了它,你就可以找到图像左上角的位置。

【讨论】:

  • 1.如果通过翘曲你的意思是它们的尺寸不同,那么没有。 2.是的,它们将逐像素相同。我想考虑一点误差范围或指定的误差范围(1%、15%、50%)等。但这不是必须的。 3. 假设最低要求是双 proc x64 2.2GHz 和 2GB RAM
  • 我知道这一切可能看起来有些过分,但如果您可以发布指向 BMP 文件的链接,我可以向您展示它的有效性/速度。
  • 很容易......我想要的东西类型是现有的 Windows 应用程序。所以只需截取 chrome dl.dropbox.com/u/2809/Chrome.bmp 的屏幕截图,然后在其中找到主页按钮 dl.dropbox.com/u/2809/HomeButton.bmp 的 X/Y。
  • 你所有的imageBs 都会那么小吗?
  • @Jacob - 我不是要施加任何压力,但刚刚结束60,452 hours几个到底是什么意思? :P
【解决方案4】:

【讨论】:

  • 前 2 个问题与我的问题不同,产生的结果也大不相同。最后一个不起作用(另一位用户报告了),即使它确实“720p 花了几分钟”。我将扫描 1920x1200 的图像,而且几分钟是不可接受的。即使是您从 ImageB 中获取 Pixel1 的算法,在 ImageA 中找到它的所有实例,然后获取 Pixel2 并删除它不是“旁边(水平/垂直)”的所有实例,并重复直到列表为空或全部扫描像素将比几分钟更快。
  • 我只是在寻找比这个想法更好的东西......必须有一个像样的算法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-11-19
  • 2018-08-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多