SSIM は 2 つの画像の類似性を測る指標である構造類似性尺度であり、ディープラーニングでは、GAN などの生成モデルで生成された画像と実際の画像との類似性を評価するために使用されます。
この図では、同じ MSE と異なる SSIM 画像の鮮明さが大きく異なることがわかり、SSIM が MSE よりも優れた評価指標であることが直感的にわかります。
SSIMの計算式
SSIM の計算は主に、画像の 3 つの主要な特徴、つまり明るさ、コントラスト、構造によって決定されます。
1.明るさ
画像の明るさは画像のピクセル値を表したもので、単一のピクセル値の場合、ピクセル値が大きいほど白に近づき明るくなり、その逆も同様です。全ピクセルの平均値が大きいほど画像全体が明るくなり、その逆も同様です。
明るさは平均グレースケールで測定され、すべてのピクセルの値を平均することで得られます。
2. コントラスト
画像のコントラストは、ダイナミック レンジ全体における画像のピクセル値の分布を表したものです。ダイナミック レンジ内の画像のピクセル値の分布が広いほど、コントラストは高くなります。そうでない場合、画像のピクセル値の分布はより厳密になります。分布範囲の説明は、分散または標準偏差の概念に正確に対応します。
3. 構造
この構造は、ピクセルの線形依存関係の観点から説明されます。共分散を求めることで、対応する構造の項を取得します。
4. SSIMの最終計算式
4. トーチは SSIM を実装します
def calculate_ssim(img1, img2, border=0):
'''calculate SSIM
the same outputs as MATLAB's
img1, img2: [0, 255]
'''
if not img1.shape == img2.shape:
raise ValueError('Input images must have the same dimensions.')
h, w = img1.shape[:2]
img1 = img1[border:h-border, border:w-border]
img2 = img2[border:h-border, border:w-border]
if img1.ndim == 2:
return ssim(img1, img2)
elif img1.ndim == 3:
if img1.shape[2] == 3:
ssims = []
for i in range(3):
ssims.append(ssim(img1, img2))
return np.array(ssims).mean()
elif img1.shape[2] == 1:
return ssim(np.squeeze(img1), np.squeeze(img2))
else:
raise ValueError('Wrong input image dimensions.')
def ssim(img1, img2):
C1 = (0.01 * 255)**2
C2 = (0.03 * 255)**2
img1 = img1.astype(np.float64)
img2 = img2.astype(np.float64)
kernel = cv2.getGaussianKernel(11, 1.5)
window = np.outer(kernel, kernel.transpose())
mu1 = cv2.filter2D(img1, -1, window)[5:-5, 5:-5] # valid
mu2 = cv2.filter2D(img2, -1, window)[5:-5, 5:-5]
mu1_sq = mu1**2
mu2_sq = mu2**2
mu1_mu2 = mu1 * mu2
sigma1_sq = cv2.filter2D(img1**2, -1, window)[5:-5, 5:-5] - mu1_sq
sigma2_sq = cv2.filter2D(img2**2, -1, window)[5:-5, 5:-5] - mu2_sq
sigma12 = cv2.filter2D(img1 * img2, -1, window)[5:-5, 5:-5] - mu1_mu2
ssim_map = ((2 * mu1_mu2 + C1) * (2 * sigma12 + C2)) / ((mu1_sq + mu2_sq + C1) *
(sigma1_sq + sigma2_sq + C2))
return ssim_map.mean()