marklpd commited on
Commit
23b2d79
·
verified ·
1 Parent(s): 61d1f02

PSRGAN v1.0

Browse files
Files changed (2) hide show
  1. README.md +1 -1
  2. degradation.py +90 -0
README.md CHANGED
@@ -109,7 +109,7 @@ The model expects Sentinel-2 L2A RGB (B04, B03, B02) after a per-image 1 to 99%
109
  | `psrgan_x4_swag.safetensors` | SWAG mean and variance (32 snapshots) |
110
  | `config.json`, `psrgan.py` | model hyperparameters and code |
111
  | `eval/metrics.json` | every number on this page |
112
- | `notebooks/` | dataset creation and training notebooks |
113
 
114
  # Evaluation
115
 
 
109
  | `psrgan_x4_swag.safetensors` | SWAG mean and variance (32 snapshots) |
110
  | `config.json`, `psrgan.py` | model hyperparameters and code |
111
  | `eval/metrics.json` | every number on this page |
112
+ | `degradation.py` | randomized degradation that made the LR images of the dataset |
113
 
114
  # Evaluation
115
 
degradation.py ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Randomized degradation that made the LR images of the PSRGAN Sentinel-2 dataset.
2
+
3
+ Each HR image gets one random blur (Gaussian, horizontal or vertical motion, defocus)
4
+ and is then downsampled 4x with a random interpolation (bicubic, bilinear, area).
5
+
6
+ python degradation.py hr_dir lr_dir --seed 0
7
+
8
+ Writes one LR PNG per HR image and degradations.csv with the drawn parameters.
9
+ """
10
+ import argparse
11
+ import csv
12
+ import random
13
+ from pathlib import Path
14
+
15
+ import cv2
16
+ import numpy as np
17
+
18
+ INTERP_NAMES = {cv2.INTER_CUBIC: "bicubic", cv2.INTER_LINEAR: "bilinear", cv2.INTER_AREA: "area"}
19
+
20
+
21
+ def degrade(hr, scale=4, rng=random):
22
+ """hr: (H, W, 3) float32 in [0, 1]. Returns the LR image and the drawn parameters."""
23
+ h, w = hr.shape[:2]
24
+ filter_type = rng.choice(["gaussian", "motion", "defocus"])
25
+ sigma = 0.0
26
+
27
+ if filter_type == "gaussian":
28
+ # Isotropic Gaussian blur
29
+ k = rng.choice([3, 5, 7])
30
+ sigma = rng.uniform(0.5, 1.5)
31
+ blurred = cv2.GaussianBlur(hr, (k, k), sigmaX=sigma)
32
+
33
+ elif filter_type == "motion":
34
+ # Line kernel, horizontal or vertical
35
+ k = rng.choice([5, 7, 9])
36
+ kernel = np.zeros((k, k), np.float32)
37
+ if rng.random() < 0.5:
38
+ kernel[k // 2, :] = 1.0
39
+ filter_type = "motion_h"
40
+ else:
41
+ kernel[:, k // 2] = 1.0
42
+ filter_type = "motion_v"
43
+ blurred = cv2.filter2D(hr, -1, kernel / k)
44
+
45
+ else:
46
+ # Defocus as a disk kernel
47
+ k = rng.choice([5, 7, 9])
48
+ c = k // 2
49
+ yy, xx = np.mgrid[:k, :k]
50
+ kernel = ((yy - c) ** 2 + (xx - c) ** 2 <= c ** 2).astype(np.float32)
51
+ blurred = cv2.filter2D(hr, -1, kernel / kernel.sum())
52
+
53
+ interpolation = rng.choice([cv2.INTER_CUBIC, cv2.INTER_LINEAR, cv2.INTER_AREA])
54
+ lr = cv2.resize(blurred, (w // scale, h // scale), interpolation=interpolation)
55
+ return lr, {"blur": filter_type, "blur_kernel": k, "blur_sigma": sigma,
56
+ "interpolation": INTERP_NAMES[interpolation]}
57
+
58
+
59
+ def main():
60
+ p = argparse.ArgumentParser(description=__doc__.splitlines()[0])
61
+ p.add_argument("hr_dir")
62
+ p.add_argument("lr_dir")
63
+ p.add_argument("--scale", type=int, default=4)
64
+ p.add_argument("--seed", type=int, default=None)
65
+ args = p.parse_args()
66
+
67
+ rng = random.Random(args.seed)
68
+ out = Path(args.lr_dir)
69
+ out.mkdir(parents=True, exist_ok=True)
70
+ rows = []
71
+ for path in sorted(Path(args.hr_dir).iterdir()):
72
+ img = cv2.imread(str(path), cv2.IMREAD_COLOR)
73
+ if img is None:
74
+ continue
75
+ # BGR stays BGR, the filters act per channel
76
+ hr = img.astype(np.float32) / 255
77
+ lr, params = degrade(hr, args.scale, rng)
78
+ lr = np.round(np.clip(lr, 0, 1) * 255).astype(np.uint8)
79
+ cv2.imwrite(str(out / f"{path.stem}.png"), lr)
80
+ rows.append({"file": path.name, **params})
81
+
82
+ with open(out / "degradations.csv", "w", newline="") as f:
83
+ w = csv.DictWriter(f, fieldnames=["file", "blur", "blur_kernel", "blur_sigma", "interpolation"])
84
+ w.writeheader()
85
+ w.writerows(rows)
86
+ print(f"{len(rows)} LR images in {out}")
87
+
88
+
89
+ if __name__ == "__main__":
90
+ main()