Upload portable Low_light_rainy_new code export
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .gitattributes +1 -0
- CR.py +63 -0
- MIGRATION_README.md +82 -0
- README.md +31 -0
- RESTORMER_FGP_IMPROVEMENTS.md +556 -0
- basicsr/data/__init__.py +135 -0
- basicsr/data/data_sampler.py +56 -0
- basicsr/data/data_util.py +340 -0
- basicsr/data/ffhq_dataset.py +71 -0
- basicsr/data/meta_info/meta_info_DIV2K800sub_GT.txt +0 -0
- basicsr/data/meta_info/meta_info_REDS4_test_GT.txt +4 -0
- basicsr/data/meta_info/meta_info_REDS_GT.txt +270 -0
- basicsr/data/meta_info/meta_info_REDSofficial4_test_GT.txt +4 -0
- basicsr/data/meta_info/meta_info_REDSval_official_test_GT.txt +30 -0
- basicsr/data/meta_info/meta_info_Vimeo90K_test_GT.txt +0 -0
- basicsr/data/meta_info/meta_info_Vimeo90K_test_fast_GT.txt +1225 -0
- basicsr/data/meta_info/meta_info_Vimeo90K_test_medium_GT.txt +0 -0
- basicsr/data/meta_info/meta_info_Vimeo90K_test_slow_GT.txt +1613 -0
- basicsr/data/meta_info/meta_info_Vimeo90K_train_GT.txt +0 -0
- basicsr/data/paired_image_SR_LR_FullImage_Memory_dataset.py +296 -0
- basicsr/data/paired_image_SR_LR_dataset.py +301 -0
- basicsr/data/paired_image_dataset.py +135 -0
- basicsr/data/prefetch_dataloader.py +132 -0
- basicsr/data/reds_dataset.py +243 -0
- basicsr/data/single_image_dataset.py +73 -0
- basicsr/data/transforms.py +247 -0
- basicsr/data/video_test_dataset.py +331 -0
- basicsr/data/vimeo90k_dataset.py +136 -0
- basicsr/demo.py +62 -0
- basicsr/demo_ssr.py +119 -0
- basicsr/metrics/__init__.py +10 -0
- basicsr/metrics/fid.py +108 -0
- basicsr/metrics/metric_util.py +53 -0
- basicsr/metrics/niqe.py +211 -0
- basicsr/metrics/niqe_pris_params.npz +3 -0
- basicsr/metrics/psnr_ssim.py +358 -0
- basicsr/models/__init__.py +48 -0
- basicsr/models/archs/Baseline_arch.py +202 -0
- basicsr/models/archs/NAFNet_arch.py +176 -0
- basicsr/models/archs/NAFSSR_arch.py +170 -0
- basicsr/models/archs/__init__.py +52 -0
- basicsr/models/archs/arch_util.py +350 -0
- basicsr/models/archs/local_arch.py +104 -0
- basicsr/models/base_model.py +356 -0
- basicsr/models/image_restoration_model.py +413 -0
- basicsr/models/losses/SWT.py +428 -0
- basicsr/models/losses/__init__.py +11 -0
- basicsr/models/losses/loss_util.py +101 -0
- basicsr/models/losses/losses.py +116 -0
- basicsr/models/losses/swt_loss.py +194 -0
.gitattributes
CHANGED
|
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
{ABA2ACC4-E114-45f5-8D6D-C62E45F0A571}.png filter=lfs diff=lfs merge=lfs -text
|
CR.py
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch.nn as nn
|
| 2 |
+
import torch
|
| 3 |
+
from torch.nn import functional as F
|
| 4 |
+
import torch.nn.functional as fnn
|
| 5 |
+
from torch.autograd import Variable
|
| 6 |
+
import numpy as np
|
| 7 |
+
from torchvision import models
|
| 8 |
+
|
| 9 |
+
class Vgg19(torch.nn.Module):
|
| 10 |
+
def __init__(self, requires_grad=False):
|
| 11 |
+
super(Vgg19, self).__init__()
|
| 12 |
+
vgg_pretrained_features = models.vgg19(pretrained=True).features
|
| 13 |
+
self.slice1 = torch.nn.Sequential()
|
| 14 |
+
self.slice2 = torch.nn.Sequential()
|
| 15 |
+
self.slice3 = torch.nn.Sequential()
|
| 16 |
+
self.slice4 = torch.nn.Sequential()
|
| 17 |
+
self.slice5 = torch.nn.Sequential()
|
| 18 |
+
for x in range(2):
|
| 19 |
+
self.slice1.add_module(str(x), vgg_pretrained_features[x])
|
| 20 |
+
for x in range(2, 7):
|
| 21 |
+
self.slice2.add_module(str(x), vgg_pretrained_features[x])
|
| 22 |
+
for x in range(7, 12):
|
| 23 |
+
self.slice3.add_module(str(x), vgg_pretrained_features[x])
|
| 24 |
+
for x in range(12, 21):
|
| 25 |
+
self.slice4.add_module(str(x), vgg_pretrained_features[x])
|
| 26 |
+
for x in range(21, 30):
|
| 27 |
+
self.slice5.add_module(str(x), vgg_pretrained_features[x])
|
| 28 |
+
if not requires_grad:
|
| 29 |
+
for param in self.parameters():
|
| 30 |
+
param.requires_grad = False
|
| 31 |
+
|
| 32 |
+
def forward(self, X):
|
| 33 |
+
h_relu1 = self.slice1(X)
|
| 34 |
+
h_relu2 = self.slice2(h_relu1)
|
| 35 |
+
h_relu3 = self.slice3(h_relu2)
|
| 36 |
+
h_relu4 = self.slice4(h_relu3)
|
| 37 |
+
h_relu5 = self.slice5(h_relu4)
|
| 38 |
+
return [h_relu1, h_relu2, h_relu3, h_relu4, h_relu5]
|
| 39 |
+
|
| 40 |
+
class ContrastLoss(nn.Module):
|
| 41 |
+
def __init__(self, ablation=False):
|
| 42 |
+
|
| 43 |
+
super(ContrastLoss, self).__init__()
|
| 44 |
+
self.vgg = Vgg19().cuda()
|
| 45 |
+
self.l1 = nn.L1Loss()
|
| 46 |
+
self.weights = [1.0/32, 1.0/16, 1.0/8, 1.0/4, 1.0]
|
| 47 |
+
self.ab = ablation
|
| 48 |
+
|
| 49 |
+
def forward(self, a, p, n):
|
| 50 |
+
a_vgg, p_vgg, n_vgg = self.vgg(a), self.vgg(p), self.vgg(n)
|
| 51 |
+
loss = 0
|
| 52 |
+
|
| 53 |
+
d_ap, d_an = 0, 0
|
| 54 |
+
for i in range(len(a_vgg)):
|
| 55 |
+
d_ap = self.l1(a_vgg[i], p_vgg[i].detach())
|
| 56 |
+
if not self.ab:
|
| 57 |
+
d_an = self.l1(a_vgg[i], n_vgg[i].detach())
|
| 58 |
+
contrastive = d_ap / (d_an + 1e-7)
|
| 59 |
+
else:
|
| 60 |
+
contrastive = d_ap
|
| 61 |
+
|
| 62 |
+
loss += self.weights[i] * contrastive
|
| 63 |
+
return loss
|
MIGRATION_README.md
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Low Light Rainy Code Export
|
| 2 |
+
|
| 3 |
+
This folder is a portable code-only export of `Low_light_rainy_new`.
|
| 4 |
+
|
| 5 |
+
## Excluded
|
| 6 |
+
|
| 7 |
+
The following large/runtime folders were intentionally excluded:
|
| 8 |
+
|
| 9 |
+
- `dataset/`
|
| 10 |
+
- `checkpoint*/`
|
| 11 |
+
- `results/`
|
| 12 |
+
- Python caches
|
| 13 |
+
- `.pth`, `.zip`, `.log` files
|
| 14 |
+
|
| 15 |
+
## Included Core Code
|
| 16 |
+
|
| 17 |
+
Key files for the current restoration experiments:
|
| 18 |
+
|
| 19 |
+
- `train_restormer.py` - main trainer for baseline, v1, and v2.
|
| 20 |
+
- `restormer.py` - original Restormer backbone and existing variants.
|
| 21 |
+
- `net/restormer_lowlight_rain.py` - FGP-Restormer v1.
|
| 22 |
+
- `net/restormer_lowlight_rain_v2.py` - FGP-Restormer v2.
|
| 23 |
+
- `utils/inference_utils.py` - validation padding, crop, RGB PSNR, optional TTA.
|
| 24 |
+
- `run_restormer_fgp.sh` - v1 launch script.
|
| 25 |
+
- `run_restormer_fgp_v2.sh` - v2 launch script.
|
| 26 |
+
- `dataset_RGB_ori.py`, `data_RGB.py` - legacy data loaders.
|
| 27 |
+
- `dataset_rwjr10k.py`, `train_restormer_rwjr10k.py`, `train_restormer_rwjr10k_from_original.py` - RWJR-10K related code, if needed.
|
| 28 |
+
|
| 29 |
+
## Environment
|
| 30 |
+
|
| 31 |
+
The current `new` conda environment was exported to:
|
| 32 |
+
|
| 33 |
+
- `requirements_new.txt`
|
| 34 |
+
- `environment_new.yml`
|
| 35 |
+
|
| 36 |
+
Recommended setup on a new server:
|
| 37 |
+
|
| 38 |
+
```bash
|
| 39 |
+
conda env create -f environment_new.yml
|
| 40 |
+
conda activate new
|
| 41 |
+
```
|
| 42 |
+
|
| 43 |
+
If the environment name conflicts, edit the first line of `environment_new.yml`, or use pip inside your own environment:
|
| 44 |
+
|
| 45 |
+
```bash
|
| 46 |
+
python -m pip install -r requirements_new.txt
|
| 47 |
+
```
|
| 48 |
+
|
| 49 |
+
## Data Layout Expected by Current v1/v2 Scripts
|
| 50 |
+
|
| 51 |
+
Default low-light-rain training expects:
|
| 52 |
+
|
| 53 |
+
```text
|
| 54 |
+
dataset/train/syn+real/input
|
| 55 |
+
dataset/train/syn+real/target
|
| 56 |
+
dataset/test/input
|
| 57 |
+
dataset/test/target
|
| 58 |
+
```
|
| 59 |
+
|
| 60 |
+
The v1/v2 scripts do not include dataset files in this export. Copy datasets separately to the same relative locations or pass explicit paths:
|
| 61 |
+
|
| 62 |
+
```bash
|
| 63 |
+
python train_restormer.py \
|
| 64 |
+
--train_inp /path/to/input \
|
| 65 |
+
--train_tar /path/to/target \
|
| 66 |
+
--test_inp /path/to/test/input \
|
| 67 |
+
--test_tar /path/to/test/target
|
| 68 |
+
```
|
| 69 |
+
|
| 70 |
+
## Run v1
|
| 71 |
+
|
| 72 |
+
```bash
|
| 73 |
+
bash run_restormer_fgp.sh
|
| 74 |
+
```
|
| 75 |
+
|
| 76 |
+
## Run v2
|
| 77 |
+
|
| 78 |
+
```bash
|
| 79 |
+
bash run_restormer_fgp_v2.sh
|
| 80 |
+
```
|
| 81 |
+
|
| 82 |
+
Before running on a new server, update any `--resume` paths in the run scripts if checkpoints are not present.
|
README.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# [TCSVT] Dual Degradation Representation for Joint Deraining and Low-Light Enhancement in the Dark
|
| 2 |
+
|
| 3 |
+
### Xin Lin*, Jingtong Yue*, Sixian Ding, Chao Ren, Lu Qi and Ming-Hsuan Yang
|
| 4 |
+
|
| 5 |
+
[]([https://arxiv.org/pdf/2308.06776.pdf](https://arxiv.org/pdf/2305.03997))
|
| 6 |
+
|
| 7 |
+

|
| 8 |
+
|
| 9 |
+
## Abstract
|
| 10 |
+
Rain in the dark poses a significant challenge to deploying real-world applications such as autonomous driving, surveillance systems, and night photography. Existing low-light enhancement or deraining methods struggle to brighten low-light conditions and remove rain simultaneously. Additionally, cascade approaches like ``deraining followed by low-light enhancement'' or the reverse often result in problematic rain patterns or overly blurred and overexposed images. To address these challenges, we introduce an end-to-end model called L$^{2}$RIRNet, designed to manage both low-light enhancement and deraining in real-world settings. Our model features two main components: a Dual Degradation Representation Network (DDR-Net) and a Restoration Network. The DDR-Net independently learns degradation representations for luminance effects in dark areas and rain patterns in light areas, employing dual degradation loss to guide the training process. The Restoration Network restores the degraded image using a Fourier Detail Guidance (FDG) module, which leverages near-rainless detailed images, focusing on texture details in frequency and spatial domains to inform the restoration process. Furthermore, we contribute a dataset containing both synthetic and real-world low-light-rainy images. Extensive experiments demonstrate that our L$^{2}$RIRNet performs favorably against existing methods in both synthetic and complex real-world scenarios.
|
| 11 |
+
|
| 12 |
+
## Dataset:
|
| 13 |
+
|
| 14 |
+
Baidu: https://pan.baidu.com/s/1yoEKRjimBlfecSMSx7uPQg 5atk
|
| 15 |
+
|
| 16 |
+
Huggingface: https://huggingface.co/datasets/linxin020826/low_light_rainy_dataset/tree/main
|
| 17 |
+
|
| 18 |
+
## Requirements
|
| 19 |
+
|
| 20 |
+
Our experiments are done with:
|
| 21 |
+
|
| 22 |
+
- Python 3.7.13
|
| 23 |
+
- PyTorch 1.13.0
|
| 24 |
+
- numpy 1.21.5
|
| 25 |
+
- opencv 4.6.0
|
| 26 |
+
- scikit-image 0.19.3
|
| 27 |
+
|
| 28 |
+
## This is the Trasformer-based version.
|
| 29 |
+
|
| 30 |
+
## Contact
|
| 31 |
+
If you have any questions, please contact linxin@stu.scu.edu.cn
|
RESTORMER_FGP_IMPROVEMENTS.md
ADDED
|
@@ -0,0 +1,556 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Restormer FGP 改进说明
|
| 2 |
+
|
| 3 |
+
本文档总结当前低光照去雨任务中,基于原始 Restormer baseline 所做的网络、训练、验证和日志保存改进。
|
| 4 |
+
|
| 5 |
+
## 1. 总体变化
|
| 6 |
+
|
| 7 |
+
原始版本:
|
| 8 |
+
|
| 9 |
+
```text
|
| 10 |
+
Restormer
|
| 11 |
+
RGB input
|
| 12 |
+
-> Restormer Encoder-Decoder
|
| 13 |
+
-> RGB output
|
| 14 |
+
Loss: L1
|
| 15 |
+
Val: 每个 epoch 测试
|
| 16 |
+
Checkpoint: 每个 epoch 保存
|
| 17 |
+
```
|
| 18 |
+
|
| 19 |
+
当前改进版:
|
| 20 |
+
|
| 21 |
+
```text
|
| 22 |
+
RestormerLowLightRain / FGP-Restormer
|
| 23 |
+
RGB input
|
| 24 |
+
-> illumination / structure / frequency prior extraction
|
| 25 |
+
-> multi-scale prior encoder
|
| 26 |
+
-> soft/hard mixture-of-frequency experts
|
| 27 |
+
-> global-local degradation router
|
| 28 |
+
-> Restormer Encoder-Decoder with multi-scale prior fusion
|
| 29 |
+
-> RGB output
|
| 30 |
+
Loss: Charbonnier + Edge + FFT
|
| 31 |
+
Val: 每 5 epoch 测试
|
| 32 |
+
Checkpoint: 每 5 epoch 保存,best 单独保存
|
| 33 |
+
Metrics: metrics.csv 逐 epoch 记录
|
| 34 |
+
```
|
| 35 |
+
|
| 36 |
+
对应核心文件:
|
| 37 |
+
|
| 38 |
+
- `net/restormer_lowlight_rain.py`:网络结构改进。
|
| 39 |
+
- `train_restormer.py`:训练、loss、EMA、验证、日志保存。
|
| 40 |
+
- `utils/inference_utils.py`:验证阶段 padding、crop、PSNR、TTA。
|
| 41 |
+
- `run_restormer_fgp.sh`:当前 FGP 版本启动脚本。
|
| 42 |
+
|
| 43 |
+
## 2. 网络结构改进
|
| 44 |
+
|
| 45 |
+
### 2.1 从原始 Restormer 改到 FGP-Restormer
|
| 46 |
+
|
| 47 |
+
从:
|
| 48 |
+
|
| 49 |
+
```text
|
| 50 |
+
Restormer()
|
| 51 |
+
```
|
| 52 |
+
|
| 53 |
+
改到:
|
| 54 |
+
|
| 55 |
+
```text
|
| 56 |
+
RestormerLowLightRain()
|
| 57 |
+
```
|
| 58 |
+
|
| 59 |
+
训练入口中通过参数选择:
|
| 60 |
+
|
| 61 |
+
```bash
|
| 62 |
+
--model fgp_restormer
|
| 63 |
+
```
|
| 64 |
+
|
| 65 |
+
对应代码位置:
|
| 66 |
+
|
| 67 |
+
```text
|
| 68 |
+
train_restormer.py
|
| 69 |
+
build_model()
|
| 70 |
+
```
|
| 71 |
+
|
| 72 |
+
原始 Restormer 只使用 RGB 图像本身作为输入特征,当前版本在 Restormer 主干之外增加了一个先验分支,用于显式建模低光照和雨纹退化。
|
| 73 |
+
|
| 74 |
+
## 3. 先验提取改进
|
| 75 |
+
|
| 76 |
+
### 3.1 从单纯 RGB 输入改到五类退化先验
|
| 77 |
+
|
| 78 |
+
从:
|
| 79 |
+
|
| 80 |
+
```text
|
| 81 |
+
RGB input only
|
| 82 |
+
```
|
| 83 |
+
|
| 84 |
+
改到:
|
| 85 |
+
|
| 86 |
+
```text
|
| 87 |
+
RGB input
|
| 88 |
+
-> luminance
|
| 89 |
+
-> darkness
|
| 90 |
+
-> high-frequency response
|
| 91 |
+
-> structure edge response
|
| 92 |
+
-> rain residual
|
| 93 |
+
```
|
| 94 |
+
|
| 95 |
+
对应模块:
|
| 96 |
+
|
| 97 |
+
```text
|
| 98 |
+
net/restormer_lowlight_rain.py
|
| 99 |
+
PriorMapExtractor
|
| 100 |
+
```
|
| 101 |
+
|
| 102 |
+
具体五类先验:
|
| 103 |
+
|
| 104 |
+
| 先验 | 作用 |
|
| 105 |
+
|---|---|
|
| 106 |
+
| `luminance` | 表示亮度分布,用于低光照恢复 |
|
| 107 |
+
| `darkness` | 表示暗区域强度,引导曝光/照明增强 |
|
| 108 |
+
| `high` | Laplacian 高频响应,用于捕捉雨纹和细节 |
|
| 109 |
+
| `structure` | Sobel 边缘结构,用于保护物体轮廓 |
|
| 110 |
+
| `rain_residual` | `luminance - low_frequency` 的正残差,用于突出局部雨纹/亮 streak |
|
| 111 |
+
|
| 112 |
+
原始 Restormer 没有显式区分低频照明和高频雨纹;当前版本把低光和去雨拆成不同先验,更符合低光照去雨的退化特性。
|
| 113 |
+
|
| 114 |
+
## 4. 多尺度先验编码
|
| 115 |
+
|
| 116 |
+
### 4.1 从无先验分支改到 MultiPriorEncoder
|
| 117 |
+
|
| 118 |
+
从:
|
| 119 |
+
|
| 120 |
+
```text
|
| 121 |
+
RGB -> patch_embed -> encoder
|
| 122 |
+
```
|
| 123 |
+
|
| 124 |
+
改到:
|
| 125 |
+
|
| 126 |
+
```text
|
| 127 |
+
RGB -> PriorMapExtractor -> MultiPriorEncoder
|
| 128 |
+
-> prior_1 H x W
|
| 129 |
+
-> prior_2 H/2 x W/2
|
| 130 |
+
-> prior_3 H/4 x W/4
|
| 131 |
+
-> prior_4 H/8 x W/8
|
| 132 |
+
```
|
| 133 |
+
|
| 134 |
+
对应模块:
|
| 135 |
+
|
| 136 |
+
```text
|
| 137 |
+
net/restormer_lowlight_rain.py
|
| 138 |
+
MultiPriorEncoder
|
| 139 |
+
```
|
| 140 |
+
|
| 141 |
+
这让先验可以在 Restormer 的 4 个 encoder scale 上逐层注入,而不是只在输入层简单拼接。
|
| 142 |
+
|
| 143 |
+
## 5. 频率专家 MoE 改进
|
| 144 |
+
|
| 145 |
+
### 5.1 从单一特征变换改到 Mixture-of-Frequency Experts
|
| 146 |
+
|
| 147 |
+
从:
|
| 148 |
+
|
| 149 |
+
```text
|
| 150 |
+
main feature -> conv/attention -> output feature
|
| 151 |
+
```
|
| 152 |
+
|
| 153 |
+
改到:
|
| 154 |
+
|
| 155 |
+
```text
|
| 156 |
+
main feature
|
| 157 |
+
-> low-frequency expert
|
| 158 |
+
-> high-frequency expert
|
| 159 |
+
-> structure expert
|
| 160 |
+
-> router selects / blends experts
|
| 161 |
+
-> expert feature
|
| 162 |
+
```
|
| 163 |
+
|
| 164 |
+
对应模块:
|
| 165 |
+
|
| 166 |
+
```text
|
| 167 |
+
net/restormer_lowlight_rain.py
|
| 168 |
+
FrequencyExpertMixer
|
| 169 |
+
```
|
| 170 |
+
|
| 171 |
+
三个专家分别负责:
|
| 172 |
+
|
| 173 |
+
| Expert | 作用 |
|
| 174 |
+
|---|---|
|
| 175 |
+
| Low-frequency expert | 处理低光照、曝光、照明不均 |
|
| 176 |
+
| High-frequency expert | 处理雨纹、高频退化、细节恢复 |
|
| 177 |
+
| Structure expert | 处理边缘、轮廓、结构保持 |
|
| 178 |
+
|
| 179 |
+
### 5.2 从统一 soft 路由改到浅层 soft + 深层 hard 路由
|
| 180 |
+
|
| 181 |
+
从:
|
| 182 |
+
|
| 183 |
+
```text
|
| 184 |
+
所有层使用同一种融合方式
|
| 185 |
+
```
|
| 186 |
+
|
| 187 |
+
改到:
|
| 188 |
+
|
| 189 |
+
```text
|
| 190 |
+
浅层 encoder: soft expert routing
|
| 191 |
+
深层 encoder / latent: hard expert routing
|
| 192 |
+
```
|
| 193 |
+
|
| 194 |
+
对应代码:
|
| 195 |
+
|
| 196 |
+
```text
|
| 197 |
+
RestormerLowLightRain.__init__()
|
| 198 |
+
|
| 199 |
+
fuse1 = FrequencyPriorFusion(..., hard_expert=False)
|
| 200 |
+
fuse2 = FrequencyPriorFusion(..., hard_expert=False)
|
| 201 |
+
fuse3 = FrequencyPriorFusion(..., hard_expert=True)
|
| 202 |
+
fuse4 = FrequencyPriorFusion(..., hard_expert=True)
|
| 203 |
+
```
|
| 204 |
+
|
| 205 |
+
设计动机:
|
| 206 |
+
|
| 207 |
+
- 浅层特征保留更多低级纹理和退化线索,适合 soft routing。
|
| 208 |
+
- 深层特征更接近语义和重建决策,适合 hard routing 强化专家分工。
|
| 209 |
+
|
| 210 |
+
这个设计参考了近期 all-in-one restoration / adverse weather restoration 中的 MoE routing 思路。
|
| 211 |
+
|
| 212 |
+
## 6. Global-Local Router 改进
|
| 213 |
+
|
| 214 |
+
### 6.1 从普通 concat fusion 改到全局-局部动态路由
|
| 215 |
+
|
| 216 |
+
从:
|
| 217 |
+
|
| 218 |
+
```text
|
| 219 |
+
concat(main_feat, prior_feat) -> conv -> residual add
|
| 220 |
+
```
|
| 221 |
+
|
| 222 |
+
改到:
|
| 223 |
+
|
| 224 |
+
```text
|
| 225 |
+
main_feat + prior_feat
|
| 226 |
+
-> global degradation router -> channel gate
|
| 227 |
+
-> local weather/texture router -> spatial mask
|
| 228 |
+
-> global-local gate
|
| 229 |
+
-> gated prior fusion
|
| 230 |
+
```
|
| 231 |
+
|
| 232 |
+
对应模块:
|
| 233 |
+
|
| 234 |
+
```text
|
| 235 |
+
net/restormer_lowlight_rain.py
|
| 236 |
+
GlobalLocalRouter
|
| 237 |
+
FrequencyPriorFusion
|
| 238 |
+
```
|
| 239 |
+
|
| 240 |
+
其中:
|
| 241 |
+
|
| 242 |
+
- `global_router` 通过全局平均池化感知整图退化类型,例如整体低光、整体雨强。
|
| 243 |
+
- `local_router` 通过卷积生成局部空间 mask,关注局部雨纹、边缘、暗区。
|
| 244 |
+
|
| 245 |
+
这样可以同时处理:
|
| 246 |
+
|
| 247 |
+
- 全局低光照问题。
|
| 248 |
+
- 局部雨纹/高频 streak。
|
| 249 |
+
- 结构边缘恢复。
|
| 250 |
+
|
| 251 |
+
## 7. 多尺度融合方式
|
| 252 |
+
|
| 253 |
+
### 7.1 从 Restormer 原始 encoder 改到 encoder 每层注入先验
|
| 254 |
+
|
| 255 |
+
从:
|
| 256 |
+
|
| 257 |
+
```text
|
| 258 |
+
out_enc_level1 = encoder_level1(inp_enc_level1)
|
| 259 |
+
out_enc_level2 = encoder_level2(inp_enc_level2)
|
| 260 |
+
out_enc_level3 = encoder_level3(inp_enc_level3)
|
| 261 |
+
latent = latent(inp_enc_level4)
|
| 262 |
+
```
|
| 263 |
+
|
| 264 |
+
改到:
|
| 265 |
+
|
| 266 |
+
```text
|
| 267 |
+
out_enc_level1 = encoder_level1(inp_enc_level1)
|
| 268 |
+
out_enc_level1 = fuse1(out_enc_level1, prior_1)
|
| 269 |
+
|
| 270 |
+
out_enc_level2 = encoder_level2(inp_enc_level2)
|
| 271 |
+
out_enc_level2 = fuse2(out_enc_level2, prior_2)
|
| 272 |
+
|
| 273 |
+
out_enc_level3 = encoder_level3(inp_enc_level3)
|
| 274 |
+
out_enc_level3 = fuse3(out_enc_level3, prior_3)
|
| 275 |
+
|
| 276 |
+
latent = latent(inp_enc_level4)
|
| 277 |
+
latent = fuse4(latent, prior_4)
|
| 278 |
+
```
|
| 279 |
+
|
| 280 |
+
这样主干仍然是 Restormer,但每个 scale 都受到低光/雨纹/结构先验引导。
|
| 281 |
+
|
| 282 |
+
## 8. 训练数据改进
|
| 283 |
+
|
| 284 |
+
### 8.1 从依赖旧 DataLoader 改到显式 paired dataset
|
| 285 |
+
|
| 286 |
+
从:
|
| 287 |
+
|
| 288 |
+
```text
|
| 289 |
+
get_training_data(opt.TRAINING.TRAIN_DIR, ...)
|
| 290 |
+
```
|
| 291 |
+
|
| 292 |
+
改到:
|
| 293 |
+
|
| 294 |
+
```text
|
| 295 |
+
PairedPatchDataset(
|
| 296 |
+
train_inp = ./dataset/train/syn+real/input,
|
| 297 |
+
train_tar = ./dataset/train/syn+real/target
|
| 298 |
+
)
|
| 299 |
+
```
|
| 300 |
+
|
| 301 |
+
对应代码:
|
| 302 |
+
|
| 303 |
+
```text
|
| 304 |
+
train_restormer.py
|
| 305 |
+
PairedPatchDataset
|
| 306 |
+
```
|
| 307 |
+
|
| 308 |
+
当前训练集明确为:
|
| 309 |
+
|
| 310 |
+
```text
|
| 311 |
+
/media/home/songmeixi_insta360.com/Low_light_rainy_new/dataset/train/syn+real/input
|
| 312 |
+
->
|
| 313 |
+
/media/home/songmeixi_insta360.com/Low_light_rainy_new/dataset/train/syn+real/target
|
| 314 |
+
```
|
| 315 |
+
|
| 316 |
+
不使用:
|
| 317 |
+
|
| 318 |
+
```text
|
| 319 |
+
dataset/train/syn+real/target_smoke
|
| 320 |
+
```
|
| 321 |
+
|
| 322 |
+
这样可以避免 smoke 任务和低光照去雨任务混杂。
|
| 323 |
+
|
| 324 |
+
## 9. Loss 改进
|
| 325 |
+
|
| 326 |
+
### 9.1 从 L1 Loss 改到 Charbonnier + Edge + FFT Loss
|
| 327 |
+
|
| 328 |
+
从:
|
| 329 |
+
|
| 330 |
+
```text
|
| 331 |
+
loss = L1(output, target)
|
| 332 |
+
```
|
| 333 |
+
|
| 334 |
+
改到:
|
| 335 |
+
|
| 336 |
+
```text
|
| 337 |
+
loss = Charbonnier(output, target)
|
| 338 |
+
+ edge_weight * L1(edge(output), edge(target))
|
| 339 |
+
+ fft_weight * L1(FFT_amp(output), FFT_amp(target))
|
| 340 |
+
```
|
| 341 |
+
|
| 342 |
+
对应代码:
|
| 343 |
+
|
| 344 |
+
```text
|
| 345 |
+
train_restormer.py
|
| 346 |
+
RestorationLoss
|
| 347 |
+
```
|
| 348 |
+
|
| 349 |
+
启动参数:
|
| 350 |
+
|
| 351 |
+
```bash
|
| 352 |
+
--loss_mode charbonnier_edge_fft
|
| 353 |
+
```
|
| 354 |
+
|
| 355 |
+
各项作用:
|
| 356 |
+
|
| 357 |
+
| Loss | 作用 |
|
| 358 |
+
|---|---|
|
| 359 |
+
| Charbonnier | 比 L1 更平滑,常用于图像复原 |
|
| 360 |
+
| Edge loss | 保持边缘和结构,减少去雨后的模糊 |
|
| 361 |
+
| FFT loss | 约束频率幅度,提升高频细节和雨纹去除一致性 |
|
| 362 |
+
|
| 363 |
+
## 10. EMA 改进
|
| 364 |
+
|
| 365 |
+
### 10.1 从直接验证当前权重改到 EMA 权重验证
|
| 366 |
+
|
| 367 |
+
从:
|
| 368 |
+
|
| 369 |
+
```text
|
| 370 |
+
validate(model)
|
| 371 |
+
```
|
| 372 |
+
|
| 373 |
+
改到:
|
| 374 |
+
|
| 375 |
+
```text
|
| 376 |
+
ema.update(model)
|
| 377 |
+
validate(ema_model)
|
| 378 |
+
```
|
| 379 |
+
|
| 380 |
+
对应代码:
|
| 381 |
+
|
| 382 |
+
```text
|
| 383 |
+
train_restormer.py
|
| 384 |
+
ModelEma
|
| 385 |
+
```
|
| 386 |
+
|
| 387 |
+
启动参数:
|
| 388 |
+
|
| 389 |
+
```bash
|
| 390 |
+
--use_ema
|
| 391 |
+
```
|
| 392 |
+
|
| 393 |
+
EMA 可以降低训练震荡,让验证 PSNR 更稳定。
|
| 394 |
+
|
| 395 |
+
## 11. 验证协议改进
|
| 396 |
+
|
| 397 |
+
### 11.1 从直接整图推理改到 factor-8 padding + crop
|
| 398 |
+
|
| 399 |
+
从:
|
| 400 |
+
|
| 401 |
+
```text
|
| 402 |
+
output = model(input)
|
| 403 |
+
psnr = PSNR(output, target)
|
| 404 |
+
```
|
| 405 |
+
|
| 406 |
+
改到:
|
| 407 |
+
|
| 408 |
+
```text
|
| 409 |
+
padded_input = pad_to_factor(input, factor=8)
|
| 410 |
+
output = model(padded_input)
|
| 411 |
+
output = crop_to_original_size(output)
|
| 412 |
+
output = clamp(output, 0, 1)
|
| 413 |
+
psnr = RGB_PSNR(output, target)
|
| 414 |
+
```
|
| 415 |
+
|
| 416 |
+
对应代码:
|
| 417 |
+
|
| 418 |
+
```text
|
| 419 |
+
utils/inference_utils.py
|
| 420 |
+
pad_to_factor
|
| 421 |
+
crop_to_size
|
| 422 |
+
run_model
|
| 423 |
+
batch_rgb_psnr
|
| 424 |
+
```
|
| 425 |
+
|
| 426 |
+
Restormer 有多次 downsample/upsample,factor-8 padding 可以避免尺寸不能被 8 整除时的潜在问题。
|
| 427 |
+
|
| 428 |
+
### 11.2 从每个 epoch 测试改到每 5 epoch 测试
|
| 429 |
+
|
| 430 |
+
从:
|
| 431 |
+
|
| 432 |
+
```bash
|
| 433 |
+
--val_every 1
|
| 434 |
+
```
|
| 435 |
+
|
| 436 |
+
改到:
|
| 437 |
+
|
| 438 |
+
```bash
|
| 439 |
+
--val_every 5
|
| 440 |
+
```
|
| 441 |
+
|
| 442 |
+
这样减少测试时间开销,适合长时间训练。
|
| 443 |
+
|
| 444 |
+
## 12. Checkpoint 保存改进
|
| 445 |
+
|
| 446 |
+
### 12.1 从每个 epoch 保存改到每 5 epoch 保存
|
| 447 |
+
|
| 448 |
+
从:
|
| 449 |
+
|
| 450 |
+
```text
|
| 451 |
+
model_1.pth
|
| 452 |
+
model_2.pth
|
| 453 |
+
model_3.pth
|
| 454 |
+
...
|
| 455 |
+
```
|
| 456 |
+
|
| 457 |
+
改到:
|
| 458 |
+
|
| 459 |
+
```text
|
| 460 |
+
model_5.pth
|
| 461 |
+
model_10.pth
|
| 462 |
+
model_15.pth
|
| 463 |
+
...
|
| 464 |
+
model_best.pth
|
| 465 |
+
```
|
| 466 |
+
|
| 467 |
+
对应参数:
|
| 468 |
+
|
| 469 |
+
```bash
|
| 470 |
+
--save_every 5
|
| 471 |
+
```
|
| 472 |
+
|
| 473 |
+
说明:
|
| 474 |
+
|
| 475 |
+
- `model_{epoch}.pth`:每 5 个 epoch 保存一次。
|
| 476 |
+
- `model_best.pth`:只要验证 PSNR 创新高就保存。
|
| 477 |
+
|
| 478 |
+
## 13. 指标记录改进
|
| 479 |
+
|
| 480 |
+
### 13.1 从只打印终端改到保存 metrics.csv
|
| 481 |
+
|
| 482 |
+
从:
|
| 483 |
+
|
| 484 |
+
```text
|
| 485 |
+
terminal only:
|
| 486 |
+
Epoch loss / Val PSNR
|
| 487 |
+
```
|
| 488 |
+
|
| 489 |
+
改到:
|
| 490 |
+
|
| 491 |
+
```text
|
| 492 |
+
checkpoint_restormer_fgp/Deraining/models/RestormerFGP/metrics.csv
|
| 493 |
+
```
|
| 494 |
+
|
| 495 |
+
字段:
|
| 496 |
+
|
| 497 |
+
```text
|
| 498 |
+
epoch,train_loss,lr,val_psnr,best_psnr,epoch_time,saved_checkpoint,is_best
|
| 499 |
+
```
|
| 500 |
+
|
| 501 |
+
对应代码:
|
| 502 |
+
|
| 503 |
+
```text
|
| 504 |
+
train_restormer.py
|
| 505 |
+
append_metrics_csv
|
| 506 |
+
```
|
| 507 |
+
|
| 508 |
+
说明:
|
| 509 |
+
|
| 510 |
+
- 每个 epoch 都会写一行。
|
| 511 |
+
- 非测试 epoch 的 `val_psnr` 为空。
|
| 512 |
+
- 保存普通 checkpoint 的 epoch,`saved_checkpoint=1`。
|
| 513 |
+
- PSNR 刷新 best 的 epoch,`is_best=1`。
|
| 514 |
+
|
| 515 |
+
## 14. 当前启动方式
|
| 516 |
+
|
| 517 |
+
当前使用:
|
| 518 |
+
|
| 519 |
+
```bash
|
| 520 |
+
bash run_restormer_fgp.sh
|
| 521 |
+
```
|
| 522 |
+
|
| 523 |
+
脚本内容等价于:
|
| 524 |
+
|
| 525 |
+
```bash
|
| 526 |
+
python train_restormer.py \
|
| 527 |
+
--config training.yml \
|
| 528 |
+
--model fgp_restormer \
|
| 529 |
+
--session RestormerFGP \
|
| 530 |
+
--save_dir ./checkpoint_restormer_fgp \
|
| 531 |
+
--loss_mode charbonnier_edge_fft \
|
| 532 |
+
--use_ema \
|
| 533 |
+
--val_every 5 \
|
| 534 |
+
--val_pad_factor 8 \
|
| 535 |
+
--save_every 5 \
|
| 536 |
+
--metrics_file metrics.csv \
|
| 537 |
+
--resume ./checkpoint_restormer_fgp/Deraining/models/RestormerFGP/model_5.pth
|
| 538 |
+
```
|
| 539 |
+
|
| 540 |
+
## 15. 当前版本的一句话概括
|
| 541 |
+
|
| 542 |
+
当前版本从原始 Restormer 改成了一个面向低光照去雨的结构感知频率专家 Restormer:
|
| 543 |
+
|
| 544 |
+
```text
|
| 545 |
+
Plain Restormer
|
| 546 |
+
-> Structure-aware Mixture-of-Frequency Prior Restormer
|
| 547 |
+
-> Low-light / rain / structure prior guided multi-scale restoration
|
| 548 |
+
```
|
| 549 |
+
|
| 550 |
+
核心 novelty 可以概括为:
|
| 551 |
+
|
| 552 |
+
```text
|
| 553 |
+
Structure-aware Mixture-of-Frequency Prior Guidance
|
| 554 |
+
for Low-Light Rainy Image Restoration
|
| 555 |
+
```
|
| 556 |
+
|
basicsr/data/__init__.py
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ------------------------------------------------------------------------
|
| 2 |
+
# Copyright (c) 2022 megvii-model. All Rights Reserved.
|
| 3 |
+
# ------------------------------------------------------------------------
|
| 4 |
+
# Modified from BasicSR (https://github.com/xinntao/BasicSR)
|
| 5 |
+
# Copyright 2018-2020 BasicSR Authors
|
| 6 |
+
# ------------------------------------------------------------------------
|
| 7 |
+
|
| 8 |
+
import importlib
|
| 9 |
+
import numpy as np
|
| 10 |
+
import random
|
| 11 |
+
import torch
|
| 12 |
+
import torch.utils.data
|
| 13 |
+
from functools import partial
|
| 14 |
+
from os import path as osp
|
| 15 |
+
|
| 16 |
+
from basicsr.data.prefetch_dataloader import PrefetchDataLoader
|
| 17 |
+
from basicsr.utils import get_root_logger, scandir
|
| 18 |
+
from basicsr.utils.dist_util import get_dist_info
|
| 19 |
+
|
| 20 |
+
__all__ = ['create_dataset', 'create_dataloader']
|
| 21 |
+
|
| 22 |
+
# automatically scan and import dataset modules
|
| 23 |
+
# scan all the files under the data folder with '_dataset' in file names
|
| 24 |
+
data_folder = osp.dirname(osp.abspath(__file__))
|
| 25 |
+
dataset_filenames = [
|
| 26 |
+
osp.splitext(osp.basename(v))[0] for v in scandir(data_folder)
|
| 27 |
+
if v.endswith('_dataset.py')
|
| 28 |
+
]
|
| 29 |
+
# import all the dataset modules
|
| 30 |
+
_dataset_modules = [
|
| 31 |
+
importlib.import_module(f'basicsr.data.{file_name}')
|
| 32 |
+
for file_name in dataset_filenames
|
| 33 |
+
]
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
def create_dataset(dataset_opt):
|
| 37 |
+
"""Create dataset.
|
| 38 |
+
|
| 39 |
+
Args:
|
| 40 |
+
dataset_opt (dict): Configuration for dataset. It constains:
|
| 41 |
+
name (str): Dataset name.
|
| 42 |
+
type (str): Dataset type.
|
| 43 |
+
"""
|
| 44 |
+
dataset_type = dataset_opt['type']
|
| 45 |
+
|
| 46 |
+
# dynamic instantiation
|
| 47 |
+
for module in _dataset_modules:
|
| 48 |
+
dataset_cls = getattr(module, dataset_type, None)
|
| 49 |
+
if dataset_cls is not None:
|
| 50 |
+
break
|
| 51 |
+
if dataset_cls is None:
|
| 52 |
+
raise ValueError(f'Dataset {dataset_type} is not found.')
|
| 53 |
+
|
| 54 |
+
dataset = dataset_cls(dataset_opt)
|
| 55 |
+
|
| 56 |
+
logger = get_root_logger()
|
| 57 |
+
logger.info(
|
| 58 |
+
f'Dataset {dataset.__class__.__name__} - {dataset_opt["name"]} '
|
| 59 |
+
'is created.')
|
| 60 |
+
return dataset
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
def create_dataloader(dataset,
|
| 64 |
+
dataset_opt,
|
| 65 |
+
num_gpu=1,
|
| 66 |
+
dist=False,
|
| 67 |
+
sampler=None,
|
| 68 |
+
seed=None):
|
| 69 |
+
"""Create dataloader.
|
| 70 |
+
|
| 71 |
+
Args:
|
| 72 |
+
dataset (torch.utils.data.Dataset): Dataset.
|
| 73 |
+
dataset_opt (dict): Dataset options. It contains the following keys:
|
| 74 |
+
phase (str): 'train' or 'val'.
|
| 75 |
+
num_worker_per_gpu (int): Number of workers for each GPU.
|
| 76 |
+
batch_size_per_gpu (int): Training batch size for each GPU.
|
| 77 |
+
num_gpu (int): Number of GPUs. Used only in the train phase.
|
| 78 |
+
Default: 1.
|
| 79 |
+
dist (bool): Whether in distributed training. Used only in the train
|
| 80 |
+
phase. Default: False.
|
| 81 |
+
sampler (torch.utils.data.sampler): Data sampler. Default: None.
|
| 82 |
+
seed (int | None): Seed. Default: None
|
| 83 |
+
"""
|
| 84 |
+
phase = dataset_opt['phase']
|
| 85 |
+
rank, _ = get_dist_info()
|
| 86 |
+
if phase == 'train':
|
| 87 |
+
if dist: # distributed training
|
| 88 |
+
batch_size = dataset_opt['batch_size_per_gpu']
|
| 89 |
+
num_workers = dataset_opt['num_worker_per_gpu']
|
| 90 |
+
else: # non-distributed training
|
| 91 |
+
multiplier = 1 if num_gpu == 0 else num_gpu
|
| 92 |
+
batch_size = dataset_opt['batch_size_per_gpu'] * multiplier
|
| 93 |
+
num_workers = dataset_opt['num_worker_per_gpu'] * multiplier
|
| 94 |
+
dataloader_args = dict(
|
| 95 |
+
dataset=dataset,
|
| 96 |
+
batch_size=batch_size,
|
| 97 |
+
shuffle=False,
|
| 98 |
+
num_workers=num_workers,
|
| 99 |
+
sampler=sampler,
|
| 100 |
+
drop_last=True,
|
| 101 |
+
persistent_workers=True
|
| 102 |
+
)
|
| 103 |
+
if sampler is None:
|
| 104 |
+
dataloader_args['shuffle'] = True
|
| 105 |
+
dataloader_args['worker_init_fn'] = partial(
|
| 106 |
+
worker_init_fn, num_workers=num_workers, rank=rank,
|
| 107 |
+
seed=seed) if seed is not None else None
|
| 108 |
+
elif phase in ['val', 'test']: # validation
|
| 109 |
+
dataloader_args = dict(
|
| 110 |
+
dataset=dataset, batch_size=1, shuffle=False, num_workers=0)
|
| 111 |
+
else:
|
| 112 |
+
raise ValueError(f'Wrong dataset phase: {phase}. '
|
| 113 |
+
"Supported ones are 'train', 'val' and 'test'.")
|
| 114 |
+
|
| 115 |
+
dataloader_args['pin_memory'] = dataset_opt.get('pin_memory', False)
|
| 116 |
+
|
| 117 |
+
prefetch_mode = dataset_opt.get('prefetch_mode')
|
| 118 |
+
if prefetch_mode == 'cpu': # CPUPrefetcher
|
| 119 |
+
num_prefetch_queue = dataset_opt.get('num_prefetch_queue', 1)
|
| 120 |
+
logger = get_root_logger()
|
| 121 |
+
logger.info(f'Use {prefetch_mode} prefetch dataloader: '
|
| 122 |
+
f'num_prefetch_queue = {num_prefetch_queue}')
|
| 123 |
+
return PrefetchDataLoader(
|
| 124 |
+
num_prefetch_queue=num_prefetch_queue, **dataloader_args)
|
| 125 |
+
else:
|
| 126 |
+
# prefetch_mode=None: Normal dataloader
|
| 127 |
+
# prefetch_mode='cuda': dataloader for CUDAPrefetcher
|
| 128 |
+
return torch.utils.data.DataLoader(**dataloader_args)
|
| 129 |
+
|
| 130 |
+
|
| 131 |
+
def worker_init_fn(worker_id, num_workers, rank, seed):
|
| 132 |
+
# Set the worker seed to num_workers * rank + worker_id + seed
|
| 133 |
+
worker_seed = num_workers * rank + worker_id + seed
|
| 134 |
+
np.random.seed(worker_seed)
|
| 135 |
+
random.seed(worker_seed)
|
basicsr/data/data_sampler.py
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ------------------------------------------------------------------------
|
| 2 |
+
# Copyright (c) 2022 megvii-model. All Rights Reserved.
|
| 3 |
+
# ------------------------------------------------------------------------
|
| 4 |
+
# Modified from BasicSR (https://github.com/xinntao/BasicSR)
|
| 5 |
+
# Copyright 2018-2020 BasicSR Authors
|
| 6 |
+
# ------------------------------------------------------------------------
|
| 7 |
+
|
| 8 |
+
import math
|
| 9 |
+
import torch
|
| 10 |
+
from torch.utils.data.sampler import Sampler
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
class EnlargedSampler(Sampler):
|
| 14 |
+
"""Sampler that restricts data loading to a subset of the dataset.
|
| 15 |
+
|
| 16 |
+
Modified from torch.utils.data.distributed.DistributedSampler
|
| 17 |
+
Support enlarging the dataset for iteration-based training, for saving
|
| 18 |
+
time when restart the dataloader after each epoch
|
| 19 |
+
|
| 20 |
+
Args:
|
| 21 |
+
dataset (torch.utils.data.Dataset): Dataset used for sampling.
|
| 22 |
+
num_replicas (int | None): Number of processes participating in
|
| 23 |
+
the training. It is usually the world_size.
|
| 24 |
+
rank (int | None): Rank of the current process within num_replicas.
|
| 25 |
+
ratio (int): Enlarging ratio. Default: 1.
|
| 26 |
+
"""
|
| 27 |
+
|
| 28 |
+
def __init__(self, dataset, num_replicas, rank, ratio=1):
|
| 29 |
+
self.dataset = dataset
|
| 30 |
+
self.num_replicas = num_replicas
|
| 31 |
+
self.rank = rank
|
| 32 |
+
self.epoch = 0
|
| 33 |
+
self.num_samples = math.ceil(
|
| 34 |
+
len(self.dataset) * ratio / self.num_replicas)
|
| 35 |
+
self.total_size = self.num_samples * self.num_replicas
|
| 36 |
+
|
| 37 |
+
def __iter__(self):
|
| 38 |
+
# deterministically shuffle based on epoch
|
| 39 |
+
g = torch.Generator()
|
| 40 |
+
g.manual_seed(self.epoch)
|
| 41 |
+
indices = torch.randperm(self.total_size, generator=g).tolist()
|
| 42 |
+
|
| 43 |
+
dataset_size = len(self.dataset)
|
| 44 |
+
indices = [v % dataset_size for v in indices]
|
| 45 |
+
|
| 46 |
+
# subsample
|
| 47 |
+
indices = indices[self.rank:self.total_size:self.num_replicas]
|
| 48 |
+
assert len(indices) == self.num_samples
|
| 49 |
+
|
| 50 |
+
return iter(indices)
|
| 51 |
+
|
| 52 |
+
def __len__(self):
|
| 53 |
+
return self.num_samples
|
| 54 |
+
|
| 55 |
+
def set_epoch(self, epoch):
|
| 56 |
+
self.epoch = epoch
|
basicsr/data/data_util.py
ADDED
|
@@ -0,0 +1,340 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ------------------------------------------------------------------------
|
| 2 |
+
# Copyright (c) 2022 megvii-model. All Rights Reserved.
|
| 3 |
+
# ------------------------------------------------------------------------
|
| 4 |
+
# Modified from BasicSR (https://github.com/xinntao/BasicSR)
|
| 5 |
+
# Copyright 2018-2020 BasicSR Authors
|
| 6 |
+
# ------------------------------------------------------------------------
|
| 7 |
+
import cv2
|
| 8 |
+
import numpy as np
|
| 9 |
+
import torch
|
| 10 |
+
from os import path as osp
|
| 11 |
+
from torch.nn import functional as F
|
| 12 |
+
|
| 13 |
+
from basicsr.data.transforms import mod_crop
|
| 14 |
+
from basicsr.utils import img2tensor, scandir
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
def read_img_seq(path, require_mod_crop=False, scale=1):
|
| 18 |
+
"""Read a sequence of images from a given folder path.
|
| 19 |
+
|
| 20 |
+
Args:
|
| 21 |
+
path (list[str] | str): List of image paths or image folder path.
|
| 22 |
+
require_mod_crop (bool): Require mod crop for each image.
|
| 23 |
+
Default: False.
|
| 24 |
+
scale (int): Scale factor for mod_crop. Default: 1.
|
| 25 |
+
|
| 26 |
+
Returns:
|
| 27 |
+
Tensor: size (t, c, h, w), RGB, [0, 1].
|
| 28 |
+
"""
|
| 29 |
+
if isinstance(path, list):
|
| 30 |
+
img_paths = path
|
| 31 |
+
else:
|
| 32 |
+
img_paths = sorted(list(scandir(path, full_path=True)))
|
| 33 |
+
imgs = [cv2.imread(v).astype(np.float32) / 255. for v in img_paths]
|
| 34 |
+
if require_mod_crop:
|
| 35 |
+
imgs = [mod_crop(img, scale) for img in imgs]
|
| 36 |
+
imgs = img2tensor(imgs, bgr2rgb=True, float32=True)
|
| 37 |
+
imgs = torch.stack(imgs, dim=0)
|
| 38 |
+
return imgs
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
def generate_frame_indices(crt_idx,
|
| 42 |
+
max_frame_num,
|
| 43 |
+
num_frames,
|
| 44 |
+
padding='reflection'):
|
| 45 |
+
"""Generate an index list for reading `num_frames` frames from a sequence
|
| 46 |
+
of images.
|
| 47 |
+
|
| 48 |
+
Args:
|
| 49 |
+
crt_idx (int): Current center index.
|
| 50 |
+
max_frame_num (int): Max number of the sequence of images (from 1).
|
| 51 |
+
num_frames (int): Reading num_frames frames.
|
| 52 |
+
padding (str): Padding mode, one of
|
| 53 |
+
'replicate' | 'reflection' | 'reflection_circle' | 'circle'
|
| 54 |
+
Examples: current_idx = 0, num_frames = 5
|
| 55 |
+
The generated frame indices under different padding mode:
|
| 56 |
+
replicate: [0, 0, 0, 1, 2]
|
| 57 |
+
reflection: [2, 1, 0, 1, 2]
|
| 58 |
+
reflection_circle: [4, 3, 0, 1, 2]
|
| 59 |
+
circle: [3, 4, 0, 1, 2]
|
| 60 |
+
|
| 61 |
+
Returns:
|
| 62 |
+
list[int]: A list of indices.
|
| 63 |
+
"""
|
| 64 |
+
assert num_frames % 2 == 1, 'num_frames should be an odd number.'
|
| 65 |
+
assert padding in ('replicate', 'reflection', 'reflection_circle',
|
| 66 |
+
'circle'), f'Wrong padding mode: {padding}.'
|
| 67 |
+
|
| 68 |
+
max_frame_num = max_frame_num - 1 # start from 0
|
| 69 |
+
num_pad = num_frames // 2
|
| 70 |
+
|
| 71 |
+
indices = []
|
| 72 |
+
for i in range(crt_idx - num_pad, crt_idx + num_pad + 1):
|
| 73 |
+
if i < 0:
|
| 74 |
+
if padding == 'replicate':
|
| 75 |
+
pad_idx = 0
|
| 76 |
+
elif padding == 'reflection':
|
| 77 |
+
pad_idx = -i
|
| 78 |
+
elif padding == 'reflection_circle':
|
| 79 |
+
pad_idx = crt_idx + num_pad - i
|
| 80 |
+
else:
|
| 81 |
+
pad_idx = num_frames + i
|
| 82 |
+
elif i > max_frame_num:
|
| 83 |
+
if padding == 'replicate':
|
| 84 |
+
pad_idx = max_frame_num
|
| 85 |
+
elif padding == 'reflection':
|
| 86 |
+
pad_idx = max_frame_num * 2 - i
|
| 87 |
+
elif padding == 'reflection_circle':
|
| 88 |
+
pad_idx = (crt_idx - num_pad) - (i - max_frame_num)
|
| 89 |
+
else:
|
| 90 |
+
pad_idx = i - num_frames
|
| 91 |
+
else:
|
| 92 |
+
pad_idx = i
|
| 93 |
+
indices.append(pad_idx)
|
| 94 |
+
return indices
|
| 95 |
+
|
| 96 |
+
|
| 97 |
+
def paired_paths_from_lmdb(folders, keys):
|
| 98 |
+
"""Generate paired paths from lmdb files.
|
| 99 |
+
|
| 100 |
+
Contents of lmdb. Taking the `lq.lmdb` for example, the file structure is:
|
| 101 |
+
|
| 102 |
+
lq.lmdb
|
| 103 |
+
├── data.mdb
|
| 104 |
+
├── lock.mdb
|
| 105 |
+
├── meta_info.txt
|
| 106 |
+
|
| 107 |
+
The data.mdb and lock.mdb are standard lmdb files and you can refer to
|
| 108 |
+
https://lmdb.readthedocs.io/en/release/ for more details.
|
| 109 |
+
|
| 110 |
+
The meta_info.txt is a specified txt file to record the meta information
|
| 111 |
+
of our datasets. It will be automatically created when preparing
|
| 112 |
+
datasets by our provided dataset tools.
|
| 113 |
+
Each line in the txt file records
|
| 114 |
+
1)image name (with extension),
|
| 115 |
+
2)image shape,
|
| 116 |
+
3)compression level, separated by a white space.
|
| 117 |
+
Example: `baboon.png (120,125,3) 1`
|
| 118 |
+
|
| 119 |
+
We use the image name without extension as the lmdb key.
|
| 120 |
+
Note that we use the same key for the corresponding lq and gt images.
|
| 121 |
+
|
| 122 |
+
Args:
|
| 123 |
+
folders (list[str]): A list of folder path. The order of list should
|
| 124 |
+
be [input_folder, gt_folder].
|
| 125 |
+
keys (list[str]): A list of keys identifying folders. The order should
|
| 126 |
+
be in consistent with folders, e.g., ['lq', 'gt'].
|
| 127 |
+
Note that this key is different from lmdb keys.
|
| 128 |
+
|
| 129 |
+
Returns:
|
| 130 |
+
list[str]: Returned path list.
|
| 131 |
+
"""
|
| 132 |
+
assert len(folders) == 2, (
|
| 133 |
+
'The len of folders should be 2 with [input_folder, gt_folder]. '
|
| 134 |
+
f'But got {len(folders)}')
|
| 135 |
+
assert len(keys) == 2, (
|
| 136 |
+
'The len of keys should be 2 with [input_key, gt_key]. '
|
| 137 |
+
f'But got {len(keys)}')
|
| 138 |
+
input_folder, gt_folder = folders
|
| 139 |
+
input_key, gt_key = keys
|
| 140 |
+
|
| 141 |
+
if not (input_folder.endswith('.lmdb') and gt_folder.endswith('.lmdb')):
|
| 142 |
+
raise ValueError(
|
| 143 |
+
f'{input_key} folder and {gt_key} folder should both in lmdb '
|
| 144 |
+
f'formats. But received {input_key}: {input_folder}; '
|
| 145 |
+
f'{gt_key}: {gt_folder}')
|
| 146 |
+
# ensure that the two meta_info files are the same
|
| 147 |
+
with open(osp.join(input_folder, 'meta_info.txt')) as fin:
|
| 148 |
+
input_lmdb_keys = [line.split('.')[0] for line in fin]
|
| 149 |
+
with open(osp.join(gt_folder, 'meta_info.txt')) as fin:
|
| 150 |
+
gt_lmdb_keys = [line.split('.')[0] for line in fin]
|
| 151 |
+
if set(input_lmdb_keys) != set(gt_lmdb_keys):
|
| 152 |
+
raise ValueError(
|
| 153 |
+
f'Keys in {input_key}_folder and {gt_key}_folder are different.')
|
| 154 |
+
else:
|
| 155 |
+
paths = []
|
| 156 |
+
for lmdb_key in sorted(input_lmdb_keys):
|
| 157 |
+
paths.append(
|
| 158 |
+
dict([(f'{input_key}_path', lmdb_key),
|
| 159 |
+
(f'{gt_key}_path', lmdb_key)]))
|
| 160 |
+
return paths
|
| 161 |
+
|
| 162 |
+
|
| 163 |
+
def paired_paths_from_meta_info_file(folders, keys, meta_info_file,
|
| 164 |
+
filename_tmpl):
|
| 165 |
+
"""Generate paired paths from an meta information file.
|
| 166 |
+
|
| 167 |
+
Each line in the meta information file contains the image names and
|
| 168 |
+
image shape (usually for gt), separated by a white space.
|
| 169 |
+
|
| 170 |
+
Example of an meta information file:
|
| 171 |
+
```
|
| 172 |
+
0001_s001.png (480,480,3)
|
| 173 |
+
0001_s002.png (480,480,3)
|
| 174 |
+
```
|
| 175 |
+
|
| 176 |
+
Args:
|
| 177 |
+
folders (list[str]): A list of folder path. The order of list should
|
| 178 |
+
be [input_folder, gt_folder].
|
| 179 |
+
keys (list[str]): A list of keys identifying folders. The order should
|
| 180 |
+
be in consistent with folders, e.g., ['lq', 'gt'].
|
| 181 |
+
meta_info_file (str): Path to the meta information file.
|
| 182 |
+
filename_tmpl (str): Template for each filename. Note that the
|
| 183 |
+
template excludes the file extension. Usually the filename_tmpl is
|
| 184 |
+
for files in the input folder.
|
| 185 |
+
|
| 186 |
+
Returns:
|
| 187 |
+
list[str]: Returned path list.
|
| 188 |
+
"""
|
| 189 |
+
assert len(folders) == 2, (
|
| 190 |
+
'The len of folders should be 2 with [input_folder, gt_folder]. '
|
| 191 |
+
f'But got {len(folders)}')
|
| 192 |
+
assert len(keys) == 2, (
|
| 193 |
+
'The len of keys should be 2 with [input_key, gt_key]. '
|
| 194 |
+
f'But got {len(keys)}')
|
| 195 |
+
input_folder, gt_folder = folders
|
| 196 |
+
input_key, gt_key = keys
|
| 197 |
+
|
| 198 |
+
with open(meta_info_file, 'r') as fin:
|
| 199 |
+
gt_names = [line.split(' ')[0] for line in fin]
|
| 200 |
+
|
| 201 |
+
paths = []
|
| 202 |
+
for gt_name in gt_names:
|
| 203 |
+
basename, ext = osp.splitext(osp.basename(gt_name))
|
| 204 |
+
input_name = f'{filename_tmpl.format(basename)}{ext}'
|
| 205 |
+
input_path = osp.join(input_folder, input_name)
|
| 206 |
+
gt_path = osp.join(gt_folder, gt_name)
|
| 207 |
+
paths.append(
|
| 208 |
+
dict([(f'{input_key}_path', input_path),
|
| 209 |
+
(f'{gt_key}_path', gt_path)]))
|
| 210 |
+
return paths
|
| 211 |
+
|
| 212 |
+
|
| 213 |
+
def paired_paths_from_folder(folders, keys, filename_tmpl):
|
| 214 |
+
"""Generate paired paths from folders.
|
| 215 |
+
|
| 216 |
+
Args:
|
| 217 |
+
folders (list[str]): A list of folder path. The order of list should
|
| 218 |
+
be [input_folder, gt_folder].
|
| 219 |
+
keys (list[str]): A list of keys identifying folders. The order should
|
| 220 |
+
be in consistent with folders, e.g., ['lq', 'gt'].
|
| 221 |
+
filename_tmpl (str): Template for each filename. Note that the
|
| 222 |
+
template excludes the file extension. Usually the filename_tmpl is
|
| 223 |
+
for files in the input folder.
|
| 224 |
+
|
| 225 |
+
Returns:
|
| 226 |
+
list[str]: Returned path list.
|
| 227 |
+
"""
|
| 228 |
+
assert len(folders) == 2, (
|
| 229 |
+
'The len of folders should be 2 with [input_folder, gt_folder]. '
|
| 230 |
+
f'But got {len(folders)}')
|
| 231 |
+
assert len(keys) == 2, (
|
| 232 |
+
'The len of keys should be 2 with [input_key, gt_key]. '
|
| 233 |
+
f'But got {len(keys)}')
|
| 234 |
+
input_folder, gt_folder = folders
|
| 235 |
+
input_key, gt_key = keys
|
| 236 |
+
|
| 237 |
+
input_paths = list(scandir(input_folder))
|
| 238 |
+
gt_paths = list(scandir(gt_folder))
|
| 239 |
+
assert len(input_paths) == len(gt_paths), (
|
| 240 |
+
f'{input_key} and {gt_key} datasets have different number of images: '
|
| 241 |
+
f'{len(input_paths)}, {len(gt_paths)}.')
|
| 242 |
+
paths = []
|
| 243 |
+
for idx in range(len(gt_paths)):
|
| 244 |
+
gt_path = gt_paths[idx]
|
| 245 |
+
basename, ext = osp.splitext(osp.basename(gt_path))
|
| 246 |
+
input_path = input_paths[idx]
|
| 247 |
+
basename_input, ext_input = osp.splitext(osp.basename(input_path))
|
| 248 |
+
input_name = f'{filename_tmpl.format(basename)}{ext_input}'
|
| 249 |
+
input_path = osp.join(input_folder, input_name)
|
| 250 |
+
assert input_name in input_paths, (f'{input_name} is not in '
|
| 251 |
+
f'{input_key}_paths.')
|
| 252 |
+
gt_path = osp.join(gt_folder, gt_path)
|
| 253 |
+
paths.append(
|
| 254 |
+
dict([(f'{input_key}_path', input_path),
|
| 255 |
+
(f'{gt_key}_path', gt_path)]))
|
| 256 |
+
return paths
|
| 257 |
+
|
| 258 |
+
|
| 259 |
+
def paths_from_folder(folder):
|
| 260 |
+
"""Generate paths from folder.
|
| 261 |
+
|
| 262 |
+
Args:
|
| 263 |
+
folder (str): Folder path.
|
| 264 |
+
|
| 265 |
+
Returns:
|
| 266 |
+
list[str]: Returned path list.
|
| 267 |
+
"""
|
| 268 |
+
|
| 269 |
+
paths = list(scandir(folder))
|
| 270 |
+
paths = [osp.join(folder, path) for path in paths]
|
| 271 |
+
return paths
|
| 272 |
+
|
| 273 |
+
|
| 274 |
+
def paths_from_lmdb(folder):
|
| 275 |
+
"""Generate paths from lmdb.
|
| 276 |
+
|
| 277 |
+
Args:
|
| 278 |
+
folder (str): Folder path.
|
| 279 |
+
|
| 280 |
+
Returns:
|
| 281 |
+
list[str]: Returned path list.
|
| 282 |
+
"""
|
| 283 |
+
if not folder.endswith('.lmdb'):
|
| 284 |
+
raise ValueError(f'Folder {folder}folder should in lmdb format.')
|
| 285 |
+
with open(osp.join(folder, 'meta_info.txt')) as fin:
|
| 286 |
+
paths = [line.split('.')[0] for line in fin]
|
| 287 |
+
return paths
|
| 288 |
+
|
| 289 |
+
|
| 290 |
+
def generate_gaussian_kernel(kernel_size=13, sigma=1.6):
|
| 291 |
+
"""Generate Gaussian kernel used in `duf_downsample`.
|
| 292 |
+
|
| 293 |
+
Args:
|
| 294 |
+
kernel_size (int): Kernel size. Default: 13.
|
| 295 |
+
sigma (float): Sigma of the Gaussian kernel. Default: 1.6.
|
| 296 |
+
|
| 297 |
+
Returns:
|
| 298 |
+
np.array: The Gaussian kernel.
|
| 299 |
+
"""
|
| 300 |
+
from scipy.ndimage import filters as filters
|
| 301 |
+
kernel = np.zeros((kernel_size, kernel_size))
|
| 302 |
+
# set element at the middle to one, a dirac delta
|
| 303 |
+
kernel[kernel_size // 2, kernel_size // 2] = 1
|
| 304 |
+
# gaussian-smooth the dirac, resulting in a gaussian filter
|
| 305 |
+
return filters.gaussian_filter(kernel, sigma)
|
| 306 |
+
|
| 307 |
+
|
| 308 |
+
def duf_downsample(x, kernel_size=13, scale=4):
|
| 309 |
+
"""Downsamping with Gaussian kernel used in the DUF official code.
|
| 310 |
+
|
| 311 |
+
Args:
|
| 312 |
+
x (Tensor): Frames to be downsampled, with shape (b, t, c, h, w).
|
| 313 |
+
kernel_size (int): Kernel size. Default: 13.
|
| 314 |
+
scale (int): Downsampling factor. Supported scale: (2, 3, 4).
|
| 315 |
+
Default: 4.
|
| 316 |
+
|
| 317 |
+
Returns:
|
| 318 |
+
Tensor: DUF downsampled frames.
|
| 319 |
+
"""
|
| 320 |
+
assert scale in (2, 3,
|
| 321 |
+
4), f'Only support scale (2, 3, 4), but got {scale}.'
|
| 322 |
+
|
| 323 |
+
squeeze_flag = False
|
| 324 |
+
if x.ndim == 4:
|
| 325 |
+
squeeze_flag = True
|
| 326 |
+
x = x.unsqueeze(0)
|
| 327 |
+
b, t, c, h, w = x.size()
|
| 328 |
+
x = x.view(-1, 1, h, w)
|
| 329 |
+
pad_w, pad_h = kernel_size // 2 + scale * 2, kernel_size // 2 + scale * 2
|
| 330 |
+
x = F.pad(x, (pad_w, pad_w, pad_h, pad_h), 'reflect')
|
| 331 |
+
|
| 332 |
+
gaussian_filter = generate_gaussian_kernel(kernel_size, 0.4 * scale)
|
| 333 |
+
gaussian_filter = torch.from_numpy(gaussian_filter).type_as(x).unsqueeze(
|
| 334 |
+
0).unsqueeze(0)
|
| 335 |
+
x = F.conv2d(x, gaussian_filter, stride=scale)
|
| 336 |
+
x = x[:, :, 2:-2, 2:-2]
|
| 337 |
+
x = x.view(b, t, c, x.size(2), x.size(3))
|
| 338 |
+
if squeeze_flag:
|
| 339 |
+
x = x.squeeze(0)
|
| 340 |
+
return x
|
basicsr/data/ffhq_dataset.py
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ------------------------------------------------------------------------
|
| 2 |
+
# Copyright (c) 2022 megvii-model. All Rights Reserved.
|
| 3 |
+
# ------------------------------------------------------------------------
|
| 4 |
+
# Modified from BasicSR (https://github.com/xinntao/BasicSR)
|
| 5 |
+
# Copyright 2018-2020 BasicSR Authors
|
| 6 |
+
# ------------------------------------------------------------------------
|
| 7 |
+
from os import path as osp
|
| 8 |
+
from torch.utils import data as data
|
| 9 |
+
from torchvision.transforms.functional import normalize
|
| 10 |
+
|
| 11 |
+
from basicsr.data.transforms import augment
|
| 12 |
+
from basicsr.utils import FileClient, imfrombytes, img2tensor
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
class FFHQDataset(data.Dataset):
|
| 16 |
+
"""FFHQ dataset for StyleGAN.
|
| 17 |
+
|
| 18 |
+
Args:
|
| 19 |
+
opt (dict): Config for train datasets. It contains the following keys:
|
| 20 |
+
dataroot_gt (str): Data root path for gt.
|
| 21 |
+
io_backend (dict): IO backend type and other kwarg.
|
| 22 |
+
mean (list | tuple): Image mean.
|
| 23 |
+
std (list | tuple): Image std.
|
| 24 |
+
use_hflip (bool): Whether to horizontally flip.
|
| 25 |
+
|
| 26 |
+
"""
|
| 27 |
+
|
| 28 |
+
def __init__(self, opt):
|
| 29 |
+
super(FFHQDataset, self).__init__()
|
| 30 |
+
self.opt = opt
|
| 31 |
+
# file client (io backend)
|
| 32 |
+
self.file_client = None
|
| 33 |
+
self.io_backend_opt = opt['io_backend']
|
| 34 |
+
|
| 35 |
+
self.gt_folder = opt['dataroot_gt']
|
| 36 |
+
self.mean = opt['mean']
|
| 37 |
+
self.std = opt['std']
|
| 38 |
+
|
| 39 |
+
if self.io_backend_opt['type'] == 'lmdb':
|
| 40 |
+
self.io_backend_opt['db_paths'] = self.gt_folder
|
| 41 |
+
if not self.gt_folder.endswith('.lmdb'):
|
| 42 |
+
raise ValueError("'dataroot_gt' should end with '.lmdb', "
|
| 43 |
+
f'but received {self.gt_folder}')
|
| 44 |
+
with open(osp.join(self.gt_folder, 'meta_info.txt')) as fin:
|
| 45 |
+
self.paths = [line.split('.')[0] for line in fin]
|
| 46 |
+
else:
|
| 47 |
+
# FFHQ has 70000 images in total
|
| 48 |
+
self.paths = [
|
| 49 |
+
osp.join(self.gt_folder, f'{v:08d}.png') for v in range(70000)
|
| 50 |
+
]
|
| 51 |
+
|
| 52 |
+
def __getitem__(self, index):
|
| 53 |
+
if self.file_client is None:
|
| 54 |
+
self.file_client = FileClient(
|
| 55 |
+
self.io_backend_opt.pop('type'), **self.io_backend_opt)
|
| 56 |
+
|
| 57 |
+
# load gt image
|
| 58 |
+
gt_path = self.paths[index]
|
| 59 |
+
img_bytes = self.file_client.get(gt_path)
|
| 60 |
+
img_gt = imfrombytes(img_bytes, float32=True)
|
| 61 |
+
|
| 62 |
+
# random horizontal flip
|
| 63 |
+
img_gt = augment(img_gt, hflip=self.opt['use_hflip'], rotation=False)
|
| 64 |
+
# BGR to RGB, HWC to CHW, numpy to tensor
|
| 65 |
+
img_gt = img2tensor(img_gt, bgr2rgb=True, float32=True)
|
| 66 |
+
# normalize
|
| 67 |
+
normalize(img_gt, self.mean, self.std, inplace=True)
|
| 68 |
+
return {'gt': img_gt, 'gt_path': gt_path}
|
| 69 |
+
|
| 70 |
+
def __len__(self):
|
| 71 |
+
return len(self.paths)
|
basicsr/data/meta_info/meta_info_DIV2K800sub_GT.txt
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
basicsr/data/meta_info/meta_info_REDS4_test_GT.txt
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
000 100 (720,1280,3)
|
| 2 |
+
011 100 (720,1280,3)
|
| 3 |
+
015 100 (720,1280,3)
|
| 4 |
+
020 100 (720,1280,3)
|
basicsr/data/meta_info/meta_info_REDS_GT.txt
ADDED
|
@@ -0,0 +1,270 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
000 100 (720,1280,3)
|
| 2 |
+
001 100 (720,1280,3)
|
| 3 |
+
002 100 (720,1280,3)
|
| 4 |
+
003 100 (720,1280,3)
|
| 5 |
+
004 100 (720,1280,3)
|
| 6 |
+
005 100 (720,1280,3)
|
| 7 |
+
006 100 (720,1280,3)
|
| 8 |
+
007 100 (720,1280,3)
|
| 9 |
+
008 100 (720,1280,3)
|
| 10 |
+
009 100 (720,1280,3)
|
| 11 |
+
010 100 (720,1280,3)
|
| 12 |
+
011 100 (720,1280,3)
|
| 13 |
+
012 100 (720,1280,3)
|
| 14 |
+
013 100 (720,1280,3)
|
| 15 |
+
014 100 (720,1280,3)
|
| 16 |
+
015 100 (720,1280,3)
|
| 17 |
+
016 100 (720,1280,3)
|
| 18 |
+
017 100 (720,1280,3)
|
| 19 |
+
018 100 (720,1280,3)
|
| 20 |
+
019 100 (720,1280,3)
|
| 21 |
+
020 100 (720,1280,3)
|
| 22 |
+
021 100 (720,1280,3)
|
| 23 |
+
022 100 (720,1280,3)
|
| 24 |
+
023 100 (720,1280,3)
|
| 25 |
+
024 100 (720,1280,3)
|
| 26 |
+
025 100 (720,1280,3)
|
| 27 |
+
026 100 (720,1280,3)
|
| 28 |
+
027 100 (720,1280,3)
|
| 29 |
+
028 100 (720,1280,3)
|
| 30 |
+
029 100 (720,1280,3)
|
| 31 |
+
030 100 (720,1280,3)
|
| 32 |
+
031 100 (720,1280,3)
|
| 33 |
+
032 100 (720,1280,3)
|
| 34 |
+
033 100 (720,1280,3)
|
| 35 |
+
034 100 (720,1280,3)
|
| 36 |
+
035 100 (720,1280,3)
|
| 37 |
+
036 100 (720,1280,3)
|
| 38 |
+
037 100 (720,1280,3)
|
| 39 |
+
038 100 (720,1280,3)
|
| 40 |
+
039 100 (720,1280,3)
|
| 41 |
+
040 100 (720,1280,3)
|
| 42 |
+
041 100 (720,1280,3)
|
| 43 |
+
042 100 (720,1280,3)
|
| 44 |
+
043 100 (720,1280,3)
|
| 45 |
+
044 100 (720,1280,3)
|
| 46 |
+
045 100 (720,1280,3)
|
| 47 |
+
046 100 (720,1280,3)
|
| 48 |
+
047 100 (720,1280,3)
|
| 49 |
+
048 100 (720,1280,3)
|
| 50 |
+
049 100 (720,1280,3)
|
| 51 |
+
050 100 (720,1280,3)
|
| 52 |
+
051 100 (720,1280,3)
|
| 53 |
+
052 100 (720,1280,3)
|
| 54 |
+
053 100 (720,1280,3)
|
| 55 |
+
054 100 (720,1280,3)
|
| 56 |
+
055 100 (720,1280,3)
|
| 57 |
+
056 100 (720,1280,3)
|
| 58 |
+
057 100 (720,1280,3)
|
| 59 |
+
058 100 (720,1280,3)
|
| 60 |
+
059 100 (720,1280,3)
|
| 61 |
+
060 100 (720,1280,3)
|
| 62 |
+
061 100 (720,1280,3)
|
| 63 |
+
062 100 (720,1280,3)
|
| 64 |
+
063 100 (720,1280,3)
|
| 65 |
+
064 100 (720,1280,3)
|
| 66 |
+
065 100 (720,1280,3)
|
| 67 |
+
066 100 (720,1280,3)
|
| 68 |
+
067 100 (720,1280,3)
|
| 69 |
+
068 100 (720,1280,3)
|
| 70 |
+
069 100 (720,1280,3)
|
| 71 |
+
070 100 (720,1280,3)
|
| 72 |
+
071 100 (720,1280,3)
|
| 73 |
+
072 100 (720,1280,3)
|
| 74 |
+
073 100 (720,1280,3)
|
| 75 |
+
074 100 (720,1280,3)
|
| 76 |
+
075 100 (720,1280,3)
|
| 77 |
+
076 100 (720,1280,3)
|
| 78 |
+
077 100 (720,1280,3)
|
| 79 |
+
078 100 (720,1280,3)
|
| 80 |
+
079 100 (720,1280,3)
|
| 81 |
+
080 100 (720,1280,3)
|
| 82 |
+
081 100 (720,1280,3)
|
| 83 |
+
082 100 (720,1280,3)
|
| 84 |
+
083 100 (720,1280,3)
|
| 85 |
+
084 100 (720,1280,3)
|
| 86 |
+
085 100 (720,1280,3)
|
| 87 |
+
086 100 (720,1280,3)
|
| 88 |
+
087 100 (720,1280,3)
|
| 89 |
+
088 100 (720,1280,3)
|
| 90 |
+
089 100 (720,1280,3)
|
| 91 |
+
090 100 (720,1280,3)
|
| 92 |
+
091 100 (720,1280,3)
|
| 93 |
+
092 100 (720,1280,3)
|
| 94 |
+
093 100 (720,1280,3)
|
| 95 |
+
094 100 (720,1280,3)
|
| 96 |
+
095 100 (720,1280,3)
|
| 97 |
+
096 100 (720,1280,3)
|
| 98 |
+
097 100 (720,1280,3)
|
| 99 |
+
098 100 (720,1280,3)
|
| 100 |
+
099 100 (720,1280,3)
|
| 101 |
+
100 100 (720,1280,3)
|
| 102 |
+
101 100 (720,1280,3)
|
| 103 |
+
102 100 (720,1280,3)
|
| 104 |
+
103 100 (720,1280,3)
|
| 105 |
+
104 100 (720,1280,3)
|
| 106 |
+
105 100 (720,1280,3)
|
| 107 |
+
106 100 (720,1280,3)
|
| 108 |
+
107 100 (720,1280,3)
|
| 109 |
+
108 100 (720,1280,3)
|
| 110 |
+
109 100 (720,1280,3)
|
| 111 |
+
110 100 (720,1280,3)
|
| 112 |
+
111 100 (720,1280,3)
|
| 113 |
+
112 100 (720,1280,3)
|
| 114 |
+
113 100 (720,1280,3)
|
| 115 |
+
114 100 (720,1280,3)
|
| 116 |
+
115 100 (720,1280,3)
|
| 117 |
+
116 100 (720,1280,3)
|
| 118 |
+
117 100 (720,1280,3)
|
| 119 |
+
118 100 (720,1280,3)
|
| 120 |
+
119 100 (720,1280,3)
|
| 121 |
+
120 100 (720,1280,3)
|
| 122 |
+
121 100 (720,1280,3)
|
| 123 |
+
122 100 (720,1280,3)
|
| 124 |
+
123 100 (720,1280,3)
|
| 125 |
+
124 100 (720,1280,3)
|
| 126 |
+
125 100 (720,1280,3)
|
| 127 |
+
126 100 (720,1280,3)
|
| 128 |
+
127 100 (720,1280,3)
|
| 129 |
+
128 100 (720,1280,3)
|
| 130 |
+
129 100 (720,1280,3)
|
| 131 |
+
130 100 (720,1280,3)
|
| 132 |
+
131 100 (720,1280,3)
|
| 133 |
+
132 100 (720,1280,3)
|
| 134 |
+
133 100 (720,1280,3)
|
| 135 |
+
134 100 (720,1280,3)
|
| 136 |
+
135 100 (720,1280,3)
|
| 137 |
+
136 100 (720,1280,3)
|
| 138 |
+
137 100 (720,1280,3)
|
| 139 |
+
138 100 (720,1280,3)
|
| 140 |
+
139 100 (720,1280,3)
|
| 141 |
+
140 100 (720,1280,3)
|
| 142 |
+
141 100 (720,1280,3)
|
| 143 |
+
142 100 (720,1280,3)
|
| 144 |
+
143 100 (720,1280,3)
|
| 145 |
+
144 100 (720,1280,3)
|
| 146 |
+
145 100 (720,1280,3)
|
| 147 |
+
146 100 (720,1280,3)
|
| 148 |
+
147 100 (720,1280,3)
|
| 149 |
+
148 100 (720,1280,3)
|
| 150 |
+
149 100 (720,1280,3)
|
| 151 |
+
150 100 (720,1280,3)
|
| 152 |
+
151 100 (720,1280,3)
|
| 153 |
+
152 100 (720,1280,3)
|
| 154 |
+
153 100 (720,1280,3)
|
| 155 |
+
154 100 (720,1280,3)
|
| 156 |
+
155 100 (720,1280,3)
|
| 157 |
+
156 100 (720,1280,3)
|
| 158 |
+
157 100 (720,1280,3)
|
| 159 |
+
158 100 (720,1280,3)
|
| 160 |
+
159 100 (720,1280,3)
|
| 161 |
+
160 100 (720,1280,3)
|
| 162 |
+
161 100 (720,1280,3)
|
| 163 |
+
162 100 (720,1280,3)
|
| 164 |
+
163 100 (720,1280,3)
|
| 165 |
+
164 100 (720,1280,3)
|
| 166 |
+
165 100 (720,1280,3)
|
| 167 |
+
166 100 (720,1280,3)
|
| 168 |
+
167 100 (720,1280,3)
|
| 169 |
+
168 100 (720,1280,3)
|
| 170 |
+
169 100 (720,1280,3)
|
| 171 |
+
170 100 (720,1280,3)
|
| 172 |
+
171 100 (720,1280,3)
|
| 173 |
+
172 100 (720,1280,3)
|
| 174 |
+
173 100 (720,1280,3)
|
| 175 |
+
174 100 (720,1280,3)
|
| 176 |
+
175 100 (720,1280,3)
|
| 177 |
+
176 100 (720,1280,3)
|
| 178 |
+
177 100 (720,1280,3)
|
| 179 |
+
178 100 (720,1280,3)
|
| 180 |
+
179 100 (720,1280,3)
|
| 181 |
+
180 100 (720,1280,3)
|
| 182 |
+
181 100 (720,1280,3)
|
| 183 |
+
182 100 (720,1280,3)
|
| 184 |
+
183 100 (720,1280,3)
|
| 185 |
+
184 100 (720,1280,3)
|
| 186 |
+
185 100 (720,1280,3)
|
| 187 |
+
186 100 (720,1280,3)
|
| 188 |
+
187 100 (720,1280,3)
|
| 189 |
+
188 100 (720,1280,3)
|
| 190 |
+
189 100 (720,1280,3)
|
| 191 |
+
190 100 (720,1280,3)
|
| 192 |
+
191 100 (720,1280,3)
|
| 193 |
+
192 100 (720,1280,3)
|
| 194 |
+
193 100 (720,1280,3)
|
| 195 |
+
194 100 (720,1280,3)
|
| 196 |
+
195 100 (720,1280,3)
|
| 197 |
+
196 100 (720,1280,3)
|
| 198 |
+
197 100 (720,1280,3)
|
| 199 |
+
198 100 (720,1280,3)
|
| 200 |
+
199 100 (720,1280,3)
|
| 201 |
+
200 100 (720,1280,3)
|
| 202 |
+
201 100 (720,1280,3)
|
| 203 |
+
202 100 (720,1280,3)
|
| 204 |
+
203 100 (720,1280,3)
|
| 205 |
+
204 100 (720,1280,3)
|
| 206 |
+
205 100 (720,1280,3)
|
| 207 |
+
206 100 (720,1280,3)
|
| 208 |
+
207 100 (720,1280,3)
|
| 209 |
+
208 100 (720,1280,3)
|
| 210 |
+
209 100 (720,1280,3)
|
| 211 |
+
210 100 (720,1280,3)
|
| 212 |
+
211 100 (720,1280,3)
|
| 213 |
+
212 100 (720,1280,3)
|
| 214 |
+
213 100 (720,1280,3)
|
| 215 |
+
214 100 (720,1280,3)
|
| 216 |
+
215 100 (720,1280,3)
|
| 217 |
+
216 100 (720,1280,3)
|
| 218 |
+
217 100 (720,1280,3)
|
| 219 |
+
218 100 (720,1280,3)
|
| 220 |
+
219 100 (720,1280,3)
|
| 221 |
+
220 100 (720,1280,3)
|
| 222 |
+
221 100 (720,1280,3)
|
| 223 |
+
222 100 (720,1280,3)
|
| 224 |
+
223 100 (720,1280,3)
|
| 225 |
+
224 100 (720,1280,3)
|
| 226 |
+
225 100 (720,1280,3)
|
| 227 |
+
226 100 (720,1280,3)
|
| 228 |
+
227 100 (720,1280,3)
|
| 229 |
+
228 100 (720,1280,3)
|
| 230 |
+
229 100 (720,1280,3)
|
| 231 |
+
230 100 (720,1280,3)
|
| 232 |
+
231 100 (720,1280,3)
|
| 233 |
+
232 100 (720,1280,3)
|
| 234 |
+
233 100 (720,1280,3)
|
| 235 |
+
234 100 (720,1280,3)
|
| 236 |
+
235 100 (720,1280,3)
|
| 237 |
+
236 100 (720,1280,3)
|
| 238 |
+
237 100 (720,1280,3)
|
| 239 |
+
238 100 (720,1280,3)
|
| 240 |
+
239 100 (720,1280,3)
|
| 241 |
+
240 100 (720,1280,3)
|
| 242 |
+
241 100 (720,1280,3)
|
| 243 |
+
242 100 (720,1280,3)
|
| 244 |
+
243 100 (720,1280,3)
|
| 245 |
+
244 100 (720,1280,3)
|
| 246 |
+
245 100 (720,1280,3)
|
| 247 |
+
246 100 (720,1280,3)
|
| 248 |
+
247 100 (720,1280,3)
|
| 249 |
+
248 100 (720,1280,3)
|
| 250 |
+
249 100 (720,1280,3)
|
| 251 |
+
250 100 (720,1280,3)
|
| 252 |
+
251 100 (720,1280,3)
|
| 253 |
+
252 100 (720,1280,3)
|
| 254 |
+
253 100 (720,1280,3)
|
| 255 |
+
254 100 (720,1280,3)
|
| 256 |
+
255 100 (720,1280,3)
|
| 257 |
+
256 100 (720,1280,3)
|
| 258 |
+
257 100 (720,1280,3)
|
| 259 |
+
258 100 (720,1280,3)
|
| 260 |
+
259 100 (720,1280,3)
|
| 261 |
+
260 100 (720,1280,3)
|
| 262 |
+
261 100 (720,1280,3)
|
| 263 |
+
262 100 (720,1280,3)
|
| 264 |
+
263 100 (720,1280,3)
|
| 265 |
+
264 100 (720,1280,3)
|
| 266 |
+
265 100 (720,1280,3)
|
| 267 |
+
266 100 (720,1280,3)
|
| 268 |
+
267 100 (720,1280,3)
|
| 269 |
+
268 100 (720,1280,3)
|
| 270 |
+
269 100 (720,1280,3)
|
basicsr/data/meta_info/meta_info_REDSofficial4_test_GT.txt
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
240 100 (720,1280,3)
|
| 2 |
+
241 100 (720,1280,3)
|
| 3 |
+
246 100 (720,1280,3)
|
| 4 |
+
257 100 (720,1280,3)
|
basicsr/data/meta_info/meta_info_REDSval_official_test_GT.txt
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
240 100 (720,1280,3)
|
| 2 |
+
241 100 (720,1280,3)
|
| 3 |
+
242 100 (720,1280,3)
|
| 4 |
+
243 100 (720,1280,3)
|
| 5 |
+
244 100 (720,1280,3)
|
| 6 |
+
245 100 (720,1280,3)
|
| 7 |
+
246 100 (720,1280,3)
|
| 8 |
+
247 100 (720,1280,3)
|
| 9 |
+
248 100 (720,1280,3)
|
| 10 |
+
249 100 (720,1280,3)
|
| 11 |
+
250 100 (720,1280,3)
|
| 12 |
+
251 100 (720,1280,3)
|
| 13 |
+
252 100 (720,1280,3)
|
| 14 |
+
253 100 (720,1280,3)
|
| 15 |
+
254 100 (720,1280,3)
|
| 16 |
+
255 100 (720,1280,3)
|
| 17 |
+
256 100 (720,1280,3)
|
| 18 |
+
257 100 (720,1280,3)
|
| 19 |
+
258 100 (720,1280,3)
|
| 20 |
+
259 100 (720,1280,3)
|
| 21 |
+
260 100 (720,1280,3)
|
| 22 |
+
261 100 (720,1280,3)
|
| 23 |
+
262 100 (720,1280,3)
|
| 24 |
+
263 100 (720,1280,3)
|
| 25 |
+
264 100 (720,1280,3)
|
| 26 |
+
265 100 (720,1280,3)
|
| 27 |
+
266 100 (720,1280,3)
|
| 28 |
+
267 100 (720,1280,3)
|
| 29 |
+
268 100 (720,1280,3)
|
| 30 |
+
269 100 (720,1280,3)
|
basicsr/data/meta_info/meta_info_Vimeo90K_test_GT.txt
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
basicsr/data/meta_info/meta_info_Vimeo90K_test_fast_GT.txt
ADDED
|
@@ -0,0 +1,1225 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
00001/0625 7 (256,448,3)
|
| 2 |
+
00001/0632 7 (256,448,3)
|
| 3 |
+
00001/0807 7 (256,448,3)
|
| 4 |
+
00001/0832 7 (256,448,3)
|
| 5 |
+
00001/0834 7 (256,448,3)
|
| 6 |
+
00001/0836 7 (256,448,3)
|
| 7 |
+
00002/0004 7 (256,448,3)
|
| 8 |
+
00002/0112 7 (256,448,3)
|
| 9 |
+
00002/0116 7 (256,448,3)
|
| 10 |
+
00002/0123 7 (256,448,3)
|
| 11 |
+
00002/0455 7 (256,448,3)
|
| 12 |
+
00002/0602 7 (256,448,3)
|
| 13 |
+
00002/0976 7 (256,448,3)
|
| 14 |
+
00002/0980 7 (256,448,3)
|
| 15 |
+
00002/0983 7 (256,448,3)
|
| 16 |
+
00002/1000 7 (256,448,3)
|
| 17 |
+
00003/0022 7 (256,448,3)
|
| 18 |
+
00003/0031 7 (256,448,3)
|
| 19 |
+
00003/0035 7 (256,448,3)
|
| 20 |
+
00003/0041 7 (256,448,3)
|
| 21 |
+
00003/0073 7 (256,448,3)
|
| 22 |
+
00003/0107 7 (256,448,3)
|
| 23 |
+
00003/0111 7 (256,448,3)
|
| 24 |
+
00003/0114 7 (256,448,3)
|
| 25 |
+
00003/0117 7 (256,448,3)
|
| 26 |
+
00003/0121 7 (256,448,3)
|
| 27 |
+
00003/0499 7 (256,448,3)
|
| 28 |
+
00003/0501 7 (256,448,3)
|
| 29 |
+
00003/0507 7 (256,448,3)
|
| 30 |
+
00003/0510 7 (256,448,3)
|
| 31 |
+
00003/0517 7 (256,448,3)
|
| 32 |
+
00003/0522 7 (256,448,3)
|
| 33 |
+
00003/0531 7 (256,448,3)
|
| 34 |
+
00003/0533 7 (256,448,3)
|
| 35 |
+
00003/0534 7 (256,448,3)
|
| 36 |
+
00003/0682 7 (256,448,3)
|
| 37 |
+
00003/0687 7 (256,448,3)
|
| 38 |
+
00003/0715 7 (256,448,3)
|
| 39 |
+
00003/0742 7 (256,448,3)
|
| 40 |
+
00003/0751 7 (256,448,3)
|
| 41 |
+
00003/0984 7 (256,448,3)
|
| 42 |
+
00004/0042 7 (256,448,3)
|
| 43 |
+
00004/0165 7 (256,448,3)
|
| 44 |
+
00004/0321 7 (256,448,3)
|
| 45 |
+
00004/0569 7 (256,448,3)
|
| 46 |
+
00004/0572 7 (256,448,3)
|
| 47 |
+
00004/0619 7 (256,448,3)
|
| 48 |
+
00004/0776 7 (256,448,3)
|
| 49 |
+
00004/0780 7 (256,448,3)
|
| 50 |
+
00004/0825 7 (256,448,3)
|
| 51 |
+
00004/0832 7 (256,448,3)
|
| 52 |
+
00004/0853 7 (256,448,3)
|
| 53 |
+
00004/0876 7 (256,448,3)
|
| 54 |
+
00004/0888 7 (256,448,3)
|
| 55 |
+
00005/0015 7 (256,448,3)
|
| 56 |
+
00005/0021 7 (256,448,3)
|
| 57 |
+
00005/0022 7 (256,448,3)
|
| 58 |
+
00005/0024 7 (256,448,3)
|
| 59 |
+
00005/0026 7 (256,448,3)
|
| 60 |
+
00005/0394 7 (256,448,3)
|
| 61 |
+
00005/0403 7 (256,448,3)
|
| 62 |
+
00005/0531 7 (256,448,3)
|
| 63 |
+
00005/0546 7 (256,448,3)
|
| 64 |
+
00005/0554 7 (256,448,3)
|
| 65 |
+
00005/0694 7 (256,448,3)
|
| 66 |
+
00005/0700 7 (256,448,3)
|
| 67 |
+
00005/0740 7 (256,448,3)
|
| 68 |
+
00005/0826 7 (256,448,3)
|
| 69 |
+
00005/0832 7 (256,448,3)
|
| 70 |
+
00005/0834 7 (256,448,3)
|
| 71 |
+
00005/0943 7 (256,448,3)
|
| 72 |
+
00006/0184 7 (256,448,3)
|
| 73 |
+
00006/0205 7 (256,448,3)
|
| 74 |
+
00006/0206 7 (256,448,3)
|
| 75 |
+
00006/0211 7 (256,448,3)
|
| 76 |
+
00006/0271 7 (256,448,3)
|
| 77 |
+
00006/0273 7 (256,448,3)
|
| 78 |
+
00006/0277 7 (256,448,3)
|
| 79 |
+
00006/0283 7 (256,448,3)
|
| 80 |
+
00006/0287 7 (256,448,3)
|
| 81 |
+
00006/0298 7 (256,448,3)
|
| 82 |
+
00006/0310 7 (256,448,3)
|
| 83 |
+
00006/0356 7 (256,448,3)
|
| 84 |
+
00006/0357 7 (256,448,3)
|
| 85 |
+
00006/0544 7 (256,448,3)
|
| 86 |
+
00006/0565 7 (256,448,3)
|
| 87 |
+
00006/0569 7 (256,448,3)
|
| 88 |
+
00006/0573 7 (256,448,3)
|
| 89 |
+
00006/0592 7 (256,448,3)
|
| 90 |
+
00006/0613 7 (256,448,3)
|
| 91 |
+
00006/0633 7 (256,448,3)
|
| 92 |
+
00006/0637 7 (256,448,3)
|
| 93 |
+
00006/0646 7 (256,448,3)
|
| 94 |
+
00006/0649 7 (256,448,3)
|
| 95 |
+
00006/0655 7 (256,448,3)
|
| 96 |
+
00006/0658 7 (256,448,3)
|
| 97 |
+
00006/0662 7 (256,448,3)
|
| 98 |
+
00006/0666 7 (256,448,3)
|
| 99 |
+
00006/0673 7 (256,448,3)
|
| 100 |
+
00007/0248 7 (256,448,3)
|
| 101 |
+
00007/0253 7 (256,448,3)
|
| 102 |
+
00007/0430 7 (256,448,3)
|
| 103 |
+
00007/0434 7 (256,448,3)
|
| 104 |
+
00007/0436 7 (256,448,3)
|
| 105 |
+
00007/0452 7 (256,448,3)
|
| 106 |
+
00007/0464 7 (256,448,3)
|
| 107 |
+
00007/0470 7 (256,448,3)
|
| 108 |
+
00007/0472 7 (256,448,3)
|
| 109 |
+
00007/0483 7 (256,448,3)
|
| 110 |
+
00007/0484 7 (256,448,3)
|
| 111 |
+
00007/0493 7 (256,448,3)
|
| 112 |
+
00007/0508 7 (256,448,3)
|
| 113 |
+
00007/0514 7 (256,448,3)
|
| 114 |
+
00007/0697 7 (256,448,3)
|
| 115 |
+
00007/0698 7 (256,448,3)
|
| 116 |
+
00007/0744 7 (256,448,3)
|
| 117 |
+
00007/0775 7 (256,448,3)
|
| 118 |
+
00007/0786 7 (256,448,3)
|
| 119 |
+
00007/0790 7 (256,448,3)
|
| 120 |
+
00007/0800 7 (256,448,3)
|
| 121 |
+
00007/0833 7 (256,448,3)
|
| 122 |
+
00007/0867 7 (256,448,3)
|
| 123 |
+
00007/0879 7 (256,448,3)
|
| 124 |
+
00007/0899 7 (256,448,3)
|
| 125 |
+
00008/0251 7 (256,448,3)
|
| 126 |
+
00008/0322 7 (256,448,3)
|
| 127 |
+
00008/0971 7 (256,448,3)
|
| 128 |
+
00008/0976 7 (256,448,3)
|
| 129 |
+
00009/0016 7 (256,448,3)
|
| 130 |
+
00009/0036 7 (256,448,3)
|
| 131 |
+
00009/0037 7 (256,448,3)
|
| 132 |
+
00009/0609 7 (256,448,3)
|
| 133 |
+
00009/0812 7 (256,448,3)
|
| 134 |
+
00009/0821 7 (256,448,3)
|
| 135 |
+
00009/0947 7 (256,448,3)
|
| 136 |
+
00009/0952 7 (256,448,3)
|
| 137 |
+
00009/0955 7 (256,448,3)
|
| 138 |
+
00009/0970 7 (256,448,3)
|
| 139 |
+
00010/0072 7 (256,448,3)
|
| 140 |
+
00010/0074 7 (256,448,3)
|
| 141 |
+
00010/0079 7 (256,448,3)
|
| 142 |
+
00010/0085 7 (256,448,3)
|
| 143 |
+
00010/0139 7 (256,448,3)
|
| 144 |
+
00010/0140 7 (256,448,3)
|
| 145 |
+
00010/0183 7 (256,448,3)
|
| 146 |
+
00010/0200 7 (256,448,3)
|
| 147 |
+
00010/0223 7 (256,448,3)
|
| 148 |
+
00010/0305 7 (256,448,3)
|
| 149 |
+
00010/0323 7 (256,448,3)
|
| 150 |
+
00010/0338 7 (256,448,3)
|
| 151 |
+
00010/0342 7 (256,448,3)
|
| 152 |
+
00010/0350 7 (256,448,3)
|
| 153 |
+
00010/0356 7 (256,448,3)
|
| 154 |
+
00010/0362 7 (256,448,3)
|
| 155 |
+
00010/0366 7 (256,448,3)
|
| 156 |
+
00010/0375 7 (256,448,3)
|
| 157 |
+
00010/0404 7 (256,448,3)
|
| 158 |
+
00010/0407 7 (256,448,3)
|
| 159 |
+
00010/0414 7 (256,448,3)
|
| 160 |
+
00010/0418 7 (256,448,3)
|
| 161 |
+
00010/0429 7 (256,448,3)
|
| 162 |
+
00010/0557 7 (256,448,3)
|
| 163 |
+
00010/0564 7 (256,448,3)
|
| 164 |
+
00010/0733 7 (256,448,3)
|
| 165 |
+
00010/0935 7 (256,448,3)
|
| 166 |
+
00010/0939 7 (256,448,3)
|
| 167 |
+
00010/0943 7 (256,448,3)
|
| 168 |
+
00011/0242 7 (256,448,3)
|
| 169 |
+
00011/0259 7 (256,448,3)
|
| 170 |
+
00011/0263 7 (256,448,3)
|
| 171 |
+
00011/0266 7 (256,448,3)
|
| 172 |
+
00011/0278 7 (256,448,3)
|
| 173 |
+
00011/0890 7 (256,448,3)
|
| 174 |
+
00011/0894 7 (256,448,3)
|
| 175 |
+
00011/0903 7 (256,448,3)
|
| 176 |
+
00011/0906 7 (256,448,3)
|
| 177 |
+
00011/0913 7 (256,448,3)
|
| 178 |
+
00012/0011 7 (256,448,3)
|
| 179 |
+
00012/0014 7 (256,448,3)
|
| 180 |
+
00012/0126 7 (256,448,3)
|
| 181 |
+
00012/0127 7 (256,448,3)
|
| 182 |
+
00012/0526 7 (256,448,3)
|
| 183 |
+
00012/0551 7 (256,448,3)
|
| 184 |
+
00012/0896 7 (256,448,3)
|
| 185 |
+
00012/0910 7 (256,448,3)
|
| 186 |
+
00012/0915 7 (256,448,3)
|
| 187 |
+
00013/0167 7 (256,448,3)
|
| 188 |
+
00013/0794 7 (256,448,3)
|
| 189 |
+
00013/0807 7 (256,448,3)
|
| 190 |
+
00013/0846 7 (256,448,3)
|
| 191 |
+
00013/0882 7 (256,448,3)
|
| 192 |
+
00013/0889 7 (256,448,3)
|
| 193 |
+
00013/0910 7 (256,448,3)
|
| 194 |
+
00013/0913 7 (256,448,3)
|
| 195 |
+
00013/0924 7 (256,448,3)
|
| 196 |
+
00013/0931 7 (256,448,3)
|
| 197 |
+
00013/0944 7 (256,448,3)
|
| 198 |
+
00013/0955 7 (256,448,3)
|
| 199 |
+
00013/0962 7 (256,448,3)
|
| 200 |
+
00013/0969 7 (256,448,3)
|
| 201 |
+
00014/0012 7 (256,448,3)
|
| 202 |
+
00014/0025 7 (256,448,3)
|
| 203 |
+
00014/0473 7 (256,448,3)
|
| 204 |
+
00014/0499 7 (256,448,3)
|
| 205 |
+
00014/0524 7 (256,448,3)
|
| 206 |
+
00014/0739 7 (256,448,3)
|
| 207 |
+
00014/0753 7 (256,448,3)
|
| 208 |
+
00014/0771 7 (256,448,3)
|
| 209 |
+
00014/0832 7 (256,448,3)
|
| 210 |
+
00014/0836 7 (256,448,3)
|
| 211 |
+
00014/0838 7 (256,448,3)
|
| 212 |
+
00014/0839 7 (256,448,3)
|
| 213 |
+
00014/0843 7 (256,448,3)
|
| 214 |
+
00014/0846 7 (256,448,3)
|
| 215 |
+
00014/0849 7 (256,448,3)
|
| 216 |
+
00014/0859 7 (256,448,3)
|
| 217 |
+
00014/0880 7 (256,448,3)
|
| 218 |
+
00014/0906 7 (256,448,3)
|
| 219 |
+
00015/0030 7 (256,448,3)
|
| 220 |
+
00015/0067 7 (256,448,3)
|
| 221 |
+
00015/0084 7 (256,448,3)
|
| 222 |
+
00015/0190 7 (256,448,3)
|
| 223 |
+
00015/0575 7 (256,448,3)
|
| 224 |
+
00015/0784 7 (256,448,3)
|
| 225 |
+
00015/0855 7 (256,448,3)
|
| 226 |
+
00015/0904 7 (256,448,3)
|
| 227 |
+
00015/0914 7 (256,448,3)
|
| 228 |
+
00015/0936 7 (256,448,3)
|
| 229 |
+
00015/0939 7 (256,448,3)
|
| 230 |
+
00015/0943 7 (256,448,3)
|
| 231 |
+
00015/0957 7 (256,448,3)
|
| 232 |
+
00016/0131 7 (256,448,3)
|
| 233 |
+
00016/0173 7 (256,448,3)
|
| 234 |
+
00016/0320 7 (256,448,3)
|
| 235 |
+
00016/0328 7 (256,448,3)
|
| 236 |
+
00016/0334 7 (256,448,3)
|
| 237 |
+
00016/0338 7 (256,448,3)
|
| 238 |
+
00016/0339 7 (256,448,3)
|
| 239 |
+
00016/0345 7 (256,448,3)
|
| 240 |
+
00016/0365 7 (256,448,3)
|
| 241 |
+
00016/0584 7 (256,448,3)
|
| 242 |
+
00016/0634 7 (256,448,3)
|
| 243 |
+
00017/0342 7 (256,448,3)
|
| 244 |
+
00017/0346 7 (256,448,3)
|
| 245 |
+
00017/0350 7 (256,448,3)
|
| 246 |
+
00017/0766 7 (256,448,3)
|
| 247 |
+
00017/0786 7 (256,448,3)
|
| 248 |
+
00017/0911 7 (256,448,3)
|
| 249 |
+
00017/0914 7 (256,448,3)
|
| 250 |
+
00018/0217 7 (256,448,3)
|
| 251 |
+
00018/0258 7 (256,448,3)
|
| 252 |
+
00018/0307 7 (256,448,3)
|
| 253 |
+
00018/0480 7 (256,448,3)
|
| 254 |
+
00018/0491 7 (256,448,3)
|
| 255 |
+
00018/0994 7 (256,448,3)
|
| 256 |
+
00018/0995 7 (256,448,3)
|
| 257 |
+
00018/0997 7 (256,448,3)
|
| 258 |
+
00018/1000 7 (256,448,3)
|
| 259 |
+
00019/0007 7 (256,448,3)
|
| 260 |
+
00019/0016 7 (256,448,3)
|
| 261 |
+
00019/0026 7 (256,448,3)
|
| 262 |
+
00019/0030 7 (256,448,3)
|
| 263 |
+
00019/0086 7 (256,448,3)
|
| 264 |
+
00019/0089 7 (256,448,3)
|
| 265 |
+
00019/0111 7 (256,448,3)
|
| 266 |
+
00019/0285 7 (256,448,3)
|
| 267 |
+
00019/0415 7 (256,448,3)
|
| 268 |
+
00019/0434 7 (256,448,3)
|
| 269 |
+
00019/0437 7 (256,448,3)
|
| 270 |
+
00019/0568 7 (256,448,3)
|
| 271 |
+
00019/0570 7 (256,448,3)
|
| 272 |
+
00019/0591 7 (256,448,3)
|
| 273 |
+
00019/0596 7 (256,448,3)
|
| 274 |
+
00019/0603 7 (256,448,3)
|
| 275 |
+
00019/0607 7 (256,448,3)
|
| 276 |
+
00019/0637 7 (256,448,3)
|
| 277 |
+
00019/0644 7 (256,448,3)
|
| 278 |
+
00019/0647 7 (256,448,3)
|
| 279 |
+
00019/0787 7 (256,448,3)
|
| 280 |
+
00019/0993 7 (256,448,3)
|
| 281 |
+
00019/0998 7 (256,448,3)
|
| 282 |
+
00021/0232 7 (256,448,3)
|
| 283 |
+
00021/0255 7 (256,448,3)
|
| 284 |
+
00021/0646 7 (256,448,3)
|
| 285 |
+
00021/0653 7 (256,448,3)
|
| 286 |
+
00021/0657 7 (256,448,3)
|
| 287 |
+
00021/0668 7 (256,448,3)
|
| 288 |
+
00021/0672 7 (256,448,3)
|
| 289 |
+
00021/0725 7 (256,448,3)
|
| 290 |
+
00021/0750 7 (256,448,3)
|
| 291 |
+
00021/0764 7 (256,448,3)
|
| 292 |
+
00021/0821 7 (256,448,3)
|
| 293 |
+
00022/0192 7 (256,448,3)
|
| 294 |
+
00022/0391 7 (256,448,3)
|
| 295 |
+
00022/0514 7 (256,448,3)
|
| 296 |
+
00022/0567 7 (256,448,3)
|
| 297 |
+
00022/0674 7 (256,448,3)
|
| 298 |
+
00022/0686 7 (256,448,3)
|
| 299 |
+
00022/0700 7 (256,448,3)
|
| 300 |
+
00023/0020 7 (256,448,3)
|
| 301 |
+
00023/0024 7 (256,448,3)
|
| 302 |
+
00023/0025 7 (256,448,3)
|
| 303 |
+
00023/0042 7 (256,448,3)
|
| 304 |
+
00023/0050 7 (256,448,3)
|
| 305 |
+
00023/0094 7 (256,448,3)
|
| 306 |
+
00023/0107 7 (256,448,3)
|
| 307 |
+
00023/0635 7 (256,448,3)
|
| 308 |
+
00023/0698 7 (256,448,3)
|
| 309 |
+
00023/0774 7 (256,448,3)
|
| 310 |
+
00023/0795 7 (256,448,3)
|
| 311 |
+
00023/0821 7 (256,448,3)
|
| 312 |
+
00023/0839 7 (256,448,3)
|
| 313 |
+
00023/0846 7 (256,448,3)
|
| 314 |
+
00023/0869 7 (256,448,3)
|
| 315 |
+
00023/0879 7 (256,448,3)
|
| 316 |
+
00023/0887 7 (256,448,3)
|
| 317 |
+
00023/0899 7 (256,448,3)
|
| 318 |
+
00023/0910 7 (256,448,3)
|
| 319 |
+
00023/0920 7 (256,448,3)
|
| 320 |
+
00023/0929 7 (256,448,3)
|
| 321 |
+
00023/0941 7 (256,448,3)
|
| 322 |
+
00023/0942 7 (256,448,3)
|
| 323 |
+
00023/0952 7 (256,448,3)
|
| 324 |
+
00024/0066 7 (256,448,3)
|
| 325 |
+
00024/0072 7 (256,448,3)
|
| 326 |
+
00024/0080 7 (256,448,3)
|
| 327 |
+
00024/0093 7 (256,448,3)
|
| 328 |
+
00024/0107 7 (256,448,3)
|
| 329 |
+
00024/0262 7 (256,448,3)
|
| 330 |
+
00024/0283 7 (256,448,3)
|
| 331 |
+
00024/0294 7 (256,448,3)
|
| 332 |
+
00024/0296 7 (256,448,3)
|
| 333 |
+
00024/0304 7 (256,448,3)
|
| 334 |
+
00024/0315 7 (256,448,3)
|
| 335 |
+
00024/0322 7 (256,448,3)
|
| 336 |
+
00024/0648 7 (256,448,3)
|
| 337 |
+
00024/0738 7 (256,448,3)
|
| 338 |
+
00024/0743 7 (256,448,3)
|
| 339 |
+
00025/0542 7 (256,448,3)
|
| 340 |
+
00025/0769 7 (256,448,3)
|
| 341 |
+
00025/0984 7 (256,448,3)
|
| 342 |
+
00025/0985 7 (256,448,3)
|
| 343 |
+
00025/0989 7 (256,448,3)
|
| 344 |
+
00025/0991 7 (256,448,3)
|
| 345 |
+
00026/0009 7 (256,448,3)
|
| 346 |
+
00026/0013 7 (256,448,3)
|
| 347 |
+
00026/0020 7 (256,448,3)
|
| 348 |
+
00026/0021 7 (256,448,3)
|
| 349 |
+
00026/0025 7 (256,448,3)
|
| 350 |
+
00026/0135 7 (256,448,3)
|
| 351 |
+
00026/0200 7 (256,448,3)
|
| 352 |
+
00026/0297 7 (256,448,3)
|
| 353 |
+
00026/0306 7 (256,448,3)
|
| 354 |
+
00026/0444 7 (256,448,3)
|
| 355 |
+
00026/0450 7 (256,448,3)
|
| 356 |
+
00026/0453 7 (256,448,3)
|
| 357 |
+
00026/0464 7 (256,448,3)
|
| 358 |
+
00026/0486 7 (256,448,3)
|
| 359 |
+
00026/0773 7 (256,448,3)
|
| 360 |
+
00026/0785 7 (256,448,3)
|
| 361 |
+
00026/0836 7 (256,448,3)
|
| 362 |
+
00026/0838 7 (256,448,3)
|
| 363 |
+
00026/0848 7 (256,448,3)
|
| 364 |
+
00026/0885 7 (256,448,3)
|
| 365 |
+
00026/0893 7 (256,448,3)
|
| 366 |
+
00026/0939 7 (256,448,3)
|
| 367 |
+
00026/0942 7 (256,448,3)
|
| 368 |
+
00027/0092 7 (256,448,3)
|
| 369 |
+
00027/0112 7 (256,448,3)
|
| 370 |
+
00027/0115 7 (256,448,3)
|
| 371 |
+
00027/0143 7 (256,448,3)
|
| 372 |
+
00027/0175 7 (256,448,3)
|
| 373 |
+
00027/0179 7 (256,448,3)
|
| 374 |
+
00027/0183 7 (256,448,3)
|
| 375 |
+
00027/0197 7 (256,448,3)
|
| 376 |
+
00027/0199 7 (256,448,3)
|
| 377 |
+
00027/0300 7 (256,448,3)
|
| 378 |
+
00028/0015 7 (256,448,3)
|
| 379 |
+
00028/0032 7 (256,448,3)
|
| 380 |
+
00028/0048 7 (256,448,3)
|
| 381 |
+
00028/0068 7 (256,448,3)
|
| 382 |
+
00028/0219 7 (256,448,3)
|
| 383 |
+
00028/0606 7 (256,448,3)
|
| 384 |
+
00028/0626 7 (256,448,3)
|
| 385 |
+
00028/0748 7 (256,448,3)
|
| 386 |
+
00028/0764 7 (256,448,3)
|
| 387 |
+
00028/0772 7 (256,448,3)
|
| 388 |
+
00028/0780 7 (256,448,3)
|
| 389 |
+
00028/0926 7 (256,448,3)
|
| 390 |
+
00028/0947 7 (256,448,3)
|
| 391 |
+
00028/0962 7 (256,448,3)
|
| 392 |
+
00029/0085 7 (256,448,3)
|
| 393 |
+
00029/0281 7 (256,448,3)
|
| 394 |
+
00029/0284 7 (256,448,3)
|
| 395 |
+
00029/0288 7 (256,448,3)
|
| 396 |
+
00029/0294 7 (256,448,3)
|
| 397 |
+
00029/0364 7 (256,448,3)
|
| 398 |
+
00029/0369 7 (256,448,3)
|
| 399 |
+
00029/0421 7 (256,448,3)
|
| 400 |
+
00029/0425 7 (256,448,3)
|
| 401 |
+
00029/0550 7 (256,448,3)
|
| 402 |
+
00030/0014 7 (256,448,3)
|
| 403 |
+
00030/0101 7 (256,448,3)
|
| 404 |
+
00030/0143 7 (256,448,3)
|
| 405 |
+
00030/0351 7 (256,448,3)
|
| 406 |
+
00030/0356 7 (256,448,3)
|
| 407 |
+
00030/0371 7 (256,448,3)
|
| 408 |
+
00030/0484 7 (256,448,3)
|
| 409 |
+
00030/0492 7 (256,448,3)
|
| 410 |
+
00030/0503 7 (256,448,3)
|
| 411 |
+
00030/0682 7 (256,448,3)
|
| 412 |
+
00030/0696 7 (256,448,3)
|
| 413 |
+
00030/0735 7 (256,448,3)
|
| 414 |
+
00030/0737 7 (256,448,3)
|
| 415 |
+
00030/0868 7 (256,448,3)
|
| 416 |
+
00031/0161 7 (256,448,3)
|
| 417 |
+
00031/0180 7 (256,448,3)
|
| 418 |
+
00031/0194 7 (256,448,3)
|
| 419 |
+
00031/0253 7 (256,448,3)
|
| 420 |
+
00031/0293 7 (256,448,3)
|
| 421 |
+
00031/0466 7 (256,448,3)
|
| 422 |
+
00031/0477 7 (256,448,3)
|
| 423 |
+
00031/0549 7 (256,448,3)
|
| 424 |
+
00031/0600 7 (256,448,3)
|
| 425 |
+
00031/0617 7 (256,448,3)
|
| 426 |
+
00031/0649 7 (256,448,3)
|
| 427 |
+
00032/0015 7 (256,448,3)
|
| 428 |
+
00032/0020 7 (256,448,3)
|
| 429 |
+
00032/0023 7 (256,448,3)
|
| 430 |
+
00032/0048 7 (256,448,3)
|
| 431 |
+
00032/0056 7 (256,448,3)
|
| 432 |
+
00032/0872 7 (256,448,3)
|
| 433 |
+
00033/0069 7 (256,448,3)
|
| 434 |
+
00033/0073 7 (256,448,3)
|
| 435 |
+
00033/0078 7 (256,448,3)
|
| 436 |
+
00033/0079 7 (256,448,3)
|
| 437 |
+
00033/0086 7 (256,448,3)
|
| 438 |
+
00033/0088 7 (256,448,3)
|
| 439 |
+
00033/0091 7 (256,448,3)
|
| 440 |
+
00033/0096 7 (256,448,3)
|
| 441 |
+
00033/0607 7 (256,448,3)
|
| 442 |
+
00033/0613 7 (256,448,3)
|
| 443 |
+
00033/0616 7 (256,448,3)
|
| 444 |
+
00033/0619 7 (256,448,3)
|
| 445 |
+
00033/0626 7 (256,448,3)
|
| 446 |
+
00033/0628 7 (256,448,3)
|
| 447 |
+
00033/0637 7 (256,448,3)
|
| 448 |
+
00033/0686 7 (256,448,3)
|
| 449 |
+
00033/0842 7 (256,448,3)
|
| 450 |
+
00034/0261 7 (256,448,3)
|
| 451 |
+
00034/0265 7 (256,448,3)
|
| 452 |
+
00034/0269 7 (256,448,3)
|
| 453 |
+
00034/0275 7 (256,448,3)
|
| 454 |
+
00034/0286 7 (256,448,3)
|
| 455 |
+
00034/0294 7 (256,448,3)
|
| 456 |
+
00034/0431 7 (256,448,3)
|
| 457 |
+
00034/0577 7 (256,448,3)
|
| 458 |
+
00034/0685 7 (256,448,3)
|
| 459 |
+
00034/0687 7 (256,448,3)
|
| 460 |
+
00034/0703 7 (256,448,3)
|
| 461 |
+
00034/0715 7 (256,448,3)
|
| 462 |
+
00034/0935 7 (256,448,3)
|
| 463 |
+
00034/0943 7 (256,448,3)
|
| 464 |
+
00034/0963 7 (256,448,3)
|
| 465 |
+
00034/0979 7 (256,448,3)
|
| 466 |
+
00034/0990 7 (256,448,3)
|
| 467 |
+
00035/0129 7 (256,448,3)
|
| 468 |
+
00035/0153 7 (256,448,3)
|
| 469 |
+
00035/0156 7 (256,448,3)
|
| 470 |
+
00035/0474 7 (256,448,3)
|
| 471 |
+
00035/0507 7 (256,448,3)
|
| 472 |
+
00035/0532 7 (256,448,3)
|
| 473 |
+
00035/0560 7 (256,448,3)
|
| 474 |
+
00035/0572 7 (256,448,3)
|
| 475 |
+
00035/0587 7 (256,448,3)
|
| 476 |
+
00035/0588 7 (256,448,3)
|
| 477 |
+
00035/0640 7 (256,448,3)
|
| 478 |
+
00035/0654 7 (256,448,3)
|
| 479 |
+
00035/0655 7 (256,448,3)
|
| 480 |
+
00035/0737 7 (256,448,3)
|
| 481 |
+
00035/0843 7 (256,448,3)
|
| 482 |
+
00035/0932 7 (256,448,3)
|
| 483 |
+
00035/0957 7 (256,448,3)
|
| 484 |
+
00036/0029 7 (256,448,3)
|
| 485 |
+
00036/0266 7 (256,448,3)
|
| 486 |
+
00036/0276 7 (256,448,3)
|
| 487 |
+
00036/0310 7 (256,448,3)
|
| 488 |
+
00036/0314 7 (256,448,3)
|
| 489 |
+
00036/0320 7 (256,448,3)
|
| 490 |
+
00036/0333 7 (256,448,3)
|
| 491 |
+
00036/0348 7 (256,448,3)
|
| 492 |
+
00036/0357 7 (256,448,3)
|
| 493 |
+
00036/0360 7 (256,448,3)
|
| 494 |
+
00036/0368 7 (256,448,3)
|
| 495 |
+
00036/0371 7 (256,448,3)
|
| 496 |
+
00036/0378 7 (256,448,3)
|
| 497 |
+
00036/0391 7 (256,448,3)
|
| 498 |
+
00036/0440 7 (256,448,3)
|
| 499 |
+
00036/0731 7 (256,448,3)
|
| 500 |
+
00036/0733 7 (256,448,3)
|
| 501 |
+
00036/0741 7 (256,448,3)
|
| 502 |
+
00036/0743 7 (256,448,3)
|
| 503 |
+
00036/0927 7 (256,448,3)
|
| 504 |
+
00036/0931 7 (256,448,3)
|
| 505 |
+
00036/0933 7 (256,448,3)
|
| 506 |
+
00036/0938 7 (256,448,3)
|
| 507 |
+
00036/0944 7 (256,448,3)
|
| 508 |
+
00036/0946 7 (256,448,3)
|
| 509 |
+
00036/0951 7 (256,448,3)
|
| 510 |
+
00036/0953 7 (256,448,3)
|
| 511 |
+
00036/0963 7 (256,448,3)
|
| 512 |
+
00036/0964 7 (256,448,3)
|
| 513 |
+
00036/0981 7 (256,448,3)
|
| 514 |
+
00036/0991 7 (256,448,3)
|
| 515 |
+
00037/0072 7 (256,448,3)
|
| 516 |
+
00037/0079 7 (256,448,3)
|
| 517 |
+
00037/0132 7 (256,448,3)
|
| 518 |
+
00037/0135 7 (256,448,3)
|
| 519 |
+
00037/0137 7 (256,448,3)
|
| 520 |
+
00037/0141 7 (256,448,3)
|
| 521 |
+
00037/0229 7 (256,448,3)
|
| 522 |
+
00037/0234 7 (256,448,3)
|
| 523 |
+
00037/0239 7 (256,448,3)
|
| 524 |
+
00037/0242 7 (256,448,3)
|
| 525 |
+
00037/0254 7 (256,448,3)
|
| 526 |
+
00037/0269 7 (256,448,3)
|
| 527 |
+
00037/0276 7 (256,448,3)
|
| 528 |
+
00037/0279 7 (256,448,3)
|
| 529 |
+
00037/0286 7 (256,448,3)
|
| 530 |
+
00037/0345 7 (256,448,3)
|
| 531 |
+
00037/0449 7 (256,448,3)
|
| 532 |
+
00037/0450 7 (256,448,3)
|
| 533 |
+
00037/0820 7 (256,448,3)
|
| 534 |
+
00037/0824 7 (256,448,3)
|
| 535 |
+
00037/0859 7 (256,448,3)
|
| 536 |
+
00037/0899 7 (256,448,3)
|
| 537 |
+
00037/0906 7 (256,448,3)
|
| 538 |
+
00038/0535 7 (256,448,3)
|
| 539 |
+
00038/0572 7 (256,448,3)
|
| 540 |
+
00038/0675 7 (256,448,3)
|
| 541 |
+
00038/0731 7 (256,448,3)
|
| 542 |
+
00038/0732 7 (256,448,3)
|
| 543 |
+
00038/0744 7 (256,448,3)
|
| 544 |
+
00038/0755 7 (256,448,3)
|
| 545 |
+
00039/0002 7 (256,448,3)
|
| 546 |
+
00039/0013 7 (256,448,3)
|
| 547 |
+
00039/0247 7 (256,448,3)
|
| 548 |
+
00039/0489 7 (256,448,3)
|
| 549 |
+
00039/0504 7 (256,448,3)
|
| 550 |
+
00039/0558 7 (256,448,3)
|
| 551 |
+
00039/0686 7 (256,448,3)
|
| 552 |
+
00039/0727 7 (256,448,3)
|
| 553 |
+
00039/0769 7 (256,448,3)
|
| 554 |
+
00040/0081 7 (256,448,3)
|
| 555 |
+
00040/0082 7 (256,448,3)
|
| 556 |
+
00040/0402 7 (256,448,3)
|
| 557 |
+
00040/0407 7 (256,448,3)
|
| 558 |
+
00040/0408 7 (256,448,3)
|
| 559 |
+
00040/0410 7 (256,448,3)
|
| 560 |
+
00040/0411 7 (256,448,3)
|
| 561 |
+
00040/0412 7 (256,448,3)
|
| 562 |
+
00040/0413 7 (256,448,3)
|
| 563 |
+
00040/0415 7 (256,448,3)
|
| 564 |
+
00040/0421 7 (256,448,3)
|
| 565 |
+
00040/0422 7 (256,448,3)
|
| 566 |
+
00040/0426 7 (256,448,3)
|
| 567 |
+
00040/0438 7 (256,448,3)
|
| 568 |
+
00040/0439 7 (256,448,3)
|
| 569 |
+
00040/0440 7 (256,448,3)
|
| 570 |
+
00040/0443 7 (256,448,3)
|
| 571 |
+
00040/0457 7 (256,448,3)
|
| 572 |
+
00040/0459 7 (256,448,3)
|
| 573 |
+
00040/0725 7 (256,448,3)
|
| 574 |
+
00040/0727 7 (256,448,3)
|
| 575 |
+
00040/0936 7 (256,448,3)
|
| 576 |
+
00040/0959 7 (256,448,3)
|
| 577 |
+
00040/0964 7 (256,448,3)
|
| 578 |
+
00040/0968 7 (256,448,3)
|
| 579 |
+
00040/0974 7 (256,448,3)
|
| 580 |
+
00040/0978 7 (256,448,3)
|
| 581 |
+
00040/0979 7 (256,448,3)
|
| 582 |
+
00040/0989 7 (256,448,3)
|
| 583 |
+
00040/0993 7 (256,448,3)
|
| 584 |
+
00040/0994 7 (256,448,3)
|
| 585 |
+
00040/0997 7 (256,448,3)
|
| 586 |
+
00041/0001 7 (256,448,3)
|
| 587 |
+
00041/0007 7 (256,448,3)
|
| 588 |
+
00041/0019 7 (256,448,3)
|
| 589 |
+
00041/0040 7 (256,448,3)
|
| 590 |
+
00041/0350 7 (256,448,3)
|
| 591 |
+
00041/0357 7 (256,448,3)
|
| 592 |
+
00041/0393 7 (256,448,3)
|
| 593 |
+
00041/0890 7 (256,448,3)
|
| 594 |
+
00041/0909 7 (256,448,3)
|
| 595 |
+
00041/0915 7 (256,448,3)
|
| 596 |
+
00041/0933 7 (256,448,3)
|
| 597 |
+
00042/0017 7 (256,448,3)
|
| 598 |
+
00042/0332 7 (256,448,3)
|
| 599 |
+
00042/0346 7 (256,448,3)
|
| 600 |
+
00042/0350 7 (256,448,3)
|
| 601 |
+
00042/0356 7 (256,448,3)
|
| 602 |
+
00042/0382 7 (256,448,3)
|
| 603 |
+
00042/0389 7 (256,448,3)
|
| 604 |
+
00042/0539 7 (256,448,3)
|
| 605 |
+
00042/0546 7 (256,448,3)
|
| 606 |
+
00042/0550 7 (256,448,3)
|
| 607 |
+
00042/0553 7 (256,448,3)
|
| 608 |
+
00042/0555 7 (256,448,3)
|
| 609 |
+
00042/0560 7 (256,448,3)
|
| 610 |
+
00042/0570 7 (256,448,3)
|
| 611 |
+
00043/0119 7 (256,448,3)
|
| 612 |
+
00043/0122 7 (256,448,3)
|
| 613 |
+
00043/0168 7 (256,448,3)
|
| 614 |
+
00043/0274 7 (256,448,3)
|
| 615 |
+
00043/0304 7 (256,448,3)
|
| 616 |
+
00043/0731 7 (256,448,3)
|
| 617 |
+
00043/0735 7 (256,448,3)
|
| 618 |
+
00043/0739 7 (256,448,3)
|
| 619 |
+
00043/0740 7 (256,448,3)
|
| 620 |
+
00044/0212 7 (256,448,3)
|
| 621 |
+
00044/0432 7 (256,448,3)
|
| 622 |
+
00044/0934 7 (256,448,3)
|
| 623 |
+
00044/0940 7 (256,448,3)
|
| 624 |
+
00044/0987 7 (256,448,3)
|
| 625 |
+
00045/0004 7 (256,448,3)
|
| 626 |
+
00045/0009 7 (256,448,3)
|
| 627 |
+
00045/0011 7 (256,448,3)
|
| 628 |
+
00045/0019 7 (256,448,3)
|
| 629 |
+
00045/0023 7 (256,448,3)
|
| 630 |
+
00045/0289 7 (256,448,3)
|
| 631 |
+
00045/0760 7 (256,448,3)
|
| 632 |
+
00045/0779 7 (256,448,3)
|
| 633 |
+
00045/0816 7 (256,448,3)
|
| 634 |
+
00045/0820 7 (256,448,3)
|
| 635 |
+
00046/0132 7 (256,448,3)
|
| 636 |
+
00046/0350 7 (256,448,3)
|
| 637 |
+
00046/0356 7 (256,448,3)
|
| 638 |
+
00046/0357 7 (256,448,3)
|
| 639 |
+
00046/0379 7 (256,448,3)
|
| 640 |
+
00046/0410 7 (256,448,3)
|
| 641 |
+
00046/0412 7 (256,448,3)
|
| 642 |
+
00046/0481 7 (256,448,3)
|
| 643 |
+
00046/0497 7 (256,448,3)
|
| 644 |
+
00046/0510 7 (256,448,3)
|
| 645 |
+
00046/0515 7 (256,448,3)
|
| 646 |
+
00046/0529 7 (256,448,3)
|
| 647 |
+
00046/0544 7 (256,448,3)
|
| 648 |
+
00046/0545 7 (256,448,3)
|
| 649 |
+
00046/0552 7 (256,448,3)
|
| 650 |
+
00046/0559 7 (256,448,3)
|
| 651 |
+
00046/0589 7 (256,448,3)
|
| 652 |
+
00046/0642 7 (256,448,3)
|
| 653 |
+
00046/0724 7 (256,448,3)
|
| 654 |
+
00046/0758 7 (256,448,3)
|
| 655 |
+
00046/0930 7 (256,448,3)
|
| 656 |
+
00046/0953 7 (256,448,3)
|
| 657 |
+
00047/0013 7 (256,448,3)
|
| 658 |
+
00047/0014 7 (256,448,3)
|
| 659 |
+
00047/0017 7 (256,448,3)
|
| 660 |
+
00047/0076 7 (256,448,3)
|
| 661 |
+
00047/0151 7 (256,448,3)
|
| 662 |
+
00047/0797 7 (256,448,3)
|
| 663 |
+
00048/0014 7 (256,448,3)
|
| 664 |
+
00048/0021 7 (256,448,3)
|
| 665 |
+
00048/0026 7 (256,448,3)
|
| 666 |
+
00048/0030 7 (256,448,3)
|
| 667 |
+
00048/0039 7 (256,448,3)
|
| 668 |
+
00048/0045 7 (256,448,3)
|
| 669 |
+
00048/0049 7 (256,448,3)
|
| 670 |
+
00048/0145 7 (256,448,3)
|
| 671 |
+
00048/0188 7 (256,448,3)
|
| 672 |
+
00048/0302 7 (256,448,3)
|
| 673 |
+
00048/0361 7 (256,448,3)
|
| 674 |
+
00048/0664 7 (256,448,3)
|
| 675 |
+
00048/0672 7 (256,448,3)
|
| 676 |
+
00048/0681 7 (256,448,3)
|
| 677 |
+
00048/0689 7 (256,448,3)
|
| 678 |
+
00048/0690 7 (256,448,3)
|
| 679 |
+
00048/0691 7 (256,448,3)
|
| 680 |
+
00048/0711 7 (256,448,3)
|
| 681 |
+
00049/0085 7 (256,448,3)
|
| 682 |
+
00049/0810 7 (256,448,3)
|
| 683 |
+
00049/0858 7 (256,448,3)
|
| 684 |
+
00049/0865 7 (256,448,3)
|
| 685 |
+
00049/0871 7 (256,448,3)
|
| 686 |
+
00049/0903 7 (256,448,3)
|
| 687 |
+
00049/0928 7 (256,448,3)
|
| 688 |
+
00050/0092 7 (256,448,3)
|
| 689 |
+
00050/0101 7 (256,448,3)
|
| 690 |
+
00050/0108 7 (256,448,3)
|
| 691 |
+
00050/0112 7 (256,448,3)
|
| 692 |
+
00050/0120 7 (256,448,3)
|
| 693 |
+
00050/0128 7 (256,448,3)
|
| 694 |
+
00050/0383 7 (256,448,3)
|
| 695 |
+
00050/0395 7 (256,448,3)
|
| 696 |
+
00050/0405 7 (256,448,3)
|
| 697 |
+
00050/0632 7 (256,448,3)
|
| 698 |
+
00050/0648 7 (256,448,3)
|
| 699 |
+
00050/0649 7 (256,448,3)
|
| 700 |
+
00050/0659 7 (256,448,3)
|
| 701 |
+
00050/0699 7 (256,448,3)
|
| 702 |
+
00050/0708 7 (256,448,3)
|
| 703 |
+
00050/0716 7 (256,448,3)
|
| 704 |
+
00050/0758 7 (256,448,3)
|
| 705 |
+
00050/0761 7 (256,448,3)
|
| 706 |
+
00051/0572 7 (256,448,3)
|
| 707 |
+
00052/0163 7 (256,448,3)
|
| 708 |
+
00052/0242 7 (256,448,3)
|
| 709 |
+
00052/0260 7 (256,448,3)
|
| 710 |
+
00052/0322 7 (256,448,3)
|
| 711 |
+
00052/0333 7 (256,448,3)
|
| 712 |
+
00052/0806 7 (256,448,3)
|
| 713 |
+
00052/0813 7 (256,448,3)
|
| 714 |
+
00052/0821 7 (256,448,3)
|
| 715 |
+
00052/0830 7 (256,448,3)
|
| 716 |
+
00052/0914 7 (256,448,3)
|
| 717 |
+
00052/0923 7 (256,448,3)
|
| 718 |
+
00052/0959 7 (256,448,3)
|
| 719 |
+
00053/0288 7 (256,448,3)
|
| 720 |
+
00053/0290 7 (256,448,3)
|
| 721 |
+
00053/0323 7 (256,448,3)
|
| 722 |
+
00053/0337 7 (256,448,3)
|
| 723 |
+
00053/0340 7 (256,448,3)
|
| 724 |
+
00053/0437 7 (256,448,3)
|
| 725 |
+
00053/0595 7 (256,448,3)
|
| 726 |
+
00053/0739 7 (256,448,3)
|
| 727 |
+
00053/0761 7 (256,448,3)
|
| 728 |
+
00054/0014 7 (256,448,3)
|
| 729 |
+
00054/0017 7 (256,448,3)
|
| 730 |
+
00054/0178 7 (256,448,3)
|
| 731 |
+
00054/0183 7 (256,448,3)
|
| 732 |
+
00054/0196 7 (256,448,3)
|
| 733 |
+
00054/0205 7 (256,448,3)
|
| 734 |
+
00054/0214 7 (256,448,3)
|
| 735 |
+
00054/0289 7 (256,448,3)
|
| 736 |
+
00054/0453 7 (256,448,3)
|
| 737 |
+
00054/0498 7 (256,448,3)
|
| 738 |
+
00054/0502 7 (256,448,3)
|
| 739 |
+
00054/0514 7 (256,448,3)
|
| 740 |
+
00054/0773 7 (256,448,3)
|
| 741 |
+
00055/0001 7 (256,448,3)
|
| 742 |
+
00055/0115 7 (256,448,3)
|
| 743 |
+
00055/0118 7 (256,448,3)
|
| 744 |
+
00055/0171 7 (256,448,3)
|
| 745 |
+
00055/0214 7 (256,448,3)
|
| 746 |
+
00055/0354 7 (256,448,3)
|
| 747 |
+
00055/0449 7 (256,448,3)
|
| 748 |
+
00055/0473 7 (256,448,3)
|
| 749 |
+
00055/0649 7 (256,448,3)
|
| 750 |
+
00055/0800 7 (256,448,3)
|
| 751 |
+
00055/0803 7 (256,448,3)
|
| 752 |
+
00055/0990 7 (256,448,3)
|
| 753 |
+
00056/0041 7 (256,448,3)
|
| 754 |
+
00056/0120 7 (256,448,3)
|
| 755 |
+
00056/0293 7 (256,448,3)
|
| 756 |
+
00056/0357 7 (256,448,3)
|
| 757 |
+
00056/0506 7 (256,448,3)
|
| 758 |
+
00056/0561 7 (256,448,3)
|
| 759 |
+
00056/0567 7 (256,448,3)
|
| 760 |
+
00056/0575 7 (256,448,3)
|
| 761 |
+
00057/0175 7 (256,448,3)
|
| 762 |
+
00057/0495 7 (256,448,3)
|
| 763 |
+
00057/0498 7 (256,448,3)
|
| 764 |
+
00057/0506 7 (256,448,3)
|
| 765 |
+
00057/0612 7 (256,448,3)
|
| 766 |
+
00057/0620 7 (256,448,3)
|
| 767 |
+
00057/0623 7 (256,448,3)
|
| 768 |
+
00057/0635 7 (256,448,3)
|
| 769 |
+
00057/0773 7 (256,448,3)
|
| 770 |
+
00057/0778 7 (256,448,3)
|
| 771 |
+
00057/0867 7 (256,448,3)
|
| 772 |
+
00057/0976 7 (256,448,3)
|
| 773 |
+
00057/0980 7 (256,448,3)
|
| 774 |
+
00057/0985 7 (256,448,3)
|
| 775 |
+
00057/0992 7 (256,448,3)
|
| 776 |
+
00058/0009 7 (256,448,3)
|
| 777 |
+
00058/0076 7 (256,448,3)
|
| 778 |
+
00058/0078 7 (256,448,3)
|
| 779 |
+
00058/0279 7 (256,448,3)
|
| 780 |
+
00058/0283 7 (256,448,3)
|
| 781 |
+
00058/0286 7 (256,448,3)
|
| 782 |
+
00058/0350 7 (256,448,3)
|
| 783 |
+
00058/0380 7 (256,448,3)
|
| 784 |
+
00061/0132 7 (256,448,3)
|
| 785 |
+
00061/0141 7 (256,448,3)
|
| 786 |
+
00061/0156 7 (256,448,3)
|
| 787 |
+
00061/0159 7 (256,448,3)
|
| 788 |
+
00061/0168 7 (256,448,3)
|
| 789 |
+
00061/0170 7 (256,448,3)
|
| 790 |
+
00061/0186 7 (256,448,3)
|
| 791 |
+
00061/0219 7 (256,448,3)
|
| 792 |
+
00061/0227 7 (256,448,3)
|
| 793 |
+
00061/0238 7 (256,448,3)
|
| 794 |
+
00061/0256 7 (256,448,3)
|
| 795 |
+
00061/0303 7 (256,448,3)
|
| 796 |
+
00061/0312 7 (256,448,3)
|
| 797 |
+
00061/0313 7 (256,448,3)
|
| 798 |
+
00061/0325 7 (256,448,3)
|
| 799 |
+
00061/0367 7 (256,448,3)
|
| 800 |
+
00061/0369 7 (256,448,3)
|
| 801 |
+
00061/0387 7 (256,448,3)
|
| 802 |
+
00061/0396 7 (256,448,3)
|
| 803 |
+
00061/0486 7 (256,448,3)
|
| 804 |
+
00061/0895 7 (256,448,3)
|
| 805 |
+
00061/0897 7 (256,448,3)
|
| 806 |
+
00062/0846 7 (256,448,3)
|
| 807 |
+
00063/0156 7 (256,448,3)
|
| 808 |
+
00063/0184 7 (256,448,3)
|
| 809 |
+
00063/0191 7 (256,448,3)
|
| 810 |
+
00063/0334 7 (256,448,3)
|
| 811 |
+
00063/0350 7 (256,448,3)
|
| 812 |
+
00063/0499 7 (256,448,3)
|
| 813 |
+
00063/0878 7 (256,448,3)
|
| 814 |
+
00064/0004 7 (256,448,3)
|
| 815 |
+
00064/0264 7 (256,448,3)
|
| 816 |
+
00064/0735 7 (256,448,3)
|
| 817 |
+
00064/0738 7 (256,448,3)
|
| 818 |
+
00065/0105 7 (256,448,3)
|
| 819 |
+
00065/0169 7 (256,448,3)
|
| 820 |
+
00065/0305 7 (256,448,3)
|
| 821 |
+
00065/0324 7 (256,448,3)
|
| 822 |
+
00065/0353 7 (256,448,3)
|
| 823 |
+
00065/0520 7 (256,448,3)
|
| 824 |
+
00065/0533 7 (256,448,3)
|
| 825 |
+
00065/0545 7 (256,448,3)
|
| 826 |
+
00065/0551 7 (256,448,3)
|
| 827 |
+
00065/0568 7 (256,448,3)
|
| 828 |
+
00065/0603 7 (256,448,3)
|
| 829 |
+
00065/0884 7 (256,448,3)
|
| 830 |
+
00065/0988 7 (256,448,3)
|
| 831 |
+
00066/0002 7 (256,448,3)
|
| 832 |
+
00066/0011 7 (256,448,3)
|
| 833 |
+
00066/0031 7 (256,448,3)
|
| 834 |
+
00066/0037 7 (256,448,3)
|
| 835 |
+
00066/0136 7 (256,448,3)
|
| 836 |
+
00066/0137 7 (256,448,3)
|
| 837 |
+
00066/0150 7 (256,448,3)
|
| 838 |
+
00066/0166 7 (256,448,3)
|
| 839 |
+
00066/0178 7 (256,448,3)
|
| 840 |
+
00066/0357 7 (256,448,3)
|
| 841 |
+
00066/0428 7 (256,448,3)
|
| 842 |
+
00066/0483 7 (256,448,3)
|
| 843 |
+
00066/0600 7 (256,448,3)
|
| 844 |
+
00066/0863 7 (256,448,3)
|
| 845 |
+
00066/0873 7 (256,448,3)
|
| 846 |
+
00066/0875 7 (256,448,3)
|
| 847 |
+
00066/0899 7 (256,448,3)
|
| 848 |
+
00067/0020 7 (256,448,3)
|
| 849 |
+
00067/0025 7 (256,448,3)
|
| 850 |
+
00067/0132 7 (256,448,3)
|
| 851 |
+
00067/0492 7 (256,448,3)
|
| 852 |
+
00067/0726 7 (256,448,3)
|
| 853 |
+
00067/0734 7 (256,448,3)
|
| 854 |
+
00067/0744 7 (256,448,3)
|
| 855 |
+
00067/0754 7 (256,448,3)
|
| 856 |
+
00067/0779 7 (256,448,3)
|
| 857 |
+
00068/0078 7 (256,448,3)
|
| 858 |
+
00068/0083 7 (256,448,3)
|
| 859 |
+
00068/0113 7 (256,448,3)
|
| 860 |
+
00068/0117 7 (256,448,3)
|
| 861 |
+
00068/0121 7 (256,448,3)
|
| 862 |
+
00068/0206 7 (256,448,3)
|
| 863 |
+
00068/0261 7 (256,448,3)
|
| 864 |
+
00068/0321 7 (256,448,3)
|
| 865 |
+
00068/0354 7 (256,448,3)
|
| 866 |
+
00068/0380 7 (256,448,3)
|
| 867 |
+
00068/0419 7 (256,448,3)
|
| 868 |
+
00068/0547 7 (256,448,3)
|
| 869 |
+
00068/0561 7 (256,448,3)
|
| 870 |
+
00068/0565 7 (256,448,3)
|
| 871 |
+
00068/0583 7 (256,448,3)
|
| 872 |
+
00068/0599 7 (256,448,3)
|
| 873 |
+
00068/0739 7 (256,448,3)
|
| 874 |
+
00068/0743 7 (256,448,3)
|
| 875 |
+
00068/0754 7 (256,448,3)
|
| 876 |
+
00068/0812 7 (256,448,3)
|
| 877 |
+
00069/0178 7 (256,448,3)
|
| 878 |
+
00070/0025 7 (256,448,3)
|
| 879 |
+
00070/0030 7 (256,448,3)
|
| 880 |
+
00070/0036 7 (256,448,3)
|
| 881 |
+
00070/0042 7 (256,448,3)
|
| 882 |
+
00070/0078 7 (256,448,3)
|
| 883 |
+
00070/0079 7 (256,448,3)
|
| 884 |
+
00070/0362 7 (256,448,3)
|
| 885 |
+
00071/0195 7 (256,448,3)
|
| 886 |
+
00071/0210 7 (256,448,3)
|
| 887 |
+
00071/0211 7 (256,448,3)
|
| 888 |
+
00071/0221 7 (256,448,3)
|
| 889 |
+
00071/0352 7 (256,448,3)
|
| 890 |
+
00071/0354 7 (256,448,3)
|
| 891 |
+
00071/0366 7 (256,448,3)
|
| 892 |
+
00071/0454 7 (256,448,3)
|
| 893 |
+
00071/0464 7 (256,448,3)
|
| 894 |
+
00071/0487 7 (256,448,3)
|
| 895 |
+
00071/0502 7 (256,448,3)
|
| 896 |
+
00071/0561 7 (256,448,3)
|
| 897 |
+
00071/0676 7 (256,448,3)
|
| 898 |
+
00071/0808 7 (256,448,3)
|
| 899 |
+
00071/0813 7 (256,448,3)
|
| 900 |
+
00071/0836 7 (256,448,3)
|
| 901 |
+
00072/0286 7 (256,448,3)
|
| 902 |
+
00072/0290 7 (256,448,3)
|
| 903 |
+
00072/0298 7 (256,448,3)
|
| 904 |
+
00072/0302 7 (256,448,3)
|
| 905 |
+
00072/0333 7 (256,448,3)
|
| 906 |
+
00072/0590 7 (256,448,3)
|
| 907 |
+
00072/0793 7 (256,448,3)
|
| 908 |
+
00072/0803 7 (256,448,3)
|
| 909 |
+
00072/0833 7 (256,448,3)
|
| 910 |
+
00073/0049 7 (256,448,3)
|
| 911 |
+
00073/0050 7 (256,448,3)
|
| 912 |
+
00073/0388 7 (256,448,3)
|
| 913 |
+
00073/0480 7 (256,448,3)
|
| 914 |
+
00073/0485 7 (256,448,3)
|
| 915 |
+
00073/0611 7 (256,448,3)
|
| 916 |
+
00073/0616 7 (256,448,3)
|
| 917 |
+
00073/0714 7 (256,448,3)
|
| 918 |
+
00073/0724 7 (256,448,3)
|
| 919 |
+
00073/0730 7 (256,448,3)
|
| 920 |
+
00074/0034 7 (256,448,3)
|
| 921 |
+
00074/0228 7 (256,448,3)
|
| 922 |
+
00074/0239 7 (256,448,3)
|
| 923 |
+
00074/0275 7 (256,448,3)
|
| 924 |
+
00074/0527 7 (256,448,3)
|
| 925 |
+
00074/0620 7 (256,448,3)
|
| 926 |
+
00074/0764 7 (256,448,3)
|
| 927 |
+
00074/0849 7 (256,448,3)
|
| 928 |
+
00074/0893 7 (256,448,3)
|
| 929 |
+
00075/0333 7 (256,448,3)
|
| 930 |
+
00075/0339 7 (256,448,3)
|
| 931 |
+
00075/0347 7 (256,448,3)
|
| 932 |
+
00075/0399 7 (256,448,3)
|
| 933 |
+
00075/0478 7 (256,448,3)
|
| 934 |
+
00075/0494 7 (256,448,3)
|
| 935 |
+
00075/0678 7 (256,448,3)
|
| 936 |
+
00075/0688 7 (256,448,3)
|
| 937 |
+
00075/0706 7 (256,448,3)
|
| 938 |
+
00075/0709 7 (256,448,3)
|
| 939 |
+
00075/0748 7 (256,448,3)
|
| 940 |
+
00075/0769 7 (256,448,3)
|
| 941 |
+
00075/0777 7 (256,448,3)
|
| 942 |
+
00075/0781 7 (256,448,3)
|
| 943 |
+
00076/0151 7 (256,448,3)
|
| 944 |
+
00076/0159 7 (256,448,3)
|
| 945 |
+
00076/0164 7 (256,448,3)
|
| 946 |
+
00076/0265 7 (256,448,3)
|
| 947 |
+
00076/0269 7 (256,448,3)
|
| 948 |
+
00076/0433 7 (256,448,3)
|
| 949 |
+
00076/0813 7 (256,448,3)
|
| 950 |
+
00076/0817 7 (256,448,3)
|
| 951 |
+
00076/0818 7 (256,448,3)
|
| 952 |
+
00076/0827 7 (256,448,3)
|
| 953 |
+
00076/0874 7 (256,448,3)
|
| 954 |
+
00076/0880 7 (256,448,3)
|
| 955 |
+
00076/0891 7 (256,448,3)
|
| 956 |
+
00076/0894 7 (256,448,3)
|
| 957 |
+
00076/0909 7 (256,448,3)
|
| 958 |
+
00076/0913 7 (256,448,3)
|
| 959 |
+
00076/0926 7 (256,448,3)
|
| 960 |
+
00076/0962 7 (256,448,3)
|
| 961 |
+
00076/0973 7 (256,448,3)
|
| 962 |
+
00076/0986 7 (256,448,3)
|
| 963 |
+
00077/0617 7 (256,448,3)
|
| 964 |
+
00077/0623 7 (256,448,3)
|
| 965 |
+
00077/0628 7 (256,448,3)
|
| 966 |
+
00077/0629 7 (256,448,3)
|
| 967 |
+
00077/0631 7 (256,448,3)
|
| 968 |
+
00077/0639 7 (256,448,3)
|
| 969 |
+
00077/0982 7 (256,448,3)
|
| 970 |
+
00077/0984 7 (256,448,3)
|
| 971 |
+
00077/0995 7 (256,448,3)
|
| 972 |
+
00077/0998 7 (256,448,3)
|
| 973 |
+
00078/0001 7 (256,448,3)
|
| 974 |
+
00078/0015 7 (256,448,3)
|
| 975 |
+
00078/0157 7 (256,448,3)
|
| 976 |
+
00078/0161 7 (256,448,3)
|
| 977 |
+
00078/0175 7 (256,448,3)
|
| 978 |
+
00078/0178 7 (256,448,3)
|
| 979 |
+
00078/0189 7 (256,448,3)
|
| 980 |
+
00078/0192 7 (256,448,3)
|
| 981 |
+
00078/0229 7 (256,448,3)
|
| 982 |
+
00078/0237 7 (256,448,3)
|
| 983 |
+
00078/0241 7 (256,448,3)
|
| 984 |
+
00078/0249 7 (256,448,3)
|
| 985 |
+
00078/0251 7 (256,448,3)
|
| 986 |
+
00078/0254 7 (256,448,3)
|
| 987 |
+
00078/0258 7 (256,448,3)
|
| 988 |
+
00078/0311 7 (256,448,3)
|
| 989 |
+
00078/0603 7 (256,448,3)
|
| 990 |
+
00078/0607 7 (256,448,3)
|
| 991 |
+
00078/0824 7 (256,448,3)
|
| 992 |
+
00079/0045 7 (256,448,3)
|
| 993 |
+
00079/0048 7 (256,448,3)
|
| 994 |
+
00079/0054 7 (256,448,3)
|
| 995 |
+
00080/0050 7 (256,448,3)
|
| 996 |
+
00080/0488 7 (256,448,3)
|
| 997 |
+
00080/0494 7 (256,448,3)
|
| 998 |
+
00080/0496 7 (256,448,3)
|
| 999 |
+
00080/0499 7 (256,448,3)
|
| 1000 |
+
00080/0502 7 (256,448,3)
|
| 1001 |
+
00080/0510 7 (256,448,3)
|
| 1002 |
+
00080/0534 7 (256,448,3)
|
| 1003 |
+
00080/0558 7 (256,448,3)
|
| 1004 |
+
00080/0571 7 (256,448,3)
|
| 1005 |
+
00080/0709 7 (256,448,3)
|
| 1006 |
+
00080/0882 7 (256,448,3)
|
| 1007 |
+
00081/0322 7 (256,448,3)
|
| 1008 |
+
00081/0428 7 (256,448,3)
|
| 1009 |
+
00081/0700 7 (256,448,3)
|
| 1010 |
+
00081/0706 7 (256,448,3)
|
| 1011 |
+
00081/0707 7 (256,448,3)
|
| 1012 |
+
00081/0937 7 (256,448,3)
|
| 1013 |
+
00082/0021 7 (256,448,3)
|
| 1014 |
+
00082/0424 7 (256,448,3)
|
| 1015 |
+
00082/0794 7 (256,448,3)
|
| 1016 |
+
00082/0807 7 (256,448,3)
|
| 1017 |
+
00082/0810 7 (256,448,3)
|
| 1018 |
+
00082/0824 7 (256,448,3)
|
| 1019 |
+
00083/0129 7 (256,448,3)
|
| 1020 |
+
00083/0131 7 (256,448,3)
|
| 1021 |
+
00083/0249 7 (256,448,3)
|
| 1022 |
+
00083/0250 7 (256,448,3)
|
| 1023 |
+
00083/0656 7 (256,448,3)
|
| 1024 |
+
00083/0812 7 (256,448,3)
|
| 1025 |
+
00083/0819 7 (256,448,3)
|
| 1026 |
+
00083/0824 7 (256,448,3)
|
| 1027 |
+
00083/0827 7 (256,448,3)
|
| 1028 |
+
00083/0841 7 (256,448,3)
|
| 1029 |
+
00083/0963 7 (256,448,3)
|
| 1030 |
+
00084/0047 7 (256,448,3)
|
| 1031 |
+
00084/0319 7 (256,448,3)
|
| 1032 |
+
00084/0334 7 (256,448,3)
|
| 1033 |
+
00084/0363 7 (256,448,3)
|
| 1034 |
+
00084/0493 7 (256,448,3)
|
| 1035 |
+
00084/0655 7 (256,448,3)
|
| 1036 |
+
00084/0752 7 (256,448,3)
|
| 1037 |
+
00084/0813 7 (256,448,3)
|
| 1038 |
+
00084/0886 7 (256,448,3)
|
| 1039 |
+
00084/0948 7 (256,448,3)
|
| 1040 |
+
00084/0976 7 (256,448,3)
|
| 1041 |
+
00085/0512 7 (256,448,3)
|
| 1042 |
+
00085/0641 7 (256,448,3)
|
| 1043 |
+
00085/0653 7 (256,448,3)
|
| 1044 |
+
00085/0655 7 (256,448,3)
|
| 1045 |
+
00085/0697 7 (256,448,3)
|
| 1046 |
+
00085/0698 7 (256,448,3)
|
| 1047 |
+
00085/0700 7 (256,448,3)
|
| 1048 |
+
00085/0703 7 (256,448,3)
|
| 1049 |
+
00085/0705 7 (256,448,3)
|
| 1050 |
+
00085/0709 7 (256,448,3)
|
| 1051 |
+
00085/0713 7 (256,448,3)
|
| 1052 |
+
00085/0739 7 (256,448,3)
|
| 1053 |
+
00085/0750 7 (256,448,3)
|
| 1054 |
+
00085/0763 7 (256,448,3)
|
| 1055 |
+
00085/0765 7 (256,448,3)
|
| 1056 |
+
00085/0769 7 (256,448,3)
|
| 1057 |
+
00085/0863 7 (256,448,3)
|
| 1058 |
+
00085/0868 7 (256,448,3)
|
| 1059 |
+
00085/0927 7 (256,448,3)
|
| 1060 |
+
00085/0936 7 (256,448,3)
|
| 1061 |
+
00085/0965 7 (256,448,3)
|
| 1062 |
+
00085/0969 7 (256,448,3)
|
| 1063 |
+
00085/0974 7 (256,448,3)
|
| 1064 |
+
00085/0981 7 (256,448,3)
|
| 1065 |
+
00085/0982 7 (256,448,3)
|
| 1066 |
+
00085/1000 7 (256,448,3)
|
| 1067 |
+
00086/0003 7 (256,448,3)
|
| 1068 |
+
00086/0009 7 (256,448,3)
|
| 1069 |
+
00086/0011 7 (256,448,3)
|
| 1070 |
+
00086/0028 7 (256,448,3)
|
| 1071 |
+
00086/0032 7 (256,448,3)
|
| 1072 |
+
00086/0034 7 (256,448,3)
|
| 1073 |
+
00086/0035 7 (256,448,3)
|
| 1074 |
+
00086/0042 7 (256,448,3)
|
| 1075 |
+
00086/0064 7 (256,448,3)
|
| 1076 |
+
00086/0066 7 (256,448,3)
|
| 1077 |
+
00086/0095 7 (256,448,3)
|
| 1078 |
+
00086/0099 7 (256,448,3)
|
| 1079 |
+
00086/0101 7 (256,448,3)
|
| 1080 |
+
00086/0104 7 (256,448,3)
|
| 1081 |
+
00086/0115 7 (256,448,3)
|
| 1082 |
+
00086/0116 7 (256,448,3)
|
| 1083 |
+
00086/0284 7 (256,448,3)
|
| 1084 |
+
00086/0291 7 (256,448,3)
|
| 1085 |
+
00086/0295 7 (256,448,3)
|
| 1086 |
+
00086/0302 7 (256,448,3)
|
| 1087 |
+
00086/0318 7 (256,448,3)
|
| 1088 |
+
00086/0666 7 (256,448,3)
|
| 1089 |
+
00086/0797 7 (256,448,3)
|
| 1090 |
+
00086/0851 7 (256,448,3)
|
| 1091 |
+
00086/0855 7 (256,448,3)
|
| 1092 |
+
00086/0874 7 (256,448,3)
|
| 1093 |
+
00086/0878 7 (256,448,3)
|
| 1094 |
+
00086/0881 7 (256,448,3)
|
| 1095 |
+
00086/0883 7 (256,448,3)
|
| 1096 |
+
00086/0896 7 (256,448,3)
|
| 1097 |
+
00086/0899 7 (256,448,3)
|
| 1098 |
+
00086/0903 7 (256,448,3)
|
| 1099 |
+
00086/0989 7 (256,448,3)
|
| 1100 |
+
00087/0008 7 (256,448,3)
|
| 1101 |
+
00087/0429 7 (256,448,3)
|
| 1102 |
+
00087/0511 7 (256,448,3)
|
| 1103 |
+
00088/0241 7 (256,448,3)
|
| 1104 |
+
00088/0319 7 (256,448,3)
|
| 1105 |
+
00088/0323 7 (256,448,3)
|
| 1106 |
+
00088/0411 7 (256,448,3)
|
| 1107 |
+
00088/0427 7 (256,448,3)
|
| 1108 |
+
00088/0452 7 (256,448,3)
|
| 1109 |
+
00088/0463 7 (256,448,3)
|
| 1110 |
+
00088/0476 7 (256,448,3)
|
| 1111 |
+
00088/0496 7 (256,448,3)
|
| 1112 |
+
00088/0559 7 (256,448,3)
|
| 1113 |
+
00089/0058 7 (256,448,3)
|
| 1114 |
+
00089/0061 7 (256,448,3)
|
| 1115 |
+
00089/0069 7 (256,448,3)
|
| 1116 |
+
00089/0077 7 (256,448,3)
|
| 1117 |
+
00089/0096 7 (256,448,3)
|
| 1118 |
+
00089/0099 7 (256,448,3)
|
| 1119 |
+
00089/0100 7 (256,448,3)
|
| 1120 |
+
00089/0211 7 (256,448,3)
|
| 1121 |
+
00089/0380 7 (256,448,3)
|
| 1122 |
+
00089/0381 7 (256,448,3)
|
| 1123 |
+
00089/0384 7 (256,448,3)
|
| 1124 |
+
00089/0390 7 (256,448,3)
|
| 1125 |
+
00089/0393 7 (256,448,3)
|
| 1126 |
+
00089/0394 7 (256,448,3)
|
| 1127 |
+
00089/0395 7 (256,448,3)
|
| 1128 |
+
00089/0406 7 (256,448,3)
|
| 1129 |
+
00089/0410 7 (256,448,3)
|
| 1130 |
+
00089/0412 7 (256,448,3)
|
| 1131 |
+
00089/0703 7 (256,448,3)
|
| 1132 |
+
00089/0729 7 (256,448,3)
|
| 1133 |
+
00089/0930 7 (256,448,3)
|
| 1134 |
+
00089/0952 7 (256,448,3)
|
| 1135 |
+
00090/0062 7 (256,448,3)
|
| 1136 |
+
00090/0101 7 (256,448,3)
|
| 1137 |
+
00090/0213 7 (256,448,3)
|
| 1138 |
+
00090/0216 7 (256,448,3)
|
| 1139 |
+
00090/0268 7 (256,448,3)
|
| 1140 |
+
00090/0406 7 (256,448,3)
|
| 1141 |
+
00090/0411 7 (256,448,3)
|
| 1142 |
+
00090/0442 7 (256,448,3)
|
| 1143 |
+
00090/0535 7 (256,448,3)
|
| 1144 |
+
00090/0542 7 (256,448,3)
|
| 1145 |
+
00090/0571 7 (256,448,3)
|
| 1146 |
+
00090/0934 7 (256,448,3)
|
| 1147 |
+
00090/0938 7 (256,448,3)
|
| 1148 |
+
00090/0947 7 (256,448,3)
|
| 1149 |
+
00091/0066 7 (256,448,3)
|
| 1150 |
+
00091/0448 7 (256,448,3)
|
| 1151 |
+
00091/0451 7 (256,448,3)
|
| 1152 |
+
00091/0454 7 (256,448,3)
|
| 1153 |
+
00091/0457 7 (256,448,3)
|
| 1154 |
+
00091/0467 7 (256,448,3)
|
| 1155 |
+
00091/0470 7 (256,448,3)
|
| 1156 |
+
00091/0477 7 (256,448,3)
|
| 1157 |
+
00091/0583 7 (256,448,3)
|
| 1158 |
+
00091/0981 7 (256,448,3)
|
| 1159 |
+
00091/0994 7 (256,448,3)
|
| 1160 |
+
00092/0112 7 (256,448,3)
|
| 1161 |
+
00092/0119 7 (256,448,3)
|
| 1162 |
+
00092/0129 7 (256,448,3)
|
| 1163 |
+
00092/0146 7 (256,448,3)
|
| 1164 |
+
00092/0149 7 (256,448,3)
|
| 1165 |
+
00092/0608 7 (256,448,3)
|
| 1166 |
+
00092/0643 7 (256,448,3)
|
| 1167 |
+
00092/0646 7 (256,448,3)
|
| 1168 |
+
00092/0766 7 (256,448,3)
|
| 1169 |
+
00092/0768 7 (256,448,3)
|
| 1170 |
+
00092/0779 7 (256,448,3)
|
| 1171 |
+
00093/0081 7 (256,448,3)
|
| 1172 |
+
00093/0085 7 (256,448,3)
|
| 1173 |
+
00093/0135 7 (256,448,3)
|
| 1174 |
+
00093/0241 7 (256,448,3)
|
| 1175 |
+
00093/0277 7 (256,448,3)
|
| 1176 |
+
00093/0283 7 (256,448,3)
|
| 1177 |
+
00093/0320 7 (256,448,3)
|
| 1178 |
+
00093/0598 7 (256,448,3)
|
| 1179 |
+
00094/0159 7 (256,448,3)
|
| 1180 |
+
00094/0253 7 (256,448,3)
|
| 1181 |
+
00094/0265 7 (256,448,3)
|
| 1182 |
+
00094/0267 7 (256,448,3)
|
| 1183 |
+
00094/0269 7 (256,448,3)
|
| 1184 |
+
00094/0281 7 (256,448,3)
|
| 1185 |
+
00094/0293 7 (256,448,3)
|
| 1186 |
+
00094/0404 7 (256,448,3)
|
| 1187 |
+
00094/0593 7 (256,448,3)
|
| 1188 |
+
00094/0612 7 (256,448,3)
|
| 1189 |
+
00094/0638 7 (256,448,3)
|
| 1190 |
+
00094/0656 7 (256,448,3)
|
| 1191 |
+
00094/0668 7 (256,448,3)
|
| 1192 |
+
00094/0786 7 (256,448,3)
|
| 1193 |
+
00094/0870 7 (256,448,3)
|
| 1194 |
+
00094/0897 7 (256,448,3)
|
| 1195 |
+
00094/0900 7 (256,448,3)
|
| 1196 |
+
00094/0944 7 (256,448,3)
|
| 1197 |
+
00094/0946 7 (256,448,3)
|
| 1198 |
+
00094/0952 7 (256,448,3)
|
| 1199 |
+
00094/0969 7 (256,448,3)
|
| 1200 |
+
00094/0973 7 (256,448,3)
|
| 1201 |
+
00094/0981 7 (256,448,3)
|
| 1202 |
+
00095/0088 7 (256,448,3)
|
| 1203 |
+
00095/0125 7 (256,448,3)
|
| 1204 |
+
00095/0130 7 (256,448,3)
|
| 1205 |
+
00095/0142 7 (256,448,3)
|
| 1206 |
+
00095/0151 7 (256,448,3)
|
| 1207 |
+
00095/0180 7 (256,448,3)
|
| 1208 |
+
00095/0192 7 (256,448,3)
|
| 1209 |
+
00095/0194 7 (256,448,3)
|
| 1210 |
+
00095/0195 7 (256,448,3)
|
| 1211 |
+
00095/0204 7 (256,448,3)
|
| 1212 |
+
00095/0245 7 (256,448,3)
|
| 1213 |
+
00095/0315 7 (256,448,3)
|
| 1214 |
+
00095/0321 7 (256,448,3)
|
| 1215 |
+
00095/0324 7 (256,448,3)
|
| 1216 |
+
00095/0327 7 (256,448,3)
|
| 1217 |
+
00095/0730 7 (256,448,3)
|
| 1218 |
+
00095/0731 7 (256,448,3)
|
| 1219 |
+
00095/0741 7 (256,448,3)
|
| 1220 |
+
00095/0948 7 (256,448,3)
|
| 1221 |
+
00096/0407 7 (256,448,3)
|
| 1222 |
+
00096/0420 7 (256,448,3)
|
| 1223 |
+
00096/0435 7 (256,448,3)
|
| 1224 |
+
00096/0682 7 (256,448,3)
|
| 1225 |
+
00096/0865 7 (256,448,3)
|
basicsr/data/meta_info/meta_info_Vimeo90K_test_medium_GT.txt
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
basicsr/data/meta_info/meta_info_Vimeo90K_test_slow_GT.txt
ADDED
|
@@ -0,0 +1,1613 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
00001/0266 7 (256,448,3)
|
| 2 |
+
00001/0268 7 (256,448,3)
|
| 3 |
+
00001/0275 7 (256,448,3)
|
| 4 |
+
00001/0278 7 (256,448,3)
|
| 5 |
+
00001/0287 7 (256,448,3)
|
| 6 |
+
00001/0291 7 (256,448,3)
|
| 7 |
+
00001/0627 7 (256,448,3)
|
| 8 |
+
00001/0636 7 (256,448,3)
|
| 9 |
+
00001/0804 7 (256,448,3)
|
| 10 |
+
00001/0837 7 (256,448,3)
|
| 11 |
+
00001/0849 7 (256,448,3)
|
| 12 |
+
00001/0851 7 (256,448,3)
|
| 13 |
+
00001/0852 7 (256,448,3)
|
| 14 |
+
00001/0986 7 (256,448,3)
|
| 15 |
+
00001/0991 7 (256,448,3)
|
| 16 |
+
00002/0007 7 (256,448,3)
|
| 17 |
+
00002/0008 7 (256,448,3)
|
| 18 |
+
00002/0016 7 (256,448,3)
|
| 19 |
+
00002/0036 7 (256,448,3)
|
| 20 |
+
00002/0091 7 (256,448,3)
|
| 21 |
+
00002/0093 7 (256,448,3)
|
| 22 |
+
00002/0209 7 (256,448,3)
|
| 23 |
+
00002/0235 7 (256,448,3)
|
| 24 |
+
00002/0236 7 (256,448,3)
|
| 25 |
+
00002/0241 7 (256,448,3)
|
| 26 |
+
00002/0466 7 (256,448,3)
|
| 27 |
+
00002/0504 7 (256,448,3)
|
| 28 |
+
00002/0960 7 (256,448,3)
|
| 29 |
+
00002/0961 7 (256,448,3)
|
| 30 |
+
00002/0964 7 (256,448,3)
|
| 31 |
+
00003/0007 7 (256,448,3)
|
| 32 |
+
00003/0069 7 (256,448,3)
|
| 33 |
+
00003/0345 7 (256,448,3)
|
| 34 |
+
00003/0347 7 (256,448,3)
|
| 35 |
+
00003/0372 7 (256,448,3)
|
| 36 |
+
00003/0525 7 (256,448,3)
|
| 37 |
+
00003/0652 7 (256,448,3)
|
| 38 |
+
00003/0667 7 (256,448,3)
|
| 39 |
+
00003/0669 7 (256,448,3)
|
| 40 |
+
00003/0706 7 (256,448,3)
|
| 41 |
+
00003/0713 7 (256,448,3)
|
| 42 |
+
00003/0721 7 (256,448,3)
|
| 43 |
+
00003/0747 7 (256,448,3)
|
| 44 |
+
00003/0829 7 (256,448,3)
|
| 45 |
+
00003/0916 7 (256,448,3)
|
| 46 |
+
00003/0918 7 (256,448,3)
|
| 47 |
+
00003/0924 7 (256,448,3)
|
| 48 |
+
00003/0926 7 (256,448,3)
|
| 49 |
+
00003/0927 7 (256,448,3)
|
| 50 |
+
00004/0288 7 (256,448,3)
|
| 51 |
+
00004/0303 7 (256,448,3)
|
| 52 |
+
00004/0307 7 (256,448,3)
|
| 53 |
+
00004/0628 7 (256,448,3)
|
| 54 |
+
00004/0713 7 (256,448,3)
|
| 55 |
+
00004/0715 7 (256,448,3)
|
| 56 |
+
00004/0719 7 (256,448,3)
|
| 57 |
+
00004/0727 7 (256,448,3)
|
| 58 |
+
00004/0821 7 (256,448,3)
|
| 59 |
+
00005/0006 7 (256,448,3)
|
| 60 |
+
00005/0007 7 (256,448,3)
|
| 61 |
+
00005/0012 7 (256,448,3)
|
| 62 |
+
00005/0013 7 (256,448,3)
|
| 63 |
+
00005/0040 7 (256,448,3)
|
| 64 |
+
00005/0055 7 (256,448,3)
|
| 65 |
+
00005/0119 7 (256,448,3)
|
| 66 |
+
00005/0130 7 (256,448,3)
|
| 67 |
+
00005/0185 7 (256,448,3)
|
| 68 |
+
00005/0198 7 (256,448,3)
|
| 69 |
+
00005/0270 7 (256,448,3)
|
| 70 |
+
00005/0541 7 (256,448,3)
|
| 71 |
+
00005/0560 7 (256,448,3)
|
| 72 |
+
00005/0660 7 (256,448,3)
|
| 73 |
+
00005/0682 7 (256,448,3)
|
| 74 |
+
00005/0683 7 (256,448,3)
|
| 75 |
+
00005/0688 7 (256,448,3)
|
| 76 |
+
00005/0706 7 (256,448,3)
|
| 77 |
+
00005/0728 7 (256,448,3)
|
| 78 |
+
00005/0732 7 (256,448,3)
|
| 79 |
+
00005/0739 7 (256,448,3)
|
| 80 |
+
00005/0804 7 (256,448,3)
|
| 81 |
+
00005/0805 7 (256,448,3)
|
| 82 |
+
00005/0827 7 (256,448,3)
|
| 83 |
+
00005/0828 7 (256,448,3)
|
| 84 |
+
00005/0857 7 (256,448,3)
|
| 85 |
+
00005/0861 7 (256,448,3)
|
| 86 |
+
00005/0862 7 (256,448,3)
|
| 87 |
+
00005/0868 7 (256,448,3)
|
| 88 |
+
00005/0872 7 (256,448,3)
|
| 89 |
+
00005/0933 7 (256,448,3)
|
| 90 |
+
00005/0958 7 (256,448,3)
|
| 91 |
+
00005/0960 7 (256,448,3)
|
| 92 |
+
00006/0087 7 (256,448,3)
|
| 93 |
+
00006/0090 7 (256,448,3)
|
| 94 |
+
00006/0351 7 (256,448,3)
|
| 95 |
+
00006/0353 7 (256,448,3)
|
| 96 |
+
00006/0558 7 (256,448,3)
|
| 97 |
+
00006/0588 7 (256,448,3)
|
| 98 |
+
00006/0619 7 (256,448,3)
|
| 99 |
+
00006/0621 7 (256,448,3)
|
| 100 |
+
00006/0748 7 (256,448,3)
|
| 101 |
+
00006/0796 7 (256,448,3)
|
| 102 |
+
00006/0805 7 (256,448,3)
|
| 103 |
+
00006/0807 7 (256,448,3)
|
| 104 |
+
00007/0236 7 (256,448,3)
|
| 105 |
+
00007/0240 7 (256,448,3)
|
| 106 |
+
00007/0243 7 (256,448,3)
|
| 107 |
+
00007/0246 7 (256,448,3)
|
| 108 |
+
00007/0247 7 (256,448,3)
|
| 109 |
+
00007/0252 7 (256,448,3)
|
| 110 |
+
00007/0322 7 (256,448,3)
|
| 111 |
+
00007/0458 7 (256,448,3)
|
| 112 |
+
00007/0492 7 (256,448,3)
|
| 113 |
+
00007/0658 7 (256,448,3)
|
| 114 |
+
00007/0717 7 (256,448,3)
|
| 115 |
+
00007/0722 7 (256,448,3)
|
| 116 |
+
00007/0725 7 (256,448,3)
|
| 117 |
+
00007/0740 7 (256,448,3)
|
| 118 |
+
00007/0748 7 (256,448,3)
|
| 119 |
+
00007/0749 7 (256,448,3)
|
| 120 |
+
00007/0759 7 (256,448,3)
|
| 121 |
+
00007/0772 7 (256,448,3)
|
| 122 |
+
00007/0783 7 (256,448,3)
|
| 123 |
+
00007/0787 7 (256,448,3)
|
| 124 |
+
00007/0883 7 (256,448,3)
|
| 125 |
+
00008/0033 7 (256,448,3)
|
| 126 |
+
00008/0035 7 (256,448,3)
|
| 127 |
+
00008/0091 7 (256,448,3)
|
| 128 |
+
00008/0154 7 (256,448,3)
|
| 129 |
+
00008/0966 7 (256,448,3)
|
| 130 |
+
00008/0987 7 (256,448,3)
|
| 131 |
+
00009/0108 7 (256,448,3)
|
| 132 |
+
00009/0607 7 (256,448,3)
|
| 133 |
+
00009/0668 7 (256,448,3)
|
| 134 |
+
00009/0683 7 (256,448,3)
|
| 135 |
+
00009/0941 7 (256,448,3)
|
| 136 |
+
00009/0949 7 (256,448,3)
|
| 137 |
+
00009/0962 7 (256,448,3)
|
| 138 |
+
00009/0972 7 (256,448,3)
|
| 139 |
+
00009/0974 7 (256,448,3)
|
| 140 |
+
00010/0014 7 (256,448,3)
|
| 141 |
+
00010/0018 7 (256,448,3)
|
| 142 |
+
00010/0043 7 (256,448,3)
|
| 143 |
+
00010/0099 7 (256,448,3)
|
| 144 |
+
00010/0252 7 (256,448,3)
|
| 145 |
+
00010/0296 7 (256,448,3)
|
| 146 |
+
00010/0413 7 (256,448,3)
|
| 147 |
+
00010/0422 7 (256,448,3)
|
| 148 |
+
00010/0516 7 (256,448,3)
|
| 149 |
+
00010/0525 7 (256,448,3)
|
| 150 |
+
00010/0556 7 (256,448,3)
|
| 151 |
+
00010/0701 7 (256,448,3)
|
| 152 |
+
00010/0740 7 (256,448,3)
|
| 153 |
+
00010/0772 7 (256,448,3)
|
| 154 |
+
00010/0831 7 (256,448,3)
|
| 155 |
+
00010/0925 7 (256,448,3)
|
| 156 |
+
00011/0013 7 (256,448,3)
|
| 157 |
+
00011/0016 7 (256,448,3)
|
| 158 |
+
00011/0017 7 (256,448,3)
|
| 159 |
+
00011/0249 7 (256,448,3)
|
| 160 |
+
00011/0826 7 (256,448,3)
|
| 161 |
+
00011/0827 7 (256,448,3)
|
| 162 |
+
00011/0831 7 (256,448,3)
|
| 163 |
+
00011/0833 7 (256,448,3)
|
| 164 |
+
00011/0835 7 (256,448,3)
|
| 165 |
+
00011/0998 7 (256,448,3)
|
| 166 |
+
00012/0023 7 (256,448,3)
|
| 167 |
+
00012/0024 7 (256,448,3)
|
| 168 |
+
00012/0027 7 (256,448,3)
|
| 169 |
+
00012/0037 7 (256,448,3)
|
| 170 |
+
00012/0444 7 (256,448,3)
|
| 171 |
+
00012/0445 7 (256,448,3)
|
| 172 |
+
00012/0451 7 (256,448,3)
|
| 173 |
+
00012/0461 7 (256,448,3)
|
| 174 |
+
00012/0521 7 (256,448,3)
|
| 175 |
+
00012/0758 7 (256,448,3)
|
| 176 |
+
00012/0760 7 (256,448,3)
|
| 177 |
+
00012/0771 7 (256,448,3)
|
| 178 |
+
00012/0903 7 (256,448,3)
|
| 179 |
+
00012/0909 7 (256,448,3)
|
| 180 |
+
00013/0581 7 (256,448,3)
|
| 181 |
+
00013/0786 7 (256,448,3)
|
| 182 |
+
00013/0789 7 (256,448,3)
|
| 183 |
+
00013/0791 7 (256,448,3)
|
| 184 |
+
00013/0798 7 (256,448,3)
|
| 185 |
+
00013/0802 7 (256,448,3)
|
| 186 |
+
00013/0820 7 (256,448,3)
|
| 187 |
+
00013/0850 7 (256,448,3)
|
| 188 |
+
00013/0854 7 (256,448,3)
|
| 189 |
+
00013/0894 7 (256,448,3)
|
| 190 |
+
00013/0919 7 (256,448,3)
|
| 191 |
+
00013/0999 7 (256,448,3)
|
| 192 |
+
00014/0001 7 (256,448,3)
|
| 193 |
+
00014/0014 7 (256,448,3)
|
| 194 |
+
00014/0018 7 (256,448,3)
|
| 195 |
+
00014/0244 7 (256,448,3)
|
| 196 |
+
00014/0475 7 (256,448,3)
|
| 197 |
+
00014/0483 7 (256,448,3)
|
| 198 |
+
00014/0680 7 (256,448,3)
|
| 199 |
+
00014/0700 7 (256,448,3)
|
| 200 |
+
00014/0701 7 (256,448,3)
|
| 201 |
+
00014/0706 7 (256,448,3)
|
| 202 |
+
00014/0712 7 (256,448,3)
|
| 203 |
+
00014/0713 7 (256,448,3)
|
| 204 |
+
00014/0717 7 (256,448,3)
|
| 205 |
+
00014/0719 7 (256,448,3)
|
| 206 |
+
00014/0728 7 (256,448,3)
|
| 207 |
+
00014/0734 7 (256,448,3)
|
| 208 |
+
00014/0736 7 (256,448,3)
|
| 209 |
+
00014/0738 7 (256,448,3)
|
| 210 |
+
00014/0742 7 (256,448,3)
|
| 211 |
+
00014/0745 7 (256,448,3)
|
| 212 |
+
00014/0746 7 (256,448,3)
|
| 213 |
+
00014/0750 7 (256,448,3)
|
| 214 |
+
00014/0769 7 (256,448,3)
|
| 215 |
+
00014/0774 7 (256,448,3)
|
| 216 |
+
00014/0781 7 (256,448,3)
|
| 217 |
+
00014/0782 7 (256,448,3)
|
| 218 |
+
00014/0852 7 (256,448,3)
|
| 219 |
+
00014/0853 7 (256,448,3)
|
| 220 |
+
00014/0855 7 (256,448,3)
|
| 221 |
+
00014/0867 7 (256,448,3)
|
| 222 |
+
00014/0876 7 (256,448,3)
|
| 223 |
+
00014/0881 7 (256,448,3)
|
| 224 |
+
00014/0890 7 (256,448,3)
|
| 225 |
+
00014/0914 7 (256,448,3)
|
| 226 |
+
00015/0033 7 (256,448,3)
|
| 227 |
+
00015/0113 7 (256,448,3)
|
| 228 |
+
00015/0125 7 (256,448,3)
|
| 229 |
+
00015/0185 7 (256,448,3)
|
| 230 |
+
00015/0194 7 (256,448,3)
|
| 231 |
+
00015/0202 7 (256,448,3)
|
| 232 |
+
00015/0312 7 (256,448,3)
|
| 233 |
+
00015/0688 7 (256,448,3)
|
| 234 |
+
00015/0698 7 (256,448,3)
|
| 235 |
+
00015/0788 7 (256,448,3)
|
| 236 |
+
00015/0854 7 (256,448,3)
|
| 237 |
+
00015/0863 7 (256,448,3)
|
| 238 |
+
00015/0864 7 (256,448,3)
|
| 239 |
+
00015/0918 7 (256,448,3)
|
| 240 |
+
00015/0931 7 (256,448,3)
|
| 241 |
+
00016/0276 7 (256,448,3)
|
| 242 |
+
00016/0301 7 (256,448,3)
|
| 243 |
+
00016/0306 7 (256,448,3)
|
| 244 |
+
00016/0324 7 (256,448,3)
|
| 245 |
+
00016/0362 7 (256,448,3)
|
| 246 |
+
00016/0364 7 (256,448,3)
|
| 247 |
+
00016/0370 7 (256,448,3)
|
| 248 |
+
00016/0378 7 (256,448,3)
|
| 249 |
+
00016/0379 7 (256,448,3)
|
| 250 |
+
00016/0402 7 (256,448,3)
|
| 251 |
+
00016/0405 7 (256,448,3)
|
| 252 |
+
00016/0418 7 (256,448,3)
|
| 253 |
+
00016/0419 7 (256,448,3)
|
| 254 |
+
00016/0435 7 (256,448,3)
|
| 255 |
+
00016/0501 7 (256,448,3)
|
| 256 |
+
00016/0561 7 (256,448,3)
|
| 257 |
+
00016/0562 7 (256,448,3)
|
| 258 |
+
00016/0569 7 (256,448,3)
|
| 259 |
+
00016/0591 7 (256,448,3)
|
| 260 |
+
00016/0599 7 (256,448,3)
|
| 261 |
+
00016/0711 7 (256,448,3)
|
| 262 |
+
00016/0713 7 (256,448,3)
|
| 263 |
+
00016/0813 7 (256,448,3)
|
| 264 |
+
00016/0953 7 (256,448,3)
|
| 265 |
+
00016/0960 7 (256,448,3)
|
| 266 |
+
00016/0961 7 (256,448,3)
|
| 267 |
+
00017/0519 7 (256,448,3)
|
| 268 |
+
00017/0523 7 (256,448,3)
|
| 269 |
+
00017/0588 7 (256,448,3)
|
| 270 |
+
00017/0608 7 (256,448,3)
|
| 271 |
+
00017/0609 7 (256,448,3)
|
| 272 |
+
00017/0719 7 (256,448,3)
|
| 273 |
+
00017/0721 7 (256,448,3)
|
| 274 |
+
00017/0727 7 (256,448,3)
|
| 275 |
+
00017/0728 7 (256,448,3)
|
| 276 |
+
00017/0769 7 (256,448,3)
|
| 277 |
+
00017/0775 7 (256,448,3)
|
| 278 |
+
00017/0787 7 (256,448,3)
|
| 279 |
+
00017/0797 7 (256,448,3)
|
| 280 |
+
00018/0043 7 (256,448,3)
|
| 281 |
+
00018/0206 7 (256,448,3)
|
| 282 |
+
00018/0209 7 (256,448,3)
|
| 283 |
+
00018/0211 7 (256,448,3)
|
| 284 |
+
00018/0216 7 (256,448,3)
|
| 285 |
+
00018/0220 7 (256,448,3)
|
| 286 |
+
00018/0221 7 (256,448,3)
|
| 287 |
+
00018/0252 7 (256,448,3)
|
| 288 |
+
00018/0260 7 (256,448,3)
|
| 289 |
+
00018/0331 7 (256,448,3)
|
| 290 |
+
00018/0333 7 (256,448,3)
|
| 291 |
+
00018/0447 7 (256,448,3)
|
| 292 |
+
00018/0523 7 (256,448,3)
|
| 293 |
+
00019/0014 7 (256,448,3)
|
| 294 |
+
00019/0015 7 (256,448,3)
|
| 295 |
+
00019/0019 7 (256,448,3)
|
| 296 |
+
00019/0049 7 (256,448,3)
|
| 297 |
+
00019/0109 7 (256,448,3)
|
| 298 |
+
00019/0114 7 (256,448,3)
|
| 299 |
+
00019/0125 7 (256,448,3)
|
| 300 |
+
00019/0137 7 (256,448,3)
|
| 301 |
+
00019/0140 7 (256,448,3)
|
| 302 |
+
00019/0148 7 (256,448,3)
|
| 303 |
+
00019/0153 7 (256,448,3)
|
| 304 |
+
00019/0155 7 (256,448,3)
|
| 305 |
+
00019/0158 7 (256,448,3)
|
| 306 |
+
00019/0159 7 (256,448,3)
|
| 307 |
+
00019/0160 7 (256,448,3)
|
| 308 |
+
00019/0162 7 (256,448,3)
|
| 309 |
+
00019/0279 7 (256,448,3)
|
| 310 |
+
00019/0282 7 (256,448,3)
|
| 311 |
+
00019/0409 7 (256,448,3)
|
| 312 |
+
00019/0427 7 (256,448,3)
|
| 313 |
+
00019/0430 7 (256,448,3)
|
| 314 |
+
00019/0545 7 (256,448,3)
|
| 315 |
+
00019/0555 7 (256,448,3)
|
| 316 |
+
00019/0558 7 (256,448,3)
|
| 317 |
+
00019/0650 7 (256,448,3)
|
| 318 |
+
00019/0681 7 (256,448,3)
|
| 319 |
+
00019/0747 7 (256,448,3)
|
| 320 |
+
00019/0748 7 (256,448,3)
|
| 321 |
+
00019/0749 7 (256,448,3)
|
| 322 |
+
00019/0752 7 (256,448,3)
|
| 323 |
+
00019/0768 7 (256,448,3)
|
| 324 |
+
00019/0772 7 (256,448,3)
|
| 325 |
+
00019/0773 7 (256,448,3)
|
| 326 |
+
00019/0777 7 (256,448,3)
|
| 327 |
+
00019/0795 7 (256,448,3)
|
| 328 |
+
00019/0806 7 (256,448,3)
|
| 329 |
+
00019/0815 7 (256,448,3)
|
| 330 |
+
00019/0840 7 (256,448,3)
|
| 331 |
+
00019/0844 7 (256,448,3)
|
| 332 |
+
00019/0848 7 (256,448,3)
|
| 333 |
+
00019/0853 7 (256,448,3)
|
| 334 |
+
00019/0863 7 (256,448,3)
|
| 335 |
+
00019/0888 7 (256,448,3)
|
| 336 |
+
00019/0894 7 (256,448,3)
|
| 337 |
+
00019/0901 7 (256,448,3)
|
| 338 |
+
00019/0995 7 (256,448,3)
|
| 339 |
+
00021/0030 7 (256,448,3)
|
| 340 |
+
00021/0035 7 (256,448,3)
|
| 341 |
+
00021/0039 7 (256,448,3)
|
| 342 |
+
00021/0041 7 (256,448,3)
|
| 343 |
+
00021/0044 7 (256,448,3)
|
| 344 |
+
00021/0045 7 (256,448,3)
|
| 345 |
+
00021/0264 7 (256,448,3)
|
| 346 |
+
00021/0330 7 (256,448,3)
|
| 347 |
+
00021/0332 7 (256,448,3)
|
| 348 |
+
00021/0333 7 (256,448,3)
|
| 349 |
+
00021/0336 7 (256,448,3)
|
| 350 |
+
00021/0337 7 (256,448,3)
|
| 351 |
+
00021/0338 7 (256,448,3)
|
| 352 |
+
00021/0343 7 (256,448,3)
|
| 353 |
+
00021/0472 7 (256,448,3)
|
| 354 |
+
00021/0667 7 (256,448,3)
|
| 355 |
+
00021/0731 7 (256,448,3)
|
| 356 |
+
00021/0779 7 (256,448,3)
|
| 357 |
+
00021/0805 7 (256,448,3)
|
| 358 |
+
00021/0814 7 (256,448,3)
|
| 359 |
+
00021/0818 7 (256,448,3)
|
| 360 |
+
00021/0874 7 (256,448,3)
|
| 361 |
+
00022/0008 7 (256,448,3)
|
| 362 |
+
00022/0010 7 (256,448,3)
|
| 363 |
+
00022/0231 7 (256,448,3)
|
| 364 |
+
00022/0323 7 (256,448,3)
|
| 365 |
+
00022/0337 7 (256,448,3)
|
| 366 |
+
00022/0359 7 (256,448,3)
|
| 367 |
+
00022/0377 7 (256,448,3)
|
| 368 |
+
00022/0378 7 (256,448,3)
|
| 369 |
+
00022/0385 7 (256,448,3)
|
| 370 |
+
00022/0393 7 (256,448,3)
|
| 371 |
+
00022/0424 7 (256,448,3)
|
| 372 |
+
00022/0582 7 (256,448,3)
|
| 373 |
+
00022/0583 7 (256,448,3)
|
| 374 |
+
00022/0605 7 (256,448,3)
|
| 375 |
+
00022/0632 7 (256,448,3)
|
| 376 |
+
00022/0633 7 (256,448,3)
|
| 377 |
+
00022/0666 7 (256,448,3)
|
| 378 |
+
00022/0671 7 (256,448,3)
|
| 379 |
+
00022/0673 7 (256,448,3)
|
| 380 |
+
00022/0702 7 (256,448,3)
|
| 381 |
+
00022/0852 7 (256,448,3)
|
| 382 |
+
00022/0853 7 (256,448,3)
|
| 383 |
+
00022/0971 7 (256,448,3)
|
| 384 |
+
00023/0037 7 (256,448,3)
|
| 385 |
+
00023/0224 7 (256,448,3)
|
| 386 |
+
00023/0308 7 (256,448,3)
|
| 387 |
+
00023/0393 7 (256,448,3)
|
| 388 |
+
00023/0633 7 (256,448,3)
|
| 389 |
+
00023/0637 7 (256,448,3)
|
| 390 |
+
00023/0638 7 (256,448,3)
|
| 391 |
+
00023/0770 7 (256,448,3)
|
| 392 |
+
00023/0786 7 (256,448,3)
|
| 393 |
+
00023/0898 7 (256,448,3)
|
| 394 |
+
00024/0247 7 (256,448,3)
|
| 395 |
+
00024/0251 7 (256,448,3)
|
| 396 |
+
00024/0267 7 (256,448,3)
|
| 397 |
+
00024/0288 7 (256,448,3)
|
| 398 |
+
00024/0530 7 (256,448,3)
|
| 399 |
+
00024/0569 7 (256,448,3)
|
| 400 |
+
00024/0587 7 (256,448,3)
|
| 401 |
+
00024/0730 7 (256,448,3)
|
| 402 |
+
00024/0736 7 (256,448,3)
|
| 403 |
+
00024/0742 7 (256,448,3)
|
| 404 |
+
00024/0832 7 (256,448,3)
|
| 405 |
+
00024/0936 7 (256,448,3)
|
| 406 |
+
00025/0044 7 (256,448,3)
|
| 407 |
+
00025/0047 7 (256,448,3)
|
| 408 |
+
00025/0540 7 (256,448,3)
|
| 409 |
+
00025/0552 7 (256,448,3)
|
| 410 |
+
00025/0554 7 (256,448,3)
|
| 411 |
+
00025/0559 7 (256,448,3)
|
| 412 |
+
00025/0572 7 (256,448,3)
|
| 413 |
+
00025/0576 7 (256,448,3)
|
| 414 |
+
00025/0699 7 (256,448,3)
|
| 415 |
+
00025/0709 7 (256,448,3)
|
| 416 |
+
00025/0743 7 (256,448,3)
|
| 417 |
+
00025/0767 7 (256,448,3)
|
| 418 |
+
00025/0780 7 (256,448,3)
|
| 419 |
+
00025/0782 7 (256,448,3)
|
| 420 |
+
00025/0784 7 (256,448,3)
|
| 421 |
+
00025/0791 7 (256,448,3)
|
| 422 |
+
00025/0889 7 (256,448,3)
|
| 423 |
+
00025/0890 7 (256,448,3)
|
| 424 |
+
00025/0894 7 (256,448,3)
|
| 425 |
+
00025/0896 7 (256,448,3)
|
| 426 |
+
00025/0898 7 (256,448,3)
|
| 427 |
+
00025/0905 7 (256,448,3)
|
| 428 |
+
00025/0999 7 (256,448,3)
|
| 429 |
+
00026/0003 7 (256,448,3)
|
| 430 |
+
00026/0005 7 (256,448,3)
|
| 431 |
+
00026/0011 7 (256,448,3)
|
| 432 |
+
00026/0017 7 (256,448,3)
|
| 433 |
+
00026/0036 7 (256,448,3)
|
| 434 |
+
00026/0129 7 (256,448,3)
|
| 435 |
+
00026/0131 7 (256,448,3)
|
| 436 |
+
00026/0161 7 (256,448,3)
|
| 437 |
+
00026/0177 7 (256,448,3)
|
| 438 |
+
00026/0178 7 (256,448,3)
|
| 439 |
+
00026/0180 7 (256,448,3)
|
| 440 |
+
00026/0298 7 (256,448,3)
|
| 441 |
+
00026/0307 7 (256,448,3)
|
| 442 |
+
00026/0308 7 (256,448,3)
|
| 443 |
+
00026/0312 7 (256,448,3)
|
| 444 |
+
00026/0352 7 (256,448,3)
|
| 445 |
+
00026/0440 7 (256,448,3)
|
| 446 |
+
00026/0706 7 (256,448,3)
|
| 447 |
+
00026/0708 7 (256,448,3)
|
| 448 |
+
00026/0715 7 (256,448,3)
|
| 449 |
+
00026/0769 7 (256,448,3)
|
| 450 |
+
00026/0777 7 (256,448,3)
|
| 451 |
+
00026/0779 7 (256,448,3)
|
| 452 |
+
00026/0789 7 (256,448,3)
|
| 453 |
+
00026/0924 7 (256,448,3)
|
| 454 |
+
00026/0928 7 (256,448,3)
|
| 455 |
+
00026/0932 7 (256,448,3)
|
| 456 |
+
00026/0935 7 (256,448,3)
|
| 457 |
+
00027/0118 7 (256,448,3)
|
| 458 |
+
00027/0121 7 (256,448,3)
|
| 459 |
+
00027/0155 7 (256,448,3)
|
| 460 |
+
00027/0168 7 (256,448,3)
|
| 461 |
+
00027/0196 7 (256,448,3)
|
| 462 |
+
00027/0289 7 (256,448,3)
|
| 463 |
+
00027/0294 7 (256,448,3)
|
| 464 |
+
00027/0803 7 (256,448,3)
|
| 465 |
+
00028/0016 7 (256,448,3)
|
| 466 |
+
00028/0045 7 (256,448,3)
|
| 467 |
+
00028/0063 7 (256,448,3)
|
| 468 |
+
00028/0601 7 (256,448,3)
|
| 469 |
+
00028/0638 7 (256,448,3)
|
| 470 |
+
00028/0733 7 (256,448,3)
|
| 471 |
+
00028/0736 7 (256,448,3)
|
| 472 |
+
00028/0741 7 (256,448,3)
|
| 473 |
+
00028/0753 7 (256,448,3)
|
| 474 |
+
00028/0770 7 (256,448,3)
|
| 475 |
+
00028/0771 7 (256,448,3)
|
| 476 |
+
00028/0777 7 (256,448,3)
|
| 477 |
+
00028/0950 7 (256,448,3)
|
| 478 |
+
00028/0951 7 (256,448,3)
|
| 479 |
+
00029/0048 7 (256,448,3)
|
| 480 |
+
00029/0060 7 (256,448,3)
|
| 481 |
+
00029/0362 7 (256,448,3)
|
| 482 |
+
00029/0399 7 (256,448,3)
|
| 483 |
+
00029/0404 7 (256,448,3)
|
| 484 |
+
00029/0412 7 (256,448,3)
|
| 485 |
+
00029/0416 7 (256,448,3)
|
| 486 |
+
00029/0418 7 (256,448,3)
|
| 487 |
+
00029/0428 7 (256,448,3)
|
| 488 |
+
00030/0131 7 (256,448,3)
|
| 489 |
+
00030/0135 7 (256,448,3)
|
| 490 |
+
00030/0150 7 (256,448,3)
|
| 491 |
+
00030/0245 7 (256,448,3)
|
| 492 |
+
00030/0339 7 (256,448,3)
|
| 493 |
+
00030/0472 7 (256,448,3)
|
| 494 |
+
00030/0482 7 (256,448,3)
|
| 495 |
+
00030/0500 7 (256,448,3)
|
| 496 |
+
00030/0501 7 (256,448,3)
|
| 497 |
+
00030/0697 7 (256,448,3)
|
| 498 |
+
00030/0707 7 (256,448,3)
|
| 499 |
+
00030/0733 7 (256,448,3)
|
| 500 |
+
00030/0743 7 (256,448,3)
|
| 501 |
+
00030/0747 7 (256,448,3)
|
| 502 |
+
00030/0754 7 (256,448,3)
|
| 503 |
+
00030/0755 7 (256,448,3)
|
| 504 |
+
00030/0759 7 (256,448,3)
|
| 505 |
+
00030/0762 7 (256,448,3)
|
| 506 |
+
00030/0764 7 (256,448,3)
|
| 507 |
+
00030/0767 7 (256,448,3)
|
| 508 |
+
00030/0794 7 (256,448,3)
|
| 509 |
+
00030/0796 7 (256,448,3)
|
| 510 |
+
00030/0799 7 (256,448,3)
|
| 511 |
+
00030/0814 7 (256,448,3)
|
| 512 |
+
00030/0823 7 (256,448,3)
|
| 513 |
+
00030/0829 7 (256,448,3)
|
| 514 |
+
00030/0833 7 (256,448,3)
|
| 515 |
+
00030/0848 7 (256,448,3)
|
| 516 |
+
00030/0853 7 (256,448,3)
|
| 517 |
+
00030/0861 7 (256,448,3)
|
| 518 |
+
00031/0182 7 (256,448,3)
|
| 519 |
+
00031/0275 7 (256,448,3)
|
| 520 |
+
00031/0279 7 (256,448,3)
|
| 521 |
+
00031/0555 7 (256,448,3)
|
| 522 |
+
00031/0648 7 (256,448,3)
|
| 523 |
+
00031/0663 7 (256,448,3)
|
| 524 |
+
00031/0680 7 (256,448,3)
|
| 525 |
+
00031/0880 7 (256,448,3)
|
| 526 |
+
00031/0922 7 (256,448,3)
|
| 527 |
+
00031/0925 7 (256,448,3)
|
| 528 |
+
00031/0928 7 (256,448,3)
|
| 529 |
+
00032/0025 7 (256,448,3)
|
| 530 |
+
00032/0377 7 (256,448,3)
|
| 531 |
+
00032/0378 7 (256,448,3)
|
| 532 |
+
00032/0382 7 (256,448,3)
|
| 533 |
+
00032/0384 7 (256,448,3)
|
| 534 |
+
00032/0386 7 (256,448,3)
|
| 535 |
+
00032/0389 7 (256,448,3)
|
| 536 |
+
00032/0391 7 (256,448,3)
|
| 537 |
+
00032/0393 7 (256,448,3)
|
| 538 |
+
00032/0492 7 (256,448,3)
|
| 539 |
+
00032/0497 7 (256,448,3)
|
| 540 |
+
00032/0505 7 (256,448,3)
|
| 541 |
+
00032/0523 7 (256,448,3)
|
| 542 |
+
00032/0542 7 (256,448,3)
|
| 543 |
+
00032/0544 7 (256,448,3)
|
| 544 |
+
00032/0712 7 (256,448,3)
|
| 545 |
+
00032/0847 7 (256,448,3)
|
| 546 |
+
00032/0850 7 (256,448,3)
|
| 547 |
+
00032/0875 7 (256,448,3)
|
| 548 |
+
00033/0062 7 (256,448,3)
|
| 549 |
+
00033/0063 7 (256,448,3)
|
| 550 |
+
00033/0098 7 (256,448,3)
|
| 551 |
+
00033/0101 7 (256,448,3)
|
| 552 |
+
00033/0105 7 (256,448,3)
|
| 553 |
+
00033/0114 7 (256,448,3)
|
| 554 |
+
00033/0432 7 (256,448,3)
|
| 555 |
+
00033/0441 7 (256,448,3)
|
| 556 |
+
00033/0606 7 (256,448,3)
|
| 557 |
+
00033/0611 7 (256,448,3)
|
| 558 |
+
00033/0634 7 (256,448,3)
|
| 559 |
+
00033/0787 7 (256,448,3)
|
| 560 |
+
00033/0792 7 (256,448,3)
|
| 561 |
+
00033/0802 7 (256,448,3)
|
| 562 |
+
00033/0825 7 (256,448,3)
|
| 563 |
+
00033/0835 7 (256,448,3)
|
| 564 |
+
00034/0249 7 (256,448,3)
|
| 565 |
+
00034/0253 7 (256,448,3)
|
| 566 |
+
00034/0254 7 (256,448,3)
|
| 567 |
+
00034/0282 7 (256,448,3)
|
| 568 |
+
00034/0318 7 (256,448,3)
|
| 569 |
+
00034/0319 7 (256,448,3)
|
| 570 |
+
00034/0323 7 (256,448,3)
|
| 571 |
+
00034/0336 7 (256,448,3)
|
| 572 |
+
00034/0348 7 (256,448,3)
|
| 573 |
+
00034/0356 7 (256,448,3)
|
| 574 |
+
00034/0379 7 (256,448,3)
|
| 575 |
+
00034/0387 7 (256,448,3)
|
| 576 |
+
00034/0575 7 (256,448,3)
|
| 577 |
+
00034/0608 7 (256,448,3)
|
| 578 |
+
00034/0663 7 (256,448,3)
|
| 579 |
+
00034/0811 7 (256,448,3)
|
| 580 |
+
00034/0812 7 (256,448,3)
|
| 581 |
+
00034/0946 7 (256,448,3)
|
| 582 |
+
00034/0948 7 (256,448,3)
|
| 583 |
+
00034/0950 7 (256,448,3)
|
| 584 |
+
00035/0204 7 (256,448,3)
|
| 585 |
+
00035/0243 7 (256,448,3)
|
| 586 |
+
00035/0308 7 (256,448,3)
|
| 587 |
+
00035/0465 7 (256,448,3)
|
| 588 |
+
00035/0478 7 (256,448,3)
|
| 589 |
+
00035/0523 7 (256,448,3)
|
| 590 |
+
00035/0540 7 (256,448,3)
|
| 591 |
+
00035/0544 7 (256,448,3)
|
| 592 |
+
00035/0556 7 (256,448,3)
|
| 593 |
+
00035/0568 7 (256,448,3)
|
| 594 |
+
00035/0570 7 (256,448,3)
|
| 595 |
+
00035/0609 7 (256,448,3)
|
| 596 |
+
00035/0643 7 (256,448,3)
|
| 597 |
+
00035/0644 7 (256,448,3)
|
| 598 |
+
00035/0645 7 (256,448,3)
|
| 599 |
+
00035/0646 7 (256,448,3)
|
| 600 |
+
00035/0650 7 (256,448,3)
|
| 601 |
+
00035/0661 7 (256,448,3)
|
| 602 |
+
00035/0724 7 (256,448,3)
|
| 603 |
+
00035/0725 7 (256,448,3)
|
| 604 |
+
00035/0850 7 (256,448,3)
|
| 605 |
+
00035/0863 7 (256,448,3)
|
| 606 |
+
00035/0870 7 (256,448,3)
|
| 607 |
+
00035/0951 7 (256,448,3)
|
| 608 |
+
00036/0038 7 (256,448,3)
|
| 609 |
+
00036/0062 7 (256,448,3)
|
| 610 |
+
00036/0423 7 (256,448,3)
|
| 611 |
+
00036/0737 7 (256,448,3)
|
| 612 |
+
00036/0750 7 (256,448,3)
|
| 613 |
+
00036/0751 7 (256,448,3)
|
| 614 |
+
00036/0754 7 (256,448,3)
|
| 615 |
+
00036/0929 7 (256,448,3)
|
| 616 |
+
00037/0085 7 (256,448,3)
|
| 617 |
+
00037/0113 7 (256,448,3)
|
| 618 |
+
00037/0130 7 (256,448,3)
|
| 619 |
+
00037/0153 7 (256,448,3)
|
| 620 |
+
00037/0169 7 (256,448,3)
|
| 621 |
+
00037/0263 7 (256,448,3)
|
| 622 |
+
00037/0272 7 (256,448,3)
|
| 623 |
+
00037/0273 7 (256,448,3)
|
| 624 |
+
00037/0275 7 (256,448,3)
|
| 625 |
+
00037/0280 7 (256,448,3)
|
| 626 |
+
00037/0399 7 (256,448,3)
|
| 627 |
+
00037/0456 7 (256,448,3)
|
| 628 |
+
00037/0853 7 (256,448,3)
|
| 629 |
+
00037/0855 7 (256,448,3)
|
| 630 |
+
00037/0856 7 (256,448,3)
|
| 631 |
+
00037/0857 7 (256,448,3)
|
| 632 |
+
00037/0925 7 (256,448,3)
|
| 633 |
+
00037/0947 7 (256,448,3)
|
| 634 |
+
00038/0148 7 (256,448,3)
|
| 635 |
+
00038/0533 7 (256,448,3)
|
| 636 |
+
00038/0534 7 (256,448,3)
|
| 637 |
+
00038/0560 7 (256,448,3)
|
| 638 |
+
00038/0562 7 (256,448,3)
|
| 639 |
+
00038/0566 7 (256,448,3)
|
| 640 |
+
00038/0578 7 (256,448,3)
|
| 641 |
+
00038/0652 7 (256,448,3)
|
| 642 |
+
00038/0674 7 (256,448,3)
|
| 643 |
+
00038/0685 7 (256,448,3)
|
| 644 |
+
00038/0686 7 (256,448,3)
|
| 645 |
+
00038/0692 7 (256,448,3)
|
| 646 |
+
00038/0736 7 (256,448,3)
|
| 647 |
+
00039/0035 7 (256,448,3)
|
| 648 |
+
00039/0105 7 (256,448,3)
|
| 649 |
+
00039/0109 7 (256,448,3)
|
| 650 |
+
00039/0121 7 (256,448,3)
|
| 651 |
+
00039/0128 7 (256,448,3)
|
| 652 |
+
00039/0129 7 (256,448,3)
|
| 653 |
+
00039/0132 7 (256,448,3)
|
| 654 |
+
00039/0137 7 (256,448,3)
|
| 655 |
+
00039/0157 7 (256,448,3)
|
| 656 |
+
00039/0496 7 (256,448,3)
|
| 657 |
+
00039/0502 7 (256,448,3)
|
| 658 |
+
00039/0526 7 (256,448,3)
|
| 659 |
+
00039/0529 7 (256,448,3)
|
| 660 |
+
00039/0682 7 (256,448,3)
|
| 661 |
+
00039/0690 7 (256,448,3)
|
| 662 |
+
00039/0693 7 (256,448,3)
|
| 663 |
+
00039/0703 7 (256,448,3)
|
| 664 |
+
00039/0725 7 (256,448,3)
|
| 665 |
+
00039/0734 7 (256,448,3)
|
| 666 |
+
00040/0518 7 (256,448,3)
|
| 667 |
+
00040/0728 7 (256,448,3)
|
| 668 |
+
00040/0774 7 (256,448,3)
|
| 669 |
+
00040/0812 7 (256,448,3)
|
| 670 |
+
00040/0818 7 (256,448,3)
|
| 671 |
+
00040/0827 7 (256,448,3)
|
| 672 |
+
00040/0914 7 (256,448,3)
|
| 673 |
+
00040/0917 7 (256,448,3)
|
| 674 |
+
00040/0918 7 (256,448,3)
|
| 675 |
+
00040/0924 7 (256,448,3)
|
| 676 |
+
00040/0925 7 (256,448,3)
|
| 677 |
+
00041/0004 7 (256,448,3)
|
| 678 |
+
00041/0006 7 (256,448,3)
|
| 679 |
+
00041/0013 7 (256,448,3)
|
| 680 |
+
00041/0059 7 (256,448,3)
|
| 681 |
+
00041/0110 7 (256,448,3)
|
| 682 |
+
00041/0291 7 (256,448,3)
|
| 683 |
+
00041/0366 7 (256,448,3)
|
| 684 |
+
00041/0388 7 (256,448,3)
|
| 685 |
+
00041/0434 7 (256,448,3)
|
| 686 |
+
00041/0436 7 (256,448,3)
|
| 687 |
+
00041/0450 7 (256,448,3)
|
| 688 |
+
00041/0457 7 (256,448,3)
|
| 689 |
+
00041/0460 7 (256,448,3)
|
| 690 |
+
00041/0468 7 (256,448,3)
|
| 691 |
+
00041/0471 7 (256,448,3)
|
| 692 |
+
00041/0474 7 (256,448,3)
|
| 693 |
+
00041/0809 7 (256,448,3)
|
| 694 |
+
00041/0844 7 (256,448,3)
|
| 695 |
+
00041/0858 7 (256,448,3)
|
| 696 |
+
00041/0874 7 (256,448,3)
|
| 697 |
+
00041/0876 7 (256,448,3)
|
| 698 |
+
00042/0020 7 (256,448,3)
|
| 699 |
+
00042/0205 7 (256,448,3)
|
| 700 |
+
00042/0206 7 (256,448,3)
|
| 701 |
+
00042/0432 7 (256,448,3)
|
| 702 |
+
00042/0563 7 (256,448,3)
|
| 703 |
+
00042/0569 7 (256,448,3)
|
| 704 |
+
00042/0575 7 (256,448,3)
|
| 705 |
+
00042/0576 7 (256,448,3)
|
| 706 |
+
00042/0888 7 (256,448,3)
|
| 707 |
+
00042/0892 7 (256,448,3)
|
| 708 |
+
00042/0943 7 (256,448,3)
|
| 709 |
+
00042/0944 7 (256,448,3)
|
| 710 |
+
00043/0126 7 (256,448,3)
|
| 711 |
+
00043/0130 7 (256,448,3)
|
| 712 |
+
00043/0136 7 (256,448,3)
|
| 713 |
+
00043/0233 7 (256,448,3)
|
| 714 |
+
00043/0235 7 (256,448,3)
|
| 715 |
+
00043/0237 7 (256,448,3)
|
| 716 |
+
00043/0277 7 (256,448,3)
|
| 717 |
+
00043/0301 7 (256,448,3)
|
| 718 |
+
00043/0302 7 (256,448,3)
|
| 719 |
+
00043/0303 7 (256,448,3)
|
| 720 |
+
00043/0308 7 (256,448,3)
|
| 721 |
+
00043/0309 7 (256,448,3)
|
| 722 |
+
00043/0314 7 (256,448,3)
|
| 723 |
+
00043/0713 7 (256,448,3)
|
| 724 |
+
00043/0715 7 (256,448,3)
|
| 725 |
+
00043/0923 7 (256,448,3)
|
| 726 |
+
00044/0095 7 (256,448,3)
|
| 727 |
+
00044/0255 7 (256,448,3)
|
| 728 |
+
00044/0864 7 (256,448,3)
|
| 729 |
+
00044/0892 7 (256,448,3)
|
| 730 |
+
00044/0898 7 (256,448,3)
|
| 731 |
+
00044/0993 7 (256,448,3)
|
| 732 |
+
00044/0995 7 (256,448,3)
|
| 733 |
+
00044/0997 7 (256,448,3)
|
| 734 |
+
00045/0001 7 (256,448,3)
|
| 735 |
+
00045/0006 7 (256,448,3)
|
| 736 |
+
00045/0269 7 (256,448,3)
|
| 737 |
+
00045/0276 7 (256,448,3)
|
| 738 |
+
00045/0280 7 (256,448,3)
|
| 739 |
+
00045/0281 7 (256,448,3)
|
| 740 |
+
00045/0282 7 (256,448,3)
|
| 741 |
+
00045/0284 7 (256,448,3)
|
| 742 |
+
00045/0550 7 (256,448,3)
|
| 743 |
+
00045/0571 7 (256,448,3)
|
| 744 |
+
00045/0629 7 (256,448,3)
|
| 745 |
+
00045/0631 7 (256,448,3)
|
| 746 |
+
00045/0659 7 (256,448,3)
|
| 747 |
+
00045/0693 7 (256,448,3)
|
| 748 |
+
00045/0807 7 (256,448,3)
|
| 749 |
+
00045/0810 7 (256,448,3)
|
| 750 |
+
00045/0826 7 (256,448,3)
|
| 751 |
+
00045/0849 7 (256,448,3)
|
| 752 |
+
00045/0946 7 (256,448,3)
|
| 753 |
+
00045/0987 7 (256,448,3)
|
| 754 |
+
00045/0990 7 (256,448,3)
|
| 755 |
+
00046/0104 7 (256,448,3)
|
| 756 |
+
00046/0477 7 (256,448,3)
|
| 757 |
+
00046/0490 7 (256,448,3)
|
| 758 |
+
00046/0491 7 (256,448,3)
|
| 759 |
+
00046/0509 7 (256,448,3)
|
| 760 |
+
00046/0513 7 (256,448,3)
|
| 761 |
+
00046/0603 7 (256,448,3)
|
| 762 |
+
00046/0723 7 (256,448,3)
|
| 763 |
+
00046/0744 7 (256,448,3)
|
| 764 |
+
00046/0746 7 (256,448,3)
|
| 765 |
+
00046/0750 7 (256,448,3)
|
| 766 |
+
00046/0852 7 (256,448,3)
|
| 767 |
+
00046/0927 7 (256,448,3)
|
| 768 |
+
00046/0928 7 (256,448,3)
|
| 769 |
+
00046/0929 7 (256,448,3)
|
| 770 |
+
00046/0931 7 (256,448,3)
|
| 771 |
+
00046/0936 7 (256,448,3)
|
| 772 |
+
00046/0939 7 (256,448,3)
|
| 773 |
+
00046/0947 7 (256,448,3)
|
| 774 |
+
00046/0948 7 (256,448,3)
|
| 775 |
+
00046/0950 7 (256,448,3)
|
| 776 |
+
00046/0955 7 (256,448,3)
|
| 777 |
+
00046/0961 7 (256,448,3)
|
| 778 |
+
00047/0023 7 (256,448,3)
|
| 779 |
+
00047/0029 7 (256,448,3)
|
| 780 |
+
00047/0035 7 (256,448,3)
|
| 781 |
+
00047/0058 7 (256,448,3)
|
| 782 |
+
00047/0061 7 (256,448,3)
|
| 783 |
+
00047/0065 7 (256,448,3)
|
| 784 |
+
00047/0068 7 (256,448,3)
|
| 785 |
+
00047/0072 7 (256,448,3)
|
| 786 |
+
00047/0074 7 (256,448,3)
|
| 787 |
+
00047/0148 7 (256,448,3)
|
| 788 |
+
00047/0594 7 (256,448,3)
|
| 789 |
+
00047/0782 7 (256,448,3)
|
| 790 |
+
00047/0787 7 (256,448,3)
|
| 791 |
+
00047/0860 7 (256,448,3)
|
| 792 |
+
00047/0889 7 (256,448,3)
|
| 793 |
+
00047/0893 7 (256,448,3)
|
| 794 |
+
00047/0894 7 (256,448,3)
|
| 795 |
+
00047/0902 7 (256,448,3)
|
| 796 |
+
00047/0975 7 (256,448,3)
|
| 797 |
+
00047/0995 7 (256,448,3)
|
| 798 |
+
00048/0033 7 (256,448,3)
|
| 799 |
+
00048/0113 7 (256,448,3)
|
| 800 |
+
00048/0115 7 (256,448,3)
|
| 801 |
+
00048/0120 7 (256,448,3)
|
| 802 |
+
00048/0129 7 (256,448,3)
|
| 803 |
+
00048/0136 7 (256,448,3)
|
| 804 |
+
00048/0327 7 (256,448,3)
|
| 805 |
+
00048/0329 7 (256,448,3)
|
| 806 |
+
00048/0341 7 (256,448,3)
|
| 807 |
+
00048/0343 7 (256,448,3)
|
| 808 |
+
00048/0345 7 (256,448,3)
|
| 809 |
+
00048/0346 7 (256,448,3)
|
| 810 |
+
00048/0355 7 (256,448,3)
|
| 811 |
+
00048/0359 7 (256,448,3)
|
| 812 |
+
00048/0363 7 (256,448,3)
|
| 813 |
+
00048/0378 7 (256,448,3)
|
| 814 |
+
00048/0386 7 (256,448,3)
|
| 815 |
+
00048/0387 7 (256,448,3)
|
| 816 |
+
00048/0388 7 (256,448,3)
|
| 817 |
+
00048/0428 7 (256,448,3)
|
| 818 |
+
00048/0439 7 (256,448,3)
|
| 819 |
+
00048/0507 7 (256,448,3)
|
| 820 |
+
00048/0510 7 (256,448,3)
|
| 821 |
+
00048/0512 7 (256,448,3)
|
| 822 |
+
00048/0514 7 (256,448,3)
|
| 823 |
+
00048/0539 7 (256,448,3)
|
| 824 |
+
00048/0542 7 (256,448,3)
|
| 825 |
+
00048/0544 7 (256,448,3)
|
| 826 |
+
00048/0631 7 (256,448,3)
|
| 827 |
+
00048/0632 7 (256,448,3)
|
| 828 |
+
00048/0636 7 (256,448,3)
|
| 829 |
+
00048/0640 7 (256,448,3)
|
| 830 |
+
00048/0644 7 (256,448,3)
|
| 831 |
+
00048/0653 7 (256,448,3)
|
| 832 |
+
00048/0655 7 (256,448,3)
|
| 833 |
+
00048/0658 7 (256,448,3)
|
| 834 |
+
00048/0667 7 (256,448,3)
|
| 835 |
+
00048/0688 7 (256,448,3)
|
| 836 |
+
00048/0708 7 (256,448,3)
|
| 837 |
+
00049/0005 7 (256,448,3)
|
| 838 |
+
00049/0074 7 (256,448,3)
|
| 839 |
+
00049/0077 7 (256,448,3)
|
| 840 |
+
00049/0084 7 (256,448,3)
|
| 841 |
+
00049/0516 7 (256,448,3)
|
| 842 |
+
00049/0800 7 (256,448,3)
|
| 843 |
+
00049/0900 7 (256,448,3)
|
| 844 |
+
00050/0607 7 (256,448,3)
|
| 845 |
+
00050/0661 7 (256,448,3)
|
| 846 |
+
00050/0665 7 (256,448,3)
|
| 847 |
+
00050/0685 7 (256,448,3)
|
| 848 |
+
00050/0711 7 (256,448,3)
|
| 849 |
+
00051/0068 7 (256,448,3)
|
| 850 |
+
00051/0069 7 (256,448,3)
|
| 851 |
+
00051/0076 7 (256,448,3)
|
| 852 |
+
00051/0569 7 (256,448,3)
|
| 853 |
+
00051/0801 7 (256,448,3)
|
| 854 |
+
00051/0927 7 (256,448,3)
|
| 855 |
+
00051/0945 7 (256,448,3)
|
| 856 |
+
00051/0952 7 (256,448,3)
|
| 857 |
+
00051/0976 7 (256,448,3)
|
| 858 |
+
00051/0985 7 (256,448,3)
|
| 859 |
+
00052/0012 7 (256,448,3)
|
| 860 |
+
00052/0015 7 (256,448,3)
|
| 861 |
+
00052/0052 7 (256,448,3)
|
| 862 |
+
00052/0056 7 (256,448,3)
|
| 863 |
+
00052/0060 7 (256,448,3)
|
| 864 |
+
00052/0157 7 (256,448,3)
|
| 865 |
+
00052/0265 7 (256,448,3)
|
| 866 |
+
00052/0788 7 (256,448,3)
|
| 867 |
+
00052/0790 7 (256,448,3)
|
| 868 |
+
00052/0793 7 (256,448,3)
|
| 869 |
+
00052/0816 7 (256,448,3)
|
| 870 |
+
00052/0824 7 (256,448,3)
|
| 871 |
+
00052/0918 7 (256,448,3)
|
| 872 |
+
00052/0933 7 (256,448,3)
|
| 873 |
+
00052/0947 7 (256,448,3)
|
| 874 |
+
00053/0232 7 (256,448,3)
|
| 875 |
+
00053/0277 7 (256,448,3)
|
| 876 |
+
00053/0362 7 (256,448,3)
|
| 877 |
+
00053/0577 7 (256,448,3)
|
| 878 |
+
00053/0609 7 (256,448,3)
|
| 879 |
+
00053/0612 7 (256,448,3)
|
| 880 |
+
00053/0628 7 (256,448,3)
|
| 881 |
+
00053/0629 7 (256,448,3)
|
| 882 |
+
00053/0633 7 (256,448,3)
|
| 883 |
+
00053/0659 7 (256,448,3)
|
| 884 |
+
00053/0667 7 (256,448,3)
|
| 885 |
+
00053/0671 7 (256,448,3)
|
| 886 |
+
00053/0797 7 (256,448,3)
|
| 887 |
+
00053/0804 7 (256,448,3)
|
| 888 |
+
00053/0807 7 (256,448,3)
|
| 889 |
+
00053/0952 7 (256,448,3)
|
| 890 |
+
00053/0970 7 (256,448,3)
|
| 891 |
+
00053/0981 7 (256,448,3)
|
| 892 |
+
00053/0999 7 (256,448,3)
|
| 893 |
+
00054/0003 7 (256,448,3)
|
| 894 |
+
00054/0013 7 (256,448,3)
|
| 895 |
+
00054/0020 7 (256,448,3)
|
| 896 |
+
00054/0022 7 (256,448,3)
|
| 897 |
+
00054/0023 7 (256,448,3)
|
| 898 |
+
00054/0044 7 (256,448,3)
|
| 899 |
+
00054/0051 7 (256,448,3)
|
| 900 |
+
00054/0063 7 (256,448,3)
|
| 901 |
+
00054/0065 7 (256,448,3)
|
| 902 |
+
00054/0145 7 (256,448,3)
|
| 903 |
+
00054/0153 7 (256,448,3)
|
| 904 |
+
00054/0203 7 (256,448,3)
|
| 905 |
+
00054/0325 7 (256,448,3)
|
| 906 |
+
00054/0445 7 (256,448,3)
|
| 907 |
+
00054/0448 7 (256,448,3)
|
| 908 |
+
00054/0456 7 (256,448,3)
|
| 909 |
+
00054/0457 7 (256,448,3)
|
| 910 |
+
00054/0519 7 (256,448,3)
|
| 911 |
+
00054/0524 7 (256,448,3)
|
| 912 |
+
00054/0530 7 (256,448,3)
|
| 913 |
+
00054/0532 7 (256,448,3)
|
| 914 |
+
00054/0535 7 (256,448,3)
|
| 915 |
+
00054/0574 7 (256,448,3)
|
| 916 |
+
00054/0760 7 (256,448,3)
|
| 917 |
+
00054/0767 7 (256,448,3)
|
| 918 |
+
00054/0837 7 (256,448,3)
|
| 919 |
+
00055/0011 7 (256,448,3)
|
| 920 |
+
00055/0109 7 (256,448,3)
|
| 921 |
+
00055/0111 7 (256,448,3)
|
| 922 |
+
00055/0117 7 (256,448,3)
|
| 923 |
+
00055/0119 7 (256,448,3)
|
| 924 |
+
00055/0182 7 (256,448,3)
|
| 925 |
+
00055/0192 7 (256,448,3)
|
| 926 |
+
00055/0193 7 (256,448,3)
|
| 927 |
+
00055/0200 7 (256,448,3)
|
| 928 |
+
00055/0204 7 (256,448,3)
|
| 929 |
+
00055/0207 7 (256,448,3)
|
| 930 |
+
00055/0212 7 (256,448,3)
|
| 931 |
+
00055/0213 7 (256,448,3)
|
| 932 |
+
00055/0348 7 (256,448,3)
|
| 933 |
+
00055/0423 7 (256,448,3)
|
| 934 |
+
00055/0427 7 (256,448,3)
|
| 935 |
+
00055/0456 7 (256,448,3)
|
| 936 |
+
00055/0489 7 (256,448,3)
|
| 937 |
+
00055/0689 7 (256,448,3)
|
| 938 |
+
00055/0753 7 (256,448,3)
|
| 939 |
+
00055/0802 7 (256,448,3)
|
| 940 |
+
00055/0844 7 (256,448,3)
|
| 941 |
+
00055/0850 7 (256,448,3)
|
| 942 |
+
00055/0982 7 (256,448,3)
|
| 943 |
+
00055/0993 7 (256,448,3)
|
| 944 |
+
00056/0113 7 (256,448,3)
|
| 945 |
+
00056/0148 7 (256,448,3)
|
| 946 |
+
00056/0151 7 (256,448,3)
|
| 947 |
+
00056/0316 7 (256,448,3)
|
| 948 |
+
00056/0379 7 (256,448,3)
|
| 949 |
+
00056/0380 7 (256,448,3)
|
| 950 |
+
00056/0385 7 (256,448,3)
|
| 951 |
+
00056/0505 7 (256,448,3)
|
| 952 |
+
00056/0579 7 (256,448,3)
|
| 953 |
+
00057/0254 7 (256,448,3)
|
| 954 |
+
00057/0264 7 (256,448,3)
|
| 955 |
+
00057/0272 7 (256,448,3)
|
| 956 |
+
00057/0403 7 (256,448,3)
|
| 957 |
+
00057/0501 7 (256,448,3)
|
| 958 |
+
00057/0503 7 (256,448,3)
|
| 959 |
+
00057/0884 7 (256,448,3)
|
| 960 |
+
00058/0026 7 (256,448,3)
|
| 961 |
+
00058/0029 7 (256,448,3)
|
| 962 |
+
00058/0104 7 (256,448,3)
|
| 963 |
+
00058/0124 7 (256,448,3)
|
| 964 |
+
00058/0162 7 (256,448,3)
|
| 965 |
+
00058/0288 7 (256,448,3)
|
| 966 |
+
00058/0289 7 (256,448,3)
|
| 967 |
+
00058/0323 7 (256,448,3)
|
| 968 |
+
00058/0328 7 (256,448,3)
|
| 969 |
+
00058/0329 7 (256,448,3)
|
| 970 |
+
00058/0337 7 (256,448,3)
|
| 971 |
+
00058/0367 7 (256,448,3)
|
| 972 |
+
00058/0383 7 (256,448,3)
|
| 973 |
+
00058/0395 7 (256,448,3)
|
| 974 |
+
00060/0178 7 (256,448,3)
|
| 975 |
+
00060/0182 7 (256,448,3)
|
| 976 |
+
00061/0001 7 (256,448,3)
|
| 977 |
+
00061/0003 7 (256,448,3)
|
| 978 |
+
00061/0006 7 (256,448,3)
|
| 979 |
+
00061/0443 7 (256,448,3)
|
| 980 |
+
00061/0586 7 (256,448,3)
|
| 981 |
+
00061/0587 7 (256,448,3)
|
| 982 |
+
00061/0774 7 (256,448,3)
|
| 983 |
+
00061/0789 7 (256,448,3)
|
| 984 |
+
00061/0815 7 (256,448,3)
|
| 985 |
+
00061/0817 7 (256,448,3)
|
| 986 |
+
00061/0826 7 (256,448,3)
|
| 987 |
+
00061/0829 7 (256,448,3)
|
| 988 |
+
00061/0830 7 (256,448,3)
|
| 989 |
+
00061/0832 7 (256,448,3)
|
| 990 |
+
00061/0833 7 (256,448,3)
|
| 991 |
+
00061/0836 7 (256,448,3)
|
| 992 |
+
00061/0837 7 (256,448,3)
|
| 993 |
+
00061/0839 7 (256,448,3)
|
| 994 |
+
00061/0843 7 (256,448,3)
|
| 995 |
+
00061/0849 7 (256,448,3)
|
| 996 |
+
00061/0859 7 (256,448,3)
|
| 997 |
+
00061/0861 7 (256,448,3)
|
| 998 |
+
00061/0868 7 (256,448,3)
|
| 999 |
+
00061/0877 7 (256,448,3)
|
| 1000 |
+
00061/0889 7 (256,448,3)
|
| 1001 |
+
00061/0905 7 (256,448,3)
|
| 1002 |
+
00062/0115 7 (256,448,3)
|
| 1003 |
+
00062/0118 7 (256,448,3)
|
| 1004 |
+
00062/0125 7 (256,448,3)
|
| 1005 |
+
00062/0134 7 (256,448,3)
|
| 1006 |
+
00062/0142 7 (256,448,3)
|
| 1007 |
+
00062/0400 7 (256,448,3)
|
| 1008 |
+
00062/0457 7 (256,448,3)
|
| 1009 |
+
00062/0459 7 (256,448,3)
|
| 1010 |
+
00062/0560 7 (256,448,3)
|
| 1011 |
+
00062/0650 7 (256,448,3)
|
| 1012 |
+
00062/0655 7 (256,448,3)
|
| 1013 |
+
00062/0715 7 (256,448,3)
|
| 1014 |
+
00062/0847 7 (256,448,3)
|
| 1015 |
+
00062/0905 7 (256,448,3)
|
| 1016 |
+
00062/0981 7 (256,448,3)
|
| 1017 |
+
00063/0177 7 (256,448,3)
|
| 1018 |
+
00063/0230 7 (256,448,3)
|
| 1019 |
+
00063/0253 7 (256,448,3)
|
| 1020 |
+
00063/0257 7 (256,448,3)
|
| 1021 |
+
00063/0326 7 (256,448,3)
|
| 1022 |
+
00063/0530 7 (256,448,3)
|
| 1023 |
+
00063/0677 7 (256,448,3)
|
| 1024 |
+
00063/0759 7 (256,448,3)
|
| 1025 |
+
00063/0761 7 (256,448,3)
|
| 1026 |
+
00063/0777 7 (256,448,3)
|
| 1027 |
+
00063/0842 7 (256,448,3)
|
| 1028 |
+
00063/0900 7 (256,448,3)
|
| 1029 |
+
00064/0014 7 (256,448,3)
|
| 1030 |
+
00064/0028 7 (256,448,3)
|
| 1031 |
+
00064/0029 7 (256,448,3)
|
| 1032 |
+
00064/0030 7 (256,448,3)
|
| 1033 |
+
00064/0037 7 (256,448,3)
|
| 1034 |
+
00064/0044 7 (256,448,3)
|
| 1035 |
+
00064/0280 7 (256,448,3)
|
| 1036 |
+
00064/0285 7 (256,448,3)
|
| 1037 |
+
00064/0286 7 (256,448,3)
|
| 1038 |
+
00064/0291 7 (256,448,3)
|
| 1039 |
+
00064/0300 7 (256,448,3)
|
| 1040 |
+
00064/0303 7 (256,448,3)
|
| 1041 |
+
00064/0308 7 (256,448,3)
|
| 1042 |
+
00064/0314 7 (256,448,3)
|
| 1043 |
+
00064/0316 7 (256,448,3)
|
| 1044 |
+
00064/0317 7 (256,448,3)
|
| 1045 |
+
00064/0323 7 (256,448,3)
|
| 1046 |
+
00064/0435 7 (256,448,3)
|
| 1047 |
+
00064/0733 7 (256,448,3)
|
| 1048 |
+
00064/0848 7 (256,448,3)
|
| 1049 |
+
00064/0868 7 (256,448,3)
|
| 1050 |
+
00064/0888 7 (256,448,3)
|
| 1051 |
+
00064/0898 7 (256,448,3)
|
| 1052 |
+
00065/0116 7 (256,448,3)
|
| 1053 |
+
00065/0121 7 (256,448,3)
|
| 1054 |
+
00065/0122 7 (256,448,3)
|
| 1055 |
+
00065/0124 7 (256,448,3)
|
| 1056 |
+
00065/0125 7 (256,448,3)
|
| 1057 |
+
00065/0126 7 (256,448,3)
|
| 1058 |
+
00065/0136 7 (256,448,3)
|
| 1059 |
+
00065/0146 7 (256,448,3)
|
| 1060 |
+
00065/0147 7 (256,448,3)
|
| 1061 |
+
00065/0163 7 (256,448,3)
|
| 1062 |
+
00065/0170 7 (256,448,3)
|
| 1063 |
+
00065/0175 7 (256,448,3)
|
| 1064 |
+
00065/0176 7 (256,448,3)
|
| 1065 |
+
00065/0180 7 (256,448,3)
|
| 1066 |
+
00065/0184 7 (256,448,3)
|
| 1067 |
+
00065/0186 7 (256,448,3)
|
| 1068 |
+
00065/0332 7 (256,448,3)
|
| 1069 |
+
00065/0343 7 (256,448,3)
|
| 1070 |
+
00065/0365 7 (256,448,3)
|
| 1071 |
+
00065/0393 7 (256,448,3)
|
| 1072 |
+
00065/0394 7 (256,448,3)
|
| 1073 |
+
00065/0442 7 (256,448,3)
|
| 1074 |
+
00065/0459 7 (256,448,3)
|
| 1075 |
+
00065/0462 7 (256,448,3)
|
| 1076 |
+
00065/0476 7 (256,448,3)
|
| 1077 |
+
00065/0483 7 (256,448,3)
|
| 1078 |
+
00065/0590 7 (256,448,3)
|
| 1079 |
+
00065/0593 7 (256,448,3)
|
| 1080 |
+
00065/0595 7 (256,448,3)
|
| 1081 |
+
00065/0774 7 (256,448,3)
|
| 1082 |
+
00065/0947 7 (256,448,3)
|
| 1083 |
+
00065/0985 7 (256,448,3)
|
| 1084 |
+
00065/0986 7 (256,448,3)
|
| 1085 |
+
00066/0015 7 (256,448,3)
|
| 1086 |
+
00066/0043 7 (256,448,3)
|
| 1087 |
+
00066/0131 7 (256,448,3)
|
| 1088 |
+
00066/0157 7 (256,448,3)
|
| 1089 |
+
00066/0169 7 (256,448,3)
|
| 1090 |
+
00066/0374 7 (256,448,3)
|
| 1091 |
+
00066/0382 7 (256,448,3)
|
| 1092 |
+
00066/0481 7 (256,448,3)
|
| 1093 |
+
00066/0482 7 (256,448,3)
|
| 1094 |
+
00066/0491 7 (256,448,3)
|
| 1095 |
+
00066/0493 7 (256,448,3)
|
| 1096 |
+
00066/0494 7 (256,448,3)
|
| 1097 |
+
00066/0496 7 (256,448,3)
|
| 1098 |
+
00066/0680 7 (256,448,3)
|
| 1099 |
+
00066/0700 7 (256,448,3)
|
| 1100 |
+
00066/0887 7 (256,448,3)
|
| 1101 |
+
00066/0910 7 (256,448,3)
|
| 1102 |
+
00066/0918 7 (256,448,3)
|
| 1103 |
+
00067/0024 7 (256,448,3)
|
| 1104 |
+
00067/0059 7 (256,448,3)
|
| 1105 |
+
00067/0408 7 (256,448,3)
|
| 1106 |
+
00067/0414 7 (256,448,3)
|
| 1107 |
+
00067/0417 7 (256,448,3)
|
| 1108 |
+
00067/0419 7 (256,448,3)
|
| 1109 |
+
00067/0423 7 (256,448,3)
|
| 1110 |
+
00067/0441 7 (256,448,3)
|
| 1111 |
+
00067/0467 7 (256,448,3)
|
| 1112 |
+
00067/0471 7 (256,448,3)
|
| 1113 |
+
00067/0487 7 (256,448,3)
|
| 1114 |
+
00067/0494 7 (256,448,3)
|
| 1115 |
+
00067/0497 7 (256,448,3)
|
| 1116 |
+
00067/0513 7 (256,448,3)
|
| 1117 |
+
00067/0521 7 (256,448,3)
|
| 1118 |
+
00068/0111 7 (256,448,3)
|
| 1119 |
+
00068/0123 7 (256,448,3)
|
| 1120 |
+
00068/0126 7 (256,448,3)
|
| 1121 |
+
00068/0129 7 (256,448,3)
|
| 1122 |
+
00068/0270 7 (256,448,3)
|
| 1123 |
+
00068/0330 7 (256,448,3)
|
| 1124 |
+
00068/0407 7 (256,448,3)
|
| 1125 |
+
00068/0428 7 (256,448,3)
|
| 1126 |
+
00068/0544 7 (256,448,3)
|
| 1127 |
+
00068/0635 7 (256,448,3)
|
| 1128 |
+
00068/0637 7 (256,448,3)
|
| 1129 |
+
00068/0736 7 (256,448,3)
|
| 1130 |
+
00068/0738 7 (256,448,3)
|
| 1131 |
+
00068/0747 7 (256,448,3)
|
| 1132 |
+
00068/0748 7 (256,448,3)
|
| 1133 |
+
00068/0749 7 (256,448,3)
|
| 1134 |
+
00068/0762 7 (256,448,3)
|
| 1135 |
+
00068/0815 7 (256,448,3)
|
| 1136 |
+
00068/0981 7 (256,448,3)
|
| 1137 |
+
00068/0982 7 (256,448,3)
|
| 1138 |
+
00069/0187 7 (256,448,3)
|
| 1139 |
+
00069/0191 7 (256,448,3)
|
| 1140 |
+
00070/0001 7 (256,448,3)
|
| 1141 |
+
00070/0003 7 (256,448,3)
|
| 1142 |
+
00070/0340 7 (256,448,3)
|
| 1143 |
+
00070/0341 7 (256,448,3)
|
| 1144 |
+
00070/0342 7 (256,448,3)
|
| 1145 |
+
00070/0347 7 (256,448,3)
|
| 1146 |
+
00070/0372 7 (256,448,3)
|
| 1147 |
+
00070/0383 7 (256,448,3)
|
| 1148 |
+
00070/0389 7 (256,448,3)
|
| 1149 |
+
00070/0728 7 (256,448,3)
|
| 1150 |
+
00070/0813 7 (256,448,3)
|
| 1151 |
+
00070/0814 7 (256,448,3)
|
| 1152 |
+
00070/0823 7 (256,448,3)
|
| 1153 |
+
00070/0840 7 (256,448,3)
|
| 1154 |
+
00070/0843 7 (256,448,3)
|
| 1155 |
+
00070/0861 7 (256,448,3)
|
| 1156 |
+
00071/0111 7 (256,448,3)
|
| 1157 |
+
00071/0138 7 (256,448,3)
|
| 1158 |
+
00071/0143 7 (256,448,3)
|
| 1159 |
+
00071/0150 7 (256,448,3)
|
| 1160 |
+
00071/0508 7 (256,448,3)
|
| 1161 |
+
00071/0514 7 (256,448,3)
|
| 1162 |
+
00071/0550 7 (256,448,3)
|
| 1163 |
+
00071/0556 7 (256,448,3)
|
| 1164 |
+
00071/0600 7 (256,448,3)
|
| 1165 |
+
00071/0665 7 (256,448,3)
|
| 1166 |
+
00071/0670 7 (256,448,3)
|
| 1167 |
+
00071/0672 7 (256,448,3)
|
| 1168 |
+
00071/0673 7 (256,448,3)
|
| 1169 |
+
00071/0705 7 (256,448,3)
|
| 1170 |
+
00071/0706 7 (256,448,3)
|
| 1171 |
+
00071/0707 7 (256,448,3)
|
| 1172 |
+
00071/0774 7 (256,448,3)
|
| 1173 |
+
00071/0799 7 (256,448,3)
|
| 1174 |
+
00071/0814 7 (256,448,3)
|
| 1175 |
+
00071/0816 7 (256,448,3)
|
| 1176 |
+
00071/0819 7 (256,448,3)
|
| 1177 |
+
00071/0823 7 (256,448,3)
|
| 1178 |
+
00071/0828 7 (256,448,3)
|
| 1179 |
+
00071/0830 7 (256,448,3)
|
| 1180 |
+
00071/0839 7 (256,448,3)
|
| 1181 |
+
00071/0841 7 (256,448,3)
|
| 1182 |
+
00072/0192 7 (256,448,3)
|
| 1183 |
+
00072/0194 7 (256,448,3)
|
| 1184 |
+
00072/0197 7 (256,448,3)
|
| 1185 |
+
00072/0199 7 (256,448,3)
|
| 1186 |
+
00072/0285 7 (256,448,3)
|
| 1187 |
+
00072/0586 7 (256,448,3)
|
| 1188 |
+
00072/0795 7 (256,448,3)
|
| 1189 |
+
00072/0811 7 (256,448,3)
|
| 1190 |
+
00072/0812 7 (256,448,3)
|
| 1191 |
+
00072/0824 7 (256,448,3)
|
| 1192 |
+
00072/0831 7 (256,448,3)
|
| 1193 |
+
00072/0835 7 (256,448,3)
|
| 1194 |
+
00072/0837 7 (256,448,3)
|
| 1195 |
+
00072/0841 7 (256,448,3)
|
| 1196 |
+
00072/0962 7 (256,448,3)
|
| 1197 |
+
00073/0296 7 (256,448,3)
|
| 1198 |
+
00073/0299 7 (256,448,3)
|
| 1199 |
+
00073/0300 7 (256,448,3)
|
| 1200 |
+
00073/0301 7 (256,448,3)
|
| 1201 |
+
00073/0427 7 (256,448,3)
|
| 1202 |
+
00073/0428 7 (256,448,3)
|
| 1203 |
+
00073/0494 7 (256,448,3)
|
| 1204 |
+
00073/0615 7 (256,448,3)
|
| 1205 |
+
00073/0620 7 (256,448,3)
|
| 1206 |
+
00073/0624 7 (256,448,3)
|
| 1207 |
+
00073/0979 7 (256,448,3)
|
| 1208 |
+
00074/0226 7 (256,448,3)
|
| 1209 |
+
00074/0250 7 (256,448,3)
|
| 1210 |
+
00074/0284 7 (256,448,3)
|
| 1211 |
+
00074/0503 7 (256,448,3)
|
| 1212 |
+
00074/0614 7 (256,448,3)
|
| 1213 |
+
00074/0629 7 (256,448,3)
|
| 1214 |
+
00074/0762 7 (256,448,3)
|
| 1215 |
+
00074/0765 7 (256,448,3)
|
| 1216 |
+
00074/0900 7 (256,448,3)
|
| 1217 |
+
00074/0908 7 (256,448,3)
|
| 1218 |
+
00075/0352 7 (256,448,3)
|
| 1219 |
+
00075/0360 7 (256,448,3)
|
| 1220 |
+
00075/0361 7 (256,448,3)
|
| 1221 |
+
00075/0365 7 (256,448,3)
|
| 1222 |
+
00075/0383 7 (256,448,3)
|
| 1223 |
+
00075/0384 7 (256,448,3)
|
| 1224 |
+
00075/0386 7 (256,448,3)
|
| 1225 |
+
00075/0407 7 (256,448,3)
|
| 1226 |
+
00075/0410 7 (256,448,3)
|
| 1227 |
+
00075/0412 7 (256,448,3)
|
| 1228 |
+
00075/0413 7 (256,448,3)
|
| 1229 |
+
00075/0459 7 (256,448,3)
|
| 1230 |
+
00075/0504 7 (256,448,3)
|
| 1231 |
+
00075/0515 7 (256,448,3)
|
| 1232 |
+
00075/0518 7 (256,448,3)
|
| 1233 |
+
00075/0567 7 (256,448,3)
|
| 1234 |
+
00075/0681 7 (256,448,3)
|
| 1235 |
+
00075/0693 7 (256,448,3)
|
| 1236 |
+
00075/0728 7 (256,448,3)
|
| 1237 |
+
00075/0731 7 (256,448,3)
|
| 1238 |
+
00075/0804 7 (256,448,3)
|
| 1239 |
+
00075/0974 7 (256,448,3)
|
| 1240 |
+
00075/0975 7 (256,448,3)
|
| 1241 |
+
00075/0983 7 (256,448,3)
|
| 1242 |
+
00075/0997 7 (256,448,3)
|
| 1243 |
+
00076/0006 7 (256,448,3)
|
| 1244 |
+
00076/0007 7 (256,448,3)
|
| 1245 |
+
00076/0011 7 (256,448,3)
|
| 1246 |
+
00076/0013 7 (256,448,3)
|
| 1247 |
+
00076/0014 7 (256,448,3)
|
| 1248 |
+
00076/0027 7 (256,448,3)
|
| 1249 |
+
00076/0029 7 (256,448,3)
|
| 1250 |
+
00076/0037 7 (256,448,3)
|
| 1251 |
+
00076/0041 7 (256,448,3)
|
| 1252 |
+
00076/0055 7 (256,448,3)
|
| 1253 |
+
00076/0071 7 (256,448,3)
|
| 1254 |
+
00076/0172 7 (256,448,3)
|
| 1255 |
+
00076/0275 7 (256,448,3)
|
| 1256 |
+
00076/0286 7 (256,448,3)
|
| 1257 |
+
00076/0467 7 (256,448,3)
|
| 1258 |
+
00076/0481 7 (256,448,3)
|
| 1259 |
+
00076/0527 7 (256,448,3)
|
| 1260 |
+
00076/0895 7 (256,448,3)
|
| 1261 |
+
00076/0896 7 (256,448,3)
|
| 1262 |
+
00076/0906 7 (256,448,3)
|
| 1263 |
+
00076/0924 7 (256,448,3)
|
| 1264 |
+
00076/0964 7 (256,448,3)
|
| 1265 |
+
00076/0984 7 (256,448,3)
|
| 1266 |
+
00077/0317 7 (256,448,3)
|
| 1267 |
+
00077/0322 7 (256,448,3)
|
| 1268 |
+
00077/0333 7 (256,448,3)
|
| 1269 |
+
00077/0334 7 (256,448,3)
|
| 1270 |
+
00077/0480 7 (256,448,3)
|
| 1271 |
+
00077/0488 7 (256,448,3)
|
| 1272 |
+
00077/0490 7 (256,448,3)
|
| 1273 |
+
00077/0582 7 (256,448,3)
|
| 1274 |
+
00077/0586 7 (256,448,3)
|
| 1275 |
+
00077/0969 7 (256,448,3)
|
| 1276 |
+
00078/0007 7 (256,448,3)
|
| 1277 |
+
00078/0011 7 (256,448,3)
|
| 1278 |
+
00078/0153 7 (256,448,3)
|
| 1279 |
+
00078/0289 7 (256,448,3)
|
| 1280 |
+
00078/0312 7 (256,448,3)
|
| 1281 |
+
00078/0492 7 (256,448,3)
|
| 1282 |
+
00078/0580 7 (256,448,3)
|
| 1283 |
+
00078/0595 7 (256,448,3)
|
| 1284 |
+
00078/0814 7 (256,448,3)
|
| 1285 |
+
00078/0950 7 (256,448,3)
|
| 1286 |
+
00078/0955 7 (256,448,3)
|
| 1287 |
+
00079/0060 7 (256,448,3)
|
| 1288 |
+
00079/0067 7 (256,448,3)
|
| 1289 |
+
00080/0216 7 (256,448,3)
|
| 1290 |
+
00080/0308 7 (256,448,3)
|
| 1291 |
+
00080/0504 7 (256,448,3)
|
| 1292 |
+
00080/0552 7 (256,448,3)
|
| 1293 |
+
00080/0576 7 (256,448,3)
|
| 1294 |
+
00080/0583 7 (256,448,3)
|
| 1295 |
+
00080/0837 7 (256,448,3)
|
| 1296 |
+
00080/0839 7 (256,448,3)
|
| 1297 |
+
00080/0871 7 (256,448,3)
|
| 1298 |
+
00080/0877 7 (256,448,3)
|
| 1299 |
+
00080/0880 7 (256,448,3)
|
| 1300 |
+
00080/0969 7 (256,448,3)
|
| 1301 |
+
00080/0973 7 (256,448,3)
|
| 1302 |
+
00080/0980 7 (256,448,3)
|
| 1303 |
+
00081/0202 7 (256,448,3)
|
| 1304 |
+
00081/0203 7 (256,448,3)
|
| 1305 |
+
00081/0210 7 (256,448,3)
|
| 1306 |
+
00081/0268 7 (256,448,3)
|
| 1307 |
+
00081/0281 7 (256,448,3)
|
| 1308 |
+
00081/0283 7 (256,448,3)
|
| 1309 |
+
00081/0317 7 (256,448,3)
|
| 1310 |
+
00081/0327 7 (256,448,3)
|
| 1311 |
+
00082/0018 7 (256,448,3)
|
| 1312 |
+
00082/0025 7 (256,448,3)
|
| 1313 |
+
00082/0089 7 (256,448,3)
|
| 1314 |
+
00082/0140 7 (256,448,3)
|
| 1315 |
+
00082/0442 7 (256,448,3)
|
| 1316 |
+
00082/0465 7 (256,448,3)
|
| 1317 |
+
00082/0473 7 (256,448,3)
|
| 1318 |
+
00082/0481 7 (256,448,3)
|
| 1319 |
+
00082/0492 7 (256,448,3)
|
| 1320 |
+
00082/0495 7 (256,448,3)
|
| 1321 |
+
00082/0497 7 (256,448,3)
|
| 1322 |
+
00082/0502 7 (256,448,3)
|
| 1323 |
+
00082/0504 7 (256,448,3)
|
| 1324 |
+
00082/0506 7 (256,448,3)
|
| 1325 |
+
00082/0507 7 (256,448,3)
|
| 1326 |
+
00082/0510 7 (256,448,3)
|
| 1327 |
+
00082/0519 7 (256,448,3)
|
| 1328 |
+
00082/0523 7 (256,448,3)
|
| 1329 |
+
00082/0588 7 (256,448,3)
|
| 1330 |
+
00082/0597 7 (256,448,3)
|
| 1331 |
+
00082/0632 7 (256,448,3)
|
| 1332 |
+
00082/0751 7 (256,448,3)
|
| 1333 |
+
00082/0767 7 (256,448,3)
|
| 1334 |
+
00082/0771 7 (256,448,3)
|
| 1335 |
+
00082/0790 7 (256,448,3)
|
| 1336 |
+
00082/0804 7 (256,448,3)
|
| 1337 |
+
00082/0823 7 (256,448,3)
|
| 1338 |
+
00083/0052 7 (256,448,3)
|
| 1339 |
+
00083/0056 7 (256,448,3)
|
| 1340 |
+
00083/0113 7 (256,448,3)
|
| 1341 |
+
00083/0114 7 (256,448,3)
|
| 1342 |
+
00083/0122 7 (256,448,3)
|
| 1343 |
+
00083/0137 7 (256,448,3)
|
| 1344 |
+
00083/0270 7 (256,448,3)
|
| 1345 |
+
00083/0295 7 (256,448,3)
|
| 1346 |
+
00083/0303 7 (256,448,3)
|
| 1347 |
+
00083/0308 7 (256,448,3)
|
| 1348 |
+
00083/0586 7 (256,448,3)
|
| 1349 |
+
00083/0592 7 (256,448,3)
|
| 1350 |
+
00083/0640 7 (256,448,3)
|
| 1351 |
+
00083/0648 7 (256,448,3)
|
| 1352 |
+
00083/0654 7 (256,448,3)
|
| 1353 |
+
00083/0662 7 (256,448,3)
|
| 1354 |
+
00083/0666 7 (256,448,3)
|
| 1355 |
+
00083/0668 7 (256,448,3)
|
| 1356 |
+
00083/0669 7 (256,448,3)
|
| 1357 |
+
00083/0675 7 (256,448,3)
|
| 1358 |
+
00083/0679 7 (256,448,3)
|
| 1359 |
+
00083/0681 7 (256,448,3)
|
| 1360 |
+
00083/0682 7 (256,448,3)
|
| 1361 |
+
00083/0694 7 (256,448,3)
|
| 1362 |
+
00083/0695 7 (256,448,3)
|
| 1363 |
+
00083/0697 7 (256,448,3)
|
| 1364 |
+
00083/0704 7 (256,448,3)
|
| 1365 |
+
00083/0713 7 (256,448,3)
|
| 1366 |
+
00083/0721 7 (256,448,3)
|
| 1367 |
+
00083/0855 7 (256,448,3)
|
| 1368 |
+
00084/0109 7 (256,448,3)
|
| 1369 |
+
00084/0113 7 (256,448,3)
|
| 1370 |
+
00084/0306 7 (256,448,3)
|
| 1371 |
+
00084/0442 7 (256,448,3)
|
| 1372 |
+
00084/0669 7 (256,448,3)
|
| 1373 |
+
00084/0679 7 (256,448,3)
|
| 1374 |
+
00084/0685 7 (256,448,3)
|
| 1375 |
+
00084/0691 7 (256,448,3)
|
| 1376 |
+
00084/0768 7 (256,448,3)
|
| 1377 |
+
00084/0817 7 (256,448,3)
|
| 1378 |
+
00085/0027 7 (256,448,3)
|
| 1379 |
+
00085/0035 7 (256,448,3)
|
| 1380 |
+
00085/0038 7 (256,448,3)
|
| 1381 |
+
00085/0223 7 (256,448,3)
|
| 1382 |
+
00085/0233 7 (256,448,3)
|
| 1383 |
+
00085/0281 7 (256,448,3)
|
| 1384 |
+
00085/0287 7 (256,448,3)
|
| 1385 |
+
00085/0313 7 (256,448,3)
|
| 1386 |
+
00085/0521 7 (256,448,3)
|
| 1387 |
+
00085/0848 7 (256,448,3)
|
| 1388 |
+
00085/0855 7 (256,448,3)
|
| 1389 |
+
00085/0865 7 (256,448,3)
|
| 1390 |
+
00085/0952 7 (256,448,3)
|
| 1391 |
+
00085/0964 7 (256,448,3)
|
| 1392 |
+
00085/0973 7 (256,448,3)
|
| 1393 |
+
00085/0986 7 (256,448,3)
|
| 1394 |
+
00085/0993 7 (256,448,3)
|
| 1395 |
+
00086/0070 7 (256,448,3)
|
| 1396 |
+
00086/0075 7 (256,448,3)
|
| 1397 |
+
00086/0094 7 (256,448,3)
|
| 1398 |
+
00086/0103 7 (256,448,3)
|
| 1399 |
+
00086/0112 7 (256,448,3)
|
| 1400 |
+
00086/0288 7 (256,448,3)
|
| 1401 |
+
00086/0576 7 (256,448,3)
|
| 1402 |
+
00086/0580 7 (256,448,3)
|
| 1403 |
+
00086/0584 7 (256,448,3)
|
| 1404 |
+
00086/0599 7 (256,448,3)
|
| 1405 |
+
00086/0600 7 (256,448,3)
|
| 1406 |
+
00086/0602 7 (256,448,3)
|
| 1407 |
+
00086/0612 7 (256,448,3)
|
| 1408 |
+
00086/0629 7 (256,448,3)
|
| 1409 |
+
00086/0655 7 (256,448,3)
|
| 1410 |
+
00086/0679 7 (256,448,3)
|
| 1411 |
+
00086/0694 7 (256,448,3)
|
| 1412 |
+
00086/0695 7 (256,448,3)
|
| 1413 |
+
00086/0701 7 (256,448,3)
|
| 1414 |
+
00086/0760 7 (256,448,3)
|
| 1415 |
+
00086/0786 7 (256,448,3)
|
| 1416 |
+
00086/0845 7 (256,448,3)
|
| 1417 |
+
00086/0868 7 (256,448,3)
|
| 1418 |
+
00086/0889 7 (256,448,3)
|
| 1419 |
+
00086/0891 7 (256,448,3)
|
| 1420 |
+
00086/0927 7 (256,448,3)
|
| 1421 |
+
00086/0938 7 (256,448,3)
|
| 1422 |
+
00086/0946 7 (256,448,3)
|
| 1423 |
+
00086/0963 7 (256,448,3)
|
| 1424 |
+
00086/0969 7 (256,448,3)
|
| 1425 |
+
00087/0023 7 (256,448,3)
|
| 1426 |
+
00087/0029 7 (256,448,3)
|
| 1427 |
+
00087/0144 7 (256,448,3)
|
| 1428 |
+
00087/0148 7 (256,448,3)
|
| 1429 |
+
00087/0159 7 (256,448,3)
|
| 1430 |
+
00087/0174 7 (256,448,3)
|
| 1431 |
+
00087/0283 7 (256,448,3)
|
| 1432 |
+
00087/0284 7 (256,448,3)
|
| 1433 |
+
00087/0294 7 (256,448,3)
|
| 1434 |
+
00087/0296 7 (256,448,3)
|
| 1435 |
+
00087/0498 7 (256,448,3)
|
| 1436 |
+
00087/0502 7 (256,448,3)
|
| 1437 |
+
00087/0532 7 (256,448,3)
|
| 1438 |
+
00087/0557 7 (256,448,3)
|
| 1439 |
+
00087/0559 7 (256,448,3)
|
| 1440 |
+
00087/0574 7 (256,448,3)
|
| 1441 |
+
00087/0577 7 (256,448,3)
|
| 1442 |
+
00088/0006 7 (256,448,3)
|
| 1443 |
+
00088/0268 7 (256,448,3)
|
| 1444 |
+
00088/0320 7 (256,448,3)
|
| 1445 |
+
00088/0412 7 (256,448,3)
|
| 1446 |
+
00088/0431 7 (256,448,3)
|
| 1447 |
+
00088/0432 7 (256,448,3)
|
| 1448 |
+
00088/0465 7 (256,448,3)
|
| 1449 |
+
00088/0507 7 (256,448,3)
|
| 1450 |
+
00088/0565 7 (256,448,3)
|
| 1451 |
+
00088/0629 7 (256,448,3)
|
| 1452 |
+
00088/0831 7 (256,448,3)
|
| 1453 |
+
00088/0836 7 (256,448,3)
|
| 1454 |
+
00088/0972 7 (256,448,3)
|
| 1455 |
+
00088/0974 7 (256,448,3)
|
| 1456 |
+
00088/0980 7 (256,448,3)
|
| 1457 |
+
00089/0067 7 (256,448,3)
|
| 1458 |
+
00089/0244 7 (256,448,3)
|
| 1459 |
+
00089/0404 7 (256,448,3)
|
| 1460 |
+
00089/0416 7 (256,448,3)
|
| 1461 |
+
00089/0419 7 (256,448,3)
|
| 1462 |
+
00089/0428 7 (256,448,3)
|
| 1463 |
+
00089/0712 7 (256,448,3)
|
| 1464 |
+
00089/0713 7 (256,448,3)
|
| 1465 |
+
00089/0723 7 (256,448,3)
|
| 1466 |
+
00089/0727 7 (256,448,3)
|
| 1467 |
+
00089/0770 7 (256,448,3)
|
| 1468 |
+
00089/0809 7 (256,448,3)
|
| 1469 |
+
00089/0811 7 (256,448,3)
|
| 1470 |
+
00089/0888 7 (256,448,3)
|
| 1471 |
+
00089/0898 7 (256,448,3)
|
| 1472 |
+
00089/0903 7 (256,448,3)
|
| 1473 |
+
00089/0907 7 (256,448,3)
|
| 1474 |
+
00089/0911 7 (256,448,3)
|
| 1475 |
+
00089/0915 7 (256,448,3)
|
| 1476 |
+
00089/0926 7 (256,448,3)
|
| 1477 |
+
00089/0955 7 (256,448,3)
|
| 1478 |
+
00090/0027 7 (256,448,3)
|
| 1479 |
+
00090/0028 7 (256,448,3)
|
| 1480 |
+
00090/0032 7 (256,448,3)
|
| 1481 |
+
00090/0038 7 (256,448,3)
|
| 1482 |
+
00090/0076 7 (256,448,3)
|
| 1483 |
+
00090/0081 7 (256,448,3)
|
| 1484 |
+
00090/0086 7 (256,448,3)
|
| 1485 |
+
00090/0119 7 (256,448,3)
|
| 1486 |
+
00090/0258 7 (256,448,3)
|
| 1487 |
+
00090/0261 7 (256,448,3)
|
| 1488 |
+
00090/0447 7 (256,448,3)
|
| 1489 |
+
00090/0498 7 (256,448,3)
|
| 1490 |
+
00090/0514 7 (256,448,3)
|
| 1491 |
+
00090/0523 7 (256,448,3)
|
| 1492 |
+
00090/0530 7 (256,448,3)
|
| 1493 |
+
00090/0540 7 (256,448,3)
|
| 1494 |
+
00090/0548 7 (256,448,3)
|
| 1495 |
+
00090/0565 7 (256,448,3)
|
| 1496 |
+
00090/0578 7 (256,448,3)
|
| 1497 |
+
00090/0580 7 (256,448,3)
|
| 1498 |
+
00090/0581 7 (256,448,3)
|
| 1499 |
+
00090/0780 7 (256,448,3)
|
| 1500 |
+
00090/0940 7 (256,448,3)
|
| 1501 |
+
00090/0984 7 (256,448,3)
|
| 1502 |
+
00091/0023 7 (256,448,3)
|
| 1503 |
+
00091/0051 7 (256,448,3)
|
| 1504 |
+
00091/0317 7 (256,448,3)
|
| 1505 |
+
00091/0320 7 (256,448,3)
|
| 1506 |
+
00091/0582 7 (256,448,3)
|
| 1507 |
+
00091/0585 7 (256,448,3)
|
| 1508 |
+
00091/0588 7 (256,448,3)
|
| 1509 |
+
00091/0601 7 (256,448,3)
|
| 1510 |
+
00091/0602 7 (256,448,3)
|
| 1511 |
+
00091/0603 7 (256,448,3)
|
| 1512 |
+
00091/0634 7 (256,448,3)
|
| 1513 |
+
00091/0693 7 (256,448,3)
|
| 1514 |
+
00091/0741 7 (256,448,3)
|
| 1515 |
+
00091/0966 7 (256,448,3)
|
| 1516 |
+
00091/0973 7 (256,448,3)
|
| 1517 |
+
00091/0985 7 (256,448,3)
|
| 1518 |
+
00092/0007 7 (256,448,3)
|
| 1519 |
+
00092/0132 7 (256,448,3)
|
| 1520 |
+
00092/0270 7 (256,448,3)
|
| 1521 |
+
00092/0296 7 (256,448,3)
|
| 1522 |
+
00092/0611 7 (256,448,3)
|
| 1523 |
+
00092/0625 7 (256,448,3)
|
| 1524 |
+
00092/0627 7 (256,448,3)
|
| 1525 |
+
00092/0651 7 (256,448,3)
|
| 1526 |
+
00092/0652 7 (256,448,3)
|
| 1527 |
+
00092/0910 7 (256,448,3)
|
| 1528 |
+
00093/0075 7 (256,448,3)
|
| 1529 |
+
00093/0078 7 (256,448,3)
|
| 1530 |
+
00093/0100 7 (256,448,3)
|
| 1531 |
+
00093/0132 7 (256,448,3)
|
| 1532 |
+
00093/0133 7 (256,448,3)
|
| 1533 |
+
00093/0176 7 (256,448,3)
|
| 1534 |
+
00093/0177 7 (256,448,3)
|
| 1535 |
+
00093/0178 7 (256,448,3)
|
| 1536 |
+
00093/0181 7 (256,448,3)
|
| 1537 |
+
00093/0183 7 (256,448,3)
|
| 1538 |
+
00093/0184 7 (256,448,3)
|
| 1539 |
+
00093/0286 7 (256,448,3)
|
| 1540 |
+
00093/0304 7 (256,448,3)
|
| 1541 |
+
00093/0305 7 (256,448,3)
|
| 1542 |
+
00093/0319 7 (256,448,3)
|
| 1543 |
+
00093/0324 7 (256,448,3)
|
| 1544 |
+
00093/0325 7 (256,448,3)
|
| 1545 |
+
00093/0327 7 (256,448,3)
|
| 1546 |
+
00093/0331 7 (256,448,3)
|
| 1547 |
+
00093/0444 7 (256,448,3)
|
| 1548 |
+
00093/0450 7 (256,448,3)
|
| 1549 |
+
00093/0593 7 (256,448,3)
|
| 1550 |
+
00094/0032 7 (256,448,3)
|
| 1551 |
+
00094/0057 7 (256,448,3)
|
| 1552 |
+
00094/0139 7 (256,448,3)
|
| 1553 |
+
00094/0206 7 (256,448,3)
|
| 1554 |
+
00094/0211 7 (256,448,3)
|
| 1555 |
+
00094/0215 7 (256,448,3)
|
| 1556 |
+
00094/0218 7 (256,448,3)
|
| 1557 |
+
00094/0257 7 (256,448,3)
|
| 1558 |
+
00094/0329 7 (256,448,3)
|
| 1559 |
+
00094/0331 7 (256,448,3)
|
| 1560 |
+
00094/0332 7 (256,448,3)
|
| 1561 |
+
00094/0369 7 (256,448,3)
|
| 1562 |
+
00094/0370 7 (256,448,3)
|
| 1563 |
+
00094/0383 7 (256,448,3)
|
| 1564 |
+
00094/0385 7 (256,448,3)
|
| 1565 |
+
00094/0387 7 (256,448,3)
|
| 1566 |
+
00094/0399 7 (256,448,3)
|
| 1567 |
+
00094/0605 7 (256,448,3)
|
| 1568 |
+
00094/0648 7 (256,448,3)
|
| 1569 |
+
00094/0649 7 (256,448,3)
|
| 1570 |
+
00094/0759 7 (256,448,3)
|
| 1571 |
+
00094/0800 7 (256,448,3)
|
| 1572 |
+
00094/0894 7 (256,448,3)
|
| 1573 |
+
00094/0896 7 (256,448,3)
|
| 1574 |
+
00095/0089 7 (256,448,3)
|
| 1575 |
+
00095/0108 7 (256,448,3)
|
| 1576 |
+
00095/0109 7 (256,448,3)
|
| 1577 |
+
00095/0114 7 (256,448,3)
|
| 1578 |
+
00095/0128 7 (256,448,3)
|
| 1579 |
+
00095/0133 7 (256,448,3)
|
| 1580 |
+
00095/0150 7 (256,448,3)
|
| 1581 |
+
00095/0153 7 (256,448,3)
|
| 1582 |
+
00095/0154 7 (256,448,3)
|
| 1583 |
+
00095/0196 7 (256,448,3)
|
| 1584 |
+
00095/0209 7 (256,448,3)
|
| 1585 |
+
00095/0228 7 (256,448,3)
|
| 1586 |
+
00095/0230 7 (256,448,3)
|
| 1587 |
+
00095/0231 7 (256,448,3)
|
| 1588 |
+
00095/0242 7 (256,448,3)
|
| 1589 |
+
00095/0243 7 (256,448,3)
|
| 1590 |
+
00095/0253 7 (256,448,3)
|
| 1591 |
+
00095/0280 7 (256,448,3)
|
| 1592 |
+
00095/0281 7 (256,448,3)
|
| 1593 |
+
00095/0283 7 (256,448,3)
|
| 1594 |
+
00095/0314 7 (256,448,3)
|
| 1595 |
+
00095/0868 7 (256,448,3)
|
| 1596 |
+
00095/0894 7 (256,448,3)
|
| 1597 |
+
00096/0062 7 (256,448,3)
|
| 1598 |
+
00096/0347 7 (256,448,3)
|
| 1599 |
+
00096/0348 7 (256,448,3)
|
| 1600 |
+
00096/0359 7 (256,448,3)
|
| 1601 |
+
00096/0363 7 (256,448,3)
|
| 1602 |
+
00096/0373 7 (256,448,3)
|
| 1603 |
+
00096/0378 7 (256,448,3)
|
| 1604 |
+
00096/0387 7 (256,448,3)
|
| 1605 |
+
00096/0395 7 (256,448,3)
|
| 1606 |
+
00096/0396 7 (256,448,3)
|
| 1607 |
+
00096/0404 7 (256,448,3)
|
| 1608 |
+
00096/0653 7 (256,448,3)
|
| 1609 |
+
00096/0668 7 (256,448,3)
|
| 1610 |
+
00096/0679 7 (256,448,3)
|
| 1611 |
+
00096/0729 7 (256,448,3)
|
| 1612 |
+
00096/0736 7 (256,448,3)
|
| 1613 |
+
00096/0823 7 (256,448,3)
|
basicsr/data/meta_info/meta_info_Vimeo90K_train_GT.txt
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
basicsr/data/paired_image_SR_LR_FullImage_Memory_dataset.py
ADDED
|
@@ -0,0 +1,296 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ------------------------------------------------------------------------
|
| 2 |
+
# Copyright (c) 2022 megvii-model. All Rights Reserved.
|
| 3 |
+
# ------------------------------------------------------------------------
|
| 4 |
+
# Modified from BasicSR (https://github.com/xinntao/BasicSR)
|
| 5 |
+
# Copyright 2018-2020 BasicSR Authors
|
| 6 |
+
# ------------------------------------------------------------------------
|
| 7 |
+
from torch.utils import data as data
|
| 8 |
+
from torchvision.transforms.functional import normalize, resize
|
| 9 |
+
|
| 10 |
+
from basicsr.data.data_util import (paired_paths_from_folder,
|
| 11 |
+
paired_paths_from_lmdb,
|
| 12 |
+
paired_paths_from_meta_info_file)
|
| 13 |
+
from basicsr.data.transforms import augment, paired_random_crop_hw
|
| 14 |
+
from basicsr.utils import FileClient, imfrombytes, img2tensor, padding
|
| 15 |
+
import os
|
| 16 |
+
import numpy as np
|
| 17 |
+
|
| 18 |
+
import pickle
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
class PairedImageSRLRFullImageMemoryDataset(data.Dataset):
|
| 22 |
+
"""Paired image dataset for image restoration.
|
| 23 |
+
|
| 24 |
+
Read LQ (Low Quality, e.g. LR (Low Resolution), blurry, noisy, etc) and
|
| 25 |
+
GT image pairs.
|
| 26 |
+
|
| 27 |
+
There are three modes:
|
| 28 |
+
1. 'lmdb': Use lmdb files.
|
| 29 |
+
If opt['io_backend'] == lmdb.
|
| 30 |
+
2. 'meta_info_file': Use meta information file to generate paths.
|
| 31 |
+
If opt['io_backend'] != lmdb and opt['meta_info_file'] is not None.
|
| 32 |
+
3. 'folder': Scan folders to generate paths.
|
| 33 |
+
The rest.
|
| 34 |
+
|
| 35 |
+
Args:
|
| 36 |
+
opt (dict): Config for train datasets. It contains the following keys:
|
| 37 |
+
dataroot_gt (str): Data root path for gt.
|
| 38 |
+
dataroot_lq (str): Data root path for lq.
|
| 39 |
+
meta_info_file (str): Path for meta information file.
|
| 40 |
+
io_backend (dict): IO backend type and other kwarg.
|
| 41 |
+
filename_tmpl (str): Template for each filename. Note that the
|
| 42 |
+
template excludes the file extension. Default: '{}'.
|
| 43 |
+
gt_size (int): Cropped patched size for gt patches.
|
| 44 |
+
use_flip (bool): Use horizontal flips.
|
| 45 |
+
use_rot (bool): Use rotation (use vertical flip and transposing h
|
| 46 |
+
and w for implementation).
|
| 47 |
+
|
| 48 |
+
scale (bool): Scale, which will be added automatically.
|
| 49 |
+
phase (str): 'train' or 'val'.
|
| 50 |
+
"""
|
| 51 |
+
|
| 52 |
+
def __init__(self, opt):
|
| 53 |
+
super(PairedImageSRLRFullImageMemoryDataset, self).__init__()
|
| 54 |
+
self.opt = opt
|
| 55 |
+
# file client (io backend)
|
| 56 |
+
self.file_client = None
|
| 57 |
+
# self.io_backend_opt = opt['io_backend']
|
| 58 |
+
self.mean = opt['mean'] if 'mean' in opt else None
|
| 59 |
+
self.std = opt['std'] if 'std' in opt else None
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
# data_list = []
|
| 63 |
+
self.gts = None
|
| 64 |
+
self.lqs = None
|
| 65 |
+
|
| 66 |
+
self.dataroot_gt = opt['dataroot_gt']
|
| 67 |
+
self.dataroot_lq = opt['dataroot_lq']
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
def __getitem__(self, index):
|
| 72 |
+
if self.lqs is None:
|
| 73 |
+
# print('self.dataroot lq .. ', self.dataroot_lq, self.dataroot_gt)
|
| 74 |
+
with open(self.dataroot_lq, 'rb') as f:
|
| 75 |
+
self.lqs = pickle.load(f)
|
| 76 |
+
if self.gts is None:
|
| 77 |
+
with open(self.dataroot_gt, 'rb') as f:
|
| 78 |
+
self.gts = pickle.load(f)
|
| 79 |
+
# with open(opt['dataroot_gt'], 'rb') as f:
|
| 80 |
+
# self.gts = pickle.load(f)
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
|
| 84 |
+
index = index % len(self.lqs)
|
| 85 |
+
|
| 86 |
+
scale = self.opt['scale']
|
| 87 |
+
|
| 88 |
+
# lr_id, hr_id = self.data_list[index]
|
| 89 |
+
#
|
| 90 |
+
# # print('lr_id, hr_id .. ', lr_id, hr_id)
|
| 91 |
+
#
|
| 92 |
+
# try:
|
| 93 |
+
# img_lr = np.frombuffer(self.fetcher.get(lr_id), np.uint8)
|
| 94 |
+
# img_hr = np.frombuffer(self.fetcher.get(hr_id), np.uint8)
|
| 95 |
+
# except:
|
| 96 |
+
# import time
|
| 97 |
+
# # time.sleep(0.01)
|
| 98 |
+
# # raise Exception(f'nori id..{index},{lr_id},{hr_id} not working .. ')
|
| 99 |
+
# print(f'nori id..{index},{lr_id},{hr_id} not working .. ')
|
| 100 |
+
# exit(0)
|
| 101 |
+
# # return self.__getitem__(index)
|
| 102 |
+
#
|
| 103 |
+
#
|
| 104 |
+
# h, w, c = 480, 480, 6
|
| 105 |
+
#
|
| 106 |
+
# if img_hr.shape[0] != h * w * c:
|
| 107 |
+
# print('index .. ', index, lr_id, hr_id, img_hr.shape, img_lr.shape)
|
| 108 |
+
#
|
| 109 |
+
# assert img_hr.shape[0] == h * w * c
|
| 110 |
+
|
| 111 |
+
img_lq = self.lqs[index].copy().astype(np.float32) / 255.
|
| 112 |
+
#
|
| 113 |
+
# print('index .. ', index)
|
| 114 |
+
# if index >= len(self.gts1):
|
| 115 |
+
# index_gt = index - len(self.gts1)
|
| 116 |
+
# img_gt = self.gts2[index_gt].copy().astype(np.float32) / 255.
|
| 117 |
+
# else:
|
| 118 |
+
# index_gt = index
|
| 119 |
+
# img_gt = self.gts1[index_gt].copy().astype(np.float32) / 255.
|
| 120 |
+
#
|
| 121 |
+
#
|
| 122 |
+
img_gt = self.gts[index].copy().astype(np.float32) / 255.
|
| 123 |
+
|
| 124 |
+
# img_lr = img_lr.reshape(h // 4, w // 4, c).astype(np.float32) / 255.
|
| 125 |
+
# img_hr = img_hr.reshape(h, w, c).astype(np.float32) / 255.
|
| 126 |
+
|
| 127 |
+
# img_lr, img_hr = img_lr.copy(), img_hr.copy()
|
| 128 |
+
|
| 129 |
+
|
| 130 |
+
# Load gt and lq images. Dimension order: HWC; channel order: BGR;
|
| 131 |
+
# image range: [0, 1], float32.
|
| 132 |
+
# gt_path = self.paths[index]['gt_path']
|
| 133 |
+
|
| 134 |
+
# gt_path_L = os.path.join(self.gt_folder, '{:04}_L.png'.format(index + 1))
|
| 135 |
+
# gt_path_R = os.path.join(self.gt_folder, '{:04}_R.png'.format(index + 1))
|
| 136 |
+
|
| 137 |
+
|
| 138 |
+
# print('gt path,', gt_path)
|
| 139 |
+
# img_bytes = self.file_client.get(gt_path_L, 'gt')
|
| 140 |
+
# try:
|
| 141 |
+
# img_gt_L = imfrombytes(img_bytes, float32=True)
|
| 142 |
+
# except:
|
| 143 |
+
# raise Exception("gt path {} not working".format(gt_path_L))
|
| 144 |
+
#
|
| 145 |
+
# img_bytes = self.file_client.get(gt_path_R, 'gt')
|
| 146 |
+
# try:
|
| 147 |
+
# img_gt_R = imfrombytes(img_bytes, float32=True)
|
| 148 |
+
# except:
|
| 149 |
+
# raise Exception("gt path {} not working".format(gt_path_R))
|
| 150 |
+
|
| 151 |
+
|
| 152 |
+
# lq_path_L = os.path.join(self.lq_folder, '{:04}_L.png'.format(index + 1))
|
| 153 |
+
# lq_path_R = os.path.join(self.lq_folder, '{:04}_R.png'.format(index + 1))
|
| 154 |
+
|
| 155 |
+
# lq_path = self.paths[index]['lq_path']
|
| 156 |
+
# print(', lq path', lq_path)
|
| 157 |
+
# img_bytes = self.file_client.get(lq_path_L, 'lq')
|
| 158 |
+
# try:
|
| 159 |
+
# img_lq_L = imfrombytes(img_bytes, float32=True)
|
| 160 |
+
# except:
|
| 161 |
+
# raise Exception("lq path {} not working".format(lq_path_L))
|
| 162 |
+
|
| 163 |
+
# img_bytes = self.file_client.get(lq_path_R, 'lq')
|
| 164 |
+
# try:
|
| 165 |
+
# img_lq_R = imfrombytes(img_bytes, float32=True)
|
| 166 |
+
# except:
|
| 167 |
+
# raise Exception("lq path {} not working".format(lq_path_R))
|
| 168 |
+
|
| 169 |
+
|
| 170 |
+
|
| 171 |
+
# img_gt = np.concatenate([img_gt_L, img_gt_R], axis=-1)
|
| 172 |
+
# img_lq = np.concatenate([img_lq_L, img_lq_R], axis=-1)
|
| 173 |
+
|
| 174 |
+
# img_gt = img_hr.copy()
|
| 175 |
+
# img_lq = img_lr.copy()
|
| 176 |
+
|
| 177 |
+
# augmentation for training
|
| 178 |
+
rot90 = False
|
| 179 |
+
|
| 180 |
+
if self.opt['phase'] == 'train':
|
| 181 |
+
if 'gt_size_h' in self.opt and 'gt_size_w' in self.opt:
|
| 182 |
+
gt_size_h = int(self.opt['gt_size_h'])
|
| 183 |
+
gt_size_w = int(self.opt['gt_size_w'])
|
| 184 |
+
else:
|
| 185 |
+
gt_size = int(self.opt['gt_size'])
|
| 186 |
+
gt_size_h, gt_size_w = gt_size, gt_size
|
| 187 |
+
|
| 188 |
+
|
| 189 |
+
if 'flip_LR' in self.opt and self.opt['flip_LR']:
|
| 190 |
+
if np.random.rand() < 0.5:
|
| 191 |
+
img_gt = img_gt[:, :, [3, 4, 5, 0, 1, 2]]
|
| 192 |
+
img_lq = img_lq[:, :, [3, 4, 5, 0, 1, 2]]
|
| 193 |
+
|
| 194 |
+
# img_gt, img_lq
|
| 195 |
+
|
| 196 |
+
if 'flip_RGB' in self.opt and self.opt['flip_RGB']:
|
| 197 |
+
idx = [
|
| 198 |
+
[0, 1, 2, 3, 4, 5],
|
| 199 |
+
[0, 2, 1, 3, 5, 4],
|
| 200 |
+
[1, 0, 2, 4, 3, 5],
|
| 201 |
+
[1, 2, 0, 4, 5, 3],
|
| 202 |
+
[2, 0, 1, 5, 3, 4],
|
| 203 |
+
[2, 1, 0, 5, 4, 3],
|
| 204 |
+
][int(np.random.rand() * 6)]
|
| 205 |
+
|
| 206 |
+
img_gt = img_gt[:, :, idx]
|
| 207 |
+
img_lq = img_lq[:, :, idx]
|
| 208 |
+
|
| 209 |
+
if 'inverse_RGB' in self.opt and self.opt['inverse_RGB']:
|
| 210 |
+
for i in range(3):
|
| 211 |
+
if np.random.rand() < 0.5:
|
| 212 |
+
img_gt[:, :, i] = 1 - img_gt[:, :, i]
|
| 213 |
+
img_gt[:, :, i+3] = 1 - img_gt[:, :, i+3]
|
| 214 |
+
img_lq[:, :, i] = 1 - img_lq[:, :, i]
|
| 215 |
+
img_lq[:, :, i+3] = 1 - img_lq[:, :, i+3]
|
| 216 |
+
|
| 217 |
+
if 'naive_inverse_RGB' in self.opt and self.opt['naive_inverse_RGB']:
|
| 218 |
+
# for i in range(3):
|
| 219 |
+
if np.random.rand() < 0.5:
|
| 220 |
+
img_gt = 1 - img_gt
|
| 221 |
+
img_lq = 1 - img_lq
|
| 222 |
+
# img_gt[:, :, i] = 1 - img_gt[:, :, i]
|
| 223 |
+
# img_gt[:, :, i+3] = 1 - img_gt[:, :, i+3]
|
| 224 |
+
# img_lq[:, :, i] = 1 - img_lq[:, :, i]
|
| 225 |
+
# img_lq[:, :, i+3] = 1 - img_lq[:, :, i+3]
|
| 226 |
+
|
| 227 |
+
if 'random_offset' in self.opt and self.opt['random_offset'] > 0:
|
| 228 |
+
# if np.random.rand() < 0.9:
|
| 229 |
+
S = int(self.opt['random_offset'])
|
| 230 |
+
|
| 231 |
+
offsets = int(np.random.rand() * (S+1)) #1~S
|
| 232 |
+
s2, s4 = 0, 0
|
| 233 |
+
|
| 234 |
+
if np.random.rand() < 0.5:
|
| 235 |
+
s2 = offsets
|
| 236 |
+
else:
|
| 237 |
+
s4 = offsets
|
| 238 |
+
|
| 239 |
+
_, w, _ = img_lq.shape
|
| 240 |
+
|
| 241 |
+
img_lq = np.concatenate([img_lq[:, s2:w-s4, :3], img_lq[:, s4:w-s2, 3:]], axis=-1)
|
| 242 |
+
img_gt = np.concatenate(
|
| 243 |
+
[img_gt[:, 4 * s2:4*w-4 * s4, :3], img_gt[:, 4 * s4:4*w-4 * s2, 3:]], axis=-1)
|
| 244 |
+
|
| 245 |
+
# random crop
|
| 246 |
+
img_gt, img_lq = img_gt.copy(), img_lq.copy()
|
| 247 |
+
img_gt, img_lq = paired_random_crop_hw(img_gt, img_lq, gt_size_h, gt_size_w, scale,
|
| 248 |
+
'gt_path_L_and_R')
|
| 249 |
+
# flip, rotation
|
| 250 |
+
imgs, status = augment([img_gt, img_lq], self.opt['use_hflip'],
|
| 251 |
+
self.opt['use_rot'], vflip=self.opt['use_vflip'], return_status=True)
|
| 252 |
+
|
| 253 |
+
|
| 254 |
+
img_gt, img_lq = imgs
|
| 255 |
+
hflip, vflip, rot90 = status
|
| 256 |
+
|
| 257 |
+
# if self.opt['phase'] == 'train':
|
| 258 |
+
# gt_size = self.opt['gt_size']
|
| 259 |
+
# # padding
|
| 260 |
+
# img_gt, img_lq = padding(img_gt, img_lq, gt_size)
|
| 261 |
+
#
|
| 262 |
+
# # random crop
|
| 263 |
+
# img_gt, img_lq = paired_random_crop(img_gt, img_lq, gt_size, scale,
|
| 264 |
+
# 'gt_path_L_and_R')
|
| 265 |
+
# # flip, rotation
|
| 266 |
+
# img_gt, img_lq = augment([img_gt, img_lq], self.opt['use_hflip'],
|
| 267 |
+
# self.opt['use_rot'], vflip=self.opt['use_vflip'])
|
| 268 |
+
|
| 269 |
+
# TODO: color space transform
|
| 270 |
+
# BGR to RGB, HWC to CHW, numpy to tensor
|
| 271 |
+
img_gt, img_lq = img2tensor([img_gt, img_lq],
|
| 272 |
+
bgr2rgb=True,
|
| 273 |
+
float32=True)
|
| 274 |
+
# normalize
|
| 275 |
+
if self.mean is not None or self.std is not None:
|
| 276 |
+
normalize(img_lq, self.mean, self.std, inplace=True)
|
| 277 |
+
normalize(img_gt, self.mean, self.std, inplace=True)
|
| 278 |
+
|
| 279 |
+
# if scale != 1:
|
| 280 |
+
# c, h, w = img_lq.shape
|
| 281 |
+
# img_lq = resize(img_lq, [h*scale, w*scale])
|
| 282 |
+
# print('img_lq .. ', img_lq.shape, img_gt.shape)
|
| 283 |
+
|
| 284 |
+
return {
|
| 285 |
+
'lq': img_lq,
|
| 286 |
+
'gt': img_gt,
|
| 287 |
+
'lq_path': 'lq path ',
|
| 288 |
+
'gt_path': 'gt path ',
|
| 289 |
+
'is_rot': 1. if rot90 else 0.
|
| 290 |
+
}
|
| 291 |
+
|
| 292 |
+
def __len__(self):
|
| 293 |
+
return 3200005
|
| 294 |
+
# return 1000
|
| 295 |
+
# return len(self.lqs)
|
| 296 |
+
# return len(self.paths)
|
basicsr/data/paired_image_SR_LR_dataset.py
ADDED
|
@@ -0,0 +1,301 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ------------------------------------------------------------------------
|
| 2 |
+
# Copyright (c) 2022 megvii-model. All Rights Reserved.
|
| 3 |
+
# ------------------------------------------------------------------------
|
| 4 |
+
# Modified from BasicSR (https://github.com/xinntao/BasicSR)
|
| 5 |
+
# Copyright 2018-2020 BasicSR Authors
|
| 6 |
+
# ------------------------------------------------------------------------
|
| 7 |
+
from torch.utils import data as data
|
| 8 |
+
from torchvision.transforms.functional import normalize, resize
|
| 9 |
+
|
| 10 |
+
from basicsr.data.data_util import (paired_paths_from_folder,
|
| 11 |
+
paired_paths_from_lmdb,
|
| 12 |
+
paired_paths_from_meta_info_file)
|
| 13 |
+
from basicsr.data.transforms import augment, paired_random_crop, paired_random_crop_hw
|
| 14 |
+
from basicsr.utils import FileClient, imfrombytes, img2tensor, padding
|
| 15 |
+
import os
|
| 16 |
+
import numpy as np
|
| 17 |
+
|
| 18 |
+
class PairedImageSRLRDataset(data.Dataset):
|
| 19 |
+
"""Paired image dataset for image restoration.
|
| 20 |
+
|
| 21 |
+
Read LQ (Low Quality, e.g. LR (Low Resolution), blurry, noisy, etc) and
|
| 22 |
+
GT image pairs.
|
| 23 |
+
|
| 24 |
+
There are three modes:
|
| 25 |
+
1. 'lmdb': Use lmdb files.
|
| 26 |
+
If opt['io_backend'] == lmdb.
|
| 27 |
+
2. 'meta_info_file': Use meta information file to generate paths.
|
| 28 |
+
If opt['io_backend'] != lmdb and opt['meta_info_file'] is not None.
|
| 29 |
+
3. 'folder': Scan folders to generate paths.
|
| 30 |
+
The rest.
|
| 31 |
+
|
| 32 |
+
Args:
|
| 33 |
+
opt (dict): Config for train datasets. It contains the following keys:
|
| 34 |
+
dataroot_gt (str): Data root path for gt.
|
| 35 |
+
dataroot_lq (str): Data root path for lq.
|
| 36 |
+
meta_info_file (str): Path for meta information file.
|
| 37 |
+
io_backend (dict): IO backend type and other kwarg.
|
| 38 |
+
filename_tmpl (str): Template for each filename. Note that the
|
| 39 |
+
template excludes the file extension. Default: '{}'.
|
| 40 |
+
gt_size (int): Cropped patched size for gt patches.
|
| 41 |
+
use_flip (bool): Use horizontal flips.
|
| 42 |
+
use_rot (bool): Use rotation (use vertical flip and transposing h
|
| 43 |
+
and w for implementation).
|
| 44 |
+
|
| 45 |
+
scale (bool): Scale, which will be added automatically.
|
| 46 |
+
phase (str): 'train' or 'val'.
|
| 47 |
+
"""
|
| 48 |
+
|
| 49 |
+
def __init__(self, opt):
|
| 50 |
+
super(PairedImageSRLRDataset, self).__init__()
|
| 51 |
+
self.opt = opt
|
| 52 |
+
# file client (io backend)
|
| 53 |
+
self.file_client = None
|
| 54 |
+
self.io_backend_opt = opt['io_backend']
|
| 55 |
+
self.mean = opt['mean'] if 'mean' in opt else None
|
| 56 |
+
self.std = opt['std'] if 'std' in opt else None
|
| 57 |
+
|
| 58 |
+
self.gt_folder, self.lq_folder = opt['dataroot_gt'], opt['dataroot_lq']
|
| 59 |
+
if 'filename_tmpl' in opt:
|
| 60 |
+
self.filename_tmpl = opt['filename_tmpl']
|
| 61 |
+
else:
|
| 62 |
+
self.filename_tmpl = '{}'
|
| 63 |
+
|
| 64 |
+
if self.io_backend_opt['type'] == 'lmdb':
|
| 65 |
+
self.io_backend_opt['db_paths'] = [self.lq_folder, self.gt_folder]
|
| 66 |
+
self.io_backend_opt['client_keys'] = ['lq', 'gt']
|
| 67 |
+
self.paths = paired_paths_from_lmdb(
|
| 68 |
+
[self.lq_folder, self.gt_folder], ['lq', 'gt'])
|
| 69 |
+
elif 'meta_info_file' in self.opt and self.opt[
|
| 70 |
+
'meta_info_file'] is not None:
|
| 71 |
+
self.paths = paired_paths_from_meta_info_file(
|
| 72 |
+
[self.lq_folder, self.gt_folder], ['lq', 'gt'],
|
| 73 |
+
self.opt['meta_info_file'], self.filename_tmpl)
|
| 74 |
+
else:
|
| 75 |
+
import os
|
| 76 |
+
nums_lq = len(os.listdir(self.lq_folder))
|
| 77 |
+
nums_gt = len(os.listdir(self.gt_folder))
|
| 78 |
+
|
| 79 |
+
# nums_lq = sorted(nums_lq)
|
| 80 |
+
# nums_gt = sorted(nums_gt)
|
| 81 |
+
|
| 82 |
+
# print('lq gt ... opt')
|
| 83 |
+
# print(nums_lq, nums_gt, opt)
|
| 84 |
+
assert nums_gt == nums_lq
|
| 85 |
+
|
| 86 |
+
self.nums = nums_lq
|
| 87 |
+
# {:04}_L {:04}_R
|
| 88 |
+
|
| 89 |
+
|
| 90 |
+
# self.paths = paired_paths_from_folder(
|
| 91 |
+
# [self.lq_folder, self.gt_folder], ['lq', 'gt'],
|
| 92 |
+
# self.filename_tmpl)
|
| 93 |
+
|
| 94 |
+
def __getitem__(self, index):
|
| 95 |
+
if self.file_client is None:
|
| 96 |
+
self.file_client = FileClient(
|
| 97 |
+
self.io_backend_opt.pop('type'), **self.io_backend_opt)
|
| 98 |
+
|
| 99 |
+
scale = self.opt['scale']
|
| 100 |
+
|
| 101 |
+
# Load gt and lq images. Dimension order: HWC; channel order: BGR;
|
| 102 |
+
# image range: [0, 1], float32.
|
| 103 |
+
# gt_path = self.paths[index]['gt_path']
|
| 104 |
+
|
| 105 |
+
gt_path_L = os.path.join(self.gt_folder, '{:04}_L.png'.format(index + 1))
|
| 106 |
+
gt_path_R = os.path.join(self.gt_folder, '{:04}_R.png'.format(index + 1))
|
| 107 |
+
|
| 108 |
+
|
| 109 |
+
# print('gt path,', gt_path)
|
| 110 |
+
img_bytes = self.file_client.get(gt_path_L, 'gt')
|
| 111 |
+
try:
|
| 112 |
+
img_gt_L = imfrombytes(img_bytes, float32=True)
|
| 113 |
+
except:
|
| 114 |
+
raise Exception("gt path {} not working".format(gt_path_L))
|
| 115 |
+
|
| 116 |
+
img_bytes = self.file_client.get(gt_path_R, 'gt')
|
| 117 |
+
try:
|
| 118 |
+
img_gt_R = imfrombytes(img_bytes, float32=True)
|
| 119 |
+
except:
|
| 120 |
+
raise Exception("gt path {} not working".format(gt_path_R))
|
| 121 |
+
|
| 122 |
+
|
| 123 |
+
lq_path_L = os.path.join(self.lq_folder, '{:04}_L.png'.format(index + 1))
|
| 124 |
+
lq_path_R = os.path.join(self.lq_folder, '{:04}_R.png'.format(index + 1))
|
| 125 |
+
|
| 126 |
+
# lq_path = self.paths[index]['lq_path']
|
| 127 |
+
# print(', lq path', lq_path)
|
| 128 |
+
img_bytes = self.file_client.get(lq_path_L, 'lq')
|
| 129 |
+
try:
|
| 130 |
+
img_lq_L = imfrombytes(img_bytes, float32=True)
|
| 131 |
+
except:
|
| 132 |
+
raise Exception("lq path {} not working".format(lq_path_L))
|
| 133 |
+
|
| 134 |
+
img_bytes = self.file_client.get(lq_path_R, 'lq')
|
| 135 |
+
try:
|
| 136 |
+
img_lq_R = imfrombytes(img_bytes, float32=True)
|
| 137 |
+
except:
|
| 138 |
+
raise Exception("lq path {} not working".format(lq_path_R))
|
| 139 |
+
|
| 140 |
+
|
| 141 |
+
|
| 142 |
+
img_gt = np.concatenate([img_gt_L, img_gt_R], axis=-1)
|
| 143 |
+
img_lq = np.concatenate([img_lq_L, img_lq_R], axis=-1)
|
| 144 |
+
|
| 145 |
+
# augmentation for training
|
| 146 |
+
if self.opt['phase'] == 'train':
|
| 147 |
+
gt_size = self.opt['gt_size']
|
| 148 |
+
# padding
|
| 149 |
+
img_gt, img_lq = padding(img_gt, img_lq, gt_size)
|
| 150 |
+
|
| 151 |
+
# random crop
|
| 152 |
+
img_gt, img_lq = paired_random_crop(img_gt, img_lq, gt_size, scale,
|
| 153 |
+
gt_path_L)
|
| 154 |
+
# flip, rotation
|
| 155 |
+
img_gt, img_lq = augment([img_gt, img_lq], self.opt['use_flip'],
|
| 156 |
+
self.opt['use_rot'])
|
| 157 |
+
|
| 158 |
+
# TODO: color space transform
|
| 159 |
+
# BGR to RGB, HWC to CHW, numpy to tensor
|
| 160 |
+
img_gt, img_lq = img2tensor([img_gt, img_lq],
|
| 161 |
+
bgr2rgb=True,
|
| 162 |
+
float32=True)
|
| 163 |
+
# normalize
|
| 164 |
+
if self.mean is not None or self.std is not None:
|
| 165 |
+
normalize(img_lq, self.mean, self.std, inplace=True)
|
| 166 |
+
normalize(img_gt, self.mean, self.std, inplace=True)
|
| 167 |
+
|
| 168 |
+
# if scale != 1:
|
| 169 |
+
# c, h, w = img_lq.shape
|
| 170 |
+
# img_lq = resize(img_lq, [h*scale, w*scale])
|
| 171 |
+
# print('img_lq .. ', img_lq.shape, img_gt.shape)
|
| 172 |
+
|
| 173 |
+
|
| 174 |
+
return {
|
| 175 |
+
'lq': img_lq,
|
| 176 |
+
'gt': img_gt,
|
| 177 |
+
'lq_path': f'{index+1:04}',
|
| 178 |
+
'gt_path': f'{index+1:04}',
|
| 179 |
+
}
|
| 180 |
+
|
| 181 |
+
def __len__(self):
|
| 182 |
+
return self.nums // 2
|
| 183 |
+
|
| 184 |
+
|
| 185 |
+
class PairedStereoImageDataset(data.Dataset):
|
| 186 |
+
'''
|
| 187 |
+
Paired dataset for stereo SR (Flickr1024, KITTI, Middlebury)
|
| 188 |
+
'''
|
| 189 |
+
def __init__(self, opt):
|
| 190 |
+
super(PairedStereoImageDataset, self).__init__()
|
| 191 |
+
self.opt = opt
|
| 192 |
+
# file client (io backend)
|
| 193 |
+
self.file_client = None
|
| 194 |
+
self.io_backend_opt = opt['io_backend']
|
| 195 |
+
self.mean = opt['mean'] if 'mean' in opt else None
|
| 196 |
+
self.std = opt['std'] if 'std' in opt else None
|
| 197 |
+
|
| 198 |
+
self.gt_folder, self.lq_folder = opt['dataroot_gt'], opt['dataroot_lq']
|
| 199 |
+
if 'filename_tmpl' in opt:
|
| 200 |
+
self.filename_tmpl = opt['filename_tmpl']
|
| 201 |
+
else:
|
| 202 |
+
self.filename_tmpl = '{}'
|
| 203 |
+
|
| 204 |
+
assert self.io_backend_opt['type'] == 'disk'
|
| 205 |
+
import os
|
| 206 |
+
self.lq_files = os.listdir(self.lq_folder)
|
| 207 |
+
self.gt_files = os.listdir(self.gt_folder)
|
| 208 |
+
|
| 209 |
+
self.nums = len(self.gt_files)
|
| 210 |
+
|
| 211 |
+
def __getitem__(self, index):
|
| 212 |
+
if self.file_client is None:
|
| 213 |
+
self.file_client = FileClient(
|
| 214 |
+
self.io_backend_opt.pop('type'), **self.io_backend_opt)
|
| 215 |
+
|
| 216 |
+
gt_path_L = os.path.join(self.gt_folder, self.gt_files[index], 'hr0.png')
|
| 217 |
+
gt_path_R = os.path.join(self.gt_folder, self.gt_files[index], 'hr1.png')
|
| 218 |
+
|
| 219 |
+
img_bytes = self.file_client.get(gt_path_L, 'gt')
|
| 220 |
+
try:
|
| 221 |
+
img_gt_L = imfrombytes(img_bytes, float32=True)
|
| 222 |
+
except:
|
| 223 |
+
raise Exception("gt path {} not working".format(gt_path_L))
|
| 224 |
+
|
| 225 |
+
img_bytes = self.file_client.get(gt_path_R, 'gt')
|
| 226 |
+
try:
|
| 227 |
+
img_gt_R = imfrombytes(img_bytes, float32=True)
|
| 228 |
+
except:
|
| 229 |
+
raise Exception("gt path {} not working".format(gt_path_R))
|
| 230 |
+
|
| 231 |
+
lq_path_L = os.path.join(self.lq_folder, self.lq_files[index], 'lr0.png')
|
| 232 |
+
lq_path_R = os.path.join(self.lq_folder, self.lq_files[index], 'lr1.png')
|
| 233 |
+
|
| 234 |
+
# lq_path = self.paths[index]['lq_path']
|
| 235 |
+
# print(', lq path', lq_path)
|
| 236 |
+
img_bytes = self.file_client.get(lq_path_L, 'lq')
|
| 237 |
+
try:
|
| 238 |
+
img_lq_L = imfrombytes(img_bytes, float32=True)
|
| 239 |
+
except:
|
| 240 |
+
raise Exception("lq path {} not working".format(lq_path_L))
|
| 241 |
+
|
| 242 |
+
img_bytes = self.file_client.get(lq_path_R, 'lq')
|
| 243 |
+
try:
|
| 244 |
+
img_lq_R = imfrombytes(img_bytes, float32=True)
|
| 245 |
+
except:
|
| 246 |
+
raise Exception("lq path {} not working".format(lq_path_R))
|
| 247 |
+
|
| 248 |
+
img_gt = np.concatenate([img_gt_L, img_gt_R], axis=-1)
|
| 249 |
+
img_lq = np.concatenate([img_lq_L, img_lq_R], axis=-1)
|
| 250 |
+
|
| 251 |
+
scale = self.opt['scale']
|
| 252 |
+
# augmentation for training
|
| 253 |
+
if self.opt['phase'] == 'train':
|
| 254 |
+
if 'gt_size_h' in self.opt and 'gt_size_w' in self.opt:
|
| 255 |
+
gt_size_h = int(self.opt['gt_size_h'])
|
| 256 |
+
gt_size_w = int(self.opt['gt_size_w'])
|
| 257 |
+
else:
|
| 258 |
+
gt_size = int(self.opt['gt_size'])
|
| 259 |
+
gt_size_h, gt_size_w = gt_size, gt_size
|
| 260 |
+
|
| 261 |
+
if 'flip_RGB' in self.opt and self.opt['flip_RGB']:
|
| 262 |
+
idx = [
|
| 263 |
+
[0, 1, 2, 3, 4, 5],
|
| 264 |
+
[0, 2, 1, 3, 5, 4],
|
| 265 |
+
[1, 0, 2, 4, 3, 5],
|
| 266 |
+
[1, 2, 0, 4, 5, 3],
|
| 267 |
+
[2, 0, 1, 5, 3, 4],
|
| 268 |
+
[2, 1, 0, 5, 4, 3],
|
| 269 |
+
][int(np.random.rand() * 6)]
|
| 270 |
+
|
| 271 |
+
img_gt = img_gt[:, :, idx]
|
| 272 |
+
img_lq = img_lq[:, :, idx]
|
| 273 |
+
|
| 274 |
+
# random crop
|
| 275 |
+
img_gt, img_lq = img_gt.copy(), img_lq.copy()
|
| 276 |
+
img_gt, img_lq = paired_random_crop_hw(img_gt, img_lq, gt_size_h, gt_size_w, scale,
|
| 277 |
+
'gt_path_L_and_R')
|
| 278 |
+
# flip, rotation
|
| 279 |
+
imgs, status = augment([img_gt, img_lq], self.opt['use_hflip'],
|
| 280 |
+
self.opt['use_rot'], vflip=self.opt['use_vflip'], return_status=True)
|
| 281 |
+
|
| 282 |
+
|
| 283 |
+
img_gt, img_lq = imgs
|
| 284 |
+
|
| 285 |
+
img_gt, img_lq = img2tensor([img_gt, img_lq],
|
| 286 |
+
bgr2rgb=True,
|
| 287 |
+
float32=True)
|
| 288 |
+
# normalize
|
| 289 |
+
if self.mean is not None or self.std is not None:
|
| 290 |
+
normalize(img_lq, self.mean, self.std, inplace=True)
|
| 291 |
+
normalize(img_gt, self.mean, self.std, inplace=True)
|
| 292 |
+
|
| 293 |
+
return {
|
| 294 |
+
'lq': img_lq,
|
| 295 |
+
'gt': img_gt,
|
| 296 |
+
'lq_path': os.path.join(self.lq_folder, self.lq_files[index]),
|
| 297 |
+
'gt_path': os.path.join(self.gt_folder, self.gt_files[index]),
|
| 298 |
+
}
|
| 299 |
+
|
| 300 |
+
def __len__(self):
|
| 301 |
+
return self.nums
|
basicsr/data/paired_image_dataset.py
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ------------------------------------------------------------------------
|
| 2 |
+
# Copyright (c) 2022 megvii-model. All Rights Reserved.
|
| 3 |
+
# ------------------------------------------------------------------------
|
| 4 |
+
# Modified from BasicSR (https://github.com/xinntao/BasicSR)
|
| 5 |
+
# Copyright 2018-2020 BasicSR Authors
|
| 6 |
+
# ------------------------------------------------------------------------
|
| 7 |
+
from torch.utils import data as data
|
| 8 |
+
from torchvision.transforms.functional import normalize
|
| 9 |
+
|
| 10 |
+
from basicsr.data.data_util import (paired_paths_from_folder,
|
| 11 |
+
paired_paths_from_lmdb,
|
| 12 |
+
paired_paths_from_meta_info_file)
|
| 13 |
+
from basicsr.data.transforms import augment, paired_random_crop
|
| 14 |
+
from basicsr.utils import FileClient, imfrombytes, img2tensor, padding
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
class PairedImageDataset(data.Dataset):
|
| 18 |
+
"""Paired image dataset for image restoration.
|
| 19 |
+
|
| 20 |
+
Read LQ (Low Quality, e.g. LR (Low Resolution), blurry, noisy, etc) and
|
| 21 |
+
GT image pairs.
|
| 22 |
+
|
| 23 |
+
There are three modes:
|
| 24 |
+
1. 'lmdb': Use lmdb files.
|
| 25 |
+
If opt['io_backend'] == lmdb.
|
| 26 |
+
2. 'meta_info_file': Use meta information file to generate paths.
|
| 27 |
+
If opt['io_backend'] != lmdb and opt['meta_info_file'] is not None.
|
| 28 |
+
3. 'folder': Scan folders to generate paths.
|
| 29 |
+
The rest.
|
| 30 |
+
|
| 31 |
+
Args:
|
| 32 |
+
opt (dict): Config for train datasets. It contains the following keys:
|
| 33 |
+
dataroot_gt (str): Data root path for gt.
|
| 34 |
+
dataroot_lq (str): Data root path for lq.
|
| 35 |
+
meta_info_file (str): Path for meta information file.
|
| 36 |
+
io_backend (dict): IO backend type and other kwarg.
|
| 37 |
+
filename_tmpl (str): Template for each filename. Note that the
|
| 38 |
+
template excludes the file extension. Default: '{}'.
|
| 39 |
+
gt_size (int): Cropped patched size for gt patches.
|
| 40 |
+
use_flip (bool): Use horizontal flips.
|
| 41 |
+
use_rot (bool): Use rotation (use vertical flip and transposing h
|
| 42 |
+
and w for implementation).
|
| 43 |
+
|
| 44 |
+
scale (bool): Scale, which will be added automatically.
|
| 45 |
+
phase (str): 'train' or 'val'.
|
| 46 |
+
"""
|
| 47 |
+
|
| 48 |
+
def __init__(self, opt):
|
| 49 |
+
super(PairedImageDataset, self).__init__()
|
| 50 |
+
self.opt = opt
|
| 51 |
+
# file client (io backend)
|
| 52 |
+
self.file_client = None
|
| 53 |
+
self.io_backend_opt = opt['io_backend']
|
| 54 |
+
self.mean = opt['mean'] if 'mean' in opt else None
|
| 55 |
+
self.std = opt['std'] if 'std' in opt else None
|
| 56 |
+
|
| 57 |
+
self.gt_folder, self.lq_folder = opt['dataroot_gt'], opt['dataroot_lq']
|
| 58 |
+
if 'filename_tmpl' in opt:
|
| 59 |
+
self.filename_tmpl = opt['filename_tmpl']
|
| 60 |
+
else:
|
| 61 |
+
self.filename_tmpl = '{}'
|
| 62 |
+
|
| 63 |
+
if self.io_backend_opt['type'] == 'lmdb':
|
| 64 |
+
self.io_backend_opt['db_paths'] = [self.lq_folder, self.gt_folder]
|
| 65 |
+
self.io_backend_opt['client_keys'] = ['lq', 'gt']
|
| 66 |
+
self.paths = paired_paths_from_lmdb(
|
| 67 |
+
[self.lq_folder, self.gt_folder], ['lq', 'gt'])
|
| 68 |
+
elif 'meta_info_file' in self.opt and self.opt[
|
| 69 |
+
'meta_info_file'] is not None:
|
| 70 |
+
self.paths = paired_paths_from_meta_info_file(
|
| 71 |
+
[self.lq_folder, self.gt_folder], ['lq', 'gt'],
|
| 72 |
+
self.opt['meta_info_file'], self.filename_tmpl)
|
| 73 |
+
else:
|
| 74 |
+
self.paths = paired_paths_from_folder(
|
| 75 |
+
[self.lq_folder, self.gt_folder], ['lq', 'gt'],
|
| 76 |
+
self.filename_tmpl)
|
| 77 |
+
|
| 78 |
+
def __getitem__(self, index):
|
| 79 |
+
if self.file_client is None:
|
| 80 |
+
self.file_client = FileClient(
|
| 81 |
+
self.io_backend_opt.pop('type'), **self.io_backend_opt)
|
| 82 |
+
|
| 83 |
+
scale = self.opt['scale']
|
| 84 |
+
|
| 85 |
+
# Load gt and lq images. Dimension order: HWC; channel order: BGR;
|
| 86 |
+
# image range: [0, 1], float32.
|
| 87 |
+
gt_path = self.paths[index]['gt_path']
|
| 88 |
+
# print('gt path,', gt_path)
|
| 89 |
+
img_bytes = self.file_client.get(gt_path, 'gt')
|
| 90 |
+
try:
|
| 91 |
+
img_gt = imfrombytes(img_bytes, float32=True)
|
| 92 |
+
except:
|
| 93 |
+
raise Exception("gt path {} not working".format(gt_path))
|
| 94 |
+
|
| 95 |
+
lq_path = self.paths[index]['lq_path']
|
| 96 |
+
# print(', lq path', lq_path)
|
| 97 |
+
img_bytes = self.file_client.get(lq_path, 'lq')
|
| 98 |
+
try:
|
| 99 |
+
img_lq = imfrombytes(img_bytes, float32=True)
|
| 100 |
+
except:
|
| 101 |
+
raise Exception("lq path {} not working".format(lq_path))
|
| 102 |
+
|
| 103 |
+
|
| 104 |
+
# augmentation for training
|
| 105 |
+
if self.opt['phase'] == 'train':
|
| 106 |
+
gt_size = self.opt['gt_size']
|
| 107 |
+
# padding
|
| 108 |
+
img_gt, img_lq = padding(img_gt, img_lq, gt_size)
|
| 109 |
+
|
| 110 |
+
# random crop
|
| 111 |
+
img_gt, img_lq = paired_random_crop(img_gt, img_lq, gt_size, scale,
|
| 112 |
+
gt_path)
|
| 113 |
+
# flip, rotation
|
| 114 |
+
img_gt, img_lq = augment([img_gt, img_lq], self.opt['use_flip'],
|
| 115 |
+
self.opt['use_rot'])
|
| 116 |
+
|
| 117 |
+
# TODO: color space transform
|
| 118 |
+
# BGR to RGB, HWC to CHW, numpy to tensor
|
| 119 |
+
img_gt, img_lq = img2tensor([img_gt, img_lq],
|
| 120 |
+
bgr2rgb=True,
|
| 121 |
+
float32=True)
|
| 122 |
+
# normalize
|
| 123 |
+
if self.mean is not None or self.std is not None:
|
| 124 |
+
normalize(img_lq, self.mean, self.std, inplace=True)
|
| 125 |
+
normalize(img_gt, self.mean, self.std, inplace=True)
|
| 126 |
+
|
| 127 |
+
return {
|
| 128 |
+
'lq': img_lq,
|
| 129 |
+
'gt': img_gt,
|
| 130 |
+
'lq_path': lq_path,
|
| 131 |
+
'gt_path': gt_path
|
| 132 |
+
}
|
| 133 |
+
|
| 134 |
+
def __len__(self):
|
| 135 |
+
return len(self.paths)
|
basicsr/data/prefetch_dataloader.py
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ------------------------------------------------------------------------
|
| 2 |
+
# Copyright (c) 2022 megvii-model. All Rights Reserved.
|
| 3 |
+
# ------------------------------------------------------------------------
|
| 4 |
+
# Modified from BasicSR (https://github.com/xinntao/BasicSR)
|
| 5 |
+
# Copyright 2018-2020 BasicSR Authors
|
| 6 |
+
# ------------------------------------------------------------------------
|
| 7 |
+
import queue as Queue
|
| 8 |
+
import threading
|
| 9 |
+
import torch
|
| 10 |
+
from torch.utils.data import DataLoader
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
class PrefetchGenerator(threading.Thread):
|
| 14 |
+
"""A general prefetch generator.
|
| 15 |
+
|
| 16 |
+
Ref:
|
| 17 |
+
https://stackoverflow.com/questions/7323664/python-generator-pre-fetch
|
| 18 |
+
|
| 19 |
+
Args:
|
| 20 |
+
generator: Python generator.
|
| 21 |
+
num_prefetch_queue (int): Number of prefetch queue.
|
| 22 |
+
"""
|
| 23 |
+
|
| 24 |
+
def __init__(self, generator, num_prefetch_queue):
|
| 25 |
+
threading.Thread.__init__(self)
|
| 26 |
+
self.queue = Queue.Queue(num_prefetch_queue)
|
| 27 |
+
self.generator = generator
|
| 28 |
+
self.daemon = True
|
| 29 |
+
self.start()
|
| 30 |
+
|
| 31 |
+
def run(self):
|
| 32 |
+
for item in self.generator:
|
| 33 |
+
self.queue.put(item)
|
| 34 |
+
self.queue.put(None)
|
| 35 |
+
|
| 36 |
+
def __next__(self):
|
| 37 |
+
next_item = self.queue.get()
|
| 38 |
+
if next_item is None:
|
| 39 |
+
raise StopIteration
|
| 40 |
+
return next_item
|
| 41 |
+
|
| 42 |
+
def __iter__(self):
|
| 43 |
+
return self
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
class PrefetchDataLoader(DataLoader):
|
| 47 |
+
"""Prefetch version of dataloader.
|
| 48 |
+
|
| 49 |
+
Ref:
|
| 50 |
+
https://github.com/IgorSusmelj/pytorch-styleguide/issues/5#
|
| 51 |
+
|
| 52 |
+
TODO:
|
| 53 |
+
Need to test on single gpu and ddp (multi-gpu). There is a known issue in
|
| 54 |
+
ddp.
|
| 55 |
+
|
| 56 |
+
Args:
|
| 57 |
+
num_prefetch_queue (int): Number of prefetch queue.
|
| 58 |
+
kwargs (dict): Other arguments for dataloader.
|
| 59 |
+
"""
|
| 60 |
+
|
| 61 |
+
def __init__(self, num_prefetch_queue, **kwargs):
|
| 62 |
+
self.num_prefetch_queue = num_prefetch_queue
|
| 63 |
+
super(PrefetchDataLoader, self).__init__(**kwargs)
|
| 64 |
+
|
| 65 |
+
def __iter__(self):
|
| 66 |
+
return PrefetchGenerator(super().__iter__(), self.num_prefetch_queue)
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
class CPUPrefetcher():
|
| 70 |
+
"""CPU prefetcher.
|
| 71 |
+
|
| 72 |
+
Args:
|
| 73 |
+
loader: Dataloader.
|
| 74 |
+
"""
|
| 75 |
+
|
| 76 |
+
def __init__(self, loader):
|
| 77 |
+
self.ori_loader = loader
|
| 78 |
+
self.loader = iter(loader)
|
| 79 |
+
|
| 80 |
+
def next(self):
|
| 81 |
+
try:
|
| 82 |
+
return next(self.loader)
|
| 83 |
+
except StopIteration:
|
| 84 |
+
return None
|
| 85 |
+
|
| 86 |
+
def reset(self):
|
| 87 |
+
self.loader = iter(self.ori_loader)
|
| 88 |
+
|
| 89 |
+
|
| 90 |
+
class CUDAPrefetcher():
|
| 91 |
+
"""CUDA prefetcher.
|
| 92 |
+
|
| 93 |
+
Ref:
|
| 94 |
+
https://github.com/NVIDIA/apex/issues/304#
|
| 95 |
+
|
| 96 |
+
It may consums more GPU memory.
|
| 97 |
+
|
| 98 |
+
Args:
|
| 99 |
+
loader: Dataloader.
|
| 100 |
+
opt (dict): Options.
|
| 101 |
+
"""
|
| 102 |
+
|
| 103 |
+
def __init__(self, loader, opt):
|
| 104 |
+
self.ori_loader = loader
|
| 105 |
+
self.loader = iter(loader)
|
| 106 |
+
self.opt = opt
|
| 107 |
+
self.stream = torch.cuda.Stream()
|
| 108 |
+
self.device = torch.device('cuda' if opt['num_gpu'] != 0 else 'cpu')
|
| 109 |
+
self.preload()
|
| 110 |
+
|
| 111 |
+
def preload(self):
|
| 112 |
+
try:
|
| 113 |
+
self.batch = next(self.loader) # self.batch is a dict
|
| 114 |
+
except StopIteration:
|
| 115 |
+
self.batch = None
|
| 116 |
+
return None
|
| 117 |
+
# put tensors to gpu
|
| 118 |
+
with torch.cuda.stream(self.stream):
|
| 119 |
+
for k, v in self.batch.items():
|
| 120 |
+
if torch.is_tensor(v):
|
| 121 |
+
self.batch[k] = self.batch[k].to(
|
| 122 |
+
device=self.device, non_blocking=True)
|
| 123 |
+
|
| 124 |
+
def next(self):
|
| 125 |
+
torch.cuda.current_stream().wait_stream(self.stream)
|
| 126 |
+
batch = self.batch
|
| 127 |
+
self.preload()
|
| 128 |
+
return batch
|
| 129 |
+
|
| 130 |
+
def reset(self):
|
| 131 |
+
self.loader = iter(self.ori_loader)
|
| 132 |
+
self.preload()
|
basicsr/data/reds_dataset.py
ADDED
|
@@ -0,0 +1,243 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ------------------------------------------------------------------------
|
| 2 |
+
# Copyright (c) 2022 megvii-model. All Rights Reserved.
|
| 3 |
+
# ------------------------------------------------------------------------
|
| 4 |
+
# Modified from BasicSR (https://github.com/xinntao/BasicSR)
|
| 5 |
+
# Copyright 2018-2020 BasicSR Authors
|
| 6 |
+
# ------------------------------------------------------------------------
|
| 7 |
+
import numpy as np
|
| 8 |
+
import random
|
| 9 |
+
import torch
|
| 10 |
+
from pathlib import Path
|
| 11 |
+
from torch.utils import data as data
|
| 12 |
+
|
| 13 |
+
from basicsr.data.transforms import augment, paired_random_crop
|
| 14 |
+
from basicsr.utils import FileClient, get_root_logger, imfrombytes, img2tensor
|
| 15 |
+
from basicsr.utils.flow_util import dequantize_flow
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
class REDSDataset(data.Dataset):
|
| 19 |
+
"""REDS dataset for training.
|
| 20 |
+
|
| 21 |
+
The keys are generated from a meta info txt file.
|
| 22 |
+
basicsr/data/meta_info/meta_info_REDS_GT.txt
|
| 23 |
+
|
| 24 |
+
Each line contains:
|
| 25 |
+
1. subfolder (clip) name; 2. frame number; 3. image shape, seperated by
|
| 26 |
+
a white space.
|
| 27 |
+
Examples:
|
| 28 |
+
000 100 (720,1280,3)
|
| 29 |
+
001 100 (720,1280,3)
|
| 30 |
+
...
|
| 31 |
+
|
| 32 |
+
Key examples: "000/00000000"
|
| 33 |
+
GT (gt): Ground-Truth;
|
| 34 |
+
LQ (lq): Low-Quality, e.g., low-resolution/blurry/noisy/compressed frames.
|
| 35 |
+
|
| 36 |
+
Args:
|
| 37 |
+
opt (dict): Config for train dataset. It contains the following keys:
|
| 38 |
+
dataroot_gt (str): Data root path for gt.
|
| 39 |
+
dataroot_lq (str): Data root path for lq.
|
| 40 |
+
dataroot_flow (str, optional): Data root path for flow.
|
| 41 |
+
meta_info_file (str): Path for meta information file.
|
| 42 |
+
val_partition (str): Validation partition types. 'REDS4' or
|
| 43 |
+
'official'.
|
| 44 |
+
io_backend (dict): IO backend type and other kwarg.
|
| 45 |
+
|
| 46 |
+
num_frame (int): Window size for input frames.
|
| 47 |
+
gt_size (int): Cropped patched size for gt patches.
|
| 48 |
+
interval_list (list): Interval list for temporal augmentation.
|
| 49 |
+
random_reverse (bool): Random reverse input frames.
|
| 50 |
+
use_flip (bool): Use horizontal flips.
|
| 51 |
+
use_rot (bool): Use rotation (use vertical flip and transposing h
|
| 52 |
+
and w for implementation).
|
| 53 |
+
|
| 54 |
+
scale (bool): Scale, which will be added automatically.
|
| 55 |
+
"""
|
| 56 |
+
|
| 57 |
+
def __init__(self, opt):
|
| 58 |
+
super(REDSDataset, self).__init__()
|
| 59 |
+
self.opt = opt
|
| 60 |
+
self.gt_root, self.lq_root = Path(opt['dataroot_gt']), Path(
|
| 61 |
+
opt['dataroot_lq'])
|
| 62 |
+
self.flow_root = Path(
|
| 63 |
+
opt['dataroot_flow']) if opt['dataroot_flow'] is not None else None
|
| 64 |
+
assert opt['num_frame'] % 2 == 1, (
|
| 65 |
+
f'num_frame should be odd number, but got {opt["num_frame"]}')
|
| 66 |
+
self.num_frame = opt['num_frame']
|
| 67 |
+
self.num_half_frames = opt['num_frame'] // 2
|
| 68 |
+
|
| 69 |
+
self.keys = []
|
| 70 |
+
with open(opt['meta_info_file'], 'r') as fin:
|
| 71 |
+
for line in fin:
|
| 72 |
+
folder, frame_num, _ = line.split(' ')
|
| 73 |
+
self.keys.extend(
|
| 74 |
+
[f'{folder}/{i:08d}' for i in range(int(frame_num))])
|
| 75 |
+
|
| 76 |
+
# remove the video clips used in validation
|
| 77 |
+
if opt['val_partition'] == 'REDS4':
|
| 78 |
+
val_partition = ['000', '011', '015', '020']
|
| 79 |
+
elif opt['val_partition'] == 'official':
|
| 80 |
+
val_partition = [f'{v:03d}' for v in range(240, 270)]
|
| 81 |
+
else:
|
| 82 |
+
raise ValueError(
|
| 83 |
+
f'Wrong validation partition {opt["val_partition"]}.'
|
| 84 |
+
f"Supported ones are ['official', 'REDS4'].")
|
| 85 |
+
self.keys = [
|
| 86 |
+
v for v in self.keys if v.split('/')[0] not in val_partition
|
| 87 |
+
]
|
| 88 |
+
|
| 89 |
+
# file client (io backend)
|
| 90 |
+
self.file_client = None
|
| 91 |
+
self.io_backend_opt = opt['io_backend']
|
| 92 |
+
self.is_lmdb = False
|
| 93 |
+
if self.io_backend_opt['type'] == 'lmdb':
|
| 94 |
+
self.is_lmdb = True
|
| 95 |
+
if self.flow_root is not None:
|
| 96 |
+
self.io_backend_opt['db_paths'] = [
|
| 97 |
+
self.lq_root, self.gt_root, self.flow_root
|
| 98 |
+
]
|
| 99 |
+
self.io_backend_opt['client_keys'] = ['lq', 'gt', 'flow']
|
| 100 |
+
else:
|
| 101 |
+
self.io_backend_opt['db_paths'] = [self.lq_root, self.gt_root]
|
| 102 |
+
self.io_backend_opt['client_keys'] = ['lq', 'gt']
|
| 103 |
+
|
| 104 |
+
# temporal augmentation configs
|
| 105 |
+
self.interval_list = opt['interval_list']
|
| 106 |
+
self.random_reverse = opt['random_reverse']
|
| 107 |
+
interval_str = ','.join(str(x) for x in opt['interval_list'])
|
| 108 |
+
logger = get_root_logger()
|
| 109 |
+
logger.info(f'Temporal augmentation interval list: [{interval_str}]; '
|
| 110 |
+
f'random reverse is {self.random_reverse}.')
|
| 111 |
+
|
| 112 |
+
def __getitem__(self, index):
|
| 113 |
+
if self.file_client is None:
|
| 114 |
+
self.file_client = FileClient(
|
| 115 |
+
self.io_backend_opt.pop('type'), **self.io_backend_opt)
|
| 116 |
+
|
| 117 |
+
scale = self.opt['scale']
|
| 118 |
+
gt_size = self.opt['gt_size']
|
| 119 |
+
key = self.keys[index]
|
| 120 |
+
clip_name, frame_name = key.split('/') # key example: 000/00000000
|
| 121 |
+
center_frame_idx = int(frame_name)
|
| 122 |
+
|
| 123 |
+
# determine the neighboring frames
|
| 124 |
+
interval = random.choice(self.interval_list)
|
| 125 |
+
|
| 126 |
+
# ensure not exceeding the borders
|
| 127 |
+
start_frame_idx = center_frame_idx - self.num_half_frames * interval
|
| 128 |
+
end_frame_idx = center_frame_idx + self.num_half_frames * interval
|
| 129 |
+
# each clip has 100 frames starting from 0 to 99
|
| 130 |
+
while (start_frame_idx < 0) or (end_frame_idx > 99):
|
| 131 |
+
center_frame_idx = random.randint(0, 99)
|
| 132 |
+
start_frame_idx = (
|
| 133 |
+
center_frame_idx - self.num_half_frames * interval)
|
| 134 |
+
end_frame_idx = center_frame_idx + self.num_half_frames * interval
|
| 135 |
+
frame_name = f'{center_frame_idx:08d}'
|
| 136 |
+
neighbor_list = list(
|
| 137 |
+
range(center_frame_idx - self.num_half_frames * interval,
|
| 138 |
+
center_frame_idx + self.num_half_frames * interval + 1,
|
| 139 |
+
interval))
|
| 140 |
+
# random reverse
|
| 141 |
+
if self.random_reverse and random.random() < 0.5:
|
| 142 |
+
neighbor_list.reverse()
|
| 143 |
+
|
| 144 |
+
assert len(neighbor_list) == self.num_frame, (
|
| 145 |
+
f'Wrong length of neighbor list: {len(neighbor_list)}')
|
| 146 |
+
|
| 147 |
+
# get the GT frame (as the center frame)
|
| 148 |
+
if self.is_lmdb:
|
| 149 |
+
img_gt_path = f'{clip_name}/{frame_name}'
|
| 150 |
+
else:
|
| 151 |
+
img_gt_path = self.gt_root / clip_name / f'{frame_name}.png'
|
| 152 |
+
img_bytes = self.file_client.get(img_gt_path, 'gt')
|
| 153 |
+
img_gt = imfrombytes(img_bytes, float32=True)
|
| 154 |
+
|
| 155 |
+
# get the neighboring LQ frames
|
| 156 |
+
img_lqs = []
|
| 157 |
+
for neighbor in neighbor_list:
|
| 158 |
+
if self.is_lmdb:
|
| 159 |
+
img_lq_path = f'{clip_name}/{neighbor:08d}'
|
| 160 |
+
else:
|
| 161 |
+
img_lq_path = self.lq_root / clip_name / f'{neighbor:08d}.png'
|
| 162 |
+
img_bytes = self.file_client.get(img_lq_path, 'lq')
|
| 163 |
+
img_lq = imfrombytes(img_bytes, float32=True)
|
| 164 |
+
img_lqs.append(img_lq)
|
| 165 |
+
|
| 166 |
+
# get flows
|
| 167 |
+
if self.flow_root is not None:
|
| 168 |
+
img_flows = []
|
| 169 |
+
# read previous flows
|
| 170 |
+
for i in range(self.num_half_frames, 0, -1):
|
| 171 |
+
if self.is_lmdb:
|
| 172 |
+
flow_path = f'{clip_name}/{frame_name}_p{i}'
|
| 173 |
+
else:
|
| 174 |
+
flow_path = (
|
| 175 |
+
self.flow_root / clip_name / f'{frame_name}_p{i}.png')
|
| 176 |
+
img_bytes = self.file_client.get(flow_path, 'flow')
|
| 177 |
+
cat_flow = imfrombytes(
|
| 178 |
+
img_bytes, flag='grayscale',
|
| 179 |
+
float32=False) # uint8, [0, 255]
|
| 180 |
+
dx, dy = np.split(cat_flow, 2, axis=0)
|
| 181 |
+
flow = dequantize_flow(
|
| 182 |
+
dx, dy, max_val=20,
|
| 183 |
+
denorm=False) # we use max_val 20 here.
|
| 184 |
+
img_flows.append(flow)
|
| 185 |
+
# read next flows
|
| 186 |
+
for i in range(1, self.num_half_frames + 1):
|
| 187 |
+
if self.is_lmdb:
|
| 188 |
+
flow_path = f'{clip_name}/{frame_name}_n{i}'
|
| 189 |
+
else:
|
| 190 |
+
flow_path = (
|
| 191 |
+
self.flow_root / clip_name / f'{frame_name}_n{i}.png')
|
| 192 |
+
img_bytes = self.file_client.get(flow_path, 'flow')
|
| 193 |
+
cat_flow = imfrombytes(
|
| 194 |
+
img_bytes, flag='grayscale',
|
| 195 |
+
float32=False) # uint8, [0, 255]
|
| 196 |
+
dx, dy = np.split(cat_flow, 2, axis=0)
|
| 197 |
+
flow = dequantize_flow(
|
| 198 |
+
dx, dy, max_val=20,
|
| 199 |
+
denorm=False) # we use max_val 20 here.
|
| 200 |
+
img_flows.append(flow)
|
| 201 |
+
|
| 202 |
+
# for random crop, here, img_flows and img_lqs have the same
|
| 203 |
+
# spatial size
|
| 204 |
+
img_lqs.extend(img_flows)
|
| 205 |
+
|
| 206 |
+
# randomly crop
|
| 207 |
+
img_gt, img_lqs = paired_random_crop(img_gt, img_lqs, gt_size, scale,
|
| 208 |
+
img_gt_path)
|
| 209 |
+
if self.flow_root is not None:
|
| 210 |
+
img_lqs, img_flows = img_lqs[:self.num_frame], img_lqs[self.
|
| 211 |
+
num_frame:]
|
| 212 |
+
|
| 213 |
+
# augmentation - flip, rotate
|
| 214 |
+
img_lqs.append(img_gt)
|
| 215 |
+
if self.flow_root is not None:
|
| 216 |
+
img_results, img_flows = augment(img_lqs, self.opt['use_flip'],
|
| 217 |
+
self.opt['use_rot'], img_flows)
|
| 218 |
+
else:
|
| 219 |
+
img_results = augment(img_lqs, self.opt['use_flip'],
|
| 220 |
+
self.opt['use_rot'])
|
| 221 |
+
|
| 222 |
+
img_results = img2tensor(img_results)
|
| 223 |
+
img_lqs = torch.stack(img_results[0:-1], dim=0)
|
| 224 |
+
img_gt = img_results[-1]
|
| 225 |
+
|
| 226 |
+
if self.flow_root is not None:
|
| 227 |
+
img_flows = img2tensor(img_flows)
|
| 228 |
+
# add the zero center flow
|
| 229 |
+
img_flows.insert(self.num_half_frames,
|
| 230 |
+
torch.zeros_like(img_flows[0]))
|
| 231 |
+
img_flows = torch.stack(img_flows, dim=0)
|
| 232 |
+
|
| 233 |
+
# img_lqs: (t, c, h, w)
|
| 234 |
+
# img_flows: (t, 2, h, w)
|
| 235 |
+
# img_gt: (c, h, w)
|
| 236 |
+
# key: str
|
| 237 |
+
if self.flow_root is not None:
|
| 238 |
+
return {'lq': img_lqs, 'flow': img_flows, 'gt': img_gt, 'key': key}
|
| 239 |
+
else:
|
| 240 |
+
return {'lq': img_lqs, 'gt': img_gt, 'key': key}
|
| 241 |
+
|
| 242 |
+
def __len__(self):
|
| 243 |
+
return len(self.keys)
|
basicsr/data/single_image_dataset.py
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ------------------------------------------------------------------------
|
| 2 |
+
# Copyright (c) 2022 megvii-model. All Rights Reserved.
|
| 3 |
+
# ------------------------------------------------------------------------
|
| 4 |
+
# Modified from BasicSR (https://github.com/xinntao/BasicSR)
|
| 5 |
+
# Copyright 2018-2020 BasicSR Authors
|
| 6 |
+
# ------------------------------------------------------------------------
|
| 7 |
+
from os import path as osp
|
| 8 |
+
from torch.utils import data as data
|
| 9 |
+
from torchvision.transforms.functional import normalize
|
| 10 |
+
|
| 11 |
+
from basicsr.data.data_util import paths_from_lmdb
|
| 12 |
+
from basicsr.utils import FileClient, imfrombytes, img2tensor, scandir
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
class SingleImageDataset(data.Dataset):
|
| 16 |
+
"""Read only lq images in the test phase.
|
| 17 |
+
|
| 18 |
+
Read LQ (Low Quality, e.g. LR (Low Resolution), blurry, noisy, etc).
|
| 19 |
+
|
| 20 |
+
There are two modes:
|
| 21 |
+
1. 'meta_info_file': Use meta information file to generate paths.
|
| 22 |
+
2. 'folder': Scan folders to generate paths.
|
| 23 |
+
|
| 24 |
+
Args:
|
| 25 |
+
opt (dict): Config for train datasets. It contains the following keys:
|
| 26 |
+
dataroot_lq (str): Data root path for lq.
|
| 27 |
+
meta_info_file (str): Path for meta information file.
|
| 28 |
+
io_backend (dict): IO backend type and other kwarg.
|
| 29 |
+
"""
|
| 30 |
+
|
| 31 |
+
def __init__(self, opt):
|
| 32 |
+
super(SingleImageDataset, self).__init__()
|
| 33 |
+
self.opt = opt
|
| 34 |
+
# file client (io backend)
|
| 35 |
+
self.file_client = None
|
| 36 |
+
self.io_backend_opt = opt['io_backend']
|
| 37 |
+
self.mean = opt['mean'] if 'mean' in opt else None
|
| 38 |
+
self.std = opt['std'] if 'std' in opt else None
|
| 39 |
+
self.lq_folder = opt['dataroot_lq']
|
| 40 |
+
|
| 41 |
+
if self.io_backend_opt['type'] == 'lmdb':
|
| 42 |
+
self.io_backend_opt['db_paths'] = [self.lq_folder]
|
| 43 |
+
self.io_backend_opt['client_keys'] = ['lq']
|
| 44 |
+
self.paths = paths_from_lmdb(self.lq_folder)
|
| 45 |
+
elif 'meta_info_file' in self.opt:
|
| 46 |
+
with open(self.opt['meta_info_file'], 'r') as fin:
|
| 47 |
+
self.paths = [
|
| 48 |
+
osp.join(self.lq_folder,
|
| 49 |
+
line.split(' ')[0]) for line in fin
|
| 50 |
+
]
|
| 51 |
+
else:
|
| 52 |
+
self.paths = sorted(list(scandir(self.lq_folder, full_path=True)))
|
| 53 |
+
|
| 54 |
+
def __getitem__(self, index):
|
| 55 |
+
if self.file_client is None:
|
| 56 |
+
self.file_client = FileClient(
|
| 57 |
+
self.io_backend_opt.pop('type'), **self.io_backend_opt)
|
| 58 |
+
|
| 59 |
+
# load lq image
|
| 60 |
+
lq_path = self.paths[index]
|
| 61 |
+
img_bytes = self.file_client.get(lq_path, 'lq')
|
| 62 |
+
img_lq = imfrombytes(img_bytes, float32=True)
|
| 63 |
+
|
| 64 |
+
# TODO: color space transform
|
| 65 |
+
# BGR to RGB, HWC to CHW, numpy to tensor
|
| 66 |
+
img_lq = img2tensor(img_lq, bgr2rgb=True, float32=True)
|
| 67 |
+
# normalize
|
| 68 |
+
if self.mean is not None or self.std is not None:
|
| 69 |
+
normalize(img_lq, self.mean, self.std, inplace=True)
|
| 70 |
+
return {'lq': img_lq, 'lq_path': lq_path}
|
| 71 |
+
|
| 72 |
+
def __len__(self):
|
| 73 |
+
return len(self.paths)
|
basicsr/data/transforms.py
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ------------------------------------------------------------------------
|
| 2 |
+
# Copyright (c) 2022 megvii-model. All Rights Reserved.
|
| 3 |
+
# ------------------------------------------------------------------------
|
| 4 |
+
# Modified from BasicSR (https://github.com/xinntao/BasicSR)
|
| 5 |
+
# Copyright 2018-2020 BasicSR Authors
|
| 6 |
+
# ------------------------------------------------------------------------
|
| 7 |
+
import cv2
|
| 8 |
+
import random
|
| 9 |
+
from cv2 import rotate
|
| 10 |
+
import numpy as np
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
def mod_crop(img, scale):
|
| 14 |
+
"""Mod crop images, used during testing.
|
| 15 |
+
|
| 16 |
+
Args:
|
| 17 |
+
img (ndarray): Input image.
|
| 18 |
+
scale (int): Scale factor.
|
| 19 |
+
|
| 20 |
+
Returns:
|
| 21 |
+
ndarray: Result image.
|
| 22 |
+
"""
|
| 23 |
+
img = img.copy()
|
| 24 |
+
if img.ndim in (2, 3):
|
| 25 |
+
h, w = img.shape[0], img.shape[1]
|
| 26 |
+
h_remainder, w_remainder = h % scale, w % scale
|
| 27 |
+
img = img[:h - h_remainder, :w - w_remainder, ...]
|
| 28 |
+
else:
|
| 29 |
+
raise ValueError(f'Wrong img ndim: {img.ndim}.')
|
| 30 |
+
return img
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
def paired_random_crop(img_gts, img_lqs, gt_patch_size, scale, gt_path):
|
| 34 |
+
"""Paired random crop.
|
| 35 |
+
|
| 36 |
+
It crops lists of lq and gt images with corresponding locations.
|
| 37 |
+
|
| 38 |
+
Args:
|
| 39 |
+
img_gts (list[ndarray] | ndarray): GT images. Note that all images
|
| 40 |
+
should have the same shape. If the input is an ndarray, it will
|
| 41 |
+
be transformed to a list containing itself.
|
| 42 |
+
img_lqs (list[ndarray] | ndarray): LQ images. Note that all images
|
| 43 |
+
should have the same shape. If the input is an ndarray, it will
|
| 44 |
+
be transformed to a list containing itself.
|
| 45 |
+
gt_patch_size (int): GT patch size.
|
| 46 |
+
scale (int): Scale factor.
|
| 47 |
+
gt_path (str): Path to ground-truth.
|
| 48 |
+
|
| 49 |
+
Returns:
|
| 50 |
+
list[ndarray] | ndarray: GT images and LQ images. If returned results
|
| 51 |
+
only have one element, just return ndarray.
|
| 52 |
+
"""
|
| 53 |
+
|
| 54 |
+
if not isinstance(img_gts, list):
|
| 55 |
+
img_gts = [img_gts]
|
| 56 |
+
if not isinstance(img_lqs, list):
|
| 57 |
+
img_lqs = [img_lqs]
|
| 58 |
+
|
| 59 |
+
h_lq, w_lq, _ = img_lqs[0].shape
|
| 60 |
+
h_gt, w_gt, _ = img_gts[0].shape
|
| 61 |
+
lq_patch_size = gt_patch_size // scale
|
| 62 |
+
|
| 63 |
+
if h_gt != h_lq * scale or w_gt != w_lq * scale:
|
| 64 |
+
raise ValueError(
|
| 65 |
+
f'Scale mismatches. GT ({h_gt}, {w_gt}) is not {scale}x ',
|
| 66 |
+
f'multiplication of LQ ({h_lq}, {w_lq}).')
|
| 67 |
+
if h_lq < lq_patch_size or w_lq < lq_patch_size:
|
| 68 |
+
raise ValueError(f'LQ ({h_lq}, {w_lq}) is smaller than patch size '
|
| 69 |
+
f'({lq_patch_size}, {lq_patch_size}). '
|
| 70 |
+
f'Please remove {gt_path}.')
|
| 71 |
+
|
| 72 |
+
# randomly choose top and left coordinates for lq patch
|
| 73 |
+
top = random.randint(0, h_lq - lq_patch_size)
|
| 74 |
+
left = random.randint(0, w_lq - lq_patch_size)
|
| 75 |
+
|
| 76 |
+
# crop lq patch
|
| 77 |
+
img_lqs = [
|
| 78 |
+
v[top:top + lq_patch_size, left:left + lq_patch_size, ...]
|
| 79 |
+
for v in img_lqs
|
| 80 |
+
]
|
| 81 |
+
|
| 82 |
+
# crop corresponding gt patch
|
| 83 |
+
top_gt, left_gt = int(top * scale), int(left * scale)
|
| 84 |
+
img_gts = [
|
| 85 |
+
v[top_gt:top_gt + gt_patch_size, left_gt:left_gt + gt_patch_size, ...]
|
| 86 |
+
for v in img_gts
|
| 87 |
+
]
|
| 88 |
+
if len(img_gts) == 1:
|
| 89 |
+
img_gts = img_gts[0]
|
| 90 |
+
if len(img_lqs) == 1:
|
| 91 |
+
img_lqs = img_lqs[0]
|
| 92 |
+
return img_gts, img_lqs
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
def paired_random_crop_hw(img_gts, img_lqs, gt_patch_size_h, gt_patch_size_w, scale, gt_path):
|
| 96 |
+
"""Paired random crop.
|
| 97 |
+
|
| 98 |
+
It crops lists of lq and gt images with corresponding locations.
|
| 99 |
+
|
| 100 |
+
Args:
|
| 101 |
+
img_gts (list[ndarray] | ndarray): GT images. Note that all images
|
| 102 |
+
should have the same shape. If the input is an ndarray, it will
|
| 103 |
+
be transformed to a list containing itself.
|
| 104 |
+
img_lqs (list[ndarray] | ndarray): LQ images. Note that all images
|
| 105 |
+
should have the same shape. If the input is an ndarray, it will
|
| 106 |
+
be transformed to a list containing itself.
|
| 107 |
+
gt_patch_size (int): GT patch size.
|
| 108 |
+
scale (int): Scale factor.
|
| 109 |
+
gt_path (str): Path to ground-truth.
|
| 110 |
+
|
| 111 |
+
Returns:
|
| 112 |
+
list[ndarray] | ndarray: GT images and LQ images. If returned results
|
| 113 |
+
only have one element, just return ndarray.
|
| 114 |
+
"""
|
| 115 |
+
|
| 116 |
+
if not isinstance(img_gts, list):
|
| 117 |
+
img_gts = [img_gts]
|
| 118 |
+
if not isinstance(img_lqs, list):
|
| 119 |
+
img_lqs = [img_lqs]
|
| 120 |
+
|
| 121 |
+
h_lq, w_lq, _ = img_lqs[0].shape
|
| 122 |
+
h_gt, w_gt, _ = img_gts[0].shape
|
| 123 |
+
lq_patch_size_h = gt_patch_size_h // scale
|
| 124 |
+
lq_patch_size_w = gt_patch_size_w // scale
|
| 125 |
+
|
| 126 |
+
# if h_gt != h_lq * scale or w_gt != w_lq * scale:
|
| 127 |
+
# raise ValueError(
|
| 128 |
+
# f'Scale mismatches. GT ({h_gt}, {w_gt}) is not {scale}x ',
|
| 129 |
+
# f'multiplication of LQ ({h_lq}, {w_lq}).')
|
| 130 |
+
# if h_lq < lq_patch_size or w_lq < lq_patch_size:
|
| 131 |
+
# raise ValueError(f'LQ ({h_lq}, {w_lq}) is smaller than patch size '
|
| 132 |
+
# f'({lq_patch_size}, {lq_patch_size}). '
|
| 133 |
+
# f'Please remove {gt_path}.')
|
| 134 |
+
|
| 135 |
+
# randomly choose top and left coordinates for lq patch
|
| 136 |
+
top = random.randint(0, h_lq - lq_patch_size_h)
|
| 137 |
+
left = random.randint(0, w_lq - lq_patch_size_w)
|
| 138 |
+
|
| 139 |
+
# crop lq patch
|
| 140 |
+
img_lqs = [
|
| 141 |
+
v[top:top + lq_patch_size_h, left:left + lq_patch_size_w, ...]
|
| 142 |
+
for v in img_lqs
|
| 143 |
+
]
|
| 144 |
+
|
| 145 |
+
# crop corresponding gt patch
|
| 146 |
+
top_gt, left_gt = int(top * scale), int(left * scale)
|
| 147 |
+
img_gts = [
|
| 148 |
+
v[top_gt:top_gt + gt_patch_size_h, left_gt:left_gt + gt_patch_size_w, ...]
|
| 149 |
+
for v in img_gts
|
| 150 |
+
]
|
| 151 |
+
if len(img_gts) == 1:
|
| 152 |
+
img_gts = img_gts[0]
|
| 153 |
+
if len(img_lqs) == 1:
|
| 154 |
+
img_lqs = img_lqs[0]
|
| 155 |
+
return img_gts, img_lqs
|
| 156 |
+
|
| 157 |
+
def augment(imgs, hflip=True, rotation=True, flows=None, return_status=False, vflip=False):
|
| 158 |
+
"""Augment: horizontal flips OR rotate (0, 90, 180, 270 degrees).
|
| 159 |
+
|
| 160 |
+
We use vertical flip and transpose for rotation implementation.
|
| 161 |
+
All the images in the list use the same augmentation.
|
| 162 |
+
|
| 163 |
+
Args:
|
| 164 |
+
imgs (list[ndarray] | ndarray): Images to be augmented. If the input
|
| 165 |
+
is an ndarray, it will be transformed to a list.
|
| 166 |
+
hflip (bool): Horizontal flip. Default: True.
|
| 167 |
+
rotation (bool): Ratotation. Default: True.
|
| 168 |
+
flows (list[ndarray]: Flows to be augmented. If the input is an
|
| 169 |
+
ndarray, it will be transformed to a list.
|
| 170 |
+
Dimension is (h, w, 2). Default: None.
|
| 171 |
+
return_status (bool): Return the status of flip and rotation.
|
| 172 |
+
Default: False.
|
| 173 |
+
|
| 174 |
+
Returns:
|
| 175 |
+
list[ndarray] | ndarray: Augmented images and flows. If returned
|
| 176 |
+
results only have one element, just return ndarray.
|
| 177 |
+
|
| 178 |
+
"""
|
| 179 |
+
hflip = hflip and random.random() < 0.5
|
| 180 |
+
if vflip or rotation:
|
| 181 |
+
vflip = random.random() < 0.5
|
| 182 |
+
rot90 = rotation and random.random() < 0.5
|
| 183 |
+
|
| 184 |
+
def _augment(img):
|
| 185 |
+
if hflip: # horizontal
|
| 186 |
+
cv2.flip(img, 1, img)
|
| 187 |
+
if img.shape[2] == 6:
|
| 188 |
+
img = img[:,:,[3,4,5,0,1,2]].copy() # swap left/right
|
| 189 |
+
if vflip: # vertical
|
| 190 |
+
cv2.flip(img, 0, img)
|
| 191 |
+
if rot90:
|
| 192 |
+
img = img.transpose(1, 0, 2)
|
| 193 |
+
return img
|
| 194 |
+
|
| 195 |
+
def _augment_flow(flow):
|
| 196 |
+
if hflip: # horizontal
|
| 197 |
+
cv2.flip(flow, 1, flow)
|
| 198 |
+
flow[:, :, 0] *= -1
|
| 199 |
+
if vflip: # vertical
|
| 200 |
+
cv2.flip(flow, 0, flow)
|
| 201 |
+
flow[:, :, 1] *= -1
|
| 202 |
+
if rot90:
|
| 203 |
+
flow = flow.transpose(1, 0, 2)
|
| 204 |
+
flow = flow[:, :, [1, 0]]
|
| 205 |
+
return flow
|
| 206 |
+
|
| 207 |
+
if not isinstance(imgs, list):
|
| 208 |
+
imgs = [imgs]
|
| 209 |
+
imgs = [_augment(img) for img in imgs]
|
| 210 |
+
if len(imgs) == 1:
|
| 211 |
+
imgs = imgs[0]
|
| 212 |
+
|
| 213 |
+
if flows is not None:
|
| 214 |
+
if not isinstance(flows, list):
|
| 215 |
+
flows = [flows]
|
| 216 |
+
flows = [_augment_flow(flow) for flow in flows]
|
| 217 |
+
if len(flows) == 1:
|
| 218 |
+
flows = flows[0]
|
| 219 |
+
return imgs, flows
|
| 220 |
+
else:
|
| 221 |
+
if return_status:
|
| 222 |
+
return imgs, (hflip, vflip, rot90)
|
| 223 |
+
else:
|
| 224 |
+
return imgs
|
| 225 |
+
|
| 226 |
+
|
| 227 |
+
def img_rotate(img, angle, center=None, scale=1.0):
|
| 228 |
+
"""Rotate image.
|
| 229 |
+
|
| 230 |
+
Args:
|
| 231 |
+
img (ndarray): Image to be rotated.
|
| 232 |
+
angle (float): Rotation angle in degrees. Positive values mean
|
| 233 |
+
counter-clockwise rotation.
|
| 234 |
+
center (tuple[int]): Rotation center. If the center is None,
|
| 235 |
+
initialize it as the center of the image. Default: None.
|
| 236 |
+
scale (float): Isotropic scale factor. Default: 1.0.
|
| 237 |
+
"""
|
| 238 |
+
(h, w) = img.shape[:2]
|
| 239 |
+
|
| 240 |
+
if center is None:
|
| 241 |
+
center = (w // 2, h // 2)
|
| 242 |
+
|
| 243 |
+
matrix = cv2.getRotationMatrix2D(center, angle, scale)
|
| 244 |
+
rotated_img = cv2.warpAffine(img, matrix, (w, h))
|
| 245 |
+
return rotated_img
|
| 246 |
+
|
| 247 |
+
|
basicsr/data/video_test_dataset.py
ADDED
|
@@ -0,0 +1,331 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ------------------------------------------------------------------------
|
| 2 |
+
# Copyright (c) 2022 megvii-model. All Rights Reserved.
|
| 3 |
+
# ------------------------------------------------------------------------
|
| 4 |
+
# Modified from BasicSR (https://github.com/xinntao/BasicSR)
|
| 5 |
+
# Copyright 2018-2020 BasicSR Authors
|
| 6 |
+
# ------------------------------------------------------------------------
|
| 7 |
+
import glob
|
| 8 |
+
import torch
|
| 9 |
+
from os import path as osp
|
| 10 |
+
from torch.utils import data as data
|
| 11 |
+
|
| 12 |
+
from basicsr.data.data_util import (duf_downsample, generate_frame_indices,
|
| 13 |
+
read_img_seq)
|
| 14 |
+
from basicsr.utils import get_root_logger, scandir
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
class VideoTestDataset(data.Dataset):
|
| 18 |
+
"""Video test dataset.
|
| 19 |
+
|
| 20 |
+
Supported datasets: Vid4, REDS4, REDSofficial.
|
| 21 |
+
More generally, it supports testing dataset with following structures:
|
| 22 |
+
|
| 23 |
+
dataroot
|
| 24 |
+
├── subfolder1
|
| 25 |
+
├── frame000
|
| 26 |
+
├── frame001
|
| 27 |
+
├── ...
|
| 28 |
+
├── subfolder1
|
| 29 |
+
├── frame000
|
| 30 |
+
├── frame001
|
| 31 |
+
├── ...
|
| 32 |
+
├── ...
|
| 33 |
+
|
| 34 |
+
For testing datasets, there is no need to prepare LMDB files.
|
| 35 |
+
|
| 36 |
+
Args:
|
| 37 |
+
opt (dict): Config for train dataset. It contains the following keys:
|
| 38 |
+
dataroot_gt (str): Data root path for gt.
|
| 39 |
+
dataroot_lq (str): Data root path for lq.
|
| 40 |
+
io_backend (dict): IO backend type and other kwarg.
|
| 41 |
+
cache_data (bool): Whether to cache testing datasets.
|
| 42 |
+
name (str): Dataset name.
|
| 43 |
+
meta_info_file (str): The path to the file storing the list of test
|
| 44 |
+
folders. If not provided, all the folders in the dataroot will
|
| 45 |
+
be used.
|
| 46 |
+
num_frame (int): Window size for input frames.
|
| 47 |
+
padding (str): Padding mode.
|
| 48 |
+
"""
|
| 49 |
+
|
| 50 |
+
def __init__(self, opt):
|
| 51 |
+
super(VideoTestDataset, self).__init__()
|
| 52 |
+
self.opt = opt
|
| 53 |
+
self.cache_data = opt['cache_data']
|
| 54 |
+
self.gt_root, self.lq_root = opt['dataroot_gt'], opt['dataroot_lq']
|
| 55 |
+
self.data_info = {
|
| 56 |
+
'lq_path': [],
|
| 57 |
+
'gt_path': [],
|
| 58 |
+
'folder': [],
|
| 59 |
+
'idx': [],
|
| 60 |
+
'border': []
|
| 61 |
+
}
|
| 62 |
+
# file client (io backend)
|
| 63 |
+
self.file_client = None
|
| 64 |
+
self.io_backend_opt = opt['io_backend']
|
| 65 |
+
assert self.io_backend_opt[
|
| 66 |
+
'type'] != 'lmdb', 'No need to use lmdb during validation/test.'
|
| 67 |
+
|
| 68 |
+
logger = get_root_logger()
|
| 69 |
+
logger.info(f'Generate data info for VideoTestDataset - {opt["name"]}')
|
| 70 |
+
self.imgs_lq, self.imgs_gt = {}, {}
|
| 71 |
+
if 'meta_info_file' in opt:
|
| 72 |
+
with open(opt['meta_info_file'], 'r') as fin:
|
| 73 |
+
subfolders = [line.split(' ')[0] for line in fin]
|
| 74 |
+
subfolders_lq = [
|
| 75 |
+
osp.join(self.lq_root, key) for key in subfolders
|
| 76 |
+
]
|
| 77 |
+
subfolders_gt = [
|
| 78 |
+
osp.join(self.gt_root, key) for key in subfolders
|
| 79 |
+
]
|
| 80 |
+
else:
|
| 81 |
+
subfolders_lq = sorted(glob.glob(osp.join(self.lq_root, '*')))
|
| 82 |
+
subfolders_gt = sorted(glob.glob(osp.join(self.gt_root, '*')))
|
| 83 |
+
|
| 84 |
+
if opt['name'].lower() in ['vid4', 'reds4', 'redsofficial']:
|
| 85 |
+
for subfolder_lq, subfolder_gt in zip(subfolders_lq,
|
| 86 |
+
subfolders_gt):
|
| 87 |
+
# get frame list for lq and gt
|
| 88 |
+
subfolder_name = osp.basename(subfolder_lq)
|
| 89 |
+
img_paths_lq = sorted(
|
| 90 |
+
list(scandir(subfolder_lq, full_path=True)))
|
| 91 |
+
img_paths_gt = sorted(
|
| 92 |
+
list(scandir(subfolder_gt, full_path=True)))
|
| 93 |
+
|
| 94 |
+
max_idx = len(img_paths_lq)
|
| 95 |
+
assert max_idx == len(img_paths_gt), (
|
| 96 |
+
f'Different number of images in lq ({max_idx})'
|
| 97 |
+
f' and gt folders ({len(img_paths_gt)})')
|
| 98 |
+
|
| 99 |
+
self.data_info['lq_path'].extend(img_paths_lq)
|
| 100 |
+
self.data_info['gt_path'].extend(img_paths_gt)
|
| 101 |
+
self.data_info['folder'].extend([subfolder_name] * max_idx)
|
| 102 |
+
for i in range(max_idx):
|
| 103 |
+
self.data_info['idx'].append(f'{i}/{max_idx}')
|
| 104 |
+
border_l = [0] * max_idx
|
| 105 |
+
for i in range(self.opt['num_frame'] // 2):
|
| 106 |
+
border_l[i] = 1
|
| 107 |
+
border_l[max_idx - i - 1] = 1
|
| 108 |
+
self.data_info['border'].extend(border_l)
|
| 109 |
+
|
| 110 |
+
# cache data or save the frame list
|
| 111 |
+
if self.cache_data:
|
| 112 |
+
logger.info(
|
| 113 |
+
f'Cache {subfolder_name} for VideoTestDataset...')
|
| 114 |
+
self.imgs_lq[subfolder_name] = read_img_seq(img_paths_lq)
|
| 115 |
+
self.imgs_gt[subfolder_name] = read_img_seq(img_paths_gt)
|
| 116 |
+
else:
|
| 117 |
+
self.imgs_lq[subfolder_name] = img_paths_lq
|
| 118 |
+
self.imgs_gt[subfolder_name] = img_paths_gt
|
| 119 |
+
else:
|
| 120 |
+
raise ValueError(
|
| 121 |
+
f'Non-supported video test dataset: {type(opt["name"])}')
|
| 122 |
+
|
| 123 |
+
def __getitem__(self, index):
|
| 124 |
+
folder = self.data_info['folder'][index]
|
| 125 |
+
idx, max_idx = self.data_info['idx'][index].split('/')
|
| 126 |
+
idx, max_idx = int(idx), int(max_idx)
|
| 127 |
+
border = self.data_info['border'][index]
|
| 128 |
+
lq_path = self.data_info['lq_path'][index]
|
| 129 |
+
|
| 130 |
+
select_idx = generate_frame_indices(
|
| 131 |
+
idx, max_idx, self.opt['num_frame'], padding=self.opt['padding'])
|
| 132 |
+
|
| 133 |
+
if self.cache_data:
|
| 134 |
+
imgs_lq = self.imgs_lq[folder].index_select(
|
| 135 |
+
0, torch.LongTensor(select_idx))
|
| 136 |
+
img_gt = self.imgs_gt[folder][idx]
|
| 137 |
+
else:
|
| 138 |
+
img_paths_lq = [self.imgs_lq[folder][i] for i in select_idx]
|
| 139 |
+
imgs_lq = read_img_seq(img_paths_lq)
|
| 140 |
+
img_gt = read_img_seq([self.imgs_gt[folder][idx]])
|
| 141 |
+
img_gt.squeeze_(0)
|
| 142 |
+
|
| 143 |
+
return {
|
| 144 |
+
'lq': imgs_lq, # (t, c, h, w)
|
| 145 |
+
'gt': img_gt, # (c, h, w)
|
| 146 |
+
'folder': folder, # folder name
|
| 147 |
+
'idx': self.data_info['idx'][index], # e.g., 0/99
|
| 148 |
+
'border': border, # 1 for border, 0 for non-border
|
| 149 |
+
'lq_path': lq_path # center frame
|
| 150 |
+
}
|
| 151 |
+
|
| 152 |
+
def __len__(self):
|
| 153 |
+
return len(self.data_info['gt_path'])
|
| 154 |
+
|
| 155 |
+
|
| 156 |
+
class VideoTestVimeo90KDataset(data.Dataset):
|
| 157 |
+
"""Video test dataset for Vimeo90k-Test dataset.
|
| 158 |
+
|
| 159 |
+
It only keeps the center frame for testing.
|
| 160 |
+
For testing datasets, there is no need to prepare LMDB files.
|
| 161 |
+
|
| 162 |
+
Args:
|
| 163 |
+
opt (dict): Config for train dataset. It contains the following keys:
|
| 164 |
+
dataroot_gt (str): Data root path for gt.
|
| 165 |
+
dataroot_lq (str): Data root path for lq.
|
| 166 |
+
io_backend (dict): IO backend type and other kwarg.
|
| 167 |
+
cache_data (bool): Whether to cache testing datasets.
|
| 168 |
+
name (str): Dataset name.
|
| 169 |
+
meta_info_file (str): The path to the file storing the list of test
|
| 170 |
+
folders. If not provided, all the folders in the dataroot will
|
| 171 |
+
be used.
|
| 172 |
+
num_frame (int): Window size for input frames.
|
| 173 |
+
padding (str): Padding mode.
|
| 174 |
+
"""
|
| 175 |
+
|
| 176 |
+
def __init__(self, opt):
|
| 177 |
+
super(VideoTestVimeo90KDataset, self).__init__()
|
| 178 |
+
self.opt = opt
|
| 179 |
+
self.cache_data = opt['cache_data']
|
| 180 |
+
if self.cache_data:
|
| 181 |
+
raise NotImplementedError(
|
| 182 |
+
'cache_data in Vimeo90K-Test dataset is not implemented.')
|
| 183 |
+
self.gt_root, self.lq_root = opt['dataroot_gt'], opt['dataroot_lq']
|
| 184 |
+
self.data_info = {
|
| 185 |
+
'lq_path': [],
|
| 186 |
+
'gt_path': [],
|
| 187 |
+
'folder': [],
|
| 188 |
+
'idx': [],
|
| 189 |
+
'border': []
|
| 190 |
+
}
|
| 191 |
+
neighbor_list = [
|
| 192 |
+
i + (9 - opt['num_frame']) // 2 for i in range(opt['num_frame'])
|
| 193 |
+
]
|
| 194 |
+
|
| 195 |
+
# file client (io backend)
|
| 196 |
+
self.file_client = None
|
| 197 |
+
self.io_backend_opt = opt['io_backend']
|
| 198 |
+
assert self.io_backend_opt[
|
| 199 |
+
'type'] != 'lmdb', 'No need to use lmdb during validation/test.'
|
| 200 |
+
|
| 201 |
+
logger = get_root_logger()
|
| 202 |
+
logger.info(f'Generate data info for VideoTestDataset - {opt["name"]}')
|
| 203 |
+
with open(opt['meta_info_file'], 'r') as fin:
|
| 204 |
+
subfolders = [line.split(' ')[0] for line in fin]
|
| 205 |
+
for idx, subfolder in enumerate(subfolders):
|
| 206 |
+
gt_path = osp.join(self.gt_root, subfolder, 'im4.png')
|
| 207 |
+
self.data_info['gt_path'].append(gt_path)
|
| 208 |
+
lq_paths = [
|
| 209 |
+
osp.join(self.lq_root, subfolder, f'im{i}.png')
|
| 210 |
+
for i in neighbor_list
|
| 211 |
+
]
|
| 212 |
+
self.data_info['lq_path'].append(lq_paths)
|
| 213 |
+
self.data_info['folder'].append('vimeo90k')
|
| 214 |
+
self.data_info['idx'].append(f'{idx}/{len(subfolders)}')
|
| 215 |
+
self.data_info['border'].append(0)
|
| 216 |
+
|
| 217 |
+
def __getitem__(self, index):
|
| 218 |
+
lq_path = self.data_info['lq_path'][index]
|
| 219 |
+
gt_path = self.data_info['gt_path'][index]
|
| 220 |
+
imgs_lq = read_img_seq(lq_path)
|
| 221 |
+
img_gt = read_img_seq([gt_path])
|
| 222 |
+
img_gt.squeeze_(0)
|
| 223 |
+
|
| 224 |
+
return {
|
| 225 |
+
'lq': imgs_lq, # (t, c, h, w)
|
| 226 |
+
'gt': img_gt, # (c, h, w)
|
| 227 |
+
'folder': self.data_info['folder'][index], # folder name
|
| 228 |
+
'idx': self.data_info['idx'][index], # e.g., 0/843
|
| 229 |
+
'border': self.data_info['border'][index], # 0 for non-border
|
| 230 |
+
'lq_path': lq_path[self.opt['num_frame'] // 2] # center frame
|
| 231 |
+
}
|
| 232 |
+
|
| 233 |
+
def __len__(self):
|
| 234 |
+
return len(self.data_info['gt_path'])
|
| 235 |
+
|
| 236 |
+
|
| 237 |
+
class VideoTestDUFDataset(VideoTestDataset):
|
| 238 |
+
""" Video test dataset for DUF dataset.
|
| 239 |
+
|
| 240 |
+
Args:
|
| 241 |
+
opt (dict): Config for train dataset.
|
| 242 |
+
Most of keys are the same as VideoTestDataset.
|
| 243 |
+
It has the follwing extra keys:
|
| 244 |
+
|
| 245 |
+
use_duf_downsampling (bool): Whether to use duf downsampling to
|
| 246 |
+
generate low-resolution frames.
|
| 247 |
+
scale (bool): Scale, which will be added automatically.
|
| 248 |
+
"""
|
| 249 |
+
|
| 250 |
+
def __getitem__(self, index):
|
| 251 |
+
folder = self.data_info['folder'][index]
|
| 252 |
+
idx, max_idx = self.data_info['idx'][index].split('/')
|
| 253 |
+
idx, max_idx = int(idx), int(max_idx)
|
| 254 |
+
border = self.data_info['border'][index]
|
| 255 |
+
lq_path = self.data_info['lq_path'][index]
|
| 256 |
+
|
| 257 |
+
select_idx = generate_frame_indices(
|
| 258 |
+
idx, max_idx, self.opt['num_frame'], padding=self.opt['padding'])
|
| 259 |
+
|
| 260 |
+
if self.cache_data:
|
| 261 |
+
if self.opt['use_duf_downsampling']:
|
| 262 |
+
# read imgs_gt to generate low-resolution frames
|
| 263 |
+
imgs_lq = self.imgs_gt[folder].index_select(
|
| 264 |
+
0, torch.LongTensor(select_idx))
|
| 265 |
+
imgs_lq = duf_downsample(
|
| 266 |
+
imgs_lq, kernel_size=13, scale=self.opt['scale'])
|
| 267 |
+
else:
|
| 268 |
+
imgs_lq = self.imgs_lq[folder].index_select(
|
| 269 |
+
0, torch.LongTensor(select_idx))
|
| 270 |
+
img_gt = self.imgs_gt[folder][idx]
|
| 271 |
+
else:
|
| 272 |
+
if self.opt['use_duf_downsampling']:
|
| 273 |
+
img_paths_lq = [self.imgs_gt[folder][i] for i in select_idx]
|
| 274 |
+
# read imgs_gt to generate low-resolution frames
|
| 275 |
+
imgs_lq = read_img_seq(
|
| 276 |
+
img_paths_lq,
|
| 277 |
+
require_mod_crop=True,
|
| 278 |
+
scale=self.opt['scale'])
|
| 279 |
+
imgs_lq = duf_downsample(
|
| 280 |
+
imgs_lq, kernel_size=13, scale=self.opt['scale'])
|
| 281 |
+
else:
|
| 282 |
+
img_paths_lq = [self.imgs_lq[folder][i] for i in select_idx]
|
| 283 |
+
imgs_lq = read_img_seq(img_paths_lq)
|
| 284 |
+
img_gt = read_img_seq([self.imgs_gt[folder][idx]],
|
| 285 |
+
require_mod_crop=True,
|
| 286 |
+
scale=self.opt['scale'])
|
| 287 |
+
img_gt.squeeze_(0)
|
| 288 |
+
|
| 289 |
+
return {
|
| 290 |
+
'lq': imgs_lq, # (t, c, h, w)
|
| 291 |
+
'gt': img_gt, # (c, h, w)
|
| 292 |
+
'folder': folder, # folder name
|
| 293 |
+
'idx': self.data_info['idx'][index], # e.g., 0/99
|
| 294 |
+
'border': border, # 1 for border, 0 for non-border
|
| 295 |
+
'lq_path': lq_path # center frame
|
| 296 |
+
}
|
| 297 |
+
|
| 298 |
+
|
| 299 |
+
class VideoRecurrentTestDataset(VideoTestDataset):
|
| 300 |
+
"""Video test dataset for recurrent architectures, which takes LR video
|
| 301 |
+
frames as input and output corresponding HR video frames.
|
| 302 |
+
|
| 303 |
+
Args:
|
| 304 |
+
Same as VideoTestDataset.
|
| 305 |
+
Unused opt:
|
| 306 |
+
padding (str): Padding mode.
|
| 307 |
+
|
| 308 |
+
"""
|
| 309 |
+
|
| 310 |
+
def __init__(self, opt):
|
| 311 |
+
super(VideoRecurrentTestDataset, self).__init__(opt)
|
| 312 |
+
# Find unique folder strings
|
| 313 |
+
self.folders = sorted(list(set(self.data_info['folder'])))
|
| 314 |
+
|
| 315 |
+
def __getitem__(self, index):
|
| 316 |
+
folder = self.folders[index]
|
| 317 |
+
|
| 318 |
+
if self.cache_data:
|
| 319 |
+
imgs_lq = self.imgs_lq[folder]
|
| 320 |
+
imgs_gt = self.imgs_gt[folder]
|
| 321 |
+
else:
|
| 322 |
+
raise NotImplementedError('Without cache_data is not implemented.')
|
| 323 |
+
|
| 324 |
+
return {
|
| 325 |
+
'lq': imgs_lq,
|
| 326 |
+
'gt': imgs_gt,
|
| 327 |
+
'folder': folder,
|
| 328 |
+
}
|
| 329 |
+
|
| 330 |
+
def __len__(self):
|
| 331 |
+
return len(self.folders)
|
basicsr/data/vimeo90k_dataset.py
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ------------------------------------------------------------------------
|
| 2 |
+
# Copyright (c) 2022 megvii-model. All Rights Reserved.
|
| 3 |
+
# ------------------------------------------------------------------------
|
| 4 |
+
# Modified from BasicSR (https://github.com/xinntao/BasicSR)
|
| 5 |
+
# Copyright 2018-2020 BasicSR Authors
|
| 6 |
+
# ------------------------------------------------------------------------
|
| 7 |
+
import random
|
| 8 |
+
import torch
|
| 9 |
+
from pathlib import Path
|
| 10 |
+
from torch.utils import data as data
|
| 11 |
+
|
| 12 |
+
from basicsr.data.transforms import augment, paired_random_crop
|
| 13 |
+
from basicsr.utils import FileClient, get_root_logger, imfrombytes, img2tensor
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
class Vimeo90KDataset(data.Dataset):
|
| 17 |
+
"""Vimeo90K dataset for training.
|
| 18 |
+
|
| 19 |
+
The keys are generated from a meta info txt file.
|
| 20 |
+
basicsr/data/meta_info/meta_info_Vimeo90K_train_GT.txt
|
| 21 |
+
|
| 22 |
+
Each line contains:
|
| 23 |
+
1. clip name; 2. frame number; 3. image shape, seperated by a white space.
|
| 24 |
+
Examples:
|
| 25 |
+
00001/0001 7 (256,448,3)
|
| 26 |
+
00001/0002 7 (256,448,3)
|
| 27 |
+
|
| 28 |
+
Key examples: "00001/0001"
|
| 29 |
+
GT (gt): Ground-Truth;
|
| 30 |
+
LQ (lq): Low-Quality, e.g., low-resolution/blurry/noisy/compressed frames.
|
| 31 |
+
|
| 32 |
+
The neighboring frame list for different num_frame:
|
| 33 |
+
num_frame | frame list
|
| 34 |
+
1 | 4
|
| 35 |
+
3 | 3,4,5
|
| 36 |
+
5 | 2,3,4,5,6
|
| 37 |
+
7 | 1,2,3,4,5,6,7
|
| 38 |
+
|
| 39 |
+
Args:
|
| 40 |
+
opt (dict): Config for train dataset. It contains the following keys:
|
| 41 |
+
dataroot_gt (str): Data root path for gt.
|
| 42 |
+
dataroot_lq (str): Data root path for lq.
|
| 43 |
+
meta_info_file (str): Path for meta information file.
|
| 44 |
+
io_backend (dict): IO backend type and other kwarg.
|
| 45 |
+
|
| 46 |
+
num_frame (int): Window size for input frames.
|
| 47 |
+
gt_size (int): Cropped patched size for gt patches.
|
| 48 |
+
random_reverse (bool): Random reverse input frames.
|
| 49 |
+
use_flip (bool): Use horizontal flips.
|
| 50 |
+
use_rot (bool): Use rotation (use vertical flip and transposing h
|
| 51 |
+
and w for implementation).
|
| 52 |
+
|
| 53 |
+
scale (bool): Scale, which will be added automatically.
|
| 54 |
+
"""
|
| 55 |
+
|
| 56 |
+
def __init__(self, opt):
|
| 57 |
+
super(Vimeo90KDataset, self).__init__()
|
| 58 |
+
self.opt = opt
|
| 59 |
+
self.gt_root, self.lq_root = Path(opt['dataroot_gt']), Path(
|
| 60 |
+
opt['dataroot_lq'])
|
| 61 |
+
|
| 62 |
+
with open(opt['meta_info_file'], 'r') as fin:
|
| 63 |
+
self.keys = [line.split(' ')[0] for line in fin]
|
| 64 |
+
|
| 65 |
+
# file client (io backend)
|
| 66 |
+
self.file_client = None
|
| 67 |
+
self.io_backend_opt = opt['io_backend']
|
| 68 |
+
self.is_lmdb = False
|
| 69 |
+
if self.io_backend_opt['type'] == 'lmdb':
|
| 70 |
+
self.is_lmdb = True
|
| 71 |
+
self.io_backend_opt['db_paths'] = [self.lq_root, self.gt_root]
|
| 72 |
+
self.io_backend_opt['client_keys'] = ['lq', 'gt']
|
| 73 |
+
|
| 74 |
+
# indices of input images
|
| 75 |
+
self.neighbor_list = [
|
| 76 |
+
i + (9 - opt['num_frame']) // 2 for i in range(opt['num_frame'])
|
| 77 |
+
]
|
| 78 |
+
|
| 79 |
+
# temporal augmentation configs
|
| 80 |
+
self.random_reverse = opt['random_reverse']
|
| 81 |
+
logger = get_root_logger()
|
| 82 |
+
logger.info(f'Random reverse is {self.random_reverse}.')
|
| 83 |
+
|
| 84 |
+
def __getitem__(self, index):
|
| 85 |
+
if self.file_client is None:
|
| 86 |
+
self.file_client = FileClient(
|
| 87 |
+
self.io_backend_opt.pop('type'), **self.io_backend_opt)
|
| 88 |
+
|
| 89 |
+
# random reverse
|
| 90 |
+
if self.random_reverse and random.random() < 0.5:
|
| 91 |
+
self.neighbor_list.reverse()
|
| 92 |
+
|
| 93 |
+
scale = self.opt['scale']
|
| 94 |
+
gt_size = self.opt['gt_size']
|
| 95 |
+
key = self.keys[index]
|
| 96 |
+
clip, seq = key.split('/') # key example: 00001/0001
|
| 97 |
+
|
| 98 |
+
# get the GT frame (im4.png)
|
| 99 |
+
if self.is_lmdb:
|
| 100 |
+
img_gt_path = f'{key}/im4'
|
| 101 |
+
else:
|
| 102 |
+
img_gt_path = self.gt_root / clip / seq / 'im4.png'
|
| 103 |
+
img_bytes = self.file_client.get(img_gt_path, 'gt')
|
| 104 |
+
img_gt = imfrombytes(img_bytes, float32=True)
|
| 105 |
+
|
| 106 |
+
# get the neighboring LQ frames
|
| 107 |
+
img_lqs = []
|
| 108 |
+
for neighbor in self.neighbor_list:
|
| 109 |
+
if self.is_lmdb:
|
| 110 |
+
img_lq_path = f'{clip}/{seq}/im{neighbor}'
|
| 111 |
+
else:
|
| 112 |
+
img_lq_path = self.lq_root / clip / seq / f'im{neighbor}.png'
|
| 113 |
+
img_bytes = self.file_client.get(img_lq_path, 'lq')
|
| 114 |
+
img_lq = imfrombytes(img_bytes, float32=True)
|
| 115 |
+
img_lqs.append(img_lq)
|
| 116 |
+
|
| 117 |
+
# randomly crop
|
| 118 |
+
img_gt, img_lqs = paired_random_crop(img_gt, img_lqs, gt_size, scale,
|
| 119 |
+
img_gt_path)
|
| 120 |
+
|
| 121 |
+
# augmentation - flip, rotate
|
| 122 |
+
img_lqs.append(img_gt)
|
| 123 |
+
img_results = augment(img_lqs, self.opt['use_flip'],
|
| 124 |
+
self.opt['use_rot'])
|
| 125 |
+
|
| 126 |
+
img_results = img2tensor(img_results)
|
| 127 |
+
img_lqs = torch.stack(img_results[0:-1], dim=0)
|
| 128 |
+
img_gt = img_results[-1]
|
| 129 |
+
|
| 130 |
+
# img_lqs: (t, c, h, w)
|
| 131 |
+
# img_gt: (c, h, w)
|
| 132 |
+
# key: str
|
| 133 |
+
return {'lq': img_lqs, 'gt': img_gt, 'key': key}
|
| 134 |
+
|
| 135 |
+
def __len__(self):
|
| 136 |
+
return len(self.keys)
|
basicsr/demo.py
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ------------------------------------------------------------------------
|
| 2 |
+
# Copyright (c) 2022 megvii-model. All Rights Reserved.
|
| 3 |
+
# ------------------------------------------------------------------------
|
| 4 |
+
# Modified from BasicSR (https://github.com/xinntao/BasicSR)
|
| 5 |
+
# Copyright 2018-2020 BasicSR Authors
|
| 6 |
+
# ------------------------------------------------------------------------
|
| 7 |
+
import torch
|
| 8 |
+
|
| 9 |
+
# from basicsr.data import create_dataloader, create_dataset
|
| 10 |
+
from basicsr.models import create_model
|
| 11 |
+
from basicsr.train import parse_options
|
| 12 |
+
from basicsr.utils import FileClient, imfrombytes, img2tensor, padding, tensor2img, imwrite
|
| 13 |
+
|
| 14 |
+
# from basicsr.utils import (get_env_info, get_root_logger, get_time_str,
|
| 15 |
+
# make_exp_dirs)
|
| 16 |
+
# from basicsr.utils.options import dict2str
|
| 17 |
+
|
| 18 |
+
def main():
|
| 19 |
+
# parse options, set distributed setting, set ramdom seed
|
| 20 |
+
opt = parse_options(is_train=False)
|
| 21 |
+
opt['num_gpu'] = torch.cuda.device_count()
|
| 22 |
+
|
| 23 |
+
img_path = opt['img_path'].get('input_img')
|
| 24 |
+
output_path = opt['img_path'].get('output_img')
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
## 1. read image
|
| 28 |
+
file_client = FileClient('disk')
|
| 29 |
+
|
| 30 |
+
img_bytes = file_client.get(img_path, None)
|
| 31 |
+
try:
|
| 32 |
+
img = imfrombytes(img_bytes, float32=True)
|
| 33 |
+
except:
|
| 34 |
+
raise Exception("path {} not working".format(img_path))
|
| 35 |
+
|
| 36 |
+
img = img2tensor(img, bgr2rgb=True, float32=True)
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
## 2. run inference
|
| 41 |
+
opt['dist'] = False
|
| 42 |
+
model = create_model(opt)
|
| 43 |
+
|
| 44 |
+
model.feed_data(data={'lq': img.unsqueeze(dim=0)})
|
| 45 |
+
|
| 46 |
+
if model.opt['val'].get('grids', False):
|
| 47 |
+
model.grids()
|
| 48 |
+
|
| 49 |
+
model.test()
|
| 50 |
+
|
| 51 |
+
if model.opt['val'].get('grids', False):
|
| 52 |
+
model.grids_inverse()
|
| 53 |
+
|
| 54 |
+
visuals = model.get_current_visuals()
|
| 55 |
+
sr_img = tensor2img([visuals['result']])
|
| 56 |
+
imwrite(sr_img, output_path)
|
| 57 |
+
|
| 58 |
+
print(f'inference {img_path} .. finished. saved to {output_path}')
|
| 59 |
+
|
| 60 |
+
if __name__ == '__main__':
|
| 61 |
+
main()
|
| 62 |
+
|
basicsr/demo_ssr.py
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ------------------------------------------------------------------------
|
| 2 |
+
# Copyright (c) 2022 megvii-model. All Rights Reserved.
|
| 3 |
+
# ------------------------------------------------------------------------
|
| 4 |
+
# Modified from BasicSR (https://github.com/xinntao/BasicSR)
|
| 5 |
+
# Copyright 2018-2020 BasicSR Authors
|
| 6 |
+
# ------------------------------------------------------------------------
|
| 7 |
+
import torch
|
| 8 |
+
|
| 9 |
+
# from basicsr.data import create_dataloader, create_dataset
|
| 10 |
+
from basicsr.models import create_model
|
| 11 |
+
from basicsr.utils import FileClient, imfrombytes, img2tensor, padding, tensor2img, imwrite, set_random_seed
|
| 12 |
+
|
| 13 |
+
import argparse
|
| 14 |
+
from basicsr.utils.options import dict2str, parse
|
| 15 |
+
from basicsr.utils.dist_util import get_dist_info, init_dist
|
| 16 |
+
import random
|
| 17 |
+
|
| 18 |
+
def parse_options(is_train=True):
|
| 19 |
+
parser = argparse.ArgumentParser()
|
| 20 |
+
parser.add_argument(
|
| 21 |
+
'-opt', type=str, required=True, help='Path to option YAML file.')
|
| 22 |
+
parser.add_argument(
|
| 23 |
+
'--launcher',
|
| 24 |
+
choices=['none', 'pytorch', 'slurm'],
|
| 25 |
+
default='none',
|
| 26 |
+
help='job launcher')
|
| 27 |
+
parser.add_argument('--local_rank', type=int, default=0)
|
| 28 |
+
|
| 29 |
+
parser.add_argument('--input_l_path', type=str, required=True, help='The path to the input left image. For stereo image inference only.')
|
| 30 |
+
parser.add_argument('--input_r_path', type=str, required=True, help='The path to the input right image. For stereo image inference only.')
|
| 31 |
+
parser.add_argument('--output_l_path', type=str, required=True, help='The path to the output left image. For stereo image inference only.')
|
| 32 |
+
parser.add_argument('--output_r_path', type=str, required=True, help='The path to the output right image. For stereo image inference only.')
|
| 33 |
+
|
| 34 |
+
args = parser.parse_args()
|
| 35 |
+
opt = parse(args.opt, is_train=is_train)
|
| 36 |
+
|
| 37 |
+
# distributed settings
|
| 38 |
+
if args.launcher == 'none':
|
| 39 |
+
opt['dist'] = False
|
| 40 |
+
print('Disable distributed.', flush=True)
|
| 41 |
+
else:
|
| 42 |
+
opt['dist'] = True
|
| 43 |
+
if args.launcher == 'slurm' and 'dist_params' in opt:
|
| 44 |
+
init_dist(args.launcher, **opt['dist_params'])
|
| 45 |
+
else:
|
| 46 |
+
init_dist(args.launcher)
|
| 47 |
+
print('init dist .. ', args.launcher)
|
| 48 |
+
|
| 49 |
+
opt['rank'], opt['world_size'] = get_dist_info()
|
| 50 |
+
|
| 51 |
+
# random seed
|
| 52 |
+
seed = opt.get('manual_seed')
|
| 53 |
+
if seed is None:
|
| 54 |
+
seed = random.randint(1, 10000)
|
| 55 |
+
opt['manual_seed'] = seed
|
| 56 |
+
set_random_seed(seed + opt['rank'])
|
| 57 |
+
|
| 58 |
+
opt['img_path'] = {
|
| 59 |
+
'input_l': args.input_l_path,
|
| 60 |
+
'input_r': args.input_r_path,
|
| 61 |
+
'output_l': args.output_l_path,
|
| 62 |
+
'output_r': args.output_r_path
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
return opt
|
| 66 |
+
|
| 67 |
+
def imread(img_path):
|
| 68 |
+
file_client = FileClient('disk')
|
| 69 |
+
img_bytes = file_client.get(img_path, None)
|
| 70 |
+
try:
|
| 71 |
+
img = imfrombytes(img_bytes, float32=True)
|
| 72 |
+
except:
|
| 73 |
+
raise Exception("path {} not working".format(img_path))
|
| 74 |
+
|
| 75 |
+
img = img2tensor(img, bgr2rgb=True, float32=True)
|
| 76 |
+
return img
|
| 77 |
+
|
| 78 |
+
def main():
|
| 79 |
+
# parse options, set distributed setting, set ramdom seed
|
| 80 |
+
opt = parse_options(is_train=False)
|
| 81 |
+
opt['num_gpu'] = torch.cuda.device_count()
|
| 82 |
+
|
| 83 |
+
img_l_path = opt['img_path'].get('input_l')
|
| 84 |
+
img_r_path = opt['img_path'].get('input_r')
|
| 85 |
+
output_l_path = opt['img_path'].get('output_l')
|
| 86 |
+
output_r_path = opt['img_path'].get('output_r')
|
| 87 |
+
|
| 88 |
+
## 1. read image
|
| 89 |
+
img_l = imread(img_l_path)
|
| 90 |
+
img_r = imread(img_r_path)
|
| 91 |
+
img = torch.cat([img_l, img_r], dim=0)
|
| 92 |
+
|
| 93 |
+
## 2. run inference
|
| 94 |
+
opt['dist'] = False
|
| 95 |
+
model = create_model(opt)
|
| 96 |
+
|
| 97 |
+
model.feed_data(data={'lq': img.unsqueeze(dim=0)})
|
| 98 |
+
|
| 99 |
+
if model.opt['val'].get('grids', False):
|
| 100 |
+
model.grids()
|
| 101 |
+
|
| 102 |
+
model.test()
|
| 103 |
+
|
| 104 |
+
if model.opt['val'].get('grids', False):
|
| 105 |
+
model.grids_inverse()
|
| 106 |
+
|
| 107 |
+
visuals = model.get_current_visuals()
|
| 108 |
+
sr_img_l = visuals['result'][:,:3]
|
| 109 |
+
sr_img_r = visuals['result'][:,3:]
|
| 110 |
+
sr_img_l, sr_img_r = tensor2img([sr_img_l, sr_img_r])
|
| 111 |
+
imwrite(sr_img_l, output_l_path)
|
| 112 |
+
imwrite(sr_img_r, output_r_path)
|
| 113 |
+
|
| 114 |
+
print(f'inference {img_l_path} .. finished. saved to {output_l_path}')
|
| 115 |
+
print(f'inference {img_r_path} .. finished. saved to {output_r_path}')
|
| 116 |
+
|
| 117 |
+
if __name__ == '__main__':
|
| 118 |
+
main()
|
| 119 |
+
|
basicsr/metrics/__init__.py
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ------------------------------------------------------------------------
|
| 2 |
+
# Copyright (c) 2022 megvii-model. All Rights Reserved.
|
| 3 |
+
# ------------------------------------------------------------------------
|
| 4 |
+
# Modified from BasicSR (https://github.com/xinntao/BasicSR)
|
| 5 |
+
# Copyright 2018-2020 BasicSR Authors
|
| 6 |
+
# ------------------------------------------------------------------------
|
| 7 |
+
from .niqe import calculate_niqe
|
| 8 |
+
from .psnr_ssim import calculate_psnr, calculate_ssim, calculate_ssim_left, calculate_psnr_left, calculate_skimage_ssim, calculate_skimage_ssim_left
|
| 9 |
+
|
| 10 |
+
__all__ = ['calculate_psnr', 'calculate_ssim', 'calculate_niqe', 'calculate_ssim_left', 'calculate_psnr_left', 'calculate_skimage_ssim', 'calculate_skimage_ssim_left']
|
basicsr/metrics/fid.py
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ------------------------------------------------------------------------
|
| 2 |
+
# Copyright (c) 2022 megvii-model. All Rights Reserved.
|
| 3 |
+
# ------------------------------------------------------------------------
|
| 4 |
+
# Modified from BasicSR (https://github.com/xinntao/BasicSR)
|
| 5 |
+
# Copyright 2018-2020 BasicSR Authors
|
| 6 |
+
# ------------------------------------------------------------------------
|
| 7 |
+
import numpy as np
|
| 8 |
+
import torch
|
| 9 |
+
import torch.nn as nn
|
| 10 |
+
from scipy import linalg
|
| 11 |
+
from tqdm import tqdm
|
| 12 |
+
|
| 13 |
+
from basicsr.models.archs.inception import InceptionV3
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
def load_patched_inception_v3(device='cuda',
|
| 17 |
+
resize_input=True,
|
| 18 |
+
normalize_input=False):
|
| 19 |
+
# we may not resize the input, but in [rosinality/stylegan2-pytorch] it
|
| 20 |
+
# does resize the input.
|
| 21 |
+
inception = InceptionV3([3],
|
| 22 |
+
resize_input=resize_input,
|
| 23 |
+
normalize_input=normalize_input)
|
| 24 |
+
inception = nn.DataParallel(inception).eval().to(device)
|
| 25 |
+
return inception
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
@torch.no_grad()
|
| 29 |
+
def extract_inception_features(data_generator,
|
| 30 |
+
inception,
|
| 31 |
+
len_generator=None,
|
| 32 |
+
device='cuda'):
|
| 33 |
+
"""Extract inception features.
|
| 34 |
+
|
| 35 |
+
Args:
|
| 36 |
+
data_generator (generator): A data generator.
|
| 37 |
+
inception (nn.Module): Inception model.
|
| 38 |
+
len_generator (int): Length of the data_generator to show the
|
| 39 |
+
progressbar. Default: None.
|
| 40 |
+
device (str): Device. Default: cuda.
|
| 41 |
+
|
| 42 |
+
Returns:
|
| 43 |
+
Tensor: Extracted features.
|
| 44 |
+
"""
|
| 45 |
+
if len_generator is not None:
|
| 46 |
+
pbar = tqdm(total=len_generator, unit='batch', desc='Extract')
|
| 47 |
+
else:
|
| 48 |
+
pbar = None
|
| 49 |
+
features = []
|
| 50 |
+
|
| 51 |
+
for data in data_generator:
|
| 52 |
+
if pbar:
|
| 53 |
+
pbar.update(1)
|
| 54 |
+
data = data.to(device)
|
| 55 |
+
feature = inception(data)[0].view(data.shape[0], -1)
|
| 56 |
+
features.append(feature.to('cpu'))
|
| 57 |
+
if pbar:
|
| 58 |
+
pbar.close()
|
| 59 |
+
features = torch.cat(features, 0)
|
| 60 |
+
return features
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
def calculate_fid(mu1, sigma1, mu2, sigma2, eps=1e-6):
|
| 64 |
+
"""Numpy implementation of the Frechet Distance.
|
| 65 |
+
|
| 66 |
+
The Frechet distance between two multivariate Gaussians X_1 ~ N(mu_1, C_1)
|
| 67 |
+
and X_2 ~ N(mu_2, C_2) is
|
| 68 |
+
d^2 = ||mu_1 - mu_2||^2 + Tr(C_1 + C_2 - 2*sqrt(C_1*C_2)).
|
| 69 |
+
Stable version by Dougal J. Sutherland.
|
| 70 |
+
|
| 71 |
+
Args:
|
| 72 |
+
mu1 (np.array): The sample mean over activations.
|
| 73 |
+
sigma1 (np.array): The covariance matrix over activations for
|
| 74 |
+
generated samples.
|
| 75 |
+
mu2 (np.array): The sample mean over activations, precalculated on an
|
| 76 |
+
representative data set.
|
| 77 |
+
sigma2 (np.array): The covariance matrix over activations,
|
| 78 |
+
precalculated on an representative data set.
|
| 79 |
+
|
| 80 |
+
Returns:
|
| 81 |
+
float: The Frechet Distance.
|
| 82 |
+
"""
|
| 83 |
+
assert mu1.shape == mu2.shape, 'Two mean vectors have different lengths'
|
| 84 |
+
assert sigma1.shape == sigma2.shape, (
|
| 85 |
+
'Two covariances have different dimensions')
|
| 86 |
+
|
| 87 |
+
cov_sqrt, _ = linalg.sqrtm(sigma1 @ sigma2, disp=False)
|
| 88 |
+
|
| 89 |
+
# Product might be almost singular
|
| 90 |
+
if not np.isfinite(cov_sqrt).all():
|
| 91 |
+
print('Product of cov matrices is singular. Adding {eps} to diagonal '
|
| 92 |
+
'of cov estimates')
|
| 93 |
+
offset = np.eye(sigma1.shape[0]) * eps
|
| 94 |
+
cov_sqrt = linalg.sqrtm((sigma1 + offset) @ (sigma2 + offset))
|
| 95 |
+
|
| 96 |
+
# Numerical error might give slight imaginary component
|
| 97 |
+
if np.iscomplexobj(cov_sqrt):
|
| 98 |
+
if not np.allclose(np.diagonal(cov_sqrt).imag, 0, atol=1e-3):
|
| 99 |
+
m = np.max(np.abs(cov_sqrt.imag))
|
| 100 |
+
raise ValueError(f'Imaginary component {m}')
|
| 101 |
+
cov_sqrt = cov_sqrt.real
|
| 102 |
+
|
| 103 |
+
mean_diff = mu1 - mu2
|
| 104 |
+
mean_norm = mean_diff @ mean_diff
|
| 105 |
+
trace = np.trace(sigma1) + np.trace(sigma2) - 2 * np.trace(cov_sqrt)
|
| 106 |
+
fid = mean_norm + trace
|
| 107 |
+
|
| 108 |
+
return fid
|
basicsr/metrics/metric_util.py
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ------------------------------------------------------------------------
|
| 2 |
+
# Copyright (c) 2022 megvii-model. All Rights Reserved.
|
| 3 |
+
# ------------------------------------------------------------------------
|
| 4 |
+
# Modified from BasicSR (https://github.com/xinntao/BasicSR)
|
| 5 |
+
# Copyright 2018-2020 BasicSR Authors
|
| 6 |
+
# ------------------------------------------------------------------------
|
| 7 |
+
import numpy as np
|
| 8 |
+
|
| 9 |
+
from basicsr.utils.matlab_functions import bgr2ycbcr
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
def reorder_image(img, input_order='HWC'):
|
| 13 |
+
"""Reorder images to 'HWC' order.
|
| 14 |
+
|
| 15 |
+
If the input_order is (h, w), return (h, w, 1);
|
| 16 |
+
If the input_order is (c, h, w), return (h, w, c);
|
| 17 |
+
If the input_order is (h, w, c), return as it is.
|
| 18 |
+
|
| 19 |
+
Args:
|
| 20 |
+
img (ndarray): Input image.
|
| 21 |
+
input_order (str): Whether the input order is 'HWC' or 'CHW'.
|
| 22 |
+
If the input image shape is (h, w), input_order will not have
|
| 23 |
+
effects. Default: 'HWC'.
|
| 24 |
+
|
| 25 |
+
Returns:
|
| 26 |
+
ndarray: reordered image.
|
| 27 |
+
"""
|
| 28 |
+
|
| 29 |
+
if input_order not in ['HWC', 'CHW']:
|
| 30 |
+
raise ValueError(
|
| 31 |
+
f'Wrong input_order {input_order}. Supported input_orders are '
|
| 32 |
+
"'HWC' and 'CHW'")
|
| 33 |
+
if len(img.shape) == 2:
|
| 34 |
+
img = img[..., None]
|
| 35 |
+
if input_order == 'CHW':
|
| 36 |
+
img = img.transpose(1, 2, 0)
|
| 37 |
+
return img
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
def to_y_channel(img):
|
| 41 |
+
"""Change to Y channel of YCbCr.
|
| 42 |
+
|
| 43 |
+
Args:
|
| 44 |
+
img (ndarray): Images with range [0, 255].
|
| 45 |
+
|
| 46 |
+
Returns:
|
| 47 |
+
(ndarray): Images with range [0, 255] (float type) without round.
|
| 48 |
+
"""
|
| 49 |
+
img = img.astype(np.float32) / 255.
|
| 50 |
+
if img.ndim == 3 and img.shape[2] == 3:
|
| 51 |
+
img = bgr2ycbcr(img, y_only=True)
|
| 52 |
+
img = img[..., None]
|
| 53 |
+
return img * 255.
|
basicsr/metrics/niqe.py
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ------------------------------------------------------------------------
|
| 2 |
+
# Copyright (c) 2022 megvii-model. All Rights Reserved.
|
| 3 |
+
# ------------------------------------------------------------------------
|
| 4 |
+
# Modified from BasicSR (https://github.com/xinntao/BasicSR)
|
| 5 |
+
# Copyright 2018-2020 BasicSR Authors
|
| 6 |
+
# ------------------------------------------------------------------------
|
| 7 |
+
import cv2
|
| 8 |
+
import math
|
| 9 |
+
import numpy as np
|
| 10 |
+
from scipy.ndimage.filters import convolve
|
| 11 |
+
from scipy.special import gamma
|
| 12 |
+
|
| 13 |
+
from basicsr.metrics.metric_util import reorder_image, to_y_channel
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
def estimate_aggd_param(block):
|
| 17 |
+
"""Estimate AGGD (Asymmetric Generalized Gaussian Distribution) paramters.
|
| 18 |
+
|
| 19 |
+
Args:
|
| 20 |
+
block (ndarray): 2D Image block.
|
| 21 |
+
|
| 22 |
+
Returns:
|
| 23 |
+
tuple: alpha (float), beta_l (float) and beta_r (float) for the AGGD
|
| 24 |
+
distribution (Estimating the parames in Equation 7 in the paper).
|
| 25 |
+
"""
|
| 26 |
+
block = block.flatten()
|
| 27 |
+
gam = np.arange(0.2, 10.001, 0.001) # len = 9801
|
| 28 |
+
gam_reciprocal = np.reciprocal(gam)
|
| 29 |
+
r_gam = np.square(gamma(gam_reciprocal * 2)) / (
|
| 30 |
+
gamma(gam_reciprocal) * gamma(gam_reciprocal * 3))
|
| 31 |
+
|
| 32 |
+
left_std = np.sqrt(np.mean(block[block < 0]**2))
|
| 33 |
+
right_std = np.sqrt(np.mean(block[block > 0]**2))
|
| 34 |
+
gammahat = left_std / right_std
|
| 35 |
+
rhat = (np.mean(np.abs(block)))**2 / np.mean(block**2)
|
| 36 |
+
rhatnorm = (rhat * (gammahat**3 + 1) *
|
| 37 |
+
(gammahat + 1)) / ((gammahat**2 + 1)**2)
|
| 38 |
+
array_position = np.argmin((r_gam - rhatnorm)**2)
|
| 39 |
+
|
| 40 |
+
alpha = gam[array_position]
|
| 41 |
+
beta_l = left_std * np.sqrt(gamma(1 / alpha) / gamma(3 / alpha))
|
| 42 |
+
beta_r = right_std * np.sqrt(gamma(1 / alpha) / gamma(3 / alpha))
|
| 43 |
+
return (alpha, beta_l, beta_r)
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
def compute_feature(block):
|
| 47 |
+
"""Compute features.
|
| 48 |
+
|
| 49 |
+
Args:
|
| 50 |
+
block (ndarray): 2D Image block.
|
| 51 |
+
|
| 52 |
+
Returns:
|
| 53 |
+
list: Features with length of 18.
|
| 54 |
+
"""
|
| 55 |
+
feat = []
|
| 56 |
+
alpha, beta_l, beta_r = estimate_aggd_param(block)
|
| 57 |
+
feat.extend([alpha, (beta_l + beta_r) / 2])
|
| 58 |
+
|
| 59 |
+
# distortions disturb the fairly regular structure of natural images.
|
| 60 |
+
# This deviation can be captured by analyzing the sample distribution of
|
| 61 |
+
# the products of pairs of adjacent coefficients computed along
|
| 62 |
+
# horizontal, vertical and diagonal orientations.
|
| 63 |
+
shifts = [[0, 1], [1, 0], [1, 1], [1, -1]]
|
| 64 |
+
for i in range(len(shifts)):
|
| 65 |
+
shifted_block = np.roll(block, shifts[i], axis=(0, 1))
|
| 66 |
+
alpha, beta_l, beta_r = estimate_aggd_param(block * shifted_block)
|
| 67 |
+
# Eq. 8
|
| 68 |
+
mean = (beta_r - beta_l) * (gamma(2 / alpha) / gamma(1 / alpha))
|
| 69 |
+
feat.extend([alpha, mean, beta_l, beta_r])
|
| 70 |
+
return feat
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
def niqe(img,
|
| 74 |
+
mu_pris_param,
|
| 75 |
+
cov_pris_param,
|
| 76 |
+
gaussian_window,
|
| 77 |
+
block_size_h=96,
|
| 78 |
+
block_size_w=96):
|
| 79 |
+
"""Calculate NIQE (Natural Image Quality Evaluator) metric.
|
| 80 |
+
|
| 81 |
+
Ref: Making a "Completely Blind" Image Quality Analyzer.
|
| 82 |
+
This implementation could produce almost the same results as the official
|
| 83 |
+
MATLAB codes: http://live.ece.utexas.edu/research/quality/niqe_release.zip
|
| 84 |
+
|
| 85 |
+
Note that we do not include block overlap height and width, since they are
|
| 86 |
+
always 0 in the official implementation.
|
| 87 |
+
|
| 88 |
+
For good performance, it is advisable by the official implemtation to
|
| 89 |
+
divide the distorted image in to the same size patched as used for the
|
| 90 |
+
construction of multivariate Gaussian model.
|
| 91 |
+
|
| 92 |
+
Args:
|
| 93 |
+
img (ndarray): Input image whose quality needs to be computed. The
|
| 94 |
+
image must be a gray or Y (of YCbCr) image with shape (h, w).
|
| 95 |
+
Range [0, 255] with float type.
|
| 96 |
+
mu_pris_param (ndarray): Mean of a pre-defined multivariate Gaussian
|
| 97 |
+
model calculated on the pristine dataset.
|
| 98 |
+
cov_pris_param (ndarray): Covariance of a pre-defined multivariate
|
| 99 |
+
Gaussian model calculated on the pristine dataset.
|
| 100 |
+
gaussian_window (ndarray): A 7x7 Gaussian window used for smoothing the
|
| 101 |
+
image.
|
| 102 |
+
block_size_h (int): Height of the blocks in to which image is divided.
|
| 103 |
+
Default: 96 (the official recommended value).
|
| 104 |
+
block_size_w (int): Width of the blocks in to which image is divided.
|
| 105 |
+
Default: 96 (the official recommended value).
|
| 106 |
+
"""
|
| 107 |
+
assert img.ndim == 2, (
|
| 108 |
+
'Input image must be a gray or Y (of YCbCr) image with shape (h, w).')
|
| 109 |
+
# crop image
|
| 110 |
+
h, w = img.shape
|
| 111 |
+
num_block_h = math.floor(h / block_size_h)
|
| 112 |
+
num_block_w = math.floor(w / block_size_w)
|
| 113 |
+
img = img[0:num_block_h * block_size_h, 0:num_block_w * block_size_w]
|
| 114 |
+
|
| 115 |
+
distparam = [] # dist param is actually the multiscale features
|
| 116 |
+
for scale in (1, 2): # perform on two scales (1, 2)
|
| 117 |
+
mu = convolve(img, gaussian_window, mode='nearest')
|
| 118 |
+
sigma = np.sqrt(
|
| 119 |
+
np.abs(
|
| 120 |
+
convolve(np.square(img), gaussian_window, mode='nearest') -
|
| 121 |
+
np.square(mu)))
|
| 122 |
+
# normalize, as in Eq. 1 in the paper
|
| 123 |
+
img_nomalized = (img - mu) / (sigma + 1)
|
| 124 |
+
|
| 125 |
+
feat = []
|
| 126 |
+
for idx_w in range(num_block_w):
|
| 127 |
+
for idx_h in range(num_block_h):
|
| 128 |
+
# process ecah block
|
| 129 |
+
block = img_nomalized[idx_h * block_size_h //
|
| 130 |
+
scale:(idx_h + 1) * block_size_h //
|
| 131 |
+
scale, idx_w * block_size_w //
|
| 132 |
+
scale:(idx_w + 1) * block_size_w //
|
| 133 |
+
scale]
|
| 134 |
+
feat.append(compute_feature(block))
|
| 135 |
+
|
| 136 |
+
distparam.append(np.array(feat))
|
| 137 |
+
# TODO: matlab bicubic downsample with anti-aliasing
|
| 138 |
+
# for simplicity, now we use opencv instead, which will result in
|
| 139 |
+
# a slight difference.
|
| 140 |
+
if scale == 1:
|
| 141 |
+
h, w = img.shape
|
| 142 |
+
img = cv2.resize(
|
| 143 |
+
img / 255., (w // 2, h // 2), interpolation=cv2.INTER_LINEAR)
|
| 144 |
+
img = img * 255.
|
| 145 |
+
|
| 146 |
+
distparam = np.concatenate(distparam, axis=1)
|
| 147 |
+
|
| 148 |
+
# fit a MVG (multivariate Gaussian) model to distorted patch features
|
| 149 |
+
mu_distparam = np.nanmean(distparam, axis=0)
|
| 150 |
+
# use nancov. ref: https://ww2.mathworks.cn/help/stats/nancov.html
|
| 151 |
+
distparam_no_nan = distparam[~np.isnan(distparam).any(axis=1)]
|
| 152 |
+
cov_distparam = np.cov(distparam_no_nan, rowvar=False)
|
| 153 |
+
|
| 154 |
+
# compute niqe quality, Eq. 10 in the paper
|
| 155 |
+
invcov_param = np.linalg.pinv((cov_pris_param + cov_distparam) / 2)
|
| 156 |
+
quality = np.matmul(
|
| 157 |
+
np.matmul((mu_pris_param - mu_distparam), invcov_param),
|
| 158 |
+
np.transpose((mu_pris_param - mu_distparam)))
|
| 159 |
+
quality = np.sqrt(quality)
|
| 160 |
+
|
| 161 |
+
return quality
|
| 162 |
+
|
| 163 |
+
|
| 164 |
+
def calculate_niqe(img, crop_border, input_order='HWC', convert_to='y'):
|
| 165 |
+
"""Calculate NIQE (Natural Image Quality Evaluator) metric.
|
| 166 |
+
|
| 167 |
+
Ref: Making a "Completely Blind" Image Quality Analyzer.
|
| 168 |
+
This implementation could produce almost the same results as the official
|
| 169 |
+
MATLAB codes: http://live.ece.utexas.edu/research/quality/niqe_release.zip
|
| 170 |
+
|
| 171 |
+
We use the official params estimated from the pristine dataset.
|
| 172 |
+
We use the recommended block size (96, 96) without overlaps.
|
| 173 |
+
|
| 174 |
+
Args:
|
| 175 |
+
img (ndarray): Input image whose quality needs to be computed.
|
| 176 |
+
The input image must be in range [0, 255] with float/int type.
|
| 177 |
+
The input_order of image can be 'HW' or 'HWC' or 'CHW'. (BGR order)
|
| 178 |
+
If the input order is 'HWC' or 'CHW', it will be converted to gray
|
| 179 |
+
or Y (of YCbCr) image according to the ``convert_to`` argument.
|
| 180 |
+
crop_border (int): Cropped pixels in each edge of an image. These
|
| 181 |
+
pixels are not involved in the metric calculation.
|
| 182 |
+
input_order (str): Whether the input order is 'HW', 'HWC' or 'CHW'.
|
| 183 |
+
Default: 'HWC'.
|
| 184 |
+
convert_to (str): Whether coverted to 'y' (of MATLAB YCbCr) or 'gray'.
|
| 185 |
+
Default: 'y'.
|
| 186 |
+
|
| 187 |
+
Returns:
|
| 188 |
+
float: NIQE result.
|
| 189 |
+
"""
|
| 190 |
+
|
| 191 |
+
# we use the official params estimated from the pristine dataset.
|
| 192 |
+
niqe_pris_params = np.load('basicsr/metrics/niqe_pris_params.npz')
|
| 193 |
+
mu_pris_param = niqe_pris_params['mu_pris_param']
|
| 194 |
+
cov_pris_param = niqe_pris_params['cov_pris_param']
|
| 195 |
+
gaussian_window = niqe_pris_params['gaussian_window']
|
| 196 |
+
|
| 197 |
+
img = img.astype(np.float32)
|
| 198 |
+
if input_order != 'HW':
|
| 199 |
+
img = reorder_image(img, input_order=input_order)
|
| 200 |
+
if convert_to == 'y':
|
| 201 |
+
img = to_y_channel(img)
|
| 202 |
+
elif convert_to == 'gray':
|
| 203 |
+
img = cv2.cvtColor(img / 255., cv2.COLOR_BGR2GRAY) * 255.
|
| 204 |
+
img = np.squeeze(img)
|
| 205 |
+
|
| 206 |
+
if crop_border != 0:
|
| 207 |
+
img = img[crop_border:-crop_border, crop_border:-crop_border]
|
| 208 |
+
|
| 209 |
+
niqe_result = niqe(img, mu_pris_param, cov_pris_param, gaussian_window)
|
| 210 |
+
|
| 211 |
+
return niqe_result
|
basicsr/metrics/niqe_pris_params.npz
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:2a7c182a68c9e7f1b2e2e5ec723279d6f65d912b6fcaf37eb2bf03d7367c4296
|
| 3 |
+
size 11850
|
basicsr/metrics/psnr_ssim.py
ADDED
|
@@ -0,0 +1,358 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ------------------------------------------------------------------------
|
| 2 |
+
# Copyright (c) 2022 megvii-model. All Rights Reserved.
|
| 3 |
+
# ------------------------------------------------------------------------
|
| 4 |
+
# modified from https://github.com/mayorx/matlab_ssim_pytorch_implementation/blob/main/calc_ssim.py
|
| 5 |
+
# ------------------------------------------------------------------------
|
| 6 |
+
# Modified from BasicSR (https://github.com/xinntao/BasicSR)
|
| 7 |
+
# Copyright 2018-2020 BasicSR Authors
|
| 8 |
+
# ------------------------------------------------------------------------
|
| 9 |
+
import cv2
|
| 10 |
+
import numpy as np
|
| 11 |
+
|
| 12 |
+
from basicsr.metrics.metric_util import reorder_image, to_y_channel
|
| 13 |
+
from skimage.metrics import structural_similarity
|
| 14 |
+
import torch
|
| 15 |
+
|
| 16 |
+
def calculate_psnr(img1,
|
| 17 |
+
img2,
|
| 18 |
+
crop_border,
|
| 19 |
+
input_order='HWC',
|
| 20 |
+
test_y_channel=False):
|
| 21 |
+
"""Calculate PSNR (Peak Signal-to-Noise Ratio).
|
| 22 |
+
|
| 23 |
+
Ref: https://en.wikipedia.org/wiki/Peak_signal-to-noise_ratio
|
| 24 |
+
|
| 25 |
+
Args:
|
| 26 |
+
img1 (ndarray/tensor): Images with range [0, 255]/[0, 1].
|
| 27 |
+
img2 (ndarray/tensor): Images with range [0, 255]/[0, 1].
|
| 28 |
+
crop_border (int): Cropped pixels in each edge of an image. These
|
| 29 |
+
pixels are not involved in the PSNR calculation.
|
| 30 |
+
input_order (str): Whether the input order is 'HWC' or 'CHW'.
|
| 31 |
+
Default: 'HWC'.
|
| 32 |
+
test_y_channel (bool): Test on Y channel of YCbCr. Default: False.
|
| 33 |
+
|
| 34 |
+
Returns:
|
| 35 |
+
float: psnr result.
|
| 36 |
+
"""
|
| 37 |
+
|
| 38 |
+
assert img1.shape == img2.shape, (
|
| 39 |
+
f'Image shapes are differnet: {img1.shape}, {img2.shape}.')
|
| 40 |
+
if input_order not in ['HWC', 'CHW']:
|
| 41 |
+
raise ValueError(
|
| 42 |
+
f'Wrong input_order {input_order}. Supported input_orders are '
|
| 43 |
+
'"HWC" and "CHW"')
|
| 44 |
+
if type(img1) == torch.Tensor:
|
| 45 |
+
if len(img1.shape) == 4:
|
| 46 |
+
img1 = img1.squeeze(0)
|
| 47 |
+
img1 = img1.detach().cpu().numpy().transpose(1,2,0)
|
| 48 |
+
if type(img2) == torch.Tensor:
|
| 49 |
+
if len(img2.shape) == 4:
|
| 50 |
+
img2 = img2.squeeze(0)
|
| 51 |
+
img2 = img2.detach().cpu().numpy().transpose(1,2,0)
|
| 52 |
+
|
| 53 |
+
img1 = reorder_image(img1, input_order=input_order)
|
| 54 |
+
img2 = reorder_image(img2, input_order=input_order)
|
| 55 |
+
img1 = img1.astype(np.float64)
|
| 56 |
+
img2 = img2.astype(np.float64)
|
| 57 |
+
|
| 58 |
+
if crop_border != 0:
|
| 59 |
+
img1 = img1[crop_border:-crop_border, crop_border:-crop_border, ...]
|
| 60 |
+
img2 = img2[crop_border:-crop_border, crop_border:-crop_border, ...]
|
| 61 |
+
|
| 62 |
+
def _psnr(img1, img2):
|
| 63 |
+
if test_y_channel:
|
| 64 |
+
img1 = to_y_channel(img1)
|
| 65 |
+
img2 = to_y_channel(img2)
|
| 66 |
+
|
| 67 |
+
mse = np.mean((img1 - img2)**2)
|
| 68 |
+
if mse == 0:
|
| 69 |
+
return float('inf')
|
| 70 |
+
max_value = 1. if img1.max() <= 1 else 255.
|
| 71 |
+
return 20. * np.log10(max_value / np.sqrt(mse))
|
| 72 |
+
|
| 73 |
+
if img1.ndim == 3 and img1.shape[2] == 6:
|
| 74 |
+
l1, r1 = img1[:,:,:3], img1[:,:,3:]
|
| 75 |
+
l2, r2 = img2[:,:,:3], img2[:,:,3:]
|
| 76 |
+
return (_psnr(l1, l2) + _psnr(r1, r2))/2
|
| 77 |
+
else:
|
| 78 |
+
return _psnr(img1, img2)
|
| 79 |
+
|
| 80 |
+
def calculate_psnr_left(img1,
|
| 81 |
+
img2,
|
| 82 |
+
crop_border,
|
| 83 |
+
input_order='HWC',
|
| 84 |
+
test_y_channel=False):
|
| 85 |
+
assert input_order == 'HWC'
|
| 86 |
+
assert crop_border == 0
|
| 87 |
+
|
| 88 |
+
img1 = img1[:,64:,:3]
|
| 89 |
+
img2 = img2[:,64:,:3]
|
| 90 |
+
return calculate_psnr(img1=img1, img2=img2, crop_border=0, input_order=input_order, test_y_channel=test_y_channel)
|
| 91 |
+
|
| 92 |
+
def _ssim(img1, img2, max_value):
|
| 93 |
+
"""Calculate SSIM (structural similarity) for one channel images.
|
| 94 |
+
|
| 95 |
+
It is called by func:`calculate_ssim`.
|
| 96 |
+
|
| 97 |
+
Args:
|
| 98 |
+
img1 (ndarray): Images with range [0, 255] with order 'HWC'.
|
| 99 |
+
img2 (ndarray): Images with range [0, 255] with order 'HWC'.
|
| 100 |
+
|
| 101 |
+
Returns:
|
| 102 |
+
float: ssim result.
|
| 103 |
+
"""
|
| 104 |
+
|
| 105 |
+
C1 = (0.01 * max_value)**2
|
| 106 |
+
C2 = (0.03 * max_value)**2
|
| 107 |
+
|
| 108 |
+
img1 = img1.astype(np.float64)
|
| 109 |
+
img2 = img2.astype(np.float64)
|
| 110 |
+
kernel = cv2.getGaussianKernel(11, 1.5)
|
| 111 |
+
window = np.outer(kernel, kernel.transpose())
|
| 112 |
+
|
| 113 |
+
mu1 = cv2.filter2D(img1, -1, window)[5:-5, 5:-5]
|
| 114 |
+
mu2 = cv2.filter2D(img2, -1, window)[5:-5, 5:-5]
|
| 115 |
+
mu1_sq = mu1**2
|
| 116 |
+
mu2_sq = mu2**2
|
| 117 |
+
mu1_mu2 = mu1 * mu2
|
| 118 |
+
sigma1_sq = cv2.filter2D(img1**2, -1, window)[5:-5, 5:-5] - mu1_sq
|
| 119 |
+
sigma2_sq = cv2.filter2D(img2**2, -1, window)[5:-5, 5:-5] - mu2_sq
|
| 120 |
+
sigma12 = cv2.filter2D(img1 * img2, -1, window)[5:-5, 5:-5] - mu1_mu2
|
| 121 |
+
|
| 122 |
+
ssim_map = ((2 * mu1_mu2 + C1) *
|
| 123 |
+
(2 * sigma12 + C2)) / ((mu1_sq + mu2_sq + C1) *
|
| 124 |
+
(sigma1_sq + sigma2_sq + C2))
|
| 125 |
+
return ssim_map.mean()
|
| 126 |
+
|
| 127 |
+
def prepare_for_ssim(img, k):
|
| 128 |
+
import torch
|
| 129 |
+
with torch.no_grad():
|
| 130 |
+
img = torch.from_numpy(img).unsqueeze(0).unsqueeze(0).float()
|
| 131 |
+
conv = torch.nn.Conv2d(1, 1, k, stride=1, padding=k//2, padding_mode='reflect')
|
| 132 |
+
conv.weight.requires_grad = False
|
| 133 |
+
conv.weight[:, :, :, :] = 1. / (k * k)
|
| 134 |
+
|
| 135 |
+
img = conv(img)
|
| 136 |
+
|
| 137 |
+
img = img.squeeze(0).squeeze(0)
|
| 138 |
+
img = img[0::k, 0::k]
|
| 139 |
+
return img.detach().cpu().numpy()
|
| 140 |
+
|
| 141 |
+
def prepare_for_ssim_rgb(img, k):
|
| 142 |
+
import torch
|
| 143 |
+
with torch.no_grad():
|
| 144 |
+
img = torch.from_numpy(img).float() #HxWx3
|
| 145 |
+
|
| 146 |
+
conv = torch.nn.Conv2d(1, 1, k, stride=1, padding=k // 2, padding_mode='reflect')
|
| 147 |
+
conv.weight.requires_grad = False
|
| 148 |
+
conv.weight[:, :, :, :] = 1. / (k * k)
|
| 149 |
+
|
| 150 |
+
new_img = []
|
| 151 |
+
|
| 152 |
+
for i in range(3):
|
| 153 |
+
new_img.append(conv(img[:, :, i].unsqueeze(0).unsqueeze(0)).squeeze(0).squeeze(0)[0::k, 0::k])
|
| 154 |
+
|
| 155 |
+
return torch.stack(new_img, dim=2).detach().cpu().numpy()
|
| 156 |
+
|
| 157 |
+
def _3d_gaussian_calculator(img, conv3d):
|
| 158 |
+
out = conv3d(img.unsqueeze(0).unsqueeze(0)).squeeze(0).squeeze(0)
|
| 159 |
+
return out
|
| 160 |
+
|
| 161 |
+
def _generate_3d_gaussian_kernel():
|
| 162 |
+
kernel = cv2.getGaussianKernel(11, 1.5)
|
| 163 |
+
window = np.outer(kernel, kernel.transpose())
|
| 164 |
+
kernel_3 = cv2.getGaussianKernel(11, 1.5)
|
| 165 |
+
kernel = torch.tensor(np.stack([window * k for k in kernel_3], axis=0))
|
| 166 |
+
conv3d = torch.nn.Conv3d(1, 1, (11, 11, 11), stride=1, padding=(5, 5, 5), bias=False, padding_mode='replicate')
|
| 167 |
+
conv3d.weight.requires_grad = False
|
| 168 |
+
conv3d.weight[0, 0, :, :, :] = kernel
|
| 169 |
+
return conv3d
|
| 170 |
+
|
| 171 |
+
def _ssim_3d(img1, img2, max_value):
|
| 172 |
+
assert len(img1.shape) == 3 and len(img2.shape) == 3
|
| 173 |
+
"""Calculate SSIM (structural similarity) for one channel images.
|
| 174 |
+
|
| 175 |
+
It is called by func:`calculate_ssim`.
|
| 176 |
+
|
| 177 |
+
Args:
|
| 178 |
+
img1 (ndarray): Images with range [0, 255]/[0, 1] with order 'HWC'.
|
| 179 |
+
img2 (ndarray): Images with range [0, 255]/[0, 1] with order 'HWC'.
|
| 180 |
+
|
| 181 |
+
Returns:
|
| 182 |
+
float: ssim result.
|
| 183 |
+
"""
|
| 184 |
+
C1 = (0.01 * max_value) ** 2
|
| 185 |
+
C2 = (0.03 * max_value) ** 2
|
| 186 |
+
img1 = img1.astype(np.float64)
|
| 187 |
+
img2 = img2.astype(np.float64)
|
| 188 |
+
|
| 189 |
+
kernel = _generate_3d_gaussian_kernel().cuda()
|
| 190 |
+
|
| 191 |
+
img1 = torch.tensor(img1).float().cuda()
|
| 192 |
+
img2 = torch.tensor(img2).float().cuda()
|
| 193 |
+
|
| 194 |
+
|
| 195 |
+
mu1 = _3d_gaussian_calculator(img1, kernel)
|
| 196 |
+
mu2 = _3d_gaussian_calculator(img2, kernel)
|
| 197 |
+
|
| 198 |
+
mu1_sq = mu1 ** 2
|
| 199 |
+
mu2_sq = mu2 ** 2
|
| 200 |
+
mu1_mu2 = mu1 * mu2
|
| 201 |
+
sigma1_sq = _3d_gaussian_calculator(img1 ** 2, kernel) - mu1_sq
|
| 202 |
+
sigma2_sq = _3d_gaussian_calculator(img2 ** 2, kernel) - mu2_sq
|
| 203 |
+
sigma12 = _3d_gaussian_calculator(img1*img2, kernel) - mu1_mu2
|
| 204 |
+
|
| 205 |
+
ssim_map = ((2 * mu1_mu2 + C1) *
|
| 206 |
+
(2 * sigma12 + C2)) / ((mu1_sq + mu2_sq + C1) *
|
| 207 |
+
(sigma1_sq + sigma2_sq + C2))
|
| 208 |
+
return float(ssim_map.mean())
|
| 209 |
+
|
| 210 |
+
def _ssim_cly(img1, img2):
|
| 211 |
+
assert len(img1.shape) == 2 and len(img2.shape) == 2
|
| 212 |
+
"""Calculate SSIM (structural similarity) for one channel images.
|
| 213 |
+
|
| 214 |
+
It is called by func:`calculate_ssim`.
|
| 215 |
+
|
| 216 |
+
Args:
|
| 217 |
+
img1 (ndarray): Images with range [0, 255] with order 'HWC'.
|
| 218 |
+
img2 (ndarray): Images with range [0, 255] with order 'HWC'.
|
| 219 |
+
|
| 220 |
+
Returns:
|
| 221 |
+
float: ssim result.
|
| 222 |
+
"""
|
| 223 |
+
|
| 224 |
+
C1 = (0.01 * 255)**2
|
| 225 |
+
C2 = (0.03 * 255)**2
|
| 226 |
+
img1 = img1.astype(np.float64)
|
| 227 |
+
img2 = img2.astype(np.float64)
|
| 228 |
+
|
| 229 |
+
kernel = cv2.getGaussianKernel(11, 1.5)
|
| 230 |
+
# print(kernel)
|
| 231 |
+
window = np.outer(kernel, kernel.transpose())
|
| 232 |
+
|
| 233 |
+
bt = cv2.BORDER_REPLICATE
|
| 234 |
+
|
| 235 |
+
mu1 = cv2.filter2D(img1, -1, window, borderType=bt)
|
| 236 |
+
mu2 = cv2.filter2D(img2, -1, window,borderType=bt)
|
| 237 |
+
|
| 238 |
+
mu1_sq = mu1**2
|
| 239 |
+
mu2_sq = mu2**2
|
| 240 |
+
mu1_mu2 = mu1 * mu2
|
| 241 |
+
sigma1_sq = cv2.filter2D(img1**2, -1, window, borderType=bt) - mu1_sq
|
| 242 |
+
sigma2_sq = cv2.filter2D(img2**2, -1, window, borderType=bt) - mu2_sq
|
| 243 |
+
sigma12 = cv2.filter2D(img1 * img2, -1, window, borderType=bt) - mu1_mu2
|
| 244 |
+
|
| 245 |
+
ssim_map = ((2 * mu1_mu2 + C1) *
|
| 246 |
+
(2 * sigma12 + C2)) / ((mu1_sq + mu2_sq + C1) *
|
| 247 |
+
(sigma1_sq + sigma2_sq + C2))
|
| 248 |
+
return ssim_map.mean()
|
| 249 |
+
|
| 250 |
+
|
| 251 |
+
def calculate_ssim(img1,
|
| 252 |
+
img2,
|
| 253 |
+
crop_border,
|
| 254 |
+
input_order='HWC',
|
| 255 |
+
test_y_channel=False,
|
| 256 |
+
ssim3d=True):
|
| 257 |
+
"""Calculate SSIM (structural similarity).
|
| 258 |
+
|
| 259 |
+
Ref:
|
| 260 |
+
Image quality assessment: From error visibility to structural similarity
|
| 261 |
+
|
| 262 |
+
The results are the same as that of the official released MATLAB code in
|
| 263 |
+
https://ece.uwaterloo.ca/~z70wang/research/ssim/.
|
| 264 |
+
|
| 265 |
+
For three-channel images, SSIM is calculated for each channel and then
|
| 266 |
+
averaged.
|
| 267 |
+
|
| 268 |
+
Args:
|
| 269 |
+
img1 (ndarray): Images with range [0, 255].
|
| 270 |
+
img2 (ndarray): Images with range [0, 255].
|
| 271 |
+
crop_border (int): Cropped pixels in each edge of an image. These
|
| 272 |
+
pixels are not involved in the SSIM calculation.
|
| 273 |
+
input_order (str): Whether the input order is 'HWC' or 'CHW'.
|
| 274 |
+
Default: 'HWC'.
|
| 275 |
+
test_y_channel (bool): Test on Y channel of YCbCr. Default: False.
|
| 276 |
+
|
| 277 |
+
Returns:
|
| 278 |
+
float: ssim result.
|
| 279 |
+
"""
|
| 280 |
+
|
| 281 |
+
assert img1.shape == img2.shape, (
|
| 282 |
+
f'Image shapes are differnet: {img1.shape}, {img2.shape}.')
|
| 283 |
+
if input_order not in ['HWC', 'CHW']:
|
| 284 |
+
raise ValueError(
|
| 285 |
+
f'Wrong input_order {input_order}. Supported input_orders are '
|
| 286 |
+
'"HWC" and "CHW"')
|
| 287 |
+
|
| 288 |
+
if type(img1) == torch.Tensor:
|
| 289 |
+
if len(img1.shape) == 4:
|
| 290 |
+
img1 = img1.squeeze(0)
|
| 291 |
+
img1 = img1.detach().cpu().numpy().transpose(1,2,0)
|
| 292 |
+
if type(img2) == torch.Tensor:
|
| 293 |
+
if len(img2.shape) == 4:
|
| 294 |
+
img2 = img2.squeeze(0)
|
| 295 |
+
img2 = img2.detach().cpu().numpy().transpose(1,2,0)
|
| 296 |
+
|
| 297 |
+
img1 = reorder_image(img1, input_order=input_order)
|
| 298 |
+
img2 = reorder_image(img2, input_order=input_order)
|
| 299 |
+
|
| 300 |
+
img1 = img1.astype(np.float64)
|
| 301 |
+
img2 = img2.astype(np.float64)
|
| 302 |
+
|
| 303 |
+
if crop_border != 0:
|
| 304 |
+
img1 = img1[crop_border:-crop_border, crop_border:-crop_border, ...]
|
| 305 |
+
img2 = img2[crop_border:-crop_border, crop_border:-crop_border, ...]
|
| 306 |
+
|
| 307 |
+
def _cal_ssim(img1, img2):
|
| 308 |
+
if test_y_channel:
|
| 309 |
+
img1 = to_y_channel(img1)
|
| 310 |
+
img2 = to_y_channel(img2)
|
| 311 |
+
return _ssim_cly(img1[..., 0], img2[..., 0])
|
| 312 |
+
|
| 313 |
+
ssims = []
|
| 314 |
+
# ssims_before = []
|
| 315 |
+
|
| 316 |
+
# skimage_before = skimage.metrics.structural_similarity(img1, img2, data_range=255., multichannel=True)
|
| 317 |
+
# print('.._skimage',
|
| 318 |
+
# skimage.metrics.structural_similarity(img1, img2, data_range=255., multichannel=True))
|
| 319 |
+
max_value = 1 if img1.max() <= 1 else 255
|
| 320 |
+
with torch.no_grad():
|
| 321 |
+
final_ssim = _ssim_3d(img1, img2, max_value) if ssim3d else _ssim(img1, img2, max_value)
|
| 322 |
+
ssims.append(final_ssim)
|
| 323 |
+
|
| 324 |
+
# for i in range(img1.shape[2]):
|
| 325 |
+
# ssims_before.append(_ssim(img1, img2))
|
| 326 |
+
|
| 327 |
+
# print('..ssim mean , new {:.4f} and before {:.4f} .... skimage before {:.4f}'.format(np.array(ssims).mean(), np.array(ssims_before).mean(), skimage_before))
|
| 328 |
+
# ssims.append(skimage.metrics.structural_similarity(img1[..., i], img2[..., i], multichannel=False))
|
| 329 |
+
|
| 330 |
+
return np.array(ssims).mean()
|
| 331 |
+
|
| 332 |
+
if img1.ndim == 3 and img1.shape[2] == 6:
|
| 333 |
+
l1, r1 = img1[:,:,:3], img1[:,:,3:]
|
| 334 |
+
l2, r2 = img2[:,:,:3], img2[:,:,3:]
|
| 335 |
+
return (_cal_ssim(l1, l2) + _cal_ssim(r1, r2))/2
|
| 336 |
+
else:
|
| 337 |
+
return _cal_ssim(img1, img2)
|
| 338 |
+
|
| 339 |
+
def calculate_ssim_left(img1,
|
| 340 |
+
img2,
|
| 341 |
+
crop_border,
|
| 342 |
+
input_order='HWC',
|
| 343 |
+
test_y_channel=False,
|
| 344 |
+
ssim3d=True):
|
| 345 |
+
assert input_order == 'HWC'
|
| 346 |
+
assert crop_border == 0
|
| 347 |
+
|
| 348 |
+
img1 = img1[:,64:,:3]
|
| 349 |
+
img2 = img2[:,64:,:3]
|
| 350 |
+
return calculate_ssim(img1=img1, img2=img2, crop_border=0, input_order=input_order, test_y_channel=test_y_channel, ssim3d=ssim3d)
|
| 351 |
+
|
| 352 |
+
def calculate_skimage_ssim(img1, img2):
|
| 353 |
+
return structural_similarity(img1, img2, multichannel=True)
|
| 354 |
+
|
| 355 |
+
def calculate_skimage_ssim_left(img1, img2):
|
| 356 |
+
img1 = img1[:,64:,:3]
|
| 357 |
+
img2 = img2[:,64:,:3]
|
| 358 |
+
return calculate_skimage_ssim(img1=img1, img2=img2)
|
basicsr/models/__init__.py
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ------------------------------------------------------------------------
|
| 2 |
+
# Copyright (c) 2022 megvii-model. All Rights Reserved.
|
| 3 |
+
# ------------------------------------------------------------------------
|
| 4 |
+
# Modified from BasicSR (https://github.com/xinntao/BasicSR)
|
| 5 |
+
# Copyright 2018-2020 BasicSR Authors
|
| 6 |
+
# ------------------------------------------------------------------------
|
| 7 |
+
import importlib
|
| 8 |
+
from os import path as osp
|
| 9 |
+
|
| 10 |
+
from basicsr.utils import get_root_logger, scandir
|
| 11 |
+
|
| 12 |
+
# automatically scan and import model modules
|
| 13 |
+
# scan all the files under the 'models' folder and collect files ending with
|
| 14 |
+
# '_model.py'
|
| 15 |
+
model_folder = osp.dirname(osp.abspath(__file__))
|
| 16 |
+
model_filenames = [
|
| 17 |
+
osp.splitext(osp.basename(v))[0] for v in scandir(model_folder)
|
| 18 |
+
if v.endswith('_model.py')
|
| 19 |
+
]
|
| 20 |
+
# import all the model modules
|
| 21 |
+
_model_modules = [
|
| 22 |
+
importlib.import_module(f'basicsr.models.{file_name}')
|
| 23 |
+
for file_name in model_filenames
|
| 24 |
+
]
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
def create_model(opt):
|
| 28 |
+
"""Create model.
|
| 29 |
+
|
| 30 |
+
Args:
|
| 31 |
+
opt (dict): Configuration. It constains:
|
| 32 |
+
model_type (str): Model type.
|
| 33 |
+
"""
|
| 34 |
+
model_type = opt['model_type']
|
| 35 |
+
|
| 36 |
+
# dynamic instantiation
|
| 37 |
+
for module in _model_modules:
|
| 38 |
+
model_cls = getattr(module, model_type, None)
|
| 39 |
+
if model_cls is not None:
|
| 40 |
+
break
|
| 41 |
+
if model_cls is None:
|
| 42 |
+
raise ValueError(f'Model {model_type} is not found.')
|
| 43 |
+
|
| 44 |
+
model = model_cls(opt)
|
| 45 |
+
|
| 46 |
+
logger = get_root_logger()
|
| 47 |
+
logger.info(f'Model [{model.__class__.__name__}] is created.')
|
| 48 |
+
return model
|
basicsr/models/archs/Baseline_arch.py
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ------------------------------------------------------------------------
|
| 2 |
+
# Copyright (c) 2022 megvii-model. All Rights Reserved.
|
| 3 |
+
# ------------------------------------------------------------------------
|
| 4 |
+
|
| 5 |
+
'''
|
| 6 |
+
Simple Baselines for Image Restoration
|
| 7 |
+
|
| 8 |
+
@article{chen2022simple,
|
| 9 |
+
title={Simple Baselines for Image Restoration},
|
| 10 |
+
author={Chen, Liangyu and Chu, Xiaojie and Zhang, Xiangyu and Sun, Jian},
|
| 11 |
+
journal={arXiv preprint arXiv:2204.04676},
|
| 12 |
+
year={2022}
|
| 13 |
+
}
|
| 14 |
+
'''
|
| 15 |
+
|
| 16 |
+
import torch
|
| 17 |
+
import torch.nn as nn
|
| 18 |
+
import torch.nn.functional as F
|
| 19 |
+
from basicsr.models.archs.arch_util import LayerNorm2d
|
| 20 |
+
from basicsr.models.archs.local_arch import Local_Base
|
| 21 |
+
|
| 22 |
+
class BaselineBlock(nn.Module):
|
| 23 |
+
def __init__(self, c, DW_Expand=1, FFN_Expand=2, drop_out_rate=0.):
|
| 24 |
+
super().__init__()
|
| 25 |
+
dw_channel = c * DW_Expand
|
| 26 |
+
self.conv1 = nn.Conv2d(in_channels=c, out_channels=dw_channel, kernel_size=1, padding=0, stride=1, groups=1, bias=True)
|
| 27 |
+
self.conv2 = nn.Conv2d(in_channels=dw_channel, out_channels=dw_channel, kernel_size=3, padding=1, stride=1, groups=dw_channel,
|
| 28 |
+
bias=True)
|
| 29 |
+
self.conv3 = nn.Conv2d(in_channels=dw_channel, out_channels=c, kernel_size=1, padding=0, stride=1, groups=1, bias=True)
|
| 30 |
+
|
| 31 |
+
# Channel Attention
|
| 32 |
+
self.se = nn.Sequential(
|
| 33 |
+
nn.AdaptiveAvgPool2d(1),
|
| 34 |
+
nn.Conv2d(in_channels=dw_channel, out_channels=dw_channel // 2, kernel_size=1, padding=0, stride=1,
|
| 35 |
+
groups=1, bias=True),
|
| 36 |
+
nn.ReLU(inplace=True),
|
| 37 |
+
nn.Conv2d(in_channels=dw_channel // 2, out_channels=dw_channel, kernel_size=1, padding=0, stride=1,
|
| 38 |
+
groups=1, bias=True),
|
| 39 |
+
nn.Sigmoid()
|
| 40 |
+
)
|
| 41 |
+
|
| 42 |
+
# GELU
|
| 43 |
+
self.gelu = nn.GELU()
|
| 44 |
+
|
| 45 |
+
ffn_channel = FFN_Expand * c
|
| 46 |
+
self.conv4 = nn.Conv2d(in_channels=c, out_channels=ffn_channel, kernel_size=1, padding=0, stride=1, groups=1, bias=True)
|
| 47 |
+
self.conv5 = nn.Conv2d(in_channels=ffn_channel, out_channels=c, kernel_size=1, padding=0, stride=1, groups=1, bias=True)
|
| 48 |
+
|
| 49 |
+
self.norm1 = LayerNorm2d(c)
|
| 50 |
+
self.norm2 = LayerNorm2d(c)
|
| 51 |
+
|
| 52 |
+
self.dropout1 = nn.Dropout(drop_out_rate) if drop_out_rate > 0. else nn.Identity()
|
| 53 |
+
self.dropout2 = nn.Dropout(drop_out_rate) if drop_out_rate > 0. else nn.Identity()
|
| 54 |
+
|
| 55 |
+
self.beta = nn.Parameter(torch.zeros((1, c, 1, 1)), requires_grad=True)
|
| 56 |
+
self.gamma = nn.Parameter(torch.zeros((1, c, 1, 1)), requires_grad=True)
|
| 57 |
+
|
| 58 |
+
def forward(self, inp):
|
| 59 |
+
x = inp
|
| 60 |
+
|
| 61 |
+
x = self.norm1(x)
|
| 62 |
+
|
| 63 |
+
x = self.conv1(x)
|
| 64 |
+
x = self.conv2(x)
|
| 65 |
+
x = self.gelu(x)
|
| 66 |
+
x = x * self.se(x)
|
| 67 |
+
x = self.conv3(x)
|
| 68 |
+
|
| 69 |
+
x = self.dropout1(x)
|
| 70 |
+
|
| 71 |
+
y = inp + x * self.beta
|
| 72 |
+
|
| 73 |
+
x = self.conv4(self.norm2(y))
|
| 74 |
+
x = self.gelu(x)
|
| 75 |
+
x = self.conv5(x)
|
| 76 |
+
|
| 77 |
+
x = self.dropout2(x)
|
| 78 |
+
|
| 79 |
+
return y + x * self.gamma
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
class Baseline(nn.Module):
|
| 83 |
+
|
| 84 |
+
def __init__(self, img_channel=3, width=16, middle_blk_num=1, enc_blk_nums=[], dec_blk_nums=[], dw_expand=1, ffn_expand=2):
|
| 85 |
+
super().__init__()
|
| 86 |
+
|
| 87 |
+
self.intro = nn.Conv2d(in_channels=img_channel, out_channels=width, kernel_size=3, padding=1, stride=1, groups=1,
|
| 88 |
+
bias=True)
|
| 89 |
+
self.ending = nn.Conv2d(in_channels=width, out_channels=img_channel, kernel_size=3, padding=1, stride=1, groups=1,
|
| 90 |
+
bias=True)
|
| 91 |
+
|
| 92 |
+
self.encoders = nn.ModuleList()
|
| 93 |
+
self.decoders = nn.ModuleList()
|
| 94 |
+
self.middle_blks = nn.ModuleList()
|
| 95 |
+
self.ups = nn.ModuleList()
|
| 96 |
+
self.downs = nn.ModuleList()
|
| 97 |
+
|
| 98 |
+
chan = width
|
| 99 |
+
for num in enc_blk_nums:
|
| 100 |
+
self.encoders.append(
|
| 101 |
+
nn.Sequential(
|
| 102 |
+
*[BaselineBlock(chan, dw_expand, ffn_expand) for _ in range(num)]
|
| 103 |
+
)
|
| 104 |
+
)
|
| 105 |
+
self.downs.append(
|
| 106 |
+
nn.Conv2d(chan, 2*chan, 2, 2)
|
| 107 |
+
)
|
| 108 |
+
chan = chan * 2
|
| 109 |
+
|
| 110 |
+
self.middle_blks = \
|
| 111 |
+
nn.Sequential(
|
| 112 |
+
*[BaselineBlock(chan, dw_expand, ffn_expand) for _ in range(middle_blk_num)]
|
| 113 |
+
)
|
| 114 |
+
|
| 115 |
+
for num in dec_blk_nums:
|
| 116 |
+
self.ups.append(
|
| 117 |
+
nn.Sequential(
|
| 118 |
+
nn.Conv2d(chan, chan * 2, 1, bias=False),
|
| 119 |
+
nn.PixelShuffle(2)
|
| 120 |
+
)
|
| 121 |
+
)
|
| 122 |
+
chan = chan // 2
|
| 123 |
+
self.decoders.append(
|
| 124 |
+
nn.Sequential(
|
| 125 |
+
*[BaselineBlock(chan, dw_expand, ffn_expand) for _ in range(num)]
|
| 126 |
+
)
|
| 127 |
+
)
|
| 128 |
+
|
| 129 |
+
self.padder_size = 2 ** len(self.encoders)
|
| 130 |
+
|
| 131 |
+
def forward(self, inp):
|
| 132 |
+
B, C, H, W = inp.shape
|
| 133 |
+
inp = self.check_image_size(inp)
|
| 134 |
+
|
| 135 |
+
x = self.intro(inp)
|
| 136 |
+
|
| 137 |
+
encs = []
|
| 138 |
+
|
| 139 |
+
for encoder, down in zip(self.encoders, self.downs):
|
| 140 |
+
x = encoder(x)
|
| 141 |
+
encs.append(x)
|
| 142 |
+
x = down(x)
|
| 143 |
+
|
| 144 |
+
x = self.middle_blks(x)
|
| 145 |
+
|
| 146 |
+
for decoder, up, enc_skip in zip(self.decoders, self.ups, encs[::-1]):
|
| 147 |
+
x = up(x)
|
| 148 |
+
x = x + enc_skip
|
| 149 |
+
x = decoder(x)
|
| 150 |
+
|
| 151 |
+
x = self.ending(x)
|
| 152 |
+
x = x + inp
|
| 153 |
+
|
| 154 |
+
return x[:, :, :H, :W]
|
| 155 |
+
|
| 156 |
+
def check_image_size(self, x):
|
| 157 |
+
_, _, h, w = x.size()
|
| 158 |
+
mod_pad_h = (self.padder_size - h % self.padder_size) % self.padder_size
|
| 159 |
+
mod_pad_w = (self.padder_size - w % self.padder_size) % self.padder_size
|
| 160 |
+
x = F.pad(x, (0, mod_pad_w, 0, mod_pad_h))
|
| 161 |
+
return x
|
| 162 |
+
|
| 163 |
+
class BaselineLocal(Local_Base, Baseline):
|
| 164 |
+
def __init__(self, *args, train_size=(1, 3, 256, 256), fast_imp=False, **kwargs):
|
| 165 |
+
Local_Base.__init__(self)
|
| 166 |
+
Baseline.__init__(self, *args, **kwargs)
|
| 167 |
+
|
| 168 |
+
N, C, H, W = train_size
|
| 169 |
+
base_size = (int(H * 1.5), int(W * 1.5))
|
| 170 |
+
|
| 171 |
+
self.eval()
|
| 172 |
+
with torch.no_grad():
|
| 173 |
+
self.convert(base_size=base_size, train_size=train_size, fast_imp=fast_imp)
|
| 174 |
+
|
| 175 |
+
if __name__ == '__main__':
|
| 176 |
+
img_channel = 3
|
| 177 |
+
width = 32
|
| 178 |
+
|
| 179 |
+
dw_expand = 1
|
| 180 |
+
ffn_expand = 2
|
| 181 |
+
|
| 182 |
+
# enc_blks = [2, 2, 4, 8]
|
| 183 |
+
# middle_blk_num = 12
|
| 184 |
+
# dec_blks = [2, 2, 2, 2]
|
| 185 |
+
|
| 186 |
+
enc_blks = [1, 1, 1, 28]
|
| 187 |
+
middle_blk_num = 1
|
| 188 |
+
dec_blks = [1, 1, 1, 1]
|
| 189 |
+
|
| 190 |
+
net = Baseline(img_channel=img_channel, width=width, middle_blk_num=middle_blk_num,
|
| 191 |
+
enc_blk_nums=enc_blks, dec_blk_nums=dec_blks, dw_expand=dw_expand, ffn_expand=ffn_expand)
|
| 192 |
+
|
| 193 |
+
inp_shape = (3, 256, 256)
|
| 194 |
+
|
| 195 |
+
from ptflops import get_model_complexity_info
|
| 196 |
+
|
| 197 |
+
macs, params = get_model_complexity_info(net, inp_shape, verbose=False, print_per_layer_stat=False)
|
| 198 |
+
|
| 199 |
+
params = float(params[:-3])
|
| 200 |
+
macs = float(macs[:-4])
|
| 201 |
+
|
| 202 |
+
print(macs, params)
|
basicsr/models/archs/NAFNet_arch.py
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ------------------------------------------------------------------------
|
| 2 |
+
# Copyright (c) 2022 megvii-model. All Rights Reserved.
|
| 3 |
+
# ------------------------------------------------------------------------
|
| 4 |
+
|
| 5 |
+
'''
|
| 6 |
+
Simple Baselines for Image Restoration
|
| 7 |
+
|
| 8 |
+
@article{chen2022simple,
|
| 9 |
+
title={Simple Baselines for Image Restoration},
|
| 10 |
+
author={Chen, Liangyu and Chu, Xiaojie and Zhang, Xiangyu and Sun, Jian},
|
| 11 |
+
journal={arXiv preprint arXiv:2204.04676},
|
| 12 |
+
year={2022}
|
| 13 |
+
}
|
| 14 |
+
'''
|
| 15 |
+
|
| 16 |
+
import torch
|
| 17 |
+
import torch.nn as nn
|
| 18 |
+
import torch.nn.functional as F
|
| 19 |
+
from basicsr.models.archs.arch_util import LayerNorm2d
|
| 20 |
+
from basicsr.models.archs.local_arch import Local_Base
|
| 21 |
+
|
| 22 |
+
class SimpleGate(nn.Module):
|
| 23 |
+
def forward(self, x):
|
| 24 |
+
x1, x2 = x.chunk(2, dim=1)
|
| 25 |
+
return x1 * x2
|
| 26 |
+
|
| 27 |
+
class NAFBlock(nn.Module):
|
| 28 |
+
def __init__(self, c, DW_Expand=2, FFN_Expand=2, drop_out_rate=0.):
|
| 29 |
+
super().__init__()
|
| 30 |
+
dw_channel = c * DW_Expand
|
| 31 |
+
self.conv1 = nn.Conv2d(in_channels=c, out_channels=dw_channel, kernel_size=1, padding=0, stride=1, groups=1, bias=True)
|
| 32 |
+
self.conv2 = nn.Conv2d(in_channels=dw_channel, out_channels=dw_channel, kernel_size=3, padding=1, stride=1, groups=dw_channel,
|
| 33 |
+
bias=True)
|
| 34 |
+
self.conv3 = nn.Conv2d(in_channels=dw_channel // 2, out_channels=c, kernel_size=1, padding=0, stride=1, groups=1, bias=True)
|
| 35 |
+
|
| 36 |
+
# Simplified Channel Attention
|
| 37 |
+
self.sca = nn.Sequential(
|
| 38 |
+
nn.AdaptiveAvgPool2d(1),
|
| 39 |
+
nn.Conv2d(in_channels=dw_channel // 2, out_channels=dw_channel // 2, kernel_size=1, padding=0, stride=1,
|
| 40 |
+
groups=1, bias=True),
|
| 41 |
+
)
|
| 42 |
+
|
| 43 |
+
# SimpleGate
|
| 44 |
+
self.sg = SimpleGate()
|
| 45 |
+
|
| 46 |
+
ffn_channel = FFN_Expand * c
|
| 47 |
+
self.conv4 = nn.Conv2d(in_channels=c, out_channels=ffn_channel, kernel_size=1, padding=0, stride=1, groups=1, bias=True)
|
| 48 |
+
self.conv5 = nn.Conv2d(in_channels=ffn_channel // 2, out_channels=c, kernel_size=1, padding=0, stride=1, groups=1, bias=True)
|
| 49 |
+
|
| 50 |
+
self.norm1 = LayerNorm2d(c)
|
| 51 |
+
self.norm2 = LayerNorm2d(c)
|
| 52 |
+
|
| 53 |
+
self.dropout1 = nn.Dropout(drop_out_rate) if drop_out_rate > 0. else nn.Identity()
|
| 54 |
+
self.dropout2 = nn.Dropout(drop_out_rate) if drop_out_rate > 0. else nn.Identity()
|
| 55 |
+
|
| 56 |
+
self.beta = nn.Parameter(torch.zeros((1, c, 1, 1)), requires_grad=True)
|
| 57 |
+
self.gamma = nn.Parameter(torch.zeros((1, c, 1, 1)), requires_grad=True)
|
| 58 |
+
|
| 59 |
+
def forward(self, inp):
|
| 60 |
+
x = inp
|
| 61 |
+
|
| 62 |
+
x = self.norm1(x)
|
| 63 |
+
|
| 64 |
+
x = self.conv1(x)
|
| 65 |
+
x = self.conv2(x)
|
| 66 |
+
x = self.sg(x)
|
| 67 |
+
x = x * self.sca(x)
|
| 68 |
+
x = self.conv3(x)
|
| 69 |
+
|
| 70 |
+
x = self.dropout1(x)
|
| 71 |
+
|
| 72 |
+
y = inp + x * self.beta
|
| 73 |
+
|
| 74 |
+
x = self.conv4(self.norm2(y))
|
| 75 |
+
x = self.sg(x)
|
| 76 |
+
x = self.conv5(x)
|
| 77 |
+
|
| 78 |
+
x = self.dropout2(x)
|
| 79 |
+
|
| 80 |
+
return y + x * self.gamma
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
class NAFNet(nn.Module):
|
| 84 |
+
|
| 85 |
+
def __init__(self, img_channel=3, width=32, middle_blk_num=1, enc_blk_nums=[1,1,1,28], dec_blk_nums=[1,1,1,1]):
|
| 86 |
+
super().__init__()
|
| 87 |
+
|
| 88 |
+
self.intro = nn.Conv2d(in_channels=img_channel, out_channels=width, kernel_size=3, padding=1, stride=1, groups=1,
|
| 89 |
+
bias=True)
|
| 90 |
+
self.ending = nn.Conv2d(in_channels=width, out_channels=img_channel, kernel_size=3, padding=1, stride=1, groups=1,
|
| 91 |
+
bias=True)
|
| 92 |
+
|
| 93 |
+
self.encoders = nn.ModuleList()
|
| 94 |
+
self.decoders = nn.ModuleList()
|
| 95 |
+
self.middle_blks = nn.ModuleList()
|
| 96 |
+
self.ups = nn.ModuleList()
|
| 97 |
+
self.downs = nn.ModuleList()
|
| 98 |
+
|
| 99 |
+
chan = width
|
| 100 |
+
for num in enc_blk_nums:
|
| 101 |
+
self.encoders.append(
|
| 102 |
+
nn.Sequential(
|
| 103 |
+
*[NAFBlock(chan) for _ in range(num)]
|
| 104 |
+
)
|
| 105 |
+
)
|
| 106 |
+
self.downs.append(
|
| 107 |
+
nn.Conv2d(chan, 2*chan, 2, 2)
|
| 108 |
+
)
|
| 109 |
+
chan = chan * 2
|
| 110 |
+
|
| 111 |
+
self.middle_blks = \
|
| 112 |
+
nn.Sequential(
|
| 113 |
+
*[NAFBlock(chan) for _ in range(middle_blk_num)]
|
| 114 |
+
)
|
| 115 |
+
|
| 116 |
+
for num in dec_blk_nums:
|
| 117 |
+
self.ups.append(
|
| 118 |
+
nn.Sequential(
|
| 119 |
+
nn.Conv2d(chan, chan * 2, 1, bias=False),
|
| 120 |
+
nn.PixelShuffle(2)
|
| 121 |
+
)
|
| 122 |
+
)
|
| 123 |
+
chan = chan // 2
|
| 124 |
+
self.decoders.append(
|
| 125 |
+
nn.Sequential(
|
| 126 |
+
*[NAFBlock(chan) for _ in range(num)]
|
| 127 |
+
)
|
| 128 |
+
)
|
| 129 |
+
|
| 130 |
+
self.padder_size = 2 ** len(self.encoders)
|
| 131 |
+
|
| 132 |
+
def forward(self, inp):
|
| 133 |
+
B, C, H, W = inp.shape
|
| 134 |
+
inp = self.check_image_size(inp)
|
| 135 |
+
|
| 136 |
+
x = self.intro(inp)
|
| 137 |
+
|
| 138 |
+
encs = []
|
| 139 |
+
|
| 140 |
+
for encoder, down in zip(self.encoders, self.downs):
|
| 141 |
+
x = encoder(x)
|
| 142 |
+
encs.append(x)
|
| 143 |
+
x = down(x)
|
| 144 |
+
|
| 145 |
+
x = self.middle_blks(x)
|
| 146 |
+
|
| 147 |
+
for decoder, up, enc_skip in zip(self.decoders, self.ups, encs[::-1]):
|
| 148 |
+
x = up(x)
|
| 149 |
+
x = x + enc_skip
|
| 150 |
+
x = decoder(x)
|
| 151 |
+
|
| 152 |
+
x = self.ending(x)
|
| 153 |
+
x = x + inp
|
| 154 |
+
|
| 155 |
+
return x[:, :, :H, :W]
|
| 156 |
+
|
| 157 |
+
def check_image_size(self, x):
|
| 158 |
+
_, _, h, w = x.size()
|
| 159 |
+
mod_pad_h = (self.padder_size - h % self.padder_size) % self.padder_size
|
| 160 |
+
mod_pad_w = (self.padder_size - w % self.padder_size) % self.padder_size
|
| 161 |
+
x = F.pad(x, (0, mod_pad_w, 0, mod_pad_h))
|
| 162 |
+
return x
|
| 163 |
+
|
| 164 |
+
class NAFNetLocal(Local_Base, NAFNet):
|
| 165 |
+
def __init__(self, *args, train_size=(1, 3, 256, 256), fast_imp=False, **kwargs):
|
| 166 |
+
Local_Base.__init__(self)
|
| 167 |
+
NAFNet.__init__(self, *args, **kwargs)
|
| 168 |
+
|
| 169 |
+
N, C, H, W = train_size
|
| 170 |
+
base_size = (int(H * 1.5), int(W * 1.5))
|
| 171 |
+
|
| 172 |
+
self.eval()
|
| 173 |
+
with torch.no_grad():
|
| 174 |
+
self.convert(base_size=base_size, train_size=train_size, fast_imp=fast_imp)
|
| 175 |
+
|
| 176 |
+
|
basicsr/models/archs/NAFSSR_arch.py
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ------------------------------------------------------------------------
|
| 2 |
+
# Copyright (c) 2022 megvii-model. All Rights Reserved.
|
| 3 |
+
# ------------------------------------------------------------------------
|
| 4 |
+
|
| 5 |
+
'''
|
| 6 |
+
NAFSSR: Stereo Image Super-Resolution Using NAFNet
|
| 7 |
+
|
| 8 |
+
@InProceedings{Chu2022NAFSSR,
|
| 9 |
+
author = {Xiaojie Chu and Liangyu Chen and Wenqing Yu},
|
| 10 |
+
title = {NAFSSR: Stereo Image Super-Resolution Using NAFNet},
|
| 11 |
+
booktitle = {CVPRW},
|
| 12 |
+
year = {2022},
|
| 13 |
+
}
|
| 14 |
+
'''
|
| 15 |
+
|
| 16 |
+
import numpy as np
|
| 17 |
+
import torch
|
| 18 |
+
import torch.nn as nn
|
| 19 |
+
import torch.nn.functional as F
|
| 20 |
+
|
| 21 |
+
from basicsr.models.archs.NAFNet_arch import LayerNorm2d, NAFBlock
|
| 22 |
+
from basicsr.models.archs.arch_util import MySequential
|
| 23 |
+
from basicsr.models.archs.local_arch import Local_Base
|
| 24 |
+
|
| 25 |
+
class SCAM(nn.Module):
|
| 26 |
+
'''
|
| 27 |
+
Stereo Cross Attention Module (SCAM)
|
| 28 |
+
'''
|
| 29 |
+
def __init__(self, c):
|
| 30 |
+
super().__init__()
|
| 31 |
+
self.scale = c ** -0.5
|
| 32 |
+
|
| 33 |
+
self.norm_l = LayerNorm2d(c)
|
| 34 |
+
self.norm_r = LayerNorm2d(c)
|
| 35 |
+
self.l_proj1 = nn.Conv2d(c, c, kernel_size=1, stride=1, padding=0)
|
| 36 |
+
self.r_proj1 = nn.Conv2d(c, c, kernel_size=1, stride=1, padding=0)
|
| 37 |
+
|
| 38 |
+
self.beta = nn.Parameter(torch.zeros((1, c, 1, 1)), requires_grad=True)
|
| 39 |
+
self.gamma = nn.Parameter(torch.zeros((1, c, 1, 1)), requires_grad=True)
|
| 40 |
+
|
| 41 |
+
self.l_proj2 = nn.Conv2d(c, c, kernel_size=1, stride=1, padding=0)
|
| 42 |
+
self.r_proj2 = nn.Conv2d(c, c, kernel_size=1, stride=1, padding=0)
|
| 43 |
+
|
| 44 |
+
def forward(self, x_l, x_r):
|
| 45 |
+
Q_l = self.l_proj1(self.norm_l(x_l)).permute(0, 2, 3, 1) # B, H, W, c
|
| 46 |
+
Q_r_T = self.r_proj1(self.norm_r(x_r)).permute(0, 2, 1, 3) # B, H, c, W (transposed)
|
| 47 |
+
|
| 48 |
+
V_l = self.l_proj2(x_l).permute(0, 2, 3, 1) # B, H, W, c
|
| 49 |
+
V_r = self.r_proj2(x_r).permute(0, 2, 3, 1) # B, H, W, c
|
| 50 |
+
|
| 51 |
+
# (B, H, W, c) x (B, H, c, W) -> (B, H, W, W)
|
| 52 |
+
attention = torch.matmul(Q_l, Q_r_T) * self.scale
|
| 53 |
+
|
| 54 |
+
F_r2l = torch.matmul(torch.softmax(attention, dim=-1), V_r) #B, H, W, c
|
| 55 |
+
F_l2r = torch.matmul(torch.softmax(attention.permute(0, 1, 3, 2), dim=-1), V_l) #B, H, W, c
|
| 56 |
+
|
| 57 |
+
# scale
|
| 58 |
+
F_r2l = F_r2l.permute(0, 3, 1, 2) * self.beta
|
| 59 |
+
F_l2r = F_l2r.permute(0, 3, 1, 2) * self.gamma
|
| 60 |
+
return x_l + F_r2l, x_r + F_l2r
|
| 61 |
+
|
| 62 |
+
class DropPath(nn.Module):
|
| 63 |
+
def __init__(self, drop_rate, module):
|
| 64 |
+
super().__init__()
|
| 65 |
+
self.drop_rate = drop_rate
|
| 66 |
+
self.module = module
|
| 67 |
+
|
| 68 |
+
def forward(self, *feats):
|
| 69 |
+
if self.training and np.random.rand() < self.drop_rate:
|
| 70 |
+
return feats
|
| 71 |
+
|
| 72 |
+
new_feats = self.module(*feats)
|
| 73 |
+
factor = 1. / (1 - self.drop_rate) if self.training else 1.
|
| 74 |
+
|
| 75 |
+
if self.training and factor != 1.:
|
| 76 |
+
new_feats = tuple([x+factor*(new_x-x) for x, new_x in zip(feats, new_feats)])
|
| 77 |
+
return new_feats
|
| 78 |
+
|
| 79 |
+
class NAFBlockSR(nn.Module):
|
| 80 |
+
'''
|
| 81 |
+
NAFBlock for Super-Resolution
|
| 82 |
+
'''
|
| 83 |
+
def __init__(self, c, fusion=False, drop_out_rate=0.):
|
| 84 |
+
super().__init__()
|
| 85 |
+
self.blk = NAFBlock(c, drop_out_rate=drop_out_rate)
|
| 86 |
+
self.fusion = SCAM(c) if fusion else None
|
| 87 |
+
|
| 88 |
+
def forward(self, *feats):
|
| 89 |
+
feats = tuple([self.blk(x) for x in feats])
|
| 90 |
+
if self.fusion:
|
| 91 |
+
feats = self.fusion(*feats)
|
| 92 |
+
return feats
|
| 93 |
+
|
| 94 |
+
class NAFNetSR(nn.Module):
|
| 95 |
+
'''
|
| 96 |
+
NAFNet for Super-Resolution
|
| 97 |
+
'''
|
| 98 |
+
def __init__(self, up_scale=4, width=48, num_blks=16, img_channel=3, drop_path_rate=0., drop_out_rate=0., fusion_from=-1, fusion_to=-1, dual=False):
|
| 99 |
+
super().__init__()
|
| 100 |
+
self.dual = dual # dual input for stereo SR (left view, right view)
|
| 101 |
+
self.intro = nn.Conv2d(in_channels=img_channel, out_channels=width, kernel_size=3, padding=1, stride=1, groups=1,
|
| 102 |
+
bias=True)
|
| 103 |
+
self.body = MySequential(
|
| 104 |
+
*[DropPath(
|
| 105 |
+
drop_path_rate,
|
| 106 |
+
NAFBlockSR(
|
| 107 |
+
width,
|
| 108 |
+
fusion=(fusion_from <= i and i <= fusion_to),
|
| 109 |
+
drop_out_rate=drop_out_rate
|
| 110 |
+
)) for i in range(num_blks)]
|
| 111 |
+
)
|
| 112 |
+
|
| 113 |
+
self.up = nn.Sequential(
|
| 114 |
+
nn.Conv2d(in_channels=width, out_channels=img_channel * up_scale**2, kernel_size=3, padding=1, stride=1, groups=1, bias=True),
|
| 115 |
+
nn.PixelShuffle(up_scale)
|
| 116 |
+
)
|
| 117 |
+
self.up_scale = up_scale
|
| 118 |
+
|
| 119 |
+
def forward(self, inp):
|
| 120 |
+
inp_hr = F.interpolate(inp, scale_factor=self.up_scale, mode='bilinear')
|
| 121 |
+
if self.dual:
|
| 122 |
+
inp = inp.chunk(2, dim=1)
|
| 123 |
+
else:
|
| 124 |
+
inp = (inp, )
|
| 125 |
+
feats = [self.intro(x) for x in inp]
|
| 126 |
+
feats = self.body(*feats)
|
| 127 |
+
out = torch.cat([self.up(x) for x in feats], dim=1)
|
| 128 |
+
out = out + inp_hr
|
| 129 |
+
return out
|
| 130 |
+
|
| 131 |
+
class NAFSSR(Local_Base, NAFNetSR):
|
| 132 |
+
def __init__(self, *args, train_size=(1, 6, 30, 90), fast_imp=False, fusion_from=-1, fusion_to=1000, **kwargs):
|
| 133 |
+
Local_Base.__init__(self)
|
| 134 |
+
NAFNetSR.__init__(self, *args, img_channel=3, fusion_from=fusion_from, fusion_to=fusion_to, dual=True, **kwargs)
|
| 135 |
+
|
| 136 |
+
N, C, H, W = train_size
|
| 137 |
+
base_size = (int(H * 1.5), int(W * 1.5))
|
| 138 |
+
|
| 139 |
+
self.eval()
|
| 140 |
+
with torch.no_grad():
|
| 141 |
+
self.convert(base_size=base_size, train_size=train_size, fast_imp=fast_imp)
|
| 142 |
+
|
| 143 |
+
if __name__ == '__main__':
|
| 144 |
+
num_blks = 128
|
| 145 |
+
width = 128
|
| 146 |
+
droppath=0.1
|
| 147 |
+
train_size = (1, 6, 30, 90)
|
| 148 |
+
|
| 149 |
+
net = NAFSSR(up_scale=2,train_size=train_size, fast_imp=True, width=width, num_blks=num_blks, drop_path_rate=droppath)
|
| 150 |
+
|
| 151 |
+
inp_shape = (6, 64, 64)
|
| 152 |
+
|
| 153 |
+
from ptflops import get_model_complexity_info
|
| 154 |
+
FLOPS = 0
|
| 155 |
+
macs, params = get_model_complexity_info(net, inp_shape, verbose=False, print_per_layer_stat=True)
|
| 156 |
+
|
| 157 |
+
# params = float(params[:-4])
|
| 158 |
+
print(params)
|
| 159 |
+
macs = float(macs[:-4]) + FLOPS / 10 ** 9
|
| 160 |
+
|
| 161 |
+
print('mac', macs, params)
|
| 162 |
+
|
| 163 |
+
# from basicsr.models.archs.arch_util import measure_inference_speed
|
| 164 |
+
# net = net.cuda()
|
| 165 |
+
# data = torch.randn((1, 6, 128, 128)).cuda()
|
| 166 |
+
# measure_inference_speed(net, (data,))
|
| 167 |
+
|
| 168 |
+
|
| 169 |
+
|
| 170 |
+
|
basicsr/models/archs/__init__.py
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ------------------------------------------------------------------------
|
| 2 |
+
# Copyright (c) 2022 megvii-model. All Rights Reserved.
|
| 3 |
+
# ------------------------------------------------------------------------
|
| 4 |
+
# Modified from BasicSR (https://github.com/xinntao/BasicSR)
|
| 5 |
+
# Copyright 2018-2020 BasicSR Authors
|
| 6 |
+
# ------------------------------------------------------------------------
|
| 7 |
+
import importlib
|
| 8 |
+
from os import path as osp
|
| 9 |
+
|
| 10 |
+
from basicsr.utils import scandir
|
| 11 |
+
|
| 12 |
+
# automatically scan and import arch modules
|
| 13 |
+
# scan all the files under the 'archs' folder and collect files ending with
|
| 14 |
+
# '_arch.py'
|
| 15 |
+
arch_folder = osp.dirname(osp.abspath(__file__))
|
| 16 |
+
arch_filenames = [
|
| 17 |
+
osp.splitext(osp.basename(v))[0] for v in scandir(arch_folder)
|
| 18 |
+
if v.endswith('_arch.py')
|
| 19 |
+
]
|
| 20 |
+
# import all the arch modules
|
| 21 |
+
_arch_modules = [
|
| 22 |
+
importlib.import_module(f'basicsr.models.archs.{file_name}')
|
| 23 |
+
for file_name in arch_filenames
|
| 24 |
+
]
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
def dynamic_instantiation(modules, cls_type, opt):
|
| 28 |
+
"""Dynamically instantiate class.
|
| 29 |
+
|
| 30 |
+
Args:
|
| 31 |
+
modules (list[importlib modules]): List of modules from importlib
|
| 32 |
+
files.
|
| 33 |
+
cls_type (str): Class type.
|
| 34 |
+
opt (dict): Class initialization kwargs.
|
| 35 |
+
|
| 36 |
+
Returns:
|
| 37 |
+
class: Instantiated class.
|
| 38 |
+
"""
|
| 39 |
+
|
| 40 |
+
for module in modules:
|
| 41 |
+
cls_ = getattr(module, cls_type, None)
|
| 42 |
+
if cls_ is not None:
|
| 43 |
+
break
|
| 44 |
+
if cls_ is None:
|
| 45 |
+
raise ValueError(f'{cls_type} is not found.')
|
| 46 |
+
return cls_(**opt)
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
def define_network(opt):
|
| 50 |
+
network_type = opt.pop('type')
|
| 51 |
+
net = dynamic_instantiation(_arch_modules, network_type, opt)
|
| 52 |
+
return net
|
basicsr/models/archs/arch_util.py
ADDED
|
@@ -0,0 +1,350 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ------------------------------------------------------------------------
|
| 2 |
+
# Copyright (c) 2022 megvii-model. All Rights Reserved.
|
| 3 |
+
# ------------------------------------------------------------------------
|
| 4 |
+
# Modified from BasicSR (https://github.com/xinntao/BasicSR)
|
| 5 |
+
# Copyright 2018-2020 BasicSR Authors
|
| 6 |
+
# ------------------------------------------------------------------------
|
| 7 |
+
import math
|
| 8 |
+
import torch
|
| 9 |
+
from torch import nn as nn
|
| 10 |
+
from torch.nn import functional as F
|
| 11 |
+
from torch.nn import init as init
|
| 12 |
+
from torch.nn.modules.batchnorm import _BatchNorm
|
| 13 |
+
|
| 14 |
+
from basicsr.utils import get_root_logger
|
| 15 |
+
|
| 16 |
+
# try:
|
| 17 |
+
# from basicsr.models.ops.dcn import (ModulatedDeformConvPack,
|
| 18 |
+
# modulated_deform_conv)
|
| 19 |
+
# except ImportError:
|
| 20 |
+
# # print('Cannot import dcn. Ignore this warning if dcn is not used. '
|
| 21 |
+
# # 'Otherwise install BasicSR with compiling dcn.')
|
| 22 |
+
#
|
| 23 |
+
|
| 24 |
+
@torch.no_grad()
|
| 25 |
+
def default_init_weights(module_list, scale=1, bias_fill=0, **kwargs):
|
| 26 |
+
"""Initialize network weights.
|
| 27 |
+
|
| 28 |
+
Args:
|
| 29 |
+
module_list (list[nn.Module] | nn.Module): Modules to be initialized.
|
| 30 |
+
scale (float): Scale initialized weights, especially for residual
|
| 31 |
+
blocks. Default: 1.
|
| 32 |
+
bias_fill (float): The value to fill bias. Default: 0
|
| 33 |
+
kwargs (dict): Other arguments for initialization function.
|
| 34 |
+
"""
|
| 35 |
+
if not isinstance(module_list, list):
|
| 36 |
+
module_list = [module_list]
|
| 37 |
+
for module in module_list:
|
| 38 |
+
for m in module.modules():
|
| 39 |
+
if isinstance(m, nn.Conv2d):
|
| 40 |
+
init.kaiming_normal_(m.weight, **kwargs)
|
| 41 |
+
m.weight.data *= scale
|
| 42 |
+
if m.bias is not None:
|
| 43 |
+
m.bias.data.fill_(bias_fill)
|
| 44 |
+
elif isinstance(m, nn.Linear):
|
| 45 |
+
init.kaiming_normal_(m.weight, **kwargs)
|
| 46 |
+
m.weight.data *= scale
|
| 47 |
+
if m.bias is not None:
|
| 48 |
+
m.bias.data.fill_(bias_fill)
|
| 49 |
+
elif isinstance(m, _BatchNorm):
|
| 50 |
+
init.constant_(m.weight, 1)
|
| 51 |
+
if m.bias is not None:
|
| 52 |
+
m.bias.data.fill_(bias_fill)
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
def make_layer(basic_block, num_basic_block, **kwarg):
|
| 56 |
+
"""Make layers by stacking the same blocks.
|
| 57 |
+
|
| 58 |
+
Args:
|
| 59 |
+
basic_block (nn.module): nn.module class for basic block.
|
| 60 |
+
num_basic_block (int): number of blocks.
|
| 61 |
+
|
| 62 |
+
Returns:
|
| 63 |
+
nn.Sequential: Stacked blocks in nn.Sequential.
|
| 64 |
+
"""
|
| 65 |
+
layers = []
|
| 66 |
+
for _ in range(num_basic_block):
|
| 67 |
+
layers.append(basic_block(**kwarg))
|
| 68 |
+
return nn.Sequential(*layers)
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
class ResidualBlockNoBN(nn.Module):
|
| 72 |
+
"""Residual block without BN.
|
| 73 |
+
|
| 74 |
+
It has a style of:
|
| 75 |
+
---Conv-ReLU-Conv-+-
|
| 76 |
+
|________________|
|
| 77 |
+
|
| 78 |
+
Args:
|
| 79 |
+
num_feat (int): Channel number of intermediate features.
|
| 80 |
+
Default: 64.
|
| 81 |
+
res_scale (float): Residual scale. Default: 1.
|
| 82 |
+
pytorch_init (bool): If set to True, use pytorch default init,
|
| 83 |
+
otherwise, use default_init_weights. Default: False.
|
| 84 |
+
"""
|
| 85 |
+
|
| 86 |
+
def __init__(self, num_feat=64, res_scale=1, pytorch_init=False):
|
| 87 |
+
super(ResidualBlockNoBN, self).__init__()
|
| 88 |
+
self.res_scale = res_scale
|
| 89 |
+
self.conv1 = nn.Conv2d(num_feat, num_feat, 3, 1, 1, bias=True)
|
| 90 |
+
self.conv2 = nn.Conv2d(num_feat, num_feat, 3, 1, 1, bias=True)
|
| 91 |
+
self.relu = nn.ReLU(inplace=True)
|
| 92 |
+
|
| 93 |
+
if not pytorch_init:
|
| 94 |
+
default_init_weights([self.conv1, self.conv2], 0.1)
|
| 95 |
+
|
| 96 |
+
def forward(self, x):
|
| 97 |
+
identity = x
|
| 98 |
+
out = self.conv2(self.relu(self.conv1(x)))
|
| 99 |
+
return identity + out * self.res_scale
|
| 100 |
+
|
| 101 |
+
|
| 102 |
+
class Upsample(nn.Sequential):
|
| 103 |
+
"""Upsample module.
|
| 104 |
+
|
| 105 |
+
Args:
|
| 106 |
+
scale (int): Scale factor. Supported scales: 2^n and 3.
|
| 107 |
+
num_feat (int): Channel number of intermediate features.
|
| 108 |
+
"""
|
| 109 |
+
|
| 110 |
+
def __init__(self, scale, num_feat):
|
| 111 |
+
m = []
|
| 112 |
+
if (scale & (scale - 1)) == 0: # scale = 2^n
|
| 113 |
+
for _ in range(int(math.log(scale, 2))):
|
| 114 |
+
m.append(nn.Conv2d(num_feat, 4 * num_feat, 3, 1, 1))
|
| 115 |
+
m.append(nn.PixelShuffle(2))
|
| 116 |
+
elif scale == 3:
|
| 117 |
+
m.append(nn.Conv2d(num_feat, 9 * num_feat, 3, 1, 1))
|
| 118 |
+
m.append(nn.PixelShuffle(3))
|
| 119 |
+
else:
|
| 120 |
+
raise ValueError(f'scale {scale} is not supported. '
|
| 121 |
+
'Supported scales: 2^n and 3.')
|
| 122 |
+
super(Upsample, self).__init__(*m)
|
| 123 |
+
|
| 124 |
+
|
| 125 |
+
def flow_warp(x,
|
| 126 |
+
flow,
|
| 127 |
+
interp_mode='bilinear',
|
| 128 |
+
padding_mode='zeros',
|
| 129 |
+
align_corners=True):
|
| 130 |
+
"""Warp an image or feature map with optical flow.
|
| 131 |
+
|
| 132 |
+
Args:
|
| 133 |
+
x (Tensor): Tensor with size (n, c, h, w).
|
| 134 |
+
flow (Tensor): Tensor with size (n, h, w, 2), normal value.
|
| 135 |
+
interp_mode (str): 'nearest' or 'bilinear'. Default: 'bilinear'.
|
| 136 |
+
padding_mode (str): 'zeros' or 'border' or 'reflection'.
|
| 137 |
+
Default: 'zeros'.
|
| 138 |
+
align_corners (bool): Before pytorch 1.3, the default value is
|
| 139 |
+
align_corners=True. After pytorch 1.3, the default value is
|
| 140 |
+
align_corners=False. Here, we use the True as default.
|
| 141 |
+
|
| 142 |
+
Returns:
|
| 143 |
+
Tensor: Warped image or feature map.
|
| 144 |
+
"""
|
| 145 |
+
assert x.size()[-2:] == flow.size()[1:3]
|
| 146 |
+
_, _, h, w = x.size()
|
| 147 |
+
# create mesh grid
|
| 148 |
+
grid_y, grid_x = torch.meshgrid(
|
| 149 |
+
torch.arange(0, h).type_as(x),
|
| 150 |
+
torch.arange(0, w).type_as(x))
|
| 151 |
+
grid = torch.stack((grid_x, grid_y), 2).float() # W(x), H(y), 2
|
| 152 |
+
grid.requires_grad = False
|
| 153 |
+
|
| 154 |
+
vgrid = grid + flow
|
| 155 |
+
# scale grid to [-1,1]
|
| 156 |
+
vgrid_x = 2.0 * vgrid[:, :, :, 0] / max(w - 1, 1) - 1.0
|
| 157 |
+
vgrid_y = 2.0 * vgrid[:, :, :, 1] / max(h - 1, 1) - 1.0
|
| 158 |
+
vgrid_scaled = torch.stack((vgrid_x, vgrid_y), dim=3)
|
| 159 |
+
output = F.grid_sample(
|
| 160 |
+
x,
|
| 161 |
+
vgrid_scaled,
|
| 162 |
+
mode=interp_mode,
|
| 163 |
+
padding_mode=padding_mode,
|
| 164 |
+
align_corners=align_corners)
|
| 165 |
+
|
| 166 |
+
# TODO, what if align_corners=False
|
| 167 |
+
return output
|
| 168 |
+
|
| 169 |
+
|
| 170 |
+
def resize_flow(flow,
|
| 171 |
+
size_type,
|
| 172 |
+
sizes,
|
| 173 |
+
interp_mode='bilinear',
|
| 174 |
+
align_corners=False):
|
| 175 |
+
"""Resize a flow according to ratio or shape.
|
| 176 |
+
|
| 177 |
+
Args:
|
| 178 |
+
flow (Tensor): Precomputed flow. shape [N, 2, H, W].
|
| 179 |
+
size_type (str): 'ratio' or 'shape'.
|
| 180 |
+
sizes (list[int | float]): the ratio for resizing or the final output
|
| 181 |
+
shape.
|
| 182 |
+
1) The order of ratio should be [ratio_h, ratio_w]. For
|
| 183 |
+
downsampling, the ratio should be smaller than 1.0 (i.e., ratio
|
| 184 |
+
< 1.0). For upsampling, the ratio should be larger than 1.0 (i.e.,
|
| 185 |
+
ratio > 1.0).
|
| 186 |
+
2) The order of output_size should be [out_h, out_w].
|
| 187 |
+
interp_mode (str): The mode of interpolation for resizing.
|
| 188 |
+
Default: 'bilinear'.
|
| 189 |
+
align_corners (bool): Whether align corners. Default: False.
|
| 190 |
+
|
| 191 |
+
Returns:
|
| 192 |
+
Tensor: Resized flow.
|
| 193 |
+
"""
|
| 194 |
+
_, _, flow_h, flow_w = flow.size()
|
| 195 |
+
if size_type == 'ratio':
|
| 196 |
+
output_h, output_w = int(flow_h * sizes[0]), int(flow_w * sizes[1])
|
| 197 |
+
elif size_type == 'shape':
|
| 198 |
+
output_h, output_w = sizes[0], sizes[1]
|
| 199 |
+
else:
|
| 200 |
+
raise ValueError(
|
| 201 |
+
f'Size type should be ratio or shape, but got type {size_type}.')
|
| 202 |
+
|
| 203 |
+
input_flow = flow.clone()
|
| 204 |
+
ratio_h = output_h / flow_h
|
| 205 |
+
ratio_w = output_w / flow_w
|
| 206 |
+
input_flow[:, 0, :, :] *= ratio_w
|
| 207 |
+
input_flow[:, 1, :, :] *= ratio_h
|
| 208 |
+
resized_flow = F.interpolate(
|
| 209 |
+
input=input_flow,
|
| 210 |
+
size=(output_h, output_w),
|
| 211 |
+
mode=interp_mode,
|
| 212 |
+
align_corners=align_corners)
|
| 213 |
+
return resized_flow
|
| 214 |
+
|
| 215 |
+
|
| 216 |
+
# TODO: may write a cpp file
|
| 217 |
+
def pixel_unshuffle(x, scale):
|
| 218 |
+
""" Pixel unshuffle.
|
| 219 |
+
|
| 220 |
+
Args:
|
| 221 |
+
x (Tensor): Input feature with shape (b, c, hh, hw).
|
| 222 |
+
scale (int): Downsample ratio.
|
| 223 |
+
|
| 224 |
+
Returns:
|
| 225 |
+
Tensor: the pixel unshuffled feature.
|
| 226 |
+
"""
|
| 227 |
+
b, c, hh, hw = x.size()
|
| 228 |
+
out_channel = c * (scale**2)
|
| 229 |
+
assert hh % scale == 0 and hw % scale == 0
|
| 230 |
+
h = hh // scale
|
| 231 |
+
w = hw // scale
|
| 232 |
+
x_view = x.view(b, c, h, scale, w, scale)
|
| 233 |
+
return x_view.permute(0, 1, 3, 5, 2, 4).reshape(b, out_channel, h, w)
|
| 234 |
+
|
| 235 |
+
|
| 236 |
+
# class DCNv2Pack(ModulatedDeformConvPack):
|
| 237 |
+
# """Modulated deformable conv for deformable alignment.
|
| 238 |
+
#
|
| 239 |
+
# Different from the official DCNv2Pack, which generates offsets and masks
|
| 240 |
+
# from the preceding features, this DCNv2Pack takes another different
|
| 241 |
+
# features to generate offsets and masks.
|
| 242 |
+
#
|
| 243 |
+
# Ref:
|
| 244 |
+
# Delving Deep into Deformable Alignment in Video Super-Resolution.
|
| 245 |
+
# """
|
| 246 |
+
#
|
| 247 |
+
# def forward(self, x, feat):
|
| 248 |
+
# out = self.conv_offset(feat)
|
| 249 |
+
# o1, o2, mask = torch.chunk(out, 3, dim=1)
|
| 250 |
+
# offset = torch.cat((o1, o2), dim=1)
|
| 251 |
+
# mask = torch.sigmoid(mask)
|
| 252 |
+
#
|
| 253 |
+
# offset_absmean = torch.mean(torch.abs(offset))
|
| 254 |
+
# if offset_absmean > 50:
|
| 255 |
+
# logger = get_root_logger()
|
| 256 |
+
# logger.warning(
|
| 257 |
+
# f'Offset abs mean is {offset_absmean}, larger than 50.')
|
| 258 |
+
#
|
| 259 |
+
# return modulated_deform_conv(x, offset, mask, self.weight, self.bias,
|
| 260 |
+
# self.stride, self.padding, self.dilation,
|
| 261 |
+
# self.groups, self.deformable_groups)
|
| 262 |
+
|
| 263 |
+
|
| 264 |
+
class LayerNormFunction(torch.autograd.Function):
|
| 265 |
+
|
| 266 |
+
@staticmethod
|
| 267 |
+
def forward(ctx, x, weight, bias, eps):
|
| 268 |
+
ctx.eps = eps
|
| 269 |
+
N, C, H, W = x.size()
|
| 270 |
+
mu = x.mean(1, keepdim=True)
|
| 271 |
+
var = (x - mu).pow(2).mean(1, keepdim=True)
|
| 272 |
+
y = (x - mu) / (var + eps).sqrt()
|
| 273 |
+
ctx.save_for_backward(y, var, weight)
|
| 274 |
+
y = weight.view(1, C, 1, 1) * y + bias.view(1, C, 1, 1)
|
| 275 |
+
return y
|
| 276 |
+
|
| 277 |
+
@staticmethod
|
| 278 |
+
def backward(ctx, grad_output):
|
| 279 |
+
eps = ctx.eps
|
| 280 |
+
|
| 281 |
+
N, C, H, W = grad_output.size()
|
| 282 |
+
y, var, weight = ctx.saved_variables
|
| 283 |
+
g = grad_output * weight.view(1, C, 1, 1)
|
| 284 |
+
mean_g = g.mean(dim=1, keepdim=True)
|
| 285 |
+
|
| 286 |
+
mean_gy = (g * y).mean(dim=1, keepdim=True)
|
| 287 |
+
gx = 1. / torch.sqrt(var + eps) * (g - y * mean_gy - mean_g)
|
| 288 |
+
return gx, (grad_output * y).sum(dim=3).sum(dim=2).sum(dim=0), grad_output.sum(dim=3).sum(dim=2).sum(
|
| 289 |
+
dim=0), None
|
| 290 |
+
|
| 291 |
+
class LayerNorm2d(nn.Module):
|
| 292 |
+
|
| 293 |
+
def __init__(self, channels, eps=1e-6):
|
| 294 |
+
super(LayerNorm2d, self).__init__()
|
| 295 |
+
self.register_parameter('weight', nn.Parameter(torch.ones(channels)))
|
| 296 |
+
self.register_parameter('bias', nn.Parameter(torch.zeros(channels)))
|
| 297 |
+
self.eps = eps
|
| 298 |
+
|
| 299 |
+
def forward(self, x):
|
| 300 |
+
return LayerNormFunction.apply(x, self.weight, self.bias, self.eps)
|
| 301 |
+
|
| 302 |
+
# handle multiple input
|
| 303 |
+
class MySequential(nn.Sequential):
|
| 304 |
+
def forward(self, *inputs):
|
| 305 |
+
for module in self._modules.values():
|
| 306 |
+
if type(inputs) == tuple:
|
| 307 |
+
inputs = module(*inputs)
|
| 308 |
+
else:
|
| 309 |
+
inputs = module(inputs)
|
| 310 |
+
return inputs
|
| 311 |
+
|
| 312 |
+
import time
|
| 313 |
+
def measure_inference_speed(model, data, max_iter=200, log_interval=50):
|
| 314 |
+
model.eval()
|
| 315 |
+
|
| 316 |
+
# the first several iterations may be very slow so skip them
|
| 317 |
+
num_warmup = 5
|
| 318 |
+
pure_inf_time = 0
|
| 319 |
+
fps = 0
|
| 320 |
+
|
| 321 |
+
# benchmark with 2000 image and take the average
|
| 322 |
+
for i in range(max_iter):
|
| 323 |
+
|
| 324 |
+
torch.cuda.synchronize()
|
| 325 |
+
start_time = time.perf_counter()
|
| 326 |
+
|
| 327 |
+
with torch.no_grad():
|
| 328 |
+
model(*data)
|
| 329 |
+
|
| 330 |
+
torch.cuda.synchronize()
|
| 331 |
+
elapsed = time.perf_counter() - start_time
|
| 332 |
+
|
| 333 |
+
if i >= num_warmup:
|
| 334 |
+
pure_inf_time += elapsed
|
| 335 |
+
if (i + 1) % log_interval == 0:
|
| 336 |
+
fps = (i + 1 - num_warmup) / pure_inf_time
|
| 337 |
+
print(
|
| 338 |
+
f'Done image [{i + 1:<3}/ {max_iter}], '
|
| 339 |
+
f'fps: {fps:.1f} img / s, '
|
| 340 |
+
f'times per image: {1000 / fps:.1f} ms / img',
|
| 341 |
+
flush=True)
|
| 342 |
+
|
| 343 |
+
if (i + 1) == max_iter:
|
| 344 |
+
fps = (i + 1 - num_warmup) / pure_inf_time
|
| 345 |
+
print(
|
| 346 |
+
f'Overall fps: {fps:.1f} img / s, '
|
| 347 |
+
f'times per image: {1000 / fps:.1f} ms / img',
|
| 348 |
+
flush=True)
|
| 349 |
+
break
|
| 350 |
+
return fps
|
basicsr/models/archs/local_arch.py
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ------------------------------------------------------------------------
|
| 2 |
+
# Copyright (c) 2022 megvii-model. All Rights Reserved.
|
| 3 |
+
# ------------------------------------------------------------------------
|
| 4 |
+
|
| 5 |
+
import numpy as np
|
| 6 |
+
import torch
|
| 7 |
+
import torch.nn as nn
|
| 8 |
+
import torch.nn.functional as F
|
| 9 |
+
|
| 10 |
+
class AvgPool2d(nn.Module):
|
| 11 |
+
def __init__(self, kernel_size=None, base_size=None, auto_pad=True, fast_imp=False, train_size=None):
|
| 12 |
+
super().__init__()
|
| 13 |
+
self.kernel_size = kernel_size
|
| 14 |
+
self.base_size = base_size
|
| 15 |
+
self.auto_pad = auto_pad
|
| 16 |
+
|
| 17 |
+
# only used for fast implementation
|
| 18 |
+
self.fast_imp = fast_imp
|
| 19 |
+
self.rs = [5, 4, 3, 2, 1]
|
| 20 |
+
self.max_r1 = self.rs[0]
|
| 21 |
+
self.max_r2 = self.rs[0]
|
| 22 |
+
self.train_size = train_size
|
| 23 |
+
|
| 24 |
+
def extra_repr(self) -> str:
|
| 25 |
+
return 'kernel_size={}, base_size={}, stride={}, fast_imp={}'.format(
|
| 26 |
+
self.kernel_size, self.base_size, self.kernel_size, self.fast_imp
|
| 27 |
+
)
|
| 28 |
+
|
| 29 |
+
def forward(self, x):
|
| 30 |
+
if self.kernel_size is None and self.base_size:
|
| 31 |
+
train_size = self.train_size
|
| 32 |
+
if isinstance(self.base_size, int):
|
| 33 |
+
self.base_size = (self.base_size, self.base_size)
|
| 34 |
+
self.kernel_size = list(self.base_size)
|
| 35 |
+
self.kernel_size[0] = x.shape[2] * self.base_size[0] // train_size[-2]
|
| 36 |
+
self.kernel_size[1] = x.shape[3] * self.base_size[1] // train_size[-1]
|
| 37 |
+
|
| 38 |
+
# only used for fast implementation
|
| 39 |
+
self.max_r1 = max(1, self.rs[0] * x.shape[2] // train_size[-2])
|
| 40 |
+
self.max_r2 = max(1, self.rs[0] * x.shape[3] // train_size[-1])
|
| 41 |
+
|
| 42 |
+
if self.kernel_size[0] >= x.size(-2) and self.kernel_size[1] >= x.size(-1):
|
| 43 |
+
return F.adaptive_avg_pool2d(x, 1)
|
| 44 |
+
|
| 45 |
+
if self.fast_imp: # Non-equivalent implementation but faster
|
| 46 |
+
h, w = x.shape[2:]
|
| 47 |
+
if self.kernel_size[0] >= h and self.kernel_size[1] >= w:
|
| 48 |
+
out = F.adaptive_avg_pool2d(x, 1)
|
| 49 |
+
else:
|
| 50 |
+
r1 = [r for r in self.rs if h % r == 0][0]
|
| 51 |
+
r2 = [r for r in self.rs if w % r == 0][0]
|
| 52 |
+
# reduction_constraint
|
| 53 |
+
r1 = min(self.max_r1, r1)
|
| 54 |
+
r2 = min(self.max_r2, r2)
|
| 55 |
+
s = x[:, :, ::r1, ::r2].cumsum(dim=-1).cumsum(dim=-2)
|
| 56 |
+
n, c, h, w = s.shape
|
| 57 |
+
k1, k2 = min(h - 1, self.kernel_size[0] // r1), min(w - 1, self.kernel_size[1] // r2)
|
| 58 |
+
out = (s[:, :, :-k1, :-k2] - s[:, :, :-k1, k2:] - s[:, :, k1:, :-k2] + s[:, :, k1:, k2:]) / (k1 * k2)
|
| 59 |
+
out = torch.nn.functional.interpolate(out, scale_factor=(r1, r2))
|
| 60 |
+
else:
|
| 61 |
+
n, c, h, w = x.shape
|
| 62 |
+
s = x.cumsum(dim=-1).cumsum_(dim=-2)
|
| 63 |
+
s = torch.nn.functional.pad(s, (1, 0, 1, 0)) # pad 0 for convenience
|
| 64 |
+
k1, k2 = min(h, self.kernel_size[0]), min(w, self.kernel_size[1])
|
| 65 |
+
s1, s2, s3, s4 = s[:, :, :-k1, :-k2], s[:, :, :-k1, k2:], s[:, :, k1:, :-k2], s[:, :, k1:, k2:]
|
| 66 |
+
out = s4 + s1 - s2 - s3
|
| 67 |
+
out = out / (k1 * k2)
|
| 68 |
+
|
| 69 |
+
if self.auto_pad:
|
| 70 |
+
n, c, h, w = x.shape
|
| 71 |
+
_h, _w = out.shape[2:]
|
| 72 |
+
# print(x.shape, self.kernel_size)
|
| 73 |
+
pad2d = ((w - _w) // 2, (w - _w + 1) // 2, (h - _h) // 2, (h - _h + 1) // 2)
|
| 74 |
+
out = torch.nn.functional.pad(out, pad2d, mode='replicate')
|
| 75 |
+
|
| 76 |
+
return out
|
| 77 |
+
|
| 78 |
+
def replace_layers(model, base_size, train_size, fast_imp, **kwargs):
|
| 79 |
+
for n, m in model.named_children():
|
| 80 |
+
if len(list(m.children())) > 0:
|
| 81 |
+
## compound module, go inside it
|
| 82 |
+
replace_layers(m, base_size, train_size, fast_imp, **kwargs)
|
| 83 |
+
|
| 84 |
+
if isinstance(m, nn.AdaptiveAvgPool2d):
|
| 85 |
+
pool = AvgPool2d(base_size=base_size, fast_imp=fast_imp, train_size=train_size)
|
| 86 |
+
assert m.output_size == 1
|
| 87 |
+
setattr(model, n, pool)
|
| 88 |
+
|
| 89 |
+
|
| 90 |
+
'''
|
| 91 |
+
ref.
|
| 92 |
+
@article{chu2021tlsc,
|
| 93 |
+
title={Revisiting Global Statistics Aggregation for Improving Image Restoration},
|
| 94 |
+
author={Chu, Xiaojie and Chen, Liangyu and and Chen, Chengpeng and Lu, Xin},
|
| 95 |
+
journal={arXiv preprint arXiv:2112.04491},
|
| 96 |
+
year={2021}
|
| 97 |
+
}
|
| 98 |
+
'''
|
| 99 |
+
class Local_Base():
|
| 100 |
+
def convert(self, *args, train_size, **kwargs):
|
| 101 |
+
replace_layers(self, *args, train_size=train_size, **kwargs)
|
| 102 |
+
imgs = torch.rand(train_size)
|
| 103 |
+
with torch.no_grad():
|
| 104 |
+
self.forward(imgs)
|
basicsr/models/base_model.py
ADDED
|
@@ -0,0 +1,356 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ------------------------------------------------------------------------
|
| 2 |
+
# Copyright (c) 2022 megvii-model. All Rights Reserved.
|
| 3 |
+
# ------------------------------------------------------------------------
|
| 4 |
+
# Modified from BasicSR (https://github.com/xinntao/BasicSR)
|
| 5 |
+
# Copyright 2018-2020 BasicSR Authors
|
| 6 |
+
# ------------------------------------------------------------------------
|
| 7 |
+
import logging
|
| 8 |
+
import os
|
| 9 |
+
import torch
|
| 10 |
+
from collections import OrderedDict
|
| 11 |
+
from copy import deepcopy
|
| 12 |
+
from torch.nn.parallel import DataParallel, DistributedDataParallel
|
| 13 |
+
|
| 14 |
+
from basicsr.models import lr_scheduler as lr_scheduler
|
| 15 |
+
from basicsr.utils.dist_util import master_only
|
| 16 |
+
|
| 17 |
+
logger = logging.getLogger('basicsr')
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
class BaseModel():
|
| 21 |
+
"""Base model."""
|
| 22 |
+
|
| 23 |
+
def __init__(self, opt):
|
| 24 |
+
self.opt = opt
|
| 25 |
+
self.device = torch.device('cuda' if opt['num_gpu'] != 0 else 'cpu')
|
| 26 |
+
self.is_train = opt['is_train']
|
| 27 |
+
self.schedulers = []
|
| 28 |
+
self.optimizers = []
|
| 29 |
+
|
| 30 |
+
def feed_data(self, data):
|
| 31 |
+
pass
|
| 32 |
+
|
| 33 |
+
def optimize_parameters(self):
|
| 34 |
+
pass
|
| 35 |
+
|
| 36 |
+
def get_current_visuals(self):
|
| 37 |
+
pass
|
| 38 |
+
|
| 39 |
+
def save(self, epoch, current_iter):
|
| 40 |
+
"""Save networks and training state."""
|
| 41 |
+
pass
|
| 42 |
+
|
| 43 |
+
def validation(self, dataloader, current_iter, tb_logger, save_img=False, rgb2bgr=True, use_image=True):
|
| 44 |
+
"""Validation function.
|
| 45 |
+
|
| 46 |
+
Args:
|
| 47 |
+
dataloader (torch.utils.data.DataLoader): Validation dataloader.
|
| 48 |
+
current_iter (int): Current iteration.
|
| 49 |
+
tb_logger (tensorboard logger): Tensorboard logger.
|
| 50 |
+
save_img (bool): Whether to save images. Default: False.
|
| 51 |
+
rgb2bgr (bool): Whether to save images using rgb2bgr. Default: True
|
| 52 |
+
use_image (bool): Whether to use saved images to compute metrics (PSNR, SSIM), if not, then use data directly from network' output. Default: True
|
| 53 |
+
"""
|
| 54 |
+
if self.opt['dist']:
|
| 55 |
+
return self.dist_validation(dataloader, current_iter, tb_logger, save_img, rgb2bgr, use_image)
|
| 56 |
+
else:
|
| 57 |
+
return self.nondist_validation(dataloader, current_iter, tb_logger,
|
| 58 |
+
save_img, rgb2bgr, use_image)
|
| 59 |
+
|
| 60 |
+
def get_current_log(self):
|
| 61 |
+
return self.log_dict
|
| 62 |
+
|
| 63 |
+
def model_to_device(self, net):
|
| 64 |
+
"""Model to device. It also warps models with DistributedDataParallel
|
| 65 |
+
or DataParallel.
|
| 66 |
+
|
| 67 |
+
Args:
|
| 68 |
+
net (nn.Module)
|
| 69 |
+
"""
|
| 70 |
+
|
| 71 |
+
net = net.to(self.device)
|
| 72 |
+
if self.opt['dist']:
|
| 73 |
+
find_unused_parameters = self.opt.get('find_unused_parameters',
|
| 74 |
+
False)
|
| 75 |
+
net = DistributedDataParallel(
|
| 76 |
+
net,
|
| 77 |
+
device_ids=[torch.cuda.current_device()],
|
| 78 |
+
find_unused_parameters=find_unused_parameters)
|
| 79 |
+
elif self.opt['num_gpu'] > 1:
|
| 80 |
+
net = DataParallel(net)
|
| 81 |
+
return net
|
| 82 |
+
|
| 83 |
+
def setup_schedulers(self):
|
| 84 |
+
"""Set up schedulers."""
|
| 85 |
+
train_opt = self.opt['train']
|
| 86 |
+
scheduler_type = train_opt['scheduler'].pop('type')
|
| 87 |
+
if scheduler_type in ['MultiStepLR', 'MultiStepRestartLR']:
|
| 88 |
+
for optimizer in self.optimizers:
|
| 89 |
+
self.schedulers.append(
|
| 90 |
+
lr_scheduler.MultiStepRestartLR(optimizer,
|
| 91 |
+
**train_opt['scheduler']))
|
| 92 |
+
elif scheduler_type == 'CosineAnnealingRestartLR':
|
| 93 |
+
for optimizer in self.optimizers:
|
| 94 |
+
self.schedulers.append(
|
| 95 |
+
lr_scheduler.CosineAnnealingRestartLR(
|
| 96 |
+
optimizer, **train_opt['scheduler']))
|
| 97 |
+
elif scheduler_type == 'TrueCosineAnnealingLR':
|
| 98 |
+
print('..', 'cosineannealingLR')
|
| 99 |
+
for optimizer in self.optimizers:
|
| 100 |
+
self.schedulers.append(
|
| 101 |
+
torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, **train_opt['scheduler']))
|
| 102 |
+
elif scheduler_type == 'LinearLR':
|
| 103 |
+
for optimizer in self.optimizers:
|
| 104 |
+
self.schedulers.append(
|
| 105 |
+
lr_scheduler.LinearLR(
|
| 106 |
+
optimizer, train_opt['total_iter']))
|
| 107 |
+
elif scheduler_type == 'VibrateLR':
|
| 108 |
+
for optimizer in self.optimizers:
|
| 109 |
+
self.schedulers.append(
|
| 110 |
+
lr_scheduler.VibrateLR(
|
| 111 |
+
optimizer, train_opt['total_iter']))
|
| 112 |
+
else:
|
| 113 |
+
raise NotImplementedError(
|
| 114 |
+
f'Scheduler {scheduler_type} is not implemented yet.')
|
| 115 |
+
|
| 116 |
+
def get_bare_model(self, net):
|
| 117 |
+
"""Get bare model, especially under wrapping with
|
| 118 |
+
DistributedDataParallel or DataParallel.
|
| 119 |
+
"""
|
| 120 |
+
if isinstance(net, (DataParallel, DistributedDataParallel)):
|
| 121 |
+
net = net.module
|
| 122 |
+
return net
|
| 123 |
+
|
| 124 |
+
@master_only
|
| 125 |
+
def print_network(self, net):
|
| 126 |
+
"""Print the str and parameter number of a network.
|
| 127 |
+
|
| 128 |
+
Args:
|
| 129 |
+
net (nn.Module)
|
| 130 |
+
"""
|
| 131 |
+
if isinstance(net, (DataParallel, DistributedDataParallel)):
|
| 132 |
+
net_cls_str = (f'{net.__class__.__name__} - '
|
| 133 |
+
f'{net.module.__class__.__name__}')
|
| 134 |
+
else:
|
| 135 |
+
net_cls_str = f'{net.__class__.__name__}'
|
| 136 |
+
|
| 137 |
+
net = self.get_bare_model(net)
|
| 138 |
+
net_str = str(net)
|
| 139 |
+
net_params = sum(map(lambda x: x.numel(), net.parameters()))
|
| 140 |
+
|
| 141 |
+
logger.info(
|
| 142 |
+
f'Network: {net_cls_str}, with parameters: {net_params:,d}')
|
| 143 |
+
logger.info(net_str)
|
| 144 |
+
|
| 145 |
+
def _set_lr(self, lr_groups_l):
|
| 146 |
+
"""Set learning rate for warmup.
|
| 147 |
+
|
| 148 |
+
Args:
|
| 149 |
+
lr_groups_l (list): List for lr_groups, each for an optimizer.
|
| 150 |
+
"""
|
| 151 |
+
for optimizer, lr_groups in zip(self.optimizers, lr_groups_l):
|
| 152 |
+
for param_group, lr in zip(optimizer.param_groups, lr_groups):
|
| 153 |
+
param_group['lr'] = lr
|
| 154 |
+
|
| 155 |
+
def _get_init_lr(self):
|
| 156 |
+
"""Get the initial lr, which is set by the scheduler.
|
| 157 |
+
"""
|
| 158 |
+
init_lr_groups_l = []
|
| 159 |
+
for optimizer in self.optimizers:
|
| 160 |
+
init_lr_groups_l.append(
|
| 161 |
+
[v['initial_lr'] for v in optimizer.param_groups])
|
| 162 |
+
return init_lr_groups_l
|
| 163 |
+
|
| 164 |
+
def update_learning_rate(self, current_iter, warmup_iter=-1):
|
| 165 |
+
"""Update learning rate.
|
| 166 |
+
|
| 167 |
+
Args:
|
| 168 |
+
current_iter (int): Current iteration.
|
| 169 |
+
warmup_iter (int): Warmup iter numbers. -1 for no warmup.
|
| 170 |
+
Default: -1.
|
| 171 |
+
"""
|
| 172 |
+
if current_iter > 1:
|
| 173 |
+
for scheduler in self.schedulers:
|
| 174 |
+
scheduler.step()
|
| 175 |
+
# set up warm-up learning rate
|
| 176 |
+
if current_iter < warmup_iter:
|
| 177 |
+
# get initial lr for each group
|
| 178 |
+
init_lr_g_l = self._get_init_lr()
|
| 179 |
+
# modify warming-up learning rates
|
| 180 |
+
# currently only support linearly warm up
|
| 181 |
+
warm_up_lr_l = []
|
| 182 |
+
for init_lr_g in init_lr_g_l:
|
| 183 |
+
warm_up_lr_l.append(
|
| 184 |
+
[v / warmup_iter * current_iter for v in init_lr_g])
|
| 185 |
+
# set learning rate
|
| 186 |
+
self._set_lr(warm_up_lr_l)
|
| 187 |
+
|
| 188 |
+
def get_current_learning_rate(self):
|
| 189 |
+
return [
|
| 190 |
+
param_group['lr']
|
| 191 |
+
for param_group in self.optimizers[0].param_groups
|
| 192 |
+
]
|
| 193 |
+
|
| 194 |
+
@master_only
|
| 195 |
+
def save_network(self, net, net_label, current_iter, param_key='params'):
|
| 196 |
+
"""Save networks.
|
| 197 |
+
|
| 198 |
+
Args:
|
| 199 |
+
net (nn.Module | list[nn.Module]): Network(s) to be saved.
|
| 200 |
+
net_label (str): Network label.
|
| 201 |
+
current_iter (int): Current iter number.
|
| 202 |
+
param_key (str | list[str]): The parameter key(s) to save network.
|
| 203 |
+
Default: 'params'.
|
| 204 |
+
"""
|
| 205 |
+
if current_iter == -1:
|
| 206 |
+
current_iter = 'latest'
|
| 207 |
+
save_filename = f'{net_label}_{current_iter}.pth'
|
| 208 |
+
save_path = os.path.join(self.opt['path']['models'], save_filename)
|
| 209 |
+
|
| 210 |
+
net = net if isinstance(net, list) else [net]
|
| 211 |
+
param_key = param_key if isinstance(param_key, list) else [param_key]
|
| 212 |
+
assert len(net) == len(
|
| 213 |
+
param_key), 'The lengths of net and param_key should be the same.'
|
| 214 |
+
|
| 215 |
+
save_dict = {}
|
| 216 |
+
for net_, param_key_ in zip(net, param_key):
|
| 217 |
+
net_ = self.get_bare_model(net_)
|
| 218 |
+
state_dict = net_.state_dict()
|
| 219 |
+
for key, param in state_dict.items():
|
| 220 |
+
if key.startswith('module.'): # remove unnecessary 'module.'
|
| 221 |
+
key = key[7:]
|
| 222 |
+
state_dict[key] = param.cpu()
|
| 223 |
+
save_dict[param_key_] = state_dict
|
| 224 |
+
|
| 225 |
+
torch.save(save_dict, save_path)
|
| 226 |
+
|
| 227 |
+
def _print_different_keys_loading(self, crt_net, load_net, strict=True):
|
| 228 |
+
"""Print keys with differnet name or different size when loading models.
|
| 229 |
+
|
| 230 |
+
1. Print keys with differnet names.
|
| 231 |
+
2. If strict=False, print the same key but with different tensor size.
|
| 232 |
+
It also ignore these keys with different sizes (not load).
|
| 233 |
+
|
| 234 |
+
Args:
|
| 235 |
+
crt_net (torch model): Current network.
|
| 236 |
+
load_net (dict): Loaded network.
|
| 237 |
+
strict (bool): Whether strictly loaded. Default: True.
|
| 238 |
+
"""
|
| 239 |
+
crt_net = self.get_bare_model(crt_net)
|
| 240 |
+
crt_net = crt_net.state_dict()
|
| 241 |
+
crt_net_keys = set(crt_net.keys())
|
| 242 |
+
load_net_keys = set(load_net.keys())
|
| 243 |
+
|
| 244 |
+
if crt_net_keys != load_net_keys:
|
| 245 |
+
logger.warning('Current net - loaded net:')
|
| 246 |
+
for v in sorted(list(crt_net_keys - load_net_keys)):
|
| 247 |
+
logger.warning(f' {v}')
|
| 248 |
+
logger.warning('Loaded net - current net:')
|
| 249 |
+
for v in sorted(list(load_net_keys - crt_net_keys)):
|
| 250 |
+
logger.warning(f' {v}')
|
| 251 |
+
|
| 252 |
+
# check the size for the same keys
|
| 253 |
+
if not strict:
|
| 254 |
+
common_keys = crt_net_keys & load_net_keys
|
| 255 |
+
for k in common_keys:
|
| 256 |
+
if crt_net[k].size() != load_net[k].size():
|
| 257 |
+
logger.warning(
|
| 258 |
+
f'Size different, ignore [{k}]: crt_net: '
|
| 259 |
+
f'{crt_net[k].shape}; load_net: {load_net[k].shape}')
|
| 260 |
+
load_net[k + '.ignore'] = load_net.pop(k)
|
| 261 |
+
|
| 262 |
+
def load_network(self, net, load_path, strict=True, param_key='params'):
|
| 263 |
+
"""Load network.
|
| 264 |
+
|
| 265 |
+
Args:
|
| 266 |
+
load_path (str): The path of networks to be loaded.
|
| 267 |
+
net (nn.Module): Network.
|
| 268 |
+
strict (bool): Whether strictly loaded.
|
| 269 |
+
param_key (str): The parameter key of loaded network. If set to
|
| 270 |
+
None, use the root 'path'.
|
| 271 |
+
Default: 'params'.
|
| 272 |
+
"""
|
| 273 |
+
net = self.get_bare_model(net)
|
| 274 |
+
logger.info(
|
| 275 |
+
f'Loading {net.__class__.__name__} model from {load_path}.')
|
| 276 |
+
load_net = torch.load(
|
| 277 |
+
load_path, map_location=lambda storage, loc: storage)
|
| 278 |
+
if param_key is not None:
|
| 279 |
+
load_net = load_net[param_key]
|
| 280 |
+
print(' load net keys', load_net.keys)
|
| 281 |
+
# remove unnecessary 'module.'
|
| 282 |
+
for k, v in deepcopy(load_net).items():
|
| 283 |
+
if k.startswith('module.'):
|
| 284 |
+
load_net[k[7:]] = v
|
| 285 |
+
load_net.pop(k)
|
| 286 |
+
self._print_different_keys_loading(net, load_net, strict)
|
| 287 |
+
net.load_state_dict(load_net, strict=strict)
|
| 288 |
+
|
| 289 |
+
@master_only
|
| 290 |
+
def save_training_state(self, epoch, current_iter):
|
| 291 |
+
"""Save training states during training, which will be used for
|
| 292 |
+
resuming.
|
| 293 |
+
|
| 294 |
+
Args:
|
| 295 |
+
epoch (int): Current epoch.
|
| 296 |
+
current_iter (int): Current iteration.
|
| 297 |
+
"""
|
| 298 |
+
if current_iter != -1:
|
| 299 |
+
state = {
|
| 300 |
+
'epoch': epoch,
|
| 301 |
+
'iter': current_iter,
|
| 302 |
+
'optimizers': [],
|
| 303 |
+
'schedulers': []
|
| 304 |
+
}
|
| 305 |
+
for o in self.optimizers:
|
| 306 |
+
state['optimizers'].append(o.state_dict())
|
| 307 |
+
for s in self.schedulers:
|
| 308 |
+
state['schedulers'].append(s.state_dict())
|
| 309 |
+
save_filename = f'{current_iter}.state'
|
| 310 |
+
save_path = os.path.join(self.opt['path']['training_states'],
|
| 311 |
+
save_filename)
|
| 312 |
+
torch.save(state, save_path)
|
| 313 |
+
|
| 314 |
+
def resume_training(self, resume_state):
|
| 315 |
+
"""Reload the optimizers and schedulers for resumed training.
|
| 316 |
+
|
| 317 |
+
Args:
|
| 318 |
+
resume_state (dict): Resume state.
|
| 319 |
+
"""
|
| 320 |
+
resume_optimizers = resume_state['optimizers']
|
| 321 |
+
resume_schedulers = resume_state['schedulers']
|
| 322 |
+
assert len(resume_optimizers) == len(
|
| 323 |
+
self.optimizers), 'Wrong lengths of optimizers'
|
| 324 |
+
assert len(resume_schedulers) == len(
|
| 325 |
+
self.schedulers), 'Wrong lengths of schedulers'
|
| 326 |
+
for i, o in enumerate(resume_optimizers):
|
| 327 |
+
self.optimizers[i].load_state_dict(o)
|
| 328 |
+
for i, s in enumerate(resume_schedulers):
|
| 329 |
+
self.schedulers[i].load_state_dict(s)
|
| 330 |
+
|
| 331 |
+
def reduce_loss_dict(self, loss_dict):
|
| 332 |
+
"""reduce loss dict.
|
| 333 |
+
|
| 334 |
+
In distributed training, it averages the losses among different GPUs .
|
| 335 |
+
|
| 336 |
+
Args:
|
| 337 |
+
loss_dict (OrderedDict): Loss dict.
|
| 338 |
+
"""
|
| 339 |
+
with torch.no_grad():
|
| 340 |
+
if self.opt['dist']:
|
| 341 |
+
keys = []
|
| 342 |
+
losses = []
|
| 343 |
+
for name, value in loss_dict.items():
|
| 344 |
+
keys.append(name)
|
| 345 |
+
losses.append(value)
|
| 346 |
+
losses = torch.stack(losses, 0)
|
| 347 |
+
torch.distributed.reduce(losses, dst=0)
|
| 348 |
+
if self.opt['rank'] == 0:
|
| 349 |
+
losses /= self.opt['world_size']
|
| 350 |
+
loss_dict = {key: loss for key, loss in zip(keys, losses)}
|
| 351 |
+
|
| 352 |
+
log_dict = OrderedDict()
|
| 353 |
+
for name, value in loss_dict.items():
|
| 354 |
+
log_dict[name] = value.mean().item()
|
| 355 |
+
|
| 356 |
+
return log_dict
|
basicsr/models/image_restoration_model.py
ADDED
|
@@ -0,0 +1,413 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ------------------------------------------------------------------------
|
| 2 |
+
# Copyright (c) 2022 megvii-model. All Rights Reserved.
|
| 3 |
+
# ------------------------------------------------------------------------
|
| 4 |
+
# Modified from BasicSR (https://github.com/xinntao/BasicSR)
|
| 5 |
+
# Copyright 2018-2020 BasicSR Authors
|
| 6 |
+
# ------------------------------------------------------------------------
|
| 7 |
+
import importlib
|
| 8 |
+
import torch
|
| 9 |
+
import torch.nn.functional as F
|
| 10 |
+
from collections import OrderedDict
|
| 11 |
+
from copy import deepcopy
|
| 12 |
+
from os import path as osp
|
| 13 |
+
from tqdm import tqdm
|
| 14 |
+
|
| 15 |
+
from basicsr.models.archs import define_network
|
| 16 |
+
from basicsr.models.base_model import BaseModel
|
| 17 |
+
from basicsr.utils import get_root_logger, imwrite, tensor2img
|
| 18 |
+
from basicsr.utils.dist_util import get_dist_info
|
| 19 |
+
|
| 20 |
+
loss_module = importlib.import_module('basicsr.models.losses')
|
| 21 |
+
metric_module = importlib.import_module('basicsr.metrics')
|
| 22 |
+
|
| 23 |
+
class ImageRestorationModel(BaseModel):
|
| 24 |
+
"""Base Deblur model for single image deblur."""
|
| 25 |
+
|
| 26 |
+
def __init__(self, opt):
|
| 27 |
+
super(ImageRestorationModel, self).__init__(opt)
|
| 28 |
+
|
| 29 |
+
# define network
|
| 30 |
+
self.net_g = define_network(deepcopy(opt['network_g']))
|
| 31 |
+
self.net_g = self.model_to_device(self.net_g)
|
| 32 |
+
|
| 33 |
+
# load pretrained models
|
| 34 |
+
load_path = self.opt['path'].get('pretrain_network_g', None)
|
| 35 |
+
if load_path is not None:
|
| 36 |
+
self.load_network(self.net_g, load_path,
|
| 37 |
+
self.opt['path'].get('strict_load_g', True), param_key=self.opt['path'].get('param_key', 'params'))
|
| 38 |
+
|
| 39 |
+
if self.is_train:
|
| 40 |
+
self.init_training_settings()
|
| 41 |
+
|
| 42 |
+
self.scale = int(opt['scale'])
|
| 43 |
+
|
| 44 |
+
def init_training_settings(self):
|
| 45 |
+
self.net_g.train()
|
| 46 |
+
train_opt = self.opt['train']
|
| 47 |
+
|
| 48 |
+
# define losses
|
| 49 |
+
if train_opt.get('pixel_opt'):
|
| 50 |
+
pixel_type = train_opt['pixel_opt'].pop('type')
|
| 51 |
+
cri_pix_cls = getattr(loss_module, pixel_type)
|
| 52 |
+
self.cri_pix = cri_pix_cls(**train_opt['pixel_opt']).to(
|
| 53 |
+
self.device)
|
| 54 |
+
else:
|
| 55 |
+
self.cri_pix = None
|
| 56 |
+
|
| 57 |
+
if train_opt.get('perceptual_opt'):
|
| 58 |
+
percep_type = train_opt['perceptual_opt'].pop('type')
|
| 59 |
+
cri_perceptual_cls = getattr(loss_module, percep_type)
|
| 60 |
+
self.cri_perceptual = cri_perceptual_cls(
|
| 61 |
+
**train_opt['perceptual_opt']).to(self.device)
|
| 62 |
+
else:
|
| 63 |
+
self.cri_perceptual = None
|
| 64 |
+
|
| 65 |
+
if self.cri_pix is None and self.cri_perceptual is None:
|
| 66 |
+
raise ValueError('Both pixel and perceptual losses are None.')
|
| 67 |
+
|
| 68 |
+
# set up optimizers and schedulers
|
| 69 |
+
self.setup_optimizers()
|
| 70 |
+
self.setup_schedulers()
|
| 71 |
+
|
| 72 |
+
def setup_optimizers(self):
|
| 73 |
+
train_opt = self.opt['train']
|
| 74 |
+
optim_params = []
|
| 75 |
+
|
| 76 |
+
for k, v in self.net_g.named_parameters():
|
| 77 |
+
if v.requires_grad:
|
| 78 |
+
# if k.startswith('module.offsets') or k.startswith('module.dcns'):
|
| 79 |
+
# optim_params_lowlr.append(v)
|
| 80 |
+
# else:
|
| 81 |
+
optim_params.append(v)
|
| 82 |
+
# else:
|
| 83 |
+
# logger = get_root_logger()
|
| 84 |
+
# logger.warning(f'Params {k} will not be optimized.')
|
| 85 |
+
# print(optim_params)
|
| 86 |
+
# ratio = 0.1
|
| 87 |
+
|
| 88 |
+
optim_type = train_opt['optim_g'].pop('type')
|
| 89 |
+
if optim_type == 'Adam':
|
| 90 |
+
self.optimizer_g = torch.optim.Adam([{'params': optim_params}],
|
| 91 |
+
**train_opt['optim_g'])
|
| 92 |
+
elif optim_type == 'SGD':
|
| 93 |
+
self.optimizer_g = torch.optim.SGD(optim_params,
|
| 94 |
+
**train_opt['optim_g'])
|
| 95 |
+
elif optim_type == 'AdamW':
|
| 96 |
+
self.optimizer_g = torch.optim.AdamW([{'params': optim_params}],
|
| 97 |
+
**train_opt['optim_g'])
|
| 98 |
+
pass
|
| 99 |
+
else:
|
| 100 |
+
raise NotImplementedError(
|
| 101 |
+
f'optimizer {optim_type} is not supperted yet.')
|
| 102 |
+
self.optimizers.append(self.optimizer_g)
|
| 103 |
+
|
| 104 |
+
def feed_data(self, data, is_val=False):
|
| 105 |
+
self.lq = data['lq'].to(self.device)
|
| 106 |
+
if 'gt' in data:
|
| 107 |
+
self.gt = data['gt'].to(self.device)
|
| 108 |
+
|
| 109 |
+
def grids(self):
|
| 110 |
+
b, c, h, w = self.gt.size()
|
| 111 |
+
self.original_size = (b, c, h, w)
|
| 112 |
+
|
| 113 |
+
assert b == 1
|
| 114 |
+
if 'crop_size_h' in self.opt['val']:
|
| 115 |
+
crop_size_h = self.opt['val']['crop_size_h']
|
| 116 |
+
else:
|
| 117 |
+
crop_size_h = int(self.opt['val'].get('crop_size_h_ratio') * h)
|
| 118 |
+
|
| 119 |
+
if 'crop_size_w' in self.opt['val']:
|
| 120 |
+
crop_size_w = self.opt['val'].get('crop_size_w')
|
| 121 |
+
else:
|
| 122 |
+
crop_size_w = int(self.opt['val'].get('crop_size_w_ratio') * w)
|
| 123 |
+
|
| 124 |
+
|
| 125 |
+
crop_size_h, crop_size_w = crop_size_h // self.scale * self.scale, crop_size_w // self.scale * self.scale
|
| 126 |
+
#adaptive step_i, step_j
|
| 127 |
+
num_row = (h - 1) // crop_size_h + 1
|
| 128 |
+
num_col = (w - 1) // crop_size_w + 1
|
| 129 |
+
|
| 130 |
+
import math
|
| 131 |
+
step_j = crop_size_w if num_col == 1 else math.ceil((w - crop_size_w) / (num_col - 1) - 1e-8)
|
| 132 |
+
step_i = crop_size_h if num_row == 1 else math.ceil((h - crop_size_h) / (num_row - 1) - 1e-8)
|
| 133 |
+
|
| 134 |
+
scale = self.scale
|
| 135 |
+
step_i = step_i//scale*scale
|
| 136 |
+
step_j = step_j//scale*scale
|
| 137 |
+
|
| 138 |
+
parts = []
|
| 139 |
+
idxes = []
|
| 140 |
+
|
| 141 |
+
i = 0 # 0~h-1
|
| 142 |
+
last_i = False
|
| 143 |
+
while i < h and not last_i:
|
| 144 |
+
j = 0
|
| 145 |
+
if i + crop_size_h >= h:
|
| 146 |
+
i = h - crop_size_h
|
| 147 |
+
last_i = True
|
| 148 |
+
|
| 149 |
+
last_j = False
|
| 150 |
+
while j < w and not last_j:
|
| 151 |
+
if j + crop_size_w >= w:
|
| 152 |
+
j = w - crop_size_w
|
| 153 |
+
last_j = True
|
| 154 |
+
parts.append(self.lq[:, :, i // scale :(i + crop_size_h) // scale, j // scale:(j + crop_size_w) // scale])
|
| 155 |
+
idxes.append({'i': i, 'j': j})
|
| 156 |
+
j = j + step_j
|
| 157 |
+
i = i + step_i
|
| 158 |
+
|
| 159 |
+
self.origin_lq = self.lq
|
| 160 |
+
self.lq = torch.cat(parts, dim=0)
|
| 161 |
+
self.idxes = idxes
|
| 162 |
+
|
| 163 |
+
def grids_inverse(self):
|
| 164 |
+
preds = torch.zeros(self.original_size)
|
| 165 |
+
b, c, h, w = self.original_size
|
| 166 |
+
|
| 167 |
+
count_mt = torch.zeros((b, 1, h, w))
|
| 168 |
+
if 'crop_size_h' in self.opt['val']:
|
| 169 |
+
crop_size_h = self.opt['val']['crop_size_h']
|
| 170 |
+
else:
|
| 171 |
+
crop_size_h = int(self.opt['val'].get('crop_size_h_ratio') * h)
|
| 172 |
+
|
| 173 |
+
if 'crop_size_w' in self.opt['val']:
|
| 174 |
+
crop_size_w = self.opt['val'].get('crop_size_w')
|
| 175 |
+
else:
|
| 176 |
+
crop_size_w = int(self.opt['val'].get('crop_size_w_ratio') * w)
|
| 177 |
+
|
| 178 |
+
crop_size_h, crop_size_w = crop_size_h // self.scale * self.scale, crop_size_w // self.scale * self.scale
|
| 179 |
+
|
| 180 |
+
for cnt, each_idx in enumerate(self.idxes):
|
| 181 |
+
i = each_idx['i']
|
| 182 |
+
j = each_idx['j']
|
| 183 |
+
preds[0, :, i: i + crop_size_h, j: j + crop_size_w] += self.outs[cnt]
|
| 184 |
+
count_mt[0, 0, i: i + crop_size_h, j: j + crop_size_w] += 1.
|
| 185 |
+
|
| 186 |
+
self.output = (preds / count_mt).to(self.device)
|
| 187 |
+
self.lq = self.origin_lq
|
| 188 |
+
|
| 189 |
+
def optimize_parameters(self, current_iter, tb_logger):
|
| 190 |
+
self.optimizer_g.zero_grad()
|
| 191 |
+
|
| 192 |
+
if self.opt['train'].get('mixup', False):
|
| 193 |
+
self.mixup_aug()
|
| 194 |
+
|
| 195 |
+
preds = self.net_g(self.lq)
|
| 196 |
+
if not isinstance(preds, list):
|
| 197 |
+
preds = [preds]
|
| 198 |
+
|
| 199 |
+
self.output = preds[-1]
|
| 200 |
+
|
| 201 |
+
l_total = 0
|
| 202 |
+
loss_dict = OrderedDict()
|
| 203 |
+
# pixel loss
|
| 204 |
+
if self.cri_pix:
|
| 205 |
+
l_pix = 0.
|
| 206 |
+
for pred in preds:
|
| 207 |
+
l_pix += self.cri_pix(pred, self.gt)
|
| 208 |
+
|
| 209 |
+
# print('l pix ... ', l_pix)
|
| 210 |
+
l_total += l_pix
|
| 211 |
+
loss_dict['l_pix'] = l_pix
|
| 212 |
+
|
| 213 |
+
# perceptual loss
|
| 214 |
+
if self.cri_perceptual:
|
| 215 |
+
l_percep, l_style = self.cri_perceptual(self.output, self.gt)
|
| 216 |
+
#
|
| 217 |
+
if l_percep is not None:
|
| 218 |
+
l_total += l_percep
|
| 219 |
+
loss_dict['l_percep'] = l_percep
|
| 220 |
+
if l_style is not None:
|
| 221 |
+
l_total += l_style
|
| 222 |
+
loss_dict['l_style'] = l_style
|
| 223 |
+
|
| 224 |
+
|
| 225 |
+
l_total = l_total + 0. * sum(p.sum() for p in self.net_g.parameters())
|
| 226 |
+
|
| 227 |
+
l_total.backward()
|
| 228 |
+
use_grad_clip = self.opt['train'].get('use_grad_clip', True)
|
| 229 |
+
if use_grad_clip:
|
| 230 |
+
torch.nn.utils.clip_grad_norm_(self.net_g.parameters(), 0.01)
|
| 231 |
+
self.optimizer_g.step()
|
| 232 |
+
|
| 233 |
+
|
| 234 |
+
self.log_dict = self.reduce_loss_dict(loss_dict)
|
| 235 |
+
|
| 236 |
+
def test(self):
|
| 237 |
+
self.net_g.eval()
|
| 238 |
+
with torch.no_grad():
|
| 239 |
+
n = len(self.lq)
|
| 240 |
+
outs = []
|
| 241 |
+
m = self.opt['val'].get('max_minibatch', n)
|
| 242 |
+
i = 0
|
| 243 |
+
while i < n:
|
| 244 |
+
j = i + m
|
| 245 |
+
if j >= n:
|
| 246 |
+
j = n
|
| 247 |
+
pred = self.net_g(self.lq[i:j])
|
| 248 |
+
if isinstance(pred, list):
|
| 249 |
+
pred = pred[-1]
|
| 250 |
+
outs.append(pred.detach().cpu())
|
| 251 |
+
i = j
|
| 252 |
+
|
| 253 |
+
self.output = torch.cat(outs, dim=0)
|
| 254 |
+
self.net_g.train()
|
| 255 |
+
|
| 256 |
+
def dist_validation(self, dataloader, current_iter, tb_logger, save_img, rgb2bgr, use_image):
|
| 257 |
+
dataset_name = dataloader.dataset.opt['name']
|
| 258 |
+
with_metrics = self.opt['val'].get('metrics') is not None
|
| 259 |
+
if with_metrics:
|
| 260 |
+
self.metric_results = {
|
| 261 |
+
metric: 0
|
| 262 |
+
for metric in self.opt['val']['metrics'].keys()
|
| 263 |
+
}
|
| 264 |
+
|
| 265 |
+
rank, world_size = get_dist_info()
|
| 266 |
+
if rank == 0:
|
| 267 |
+
pbar = tqdm(total=len(dataloader), unit='image')
|
| 268 |
+
|
| 269 |
+
cnt = 0
|
| 270 |
+
|
| 271 |
+
for idx, val_data in enumerate(dataloader):
|
| 272 |
+
if idx % world_size != rank:
|
| 273 |
+
continue
|
| 274 |
+
|
| 275 |
+
img_name = osp.splitext(osp.basename(val_data['lq_path'][0]))[0]
|
| 276 |
+
|
| 277 |
+
self.feed_data(val_data, is_val=True)
|
| 278 |
+
if self.opt['val'].get('grids', False):
|
| 279 |
+
self.grids()
|
| 280 |
+
|
| 281 |
+
self.test()
|
| 282 |
+
|
| 283 |
+
if self.opt['val'].get('grids', False):
|
| 284 |
+
self.grids_inverse()
|
| 285 |
+
|
| 286 |
+
visuals = self.get_current_visuals()
|
| 287 |
+
sr_img = tensor2img([visuals['result']], rgb2bgr=rgb2bgr)
|
| 288 |
+
if 'gt' in visuals:
|
| 289 |
+
gt_img = tensor2img([visuals['gt']], rgb2bgr=rgb2bgr)
|
| 290 |
+
del self.gt
|
| 291 |
+
|
| 292 |
+
# tentative for out of GPU memory
|
| 293 |
+
del self.lq
|
| 294 |
+
del self.output
|
| 295 |
+
torch.cuda.empty_cache()
|
| 296 |
+
|
| 297 |
+
if save_img:
|
| 298 |
+
if sr_img.shape[2] == 6:
|
| 299 |
+
L_img = sr_img[:, :, :3]
|
| 300 |
+
R_img = sr_img[:, :, 3:]
|
| 301 |
+
|
| 302 |
+
# visual_dir = osp.join('visual_results', dataset_name, self.opt['name'])
|
| 303 |
+
visual_dir = osp.join(self.opt['path']['visualization'], dataset_name)
|
| 304 |
+
|
| 305 |
+
imwrite(L_img, osp.join(visual_dir, f'{img_name}_L.png'))
|
| 306 |
+
imwrite(R_img, osp.join(visual_dir, f'{img_name}_R.png'))
|
| 307 |
+
else:
|
| 308 |
+
if self.opt['is_train']:
|
| 309 |
+
|
| 310 |
+
save_img_path = osp.join(self.opt['path']['visualization'],
|
| 311 |
+
img_name,
|
| 312 |
+
f'{img_name}_{current_iter}.png')
|
| 313 |
+
|
| 314 |
+
save_gt_img_path = osp.join(self.opt['path']['visualization'],
|
| 315 |
+
img_name,
|
| 316 |
+
f'{img_name}_{current_iter}_gt.png')
|
| 317 |
+
else:
|
| 318 |
+
save_img_path = osp.join(
|
| 319 |
+
self.opt['path']['visualization'], dataset_name,
|
| 320 |
+
f'{img_name}.png')
|
| 321 |
+
save_gt_img_path = osp.join(
|
| 322 |
+
self.opt['path']['visualization'], dataset_name,
|
| 323 |
+
f'{img_name}_gt.png')
|
| 324 |
+
|
| 325 |
+
imwrite(sr_img, save_img_path)
|
| 326 |
+
imwrite(gt_img, save_gt_img_path)
|
| 327 |
+
|
| 328 |
+
if with_metrics:
|
| 329 |
+
# calculate metrics
|
| 330 |
+
opt_metric = deepcopy(self.opt['val']['metrics'])
|
| 331 |
+
if use_image:
|
| 332 |
+
for name, opt_ in opt_metric.items():
|
| 333 |
+
metric_type = opt_.pop('type')
|
| 334 |
+
self.metric_results[name] += getattr(
|
| 335 |
+
metric_module, metric_type)(sr_img, gt_img, **opt_)
|
| 336 |
+
else:
|
| 337 |
+
for name, opt_ in opt_metric.items():
|
| 338 |
+
metric_type = opt_.pop('type')
|
| 339 |
+
self.metric_results[name] += getattr(
|
| 340 |
+
metric_module, metric_type)(visuals['result'], visuals['gt'], **opt_)
|
| 341 |
+
|
| 342 |
+
cnt += 1
|
| 343 |
+
if rank == 0:
|
| 344 |
+
for _ in range(world_size):
|
| 345 |
+
pbar.update(1)
|
| 346 |
+
pbar.set_description(f'Test {img_name}')
|
| 347 |
+
if rank == 0:
|
| 348 |
+
pbar.close()
|
| 349 |
+
|
| 350 |
+
# current_metric = 0.
|
| 351 |
+
collected_metrics = OrderedDict()
|
| 352 |
+
if with_metrics:
|
| 353 |
+
for metric in self.metric_results.keys():
|
| 354 |
+
collected_metrics[metric] = torch.tensor(self.metric_results[metric]).float().to(self.device)
|
| 355 |
+
collected_metrics['cnt'] = torch.tensor(cnt).float().to(self.device)
|
| 356 |
+
|
| 357 |
+
self.collected_metrics = collected_metrics
|
| 358 |
+
|
| 359 |
+
keys = []
|
| 360 |
+
metrics = []
|
| 361 |
+
for name, value in self.collected_metrics.items():
|
| 362 |
+
keys.append(name)
|
| 363 |
+
metrics.append(value)
|
| 364 |
+
metrics = torch.stack(metrics, 0)
|
| 365 |
+
torch.distributed.reduce(metrics, dst=0)
|
| 366 |
+
if self.opt['rank'] == 0:
|
| 367 |
+
metrics_dict = {}
|
| 368 |
+
cnt = 0
|
| 369 |
+
for key, metric in zip(keys, metrics):
|
| 370 |
+
if key == 'cnt':
|
| 371 |
+
cnt = float(metric)
|
| 372 |
+
continue
|
| 373 |
+
metrics_dict[key] = float(metric)
|
| 374 |
+
|
| 375 |
+
for key in metrics_dict:
|
| 376 |
+
metrics_dict[key] /= cnt
|
| 377 |
+
|
| 378 |
+
self._log_validation_metric_values(current_iter, dataloader.dataset.opt['name'],
|
| 379 |
+
tb_logger, metrics_dict)
|
| 380 |
+
return 0.
|
| 381 |
+
|
| 382 |
+
def nondist_validation(self, *args, **kwargs):
|
| 383 |
+
logger = get_root_logger()
|
| 384 |
+
logger.warning('nondist_validation is not implemented. Run dist_validation.')
|
| 385 |
+
self.dist_validation(*args, **kwargs)
|
| 386 |
+
|
| 387 |
+
|
| 388 |
+
def _log_validation_metric_values(self, current_iter, dataset_name,
|
| 389 |
+
tb_logger, metric_dict):
|
| 390 |
+
log_str = f'Validation {dataset_name}, \t'
|
| 391 |
+
for metric, value in metric_dict.items():
|
| 392 |
+
log_str += f'\t # {metric}: {value:.4f}'
|
| 393 |
+
logger = get_root_logger()
|
| 394 |
+
logger.info(log_str)
|
| 395 |
+
|
| 396 |
+
log_dict = OrderedDict()
|
| 397 |
+
# for name, value in loss_dict.items():
|
| 398 |
+
for metric, value in metric_dict.items():
|
| 399 |
+
log_dict[f'm_{metric}'] = value
|
| 400 |
+
|
| 401 |
+
self.log_dict = log_dict
|
| 402 |
+
|
| 403 |
+
def get_current_visuals(self):
|
| 404 |
+
out_dict = OrderedDict()
|
| 405 |
+
out_dict['lq'] = self.lq.detach().cpu()
|
| 406 |
+
out_dict['result'] = self.output.detach().cpu()
|
| 407 |
+
if hasattr(self, 'gt'):
|
| 408 |
+
out_dict['gt'] = self.gt.detach().cpu()
|
| 409 |
+
return out_dict
|
| 410 |
+
|
| 411 |
+
def save(self, epoch, current_iter):
|
| 412 |
+
self.save_network(self.net_g, 'net_g', current_iter)
|
| 413 |
+
self.save_training_state(epoch, current_iter)
|
basicsr/models/losses/SWT.py
ADDED
|
@@ -0,0 +1,428 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pywt
|
| 2 |
+
import torch
|
| 3 |
+
|
| 4 |
+
import matplotlib.pyplot as plt
|
| 5 |
+
import numpy as np
|
| 6 |
+
import torch.nn as nn
|
| 7 |
+
import torch.nn.functional as F
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
def reflect(x, minx, maxx):
|
| 11 |
+
"""Reflect the values in matrix *x* about the scalar values *minx* and
|
| 12 |
+
*maxx*. Hence a vector *x* containing a long linearly increasing series is
|
| 13 |
+
converted into a waveform which ramps linearly up and down between *minx*
|
| 14 |
+
and *maxx*. If *x* contains integers and *minx* and *maxx* are (integers +
|
| 15 |
+
0.5), the ramps will have repeated max and min samples.
|
| 16 |
+
.. codeauthor:: Rich Wareham <rjw57@cantab.net>, Aug 2013
|
| 17 |
+
.. codeauthor:: Nick Kingsbury, Cambridge University, January 1999.
|
| 18 |
+
"""
|
| 19 |
+
x = np.asanyarray(x)
|
| 20 |
+
rng = maxx - minx
|
| 21 |
+
rng_by_2 = 2 * rng
|
| 22 |
+
mod = np.fmod(x - minx, rng_by_2)
|
| 23 |
+
normed_mod = np.where(mod < 0, mod + rng_by_2, mod)
|
| 24 |
+
out = np.where(normed_mod >= rng, rng_by_2 - normed_mod, normed_mod) + minx
|
| 25 |
+
return np.array(out, dtype=x.dtype)
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
def mypad(x, pad, mode='constant', value=0):
|
| 29 |
+
""" Function to do numpy like padding on tensors. Only works for 2-D
|
| 30 |
+
padding.
|
| 31 |
+
Inputs:
|
| 32 |
+
x (tensor): tensor to pad
|
| 33 |
+
pad (tuple): tuple of (left, right, top, bottom) pad sizes
|
| 34 |
+
mode (str): 'symmetric', 'wrap', 'constant, 'reflect', 'replicate', or
|
| 35 |
+
'zero'. The padding technique.
|
| 36 |
+
"""
|
| 37 |
+
if mode == 'symmetric':
|
| 38 |
+
if pad[0] == 0 and pad[1] == 0:
|
| 39 |
+
m1, m2 = pad[2], pad[3]
|
| 40 |
+
l = x.shape[-2]
|
| 41 |
+
xe = reflect(np.arange(-m1, l + m2, dtype='int32'), -0.5, l - 0.5)
|
| 42 |
+
return x[:, :, xe]
|
| 43 |
+
elif pad[2] == 0 and pad[3] == 0:
|
| 44 |
+
m1, m2 = pad[0], pad[1]
|
| 45 |
+
l = x.shape[-1]
|
| 46 |
+
xe = reflect(np.arange(-m1, l + m2, dtype='int32'), -0.5, l - 0.5)
|
| 47 |
+
return x[:, :, :, xe]
|
| 48 |
+
else:
|
| 49 |
+
m1, m2 = pad[0], pad[1]
|
| 50 |
+
l1 = x.shape[-1]
|
| 51 |
+
xe_row = reflect(np.arange(-m1, l1 + m2, dtype='int32'), -0.5, l1 - 0.5)
|
| 52 |
+
m1, m2 = pad[2], pad[3]
|
| 53 |
+
l2 = x.shape[-2]
|
| 54 |
+
xe_col = reflect(np.arange(-m1, l2 + m2, dtype='int32'), -0.5, l2 - 0.5)
|
| 55 |
+
i = np.outer(xe_col, np.ones(xe_row.shape[0]))
|
| 56 |
+
j = np.outer(np.ones(xe_col.shape[0]), xe_row)
|
| 57 |
+
return x[:, :, i, j]
|
| 58 |
+
elif mode == 'periodic':
|
| 59 |
+
if pad[0] == 0 and pad[1] == 0:
|
| 60 |
+
xe = np.arange(x.shape[-2])
|
| 61 |
+
xe = np.pad(xe, (pad[2], pad[3]), mode='wrap')
|
| 62 |
+
return x[:, :, xe]
|
| 63 |
+
elif pad[2] == 0 and pad[3] == 0:
|
| 64 |
+
xe = np.arange(x.shape[-1])
|
| 65 |
+
xe = np.pad(xe, (pad[0], pad[1]), mode='wrap')
|
| 66 |
+
return x[:, :, :, xe]
|
| 67 |
+
else:
|
| 68 |
+
xe_col = np.arange(x.shape[-2])
|
| 69 |
+
xe_col = np.pad(xe_col, (pad[2], pad[3]), mode='wrap')
|
| 70 |
+
xe_row = np.arange(x.shape[-1])
|
| 71 |
+
xe_row = np.pad(xe_row, (pad[0], pad[1]), mode='wrap')
|
| 72 |
+
i = np.outer(xe_col, np.ones(xe_row.shape[0]))
|
| 73 |
+
j = np.outer(np.ones(xe_col.shape[0]), xe_row)
|
| 74 |
+
return x[:, :, i, j]
|
| 75 |
+
|
| 76 |
+
elif mode == 'constant' or mode == 'reflect' or mode == 'replicate':
|
| 77 |
+
return F.pad(x, pad, mode, value)
|
| 78 |
+
elif mode == 'zero':
|
| 79 |
+
return F.pad(x, pad)
|
| 80 |
+
else:
|
| 81 |
+
raise ValueError("Unkown pad type: {}".format(mode))
|
| 82 |
+
|
| 83 |
+
|
| 84 |
+
def prep_filt_afb2d(h0_col, h1_col, h0_row=None, h1_row=None, device=None):
|
| 85 |
+
"""
|
| 86 |
+
Prepares the filters to be of the right form for the afb2d function. In
|
| 87 |
+
particular, makes the tensors the right shape. It takes mirror images of
|
| 88 |
+
them as as afb2d uses conv2d which acts like normal correlation.
|
| 89 |
+
Inputs:
|
| 90 |
+
h0_col (array-like): low pass column filter bank
|
| 91 |
+
h1_col (array-like): high pass column filter bank
|
| 92 |
+
h0_row (array-like): low pass row filter bank. If none, will assume the
|
| 93 |
+
same as column filter
|
| 94 |
+
h1_row (array-like): high pass row filter bank. If none, will assume the
|
| 95 |
+
same as column filter
|
| 96 |
+
device: which device to put the tensors on to
|
| 97 |
+
Returns:
|
| 98 |
+
(h0_col, h1_col, h0_row, h1_row)
|
| 99 |
+
"""
|
| 100 |
+
h0_col = np.array(h0_col[::-1]).ravel()
|
| 101 |
+
h1_col = np.array(h1_col[::-1]).ravel()
|
| 102 |
+
t = torch.get_default_dtype()
|
| 103 |
+
if h0_row is None:
|
| 104 |
+
h0_row = h0_col
|
| 105 |
+
else:
|
| 106 |
+
h0_row = np.array(h0_row[::-1]).ravel()
|
| 107 |
+
if h1_row is None:
|
| 108 |
+
h1_row = h1_col
|
| 109 |
+
else:
|
| 110 |
+
h1_row = np.array(h1_row[::-1]).ravel()
|
| 111 |
+
h0_col = torch.tensor(h0_col, device=device, dtype=t).reshape((1, 1, -1, 1))
|
| 112 |
+
h1_col = torch.tensor(h1_col, device=device, dtype=t).reshape((1, 1, -1, 1))
|
| 113 |
+
h0_row = torch.tensor(h0_row, device=device, dtype=t).reshape((1, 1, 1, -1))
|
| 114 |
+
h1_row = torch.tensor(h1_row, device=device, dtype=t).reshape((1, 1, 1, -1))
|
| 115 |
+
|
| 116 |
+
return h0_col, h1_col, h0_row, h1_row
|
| 117 |
+
|
| 118 |
+
|
| 119 |
+
def prep_filt_sfb2d(g0_col, g1_col, g0_row=None, g1_row=None, device=None):
|
| 120 |
+
"""
|
| 121 |
+
Prepares the filters to be of the right form for the sfb2d function. In
|
| 122 |
+
particular, makes the tensors the right shape. It does not mirror image them
|
| 123 |
+
as as sfb2d uses conv2d_transpose which acts like normal convolution.
|
| 124 |
+
Inputs:
|
| 125 |
+
g0_col (array-like): low pass column filter bank
|
| 126 |
+
g1_col (array-like): high pass column filter bank
|
| 127 |
+
g0_row (array-like): low pass row filter bank. If none, will assume the
|
| 128 |
+
same as column filter
|
| 129 |
+
g1_row (array-like): high pass row filter bank. If none, will assume the
|
| 130 |
+
same as column filter
|
| 131 |
+
device: which device to put the tensors on to
|
| 132 |
+
Returns:
|
| 133 |
+
(g0_col, g1_col, g0_row, g1_row)
|
| 134 |
+
"""
|
| 135 |
+
g0_col = np.array(g0_col).ravel()
|
| 136 |
+
g1_col = np.array(g1_col).ravel()
|
| 137 |
+
t = torch.get_default_dtype()
|
| 138 |
+
if g0_row is None:
|
| 139 |
+
g0_row = g0_col
|
| 140 |
+
if g1_row is None:
|
| 141 |
+
g1_row = g1_col
|
| 142 |
+
g0_col = torch.tensor(g0_col, device=device, dtype=t).reshape((1, 1, -1, 1))
|
| 143 |
+
g1_col = torch.tensor(g1_col, device=device, dtype=t).reshape((1, 1, -1, 1))
|
| 144 |
+
g0_row = torch.tensor(g0_row, device=device, dtype=t).reshape((1, 1, 1, -1))
|
| 145 |
+
g1_row = torch.tensor(g1_row, device=device, dtype=t).reshape((1, 1, 1, -1))
|
| 146 |
+
|
| 147 |
+
return g0_col, g1_col, g0_row, g1_row
|
| 148 |
+
|
| 149 |
+
|
| 150 |
+
def afb1d_atrous(x, h0, h1, mode='symmetric', dim=-1, dilation=1):
|
| 151 |
+
""" 1D analysis filter bank (along one dimension only) of an image without
|
| 152 |
+
downsampling. Does the a trous algorithm.
|
| 153 |
+
Inputs:
|
| 154 |
+
x (tensor): 4D input with the last two dimensions the spatial input
|
| 155 |
+
h0 (tensor): 4D input for the lowpass filter. Should have shape (1, 1,
|
| 156 |
+
h, 1) or (1, 1, 1, w)
|
| 157 |
+
h1 (tensor): 4D input for the highpass filter. Should have shape (1, 1,
|
| 158 |
+
h, 1) or (1, 1, 1, w)
|
| 159 |
+
mode (str): padding method
|
| 160 |
+
dim (int) - dimension of filtering. d=2 is for a vertical filter (called
|
| 161 |
+
column filtering but filters across the rows). d=3 is for a
|
| 162 |
+
horizontal filter, (called row filtering but filters across the
|
| 163 |
+
columns).
|
| 164 |
+
dilation (int): dilation factor. Should be a power of 2.
|
| 165 |
+
Returns:
|
| 166 |
+
lohi: lowpass and highpass subbands concatenated along the channel
|
| 167 |
+
dimension
|
| 168 |
+
"""
|
| 169 |
+
C = x.shape[1]
|
| 170 |
+
d = dim % 4
|
| 171 |
+
if not isinstance(h0, torch.Tensor):
|
| 172 |
+
h0 = torch.tensor(np.copy(np.array(h0).ravel()[::-1]),
|
| 173 |
+
dtype=torch.float, device=x.device)
|
| 174 |
+
if not isinstance(h1, torch.Tensor):
|
| 175 |
+
h1 = torch.tensor(np.copy(np.array(h1).ravel()[::-1]),
|
| 176 |
+
dtype=torch.float, device=x.device)
|
| 177 |
+
L = h0.numel()
|
| 178 |
+
shape = [1, 1, 1, 1]
|
| 179 |
+
shape[d] = L
|
| 180 |
+
if h0.shape != tuple(shape):
|
| 181 |
+
h0 = h0.reshape(*shape)
|
| 182 |
+
if h1.shape != tuple(shape):
|
| 183 |
+
h1 = h1.reshape(*shape)
|
| 184 |
+
h = torch.cat([h0, h1] * C, dim=0)
|
| 185 |
+
|
| 186 |
+
L2 = (L * dilation) // 2
|
| 187 |
+
pad = (0, 0, L2 - dilation, L2) if d == 2 else (L2 - dilation, L2, 0, 0)
|
| 188 |
+
x = mypad(x, pad=pad, mode=mode)
|
| 189 |
+
lohi = F.conv2d(x, h, groups=C, dilation=dilation)
|
| 190 |
+
|
| 191 |
+
return lohi
|
| 192 |
+
|
| 193 |
+
|
| 194 |
+
def afb2d_atrous(x, filts, mode='symmetric', dilation=1):
|
| 195 |
+
""" Does a single level 2d wavelet decomposition of an input. Does separate
|
| 196 |
+
row and column filtering by two calls to `afb1d_atrous`
|
| 197 |
+
Inputs:
|
| 198 |
+
x (torch.Tensor): Input to decompose
|
| 199 |
+
filts (list of ndarray or torch.Tensor): If a list of tensors has been
|
| 200 |
+
given, this function assumes they are in the right form (the form
|
| 201 |
+
returned by `prep_filt_afb2d`).
|
| 202 |
+
Otherwise, this function will prepare the filters to be of the right
|
| 203 |
+
form by calling `prep_filt_afb2d`.
|
| 204 |
+
mode (str): 'zero', 'symmetric', 'reflect' or 'periodization'. Which
|
| 205 |
+
padding to use. If periodization, the output size will be half the
|
| 206 |
+
input size. Otherwise, the output size will be slightly larger than
|
| 207 |
+
half.
|
| 208 |
+
dilation (int): dilation factor for the filters. Should be 2**level
|
| 209 |
+
Returns:
|
| 210 |
+
y: Tensor of shape (N, C, 4, H, W)
|
| 211 |
+
"""
|
| 212 |
+
tensorize = [not isinstance(f, torch.Tensor) for f in filts]
|
| 213 |
+
if len(filts) == 2:
|
| 214 |
+
h0, h1 = filts
|
| 215 |
+
if True in tensorize:
|
| 216 |
+
h0_col, h1_col, h0_row, h1_row = prep_filt_afb2d(
|
| 217 |
+
h0, h1, device=x.device)
|
| 218 |
+
else:
|
| 219 |
+
h0_col = h0
|
| 220 |
+
h0_row = h0.transpose(2, 3)
|
| 221 |
+
h1_col = h1
|
| 222 |
+
h1_row = h1.transpose(2, 3)
|
| 223 |
+
elif len(filts) == 4:
|
| 224 |
+
if True in tensorize:
|
| 225 |
+
h0_col, h1_col, h0_row, h1_row = prep_filt_afb2d(
|
| 226 |
+
*filts, device=x.device)
|
| 227 |
+
else:
|
| 228 |
+
h0_col, h1_col, h0_row, h1_row = filts
|
| 229 |
+
else:
|
| 230 |
+
raise ValueError("Unknown form for input filts")
|
| 231 |
+
|
| 232 |
+
lohi = afb1d_atrous(x, h0_row, h1_row, mode=mode, dim=3, dilation=dilation)
|
| 233 |
+
y = afb1d_atrous(lohi, h0_col, h1_col, mode=mode, dim=2, dilation=dilation)
|
| 234 |
+
|
| 235 |
+
return y
|
| 236 |
+
|
| 237 |
+
|
| 238 |
+
def sfb1d_atrous(lo, hi, g0, g1, mode='symmetric', dim=-1, dilation=1,
|
| 239 |
+
pad1=None, pad=None):
|
| 240 |
+
""" 1D synthesis filter bank of an image tensor with no upsampling. Used for
|
| 241 |
+
the stationary wavelet transform.
|
| 242 |
+
"""
|
| 243 |
+
C = lo.shape[1]
|
| 244 |
+
d = dim % 4
|
| 245 |
+
if not isinstance(g0, torch.Tensor):
|
| 246 |
+
g0 = torch.tensor(np.copy(np.array(g0).ravel()),
|
| 247 |
+
dtype=torch.float, device=lo.device)
|
| 248 |
+
if not isinstance(g1, torch.Tensor):
|
| 249 |
+
g1 = torch.tensor(np.copy(np.array(g1).ravel()),
|
| 250 |
+
dtype=torch.float, device=lo.device)
|
| 251 |
+
L = g0.numel()
|
| 252 |
+
shape = [1, 1, 1, 1]
|
| 253 |
+
shape[d] = L
|
| 254 |
+
if g0.shape != tuple(shape):
|
| 255 |
+
g0 = g0.reshape(*shape)
|
| 256 |
+
if g1.shape != tuple(shape):
|
| 257 |
+
g1 = g1.reshape(*shape)
|
| 258 |
+
g0 = torch.cat([g0] * C, dim=0)
|
| 259 |
+
g1 = torch.cat([g1] * C, dim=0)
|
| 260 |
+
|
| 261 |
+
centre = L / 2
|
| 262 |
+
fsz = (L - 1) * dilation + 1
|
| 263 |
+
newcentre = fsz / 2
|
| 264 |
+
before = newcentre - dilation * centre
|
| 265 |
+
|
| 266 |
+
short_offset = dilation - 1
|
| 267 |
+
centre_offset = fsz % 2
|
| 268 |
+
a = fsz // 2
|
| 269 |
+
b = fsz // 2 + (fsz + 1) % 2
|
| 270 |
+
|
| 271 |
+
pad = (0, 0, b, a) if d == 2 else (b, a, 0, 0)
|
| 272 |
+
lo = mypad(lo, pad=pad, mode=mode)
|
| 273 |
+
hi = mypad(hi, pad=pad, mode=mode)
|
| 274 |
+
|
| 275 |
+
unpad = (fsz, 0) if d == 2 else (0, fsz)
|
| 276 |
+
|
| 277 |
+
y = F.conv_transpose2d(lo, g0, padding=unpad, groups=C, dilation=dilation) + \
|
| 278 |
+
F.conv_transpose2d(hi, g1, padding=unpad, groups=C, dilation=dilation)
|
| 279 |
+
|
| 280 |
+
return y / (2 * dilation)
|
| 281 |
+
|
| 282 |
+
|
| 283 |
+
def sfb2d_atrous(ll, lh, hl, hh, filts, mode='symmetric'):
|
| 284 |
+
""" Does a single level 2d wavelet reconstruction of wavelet coefficients.
|
| 285 |
+
Does separate row and column filtering by two calls to `sfb1d_atrous`
|
| 286 |
+
Inputs:
|
| 287 |
+
ll (torch.Tensor): lowpass coefficients
|
| 288 |
+
lh (torch.Tensor): horizontal coefficients
|
| 289 |
+
hl (torch.Tensor): vertical coefficients
|
| 290 |
+
hh (torch.Tensor): diagonal coefficients
|
| 291 |
+
filts (list of ndarray or torch.Tensor): If a list of tensors has been
|
| 292 |
+
given, this function assumes they are in the right form (the form
|
| 293 |
+
returned by `prep_filt_sfb2d`).
|
| 294 |
+
Otherwise, this function will prepare the filters to be of the right
|
| 295 |
+
form by calling `prep_filt_sfb2d`.
|
| 296 |
+
mode (str): 'zero', 'symmetric', 'reflect' or 'periodization'. Which
|
| 297 |
+
padding to use. If periodization, the output size will be half the
|
| 298 |
+
input size. Otherwise, the output size will be slightly larger than
|
| 299 |
+
half.
|
| 300 |
+
"""
|
| 301 |
+
tensorize = [not isinstance(x, torch.Tensor) for x in filts]
|
| 302 |
+
if len(filts) == 2:
|
| 303 |
+
g0, g1 = filts
|
| 304 |
+
if True in tensorize:
|
| 305 |
+
g0_col, g1_col, g0_row, g1_row = prep_filt_sfb2d(g0, g1)
|
| 306 |
+
else:
|
| 307 |
+
g0_col = g0
|
| 308 |
+
g0_row = g0.transpose(2, 3)
|
| 309 |
+
g1_col = g1
|
| 310 |
+
g1_row = g1.transpose(2, 3)
|
| 311 |
+
elif len(filts) == 4:
|
| 312 |
+
if True in tensorize:
|
| 313 |
+
g0_col, g1_col, g0_row, g1_row = prep_filt_sfb2d(*filts)
|
| 314 |
+
else:
|
| 315 |
+
g0_col, g1_col, g0_row, g1_row = filts
|
| 316 |
+
else:
|
| 317 |
+
raise ValueError("Unknown form for input filts")
|
| 318 |
+
|
| 319 |
+
lo = sfb1d_atrous(ll, lh, g0_col, g1_col, mode=mode, dim=2)
|
| 320 |
+
hi = sfb1d_atrous(hl, hh, g0_col, g1_col, mode=mode, dim=2)
|
| 321 |
+
y = sfb1d_atrous(lo, hi, g0_row, g1_row, mode=mode, dim=3)
|
| 322 |
+
|
| 323 |
+
return y
|
| 324 |
+
|
| 325 |
+
|
| 326 |
+
class SWTForward(nn.Module):
|
| 327 |
+
""" Performs a 2d Stationary wavelet transform (or undecimated wavelet
|
| 328 |
+
transform) of an image
|
| 329 |
+
Args:
|
| 330 |
+
J (int): Number of levels of decomposition
|
| 331 |
+
wave (str or pywt.Wavelet): Which wavelet to use. Can be a string to
|
| 332 |
+
pass to pywt.Wavelet constructor, can also be a pywt.Wavelet class,
|
| 333 |
+
or can be a two tuple of array-like objects for the analysis low and
|
| 334 |
+
high pass filters.
|
| 335 |
+
mode (str): 'zero', 'symmetric', 'reflect' or 'periodization'. The
|
| 336 |
+
padding scheme. PyWavelets uses only periodization so we use this
|
| 337 |
+
as our default scheme.
|
| 338 |
+
"""
|
| 339 |
+
|
| 340 |
+
def __init__(self, J=1, wave='db1', mode='symmetric'):
|
| 341 |
+
super().__init__()
|
| 342 |
+
if isinstance(wave, str):
|
| 343 |
+
wave = pywt.Wavelet(wave)
|
| 344 |
+
if isinstance(wave, pywt.Wavelet):
|
| 345 |
+
h0_col, h1_col = wave.dec_lo, wave.dec_hi
|
| 346 |
+
h0_row, h1_row = h0_col, h1_col
|
| 347 |
+
else:
|
| 348 |
+
if len(wave) == 2:
|
| 349 |
+
h0_col, h1_col = wave[0], wave[1]
|
| 350 |
+
h0_row, h1_row = h0_col, h1_col
|
| 351 |
+
elif len(wave) == 4:
|
| 352 |
+
h0_col, h1_col = wave[0], wave[1]
|
| 353 |
+
h0_row, h1_row = wave[2], wave[3]
|
| 354 |
+
|
| 355 |
+
filts = prep_filt_afb2d(h0_col, h1_col, h0_row, h1_row)
|
| 356 |
+
self.h0_col = nn.Parameter(filts[0], requires_grad=False)
|
| 357 |
+
self.h1_col = nn.Parameter(filts[1], requires_grad=False)
|
| 358 |
+
self.h0_row = nn.Parameter(filts[2], requires_grad=False)
|
| 359 |
+
self.h1_row = nn.Parameter(filts[3], requires_grad=False)
|
| 360 |
+
|
| 361 |
+
self.J = J
|
| 362 |
+
self.mode = mode
|
| 363 |
+
|
| 364 |
+
def forward(self, x):
|
| 365 |
+
""" Forward pass of the SWT.
|
| 366 |
+
Args:
|
| 367 |
+
x (tensor): Input of shape :math:`(N, C_{in}, H_{in}, W_{in})`
|
| 368 |
+
Returns:
|
| 369 |
+
List of coefficients for each scale. Each coefficient has
|
| 370 |
+
shape :math:`(N, C_{in}, 4, H_{in}, W_{in})` where the extra
|
| 371 |
+
dimension stores the 4 subbands for each scale. The ordering in
|
| 372 |
+
these 4 coefficients is: (A, H, V, D) or (ll, lh, hl, hh).
|
| 373 |
+
"""
|
| 374 |
+
ll = x
|
| 375 |
+
coeffs = []
|
| 376 |
+
filts = (self.h0_col, self.h1_col, self.h0_row, self.h1_row)
|
| 377 |
+
for j in range(self.J):
|
| 378 |
+
y = afb2d_atrous(ll, filts, self.mode)
|
| 379 |
+
coeffs.append(y)
|
| 380 |
+
ll = y[:, 0:1, :, :]
|
| 381 |
+
|
| 382 |
+
return coeffs
|
| 383 |
+
|
| 384 |
+
|
| 385 |
+
class SWTInverse(nn.Module):
|
| 386 |
+
""" Performs a 2d DWT Inverse reconstruction of an image
|
| 387 |
+
Args:
|
| 388 |
+
wave (str or pywt.Wavelet): Which wavelet to use
|
| 389 |
+
C: deprecated, will be removed in future
|
| 390 |
+
"""
|
| 391 |
+
|
| 392 |
+
def __init__(self, wave='db1', mode='symmetric'):
|
| 393 |
+
super().__init__()
|
| 394 |
+
if isinstance(wave, str):
|
| 395 |
+
wave = pywt.Wavelet(wave)
|
| 396 |
+
if isinstance(wave, pywt.Wavelet):
|
| 397 |
+
g0_col, g1_col = wave.rec_lo, wave.rec_hi
|
| 398 |
+
g0_row, g1_row = g0_col, g1_col
|
| 399 |
+
else:
|
| 400 |
+
if len(wave) == 2:
|
| 401 |
+
g0_col, g1_col = wave[0], wave[1]
|
| 402 |
+
g0_row, g1_row = g0_col, g1_col
|
| 403 |
+
elif len(wave) == 4:
|
| 404 |
+
g0_col, g1_col = wave[0], wave[1]
|
| 405 |
+
g0_row, g1_row = wave[2], wave[3]
|
| 406 |
+
|
| 407 |
+
filts = prep_filt_sfb2d(g0_col, g1_col, g0_row, g1_row)
|
| 408 |
+
self.g0_col = nn.Parameter(filts[0], requires_grad=False)
|
| 409 |
+
self.g1_col = nn.Parameter(filts[1], requires_grad=False)
|
| 410 |
+
self.g0_row = nn.Parameter(filts[2], requires_grad=False)
|
| 411 |
+
self.g1_row = nn.Parameter(filts[3], requires_grad=False)
|
| 412 |
+
|
| 413 |
+
self.mode = mode
|
| 414 |
+
|
| 415 |
+
def forward(self, coeffs):
|
| 416 |
+
yl = coeffs[-1][:, 0:1, :, :]
|
| 417 |
+
yh = []
|
| 418 |
+
for lohi in coeffs:
|
| 419 |
+
yh.append(lohi[:, None, 1:4, :, :])
|
| 420 |
+
|
| 421 |
+
ll = yl
|
| 422 |
+
|
| 423 |
+
for h_ in yh[::-1]:
|
| 424 |
+
lh, hl, hh = torch.unbind(h_, dim=2)
|
| 425 |
+
filts = (self.g0_col, self.g1_col, self.g0_row, self.g1_row)
|
| 426 |
+
ll = sfb2d_atrous(ll, lh, hl, hh, filts, mode=self.mode)
|
| 427 |
+
|
| 428 |
+
return ll
|
basicsr/models/losses/__init__.py
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ------------------------------------------------------------------------
|
| 2 |
+
# Copyright (c) 2022 megvii-model. All Rights Reserved.
|
| 3 |
+
# ------------------------------------------------------------------------
|
| 4 |
+
# Modified from BasicSR (https://github.com/xinntao/BasicSR)
|
| 5 |
+
# Copyright 2018-2020 BasicSR Authors
|
| 6 |
+
# ------------------------------------------------------------------------
|
| 7 |
+
from .losses import (L1Loss, MSELoss, PSNRLoss)
|
| 8 |
+
from .swt_loss import (SWTLoss, SWTLossRGB)
|
| 9 |
+
__all__ = [
|
| 10 |
+
'L1Loss', 'MSELoss', 'PSNRLoss','SWTLoss', 'SWTLossRGB',
|
| 11 |
+
]
|
basicsr/models/losses/loss_util.py
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ------------------------------------------------------------------------
|
| 2 |
+
# Copyright (c) 2022 megvii-model. All Rights Reserved.
|
| 3 |
+
# ------------------------------------------------------------------------
|
| 4 |
+
# Modified from BasicSR (https://github.com/xinntao/BasicSR)
|
| 5 |
+
# Copyright 2018-2020 BasicSR Authors
|
| 6 |
+
# ------------------------------------------------------------------------
|
| 7 |
+
import functools
|
| 8 |
+
from torch.nn import functional as F
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
def reduce_loss(loss, reduction):
|
| 12 |
+
"""Reduce loss as specified.
|
| 13 |
+
|
| 14 |
+
Args:
|
| 15 |
+
loss (Tensor): Elementwise loss tensor.
|
| 16 |
+
reduction (str): Options are 'none', 'mean' and 'sum'.
|
| 17 |
+
|
| 18 |
+
Returns:
|
| 19 |
+
Tensor: Reduced loss tensor.
|
| 20 |
+
"""
|
| 21 |
+
reduction_enum = F._Reduction.get_enum(reduction)
|
| 22 |
+
# none: 0, elementwise_mean:1, sum: 2
|
| 23 |
+
if reduction_enum == 0:
|
| 24 |
+
return loss
|
| 25 |
+
elif reduction_enum == 1:
|
| 26 |
+
return loss.mean()
|
| 27 |
+
else:
|
| 28 |
+
return loss.sum()
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
def weight_reduce_loss(loss, weight=None, reduction='mean'):
|
| 32 |
+
"""Apply element-wise weight and reduce loss.
|
| 33 |
+
|
| 34 |
+
Args:
|
| 35 |
+
loss (Tensor): Element-wise loss.
|
| 36 |
+
weight (Tensor): Element-wise weights. Default: None.
|
| 37 |
+
reduction (str): Same as built-in losses of PyTorch. Options are
|
| 38 |
+
'none', 'mean' and 'sum'. Default: 'mean'.
|
| 39 |
+
|
| 40 |
+
Returns:
|
| 41 |
+
Tensor: Loss values.
|
| 42 |
+
"""
|
| 43 |
+
# if weight is specified, apply element-wise weight
|
| 44 |
+
if weight is not None:
|
| 45 |
+
assert weight.dim() == loss.dim()
|
| 46 |
+
assert weight.size(1) == 1 or weight.size(1) == loss.size(1)
|
| 47 |
+
loss = loss * weight
|
| 48 |
+
|
| 49 |
+
# if weight is not specified or reduction is sum, just reduce the loss
|
| 50 |
+
if weight is None or reduction == 'sum':
|
| 51 |
+
loss = reduce_loss(loss, reduction)
|
| 52 |
+
# if reduction is mean, then compute mean over weight region
|
| 53 |
+
elif reduction == 'mean':
|
| 54 |
+
if weight.size(1) > 1:
|
| 55 |
+
weight = weight.sum()
|
| 56 |
+
else:
|
| 57 |
+
weight = weight.sum() * loss.size(1)
|
| 58 |
+
loss = loss.sum() / weight
|
| 59 |
+
|
| 60 |
+
return loss
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
def weighted_loss(loss_func):
|
| 64 |
+
"""Create a weighted version of a given loss function.
|
| 65 |
+
|
| 66 |
+
To use this decorator, the loss function must have the signature like
|
| 67 |
+
`loss_func(pred, target, **kwargs)`. The function only needs to compute
|
| 68 |
+
element-wise loss without any reduction. This decorator will add weight
|
| 69 |
+
and reduction arguments to the function. The decorated function will have
|
| 70 |
+
the signature like `loss_func(pred, target, weight=None, reduction='mean',
|
| 71 |
+
**kwargs)`.
|
| 72 |
+
|
| 73 |
+
:Example:
|
| 74 |
+
|
| 75 |
+
>>> import torch
|
| 76 |
+
>>> @weighted_loss
|
| 77 |
+
>>> def l1_loss(pred, target):
|
| 78 |
+
>>> return (pred - target).abs()
|
| 79 |
+
|
| 80 |
+
>>> pred = torch.Tensor([0, 2, 3])
|
| 81 |
+
>>> target = torch.Tensor([1, 1, 1])
|
| 82 |
+
>>> weight = torch.Tensor([1, 0, 1])
|
| 83 |
+
|
| 84 |
+
>>> l1_loss(pred, target)
|
| 85 |
+
tensor(1.3333)
|
| 86 |
+
>>> l1_loss(pred, target, weight)
|
| 87 |
+
tensor(1.5000)
|
| 88 |
+
>>> l1_loss(pred, target, reduction='none')
|
| 89 |
+
tensor([1., 1., 2.])
|
| 90 |
+
>>> l1_loss(pred, target, weight, reduction='sum')
|
| 91 |
+
tensor(3.)
|
| 92 |
+
"""
|
| 93 |
+
|
| 94 |
+
@functools.wraps(loss_func)
|
| 95 |
+
def wrapper(pred, target, weight=None, reduction='mean', **kwargs):
|
| 96 |
+
# get element-wise loss
|
| 97 |
+
loss = loss_func(pred, target, **kwargs)
|
| 98 |
+
loss = weight_reduce_loss(loss, weight, reduction)
|
| 99 |
+
return loss
|
| 100 |
+
|
| 101 |
+
return wrapper
|
basicsr/models/losses/losses.py
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ------------------------------------------------------------------------
|
| 2 |
+
# Copyright (c) 2022 megvii-model. All Rights Reserved.
|
| 3 |
+
# ------------------------------------------------------------------------
|
| 4 |
+
# Modified from BasicSR (https://github.com/xinntao/BasicSR)
|
| 5 |
+
# Copyright 2018-2020 BasicSR Authors
|
| 6 |
+
# ------------------------------------------------------------------------
|
| 7 |
+
import torch
|
| 8 |
+
from torch import nn as nn
|
| 9 |
+
from torch.nn import functional as F
|
| 10 |
+
import numpy as np
|
| 11 |
+
|
| 12 |
+
from basicsr.models.losses.loss_util import weighted_loss
|
| 13 |
+
|
| 14 |
+
_reduction_modes = ['none', 'mean', 'sum']
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
@weighted_loss
|
| 18 |
+
def l1_loss(pred, target):
|
| 19 |
+
return F.l1_loss(pred, target, reduction='none')
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
@weighted_loss
|
| 23 |
+
def mse_loss(pred, target):
|
| 24 |
+
return F.mse_loss(pred, target, reduction='none')
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
# @weighted_loss
|
| 28 |
+
# def charbonnier_loss(pred, target, eps=1e-12):
|
| 29 |
+
# return torch.sqrt((pred - target)**2 + eps)
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
class L1Loss(nn.Module):
|
| 33 |
+
"""L1 (mean absolute error, MAE) loss.
|
| 34 |
+
|
| 35 |
+
Args:
|
| 36 |
+
loss_weight (float): Loss weight for L1 loss. Default: 1.0.
|
| 37 |
+
reduction (str): Specifies the reduction to apply to the output.
|
| 38 |
+
Supported choices are 'none' | 'mean' | 'sum'. Default: 'mean'.
|
| 39 |
+
"""
|
| 40 |
+
|
| 41 |
+
def __init__(self, loss_weight=1.0, reduction='mean'):
|
| 42 |
+
super(L1Loss, self).__init__()
|
| 43 |
+
if reduction not in ['none', 'mean', 'sum']:
|
| 44 |
+
raise ValueError(f'Unsupported reduction mode: {reduction}. '
|
| 45 |
+
f'Supported ones are: {_reduction_modes}')
|
| 46 |
+
|
| 47 |
+
self.loss_weight = loss_weight
|
| 48 |
+
self.reduction = reduction
|
| 49 |
+
|
| 50 |
+
def forward(self, pred, target, weight=None, **kwargs):
|
| 51 |
+
"""
|
| 52 |
+
Args:
|
| 53 |
+
pred (Tensor): of shape (N, C, H, W). Predicted tensor.
|
| 54 |
+
target (Tensor): of shape (N, C, H, W). Ground truth tensor.
|
| 55 |
+
weight (Tensor, optional): of shape (N, C, H, W). Element-wise
|
| 56 |
+
weights. Default: None.
|
| 57 |
+
"""
|
| 58 |
+
return self.loss_weight * l1_loss(
|
| 59 |
+
pred, target, weight, reduction=self.reduction)
|
| 60 |
+
|
| 61 |
+
class MSELoss(nn.Module):
|
| 62 |
+
"""MSE (L2) loss.
|
| 63 |
+
|
| 64 |
+
Args:
|
| 65 |
+
loss_weight (float): Loss weight for MSE loss. Default: 1.0.
|
| 66 |
+
reduction (str): Specifies the reduction to apply to the output.
|
| 67 |
+
Supported choices are 'none' | 'mean' | 'sum'. Default: 'mean'.
|
| 68 |
+
"""
|
| 69 |
+
|
| 70 |
+
def __init__(self, loss_weight=1.0, reduction='mean'):
|
| 71 |
+
super(MSELoss, self).__init__()
|
| 72 |
+
if reduction not in ['none', 'mean', 'sum']:
|
| 73 |
+
raise ValueError(f'Unsupported reduction mode: {reduction}. '
|
| 74 |
+
f'Supported ones are: {_reduction_modes}')
|
| 75 |
+
|
| 76 |
+
self.loss_weight = loss_weight
|
| 77 |
+
self.reduction = reduction
|
| 78 |
+
|
| 79 |
+
def forward(self, pred, target, weight=None, **kwargs):
|
| 80 |
+
"""
|
| 81 |
+
Args:
|
| 82 |
+
pred (Tensor): of shape (N, C, H, W). Predicted tensor.
|
| 83 |
+
target (Tensor): of shape (N, C, H, W). Ground truth tensor.
|
| 84 |
+
weight (Tensor, optional): of shape (N, C, H, W). Element-wise
|
| 85 |
+
weights. Default: None.
|
| 86 |
+
"""
|
| 87 |
+
return self.loss_weight * mse_loss(
|
| 88 |
+
pred, target, weight, reduction=self.reduction)
|
| 89 |
+
|
| 90 |
+
class PSNRLoss(nn.Module):
|
| 91 |
+
|
| 92 |
+
def __init__(self, loss_weight=1.0, reduction='mean', toY=False):
|
| 93 |
+
super(PSNRLoss, self).__init__()
|
| 94 |
+
assert reduction == 'mean'
|
| 95 |
+
self.loss_weight = loss_weight
|
| 96 |
+
self.scale = 10 / np.log(10)
|
| 97 |
+
self.toY = toY
|
| 98 |
+
self.coef = torch.tensor([65.481, 128.553, 24.966]).reshape(1, 3, 1, 1)
|
| 99 |
+
self.first = True
|
| 100 |
+
|
| 101 |
+
def forward(self, pred, target):
|
| 102 |
+
assert len(pred.size()) == 4
|
| 103 |
+
if self.toY:
|
| 104 |
+
if self.first:
|
| 105 |
+
self.coef = self.coef.to(pred.device)
|
| 106 |
+
self.first = False
|
| 107 |
+
|
| 108 |
+
pred = (pred * self.coef).sum(dim=1).unsqueeze(dim=1) + 16.
|
| 109 |
+
target = (target * self.coef).sum(dim=1).unsqueeze(dim=1) + 16.
|
| 110 |
+
|
| 111 |
+
pred, target = pred / 255., target / 255.
|
| 112 |
+
pass
|
| 113 |
+
assert len(pred.size()) == 4
|
| 114 |
+
|
| 115 |
+
return self.loss_weight * self.scale * torch.log(((pred - target) ** 2).mean(dim=(1, 2, 3)) + 1e-8).mean()
|
| 116 |
+
|
basicsr/models/losses/swt_loss.py
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
import torch.nn as nn
|
| 3 |
+
import pywt
|
| 4 |
+
import numpy as np
|
| 5 |
+
from . import SWT
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
class SWTLoss(nn.Module):
|
| 9 |
+
"""
|
| 10 |
+
Stationary Wavelet Transform Loss (SWT Loss)
|
| 11 |
+
|
| 12 |
+
基于平稳小波变换的损失函数,将图像分解为多个频带(LL, LH, HL, HH),
|
| 13 |
+
然后分别计算各频带的L1损失。
|
| 14 |
+
|
| 15 |
+
Args:
|
| 16 |
+
loss_weight_ll (float): 低频分量(LL)的损失权重. Default: 0.01
|
| 17 |
+
loss_weight_lh (float): 水平高频分量(LH)的损失权重. Default: 0.01
|
| 18 |
+
loss_weight_hl (float): 垂直高频分量(HL)的损失权重. Default: 0.01
|
| 19 |
+
loss_weight_hh (float): 对角高频分量(HH)的损失权重. Default: 0.01
|
| 20 |
+
reduction (str): 损失归约方式. Default: 'mean'
|
| 21 |
+
wavelet (str): 小波类型. Default: 'sym19'
|
| 22 |
+
mode (str): 填充模式. Default: 'periodic'
|
| 23 |
+
"""
|
| 24 |
+
|
| 25 |
+
def __init__(self,
|
| 26 |
+
loss_weight_ll=0.01,
|
| 27 |
+
loss_weight_lh=0.01,
|
| 28 |
+
loss_weight_hl=0.01,
|
| 29 |
+
loss_weight_hh=0.01,
|
| 30 |
+
reduction='mean',
|
| 31 |
+
wavelet='sym19',
|
| 32 |
+
mode='periodic'):
|
| 33 |
+
super(SWTLoss, self).__init__()
|
| 34 |
+
self.loss_weight_ll = loss_weight_ll
|
| 35 |
+
self.loss_weight_lh = loss_weight_lh
|
| 36 |
+
self.loss_weight_hl = loss_weight_hl
|
| 37 |
+
self.loss_weight_hh = loss_weight_hh
|
| 38 |
+
self.wavelet_name = wavelet
|
| 39 |
+
self.mode = mode
|
| 40 |
+
|
| 41 |
+
self.criterion = nn.L1Loss(reduction=reduction)
|
| 42 |
+
|
| 43 |
+
self._swt_forward = None
|
| 44 |
+
self._device = None
|
| 45 |
+
|
| 46 |
+
def _get_swt_forward(self, device):
|
| 47 |
+
if self._swt_forward is None or self._device != device:
|
| 48 |
+
wavelet = pywt.Wavelet(self.wavelet_name)
|
| 49 |
+
|
| 50 |
+
dlo = wavelet.dec_lo
|
| 51 |
+
an_lo = np.divide(dlo, sum(dlo))
|
| 52 |
+
an_hi = wavelet.dec_hi
|
| 53 |
+
rlo = wavelet.rec_lo
|
| 54 |
+
syn_lo = 2 * np.divide(rlo, sum(rlo))
|
| 55 |
+
syn_hi = wavelet.rec_hi
|
| 56 |
+
|
| 57 |
+
filters = pywt.Wavelet('wavelet_normalized', [an_lo, an_hi, syn_lo, syn_hi])
|
| 58 |
+
self._swt_forward = SWT.SWTForward(1, filters, self.mode).to(device)
|
| 59 |
+
self._device = device
|
| 60 |
+
return self._swt_forward
|
| 61 |
+
|
| 62 |
+
def forward(self, pred, target):
|
| 63 |
+
"""
|
| 64 |
+
计算SWT损失
|
| 65 |
+
|
| 66 |
+
Args:
|
| 67 |
+
pred (Tensor): 预测图像, shape (N, C, H, W), 值范围 [0, 1]
|
| 68 |
+
target (Tensor): 目标图像, shape (N, C, H, W), 值范围 [0, 1]
|
| 69 |
+
|
| 70 |
+
Returns:
|
| 71 |
+
Tensor: SWT损失值
|
| 72 |
+
"""
|
| 73 |
+
device = pred.device
|
| 74 |
+
sfm = self._get_swt_forward(device)
|
| 75 |
+
|
| 76 |
+
pred_y = 16.0 + (pred[:, 0:1, :, :] * 65.481 + pred[:, 1:2, :, :] * 128.553 + pred[:, 2:, :, :] * 24.966)
|
| 77 |
+
target_y = 16.0 + (
|
| 78 |
+
target[:, 0:1, :, :] * 65.481 + target[:, 1:2, :, :] * 128.553 + target[:, 2:, :, :] * 24.966)
|
| 79 |
+
|
| 80 |
+
wavelet_pred = sfm(pred_y)[0]
|
| 81 |
+
wavelet_target = sfm(target_y)[0]
|
| 82 |
+
|
| 83 |
+
LL_pred = wavelet_pred[:, 0:1, :, :]
|
| 84 |
+
LH_pred = wavelet_pred[:, 1:2, :, :]
|
| 85 |
+
HL_pred = wavelet_pred[:, 2:3, :, :]
|
| 86 |
+
HH_pred = wavelet_pred[:, 3:, :, :]
|
| 87 |
+
|
| 88 |
+
LL_target = wavelet_target[:, 0:1, :, :]
|
| 89 |
+
LH_target = wavelet_target[:, 1:2, :, :]
|
| 90 |
+
HL_target = wavelet_target[:, 2:3, :, :]
|
| 91 |
+
HH_target = wavelet_target[:, 3:, :, :]
|
| 92 |
+
|
| 93 |
+
loss_subband_LL = self.loss_weight_ll * self.criterion(LL_pred, LL_target)
|
| 94 |
+
loss_subband_LH = self.loss_weight_lh * self.criterion(LH_pred, LH_target)
|
| 95 |
+
loss_subband_HL = self.loss_weight_hl * self.criterion(HL_pred, HL_target)
|
| 96 |
+
loss_subband_HH = self.loss_weight_hh * self.criterion(HH_pred, HH_target)
|
| 97 |
+
|
| 98 |
+
return loss_subband_LL + loss_subband_LH + loss_subband_HL + loss_subband_HH
|
| 99 |
+
|
| 100 |
+
|
| 101 |
+
class SWTLossRGB(nn.Module):
|
| 102 |
+
"""
|
| 103 |
+
Stationary Wavelet Transform Loss for RGB images (applied to each channel)
|
| 104 |
+
|
| 105 |
+
对RGB三个通道分别应用SWT变换并计算损失。
|
| 106 |
+
|
| 107 |
+
Args:
|
| 108 |
+
loss_weight_ll (float): 低频分量(LL)的损失权重. Default: 0.01
|
| 109 |
+
loss_weight_lh (float): 水平高频分量(LH)的损失权重. Default: 0.01
|
| 110 |
+
loss_weight_hl (float): 垂直高频分量(HL)的损失权重. Default: 0.01
|
| 111 |
+
loss_weight_hh (float): 对角高频分量(HH)的损失权重. Default: 0.01
|
| 112 |
+
reduction (str): 损失归约方式. Default: 'mean'
|
| 113 |
+
wavelet (str): 小波类型. Default: 'sym19'
|
| 114 |
+
mode (str): 填充模式. Default: 'periodic'
|
| 115 |
+
"""
|
| 116 |
+
|
| 117 |
+
def __init__(self,
|
| 118 |
+
loss_weight_ll=0.01,
|
| 119 |
+
loss_weight_lh=0.01,
|
| 120 |
+
loss_weight_hl=0.01,
|
| 121 |
+
loss_weight_hh=0.01,
|
| 122 |
+
reduction='mean',
|
| 123 |
+
wavelet='sym19',
|
| 124 |
+
mode='periodic'):
|
| 125 |
+
super(SWTLossRGB, self).__init__()
|
| 126 |
+
self.loss_weight_ll = loss_weight_ll
|
| 127 |
+
self.loss_weight_lh = loss_weight_lh
|
| 128 |
+
self.loss_weight_hl = loss_weight_hl
|
| 129 |
+
self.loss_weight_hh = loss_weight_hh
|
| 130 |
+
self.wavelet_name = wavelet
|
| 131 |
+
self.mode = mode
|
| 132 |
+
|
| 133 |
+
self.criterion = nn.L1Loss(reduction=reduction)
|
| 134 |
+
|
| 135 |
+
self._swt_forward = None
|
| 136 |
+
self._device = None
|
| 137 |
+
|
| 138 |
+
def _get_swt_forward(self, device):
|
| 139 |
+
if self._swt_forward is None or self._device != device:
|
| 140 |
+
wavelet = pywt.Wavelet(self.wavelet_name)
|
| 141 |
+
|
| 142 |
+
dlo = wavelet.dec_lo
|
| 143 |
+
an_lo = np.divide(dlo, sum(dlo))
|
| 144 |
+
an_hi = wavelet.dec_hi
|
| 145 |
+
rlo = wavelet.rec_lo
|
| 146 |
+
syn_lo = 2 * np.divide(rlo, sum(rlo))
|
| 147 |
+
syn_hi = wavelet.rec_hi
|
| 148 |
+
|
| 149 |
+
filters = pywt.Wavelet('wavelet_normalized', [an_lo, an_hi, syn_lo, syn_hi])
|
| 150 |
+
self._swt_forward = SWT.SWTForward(1, filters, self.mode).to(device)
|
| 151 |
+
self._device = device
|
| 152 |
+
return self._swt_forward
|
| 153 |
+
|
| 154 |
+
def forward(self, pred, target):
|
| 155 |
+
"""
|
| 156 |
+
计算RGB SWT损失
|
| 157 |
+
|
| 158 |
+
Args:
|
| 159 |
+
pred (Tensor): 预测图像, shape (N, C, H, W), 值范围 [0, 1]
|
| 160 |
+
target (Tensor): 目标图像, shape (N, C, H, W), 值范围 [0, 1]
|
| 161 |
+
|
| 162 |
+
Returns:
|
| 163 |
+
Tensor: SWT损失值
|
| 164 |
+
"""
|
| 165 |
+
device = pred.device
|
| 166 |
+
sfm = self._get_swt_forward(device)
|
| 167 |
+
|
| 168 |
+
total_loss = 0.0
|
| 169 |
+
|
| 170 |
+
for c in range(pred.shape[1]):
|
| 171 |
+
pred_channel = pred[:, c:c + 1, :, :]
|
| 172 |
+
target_channel = target[:, c:c + 1, :, :]
|
| 173 |
+
|
| 174 |
+
wavelet_pred = sfm(pred_channel)[0]
|
| 175 |
+
wavelet_target = sfm(target_channel)[0]
|
| 176 |
+
|
| 177 |
+
LL_pred = wavelet_pred[:, 0:1, :, :]
|
| 178 |
+
LH_pred = wavelet_pred[:, 1:2, :, :]
|
| 179 |
+
HL_pred = wavelet_pred[:, 2:3, :, :]
|
| 180 |
+
HH_pred = wavelet_pred[:, 3:, :, :]
|
| 181 |
+
|
| 182 |
+
LL_target = wavelet_target[:, 0:1, :, :]
|
| 183 |
+
LH_target = wavelet_target[:, 1:2, :, :]
|
| 184 |
+
HL_target = wavelet_target[:, 2:3, :, :]
|
| 185 |
+
HH_target = wavelet_target[:, 3:, :, :]
|
| 186 |
+
|
| 187 |
+
loss_subband_LL = self.loss_weight_ll * self.criterion(LL_pred, LL_target)
|
| 188 |
+
loss_subband_LH = self.loss_weight_lh * self.criterion(LH_pred, LH_target)
|
| 189 |
+
loss_subband_HL = self.loss_weight_hl * self.criterion(HL_pred, HL_target)
|
| 190 |
+
loss_subband_HH = self.loss_weight_hh * self.criterion(HH_pred, HH_target)
|
| 191 |
+
|
| 192 |
+
total_loss = total_loss + loss_subband_LL + loss_subband_LH + loss_subband_HL + loss_subband_HH
|
| 193 |
+
|
| 194 |
+
return total_loss / pred.shape[1]
|