SSIM(structural similarity index)结构相似性算法原理及python实现

一、SSIM算法简介

      SSIM(structural similarity index),结构相似性,是一种衡量两幅图像相似度的指标。该指标首先由德州大学奥斯丁分校的图像和视频工程实验室(Laboratory for Image and Video Engineering)提出。SSIM使用的两张图像中,一张为未经压缩的无失真图像,另一张为失真后的图像。
标题为:Image Quality Assessment: From Error Visibility to Structural Similarity
地址为:https://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=1284395

      与PSNR一样,SSIM也经常用作图像质量的评价。

二、SSIM算法原理

      对SSIM算法,其输入是两张图片,即要求结构相似性的两张图片。其中一张是未经压缩的无失真图像(即ground truth),另一张就是需要与无失真图片对比的图片。物体表面的亮度信息与照度反射系数有关,且场景中的物体的结构与照度是独立的,反射系数与物体有关。我们可以通过分离照度对物体的影响来探索一张图像中的结构信息。这里,把与物体结构相关的亮度和对比度作为图像中结构信息的定义。因为一个场景中的亮度和对比度总是在变化的,所以我们可以通过分别对局部的处理来得到更精确的结果。

      算法处理的原理图如下图所示:

                   

      由SSIM测量系统可得相似度的测量可由三种对比模块组成,分别为:亮度,对比度,结构。接下来我们将会对这三模块函数进行定义。

      首先,对于离散信号,我们以平均灰度来作为亮度测量的估计:

                                                       (1)

       亮度对比函数l(x,y)是关于的函数。

       然后,由测量系统知道要把平均灰度值从信号中去除,对于离散信号,可使用标准差来做对比度估量值。

                                        (2)

       对比度对比函数c(x,y)就是的函数。

       接下来,信号被自己的标准差相除,结构对比函数就被定义成的函数。

       最后,三个对比模块组合成一个完整的相似测量函数:

                                    (3)

       

       S(x,y)应该满足以下三个条件:

       (1) 对称性:

       (2) 有界性:

       (3) 最大值唯一性:当且仅当x=y时,S(x,y)=1 。

 

       现在,我们定义三个对比函数。

       亮度对比函数:

                                                  (4)

       常数是为了避免接近0时造成系统的不稳定。

       特别的,我们选择,L为图像灰度级数,对于8-bit灰度图像,L=255,。公式(4)满足上述三个条件。

       对比度对比函数:

                                                   (5)

       常数,且。公式(5)依然满足上述三个条件。

       结构对比函数:

                                                     (6)

       其中

                                         (7)

      最后把三个函数组合起来,得到SSIM指数函数:

                                   (8)

      这里,用来调整三个模块间的重要性。

      为了得到简化形式,设,得到:

                                 (9)

三、SSIM指数应用于图像质量评估

在图像质量评估之中,局部求SSIM指数的效果要好于全局。第一,图像的统计特征通常在空间中分布不均;第二,图像的失真情况在空间中也是变化的;第三,在正常视距内,人们只能将视线聚焦在图像的一个区域内,所以局部处理更符合人类视觉系统的特点;第四,局部质量检测能得到图片空间质量变化的映射矩阵,结果可服务到其他应用中。

     所以,在上述公式中,都加入了一个8*8的方形窗,并且逐像素的遍历整幅图片。每一步计算,和SSIM都是基于窗口内像素的,最终得到一个SSIM指数映射矩阵,由局部SSIM指数组成。然而,简单的加窗会使映射矩阵出现不良的“分块”效应。为解决这问题,我们使用11*11的对称高斯加权函数作为加权窗口,标准差为1.5,且

                                                 (10)

 

的估计值表示为:

                                               (11)

                                  (12)

                               (13)

       应用这种加窗方法,映射矩阵就可展现出局部各向同性的性质。

       在这里,经过一些实验总结,我们把K1设为0.01,K2设为0.03,然后用平均SSIM指数作为整幅图像的估计质量评价:

                    (14)

其中X,Y为图像,为局部SSIM指数在映射中的位置,MN为局部窗口的数量。

三、python代码实现

代码是从项目里面直接贴过来的,只改了其中一些部分,代码的目录格式如下所示:

├─python-ssim
│  │  python-ssim.py
│  │  README.md
│  │  使用.txt
│  └─data
│          1.jpg
│          2.jpg
│          3.jpg
│          4.jpg
│          5.png
│          6.png
 

python-ssim.py文件

import numpy
import scipy.ndimage
from scipy.ndimage import imread
from numpy.ma.core import exp
from scipy.constants.constants import pi

