【基础知识】图像去噪评估—PSNR和SSIM

PSNR简介

PSNR的全称为“Peak Signal-to-Noise Ratio”,直译为中文就是峰值信噪比。是一种衡量图像质量的指标。在很多领域都会需要这个指标,比如在超分辨率重建图像的时候,PSNR就是很重要的指标了。

WIKI解释

峰值信噪比(英语:Peak signal-to-noise ratio,常缩写为PSNR)是一个表示信号最大可能功率和影响它的表示精度的破坏性噪声功率的比值的工程术语。由于许多信号都有非常宽的动态范围,峰值信噪比常用对数分贝单位来表示。

计算PSNR要先知道MSE(均方误差)的计算。两个m×n单色图像I和K,如果一个为另外一个的噪声近似,那么它们的的均方误差定义为:

MSE的概念应该是比较熟悉的,这也是常见的损失函数。而PSNR就是通过MSE得出来的,公式如下:

其中,MAXI是表示图像点颜色的最大数值,如果每个采样点用 8 位表示,那么就是 255。

所以MSE越小,则PSNR越大;所以PSNR越大,代表着图像质量越好。一般来说,

PSNR高于40dB说明图像质量极好(即非常接近原始图像),
在30—40dB通常表示图像质量是好的(即失真可以察觉但可以接受),
在20—30dB说明图像质量差;
最后,PSNR低于20dB图像不可接受

python代码实现PSNR计算

# PSNR.py
 
import numpy
import math

def psnr(img1, img2):
    mse = numpy.mean( (img1 - img2) ** 2 )
    if mse == 0:
        return 100
    PIXEL_MAX = 255.0
    return 20 * math.log10(PIXEL_MAX / math.sqrt(mse))

以上代码仅作参考之用,tensorflow框架里有直接关于psnr计算的函数,直接调用就行了:(更推荐)

注意:计算PSNR的时候必须满足两张图像的size要完全一样!

import tensorflow as tf
 
def read_img(path):
	return tf.image.decode_image(tf.read_file(path))
 
def psnr(tf_img1, tf_img2):
	return tf.image.psnr(tf_img1, tf_img2, max_val=255)
 
def _main():
	t1 = read_img('t1.jpg')
	t2 = read_img('t2.jpg')
	with tf.Session() as sess:
		sess.run(tf.global_variables_initializer())
		y = sess.run(psnr(t1, t2))
		print(y)
 
if __name__ == '__main__':
    _main()

SSIM简介

SSIM是一种衡量两幅图片相似度的指标。
出处来自于2004年的一篇TIP,标题为:Image Quality Assessment: From Error Visibility to Structural Similarity 论文地址,与PSNR一样,SSIM也经常用作图像质量的评价。

先了解SSIM的输入
SSIM的输入就是两张图像,我们要得到其相似性的两张图像。其中一张是未经压缩的无失真图像(即ground truth),另一张就是你恢复出的图像。所以,SSIM可以作为super-resolution质量的指标。假设我们输入的两张图像分别是x和y,那么

α>0, β>0β>0,and γ>0γ>0. 式1是SSIM的数学定义,其中:

其中l(x, y)是亮度比较,c(x,y)是对比度比较,s(x,y)是结构比较μ**xμx和μ**yμy分别代表x,y的平均值,σ**xσx和σ**yσy分别代表x,y的标准差。σxyσxy代表x和y的协方差。而c1c1,c2c2,c3c3分别为常数,避免分母为0带来的系统错误。
在实际工程计算中,我们一般设定α=β=γ=1α=β=γ=1,以及c3=c2/2c3=c2/2,可以将SSIM简化为下:

总结

  1. SSIM具有对称性,即SSIM(x,y)=SSIM(y,x)
  2. SSIM是一个0到1之间的数,越大表示输出图像和无失真图像的差距越小,即图像质量越好。当两幅图像一模一样时,SSIM=1;

如PSNR一样,SSIM这种常用计算函数也被tensorflow收编了,我们只需在tf中调用ssim就可以了tf.image.ssim(x, y, 255)

源代码如下:

import numpy as np
def ssim(y_true , y_pred):
    u_true = np.mean(y_true)
    u_pred = np.mean(y_pred)
    var_true = np.var(y_true)
    var_pred = np.var(y_pred)
    std_true = np.sqrt(var_true)
    std_pred = np.sqrt(var_pred)
    c1 = np.square(0.01*7)
    c2 = np.square(0.03*7)
    ssim = (2 * u_true * u_pred + c1) * (2 * std_pred * std_true + c2)
    denom = (u_true ** 2 + u_pred ** 2 + c1) * (var_pred + var_true + c2)
    return ssim / denom

