在更大的图像内找到图像的位置

时间:2016-07-20 06:37:21

标签: python numpy image-processing

所以我有一个图像可以说small.png和更大的图像big.png。小图像在较大的图像中出现2次,我希望找到它的位置。

我尝试使用numpy和Image但出现错误

'JpegImageFile' object has no attribute '__getitem__'。之前我有png格式,它也给出了同样的错误。

是否有任何其他模块或方法可以完成此任务。我对任何人开放。

现在抛出错误的代码是

import numpy
from PIL import Image
here = Image.open(r"/Users/vks/Desktop/heren.jpg")
big = Image.open(r"/Users/vks/Desktop/Settingsn.jpg")
print here,big
herear = numpy.asarray(here)
bigar = numpy.asarray(big)
herearx = herear.shape[0]
hereary = herear.shape[1]

bigarx = bigar.shape[0]
bigary = bigar.shape[1]

print herearx , hereary , bigarx, bigary

stopx = bigarx - herearx + 1
stopy = bigary - hereary + 1

for x in range(0, stopx):
    for y in range(0, stopy):
        x2 = x+ herearx
        y2 = y + hereary
        pic = big[y:y2, x:x2] ===> error thrown here
        test = pic = here
        if test.all():
            print x,y
else:
    print "None"

还有另一个cv2模块,但它并没有安装在我的mac上。 pip install cv2在找到包裹时失败了。

enter image description here

enter image description here

1 个答案:

答案 0 :(得分:4)

以下代码适用于我:

import numpy
from PIL import Image

here = Image.open(r"eye.png")
big  = Image.open(r"lenna.png")

herear = numpy.asarray(here)
bigar  = numpy.asarray(big)

hereary, herearx = herear.shape[:2]
bigary,  bigarx  = bigar.shape[:2]

stopx = bigarx - herearx + 1
stopy = bigary - hereary + 1

for x in range(0, stopx):
    for y in range(0, stopy):
        x2 = x + herearx
        y2 = y + hereary
        pic = bigar[y:y2, x:x2]
        test = (pic == herear)
        if test.all():
            print(x,y)

输出: 312 237

<强>图形:

enter image description here

使用的测试图像

<强> lenna.png

Lenna

<强> eye.png

Eye

注意:在创建较小的裁剪版本时使用无损图像格式非常重要(PNG是无损的,JPEG通常是有损的)。如果使用有损格式,则可能会使像素值接近但不相同。基于您的上述代码将仅找到精确的逐像素匹配。在这方面,OpenCV模板匹配功能更灵活一些。这并不是说你无法修改你的代码也可以。但就目前而言,这个答案中的代码有这个限制。

更一般的版本

这里,作为一个函数,它收集所有匹配的坐标并将它们作为(x,y)元组的列表返回:

import numpy as np
from PIL import Image

im_haystack = Image.open(r"lenna.png")
im_needle   = Image.open(r"eye.png")

def find_matches(haystack, needle):
    arr_h = np.asarray(haystack)
    arr_n = np.asarray(needle)

    y_h, x_h = arr_h.shape[:2]
    y_n, x_n = arr_n.shape[:2]

    xstop = x_h - x_n + 1
    ystop = y_h - y_n + 1

    matches = []
    for xmin in range(0, xstop):
        for ymin in range(0, ystop):
            xmax = xmin + x_n
            ymax = ymin + y_n

            arr_s = arr_h[ymin:ymax, xmin:xmax]     # Extract subimage
            arr_t = (arr_s == arr_n)                # Create test matrix
            if arr_t.all():                         # Only consider exact matches
                matches.append((xmin,ymin))

    return matches

print(find_matches(im_haystack, im_needle))

<强>更新

根据您提供的图片,您会注意到匹配的设置方式,它只会匹配这两个中的一个。左上角是针对针图像裁剪的一个,因此它完全匹配。右下角的图像需要精确匹配像素。通过这种实现,即使其中一个颜色通道中的单个位差异也会导致它被忽略。

事实证明,这里的两个变化相当多: enter image description here

经过测试的版本

  • Python 2.7.10,Numpy 1.11.1,PIL(Pillow)1.1.7
  • Python 3.5.0,Numpy 1.10.4,PIL(Pillow)1.1.7