写在前面:本博客仅作记录学习之用,部分图片来自网络,如需引用请注明出处,同时如有侵犯您的权益,请联系删除!
超分辨率是指将低分辨率图像通过算法提升其分辨率,使其看起来更加清晰、细腻。在计算机视觉领域,超分辨率技术应用广泛,包括图像处理、视频压缩、安防监控等。
为了进行超分辨率项目开发,需要配置相应的环境。一般来说,超分辨率算法需要依赖于深度学习框架和图像处理库等多个组件。
GCFSR是一种无需GAN先验的生成式超分辨率方法,旨在提高人脸图像的分辨率。该方法采用了Encoder-Generator架构,并设计了样式调制模块和特征调制模块。其中,样式调制模块用于生成逼真的面部细节,特征调制模块用于动态融合多级编码特征和生成特征,进而实现超分辨率。
相较于其他超分辨率方法,GCFSR的一个优点在于无需预训练的GAN模型,以及不需要设计额外的模块来利用GAN先验中的信息。此外,GCFSR还可以实现自适应调整不同强度的样式来生成不同的超分辨率结果,更具有灵活性。
GCFSR的源代码已在Github(GCFSR)上公开发布,并提供了相关论文、项目页面和演示。该方法为人脸超分辨率提供了一种新的思路,也为其他超分辨率领域的研究提供了借鉴和参考。
BasicSR是一款基于PyTorch框架开发的超分辨率(SR)和图像恢复模型库。它提供了大量预训练模型和用于训练新模型的代码和工具,以帮助研究人员和工程师高效地进行SR和图像恢复任务的研究和应用。
basicSR的优点包括:
多种超分辨率和图像恢复算法:basicSR支持多种流行的SR算法,如SRCNN、ESPCN、EDSR等,还提供了多种其他的图像恢复算法,例如去噪、去卷积等。
可扩展性:基于PyTorch框架的设计使得basicSR可以方便地进行扩展和自定义,用户可以按需添加自己的算法或改进现有算法。
高效性:basicSR实现了诸多加速技术,如混合精度训练、异步数据加载等,以在保持高精度的同时提高训练和推理效率。
丰富的文档和教程:在GitHub上,basicSR提供了详尽的文档和使用教程,指导用户如何使用库中的不同算法和API,并以图像超分辨率为例介绍了其基本原理和应用。
查看自身的cuda版本,很重要,否则算力框架不匹配:
nvcc --version
nvcc -V
或者利用torch
查看
import torch
print(torch.__version__) # 查看torch当前版本号
print(torch.version.cuda) # 编译当前版本的torch使用的cuda版本号
print(torch.cuda.is_available()) # 查看当前cuda是否可用于当前版本的Torch
还不会的参考这里 这个比较详细,应该可以帮到你。
建议去查询与之对应的pytorch版本:torch与cuda版本匹配网址
这里以10.2为例,选择其中cudatoolkit=10.2即可。千万别就看requirement中的torch版本,单独pip或者conda install torch==xxx,容易出现cudatoolkit与cuda不匹配的情况。
运行其中的命令就等着ok就好了。
哟,看着readme.md还简单,照着步骤走就行了。let us go!
无法推理只能倒回去看过程:
按照以上步骤是半可行的:
注意
:如果自行安装了torch就把requirement的中的torch去掉,避免版本变更。sm_xx代表NVIDIA GPU架构的编译选项,其中xx为两位数字。通常情况下,sm_xx与PyTorch版本之间并没有明确的匹配关系,而是与CUDA版本和GPU架构有关。一般来说,PyTorch版本需要与CUDA版本匹配,而CUDA版本需要与GPU架构匹配。需要注意的是,不同的GPU架构支持的CUDA版本可能存在差异,因此在选择GPU、CUDA和PyTorch版本时需要仔细考虑。如果您遇到了版本兼容性问题,可以尝试升级或降级相关的软件包
此时,参考上述安装对应的cuda版本有可能解决问题。
python basicsr/train.py -opt options/train_gcfsr_gan.yml
python basicsr/train.py -opt options/train_gcfsr_gan.yml -h
主要的函数,参考图中注释。主要包括了解析配置文件,断点训练,日志系统、tensorboard、以及创建模型进行训练。
主要使用到配置文件中:auto_resume 选项。
如果对这个BasicSR有想法,可以自己改哈。
主要使用到配置文件中:datasets、dataset_enlarge_ratio、batch_size_per_gpu、total_iter、num_gpu等选项。
左侧为配置文件,右侧为注册的对应名字类,主要是想说明配置文件要和使用的类名对应。配置的解释,见绿色注释。
膜拜Xintao大佬,有所参考,宣传BasicSR。
传统的OpenMMlab,需要__init__.py 中把写好的网络结构显式地import进来。每写一个新的网络结构,就要去更新 init.py,很繁琐。
因此在 BasicSR,约定凡是网络结构的文件都以 _arch.py 结尾,模型都以以_model.py结尾,数据集以 _dataset.py结尾
,然后python在import的时候,会自动扫描以 _arch.py、 _model.py结尾的脚本,自动把所有的符合命名的类都import进去。
这样一来,写网络结构本身、模型和修改配置文件,就改动三个文件就ok了,也就是下文的三步走。
动态实例化存在问题:
注册以解决上述问题:
注册借助于下面两个函数:
此处简单的示意了修改通道,具体修改还看自己的想法。
需要修改其中的通道。
self.final_linear = EqualLinear(参数要改)
此处简单示意了修改保存内容和非分布式验证方式。
基本上根据这三步走,只要能正确修改,就可以开始玄学炼丹了。
pip3 install ninja
\basicsr\ops\upfirdn2d\upfirdn2d.py
修改下列第一个语句为Ture train_pipeline(root_path)
File "basicsr/train.py", line 173, in train_pipeline
model.optimize_parameters(current_iter)
File "/home/tang/work/QXD/GCFSR/basicsr/models/model.py", line 222, in optimize_parameters
fake_pred = self.net_d(fake_img.detach())
File "/home/tang/work/Anaconda/env/sr-gan/lib/python3.7/site-packages/torch/nn/modules/module.py", line 550, in __call__
result = self.forward(*input, **kwargs)
File "/home/tang/work/QXD/GCFSR/basicsr/archs/arch.py", line 1006, in forward
out = self.conv_body(x)
RuntimeError: Calculated padded input size per channel: (2 x 2). Kernel size: (3 x 3). Kernel size can't be greater than actual input size
一看就是特征图小了,直接定位到下面的代码,为什么?因为to_rgb()
设置了upsample=True
是会上采样的,但是输出还是16x16,显然没有进入该循环。
for conv1, conv2, noise1, noise2, to_rgb in zip(self.style_convs[::2], self.style_convs[1::2], noise[1::2], noise[2::2], self.to_rgbs):
out = conv1(out, latent[:, i], noise=noise1)
out = conv2(out, latent[:, i + 1], noise=noise2)
skip = to_rgb(out, latent[:, i + 2], skip)
self.to_rgbs.append(ToRGB(out_channels, num_style_feat, upsample=True, resample_kernel=resample_kernel))
分析原因,zip函数能够把多个可迭代对象打包成一个元组构成的可迭代对象,但是却取决于其中最短的迭代对象,发现noise长度是0,因此不会进循环。解决办法就是把noise去掉。
for conv1, conv2, to_rgb in zip(self.style_convs[::2], self.style_convs[1::2], self.to_rgbs):
out = conv1(out, latent[:, i], noise=None)
out = conv2(out, latent[:, i + 1], noise=None, scale1=scales1[j], scale2=scales2[j], shift=shifts[j])
skip = to_rgb(out, latent[:, i + 2], skip)
或者另外的途径:
由下列图像发现,noise是none是会生成层数相等的none的列表,是可以实现进入循环的。
进一步,发现实际输入的noise是来之数据加载中的in_size,因此直接在数据处理后不返回in_size也可以实现相同的效果。
但是在val阶段会导致生成的图像尺寸还是16x16,在不使用val是可以这么做的,具体原因留给后面。
三步走后,顺顺利利的训练和保存了权重,本就打算测试下效果,没曾想加载不了,就是下图的错。
不仅不能加载,还多了给ema的键,没办法,打印下看看有些什么键值对。
net = torch.load(args.model_path)
for k in net.keys():
print(k)
#'params', 'params_ema'
确实,由参数和ema,因此只需要加载参数即可,像下面一样。
model.load_state_dict(torch.load(args.model_path, map_location=device)['params'], strict=True)
这样了不得不看下怎么保存的权重,果然是保存的问题,保存的不仅仅是网络参数还有ema的参数。
简单百度下:EMA(指数移动平均)这个方法对模型的参数做平均,以求提高测试指标并增加模型鲁棒。大概是为了断点训练把,不保存ema也能加载,影响的是ema的效果。
对于自己的数据集,无法直接引用别人论文结果,需要自己复现进行比较,极力推荐AutoDL,一个小时几毛,很良心。
欲尽善本文,因所视短浅,怎奈所书皆是瞽言蒭议。行文至此,诚向予助与余者致以谢意。