使用opencv查找包含另一张图像的最相似图像
如果标题不清楚,假设我有一个图像列表(10k+),并且我有一个我正在搜索的目标图像。
这是目标图像的示例:
这是我想要搜索以找到“相似”内容(ex1、ex2 和 ex3)的图像示例:
这是我做的匹配(我使用 KAZE)
from matplotlib import pyplot as plt
import numpy as np
import cv2
from typing import List
import os
import imutils
def calculate_matches(des1: List[cv2.KeyPoint], des2: List[cv2.KeyPoint]):
"""
does a matching algorithm to match if keypoints 1 and 2 are similar
@param des1: a numpy array of floats that are the descriptors of the keypoints
@param des2: a numpy array of floats that are the descriptors of the keypoints
@return:
"""
# bf matcher with default params
bf = cv2.BFMatcher(cv2.NORM_L2)
matches = bf.knnMatch(des1, des2, k=2)
topResults = []
for m, n in matches:
if m.distance < 0.7 * n.distance:
topResults.append([m])
return topResults
def compare_images_kaze():
cwd = os.getcwd()
target = os.path.join(cwd, 'opencv_target', 'target.png')
images_list = os.listdir('opencv_images')
for image in images_list:
# get my 2 images
img2 = cv2.imread(target)
img1 = cv2.imread(os.path.join(cwd, 'opencv_images', image))
for i in range(0, 360, int(360 / 8)):
# rotate my image by i
img_target_rotation = imutils.rotate_bound(img2, i)
# Initiate KAZE object with default values
kaze = cv2.KAZE_create()
kp1, des1 = kaze.detectAndCompute(img1, None)
kp2, des2 = kaze.detectAndCompute(img2, None)
matches = calculate_matches(des1, des2)
try:
score = 100 * (len(matches) / min(len(kp1), len(kp2)))
except ZeroDivisionError:
score = 0
print(image, score)
img3 = cv2.drawMatchesKnn(img1, kp1, img_target_rotation, kp2, matches,
None, flags=2)
img3 = cv2.cvtColor(img3, cv2.COLOR_BGR2RGB)
plt.imshow(img3)
plt.show()
plt.clf()
if __name__ == '__main__':
compare_images_kaze()
这是我的代码的结果:
ex1.png 21.052631578947366
ex2.png 0.0
ex3.png 42.10526315789473
没毛病!它能够分辨出 ex1 相似而 ex2 不相似,但是它指出 ex3 相似(甚至比 ex1 更相似)。任何额外的预处理或后处理(可能是 ml,假设 ml 实际上有用)或只是我可以对我的方法做的更改,以便仅保持 ex1 相似而不是 ex3?
(注意我创建的这个分数是我在网上找到的。不确定这是否是一种准确的方法)
在下面添加了更多示例
另一组例子:
这是我正在寻找的
我希望上面的图像与中间和底部的图像相似(注意:我将目标图像旋转 45 度并将其与下面的图像进行比较。)
特征匹配(如下面的答案所述)在发现与第二张图像的相似性方面很有用,但不是第三张图像(即使在正确旋转之后)