2025年图像质量评估指标——SSIM介绍及计算方法

图像质量评估指标——SSIM介绍及计算方法图像质量评估指标 SSIM 介绍及计算方法 SSIM 全称为 Structural Similarity 即结构相似性 用于评估两幅图像相似度的指标 常用于衡量图像失真前与失真后的相似性 也用于衡量模型生成图像的真实性 如图像去雨 图像去雾 图像和谐化等等 计算方法 SSIM 的计算基于滑动窗口实现

大家好,我是讯享网,很高兴认识大家。

图像质量评估指标——SSIM介绍及计算方法

  SSIM全称为Structural Similarity,即结构相似性,用于评估两幅图像相似度的指标,常用于衡量图像失真前与失真后的相似性,也用于衡量模型生成图像的真实性,如图像去雨、图像去雾、图像和谐化等等。

计算方法

  SSIM的计算基于滑动窗口实现,即每次计算均从图片上取一个尺寸为 N × N N\times N N×N的窗口,基于窗口计算SSIM指标,遍历整张图像后再将所有窗口的数值取平均值,作为整张图像的SSIM指标

  假设 x x x表示第一张图像窗口中的数据, y y y表示第二张图像窗口中的数据。其中图像的相似性由三部分构成:luminance(亮度)、contrast(对比度)和structure(结构)。luminance计算公式为:
l ( x , y ) = 2 μ x μ y + c 1 μ x 2 + μ y 2 + c 1 l(x,y)=\frac{2\mu_x\mu_y+c_1}{\mu_x^2+\mu_y^2+c_1} l(x,y)=μx2+μy2+c12μxμy+c1
contrast计算公式为:
c ( x , y ) = 2 σ x σ y + c 2 σ x 2 + σ y 2 + c 2 c(x,y)=\frac{2\sigma_x\sigma_y+c_2}{\sigma_x^2+\sigma_y^2+c_2} c(x,y)=σx2+σy2+c22σxσy+c2
structure计算公式为:
s ( x , y ) = σ x y + c 3 σ x σ y + c 3 s(x,y)=\frac{\sigma_{xy}+c_3}{\sigma_x\sigma_y+c_3} s(x,y)=σxσy+c3σxy+c3
其中 μ x \mu_x μx μ y \mu_y μy依次表示 x x x y y y的均值, σ x \sigma_x σx σ y \sigma_y σy依次表示 x x x y y y的方差, σ x y \sigma_{xy} σxy表示 x x x y y y之间的协方差, c 1 = ( k 1 L ) 2 c_1=(k_1L)^2 c1=(k1L)2 c 2 = ( k 2 L ) 2 c_2=(k_2L)^2 c2=(k2L)2以及 c 3 = c 2 / 2 c_3=c_2/2 c3=c2/2,表示三个常数,避免分母为0, k 1 k_1 k1 k 2 k_2 k2依次默认为 0.01 0.01 0.01 0.03 0.03 0.03 L L L表示图像像素值的范围,即 2 B − 1 2^B-1 2B1


讯享网

  最后SSIM的计算公式为:
S S I M ( x , y ) = [ l ( x , y ) α ⋅ c ( x , y ) β ⋅ s ( x , y ) γ ] SSIM(x,y)=[l(x,y)^{\alpha}·c(x,y)^{\beta}·s(x,y)^{\gamma}] SSIM(x,y)=[l(x,y)αc(x,y)βs(x,y)γ]
如果令 α , β , γ \alpha, \beta, \gamma α,β,γ均为1,则得到常用的SSIM计算公式:
S S I M ( x , y ) = ( 2 μ x μ y + c 1 ) ( 2 σ x y + c 2 ) ( μ x 2 + μ y 2 + c 1 ) ( σ x 2 + σ y 2 + c 2 ) SSIM(x,y)=\frac{(2\mu_x\mu_y+c_1)(2\sigma_{xy}+c_2)}{(\mu_x^2+\mu_y^2+c_1)(\sigma_x^2+\sigma_y^2+c_2)} SSIM(x,y)=(μx2+μy2+c1)(σx2+σy2+c2)(2μxμy+c1)(2σxy+c2)

代码实现

  • 参考论文《Spatial Attentive Single-Image Deraining with a High Quality Real Rain Dataset》的源码:https://github.com/stevewongv/SPANet
