5

我一直在使用结构相似性指数(通过 tensorflow)来比较图像,但是它需要的时间太长。我想知道是否有一种不需要太多时间的替代技术。如果有人能指出比 Python 中的 tensorflow 更有效的 SSIM 实现,那也没关系。

我使用 SSIM 的意图是,给定参考图像 (A) 和一图像 (B),我需要了解 B 中的哪个图像与参考图像 A 最相似。

4

1 回答 1

5

更新 01-02-2021

我决定探索一些其他可用于图像比较的 Python 模块。我还想使用concurrent.futures,我以前没有使用过。

我使用自己编写的代码创建了两个GitGub Gists

skimage ssim 图像比较

ImageHash aHash图片对比

ImageHash 模块能够在 0.29 秒内比较 100 张图像,而 skimage 模块则需要 1.2 秒来完成相同的任务。


原帖

我没有测试这个答案中代码的速度,因为我只在我发布到 GitHub 的一些图像测试中使用了代码:

面部相似之处

面部预测

下面的代码将产生参考图像 (A) 和图像集 (B) 之间的相似度分数。

完整代码位于我的 GitHub 存储库中

import os
from os import walk
import numpy as np
from PIL import Image
from math import *


def get_image_files(directory_of_images):
    """
     This function is designed to traverse a directory tree and extract all
     the image names contained in the directory.
    :param directory_of_images: the name of the target directory containing
           the images to be trained on.
    :return: list of images to be processed.
    """
    images_to_process = []
    for (dirpath, dirnames, filenames) in walk(directory_of_images):
        for filename in filenames:
            accepted_extensions = ('.bmp', '.gif', '.jpg', '.jpeg', '.png', '.svg', '.tiff')
            if filename.endswith(accepted_extensions):
                images_to_process.append(os.path.join(dirpath, filename))
        return images_to_process


def pre_process_images(image_one, image_two, additional_resize=False, max_image_size=1000):
    """
     This function is designed to resize the images using the Pillow module.
    :param image_one: primary image to evaluate against a secondary image
    :param image_two: secondary image to evaluate against the primary image
    :param additional_resize:
    :param max_image_size: maximum allowable image size in pixels
    :return: resized images
    """
    lower_boundary_size = (min(image_one.size[0], image_two.size[0]), min(image_one.size[1], image_two.size[1]))
    # reference: https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.resize
    # reference: https://pillow.readthedocs.io/en/stable/handbook/concepts.html#PIL.Image.LANCZOS
    image_one = image_one.resize(lower_boundary_size, resample=Image.LANCZOS)
    image_two = image_two.resize(lower_boundary_size, resample=Image.LANCZOS)
    if max(image_one.size) > max_image_size and additional_resize:
        resize_factor = max_image_size / max(image_one.size)
        image_one = image_one.resize((int(lower_boundary_size[0] * resize_factor),
                                      int(lower_boundary_size[1] * resize_factor)), resample=Image.LANCZOS)

        image_two = image_two.resize((int(lower_boundary_size[0] * resize_factor),
                                      int(lower_boundary_size[1] * resize_factor)), resample=Image.LANCZOS)
    return image_one, image_two


def get_ssim_similarity(image_one_name, image_two_name, window_size=7, dynamic_range=255):
    """
    The Structural Similarity Index (SSIM) is a method for measuring the similarity between two images.
    The SSIM index can be viewed as a quality measure of one of the images being compared, provided the
    other image is regarded as of perfect quality.
    :param image_one_name: primary image to evaluate against a secondary image
    :param image_two_name: secondary image to evaluate against the primary image
    :param window_size: The side-length of the sliding window used in comparison. Must be an odd value.
    :param dynamic_range: Dynamic range of the input image, specified as a positive scalar.
    The default dynamic range is 255 for images of data type uint8.
    :return: computational score and image names
    """
    image_one = Image.open(image_one_name)
    image_two = Image.open(image_two_name)

    if min(list(image_one.size) + list(image_two.size)) < 7:
        raise Exception("One of the images was too small to process using the SSIM approach")
    image_one, image_two = pre_process_images(image_one, image_two, True)
    image_one, image_two = image_one.convert('I'), image_two.convert('I')
    c1 = (dynamic_range * 0.01) ** 2
    c2 = (dynamic_range * 0.03) ** 2
    pixel_length = window_size ** 2
    ssim = 0.0
    adjusted_width = image_one.size[0] // window_size * window_size
    adjusted_height = image_one.size[1] // window_size * window_size
    for i in range(0, adjusted_width, window_size):
        for j in range(0, adjusted_height, window_size):
            crop_box = (i, j, i + window_size, j + window_size)
            crop_box_one = image_one.crop(crop_box)
            crop_box_two = image_two.crop(crop_box)
            np_array_one, np_array_two = np.array(crop_box_one).flatten(), np.array(crop_box_two).flatten()
            np_variable_one, np_variable_two = np.var(np_array_one), np.var(np_array_two)
            np_average_one, np_average_two = np.average(np_array_one), np.average(np_array_two)
            cov = (np.sum(np_array_one * np_array_two) - (np.sum(np_array_one) *
                                                          np.sum(crop_box_two) / pixel_length)) / pixel_length
            ssim += ((2.0 * np_average_one * np_average_two + c1) * (2.0 * cov + c2)) / \
                    ((np_average_one ** 2 + np_average_two ** 2 + c1) * (np_variable_one + np_variable_two + c2))
    similarity_percent = (ssim * pixel_length / (adjusted_height * adjusted_width)) * 100
    return round(similarity_percent, 2)


target_image = 'a.jpg'
image_directory = 'b_images'

images = get_image_files(image_directory)

for image in images:
    ssim_result = get_ssim_similarity(target_image, image)

我还建议查看Python模块ImageHash我在这里发布了多个代码示例和测试用例。

于 2020-12-28T21:28:40.613 回答