图像/视频超分领域近期并无突破性的方法出现,故近期计划将图像/视频超分相关方法进行一次综述性汇总。计划从不同点出发对图像/视频超分进行一次“反思”之旅。本文是该旅程的第一站:图像降质过程。
尽管图像超分和视频超分在方法上或多或少会有一些关键性的区别,但是两者在训练数据对的制作方面其实并无非常大的区别。所以本文主要以图像超分为例进行介绍。
说到图像超分,大家可能会很自然的想到这样几个数据集:DIV2K,Set5,Set14等等。确实,这些数据集都是图像超分领域最常见的数据集。我们先来简单汇总一下图像/视频超分领域有哪些公开数据集。
Name | Phase |
---|---|
Set5 | test |
Set14 | test |
B100 | test |
Menga109 | test |
Urban100 | test |
General100 | test |
L20 | test |
DIV2K | train/val |
DIV8K | train/val |
Flickr2K | train |
DF2K(DIV2K Flickr2K) | train |
City100 | train/val |
DRealSR | train/val |
RealSR(V1, V2, V3) | train/val |
Aogra(声网) | train |
Vid4 | test |
SPMCs | test |
UDM10 | test |
MM522 | train |
REDS | train/val |
Vimeo | train/val |
Youku | train |
注:上面所列出的仅是图像/视频超分的常用数据集以及部分竞赛数据集,除此之外还有一些Real-World数据集。其中DIV2K当属图像超分领域应用最多的一个数据集,它也是目前图像超分最常用的一个训练数据集(部分模型会考虑采用DF2K进一步提升模型性能,比如AIM2020-Efficient SuperResolution中的方法都采用了DF2K进行模型训练);REDS与Vimeo是视频超分领域应用最多的两个训练数据集(REDS是NTIRE2019竞赛中引入的一个数据集);RealSR、DRealSR是两个真实场景采集的图像超分数据集(具体怎样构建的训练数据对后期有空会介绍一下)。
尽管有了上述数据集,那么训练数据对LR-HR是如何构建的呢?
原理
对于图像超分而言,LR图像的获取过程一般可以描述为:
其中,k表示降质模糊核(它有多种选择,比如双三次核、高斯核等),
表示下采样,n表示加性高斯白噪声。
可以看到上述降质过程包含模糊、下采样以及噪声,而图像超分则仅仅考虑了模糊核下采样。我们就来对可能的降质过程做一个简单的归纳,见下表。
类型 | 说明 |
---|---|
BI | bicubic-down |
BD | blur-down |
BN | bicubic-down noise |
DN | blur-down noise |
注:BI表示降质过程仅包含双三次下采样;BD表示通过高斯模糊下采样;BN表示双三次插值下采样 高斯白噪声;DN表示高斯模糊下采样 高斯白噪声。
在这四种降质类型中,BI与BD是最常见的两种降质类型,而针对BN和DN的研究相对较少。而针对BI与BD两种降质的研究则属BI更多。
BI实现
接下来,我们将简单的介绍一下上述四种降质类型是如何实现的。首先,我们来看一下BI。做CV的同学对Bicubic应该非常熟悉,可以轻松的采用OpenCV或者PIL等库图像的双三次插值。但是,这里大家需要特别注意:BI一般特指matlab中的imresize。OpenCV与MATLAB在imresize的实现上是有区别的:matlab中的imresize具有抗锯齿功能,而OpenCV中的resize则不具备上述功能。关于matlab如何制作数据,可以参考BasicSR。这里附上关键性代码。
代码语言:javascript复制sclae = 4
image_path = "butterfly.png"
image = imread(image_path)
image = im2double(image)
image = modcrop(image, scale)
imgLR = imresize(image, 1/scale, 'bicubic')
function image = modcrop(image, scale)
if size(img, 3) == 1
sz = size(img);
sz = sz - mod(sz, scale)
image = image(1:sz(1), 1:sz(2))
else
tmpsz = size(img);
sz = tmpsz(1:2)
sz = sz - mod(sz, scale)
image = image(1:sz(1), 1:sz(2))
end
end
也许有同学会说,都2020年了,谁还会用MATLAB啊,有没有Python版的呢?这里提供两个基于Pytorch与matlab相当的imresize。
- matlab_functiosn_verification
- bicubic_pytorch
但是,需要注意:尽管上述两个版本的imresize实现是参考MATLAB中的imresize进行的实现,但因为一些数据精度问题,最终的实现还是会有一点点的区别。区别有多大呢,见下表。
Accuracy
注:表中数据来自XinTao大佬的测试,笔者也对Diff进行了测试,指标一致;不过与测试机器的性能区别,算法的耗时存在部分出入。
从上述表中结果来看,如果要进行X4超分,强烈建议各位同学采用bicubic_pytorch中的实现,因为它还可以通过GPU进行加速(就是这么优秀);当然XinTao大佬提供的Pytorch实现更为精确(笔者就是资深受益者,哈哈)。
BD实现
上面介绍了BI的实现方法(matlab和python),这里我们将介绍BD的实现方法。
在图像超分领域,BD中的高斯模糊参数为:kernelsize=7,sigma=1.6。相关实现可以参考如下链接中的代码:Prepare_TrainData_HR_LR_BD.m。这里列出核心代码:
代码语言:javascript复制kernelsize = 7;
sigma = 1.6;
kernel = fspecial('gaussian', kernelsize, sigma)
sclae = 4
image_path = "butterfly.png"
image = imread(image_path)
image = im2double(image)
image = modcrop(image, scale)
blur = imfilter(image, kernel, 'replicate')
imgLR = imresize(blur, 1/scale, 'nearest')
在视频超分领域,BD中的高斯模糊参数为:kernelsize=13, sigma=1.6。相关实现可以参考如下链接中的代码:DUFDown(这里这里是采用Tesorflow进行的实现)。考虑到不少同学对于Tensorflow不熟悉,我们这里提供一版Pytorch实现(XinTao大佬提供)。
代码语言:javascript复制def DUF_downsample(x, scale=4):
"""Downsamping with Gaussian kernel used in the DUF official code
Args:
x (Tensor, [B, T, C, H, W]): frames to be downsampled.
scale (int): downsampling factor: 2 | 3 | 4.
"""
assert scale in [2, 3, 4], 'Scale [{}] is not supported'.format(scale)
def gkern(kernlen=13, nsig=1.6):
import scipy.ndimage.filters as fi
inp = np.zeros((kernlen, kernlen))
# set element at the middle to one, a dirac delta
inp[kernlen // 2, kernlen // 2] = 1
# gaussian-smooth the dirac, resulting in a gaussian filter mask
return fi.gaussian_filter(inp, nsig)
B, T, C, H, W = x.size()
x = x.view(-1, 1, H, W)
pad_w, pad_h = 6 scale * 2, 6 scale * 2 # 6 is the pad of the gaussian filter
r_h, r_w = 0, 0
if scale == 3:
r_h = 3 - (H % 3)
r_w = 3 - (W % 3)
x = F.pad(x, [pad_w, pad_w r_w, pad_h, pad_h r_h], 'reflect')
gaussian_filter = torch.from_numpy(gkern(13, 0.4 * scale)).type_as(x).unsqueeze(0).unsqueeze(0)
x = F.conv2d(x, gaussian_filter, stride=scale)
x = x[:, :, 2:-2, 2:-2]
x = x.view(B, T, C, x.size(2), x.size(3))
return x
BN/DN实现
接下来,我们将要介绍一下DN的实现。它是在BD的基础上添加额外的高斯白噪声,它是RDN所提出。RDN的官方代码中也提供了响应的matlab实现:Prepare_TrainData_HR_LR_DN。但不知为何这里的DN其实是BI Noise的实现,也就是应当是Noise。但无论如何,这里关键的是Noise的生成方式,看到code后,想必各位同学可以轻易根据改成所需要的code。这里列出关键性code。
代码语言:javascript复制sclae = 4;
sigma = 30; %噪声水平
image_path = "butterfly.png";
image = imread(image_path);
image = im2double(image);
image = modcrop(image, scale);
imgLR = imresize(image, 1/scale, 'bicubic');
imgLR = single(imgLR)
LRNoise = imgLR single(sigma * randn(size(imgLR)));
LRNoise = uint8(LRNoise)
上面所提供的代码为matlab代码,但相比BI,BD,这里的关键仅在于Noise的生成部分。大家可以采用Pytorch、Numpy以及Tensorflow等轻易实现。比如,Pytorch的参考实现:
代码语言:javascript复制noise = torch.randn(B,C,H,W).mul_(noise_level).float()
Others
上面介绍了BI、BD、BN以及BD降质原理以及实现代码。那么除了上述降质外,还有其他类型的吗?有的!但基本与上述降质大同小异,对此感兴趣的同学可以去看一下KAIR中实现的几种降质:SRMD, DPSR, USRNet。这里就不再进行过多的介绍。
注意事项
前面对图像/视频超分中的降质方案进行了简单的梳理与总结。有一点需要各位同学牢记在心:在进行方法对比时,其降质过程一定要相同,否则对比就会不公平。为什么这样说呢?见下表的结果对比。
Degradation | Method | Scale | Dataset | PSNR | SSIM |
---|---|---|---|---|---|
BI | RDN | X3 | Set5 | 34.71 | 0.9296 |
BD | RDN | X3 | Set5 | 34.58 | 0.9280 |
BI | RCAN | X3 | Set5 | 34.74 | 0.9299 |
BD | RCAN | X3 | Set5 | 34.70 | 0.9288 |
BI | TDAN | X4 | Vid4 | 26.24 | 0.7800 |
BD | TDAN | X4 | Vid4 | 26.58 | 0.8010 |
从上表可以看到:对于图像超分而言,BI与BD两种降质制作的数据训练的模型指标基本相当;而对于视频超分而言,BI与BD两种降质方式训练的模型的指标差别较大(0.34dB)。
所以研究视频超分的小伙伴一定要特别注意新方法的指标是在BD降质所得,还是BI降质所得。如果强制的将BD模型指标与BI模型指标进行对比,那么有点"贻笑大方"了。
参考
- KAIR
- RDN
- EDVR
- BasicSR
- matlab_functions_verification
- bicubic_pytorch
- VSR-DUF