图像处理中常用的相似度评估指标

news2024/11/15 9:21:58

导读

有时候我们想要计算两张图片是否相似,而用来衡量两张图片相似度的算法也有很多,例如:RMSEPSNRSSIMUQISIFT以及深度学习等。这篇文章主要介绍,RMSEPSNRSSIMUQI这些指标的计算和应用,关于SIFT算法来计算图像的相似度在后面的文章中再进行介绍

影响这些算法的结果也有很多因素,图片的噪声平移缩放旋转裁剪透视变换等,都会影响到算法的最终结果,所以我们需要根据不同的应用场景来选择使用不同的算法

MSE和RMSE

MSE(mean squared error):图像像素值的平方误差
RMSE(root mean squared error):图像像素值的平方根误差

  • 缺点
  1. 对比两张图片的size必须要完全一致
  2. 对缩放、旋转、裁剪敏感
  • 优点
  1. 计算速度快
  2. 算法简单
  • 适应场景
  1. 视频中对比前后两帧的差别
  2. 计算图片的相似
  • 代码实现
def mean_squared_error(img1,img2):
    #判断两张图片的shape是否一致
    assert img1.shape == img2.shape,"images have different shape " \
                                    "{} and {}".format(img1.shape,img2.shape)
    #计算两张图像的MSE
    img_mse = np.mean((img1.astype(np.float64) - img2.astype(np.float64))**2)
    #将图像的MSE量化为相似度
    img_sim = img_mse / (255**2)
    return img_mse,1 - img_sim

def root_mean_squared_error(img1,img2):
    #判断两张图片的shape是否一致
    assert img1.shape == img2.shape,"images have different shape " \
                                    "{} and {}".format(img1.shape,img2.shape)
    #计算两张图像的MSE
    img_rmse = np.sqrt(np.mean((img1.astype(np.float64) - img2.astype(np.float64))**2))
    #将图像的MSE量化为相似度
    img_sim = img_rmse / 255
    return img_rmse,1 - img_sim

计算两张图片的MSERMSE
在这里插入图片描述

print(mean_squared_error(img1,img2))
#(10826.879833697936, 0.8334966576901509)
print(root_mean_squared_error(img1,img2))
#(104.05229374549096, 0.5919517892333688)

PSNR

PSNR(Peak Signal Noise Ratio)也叫峰值信噪比:为了衡量处理后图像的品质,我们经常会使用到PSNR来衡量程序的处理结果是否令人满意。它是原图像与被处理图像之间的均方误差相对于 ( 2 n − 1 ) 2 (2^n-1)^2 (2n1)2的对数值(信号最大值的平方,n是每个采样值的比特数),计算公式如下:
P S N R = 10 ∗ l o g 10 ( 2 n − 1 ) 2 M S E PSNR = 10 * log_{10}\frac{(2^n-1)^2}{MSE} PSNR=10log10MSE(2n1)2

  • 缺点
    PSNR的分数无法和人眼看到的品质完全一致

  • 优点
    算法简单,应用广泛

  • 适用场景
    用来评价画质客观量的测法,也可以用于图像相似的计算

  • 代码实现

def peak_signal_noise_ratio(img1,img2):
    #判断两张图片的size是否一致
    assert img1.shape == img2.shape,"images hava different shape " \
                                    "{} and {}".format(img1.shape,img2.shape)
    #获取数据类型所表示的最大值
    MAX = np.iinfo(img1.dtype).max
    #计算两张图片的MSE
    mse,_ = mean_squared_error(img1,img2)
    #计算两张图片的PSNR
    psnr = 10 * np.log10(MAX**2 / mse)

    return psnr


print(peak_signal_noise_ratio(img1,img2))
#49.24985796979349

:由于PSNR的取值范围在(0,inf),PSNR的值越大表示图像越相似。如果想要将PSNR指标量化为相似度,可以基于测试图片上设置一个最大的PSNR值,进行取最大操作来换算成相似度

SSIM

