it-swarm.com.ru

Как найти одно изображение внутри другого?

У меня есть 2 изображения BMP. ImageA - это скриншот (пример) ImageB - это подмножество. Скажем, например, значок.

Я хочу найти координаты X, Y ImageB в ImageA (если он существует).

Есть идеи, как мне это сделать?

27
esac
  1. Так есть ли искажение ImageB в ImageA? 
  2. Насколько «точны» изображения, например, «пиксель за пикселем», они будут одинаковыми?
  3. Сколько вычислительных мощностей у вас есть для этого?

Если ответы на первые два вопроса - Нет и Да, то у вас есть простая проблема. Это также помогает узнать ответ на Q3.

Обновление:

Основная идея такова: вместо того, чтобы сопоставлять окно вокруг каждого пикселя в imageB с каждым пикселем в imageA и проверять корреляцию, давайте определим точки интереса (или особенности) в обоих изображениях, которые будут trackable. Таким образом, похоже, что углы действительно отслеживаются, поскольку область вокруг них похожа (не вдаваясь в подробности) - следовательно, давайте найдем действительно сильные углы на обоих изображениях и поищем углы, которые выглядят наиболее похожими. 

Это сводит проблему поиска каждого пикселя в B с A к поиску, скажем, 500 углов в B с 1000 углами в A (или что-то в этом роде) - намного быстрее.

И что удивительно, у вас есть несколько таких угловых детекторов в вашем распоряжении в OpenCV . Если вы не чувствуете, что используете emguCV (C # varriant), то используйте БЫСТРЫЙ детектор, чтобы найти совпадающие углы и, таким образом, найти несколько объектов между изображениями. Как только вы это сделаете, вы можете найти местоположение в верхнем левом углу изображения.

15
Jacob

Вот быстрый пример, но он медленный, занимает около 4-6 секунд, но он делает именно то, что вы ищете, и я знаю, что этот пост старый, но если кто-то еще посещал этот пост недавно вы можете посмотреть эту вещь вы нужно .NET AForge пространство имен или фреймворк Google и установите его включите пространство имен AForge в свой проект, и все it находит изображение с другим и выдает координаты. 

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);
15
Mandah Mr.

Если изображение B является точным подмножеством изображения A (то есть значения пикселей в точности совпадают), это не проблема обработки изображений, это просто сопоставление строк в 2D. В 99% случаев взятие линии из середины B и сопоставление ее с каждой линией A будет делать то, что вы хотите, и супер быстро & mdhas; Я думаю, в C # есть функция для этого. После того, как вы получите свои совпадения (как правило, несколько из них), просто проверьте весь B против соответствующей части A. 

Единственная проблема, с которой я могу столкнуться - это то, что в некоторых случаях вы можете получить слишком много совпадений. Например. если A - ваш рабочий стол, B - значок, и вам не повезло выбрать линию в B, состоящую только из фона. Эту проблему легко решить (вам нужно выбирать строки из B немного более тщательно), но это зависит от специфики вашей проблемы.

1
AVB
0
SwDevMan81