Image quality evaluation index: PSNR / SSIM principle and Python code

2023.6.19 update:
APIs of PSNR and SSIM have been migrated to skimage.metrics.peak_signal_noise_ratioand skimage.metrics.structural_similarity
for details, please refer to skimage official documentation API

1. PSNR

  PSNR (Peak Signal-to-Noise Ratio, Peak Signal-to-Noise Ratio) is used to measure the difference between two images, such as compressed image and original image, to evaluate the quality of compressed image; restored image and ground truth, to evaluate the performance of restoration algorithm, etc.

公式: P S N R = 10 × l g ( M a x V a l u e 2 M S E ) \mathrm{PSNR}=10 \times lg \left( \frac{\mathrm{MaxValue}^2}{\mathrm{MSE}}\right) PSNR=10×lg(MSEMaxValue2)

  where MSE \mathrm{MSE}MSE is the mean square error of the two images;Max Value \mathrm{MaxValue}MaxValue is the maximum value available for image pixels, for example, 8-bit image is2 8 − 1 = 255 2^8-1=255281=255

code:

# 直接调库
from skimage.measure import compare_psnr

compare_psnr(img1, img2, 255)

'''
2022-7-28: 更新
skimage.measure.compare_psnr has been moved to skimage.metrics.peak_signal_noise_ratio
'''
from skimage.metrics import peak_signal_noise_ratio as compare_psnr
compare_psnr(img1, img2, data_range=255)
# 自己实现
import numpy as np

def compare_psnr(img1, img2, maxvalue):
	'''
	一般 opencv 读图是 uint8, 漏掉转数据格式会导致计算出错;
	有些代码会在 mse==0 的时候直接返回 100, 但很明显 psnr 并没有最大值为 100 的说法,
	通常也不会算两张相同图像的 psnr, 干脆和 skimage 一样不写 mse==0 的情况
	'''
    img1, img2 = img1.astype(np.float64), img2.astype(np.float64)
    mse = np.mean((img1 - img2) ** 2)
    return 10 * np.log10((maxvalue ** 2) / mse)

Significance:
  The minimum value of PSNR is 0, the greater the PSNR, the smaller the difference between the two images;
  the calculation of PSNR is simple, and the physical meaning is clear, but this evaluation index based on MSE cannot measure the two images according to the perception of human eyes. The similarity of the image, such as the picture in the SSIM paper:
insert image description here
  It means that the MSE of the five different transformed images is the same as the original image, that is, the PSNR is also the same, but the SSIM is different, and the image similarity can be evaluated similar to human feelings.
  To verify, save the 6 images in the paper to calculate PSNR. After all, it is not completely calculated on the original image, but the difference in PSNR is really not big:
psnr(a,b) = 22.8197
psnr(a,c) = 24.6104
psnr(a,d) = 23.6994
psnr(a,e) = 22.9966
psnr(a,f) = 24.6628

2. SSIM

  SSIM (Structural Similarity, Structural Similarity) is based on the assumption that the human eye will extract the structured information in the image, which is more in line with the human visual perception than the traditional method.

For example: SSIM ⁡ ( x , y ) = [ l ( x , y ) ] α ⋅ [ c ( x , y ) ] β ⋅ [ s ( x , y ) ] γ \operatorname{SSIM}(\mathbf{x} , \mathbf{y})=[l(\mathbf{x}, \mathbf{y})]^{\alpha} \cdot[c(\mathbf{x}, \mathbf{y})]^{\ beta} \cdot[s(\mathbf{x}, \mathbf{y})]^{\gamma}SSIM ( x ,y)=[l(x,y)]a[c(x,y)]b[s(x,y)]c

SSIM consists of three parts, α , β , γ > 0 \alpha, \beta, \gamma>0a ,b ,c>0 , used to adjust the specific gravity of the three parts

  l ( x , y ) = 2 µ x µ y + C 1 µ x 2 + µ y 2 + C 1 ⟶ Single l(\mathbf{x}, \mathbf{y})=\frac{2 \mu_{x } \mu_{y}+C_{1}}{\mu_{x}^{2}+\mu_{y}^{2}+C_{1}} \longrightarrow exponentl(x,y)=mx2+ my2+C12 mxmy+C1brightness

  c ( x , y ) = 2 σ x σ y + C 2 σ x 2 + σ y 2 + C 2 ⟶ Let c(\mathbf{x}, \mathbf{y})=\frac{2 \sigma_{x } \sigma_{y}+C_{2}}{\sigma_{x}^{2}+\sigma_{y}^{2}+C_{2}} \longrightarrow Alignmentc(x,y)=px2+ py2+C22 pxpy+C2contrast

  s ( x , y ) = σ xy + C 3 σ x σ y + C 3 ⟶ The function s(\mathbf{x}, \mathbf{y})=\frac{\sigma_{xy}+C_{3}} {\sigma_{x}\sigma_{y}+C_{3}} \longrightarrow ratios(x,y)=pxpy+C3pxy+C3structure

