Как рассчитать SSIM между двумя изображениями и преобразовать их в проценты? - PullRequest
0 голосов
/ 27 июня 2019

Я написал код для вычисления индекса структурного сходства (SSIM) между двумя изображениями. Я хотел бы получить процентное сходство из этого вычисления. Мой вопрос заключается в том, удовлетворяет ли SSIM математическим свойствам метрики.

Я написал фрагмент кода с комментариями на этот счет

# -*- coding: utf-8 -*-
"""
Created on Thu Jun 27 12:47:56 2019

@author: configcar005
"""

import warnings
from scipy.ndimage import imread
import numpy as np
import argparse
from skimage.measure import compare_ssim
from skimage.transform import resize
import cv2

##
# Globals
##

warnings.filterwarnings('ignore')

# specify resized image sizes
height = 2**10
width = 2**10

def get_histogram(img):
  '''
  Get the histogram of an image. For an 8-bit, grayscale image, the
  histogram will be a 256 unit vector in which the nth value indicates
  the percent of the pixels in the image with the given darkness level.
  The histogram's values sum to 1.
  '''
  h, w = img.shape
  hist = [0.0] * 256
  for i in range(h):
    for j in range(w):
      hist[img[i, j]] += 1
  return np.array(hist) / (h * w) 

def normalize_exposure(img):
  '''
  Normalize the exposure of an image.
  '''
  img = img.astype(int)
  hist = get_histogram(img)
  # get the sum of vals accumulated by each position in hist
  cdf = np.array([sum(hist[:i+1]) for i in range(len(hist))])
  # determine the normalization values for each unit of the cdf
  sk = np.uint8(255 * cdf)
  # normalize each position in the output image
  height, width = img.shape
  normalized = np.zeros_like(img)
  for i in range(0, height):
    for j in range(0, width):
      normalized[i, j] = sk[img[i, j]]
  return normalized.astype(int)

def get_img(path, norm_size=True, norm_exposure=False):
  '''
  Prepare an image for image processing tasks
  '''
  # flatten returns a 2d grayscale array
  img = imread(path, flatten=True).astype(int)
  # resizing returns float vals 0:255; convert to ints for downstream tasks
  if norm_size:
    img = resize(img, (height, width), anti_aliasing=True, preserve_range=True)
  if norm_exposure:
    img = normalize_exposure(img)
  return img

def structural_sim(path_a, path_b):
  '''
  Measure the structural similarity between two images
  @args:
    {str} path_a: the path to an image file
    {str} path_b: the path to an image file
  @returns:
    {float} a float {-1:1} that measures structural similarity
      between the input images
  '''
  img_a = get_img(path_a)
  img_b = get_img(path_b)
  sim, diff = compare_ssim(img_a, img_b, full=True) # if 1 they are similar
  return sim

if __name__ == '__main__':
    ap = argparse.ArgumentParser()
    ap.add_argument("-i1", "--image_path_first", help="path to the first image file")
    ap.add_argument("-i2", "--image_path_second", help="path to the second image file")
    args = vars(ap.parse_args())

    # get the similarity values
    structural_sim = structural_sim(args["image_path_first"], args["image_path_second"]) # 1 is perfect structural similarity. A value of -1 indicates no structural similarity

    if structural_sim < 0:
        print(structural_sim, "the images are not similar")
    elif structural_sim > 0:
        print(structural_sim, "the images are nearly similar")     

Я ожидаю процентного сходства между двумя изображениями.

...