使用简单的True / False确定特定图像是否包含在另一个图像中

时间:2019-01-29 23:53:10

标签: python opencv

我想知道大图像是否包含小图像。小图像可以是半透明的(类似于水印,因此它不是一张完整的照片)。我已经尝试过针对该主题的不同SO答案,但它们都与EXACT照片匹配,但是我要寻找的是照片是否以80%的准确性存在,因为照片将是原始照片的有损渲染版本。

这是如何生成我正在搜索的图像的过程: 使用任何照片,在Photoshop中在其上放置一个半透明的“水印”并保存。然后我要检查所创建照片中的“水印”是否存在一定百分比的准确性(80%足够好)。

我尝试使用他们的docs page上提供的原始模板匹配示例,但根本找不到任何匹配。

这是我正在使用的代码:

import cv2
import numpy as np

img_rgb = cv2.imread('photo2.jpeg')
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
template = cv2.imread('small-image.png', 0)
w, h = template.shape[::-1]
res = cv2.matchTemplate(img_gray,template,cv2.TM_CCOEFF_NORMED)
threshold = 0.7
loc = np.where( res >= threshold)
for pt in zip(*loc[::-1]):
    cv2.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0,0,255), 2)
cv2.imshow('output', img_rgb)
cv2.waitKey(0)

这是我一直用于测试的照片,因为这与我尝试进行匹配时类似。

small-image.png photo2.jpeg

1 个答案:

答案 0 :(得分:0)

我假设整个水印将具有相同的RGB值,并且文本将具有一些不同的RGB值,否则该技术将无法正常工作。基于此,我们可以使用cv2.inRange在大图像中找到那些像素值,从而获得小图像的像素的RGB值并将其视为遮罩。同样,也使用这些像素值为小图像创建了一个蒙版。

small = cv2.imread('small_find.png')
large = cv2.imread('large_find.jpg')
pixel = np.reshape(small[3,3], (1,3))
lower =[pixel[0,0]-10,pixel[0,1]-10,pixel[0,2]-10]
lower = np.array(lower, dtype = 'uint8')
upper =[pixel[0,0]+10,pixel[0,1]+10,pixel[0,2]+10]
upper = np.array(upper, dtype = 'uint8')
mask = cv2.inRange(large,lower, upper)
mask2 = cv2.inRange(small, lower, upper)

我必须取一个20的缓冲值,因为在大图像中这些值不明显匹配,否则上限或下限只有1足够。然后我们在mask中找到轮廓,并找到其边界矩形的值,该矩形被切出并重塑为mask2的大小。

im, contours, hierarchy = cv2.findContours(mask,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
#cv2.drawContours(large, contours, -1, (0,0,255), 1)
cnt = max(contours, key = cv2.contourArea)
x,y,w,h = cv2.boundingRect(cnt)
wanted_part = mask[y:y+h, x:x+w]
wanted_part = cv2.resize(wanted_part, (mask2.shape[1], mask2.shape[0]), interpolation = cv2.INTER_LINEAR)

Output

两个面具并排放置(将它们颠倒过来,否则它们将不可见)。

为进行比较,您可以使用任何参数并检查其是否满足您的条件。我使用均方误差,得到的误差仅为6.20,这是非常小的。

def MSE(img1, img2):
    squared_diff = img1 -img2
    summed = np.sum(squared_diff)
    num_pix = img1.shape[0] * img1.shape[1] #img1 and 2 should have same shape
    err = summed / num_pix
    return err