Source code for IQM_Vis.metrics.non_perceptual

# Author: Matt Clifford <matt.clifford@bristol.ac.uk>
# License: BSD 3-Clause License
import numpy as np

# from torchmetrics import PeakSignalNoiseRatio as PSNRs
from IQM_Vis.metrics.metric_utils import _check_shapes

[docs]class MAE: '''Mean Absolute Error between two images. Images must have the same dimensions Args: return_image (bool): Whether to return the image (Defaults to False which will return a scalar value) ''' def __init__(self, return_image=False): self.return_image = return_image
[docs] def __call__(self, im_ref, im_comp, **kwargs): '''When an instance is called Args: im_ref (np.array): Reference image im_comp (np.array): Comparison image **kwargs: Arbitrary keyword arguments Returns: score (np.array): MAE (scalar if return_image is False, image if return_image is True) ''' _check_shapes(im_ref, im_comp) L1 = np.abs(im_ref - im_comp) if self.return_image: return L1 else: return L1.mean()
[docs]class MSE: '''Mean Squared Error between two images. Images must have the same dimensions Args: return_image (bool): Whether to return the image (Defaults to False which will return a scalar value) ''' def __init__(self, return_image=False): self.return_image = return_image
[docs] def __call__(self, im_ref, im_comp, **kwargs): '''When an instance is called Args: im_ref (np.array): Reference image im_comp (np.array): Comparison image **kwargs: Arbitrary keyword arguments Returns: score (np.array): MSE (scalar if return_image is False, image if return_image is True) ''' _check_shapes(im_ref, im_comp) L2 = np.square(im_ref - im_comp) if self.return_image: return L2 else: return L2.mean()
[docs]class RMSE: '''Root Mean Squared Error between two images. Images must have the same dimensions Args: return_image (bool): Whether to return the image (Defaults to False which will return a scalar value) ''' def __init__(self, return_image=False): self.return_image = return_image
[docs] def __call__(self, im_ref, im_comp, **kwargs): '''When an instance is called Args: im_ref (np.array): Reference image im_comp (np.array): Comparison image **kwargs: Arbitrary keyword arguments Returns: score (np.array): RMSE (scalar if return_image is False, image if return_image is True) ''' _check_shapes(im_ref, im_comp) L2 = np.square(im_ref - im_comp) if self.return_image: return np.sqrt(L2) else: return np.sqrt(L2.mean())
[docs]class one_over_PSNR: '''Peak signal to noise ratio - https://en.wikipedia.org/wiki/Peak_signal-to-noise_ratio The score given is normalised between 0, 1 by taking 1/PSNR Args: return_image (bool): Whether to return the image (Defaults to False which will return a scalar value) ''' def __init__(self): self.initialised = False # self.metric = PSNRs # self.device = torch.device( # "cuda" if torch.cuda.is_available() else "cpu") # self.preproccess_function = _numpy_to_torch_image
[docs] def __call__(self, im_ref, im_comp, **kwargs): '''When an instance is called Args: im_ref (np.array): Reference image im_comp (np.array): Comparison image **kwargs: Arbitrary keyword arguments Returns: score (np.array): PSNR between the images ''' _check_shapes(im_ref, im_comp) se = np.square(im_ref - im_comp) mse = se.mean() if mse == 0: return 0 psnr = 10 * np.log10(1/(mse)) return 1/psnr
# im_ref = self.preproccess_function(im_ref).to( # device=self.device, dtype=torch.float) # im_comp = self.preproccess_function(im_comp).to( # device=self.device, dtype=torch.float) # # set up metric # if self.initialised == False: # with warnings.catch_warnings(): # we don't care about the warnings these give # warnings.simplefilter("ignore") # self._metric = self.metric() # self._metric.to(self.device) # _score = self._metric(im_ref*255, im_comp*255).cpu().detach().numpy() # _score = 1 - _score # self._metric.reset() # return _score/255