img_mat_1=imread('./data/5.png', flatten=True)
img_mat_2=imread('./data/6.png', flatten=True)


'''
The function to compute SSIM
@param param: img_mat_1 1st 2D matrix
@param param: img_mat_2 2nd 2D matrix
'''
def compute_ssim(img_mat_1, img_mat_2):
    #Variables for Gaussian kernel definition
    gaussian_kernel_sigma=1.5
    gaussian_kernel_width=11
    gaussian_kernel=numpy.zeros((gaussian_kernel_width,gaussian_kernel_width))
    
    #Fill Gaussian kernel
    for i in range(gaussian_kernel_width):
        for j in range(gaussian_kernel_width):
            gaussian_kernel[i,j]=\
            (1/(2*pi*(gaussian_kernel_sigma**2)))*\
            exp(-(((i-5)**2)+((j-5)**2))/(2*(gaussian_kernel_sigma**2)))

    #Convert image matrices to double precision (like in the Matlab version)
    img_mat_1=img_mat_1.astype(numpy.float)
    img_mat_2=img_mat_2.astype(numpy.float)
    
    #Squares of input matrices
    img_mat_1_sq=img_mat_1**2
    img_mat_2_sq=img_mat_2**2
    img_mat_12=img_mat_1*img_mat_2
    
    #Means obtained by Gaussian filtering of inputs
    img_mat_mu_1=scipy.ndimage.filters.convolve(img_mat_1,gaussian_kernel)
    img_mat_mu_2=scipy.ndimage.filters.convolve(img_mat_2,gaussian_kernel)
        
    #Squares of means
    img_mat_mu_1_sq=img_mat_mu_1**2
    img_mat_mu_2_sq=img_mat_mu_2**2
    img_mat_mu_12=img_mat_mu_1*img_mat_mu_2
    
    #Variances obtained by Gaussian filtering of inputs' squares
    img_mat_sigma_1_sq=scipy.ndimage.filters.convolve(img_mat_1_sq,gaussian_kernel)
    img_mat_sigma_2_sq=scipy.ndimage.filters.convolve(img_mat_2_sq,gaussian_kernel)
    
    #Covariance
    img_mat_sigma_12=scipy.ndimage.filters.convolve(img_mat_12,gaussian_kernel)
    
    #Centered squares of variances
    img_mat_sigma_1_sq=img_mat_sigma_1_sq-img_mat_mu_1_sq
    img_mat_sigma_2_sq=img_mat_sigma_2_sq-img_mat_mu_2_sq
    img_mat_sigma_12=img_mat_sigma_12-img_mat_mu_12;
    
    #c1/c2 constants
    #First use: manual fitting
    c_1=6.5025
    c_2=58.5225
    
    #Second use: change k1,k2 & c1,c2 depend on L (width of color map)
    l=255
    k_1=0.01
    c_1=(k_1*l)**2
    k_2=0.03
    c_2=(k_2*l)**2
    
    #Numerator of SSIM
    num_ssim=(2*img_mat_mu_12+c_1)*(2*img_mat_sigma_12+c_2)
    #Denominator of SSIM
    den_ssim=(img_mat_mu_1_sq+img_mat_mu_2_sq+c_1)*\
    (img_mat_sigma_1_sq+img_mat_sigma_2_sq+c_2)
    #SSIM
    ssim_map=num_ssim/den_ssim
    index=numpy.average(ssim_map)

    print(index)

    return index

    
compute_ssim(img_mat_1, img_mat_2)

三、结果示例

示例1

示例2

 

示例3


参考:https://blog.csdn.net/ecnu18918079120/article/details/60149864SSIM指数应用于图像质量评估

https://baike.baidu.com/item/SSIM/2091025?fr=aladdin

https://blog.csdn.net/leviopku/article/details/84635897

