Search for the position of the object in the image

My goal is to find the location of certain images on other images using python. Take this example:

enter image description hereenter image description here

I want to find the location of the walnut in the image. The image of the walnut is known, so I think that there is no need for any extended pattern matching or machine learning to say that something is walnut or not.

How can I find a walnut in the image? Will a strategy in these areas work:

  • read images using PIL
  • convert them to numpy arrays
  • Use Scipy filters (which filters?)

Thanks!

+7
python image-processing python-imaging-library
source share
1 answer

I would go with a clean PIL.

  • Read the image and walnut.
  • Take any pixel of a walnut.
  • Find all image pixels with the same color.
  • Check if the surrounding pixels match the surrounding pixels of the walnut (and break as soon as you find one mismatch to minimize time).

Now, if the image uses lossy compression (for example, JFIF), the walnut image will not be exactly the same as the walnut picture. In this case, you can define some value for comparison.


EDIT: I used the following code (by converting white to alpha, the colors of the original walnut changed slightly):

#! /usr/bin/python2.7 from PIL import Image, ImageDraw im = Image.open ('zGjE6.png') isize = im.size walnut = Image.open ('walnut.png') wsize = walnut.size x0, y0 = wsize [0] // 2, wsize [1] // 2 pixel = walnut.getpixel ( (x0, y0) ) [:-1] def diff (a, b): return sum ( (a - b) ** 2 for a, b in zip (a, b) ) best = (100000, 0, 0) for x in range (isize [0] ): for y in range (isize [1] ): ipixel = im.getpixel ( (x, y) ) d = diff (ipixel, pixel) if d < best [0]: best = (d, x, y) draw = ImageDraw.Draw (im) x, y = best [1:] draw.rectangle ( (x - x0, y - y0, x + x0, y + y0), outline = 'red') im.save ('out.png') 

Basically, one random walnut pixel and search for a better match. This is the first step with not too bad output:

enter image description here

What you still want to do:

  • Increase the sample space (not only using one pixel, but maybe 10 or 20).

  • Not only check the best match, but also the top 10 matches per instance.


EDIT 2: Some improvements

 #! /usr/bin/python2.7 import random import sys from PIL import Image, ImageDraw im, pattern, samples = sys.argv [1:] samples = int (samples) im = Image.open (im) walnut = Image.open (pattern) pixels = [] while len (pixels) < samples: x = random.randint (0, walnut.size [0] - 1) y = random.randint (0, walnut.size [1] - 1) pixel = walnut.getpixel ( (x, y) ) if pixel [-1] > 200: pixels.append ( ( (x, y), pixel [:-1] ) ) def diff (a, b): return sum ( (a - b) ** 2 for a, b in zip (a, b) ) best = [] for x in range (im.size [0] ): for y in range (im.size [1] ): d = 0 for coor, pixel in pixels: try: ipixel = im.getpixel ( (x + coor [0], y + coor [1] ) ) d += diff (ipixel, pixel) except IndexError: d += 256 ** 2 * 3 best.append ( (d, x, y) ) best.sort (key = lambda x: x [0] ) best = best [:3] draw = ImageDraw.Draw (im) for best in best: x, y = best [1:] draw.rectangle ( (x, y, x + walnut.size [0], y + walnut.size [1] ), outline = 'red') im.save ('out.png') 

Doing this with scriptname.py image.png walnut.png 5 gives, for example:

enter image description here

+9
source share

All Articles