我想知道大图像是否包含小图像。小图像可以是半透明的(类似于水印,因此它不是一张完整的照片)。我已经尝试过针对该主题的不同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)
这是我一直用于测试的照片,因为这与我尝试进行匹配时类似。
答案 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)
两个面具并排放置(将它们颠倒过来,否则它们将不可见)。
为进行比较,您可以使用任何参数并检查其是否满足您的条件。我使用均方误差,得到的误差仅为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