使用开源Pytorch图像质量评价包

转自PyTorch Image Quality Assessment

PIQA is not endorsed by Facebook, Inc.; PyTorch, the PyTorch logo and any related marks are trademarks of Facebook, Inc.

PyTorch Image Quality Assessment

The piqa package is a collection of measures and metrics for image quality assessment in various image processing tasks such as denoising, super-resolution, image interpolation, etc. It relies only on PyTorch and takes advantage of its efficiency and automatic differentiation.

PIQA is directly inspired from the piq project, but focuses on the conciseness, readability and understandability of its (sub-)modules, such that anyone can easily reuse and/or adapt them to its needs.

However, conciseness should never be at the expense of efficiency; PIQA's implementations are up to 3 times faster than those of other IQA PyTorch packages like kornia, piq and IQA-pytorch.

PIQA should be pronounced pika (like Pikachu ⚡️)

Installation

The piqa package is available on PyPI, which means it is installable with pip:

pip install piqa

Alternatively, if you need the latest features, you can install it using

pip install git+https://github.com/francois-rozet/piqa

or copy the package directly to your project, with

git clone https://github.com/francois-rozet/piqa
cp -R piqa/piqa <path/to/project>/piqa

Getting started

In piqa, each metric is associated to a class, child of torch.nn.Module, which has to be instantiated to evaluate the metric.

import torch

# PSNR
from piqa import PSNR

x = torch.rand(5, 3, 256, 256)
y = torch.rand(5, 3, 256, 256)

psnr = PSNR()
l = psnr(x, y)

# SSIM
from piqa import SSIM

x = torch.rand(5, 3, 256, 256, requires_grad=True).cuda()
y = torch.rand(5, 3, 256, 256).cuda()

ssim = SSIM().cuda()
l = 1 - ssim(x, y)
l.backward()

Like torch.nn built-in components, these classes are based on functional definitions of the metrics, which are less user-friendly, but more versatile.

import torch

from piqa.ssim import ssim
from piqa.utils.functional import gaussian_kernel

x = torch.rand(5, 3, 256, 256)
y = torch.rand(5, 3, 256, 256)

kernel = gaussian_kernel(11, sigma=1.5).repeat(3, 1, 1)

l = ssim(x, y, kernel=kernel, channel_avg=False)

For more information about PIQA's features, check out the documentation at francois-rozet.github.io/piqa/.

Metrics

Acronym Class Range Objective Year Metric
TV TV [0, ∞] / 1937 Total Variation
PSNR PSNR [0, ∞] max / Peak Signal-to-Noise Ratio
SSIM SSIM [0, 1] max 2004 Structural Similarity
MS-SSIM MS_SSIM [0, 1] max 2004 Multi-Scale Structural Similarity
LPIPS LPIPS [0, ∞] min 2018 Learned Perceptual Image Patch Similarity
GMSD GMSD [0, ∞] min 2013 Gradient Magnitude Similarity Deviation
MS-GMSD MS_GMSD [0, ∞] min 2017 Multi-Scale Gradient Magnitude Similarity Deviation
MDSI MDSI [0, ∞] min 2016 Mean Deviation Similarity Index
HaarPSI HaarPSI [0, 1] max 2018 Haar Perceptual Similarity Index
VSI VSI [0, 1] max 2014 Visual Saliency-based Index
FSIM FSIM [0, 1] max 2011 Feature Similarity

JIT

Most functional components of piqa support PyTorch's JIT, i.e. TorchScript, which is a way to create serializable and optimizable functions from PyTorch code.

By default, jitting is disabled for those components. To enable it, the PIQA_JIT environment variable has to be set to 1. To do so temporarily,

  • UNIX-like bash
export PIQA_JIT=1
  • Windows cmd
set PIQA_JIT=1
  • Microsoft PowerShell
$env:PIQA_JIT=1

Assert

PIQA uses type assertions to raise meaningful messages when an object-oriented component doesn't receive an input of the expected type. This feature eases a lot early prototyping and debugging, but it might hurt a little the performances.

If you need the absolute best performances, the assertions can be disabled with the Python flag -O. For example,

python -O your_awesome_code_using_piqa.py

Alternatively, you can disable PIQA's type assertions within your code with

from piqa.utils import set_debug
set_debug(False)
posted @ 2021-01-26 14:14  梁君牧  阅读(22574)  评论(0编辑  收藏  举报