### 回答1: PSNR 和 SSIM 的 Python 实现可以使用现成的库,例如 scikit-image。 PSNR 的实现代码如下: ``` from skimage import metrics import numpy as np def psnr(img1, img2): mse = metrics.mean_squared_error(img1, img2) return 10 * np.log10(255**2 / mse) ``` SSIM 的实现代码如下: ``` from skimage import metrics import numpy as np def ssim(img1, img2): return metrics.structural_similarity(img1, img2, multichannel=True) ``` 请注意,img1 和 img2 必须是 NumPy 数组,且数据类型必须是 float32。 ### 回答2: PSNR (Peak Signal to Noise Ratio) 和 SSIM (Structural Similarity Index) 都是用于评估图像质量的指标,可以通过Python实现。 首先,我们来实现PSNR指标的计算。PSNR用于度量原始图像与压缩或处理后图像之间的误差。具体计算公式如下: PSNR = 10 * log10(MAX^2 / MSE) 其中,MAX为像素点的最大值(一般为255),MSE为均方误差。 以下是Python实现的代码: ```python import cv2 import numpy as np import math def calculate_psnr(original_image, processed_image): mse = np.mean((original_image - processed_image) ** 2) psnr = 10 * math.log10(255**2 / mse) return psnr # 加载图像 original_image = cv2.imread('original.jpg', 0) # 以灰度模式读取原始图像 processed_image = cv2.imread('processed.jpg', 0) # 以灰度模式读取处理后的图像 # 计算PSNR psnr = calculate_psnr(original_image, processed_image) print("PSNR: ", psnr) ``` 接下来,我们来实现SSIM指标的计算。SSIM用于度量原始图像与处理后图像在结构上的相似性。具体计算公式如下: SSIM = (2 * u_x * u_y + c1) * (2 * cov_xy + c2) / (u_x^2 + u_y^2 + c1) * (var_x + var_y + c2) 其中,u_x和u_y分别为原始图像和处理后图像的均值,cov_xy为两者的协方差,var_x和var_y为方差,c1和c2为常数。 以下是Python实现的代码: ```python import cv2 import numpy as np def calculate_ssim(original_image, processed_image): original_image = original_image.astype(np.float64) processed_image = processed_image.astype(np.float64) k1 = 0.01 k2 = 0.03 L = 255 c1 = (k1 * L) ** 2 c2 = (k2 * L) ** 2 u_x = np.mean(original_image) u_y = np.mean(processed_image) var_x = np.var(original_image) var_y = np.var(processed_image) cov_xy = np.cov(original_image, processed_image)[0, 1] ssim = ((2 * u_x * u_y + c1) * (2 * cov_xy + c2)) / ((u_x ** 2 + u_y ** 2 + c1) * (var_x + var_y + c2)) return ssim # 加载图像 original_image = cv2.imread('original.jpg', 0) # 以灰度模式读取原始图像 processed_image = cv2.imread('processed.jpg', 0) # 以灰度模式读取处理后的图像 # 计算SSIM ssim = calculate_ssim(original_image, processed_image) print("SSIM: ", ssim) ``` 需要注意的是,以上代码仅为简单的示例。实际应用中,可能需要进行其他的图像处理或转换,以符合计算PSNR和SSIM所需的输入条件。 ### 回答3: PSNR和SSIM是常用的图像质量评价指标,可以用来比较原始图像和经过压缩或其他失真处理后的图像之间的差异。它们的Python实现如下: PSNR的Python实现: ```python import numpy as np import math def psnr(original_image, distorted_image): mse = np.mean((original_image - distorted_image) ** 2) max_value = np.max(original_image) psnr_value = 20 * math.log10(max_value / math.sqrt(mse)) return psnr_value ``` SSIM的Python实现: ```python import numpy as np from scipy import signal def ssim(original_image, distorted_image): original_image = original_image.astype(float) distorted_image = distorted_image.astype(float) k1 = 0.01 k2 = 0.03 L = np.max(original_image) - np.min(original_image) C1 = (k1*L)**2 C2 = (k2*L)**2 mu1 = signal.convolve2d(original_image, np.ones((8, 8))/64, mode='same') mu2 = signal.convolve2d(distorted_image, np.ones((8, 8))/64, mode='same') mu1_sq = mu1**2 mu2_sq = mu2**2 mu1_mu2 = mu1 * mu2 sigma1_sq = signal.convolve2d(original_image**2, np.ones((8, 8))/64, mode='same') - mu1_sq sigma2_sq = signal.convolve2d(distorted_image**2, np.ones((8, 8))/64, mode='same') - mu2_sq sigma12 = signal.convolve2d(original_image * distorted_image, np.ones((8, 8))/64, mode='same') - mu1_mu2 ssim_value = np.mean(((2 * mu1_mu2 + C1) * (2 * sigma12 + C2)) / ((mu1_sq + mu2_sq + C1) * (sigma1_sq + sigma2_sq + C2))) return ssim_value ``` 这两个函数分别计算了输入的原始图像和失真图像之间的PSNR值和SSIM值。你可以通过调用这两个函数,将原始图像和失真图像传递给它们,来获取对应的评估结果。请注意,这两个实现仅适用于灰度图像,如果需要评估彩色图像,则需要对算法进行修改。
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值