Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/359.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
确定较大图像中是否存在图像,如果存在,请使用Python查找它_Python_Opencv_Image Processing_Numpy_Graphics - Fatal编程技术网

确定较大图像中是否存在图像,如果存在,请使用Python查找它

确定较大图像中是否存在图像,如果存在,请使用Python查找它,python,opencv,image-processing,numpy,graphics,Python,Opencv,Image Processing,Numpy,Graphics,我需要一个我正在开发的Python程序,以便能够拍摄一个小图像,确定它是否存在于一个较大的图像中,如果存在,报告它的位置。如果没有,请报告。(在我的例子中,大图像是一个屏幕截图,小图像是一个可能在屏幕上,也可能不在HTML5画布上的图像。)在线查看,我发现了OpenCV中的模板匹配,它确实具有出色的Python绑定。我尝试了以下方法,基于我在网上找到的非常相似的代码,也使用了numpy: import cv2 import numpy as np image = cv2.imread("scre

我需要一个我正在开发的Python程序,以便能够拍摄一个小图像,确定它是否存在于一个较大的图像中,如果存在,报告它的位置。如果没有,请报告。(在我的例子中,大图像是一个屏幕截图,小图像是一个可能在屏幕上,也可能不在HTML5画布上的图像。)在线查看,我发现了OpenCV中的模板匹配,它确实具有出色的Python绑定。我尝试了以下方法,基于我在网上找到的非常相似的代码,也使用了numpy:

import cv2
import numpy as np
image = cv2.imread("screenshot.png")
template = cv2.imread("button.png")
result = cv2.matchTemplate(image,template,cv2.TM_CCOEFF_NORMED)
StartButtonLocation = np.unravel_index(result.argmax(),result.shape)

这并不是我需要它做的,因为它总是在大图中返回一个点;比赛最接近的点,无论比赛有多糟糕。我想要的是在较大的图像中找到较小图像的精确逐像素匹配,如果不存在,则引发异常,或返回
False
,或类似的内容。而且,它需要相当快。有人知道如何做到这一点吗?

既然您对OpenCV很满意,我建议您从已经完成的工作开始,并获得最佳匹配。一旦找到了最佳匹配的位置,就可以检查它是否真的是一个好匹配

检查匹配是否良好应该与提取匹配图像并将其与模板进行比较一样简单。要提取图像,可能需要使用
cv2.minMaxLoc(result)
并处理输出。提取方法似乎取决于用于比较图像的方法,并通过示例完成


提取图像后,应该能够使用
numpy.allclose
或其他方法对它们进行比较

如果您希望在大小和图像值方面都能找到完全匹配的
我将提出一个快速而完美的答案

这个想法是在一张更大的
hxw
图像中,对想要的
hxw
模板进行暴力搜索。bruteforce方法包括查看图像上所有可能的
hxw
窗口,并检查模板中的逐像素对应关系。然而,这在计算上非常昂贵,但可以加速

im = np.atleast_3d(im)
H, W, D = im.shape[:3]
h, w = tpl.shape[:2]
通过使用smart,可以快速计算从每个像素开始的
hxw
窗口内的总和。积分图像是一个求和面积表(累积求和数组),可以使用numpy快速计算,如下所示:

sat = im.cumsum(1).cumsum(0)
它具有非常好的特性,例如只需4次算术运算即可计算一个窗口内所有值的总和:

因此,通过计算模板的和并将其与积分图像上的
h x w
窗口的和匹配,很容易找到“可能窗口”列表,其中内部值的和与模板中的值的和相同(快速近似)

以上是图像中显示的所有可能的
hxw
矩形在图像上的操作的numpy矢量化(因此,非常快)

这将大大减少可能的窗口数(在我的一个测试中,窗口数将减少到2个)。最后一步是检查是否与模板完全匹配:

posible_match = np.where(np.logical_and.reduce([lookup[..., i] == tplsum[i] for i in range(D)]))
for y, x in zip(*posible_match):
    if np.all(im[y+1:y+h+1, x+1:x+w+1] == tpl):
        return (y+1, x+1)
请注意,此处的
y
x
坐标对应于图像中的A点,即模板的前一行和前一列

综合起来:

def find_image(im, tpl):
    im = np.atleast_3d(im)
    tpl = np.atleast_3d(tpl)
    H, W, D = im.shape[:3]
    h, w = tpl.shape[:2]

    # Integral image and template sum per channel
    sat = im.cumsum(1).cumsum(0)
    tplsum = np.array([tpl[:, :, i].sum() for i in range(D)])

    # Calculate lookup table for all the possible windows
    iA, iB, iC, iD = sat[:-h, :-w], sat[:-h, w:], sat[h:, :-w], sat[h:, w:] 
    lookup = iD - iB - iC + iA
    # Possible matches
    possible_match = np.where(np.logical_and.reduce([lookup[..., i] == tplsum[i] for i in range(D)]))

    # Find exact match
    for y, x in zip(*possible_match):
        if np.all(im[y+1:y+h+1, x+1:x+w+1] == tpl):
            return (y+1, x+1)

    raise Exception("Image not found")
它可用于灰度图像和彩色图像,并在
7ms
中运行,用于
303x384
彩色图像和
50x50
模板

一个实际例子:

>>> from skimage import data
>>> im = gray2rgb(data.coins())
>>> tpl = im[170:220, 75:130].copy()

>>> y, x = find_image(im, tpl)
>>> y, x
(170, 75)
并举例说明结果:

左为原始图像,右为模板。这里是确切的匹配:

>>> fig, ax = plt.subplots()
>>> imshow(im)
>>> rect = Rectangle((x, y), tpl.shape[1], tpl.shape[0], edgecolor='r', facecolor='none')
>>> ax.add_patch(rect)

最后,只是测试的
可能匹配的一个示例:


图像中两个窗口的总和相同,但函数的最后一步过滤与模板不完全匹配的窗口。

这是对@Imanol Luengo函数的改进。为了减少计算量,我们首先过滤与模板左上角顶点相同的像素。然后我们只检查由这些像素诱导的矩形

def find_image(pic1, pic2): # pic1 is the original, while pic2 is the embedding

    dim1_ori = pic1.shape[0]
    dim2_ori = pic1.shape[1]

    dim1_emb = pic2.shape[0]
    dim2_emb = pic2.shape[1]

    v1_emb = pic2[0, 0]
    v2_emb = pic2[0, dim2_emb - 1]
    v3_emb = pic2[dim1_emb - 1, dim2_emb - 1]
    v4_emb = pic2[dim1_emb - 1, 0]

    mask = (pic1 == v1_emb).all(-1)
    found = 0

    if np.sum(mask) > 0: # Check if a pixel identical to v1_emb
        result = np.argwhere(mask)
        mask = (result[:, 0] <= dim1_ori - dim1_emb) & (result[:, 1] <= dim2_ori - dim2_emb)

        if np.sum(mask) > 0: # Check if the pixel induce a rectangle
            result = result[mask] + [0, dim2_emb - 1]
            mask = [(pic1[tuple(coor)] == v2_emb).all(-1) for coor in result]

            if np.sum(mask) > 0: # Check if a pixel identical to v2_emb
                result = result[mask] + [dim1_emb-1, 0]
                mask = [(pic1[tuple(coor)] == v3_emb).all(-1) for coor in result]

                if np.sum(mask) > 0: # Check if a pixel identical to v3_emb
                    result = result[mask] - [0, dim2_emb - 1]
                    mask = [(pic1[tuple(coor)] == v4_emb).all(-1) for coor in result]

                    if np.sum(mask) > 0: # Check if a pixel identical to v4_emb
                        result = result[mask]
                        result[:, 0] = result[:, 0] - (dim1_emb - 1)
                        result = np.c_[result, result[:, 0] + dim1_emb, result[:, 1] + dim2_emb]

                        for coor in result: # Check if the induced rectangle is indentical to the embedding
                            induced_rectangle = pic1[coor[0]:coor[2], coor[1]:coor[3]]
                            if np.array_equal(induced_rectangle, pic2):
                                found = 1
                                break
    if found == 0:
        return('No image found')
    else:
        return('Image found')
def find_image(pic1,pic2):#pic1是原始图像,而pic2是嵌入图像
dim1_ori=pic1.形状[0]
dim2_ori=pic1.形状[1]
dim1_emb=pic2.形状[0]
dim2_emb=pic2.形状[1]
v1_emb=pic2[0,0]
v2_emb=pic2[0,dim2_emb-1]
v3_emb=pic2[dim1_emb-1,dim2_emb-1]
v4_emb=pic2[dim1_emb-1,0]
掩码=(pic1==v1_emb).all(-1)
找到=0
如果np.sum(mask)>0:#检查像素是否与v1_emb相同
结果=np.argwhere(掩码)
掩码=(结果[:,0]0:#检查像素是否与v2#emb相同
结果=结果[掩码]+[dim1\U emb-1,0]
掩码=[(pic1[元组(coor)]==v3\u emb.all(-1)表示结果中的coor]
如果np.sum(mask)>0:#检查像素是否与v3_emb相同
结果=结果[掩码][0,dim2\U emb-1]
掩码=[(pic1[元组(coor)]==v4\u emb.all(-1)表示结果中的coor]
如果np.sum(掩码)>0:#检查像素是否与v4_emb相同
结果=结果[掩码]
结果[:,0]=结果[:,0](dim1_emb-1)
result=np.c_[result,result[:,0]+dim1_emb,result[:,1]+dim2_emb]
对于coor-in-result:#检查诱导矩形是否与嵌入一致
诱导的_矩形=pic1[coor[0]:coor[2],coor[1]:coor[3]]
如果np.数组_相等(诱导_矩形,pic2):
发现=1
打破
如果找到==0:
返回('未找到图像')
其他:
返回('找到图像')

我尝试使用最后一个脚本来查找保存在director中的图像
def find_image(pic1, pic2): # pic1 is the original, while pic2 is the embedding

    dim1_ori = pic1.shape[0]
    dim2_ori = pic1.shape[1]

    dim1_emb = pic2.shape[0]
    dim2_emb = pic2.shape[1]

    v1_emb = pic2[0, 0]
    v2_emb = pic2[0, dim2_emb - 1]
    v3_emb = pic2[dim1_emb - 1, dim2_emb - 1]
    v4_emb = pic2[dim1_emb - 1, 0]

    mask = (pic1 == v1_emb).all(-1)
    found = 0

    if np.sum(mask) > 0: # Check if a pixel identical to v1_emb
        result = np.argwhere(mask)
        mask = (result[:, 0] <= dim1_ori - dim1_emb) & (result[:, 1] <= dim2_ori - dim2_emb)

        if np.sum(mask) > 0: # Check if the pixel induce a rectangle
            result = result[mask] + [0, dim2_emb - 1]
            mask = [(pic1[tuple(coor)] == v2_emb).all(-1) for coor in result]

            if np.sum(mask) > 0: # Check if a pixel identical to v2_emb
                result = result[mask] + [dim1_emb-1, 0]
                mask = [(pic1[tuple(coor)] == v3_emb).all(-1) for coor in result]

                if np.sum(mask) > 0: # Check if a pixel identical to v3_emb
                    result = result[mask] - [0, dim2_emb - 1]
                    mask = [(pic1[tuple(coor)] == v4_emb).all(-1) for coor in result]

                    if np.sum(mask) > 0: # Check if a pixel identical to v4_emb
                        result = result[mask]
                        result[:, 0] = result[:, 0] - (dim1_emb - 1)
                        result = np.c_[result, result[:, 0] + dim1_emb, result[:, 1] + dim2_emb]

                        for coor in result: # Check if the induced rectangle is indentical to the embedding
                            induced_rectangle = pic1[coor[0]:coor[2], coor[1]:coor[3]]
                            if np.array_equal(induced_rectangle, pic2):
                                found = 1
                                break
    if found == 0:
        return('No image found')
    else:
        return('Image found')
import cv2
import numpy as np
import os
import glob

pic2 = "/home/tse/Images/pictures/20/redu.png"
path = "/home/tse/Images/pictures/20/*.png"
for pic1 in glob.glob(path):
    def find_image(pic1, pic2):
        dim1_ori = pic1.shape[0]
        dim2_ori = pic1.shape[1]
        dim1_emb = pic2.shape[0]
        dim2_emb = pic2.shape[1]

        v1_emb = pic2[0, 0]
        v2_emb = pic2[0, dim2_emb - 1]
        v3_emb = pic2[dim1_emb - 1, dim2_emb - 1]
        v4_emb = pic2[dim1_emb - 1, 0]

        mask = (pic1 == v1_emb).all(-1)
        found = 0

        if np.sum(mask) > 0: # Check if a pixel identical to v1_emb
            result = np.argwhere(mask)
            mask = (result[:, 0] <= dim1_ori - dim1_emb) & (result[:, 1] <= dim2_ori - dim2_emb)

            if np.sum(mask) > 0: # Check if the pixel induce a rectangl
                result = result[mask] + [0, dim2_emb - 1]
                mask = [(pic1[tuple(coor)] == v2_emb).all(-1) for coor in result]

                if np.sum(mask) > 0: # Check if a pixel identical to v2_emb
                    result = result[mask] + [dim1_emb-1, 0]
                    mask = [(pic1[tuple(coor)] == v3_emb).all(-1) for coor in result]

                    if np.sum(mask) > 0: # Check if a pixel identical to v3_emb
                        result = result[mask] - [0, dim2_emb - 1]
                        mask = [(pic1[tuple(coor)] == v4_emb).all(-1) for coor in result]

                        if np.sum(mask) > 0: # Check if a pixel identical to v4_emb
                            result = result[mask]
                            result[:, 0] = result[:, 0] - (dim1_emb - 1)
                            result = np.c_[result, result[:, 0] + dim1_emb, result[:, 1] + dim2_emb]

                            for coor in result: # Check if the induced rectangle is indentical to the embedding
                                induced_rectangle = pic1[coor[0]:coor[2], coor[1]:coor[3]]
                                if np.array_equal(induced_rectangle, pic2):
                                    found = 1
                                    break
        if found == 0:
            return('No image found')
            print("Not found")
        else:
            return('Image found')
            print("Found")