简体   繁体   中英

How to get the SSIM comparison score between two images?

I am trying to calculate the SSIM between corresponding images. For example, an image called 106.tif in the ground truth directory corresponds to a 'fake' generated image 106.jpg in the fake directory.

The ground truth directory absolute pathway is /home/pr/pm/zh_pix2pix/datasets/mousebrain/test/B The fake directory absolute pathway is /home/pr/pm/zh_pix2pix/output/fake_B

The images inside correspond to each other, like this: see image

There are thousands of these images I want to compare on a one-to-one basis. I do not want to compare SSIM of one image to many others. Both the corresponding ground truth and fake images have the same file name, but different extension (ie 106.tif and 106.jpg) and I only want to compare them to each other.

I am struggling to edit available scripts for SSIM comparison in this way. I want to use this one: https://github.com/mostafaGwely/Structural-Similarity-Index-SSIM-/blob/master/ssim.py but other suggestions are welcome. The code is also shown below:

# Usage:
#
# python3 script.py --input original.png --output modified.png
# Based on: https://github.com/mostafaGwely/Structural-Similarity-Index-SSIM-

# 1. Import the necessary packages
#from skimage.measure import compare_ssim
from skimage.metrics import structural_similarity as ssim
import argparse
import imutils
import cv2

# 2. Construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-f", "--first", required=True, help="Directory of the image that will be compared")
ap.add_argument("-s", "--second", required=True, help="Directory of the image that will be used to compare")
args = vars(ap.parse_args())

# 3. Load the two input images
imageA = cv2.imread(args["first"])
imageB = cv2.imread(args["second"])

# 4. Convert the images to grayscale
grayA = cv2.cvtColor(imageA, cv2.COLOR_BGR2GRAY)
grayB = cv2.cvtColor(imageB, cv2.COLOR_BGR2GRAY)

# 5. Compute the Structural Similarity Index (SSIM) between the two
#    images, ensuring that the difference image is returned
#(score, diff) = compare_ssim(grayA, grayB, full=True)
(score, diff) = ssim(grayA, grayB, full=True)
diff = (diff * 255).astype("uint8")

# 6. You can print only the score if you want
print("SSIM: {}".format(score))

The use of argparse currently limits me to just one image at a time, but I would ideally like to compare them using a loop across the ground truth and fake directories. Any advice would be appreciated.

Here's a working example to compare one image to another. You can expand it to compare multiple at once. Two test input images with slight differences:

在此处输入图像描述 在此处输入图像描述

Results

Highlighted differences

在此处输入图像描述 在此处输入图像描述

Similarity score

Image similarity 0.9639027981846681

Difference masks

在此处输入图像描述 在此处输入图像描述 在此处输入图像描述

Code

from skimage.metrics import structural_similarity
import cv2
import numpy as np

before = cv2.imread('5.jpg')
after = cv2.imread('6.jpg')

# Convert images to grayscale
before_gray = cv2.cvtColor(before, cv2.COLOR_BGR2GRAY)
after_gray = cv2.cvtColor(after, cv2.COLOR_BGR2GRAY)

# Compute SSIM between two images
(score, diff) = structural_similarity(before_gray, after_gray, full=True)
print("Image similarity", score)

# The diff image contains the actual image differences between the two images
# and is represented as a floating point data type in the range [0,1] 
# so we must convert the array to 8-bit unsigned integers in the range
# [0,255] before we can use it with OpenCV
diff = (diff * 255).astype("uint8")

# Threshold the difference image, followed by finding contours to
# obtain the regions of the two input images that differ
thresh = cv2.threshold(diff, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
contours = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]

mask = np.zeros(before.shape, dtype='uint8')
filled_after = after.copy()

for c in contours:
    area = cv2.contourArea(c)
    if area > 40:
        x,y,w,h = cv2.boundingRect(c)
        cv2.rectangle(before, (x, y), (x + w, y + h), (36,255,12), 2)
        cv2.rectangle(after, (x, y), (x + w, y + h), (36,255,12), 2)
        cv2.drawContours(mask, [c], 0, (0,255,0), -1)
        cv2.drawContours(filled_after, [c], 0, (0,255,0), -1)

cv2.imshow('before', before)
cv2.imshow('after', after)
cv2.imshow('diff',diff)
cv2.imshow('mask',mask)
cv2.imshow('filled after',filled_after)
cv2.waitKey(0)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM