単一画像超解像の評価方法
単一画像超解像の評価にはSSIMやPSNRなどの指標が挙げられますが,今回は特にPSNRを焦点に当てます.
多くの論文はおそらく
https://github.com/jbhuang0604/SelfExSR
の sr_quant_eval.m の実装を参考にしていると思います.
この中でやっていることは
超解像画像と正解画像をRGBからYCbCrに変換して輝度値Yだけを取り出す.
周囲 $cr$ ピクセルを除外した上で超解像画像と正解画像の $\mathrm{MSE}$ を算出する.
その上で以下の式を用いて $\mathrm{PSNR}$ を求める.
$$ \mathrm{PSNR} = 10\times log_{10}{\frac{255^2}{\mathrm{MSE}}} $$
式自体は非常に単純であるので上のリンクはMATLABで書いていますが別に他の言語でも実装は簡単そうです.
特に最近は機械学習の影響でPythonで実装しようとする方も多いと思います.
その際,OpenCVを使うと思わぬ穴にはまります.
MATLABとOpenCVではRGB→YCbCrの計算式が異なる
上に書いた通りです.MATLABとOpenCVではRGB→YCbCrの計算式が異なります.
なるべく寄せたコードがこちらです.
import numpy as np
import math
def psnr(img1, img2):
mse = np.mean((img1 - img2) ** 2)
if mse == 0:
return 100
PIXEL_MAX = 255.0
return 10 * math.log10(PIXEL_MAX * PIXEL_MAX / mse)
def extract_y(image: np.ndarray) -> np.ndarray:
if image.ndim == 2:
return image
image = image.astype(np.float64)
return ((image[:, :, 2] * 65.481 / 255.
+ image[:, :, 1] * 128.553 / 255.
+ image[:, :, 0] * 24.966 / 255.) + 16)
def evaluate(img1: np.ndarray, img2: np.ndarray, upscaling=4):
# BGR -> YCrCb
# 画像はcv2.imreadで読まれている前提 [0, 255]
y1 = extract_y(img1)
y2 = extract_y(img2)
# 周囲のcropping
# assert y1.shape == y2.shape
h, w = y1.shape
cr = upscaling
cropped_y1 = y1[cr:h - cr, cr:w - cr]
cropped_y2 = y2[cr:h - cr, cr:w - cr]
# psnr
psnr_val = psnr(cropped_y1, cropped_y2)
return psnr_val
まだ微妙にMATLABとずれるので厳しい