首页 > 编程知识 正文

超分辨率中PSNR的计算与bicubic插值,高斯插值超分辨

时间:2023-05-05 18:20:04 阅读:184934 作者:2354

正确计算PSNR对于做超分辨率研究是很重要的,因为PSNR是被广泛使用的metric之一。同时bicubic插值算法也很重要,因为目前主流的有监督超分辨率算法中,需要构成HR-LR训练对,而这个对的构成方法需要使用到bicubic插值。PSNR的定义很简单,

M S E = 1 H × W ∑ i = 1 H ∑ j = 1 W ( X ( i , j ) − Y ( i , j ) ) 2 M S E=frac{1}{H times W} sum_{i=1}^{H} sum_{j=1}^{W}(X(i, j)-Y(i, j))^{2} MSE=H×W1​i=1∑H​j=1∑W​(X(i,j)−Y(i,j))2

P S N R = 10 log ⁡ 10 ( 25 5 2 M S E ) P S N R=10 log _{10}left(frac{255^{2}}{M S E}right) PSNR=10log10​(MSE2552​)

其中X和Y分别是GT图片和待测图片,值域为[0,255]。

但是当真正在python上用这个公式计算bicubic的PSNR时(因为bicubic的结果是能精确复现的,其他深度学习的算法不一定能精确复现),会发现计算出来的结果经常会有很大偏差。这是因为这2个原因:

1、使用的resize方法不正确。以下以Set5的bicubic_x2结果为例,结果应该为33.66,这个结果是用Matlab的imresize做bicubic插值(必须要在float16或float32的type下计算),还需要在线计算(即不能保存后读取再算,或者转type后再算)才能得到。如果使用的是python中的插值(不论用的是Opencv、Image还是skimage),都得不到这个结果。

2、使用的计算方法不正确,包括转换Y通道的时机和计算中间量的数据类型。

我研究的结果是参考SRCNN的Matlab代码http://mmlab.ie.cuhk.edu.hk/projects/SRCNN.html,实验证明Matlab代码是可以获得33.66这个结果的,并且在python上复现了计算PSNR的代码,验证后与matlab计算的结果一致(33.65,这是因为用bicubic插值得到的中间图像,是计算不出33.66的(在python和matlab上都不行),具体看流程图就很好理解了)

这里要感谢https://github.com/fatheral/matlab_imresize的工作,这份工作成功在python上复现了matlab版本的bicubic插值算法(别的是否一致我不确定)。但是我的实验表明,double版本的插值完全一致,但uint8版本的插值有些区别,不过正常计算PSNR的流程中不需要uint8版本的插值,也就没有影响了。

我的代码放在https://github.com/cyfwry/PSNR_metric,如有需要可以取用。

2020.12.21
最近的工作发现,matlab的imsize之前有些问题是没法确定的,比如是转成float16还是float32,除不除255,这些没法确定。诚然,这些操作会影响最后的计算结果,但是影响实在太小(不到0.01dB)导致没法确认采用哪个,所以索性喜欢用哪个就用哪个吧。SRCNN里是除255,转float16做的。
另外,还有个很奇怪的事。DIV2K官方提供的bicubic_4x数据集,它确实是用matlab上的imresize做出来的,但是它并没有转float16或float32,而是直接用uint8算的!(我对了各种做法输出的图像的总大小,只有这样做最终的结果才是一致的)

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。