如何在一张图像中找到另一张图像?

73 投票
4 回答
133608 浏览
提问于 2025-04-17 04:46

我现在正在做一个项目,基本上是一个搜索引擎和网络漫画画廊的结合,重点是引用来源和给作者打分。

我想找个办法来搜索图片,看看里面有没有角色。

举个例子:

cyanide and happiness

假设我把红色角色和绿色角色分别保存为红人和绿人,我该怎么判断一张图片里有没有这两个角色中的一个。

这个功能不需要做到百分之百的识别,只是我想增加的一个附加功能,但我不知道从哪里开始。我在网上查了很多关于图像识别的资料,但没找到什么有用的信息。

顺便说一下,我更希望用Python来实现这个功能。

4 个回答

2

重要提示:matchTemplate 这个功能甚至可以识别被缩放或旋转过的模板。下面是相关的代码和输出结果。

import matplotlib.pyplot as plt
import numpy as np
import cv2

image = cv2.imread('/content/picture.png')
template = cv2.imread('/content/penguin.png')
heat_map = cv2.matchTemplate(image, template, cv2.TM_CCOEFF_NORMED)

h, w, _ = template.shape
y, x = np.unravel_index(np.argmax(heat_map), heat_map.shape)
cv2.rectangle(image, (x,y), (x+w, y+h), (0,0,255), 5)

plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))

图片: 这是一张图片 模板: 这是一只企鹅的模板 结果: 这是检测到的结果

详细解释可以在这里找到(我的博客): simple-ai.net/find-and-replace-in-image

92

Moshe的回答 中,只讲了如何在图片中找到只出现一次的模板。接下来,我会告诉你怎么一次找到多个模板:

import cv2
import numpy as np

img_rgb = cv2.imread('mario.png')
template = cv2.imread('mario_coin.png')
w, h = template.shape[:-1]

res = cv2.matchTemplate(img_rgb, template, cv2.TM_CCOEFF_NORMED)
threshold = .8
loc = np.where(res >= threshold)
for pt in zip(*loc[::-1]):  # Switch columns and rows
    cv2.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0, 0, 255), 2)

cv2.imwrite('result.png', img_rgb)

(注意:我修改并修正了一些原代码中的‘错误’

结果:

检测马里奥金币(前后对比)

来源: https://opencv24-python-tutorials.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_template_matching/py_template_matching.html#template-matching-with-multiple-objects

82

对于将来可能看到这个的人。

这可以通过模板匹配来实现。简单来说,我的理解是,模板匹配就是在一张图片中寻找另一张图片的完全相同的部分。

下面是一个在Python中实现这个功能的例子:

import cv2

method = cv2.TM_SQDIFF_NORMED

# Read the images from the file
small_image = cv2.imread('small_image.png')
large_image = cv2.imread('large_image.jpeg')

result = cv2.matchTemplate(small_image, large_image, method)

# We want the minimum squared difference
mn,_,mnLoc,_ = cv2.minMaxLoc(result)

# Draw the rectangle:
# Extract the coordinates of our best match
MPx,MPy = mnLoc

# Step 2: Get the size of the template. This is the same size as the match.
trows,tcols = small_image.shape[:2]

# Step 3: Draw the rectangle on large_image
cv2.rectangle(large_image, (MPx,MPy),(MPx+tcols,MPy+trows),(0,0,255),2)

# Display the original image with the rectangle around the match.
cv2.imshow('output',large_image)

# The image is only displayed if we call this
cv2.waitKey(0)

撰写回答