SSIM(structural similarity index)结构相似性:是一种用来衡量两张图像相似程度的指标。当两张图像其中有一张为无失真图像,另一张为失真后的图像,两张图像的结构相似性可以看做是失真图像的品质质量指标。结构相似性相对于峰值信噪比而言,结构相似性指标在图像品质的衡量上更能符合人眼对图像品质的判断

x x x y y y两个信号为例,结构相似性的计算公式如下:
S S I M ( x , y ) = ( l ( x , y ) ) α ( c ( x , y ) ) β ( s ( x , y ) ) γ l ( x , y ) = 2 μ x μ y + C 1 μ x 2 + μ y 2 + C 1 c ( x , y ) = 2 δ x δ y + C 2 δ x 2 + δ y 2 + C 2 s ( x , y ) = δ x y + C 3 δ x δ y + C 3 \begin{aligned} SSIM(x,y) &= (l(x,y))^\alpha(c(x,y))^\beta(s(x,y))^\gamma \\ l(x,y) &= \frac{2\mu_x\mu_y + C_1}{\mu_x^2+\mu_y^2+C_1} \\ c(x,y) &= \frac{2\delta_x\delta_y + C_2}{\delta_x^2+\delta_y^2+C_2}\\ s(x,y) &= \frac{\delta_{xy}+C_3}{\delta_x\delta_y+C_3} \end{aligned} SSIM(x,y)l(x,y)c(x,y)s(x,y)=(l(x,y))α(c(x,y))β(s(x,y))γ=μx2+μy2+C12μxμy+C1=δx2+δy2+C22δxδy+C2=δxδy+C3δxy+C3
上式中的 l ( x , y ) l(x,y) l(x,y)比较的是两个信号之间的亮度, c ( x , y ) c(x,y) c(x,y)比较的是两个信号的对比度, s ( x , y ) s(x,y) s(x,y)比较的是两个信号的结构,其中 α > 0 , β > 0 , γ > 0 \alpha > 0,\beta > 0,\gamma > 0 α>0β>0γ>0主要是用来调整 l ( x , y ) 、 c ( x , y ) 、 s ( x , y ) l(x,y)、c(x,y)、s(x,y) l(x,y)c(x,y)s(x,y)的重要性, μ x 和 μ y \mu_x和\mu_y μxμy表示的是信号的平均值, δ x 和 δ y \delta_x和\delta_y δxδy表示的是信号的标准差,而 δ x y \delta_{xy} δxy为信号的协方差, C 1 、 C 2 、 C 3 C_1、C_2、C_3 C1C2C3皆为常数,用来维持 l ( x , y ) 、 c ( x , y ) 、 s ( x , y ) l(x,y)、c(x,y)、s(x,y) l(x,y)c(x,y)s(x,y)的稳定,SSIM的值越大,表示两个信号之间的相似度越高

在计算图像结构相似性的时候,我们一般会将参数设为 α = β = γ = 1 以 及 C 3 = C 2 / 2 \alpha=\beta=\gamma=1以及C_3=C_2/2 α=β=γ=1C3=C2/2所以 S S I M SSIM 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\delta_{xy}+C_2))}{(\mu_x^2+\mu_y^2+C_1)(\delta_x^2+\delta_y^2+C_2)} SSIM(x,y)=(μx2+μy2+C1)(δx2+δy2+C2)(2μxμy+C1)(2δxy+C2))
通常在计算图像的 S S I M SSIM SSIM的时候,我们都会采用移动的filter来进行计算

  • 代码实现
from scipy import signal
from enum import Enum

def filter2(img,fltr,mode='same'):
    return signal.convolve2d(img, np.rot90(fltr,2), mode=mode)

def _get_sums(GT,P,win,mode='same'):
    mu1,mu2 = (filter2(GT,win,mode),filter2(P,win,mode))
    return mu1*mu1, mu2*mu2, mu1*mu2

