使用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 度并将其与下面的图像进行比较。)

特征匹配(如下面的答案所述)在发现与第二张图像的相似性方面很有用,但不是第三张图像(即使在正确旋转之后)

以上是使用opencv查找包含另一张图像的最相似图像的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>