File size: 5,096 Bytes
d16ffa3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
---
license: mit
library_name: pytorch
pipeline_tag: image-to-image
tags:
  - super-resolution
  - image-super-resolution
  - image-to-image
  - pytorch
  - onnx
datasets:
  - eugenesiow/Div2k
model-index:
  - name: SRNet-x4-Upscaler
    results:
      - task:
          type: image-to-image
          name: Image super-resolution (x4)
        dataset:
          name: DIV2K validation (100 images, bicubic degradation)
          type: eugenesiow/Div2k
        metrics:
          - type: psnr
            name: PSNR (Y channel, shave 4)
            value: 30.28
---

# SRNet-x4-Upscaler — small, fast single-image super-resolution

A compact residual CNN (~1.25 M parameters) that upscales images 4x. It predicts a residual on top of a bicubic upscale, so it starts from — and improves on — plain bicubic interpolation. Trained in 30 minutes on 2x T4 GPUs.

**Live demo (runs in your browser, nothing is uploaded):** [Infinitode Experiments](https://infinitode.netlify.app/experiments)

## Results

Evaluated on the 100 DIV2K validation images, full images, bicubic-x4 degradation, Y-channel PSNR with a 4 px border shave, 8-bit outputs:

| Method | PSNR (dB) |
|---|---|
| Bicubic | 28.23 |
| **SRNet-x4-Upscaler** | **30.28** (+2.05) |

Metrics come from the training notebook (antialiased bicubic downscale, not the official MATLAB `imresize`), so they are comparable between methods here but only approximately comparable to published tables. Published tables usually report RGB PSNR, which reads about 1.5 dB lower than Y-channel PSNR for the same images.

## Usage

```python
import numpy as np, torch
from PIL import Image
from huggingface_hub import hf_hub_download
import importlib.util

REPO = "InfinitodeLTD/srnet-x4-upscaler"
spec = importlib.util.spec_from_file_location("srnet", hf_hub_download(REPO, "srnet.py"))
srnet = importlib.util.module_from_spec(spec); spec.loader.exec_module(srnet)
model = srnet.SRNet.from_pretrained(REPO).eval()

img = np.asarray(Image.open("photo.png").convert("RGB"), np.float32) / 255
x = torch.from_numpy(img).permute(2, 0, 1)[None]
with torch.inference_mode():
    y = model(x).clamp(0, 1)[0].permute(1, 2, 0).numpy()
Image.fromarray((y * 255).round().astype("uint8")).save("photo_x4.png")
```

### Large images (tiled inference)

Process tiles with a margin of at least `2*nb + 6 = 38` input pixels; the result is then identical to whole-image inference.

```python
@torch.inference_mode()
def upscale_tiled(model, x, tile=128):
    s, m = model.scale, 2 * model.nb + 6
    _, _, H, W = x.shape
    out = torch.empty(1, 3, H * s, W * s)
    for y in range(0, H, tile):
        for xx in range(0, W, tile):
            y1, x1 = min(H, y + tile), min(W, xx + tile)
            ya, xa, yb, xb = max(0, y - m), max(0, xx - m), min(H, y1 + m), min(W, x1 + m)
            sr = model(x[:, :, ya:yb, xa:xb]).clamp(0, 1)
            out[:, :, y * s:y1 * s, xx * s:x1 * s] = sr[:, :, (y - ya) * s:(y1 - ya) * s, (xx - xa) * s:(x1 - xa) * s]
    return out
```

### ONNX

`srnet_x4.onnx` takes `input` (float32 NCHW RGB in [0, 1], dynamic batch/height/width) and returns `output` (clip to [0, 1]). It runs with onnxruntime and onnxruntime-web (the browser demo uses it).

## Model details

- Architecture: 3x3 conv head -> 16 residual blocks (conv-ReLU-conv, 64 channels) -> 3x3 conv with long skip -> conv to 48 channels + PixelShuffle(4) -> added to a bicubic upscale of the input. The final conv is zero-initialised, so training starts at exact bicubic.
- Compute: all convolutions run at input resolution; about 2.5 MFLOPs per input pixel.

## Training

- Data: DF2K (DIV2K + Flickr2K) HR training images; DIV2K validation images held out.
- Degradation: antialiased bicubic x4 downscale, quantised to 8 bit. No noise, blur or compression.
- 16,157 steps, batch 32, 64x64 LR patches (256x256 HR), random flips/rotations.
- AdamW, peak LR 4e-4 with cosine decay, L1 loss, then MSE for the final 8% of the schedule; EMA (0.999) weights evaluated alongside raw weights and the better one kept; fp16 mixed precision.

## Limitations

- Trained only on clean bicubic-downscaled images. On real-world inputs with noise, blur or JPEG artefacts it will not denoise or deblock and may amplify artefacts.
- Optimised for PSNR with L1/MSE losses, so fine texture (fur, feathers, foliage) comes out smoother than the original. It does not hallucinate detail the way GAN-based upscalers do.
- x4 only.

## License

The code and weights in this repository are released under the [MIT License](LICENSE).

The MIT license does not change the terms of the training data: DIV2K is distributed for academic research use, and Flickr2K images carry their original Flickr licenses. If you plan commercial use, confirm those terms are acceptable to you.

## Acknowledgements

- DIV2K: Agustsson & Timofte, *NTIRE 2017 Challenge on Single Image Super-Resolution: Dataset and Study*, CVPRW 2017.
- Flickr2K: collected for Lim et al., *Enhanced Deep Residual Networks for Single Image Super-Resolution* (EDSR), CVPRW 2017. The residual-block design follows the EDSR family.