def _get_sigmas(GT,P,win,mode='same',**kwargs):
    if 'sums' in kwargs:
        GT_sum_sq,P_sum_sq,GT_P_sum_mul = kwargs['sums']
    else:
        GT_sum_sq,P_sum_sq,GT_P_sum_mul = _get_sums(GT,P,win,mode)

    return filter2(GT*GT,win,mode)  - GT_sum_sq,\
            filter2(P*P,win,mode)  - P_sum_sq, \
            filter2(GT*P,win,mode) - GT_P_sum_mul

class Filter(Enum):
    UNIFORM = 0
    GAUSSIAN = 1

def fspecial(fltr,ws,**kwargs):
    if fltr == Filter.UNIFORM:
        return np.ones((ws,ws))/ ws**2
    elif fltr == Filter.GAUSSIAN:
        x, y = np.mgrid[-ws//2 + 1:ws//2 + 1, -ws//2 + 1:ws//2 + 1]
        g = np.exp(-((x**2 + y**2)/(2.0*kwargs['sigma']**2)))
        g[ g < np.finfo(g.dtype).eps*g.max() ] = 0
        assert g.shape == (ws,ws)
        den = g.sum()
        if den !=0:
            g/=den
        return g
    return None

def _ssim_single(GT, P, ws, C1, C2, fltr_specs, mode):
    win = fspecial(**fltr_specs)

    GT_sum_sq, P_sum_sq, GT_P_sum_mul = _get_sums(GT, P, win, mode)
    sigmaGT_sq, sigmaP_sq, sigmaGT_P = _get_sigmas(GT, P, win, mode, sums=(GT_sum_sq, P_sum_sq, GT_P_sum_mul))

    assert C1 > 0
    assert C2 > 0

    ssim_map = ((2 * GT_P_sum_mul + C1) * (2 * sigmaGT_P + C2)) / (
                (GT_sum_sq + P_sum_sq + C1) * (sigmaGT_sq + sigmaP_sq + C2))
    cs_map = (2 * sigmaGT_P + C2) / (sigmaGT_sq + sigmaP_sq + C2)

    return np.mean(ssim_map), np.mean(cs_map)

def ssim(GT,P,ws=11,K1=0.01,K2=0.03,MAX=None,fltr_specs=None,mode='valid'):
    if MAX is None:
        MAX = np.iinfo(GT.dtype).max

    assert GT.shape == P.shape, "Supplied images have different sizes " + \
                                str(GT.shape) + " and " + str(P.shape)

    if fltr_specs is None:
        fltr_specs=dict(fltr=Filter.UNIFORM,ws=ws)

    C1 = (K1*MAX)**2
    C2 = (K2*MAX)**2

    ssims = []
    css = []
    for i in range(GT.shape[2]):
        ssim,cs = _ssim_single(GT[:,:,i],P[:,:,i],ws,C1,C2,fltr_specs,mode)
        ssims.append(ssim)
        css.append(cs)
    return np.mean(ssims),np.mean(css)

img_sim,_ = ssim(img1,img2)
#0.9459787655432684

UQI

UQI(Universal Quality Image Index)也叫图像通用质量指标:它能够很容易的计算并且应用到各种图像处理的应用中,主要结合三个因素来计算,相关性的损失亮度失真对比度失真。尽管UQI指标是从数学的角度来定义的不是利用人类的视觉系统,但是通过各种各样的图像失真表明UQI与主观质量测量有着惊人的一致性

UQI指标的计算公式如下:
Q = 4 δ x y x ^ y ^ ( δ x 2 + δ y 2 ) [ ( x ^ ) 2 + ( y ^ ) 2 ] x ^ = 1 N ∑ i = 1 N x i y ^ = 1 N ∑ i = 1 N y i δ x 2 = 1 N − 1 ∑ i = 1 N ( x i − x ^ ) 2 δ y 2 = 1 N − 1 ∑ i = 1 N ( y i − y ^ ) 2 \begin{aligned} Q &= \frac{4\delta_{xy}\hat{x}\hat{y}}{(\delta^2_x+\delta^2_y)[(\hat{x})^2+(\hat{y})^2]} \\ \hat{x} &= \frac{1}{N}\sum_{i=1}^{N}x_i \\ \hat{y} &= \frac{1}{N}\sum_{i=1}^{N}y_i \\ \delta_{x}^2 &= \frac{1}{N - 1}\sum_{i=1}^{N}(x_i-\hat{x}) ^2\\ \delta_{y}^2 &= \frac{1}{N - 1}\sum_{i=1}^{N}(y_i - \hat{y})^2 \end{aligned} Qx^y^δx2δy2=(δx2+δy2)[(x^)2+(y^)2]4δxyx^y^=N1i=1Nxi=N1i=1Nyi=N11i=1N(xix^)2=N11i=1N(yiy^)2
Q的取值范围在[-1,1]之间

  • 代码实现
import numpy as np
from scipy.ndimage import uniform_filter

def _uqi_single(GT,P,ws):
    N = ws**2
    window = np.ones((ws,ws))

    GT_sq = GT*GT
    P_sq = P*P
    GT_P = GT*P

    GT_sum = uniform_filter(GT, ws)
    P_sum =  uniform_filter(P, ws)
    GT_sq_sum = uniform_filter(GT_sq, ws)
    P_sq_sum = uniform_filter(P_sq, ws)
    GT_P_sum = uniform_filter(GT_P, ws)

    GT_P_sum_mul = GT_sum*P_sum
    GT_P_sum_sq_sum_mul = GT_sum*GT_sum + P_sum*P_sum
    numerator = 4*(N*GT_P_sum - GT_P_sum_mul)*GT_P_sum_mul
    denominator1 = N*(GT_sq_sum + P_sq_sum) - GT_P_sum_sq_sum_mul
    denominator = denominator1*GT_P_sum_sq_sum_mul

    q_map = np.ones(denominator.shape)
    index = np.logical_and((denominator1 == 0) , (GT_P_sum_sq_sum_mul != 0))
    q_map[index] = 2*GT_P_sum_mul[index]/GT_P_sum_sq_sum_mul[index]
    index = (denominator != 0)
    q_map[index] = numerator[index]/denominator[index]

    s = int(np.round(ws/2))
    return np.mean(q_map[s:-s,s:-s])

def uqi (GT,P,ws=8):
    if len(GT.shape) == 2:
        GT = GT[:, :, np.newaxis]
        P = P[:, :, np.newaxis]

    GT = GT.astype(np.float64)
    P = P.astype(np.float64)
    return np.mean([_uqi_single(GT[:,:,i],P[:,:,i],ws) for i in range(GT.shape[2])])

总结

除了上面的图像相似度评估指标之外,Sewar还提供了很多其他的图像质量评估指标算法,例如:MS-SSIMERGASSCCRASESAMD_lambdaD_SQNRVIF以及PSNR-B

下面我们来对比一下一些常用指标在添加不同噪声的情况下,计算出来的相似度结果之间的差异
在这里插入图片描述
给图片添加噪声可以参考我的这篇文章对图像添加(高斯/椒盐/泊松/斑点)噪声

评估算法原图像高斯噪声高斯模糊泊松噪声椒盐噪声散斑噪声
MSE0.00548.6679.780.77885.1210826.88
RMSE0.0023.428.930.8829.75104.05
PSNRinf20.7429.1149.2518.667.79
SSIM1.000.250.940.990.450.06
UQI1.000.980.991.000.980.80
MS-SSIM1.00+0.00j0.76+0.00j0.98+0.00j1.00+0.00j0.86+0.00j0.32+0.00j
ERGAS0.008031.332322.77225.7911187.3326741.73
SCC0.890.080.170.480.350.02
RASE0.001158.13333.2532.211600.903814.14
SAM0.000.130.050.000.130.58
D_lambda0.000.020.000.000.030.20
VIFP1.000.230.490.930.440.06
PSNR-Binf20.7028.9349.59inf8.10

参考

  1. https://ece.uwaterloo.ca/~z70wang/publications/uqi.html
  2. https://github.com/andrewekhalel/sewar
  3. https://ece.uwaterloo.ca/~z70wang/publications/quality_2c.pdf

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1234789.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring-IOC-Spring6和JUnit5集成

1、父工程pom.xml <properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><spring.version>…

国产压力测试工具的主要作用

国产压力测试工具可以帮助软件开发和维护团队对系统进行全面的性能测试&#xff0c;以评估系统在高负载下的性能表现。以下是国产压力测试工具的主要作用&#xff1a; 性能评估&#xff1a;国产压力测试工具可以模拟多用户同时对系统进行访问和操作&#xff0c;通过对系统的响应…

SwiftUI 如何动态开始和停止播放永久重复(repeatForever)动画

0. 功能需求 在 SwiftUI 丰富多彩的动画世界中,我们有时希望可以随意开始和停止永久循环(repeatForever)的动画,不过这时往往会产生错误的动画“叠加”效果。 从上图可以看到:虽然我们希望密码输入框背景只在用户输入密码时才发生闪烁,但顶部的密码输入框随着不断输入其…

gitlab 实战

一.安装依赖 yum install -y curl policycoreutils-python openssh-server perl 二.安装gitlab yum install gitlab-jh-16.0.3-jh.0.el7.x86_64.rpm 三.修改下面的 vim /etc/gitlab/gitlab.rbexternal_url http://192.168.249.156 四.初始化 gitlab-ctl reconfigure 五.查看状…

三字经||无聊数了下三字经的字数

三字经总字数去除标点后1416个 该文章无技术含量&#xff0c;仅三字经原文&#xff0c;学技术的同学可以止步了 三字经&#xff08;原文&#xff09; 【作者】王应麟 【朝代】南宋 人之初&#xff0c;性本善。性相近&#xff0c;习相远。 苟不教&#xff0c;性乃迁。教之道&a…

c语言-数据结构-链式二叉树

目录 1、二叉树的概念及结构 2、二叉树的遍历概念 2.1 二叉树的前序遍历 2.2 二叉树的中序遍历 2.3 二叉树的后序遍历 2.4 二叉树的层序遍历 3、创建一颗二叉树 4、递归方法实现二叉树前、中、后遍历 4.1 实现前序遍历 4.2 实现中序遍历 4.3 实现后序遍历 5、…

从零开始的c语言日记day35——数据在内存中的储存

数据类型介绍 之前已经学了了一些基本的内置类型&#xff0c;以及空间大小。 类型的意义&#xff1a; 使用这个类型开辟内存空间的大小&#xff08;大小决定了使用范围&#xff09;。如何看待内存空间的视角 类型的基本归类 整形&#xff1a; 字符的本质是ASCLL码值&#x…

Java实现堆算法

堆是一种特殊的数据结构&#xff0c;它是一棵完全二叉树&#xff0c;且满足堆的性质&#xff1a;对于每个节点&#xff0c;它的值都不小于&#xff08;或不大于&#xff09;它的孩子节点的值。根节点的值就是堆中的最大值&#xff08;或最小值&#xff09;。 Java中提供了一个…

算法分析与设计课后练习22

设W(5,7,10,12,15,18,20)和M35&#xff0c;使用过程SUMOFSUB找出W种使得和数等于M的全部子集并画出所生成的部分状态空间树

Linux C 网络编程概述

网络编程 计算机网络概述分类网络体系结构通信协议通信流程网络通信帧格式以太网帧格式分析ARP 协议分析IP 数据报分析IP分类IP 分配子网掩码 TCP 段分析 TCP三次握手协议 ⭐TCP四次挥手协议 ⭐ TCP编程基于 TCP 客户端编程-步骤说明基于 TCP 服务器端编程-步骤说明基于 TCP 服…

TypeError: expected np.ndarray (got Tensor)解决办法

文章目录 一、错误展示二、错误分析三、解决办法四、其余解决办法总结 一、错误展示 二、错误分析 这个错误表示正在尝试将一个PyTorch的Tensor对象作为numpy的ndarray对象来使用。我们需要使用numpy的ndarray而不是PyTorch的Tensor。 三、解决办法 在我的程序中去掉这一行代…

Redis跳跃表

前言 跳跃表(skiplist)是一种有序数据结构&#xff0c;它通过在每一个节点中维持多个指向其他节点的指针&#xff0c;从而达到快速访问节点的目的。 跳跃表支持平均O(logN)&#xff0c;最坏O(N)&#xff0c;复杂度的节点查找&#xff0c;还可以通过顺序性来批量处理节点…

局域网文件共享神器:Landrop

文章目录 前言解决方案Landrop软件界面手机打开效果 软件操作 前言 平常为了方便传文件&#xff0c;我们都是使用微信或者QQ等聊天软件&#xff0c;互传文件。这样传输有两个问题&#xff1a; 必须登录微信或者QQ聊天软件。手机传电脑还有网页版微信&#xff0c;电脑传手机比…

鸿蒙4.0开发笔记之DevEco Studio启动时不直接打开原项目(二)

1、想要在DevEco Studio启动时不直接打开关闭前的那个项目&#xff0c;可以在设置中进行。 有两个位置可以进入“设置”&#xff0c;一个是左上角的File>Settings&#xff0c;二是右上方的设置图标。 2、进入Settings界面以后&#xff0c;选择Appearance&Behavior下面…

【C++】泛型编程 ⑨ ( 类模板的运算符重载 - 函数声明 和 函数实现 写在同一个类中 | 类模板 的 外部友元函数问题 )

文章目录 一、类模板 - 函数声明与函数实现分离1、函数声明与函数实现分离2、代码示例 - 函数声明与函数实现分离3、函数声明与函数实现分离 友元函数引入 二、普通类的运算符重载 - 函数声明 和 函数实现 写在同一个类中三、类模板的运算符重载 - 函数声明 和 函数实现 写在同…

AMEYA360:蔡司扫描电镜Sigma系列:扫描电子显微镜的用途原来这么多

扫描电子显微镜是一种全自动的、非破坏性的显微分析系统&#xff0c;可针对无机材料和部分有机材料&#xff0c;迅速提供在统计学上可靠且可重复的矿物学、岩相学和冶金学数据&#xff0c;在采矿业&#xff0c;可用于矿产勘查、矿石表征和选矿工艺优化&#xff0c;在石油和天然…

Oracle数据库笔记(一)

1.概述 Oracle版本 19c 在线迁移、自适应扫描、自适应数据共享11g 企业管理器、自动化诊断工具、自动化性能管理 Oracle特点 可用性强可扩展性强数据安全性强稳定性强 常见数据库 小 Access中 SQL Server、MySQL大 Oracle、DB2 2.数据、数据库、数据库管理系统、数据库系…

【项目管理】甘特图(1)——认识甘特图

哈喽&#xff0c;大家好&#xff0c;我是雷工&#xff01; 今天学习下甘特图的绘制&#xff0c;以下为学习笔记。 一、什么是甘特图 甘特图是可以直观展示项目进展随时间走势和联系的条状图。是一种常见的项目管理工具。 项目的时间用横轴表示&#xff0c;项目的进度用纵轴表…

vue diff算法原理以及v2v3的区别

diff算法简介 diff算法的目的是为了找到哪些节点发生了变化&#xff0c;哪些节点没有发生变化可以复用。如果用最传统的diff算法&#xff0c;如下图所示&#xff0c;每个节点都要遍历另一棵树上的所有节点做比较&#xff0c;这就是o(n^2)的复杂度&#xff0c;加上更新节点时的…

可视化大屏时代的到来:智慧城市管理的新思路

随着科技的不断发展&#xff0c;智能芯片作为一种新型的电子元件&#xff0c;被广泛应用于各个领域&#xff0c;其中智慧芯片可视化大屏是一种重要的应用形式。 一、智慧芯片可视化大屏的优势 智慧芯片可视化大屏是一种将智能芯片与大屏幕显示技术相结合的产品&#xff0c;山海…