def gaussian(window_size, sigma): # 计算公式:e^(-x^2)/(2*sigma^2),其中x表示距离中心点的距离,sigma默认1.5 gauss = torch.Tensor([exp(-(x - window_size // 2)  2 / float(2 * sigma  2)) for x in range(window_size)]) # 数据归一化 return gauss / gauss.sum() # 计算滑动窗口权重 def create_window(window_size, channel): # 利用滑动窗口尺寸先计算一个一维,并且服从正态分布的数据 # 注意这里利用unsqueeze函数扩了一下维度,从行向量变为了列向量 _1D_window = gaussian(window_size, 1.5).unsqueeze(1) # 列向量乘以行向量,变为n*n的矩阵,正好对应窗口权重 _2D_window = _1D_window.mm(_1D_window.t()).float().unsqueeze(0).unsqueeze(0) # 沿通道维度复制channel遍,每个通道对应一个权重(这里所有通道权重相同,均服从正态分布),并且变为连续存储的数据 window = Variable(_2D_window.expand(channel, 1, window_size, window_size).contiguous()) # 返回窗口权重数据 return window def _ssim(img1, img2, window, window_size, channel, size_average=True): # 计算每个滑动窗口的均值 # 卷积运算正好是窗口数据按权重求和再取均值,因此可以利用二维卷积运算来计算窗口中数据的均值 mu1 = F.conv2d(img1, window, padding=window_size // 2, groups=channel) mu2 = F.conv2d(img2, window, padding=window_size // 2, groups=channel) # 均值取平方,即E^2(X) mu1_sq = mu1.pow(2) mu2_sq = mu2.pow(2) # 计算E(X)E(Y),用于后续计算协方差 mu1_mu2 = mu1 * mu2 # 依次计算img1与img2的方差 # 这里计算方差利用公式D(X)=E(X^2)-E^2(X),其中E^2(X)表示均值的平方,即上述公式中的mu1_sq、mu2_sq、mu1_mu2 sigma1_sq = F.conv2d(img1 * img1, window, padding=window_size // 2, groups=channel) - mu1_sq sigma2_sq = F.conv2d(img2 * img2, window, padding=window_size // 2, groups=channel) - mu2_sq # 计算img1、img2之间的协方差 # 利用公式Conv(X,Y)=E(XY)-E(X)E(Y) sigma12 = F.conv2d(img1 * img2, window, padding=window_size // 2, groups=channel) - mu1_mu2 C1 = 0.01  2 C2 = 0.03  2 # 利用上述得到的指标,传入公式计算ssim值,此时会得到一张图,最后再求均值即可 ssim_map = ((2 * mu1_mu2 + C1) * (2 * sigma12 + C2)) / ((mu1_sq + mu2_sq + C1) * (sigma1_sq + sigma2_sq + C2)) if size_average: return ssim_map.mean() else: return ssim_map.mean(1).mean(1).mean(1) def ssim(img1, img2, window_size=11, size_average=True): # 将输入的图像数据限制为0-1之间(一般数据就是位于0-1之间,防止出现异常值) img1 = torch.clamp(img1, min=0, max=1) img2 = torch.clamp(img2, min=0, max=1) # 得到图片通道数 (_, channel, _, _) = img1.size() # 得到窗口的权重数据,离窗口中心越远,权重越小。权重服从高斯分布(正态分布) window = create_window(window_size, channel) # 如果图片数据储存在cuda上(即利用显卡训练),则将窗口权重数据也传入cuda中 if img1.is_cuda: window = window.cuda(img1.get_device()) # 统一数据类型 window = window.type_as(img1) # 调用_ssim,计算ssim值 return _ssim(img1, img2, window, window_size, channel, size_average) 

讯享网

直接调用skimage库中的函数

讯享网from skimage.metrics import structural_similarity # im1, im2分别表示参与计算的图像数据 # data_range表示图像数据的范围,一般设置为255或者1(如果对图像数据做了归一化操作,则为1) # channel_axis表示颜色通道位于图像的第几维度,如果不指定的话,则默认输入灰度图像 ssim = structural_similarity(im1, im2, win_size=None, gradient=False, data_range=None, channel_axis=None, multichannel=False, gaussian_weights=False, full=False) 

以上仅是笔者个人见解,若有问题,欢迎指正。

小讯
上一篇 2025-03-12 09:06
下一篇 2025-02-21 08:39

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/121862.html