在大型内部寻找小图像(PIL + OpenCV)

时间:2013-06-29 22:05:30

标签: python opencv numpy python-imaging-library

我正在尝试按照此处的说明进行操作:Finding a subimage inside a Numpy image,以便能够在屏幕截图中搜索图片。

代码如下:

import cv2
import numpy as np
import gtk.gdk
from PIL import Image

def make_screenshot():
    w = gtk.gdk.get_default_root_window()
    sz = w.get_size()
    pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, sz[0], sz[1])
    pb = pb.get_from_drawable(w, w.get_colormap(), 0, 0, 0, 0, sz[0], sz[1])
    width, height = pb.get_width(), pb.get_height()
    return Image.fromstring("RGB", (width, height), pb.get_pixels())

if __name__ == "__main__":
    img = make_screenshot()
    cv_im = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
    template = cv_im[30:40, 30:40, :]
    result = cv2.matchTemplate(cv_im, template, cv2.TM_CCORR_NORMED)
    print np.unravel_index(result.argmax(), result.shape)

根据所选择的方法(而不是cv2.TM_CCORR_NORMED),我得到了完全不同的坐标,但是没有一个是(30,30),例如。

请教我这种方法有什么问题?

1 个答案:

答案 0 :(得分:0)

简短回答:您需要使用以下行找到最佳匹配的角落:

minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(result)

变量maxLoc将保存一个元组,其中包含最佳匹配的左上角的x,y索引。

答案很长:

cv2.matchTemplate()返回单个通道图像,其中每个索引处的数字对应于输入图像与该索引处的模板匹配的程度。在调用matchTemplate之后插入以下代码行来尝试可视化结果,你会发现为什么numpy很难理解它。

cv2.imshow("Debugging Window", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

minMaxLoc()将matchTemplate返回的结果转换为您想要的信息。如果您不知道模板的匹配程度最差,或者最佳和最差匹配的结果值是多少,那么您也可以使用这些值。

这段代码对我来说是一个我从文件中读取的示例图像。如果您的代码仍然行为不当,您可能无法按照自己的方式阅读图像。上面的代码片段对于使用OpenCV进行调试很有用。将imshow中的参数结果替换为任何图像对象(numpy数组)的名称,以直观地确认您获得了所需的图像。