where C 1 = ( K 1 L ) 2 C_{1} = (K_1L)^2C1=(K1L)2C 2 = ( K 2 L ) 2 C_{2} = (K_2L)^2C2=(K2L)2 , used to avoid the case where the denominator is 0,
LLL is equivalent to Max Value \mathrm{MaxValue}in PSNRMaxValue K 1 , K 2 ≪ 1 K_1,K_2 \ll 1 K1,K21 is a very small constant, the defaultK 1 = 0.01 K_1=0.01K1=0.01 K 2 = 0.03 K_2=0.03 K2=0.03

In the paper, α = β = γ = 1 \alpha = \beta = \gamma = 1a=b=c=1 andC 3 = C 2 / 2 C_{3}=C_{2}/2C3=C2/2 to simplify the formula:

  SSIM ⁡ ( x , y ) = ( 2 µ x µ y + C 1 ) ( 2 σ xy + C 2 ) ( µ x 2 + µ y 2 + C 1 ) ( σ x 2 + σ y 2 + C 2 ) \operatorname{SSIM}(\mathbf{x}, \mathbf{y})=\frac{\left(2\mu_{x}\mu_{y}+C_{1}\right)\left(2\sigma_ {xy}+C_{2}\right)}{\left(\mu_{x}^{2}+\mu_{y}^{2}+C_{1}\right)\left(\sigma_{x }^{2}+\sigma_{y}^{2}+C_{2}\right)}SSIM ( x ,y)=( mx2+ my2+C1) ( px2+ py2+C2)( 2 mxmy+C1) ( 2 pxy+C2)

  均值:  μ x = 1 N ∑ i = 1 N x i \mu_{x}=\frac{1}{N} \sum \limits_{i=1}^{N} x_{i} mx=N1i=1Nxi

  标准差: σ x = ( 1 N − 1 ∑ i = 1 N ( x i − μ x ) 2 ) 1 / 2 \sigma_{x}=\left(\frac{1}{N-1} \sum \limits_{i=1}^{N}\left(x_{i}-\mu_{x}\right)^{2}\right)^{1 / 2} px=(N11i=1N(ximx)2)1/2

  小方差:σ xy = 1 N − 1 ∑ i = 1 N ( xi − μ x ) ( yi − μ y ) \sigma_{xy}=\frac{1}{N-1} \sum \limits_{i= 1}^{N}\left(x_{i}-\mu_{x}\right)\left(y_{i}-\mu_{y}\right)pxy=N11i=1N(ximx)(yimy)

code:

from skimage.measure import compare_ssim

'''
compare_ssim(X, Y, win_size=None, gradient=False, 
			 data_range=None, multichannel=False, 
			 gaussian_weights=False, full=False, **kwargs)
			 
-------- Parameters --------
X, Y : ndarray
	   任意维度图像
win_size : int or None
gradient : bool, optional
		   是否返回关于Y的梯度
data_range : float, optional
			 输入图像数据范围(MaxValue), 默认情况根据图像数据类型估计
multichannel : bool, optional
			   if True, 则将数组的最后一个维度视为通道, 
			   对每个通道独立进行相似度计算, 然后取平均值。
gaussian_weights : bool, optional
				   if True, 则每个patch的均值和方差由宽度为 sigma=1.5 的归一化高斯核在空间上加权。
full : bool, optional
	   if True, 返回原图大小的ssim而不是均值
	   
-------- Other Parameters --------
use_sample_covariance : bool, default=True
						if True, 则通过 N-1 而不是 N 对协方差进行归一化,
						其中 N 是滑动窗口内的像素数。
K1 : float, default=0.01
K2 : float, default=0.03
sigma : float, default=1.5
		gaussian_weights=True 时的 sigma
		
-------- Returns --------
mssim : float
grad : ndarray
	   X 和 Y 之间结构相似指数的梯度。
	   仅在 gradient=True 时返回
S : ndarray
	完整的 ssim 图像
	仅在 full=True 时返回
'''
ssim = compare_ssim(img1, img2, win_size=11, data_range=255, multichannel=True)

Meaning:
  SSIM ⁡ ≤ 1 \operatorname{SSIM}\le 1SSIM1 , the larger the SSIM, the more similar the two images are.

  However, both PSNR and SSIM are only suitable for images with low picture complexity or fully aligned images. For example, the following picture shows satellite images of the same location in different periods and their overlapping displays. The similarity is high to the human eye, but the SSIM is very low due to misalignment .
insert image description here

Guess you like

Origin blog.csdn.net/weixin_43605641/article/details/118088814