33

I have 2 bmp images. ImageA is a screenshot (example) ImageB is a subset of that. Say for example, an icon.

I want to find the X,Y coordinates of ImageB within ImageA (if it exists).

Any idea how I would do that?

esac
  • 24,099
  • 38
  • 122
  • 179

4 Answers4

26

Here's a quick sample but it is slow take around 4-6 seconds, but it does exactly what you looking for and i know this post is old but if anyone else visiting this post recently you can look this thing you need .NET AForge namespace or framework google it and install it include AForge name space in your project and that's it it finds the pictiure with another and gives out the coordinates.

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);
Francois
  • 10,730
  • 7
  • 47
  • 80
Mandah Mr.
  • 355
  • 4
  • 10
  • Thanks this is exactly what i was looking for. Is there a way to reduce the time 6sec? it is bit too high for what i am doing – kumar Jun 28 '12 at 07:30
  • This worked for me too. I reduced time by first shrinking both the sourceImage and template to 40% of original size. (Pick a size that works for you.) bitmap = new ResizeBicubic((int)(bitmap.Width * 0.4), (int)(bitmap.Height * 0.4)).Apply(bitmap); – Jared Thirsk May 27 '13 at 06:42
  • 2
    Now in year 2020 you just need to install the **nuget** package `AForge.Imaging`, solve namespaces (`using AForge.Imaging;` / `using System.Drawing;`) and the code works quickly. (-: – Beauty Nov 18 '20 at 21:45
16
  1. So is there any warping of ImageB in ImageA?
  2. How "exact" are the images, as in, pixel-for-pixel they will be the same?
  3. How much computational power do you have for this?

If the answers to the first two questions are No and Yes, then you have a simple problem. It also helps to know the answer to Q3.

Update:

The basic idea's this: instead of matching a window around every pixel in imageB with every pixel in imageA and checking the correlation, let's identify points of interest (or features) in both images which will be trackable. So it looks like corners are really trackable since the area around it is kinda similar (not going into details) - hence, let's find some really strong corners in both images and search for corners which look most similar.

This reduces the problem of searching every pixel in B with A to searching for, say, 500 corners in B with a 1000 corners in A (or something like that) - much faster.

And the awesome thing is you have several such corner detectors at your disposal in OpenCV. If you don't feel using emguCV (C# varriant), then use the FAST detector to find matching corners and thus locate multiple features between your images. Once you have that, you can find the location of the top-left corner of the image.

Jacob
  • 34,255
  • 14
  • 110
  • 165
  • 1. if by warping you mean they are of different sizes, then no. 2. yes, they will be pixel by pixel the same. i would like to account for a tiny bit of a margin of error or a specified margin of error (1%, 15%, 50%) etc.. but it is not a must. 3. assume minimum requirement is dual proc x64 2.2GHz with 2GB RAM – esac Mar 18 '10 at 20:22
  • I know all this might seem excessive but if you could post links to the BMP files, I can show you how effective/fast it is. – Jacob Mar 18 '10 at 20:47
  • Easy enough .. the type of stuff I want this for is existing windows applications. So just take a screenshot of chrome http://dl.dropbox.com/u/2809/Chrome.bmp and the idea is to find the X/Y of the home button http://dl.dropbox.com/u/2809/HomeButton.bmp within that. – esac Mar 18 '10 at 21:25
  • Are all your `imageB`s going to be that small? – Jacob Mar 18 '10 at 21:49
  • No, they can vary in size, probably from 16x16 to 800x600 – esac Mar 19 '10 at 01:35
  • 8
    @Jacob - I don't mean to put any pressure on, but it's been just over [60,452 hours](https://www.timeanddate.com/date/durationresult.html?m1=3&d1=18&y1=2010&m2=2&d2=8&y2=2017&h1=21&i1=50&s1=00&h2=17&i2=50&s2=41). What exactly did you mean by *a few*? :P – bPratik Feb 08 '17 at 17:52
  • um, bud. 69,284 hours. –  Feb 11 '18 at 13:03
  • https://www.timeanddate.com/date/durationresult.html?m1=3&d1=18&y1=2010&m2=2&d2=11&y2=2018&h1=21&i1=50&s1=0&h2=17&i2=50&s2=41 –  Feb 11 '18 at 13:04
1

If image B is an exact subset of image A (meaning, the pixel values are exactly the same), this is not an image processing problem, it's just string matching in 2D. In 99% of the cases, taking a line form the middle of B and matching it against each line of A will do what you want, and super fast &mdhas; I guess C# has a function for that. After you get your matches (normally, a few of them), just check the whole of B against the appropriate part of A.

The only problem I can see with this is that in some cases you can get too many matches. E.g. if A is your desktop, B is an icon, and you are unlucky enough to pick a line in B consisting of background only. This problem is easy to solve (you have to choose lines from B a bit more carefully), but this depends on the specifics of your problem.

AVB
  • 3,994
  • 22
  • 21
  • how would you do the full 2d string search, instead of just one line? – mikew Feb 16 '13 at 07:42
  • I'd find all valid pixel colours from B, and the largest continuous / non-transparent rectangular area, then I could use that to skip around the large image & limit the areas I tested. – penguat May 09 '13 at 15:43
0

Finding sub images in an image
Find an image in an Image
Check if an image exists within another image

Community
  • 1
  • 1
SwDevMan81
  • 48,814
  • 22
  • 151
  • 184
  • The first 2 are not the same question as mine and produce very different results. The last one does not work (another user reported so), and even if it did '720p took a couple of minutes'. I would be scanning 1920x1200 images and multiple minutes would not be acceptable. Even an algorithm where you took Pixel1 from ImageB, found all instances of it in ImageA, then took Pixel2 and removed all instances where it isn't 'next to (horiz/vert respective)', and repeated until the list is empty or all pixels have been scanned would be faster than a couple of minutes. – esac Mar 18 '10 at 19:23
  • I am just looking for something better than that idea .. there has to be a decent algorithm for something like this. – esac Mar 18 '10 at 19:23