Python 3.x 在Python中比较优于MSE的图像的快速技术

Python 3.x 在Python中比较优于MSE的图像的快速技术,python-3.x,image-processing,similarity,ssim,Python 3.x,Image Processing,Similarity,Ssim,我一直在使用结构相似性指数(通过tensorflow)来比较图像,但是它花费的时间太长了。我想知道是否有一种不需要花费太多时间的替代技术。如果有人能指出一种比Python中的tensorflow更有效的SSIM实现,也没关系 我使用SSIM的目的是,给定一个参考图像(a)和一组图像(B),我需要了解B中的哪个图像与参考图像a最相似。更新01-02-2021 我决定探索其他一些可用于图像比较的Python模块。我还想使用concurrent.futures,这是我以前从未使用过的 我用自己编写的代

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


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

更新01-02-2021

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

我用自己编写的代码创建了两个GitGub注册表

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


原创帖子

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

下面的代码将在参考图像(a)和一组图像(B)之间生成相似性分数

完整的代码位于

导入操作系统
从操作系统导入漫游
将numpy作为np导入
从PIL导入图像
从数学导入*
def get_图像_文件(图像目录):
"""
此函数用于遍历目录树并提取所有
目录中包含的图像名称。
:param directory\u of_images:包含
要训练的图像。
:return:要处理的图像列表。
"""
图像到进程=[]
对于walk(图像的目录)中的(dirpath、dirname、filename):
对于文件名中的文件名:
接受的_扩展=(“.bmp”、“.gif”、“.jpg”、“.jpeg”、“.png”、“.svg”、“.tiff”)
如果filename.endswith(接受的扩展名):
图像\u到\u进程.append(os.path.join(dirpath,filename))
将图像返回到进程
def预处理图像(图像一、图像二、附加图像大小=假、最大图像大小=1000):
"""
此功能旨在使用枕头模块调整图像大小。
:param image_one:要针对次映像进行评估的主映像
:param image_two:要针对主映像进行评估的次映像
:param附加值\u调整大小:
:param max_image_size:允许的最大图像大小(像素)
:return:调整大小的图像
"""
下边界大小=(最小值(图像大小[0],图像大小[0]),最小值(图像大小[1],图像大小[1]))
#参考:https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.resize
#参考:https://pillow.readthedocs.io/en/stable/handbook/concepts.html#PIL.Image.LANCZOS
image\u one=image\u one.resize(下边界大小,重采样=image.LANCZOS)
image\u two=image\u two.resize(下边界大小,重采样=image.LANCZOS)
如果最大(图像大小)>最大图像大小和附加大小:
调整大小系数=最大图像大小/最大(图像大小)
image\u one=image\u one.resize((int(下限边界大小[0]*调整大小因子),
int(下边界大小[1]*调整大小因子),重采样=Image.LANCZOS)
image\u two=image\u two.resize((int(下边界大小[0]*调整大小因子),
int(下边界大小[1]*调整大小因子),重采样=Image.LANCZOS)
返回图像1,图像2
def get_ssim_相似性(图像名称、图像名称、窗口大小=7、动态范围=255):
"""
结构相似性指数(SSIM)是一种测量两幅图像之间相似性的方法。
SSIM索引可被视为所比较图像之一的质量度量,前提是
其他图像被认为质量完美。
:param image_one_name:要针对次映像进行评估的主映像
:param image_two_name:要针对主映像进行评估的次映像
:param window_size:用于比较的滑动窗口的边长。必须为奇数。
:param dynamic_range:输入图像的动态范围,指定为正标量。
数据类型为uint8的图像的默认动态范围为255。
:return:计算分数和图像名称
"""
image\u one=image.open(image\u one\u name)
image\u two=image.open(image\u two\u名称)
如果最小值(列表(图像大小)+列表(图像大小))<7:
引发异常(“其中一个图像太小,无法使用SSIM方法处理”)
图像1,图像2=预处理图像(图像1,图像2,真)
image\u-one,image\u-two=image\u-one.convert('I'),image\u-two.convert('I'))
c1=(动态范围*0.01)**2
c2=(动态范围*0.03)**2
像素长度=窗口大小**2
ssim=0.0
调整后的宽度=图像大小[0]//窗口大小*窗口大小
调整后的高度=图像大小[1]//窗口大小*窗口大小
对于范围内的i(0,调整的宽度,窗口大小):
对于范围内的j(0,调整的高度,窗口大小):
裁剪框=(i,j,i+窗口大小,j+窗口大小)
裁剪框裁剪一=图像裁剪一。裁剪(裁剪框)
裁剪框\二=图像\二。裁剪(裁剪框)
np\u数组\u-one,np\u数组\u-two=np.array(crop\u-box\u-one).flatten(),np.array(crop\u-box\u-two).flatten()
np_变量_-one,np_变量_-two=np.var(np_数组_-one),np.var(np_数组_-two)
np_average_one,np_average_two=np.average(np_数组_one),np.average(np_数组_two)
cov=(np.sum(np_数组_-one*np_数组_-two)-(np.sum(np_数组_-one)*
np.sum(裁剪框/像素长度)/像素长度
ssim+=((2.0*np_平均值\u 1*np_平均值\u 2+c1)*(2.0*cov+c2))/\
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)