<think>我们首先明确多尺度SSIM(MS-SSIM)的定义。根据引用[1]的描述,MS-SSIM是基于多尺度(多级二元金字塔)的结构相似性指数。其核心思想是在多个分辨率上计算SSIM,然后组合这些测量值。定义:给定一幅参考图像$x$和一幅待评估图像$y$,以及一个$M$层的图像金字塔(通常通过逐级下采样得到),MS-SSIM的公式为:$$MS\mhyphSSIM(x,y)=[l_M(x,y)]^{\alpha_M}\cdot\prod_{j=1}^{M}[c_j(x,y)]^{\beta_j}[s_j(x,y)]^{\gamma_j}$$其中:-$l_M$是在第$M$层(最粗糙层)计算的亮度比较函数。-$c_j$和$s_j$分别是在第$j$层计算的对比度和结构比较函数。-指数$\alpha_M,\beta_j,\gamma_j$用于调整各分量的相对重要性。通常,为了简化,可以设$\alpha_M=\beta_j=\gamma_j=1$,并且只使用最粗糙层的亮度比较,而对比度和结构比较在所有尺度上进行。另一种常见的简化是:$$MS\mhyphSSIM(x,y)=[l_M(x,y)]^{\alpha}\cdot\prod_{j=1}^{M}[c_j(x,y)s_j(x,y)]^{\beta_j}$$其中$\alpha$和$\beta_j$是根据实验确定的权重。接下来,我们将提供一个MATLAB实现MS-SSIM的代码。这个实现将基于以下步骤:1.构建图像金字塔(通常使用高斯金字塔,即先高斯滤波然后下采样)。2.从最粗糙层开始,计算该层的亮度比较($l_M$)以及对比度和结构比较($c_M,s_M$)。3.在每一层(除了最粗糙层)计算对比度和结构比较($c_j,s_j$)。4.按公式组合所有尺度的结果。注意:在实现中,我们通常使用固定的权重,且通常将指数都设为1,因此公式简化为:$$MS\mhyphSSIM=l_M\cdot\exp\left(\sum_{j=1}^{M}\log(c_j\cdots_j)\right)$$或者,我们可以将各尺度的$c_j\cdots_j$相乘,然后乘以$l_M$。我们将参考Wang等人在2003年提出的多尺度SSIM方法,并按照以下参数设置:-尺度数M通常为5(从0到4,0是原始尺度,然后每层下采样)。-每一层的高斯滤波器窗口大小为$11\times11$,标准差为1.5。-常数C1、C2、C3用于避免分母为零(通常取小常数)。由于MATLAB没有内置的MS-SSIM函数,我们需要自己实现。以下代码基于上述思路。注意:为了简化计算,我们假设图像是灰度图像。如果是彩色图像,通常转换为灰度图像,或对每个通道分别计算然后取平均(但MS-SSIM通常用于灰度图像)。实现步骤:1.将输入图像转换为灰度(如果需要)。2.设置金字塔层数M(例如5)。3.设置高斯滤波器(使用fspecial或imgaussfilt)。4.初始化各层的权重(通常每一层对比度和结构比较的权重相等,且所有层的权重和为1;而最顶层的亮度比较权重单独设置,如0.0448,其他层的对比度结构组合权重为0.0448,0.2856,0.3001,0.2363,0.1333,这是Wang等人在2003年论文中使用的权重,但是也可以简化使用相等权重)。5.对每一层进行循环(从最精细层到最粗糙层):-如果是第一次迭代(最精细层),则计算当前层的SSIM的三个分量(但注意,最顶层需要单独保留亮度分量)。-否则,通过下采样得到下一层图像。6.在每一层(除了最顶层)计算对比度和结构分量(注意,最顶层需要亮度分量)。7.计算乘积。由于代码较长,我们提供一个简化版本,使用固定5层,且使用Wang等人的权重。但是注意:由于Wang等人原始论文中的权重设置较为复杂,为了教学目的,我们可以使用相等权重(即每层的对比度和结构部分的权重相等,然后顶层亮度权重为1,这样乘积就变成了各层结构对比度分量的乘积再乘以顶层亮度分量)。但这里我们按照标准权重实现。以下代码中,我们使用预先计算的权重(来自Wang2003):亮度权重:0.0448对比度结构权重:[0.0448,0.2856,0.3001,0.2363,0.1333](注意:这些权重用于对比度结构乘积项,并且它们加起来等于1)但是注意,在MS-SSIM中,顶层(第5层)我们使用亮度分量乘以权重0.0448,然后其他每层的对比度结构乘积项乘以其对应的权重,最后全部相乘(指数权重已经包含在权重中,所以用加权乘积)。然而,原始论文中其实不是这样直接相乘,而是将权重作为指数,但为了与SSIM保持一致,他们使用了乘积的加权几何平均。在实现中,我们可以先将对比度结构分量(即c*s)进行加权几何平均,然后乘以亮度分量。但注意,在顶层,我们同时有亮度和对比度结构,但原始论文中只取顶层的亮度分量,而在其他层取对比度和结构分量。因此,顶层实际上只用了亮度分量,而其他层用了对比度和结构分量。为了更清楚,我们可以这样写:令$L$为最顶层的亮度分量(即$l_M$),$C_j$和$S_j$为第j层的对比度和结构分量,则MS-SSIM可以表示为:$$MS\mhyphSSIM=(L)^{\alpha}\cdot\prod_{j=1}^{M}(C_jS_j)^{\beta_j}$$其中$\alpha$和$\beta_j$就是上面给出的权重。注意,在顶层(第M层),我们只取亮度分量,而忽略该层的对比度和结构分量吗?实际上,在原始论文中,顶层的亮度分量是独立计算的,但该层同时也会计算对比度和结构分量,然而在公式中,顶层却没有使用自己的对比度和结构分量(因为公式中乘积的索引j是从1到M,而顶层是第M层,所以也包括在内)。这里需要澄清:在公式中,每个尺度j都包含对比度和结构分量,但亮度分量只在最粗糙层(第M层)计算一次。所以,顶层也会参与对比度和结构分量的计算。因此,我们每一层都要计算对比度和结构分量,而亮度分量只在最高层计算一次(但注意,在原始SSIM中,每一层计算时都会得到三个分量,但最后组合时,我们只使用顶层的亮度分量和所有层的对比度、结构分量?)实际上,根据Wang2003论文的公式(7):$$MS\mhyphSSIM(x,y)=[l_M(x,y)]^{\alpha_M}\cdot\prod_{j=1}^{M}[c_j(x,y)]^{\beta_j}[s_j(x,y)]^{\gamma_j}$$这里,$l_M$只在第M层计算,而对比度和结构分量在每一层(包括j=1到M)都计算。注意,这里的层索引j=1表示最精细层,j=M表示最粗糙层。所以,在实现中,我们需要在每一层(共M层)都计算对比度和结构分量,而亮度分量只在最粗糙层(第M层)计算。因此,实现步骤修改为:1.从最精细层(原始图像)开始,不断下采样得到M层图像(包括原始层,共M层)。2.对于每一层图像,计算对比度和结构分量(但注意,最粗糙层还需要额外计算亮度分量,因为公式中亮度分量只在这一层用)。3.然后,取最粗糙层的亮度分量,并乘以其他层的对比度结构分量(包括最粗糙层自己的对比度和结构分量)的加权几何平均(用指数权重)。所以,在每一层j,我们计算:-对比度分量:$c_j=\frac{2\sigma_{x,j}\sigma_{y,j}+C_2}{\sigma_{x,j}^2+\sigma_{y,j}^2+C_2}$-结构分量:$s_j=\frac{\sigma_{xy,j}+C_3}{\sigma_{x,j}\sigma_{y,j}+C_3}$(注意:在标准SSIM中,C3一般取C2/2)而在最粗糙层(j=M)额外计算:-亮度分量:$l_M=\frac{2\mu_x\mu_y+C_1}{\mu_x^2+\mu_y^2+C_1}$然后,按照权重组合。但是,在原始论文中,他们使用的是:$$MS\mhyphSSIM(x,y)=[l_M(x,y)]^{\alpha_M}\cdot\prod_{j=1}^{M}[c_j(x,y)s_j(x,y)]^{\beta_j}$$其中,$\beta_j$是各层的权重(且$\sum_{j=1}^{M}\beta_j=1$),$\alpha_M$是顶层亮度分量的权重(这里他们使用了经验值0.0448)。所以,我们可以这样计算:mssim=(l_M^alpha_M)*prod((c_j.*s_j).^beta_j)forjfrom1toM注意:每一层都计算了c_j和s_j,而只有最顶层计算了l_M。因此,我们开始写代码。由于代码较长,我们采用逐步生成图像金字塔的方式,并在每一层计算局部统计量(均值和方差,协方差)以计算各分量。我们将使用以下参数:-K=[0.010.03]用于计算C1,C2-window=高斯滤波器,大小为11×11,标准差1.5-weights=[0.04480.28560.30010.23630.1333];%5层的权重(用于对比度结构项)-alpha=0.0448;%顶层亮度分量的权重注意:这里权重是对比度结构分量的权重,而顶层亮度分量的权重alpha与这些权重无关。但是,在公式中,对比度结构分量的乘积是各个尺度的(c_js_j)的beta_j次方相乘,然后乘以亮度分量的alpha_M次方。因此,这里顶层亮度分量的权重alpha_M等于0.0448,而对比度结构分量在每一层的权重beta_j如上数组。然而,在原始论文中,他们使用的顶层亮度权重就是0.0448,而其他各层的对比度结构权重是上面那个数组(每个元素对应一层,从最精细到最粗糙)。所以,当我们有5层时,beta_j有5个权重(和上面数组一样),而alpha_M=0.0448。但是,这样计算的话,MS-SSIM的值会非常小(因为所有分量都是小于1的数,而且还要乘方很小的权重),因此,我们需要重新检查原始论文。实际上,在论文中,他们使用的指数权重是用于加权几何平均,所以最终指数为1的权重相当于对数值求加权平均然后取指数。然而,在实现中,我们可以将指数权重作为乘积的权重(即每个分量的beta_j次方),最后再乘以亮度分量的alpha_M次方。这里我们直接按照公式实现。具体步骤:1.设置参数:M=5;%5层K=[0.01,0.03];C1=(K(1)*255)^2;%动态范围如果是255,则255^2;如果是1,则1^2,这里我们假设图像是uint8,所以动态范围255C2=(K(2)*255)^2;C3=C2/2;%根据原论文,结构分量中的常数C3=C2/22.生成高斯滤波器:window=fspecial('gaussian',11,1.5);window=window/sum(window(:));3.权重设置:weight_contrast_structure=[0.0448,0.2856,0.3001,0.2363,0.1333];%从最精细层(第1层)到最粗糙层(第5层)weight_luminance=0.0448;%用于顶层(第5层)的亮度分量4.初始化图像金字塔:img1=double(ref_img);%参考图像img2=double(test_img);%待评估图像5.初始化乘积项数组(用于存储每一层的对比度结构乘积):mcs=zeros(1,M);%mcs:multi-scalecontrastandstructure6.从最精细层开始,循环M次(生成M层,从0到M-1,或者从1到M,这里我们用1到M表示最精细到最粗糙)第一层是原始图像,第二层是原始图像下采样,以此类推。我们使用imresize进行下采样,每次缩小一倍。7.对于每一层(第i层,i从1到M):a.计算当前层的局部统计量(使用卷积):mu1=filter2(window,img1,'valid');mu2=filter2(window,img2,'valid');mu1_sq=mu1.*mu1;mu2_sq=mu2.*mu2;mu1_mu2=mu1.*mu2;sigma1_sq=filter2(window,img1.*img1,'valid')-mu1_sq;sigma2_sq=filter2(window,img2.*img2,'valid')-mu2_sq;sigma12=filter2(window,img1.*img2,'valid')-mu1_mu2;b.根据当前层的序号,我们计算对比度分量(c)和结构分量(s):c=(2*sigma12+C2)./(sigma1_sq+sigma2_sq+C2);s=(sigma12+C3)./(sqrt(sigma1_sq.*sigma2_sq)+C3/2);%注意:这里分母的写法有变化,但原始论文中结构分量用的是相关系数,所以分母是sigma1和sigma2的乘积。另外,C3的加入方式,通常分母的常数项是C3,但这里我们按照(sigma1_sq*sigma2_sq)的平方根加上C3/2?实际上,标准SSIM的结构分量是:s=(sigma12+C3)/(sqrt(sigma1_sq*sigma2_sq)+C3)。所以,这里使用:%修正:结构分量应写成:%s=(sigma12+C3)./(sqrt(sigma1_sq).*sqrt(sigma2_sq)+C3);%但为了数值稳定性,我们使用:s=(sigma12+C3)./(sqrt(sigma1_sq.*sigma2_sq)+C3);c.计算当前层的对比度结构乘积:cs=c.*s;d.计算当前层cs的平均值(作为该层的整体对比度结构值):mcs_i=mean(cs(:));e.将mcs_i存入mcs(i)f.如果是顶层(第M层),则额外计算亮度分量:l=(2*mu1_mu2+C1)./(mu1_sq+mu2_sq+C1);l_M=mean(l(:));g.如果不是最后一层,则对当前图像进行下采样(为下一层做准备):img1=imresize(img1,0.5,'bilinear');img2=imresize(img2,0.5,'bilinear');8.计算MS-SSIM:首先,计算对比度结构部分的加权几何平均:mcs_prod=prod(mcs.^weight_contrast_structure);%对每一层的mcs进行加权(指数为对应层的权重)然后相乘。然后,乘以顶层亮度分量的权重:ms_ssim=(l_M^weight_luminance)*mcs_prod;但是,这里注意:我们在第7步的f中,只计算了第M层的亮度分量。但是,在mcs数组中,第M层对应mcs(M),而mcs(M)包含了第M层的对比度结构分量。这意味着,我们在第M层同时使用了亮度分量和对比度结构分量?这与公式一致。然而,在公式中,亮度分量只用于第M层,而其他层只用对比度结构分量。所以,上面的计算是正确的。但是,我们也可以看到,在每一层我们都计算了对比度结构分量,包括第M层。所以,整个流程正确。下面我们提供MATLAB代码实现:注意:为了提高效率,我们可能希望避免在每一层都使用全尺寸的高斯滤波,因为图像金字塔会逐步缩小。另外,我们使用双线性下采样。另外,由于我们只在有效区域进行卷积(filter2(...,'valid')),所以边界没有被填充。为了保持图像大小一致,我们可以在每一层先对图像进行镜像填充,使卷积后大小不变,然后再下采样。但这里为了简单,我们直接使用'valid'模式,然后在计算平均值时只取中心部分。但这样会丢弃边界。或者,我们可以使用整个图像区域(去掉边界后)。为了避免边界问题,我们可以使用对称填充(在调用filter2之前填充图像)。但是,由于MS-SSIM对边界不敏感(而且下采样会减少边界影响),我们这里不填充。代码实现如下(注意:我们假设输入图像是灰度图像,且是double类型,值在0-255之间):</think>
### 多尺度结构相似性指数 (MS-SSIM) 定义
MS-SSIM 是对经典 SSIM 的改进,通过在多个尺度上分析图像结构相似性来更符合人类视觉感知。给定参考图像 $x$ 和待评估图像 $y$,其定义如下:
1. **图像金字塔构建**
生成 $M$ 级高斯金字塔,通过迭代应用高斯滤波和下采样:
$$x_1 = x, \quad x_{k} = \downarrow_2 \!(x_{k-1} * G_\sigma)$$
其中 $\downarrow_2$ 表示下采样率,$G_\sigma$ 是高斯核,$\sigma$ 控制平滑度(通常 $\sigma = 1.5$)[^1]。
2. **多尺度分量计算**
从最粗糙层($k = M$)到最精细层($k = 1$)计算:
$$ \begin{cases}
l_M(x,y) & = \dfrac{2\mu_x \mu_y + C_1}{\mu_x^2 + \mu_y^2 + C_1} \\
c_k(x,y) & = \dfrac{2\sigma_x \sigma_y + C_2}{\sigma_x^2 + \sigma_y^2 + C_2} \\
s_k(x,y) & = \dfrac{\sigma_{xy} + C_3}{\sigma_x \sigma_y + C_3}
\end{cases} $$
其中 $\mu,\sigma$ 分别为局部均值和标准差,$\sigma_{xy}$ 为协方差,$C_i$ 为稳定常数。
3. **最终融合**
各尺度分量加权组合:
$$ MS\text{-}SSIM(x,y) = [l_M(x,y)]^{\alpha_M} \cdot \prod_{k=1}^{M} [c_k(x,y)]^{\beta_k} [s_k(x,y)]^{\gamma_k} $$
其中指数 $\alpha_M, \beta_k, \gamma_k$ 控制各分量权重(通常取 $\alpha_M = \beta_k = \gamma_k = 1$)。
---
### MATLAB 实现代码
```matlab
function mssim = ms_ssim(img1, img2, K, win_size, level, weight, sigma)
% 输入参数:
% img1, img2: 灰度图像 (范围 0-255)
% K: 稳定常数 [k1 k2] (默认 [0.01 0.03])
% win_size: 滑动窗口大小 (默认 11)
% level: 金字塔层数 (默认 5)
% weight: 各层权重向量 (默认 [0.0448 0.2856 0.3001 0.2363 0.1333])
% sigma: 高斯核标准差 (默认 1.5)
%
% 输出: MS-SSIM 指数值 (0-1, 1表示完全匹配)
% 参数初始化
if nargin < 3 || isempty(K)
K = [0.01 0.03];
end
if nargin < 4 || isempty(win_size)
win_size = 11;
end
if nargin < 5 || isempty(level)
level = 5;
end
if nargin < 6 || isempty(weight)
weight = [0.0448 0.2856 0.3001 0.2363 0.1333];
end
if nargin < 7 || isempty(sigma)
sigma = 1.5;
end
% 创建高斯窗口
window = fspecial('gaussian', win_size, sigma);
window = window / sum(window(:)); % 归一化
% 动态范围 (假设8-bit图像)
L = 255;
C1 = (K(1)*L)^2;
C2 = (K(2)*L)^2;
C3 = C2/2; % 根据引用[1]建议
% 构建图像金字塔
pyr1{1} = img1;
pyr2{1} = img2;
for s = 2:level
pyr1{s} = imresize(img1, 0.5^(s-1), 'bilinear');
pyr2{s} = imresize(img2, 0.5^(s-1), 'bilinear');
end
% 从最粗糙层开始计算
mssim_map = cell(1,level);
for s = level:-1:1
[mssim_map{s}, ~, ~, cs_map] = ssim_index(pyr1{s}, pyr2{s}, K, window, C1, C2, C3);
% 最顶层存储亮度分量
if s == level
luminance = mssim_map{s};
end
end
% 加权组合各尺度分量
mssim = weight(level) * mean2(luminance);
for s = 1:level-1
mssim = mssim * weight(s) * mean2(cs_map{s});
end
end
% 单尺度SSIM计算子函数
function [mssim, l_map, c_map, s_map] = ssim_index(img1, img2, K, window, C1, C2, C3)
% 计算局部统计量
mu1 = filter2(window, img1, 'valid');
mu2 = filter2(window, img2, 'valid');
mu1_sq = mu1.*mu1;
mu2_sq = mu2.*mu2;
mu1_mu2 = mu1.*mu2;
sigma1_sq = filter2(window, img1.*img1, 'valid') - mu1_sq;
sigma2_sq = filter2(window, img2.*img2, 'valid') - mu2_sq;
sigma12 = filter2(window, img1.*img2, 'valid') - mu1_mu2;
% 亮度分量
l_map = (2*mu1_mu2 + C1) ./ (mu1_sq + mu2_sq + C1);
% 对比度分量
c_map = (2*sqrt(sigma1_sq.*sigma2_sq) + C2) ./ (sigma1_sq + sigma2_sq + C2);
% 结构分量
s_map = (sigma12 + C3) ./ (sqrt(sigma1_sq.*sigma2_sq) + C3);
% 组合分量
mssim_map = l_map .* c_map .* s_map;
mssim = mean2(mssim_map);
end
```
### 使用示例
```matlab
ref = imread('reference.jpg'); % 参考图像
test = imread('test.jpg'); % 待评估图像
% 转换为灰度图
ref_gray = rgb2gray(ref);
test_gray = rgb2gray(test);
% 计算 MS-SSIM
score = ms_ssim(double(ref_gray), double(test_gray));
disp(['MS-SSIM = ', num2str(score)]);
```
### 关键参数说明
1. **高斯核设计**
$\sigma = 1.5$ 平衡了局部特征敏感性和噪声鲁棒性。$\sigma$ 过小会引入噪声敏感,过大则忽略细节(如引用[1]所述)[^1]。
2. **多尺度权重**
默认权重 `[0.0448 0.2856 0.3001 0.2363 0.1333]` 来自人眼视觉特性研究,精细层赋予更高权重以保留纹理细节[^2]。
3. **稳定常数**
$K_1 = 0.01$, $K_2 = 0.03$ 防止分母为零,其取值基于图像动态范围(8-bit图像 $L=255$)[^1]。
---
### 优化建议
1. **医学图像适配**
```matlab
% 调整金字塔层数(层数过多会弱化病理特征)
mssim_medical = ms_ssim(img1, img2, [0.01 0.03], 11, 3);
```
2. **硬件加速**
用并行计算处理金字塔层:
```matlab
parfor s = 1:level
% 各层独立计算
end
```
3. **与深度学习结合**
如引用[3]所述,可将 MS-SSIM 嵌入损失函数:
$$ \mathcal{L}_{total} = \lambda_1 \mathcal{L}_{MS-SSIM} + \lambda_2 \mathcal{L}_{L1} $$
---