Search code examples
pythonpython-2.7numpyscipydetection

How to detect if a 2D array is inside another 2D array?


So with the help of a stack-overflow member, I have the following code:

data = "needle's (which is a png image) base64 code goes here"
decoded = data.decode('base64')
f = cStringIO.StringIO(decoded)
image = Image.open(f)
needle = image.load()

while True:
    screenshot = ImageGrab.grab()
    haystack = screenshot.load()
    if detectImage(haystack, needle):
        break
    else:
        time.sleep(5)

I've written the following code to check if the needle is in the haystack:

def detectImage(haystack, needle):
    counter = 0
    for hayrow in haystack:
        for haypix in hayrow:
            for needlerow in needle:
                for needlepix in needlerow:
                    if haypix == needlepix:
                        counter += 1

    if counter == 980: #the needle has 980 pixels
        return True
    else:
        return False

The issue is that I get this error for line 3: 'PixelAccess' object is not iterable

It was suggested to me that it would be easier to copy both needle and haystack into a numpy/scipy array. And then I can just use a function that checks to see if the 2D array needle is inside the 2D array haystack.

I need help with:

1) converting those arrays to numpy arrays.

2) a function that checks to see if the 2D array needle is inside the 2D array haystack. My function doesn't work.

These are the images:
Needle:
needle
Haystack:
haystack haystack


Solution

  • You can use matchTemplate in opencv to detect the position:

    import cv2
    import numpy as np
    import pylab as pl
    
    needle = cv2.imread("needle.png")
    haystack = cv2.imread("haystack.jpg")
    
    diff = cv2.matchTemplate(haystack, needle, cv2.TM_CCORR_NORMED)
    x, y = np.unravel_index(np.argmax(diff), diff.shape)
    
    pl.figure(figsize=(12, 8))
    im = pl.imshow(haystack[:,:, ::-1])
    ax = pl.gca()
    ax.add_artist(pl.Rectangle((y, x), needle.shape[1], needle.shape[0],  transform=ax.transData, alpha=0.6))
    

    here is the output:

    enter image description here