所以在堆栈溢出成员的帮助下,我有以下代码:
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)
我写了下面的代码来检查针是否在大海捞针:
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
问题是我在第3行遇到这个错误:'PixelAccess'对象不可迭代
有人告诉我,将针和干草堆复制成numpy / scipy阵列会更容易。然后我可以使用一个函数来检查2D数组针是否在2D数组haystack中。
我需要帮助:
1)将这些数组转换为numpy数组。
2)检查2D阵列针是否在2D阵列haystack内的功能。我的功能不起作用。
这些是图像:
针:
草堆:
答案 0 :(得分:2)
要将图像转换为numpy数组,您应该能够简单地执行此操作:
import numpy as np
from PIL import Image
needle = Image.open('needle.png')
haystack = Image.open('haystack.jpg')
needle = np.asarray(needle)
haystack = np.asarray(haystack)
为了让您开始寻找针头,请注意,这将为您提供角落匹配的所有位置的列表:
haystack = np.array([[1,2,3],[3,2,1],[2,1,3]])
needle = np.array([[2,1],[1,3]])
np.where(haystack == needle[0,0])
#(array([0, 1, 2]), row-values
# array([1, 1, 0])) col-values
然后,您可以查看所有角落匹配,并查看其中的subhaystack是否匹配:
h,w = needle.shape
rows, cols = np.where(haystack == needle[0,0])
for row, col in zip(rows, cols):
if np.all(haystack[row:row+h, col:col+w] == needle):
print "found it at row = %i, col = %i"%(row,col)
break
else:
print "no needle in haystack"
下面是一个更健壮的版本,可以找到最佳匹配,如果匹配得比某个百分比好,则会考虑找到针。如果找到则返回角坐标,如果没有,则返回None
。
def find_needle(needle, haystack, tolerance=.80):
""" input: PIL.Image objects
output: coordinat of found needle, else None """
# convert to grayscale ("L"uminosity) for simplicity.
needle = np.asarray(needle.convert('L'))
haystack = np.asarray(haystack.convert('L'))
h,w = needle.shape
H,W = haystack.shape
L = haystack.max()
best = (None, None, 1)
rows, cols = np.where((haystack - needle[0,0])/L < tolerance)
for row, col in zip(rows, cols):
if row+h > H or col+w > W: continue # out of range
diff = np.mean(haystack[row:row+h, col:col+w] - needle)/L
if diff < best[-1]:
best = (diff, row, col)
return best if best[-1] < tolerance else None
答案 1 :(得分:2)
我终于设法实现了互相关搜索工作的仅限numpy ......使用cross-correlation theorem和FFT计算互相关。
from __future__ import division
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
def cross_corr(a, b):
a_rows, a_cols = a.shape[:2]
b_rows, b_cols = b.shape[:2]
rows, cols = max(a_rows, b_rows), max(a_cols, b_cols)
a_f = np.fft.fft2(a, s=(rows, cols), axes=(0, 1))
b_f = np.fft.fft2(b, s=(rows, cols), axes=(0, 1))
corr_ab = np.fft.fft2(a_f.conj()*b_f, axes=(0,1))
return np.rint(corr_ab / rows / cols)
def find_needle(haystack, needle, n=10):
# convert to float and subtract 128 for better matching
haystack = haystack.astype(np.float) - 128
needle = needle.astype(np.float) - 128
target = np.sum(np.sum(needle*needle, axis=0), axis=0)
corr_hn = cross_corr(haystack, needle)
delta = np.sum(np.abs(corr_hn - target), axis=-1)
return np.unravel_index(np.argsort(delta, axis=None)[:n],
dims=haystack.shape[:2])
haystack = np.array(Image.open('haystack.jpg'))
needle = np.array(Image.open('needle.png'))[..., :3]
plt.imshow(haystack, interpolation='nearest')
dy, dx = needle.shape[:2]
candidates = find_needle(haystack, needle, 1)
for y, x in zip(*candidates):
plt.plot([x, x+dx, x+dx, x, x], [y, y, y+dy,y+dy, y], 'g-', lw=2)
plt.show()
所以得分最高的是真正的指针:
>>> print candidates
(array([553], dtype=int64), array([821], dtype=int64))
答案 2 :(得分:1)
您可以在opencv中使用matchTemplate
来检测位置:
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))
这是输出: