要求:两个文件夹内的图像数量一致、文件名对应一致。 比如:文件夹A下有3张图像x1.png、x2.png、x3.png,文件夹B下也有3张图像x1.png、x2.png、x3.png。
所用命令如下:
python evaluate.py --org_img_path path_1 --pred_img_path path_2 --metric psnr
上述命令中的path_1与path_2分别是两个文件夹的绝对路径。
运行结果示例,如图1至图3所示。
![](https://i-blog.csdnimg.cn/blog_migrate/abc893b254659924104895db3adb2e3c.png)
图 1
![](https://i-blog.csdnimg.cn/blog_migrate/4397e8cedb7759cbafb9929bbcae7e59.png)
图 2
![](https://i-blog.csdnimg.cn/blog_migrate/002a397af0beb1e8be94179838d17dff.png)
图 3
所用代码附在末尾。其实这个代码还可以计算其它指标,具体可以参考博文末的参考资料,但博主所附代码不支持计算两个文件夹下的图像除SSIM与PSNR外的指标。
# file: __init__.py
# file: quality_metrics.py
"""
This module is a collection of metrics to assess the similarity between two images.
PSNR, SSIM, FSIM and ISSM are the current metrics that are implemented in this module.
"""
import math
import numpy as np
from skimage.metrics import structural_similarity
import phasepack.phasecong as pc
import cv2
def _assert_image_shapes_equal(org_img: np.ndarray, pred_img: np.ndarray, metric: str):
msg = (f"Cannot calculate {
metric}. Input shapes not identical. y_true shape ="
f"{
str(org_img.shape)}, y_pred shape = {
str(pred_img.shape)}")
assert org_img.shape == pred_img.shape, msg
def rmse(org_img: np.ndarray, pred_img: np.ndarray, max_p=4095) -> float:
"""
Root Mean Squared Error
Calculated individually for all bands, then averaged
"""
_assert_image_shapes_equal(org_img, pred_img, "RMSE")
org_img = org_img.astype(np.float32)
rmse_bands = []
for i in range(org_img.shape[2]):
dif = np.subtract(org_img, pred_img)
m = np.mean(np.square( dif / max_p))
s = np.sqrt(m)
rmse_bands.append(s)
return np.mean(rmse_bands)
def psnr(org_img: np.ndarray, pred_img: np.ndarray, max_p=4095) -> float:
"""
Peek Signal to Noise Ratio, implemented as mean squared error converted to dB.
It can be calculated as
PSNR = 20 * log10(MAXp) - 10 * log10(MSE)
When using 12-bit imagery MaxP is 4095, for 8-bit imagery 255. For floating point imagery using values between
0 and 1 (e.g. unscaled reflectance) the first logarithmic term can be dropped as it becomes 0
"""
_assert_image_shapes_equal(org_img, pred_img, "PSNR")
org_img = org_img.astype(np.float32)
mse_bands = []
for i in range(org_img.shape[2]):
mse_bands.append(np.mean(np.square(org_img[:, :, i] - pred_img[:, :, i])))
return 20 * np.log10(max_p) - 10. * np.log10(np.mean(mse_bands))
def _similarity_measure(x, y, constant):
"""
Calculate feature similarity measurement between two images
"""
numerator = 2 * x * y + constant
denominator = x ** 2 + y ** 2 + constant
return numerator / denominator
def _gradient_magnitude(img: np.ndarray, img_depth):
"""
Calculate gradient magnitude based on Scharr operator
"""
scharrx = cv2.Scharr(img, img_depth, 1, 0)
scharry = cv2.Scharr(img, img_depth, 0, 1)
return np.sqrt(scharrx ** 2 + scharry ** 2)
def fsim(org_img: np.ndarray, pred_img: np.ndarray, T1=0.85, T2=160) -> float:
"""
Feature-based similarity index, based on phase congruency (PC) and image gradient magnitude (GM)
There are different ways to implement PC, the authors of the original FSIM paper use the method
defined by Kovesi (1999). The Python phasepack project fortunately provides an implementation
of the approach.
There are also alternatives to implement GM, the FSIM authors suggest to use the Scharr
operation which is implemented in OpenCV.
Note that FSIM is defined in the original papers for grayscale as well as for RGB images. Our use cases
are mostly multi-band images e.g. RGB + NIR. To accommodate for this fact, we compute FSIM for each individual
band and then take the average.
Note also that T1 and T2 are constants depending on the dynamic range of PC/GM values. In theory this parameters
would benefit from fine-tuning based on the used data, we use the values found in the original paper as defaults.
Args:
org_img -- numpy array containing the origi