Download patch_dataset/compute_norm_stats.py from kabiriitb/rockglacierNET: direct link, hf CLI and curl.
- Browser
- Download file 2.38 kB
-
https://huggingface.co/kabiriitb/rockglacierNET/resolve/main/patch_dataset/compute_norm_stats.py
- Command line
-
hf download hf://kabiriitb/rockglacierNET/patch_dataset/compute_norm_stats.py
-
curl -L -o compute_norm_stats.py https://huggingface.co/kabiriitb/rockglacierNET/resolve/main/patch_dataset/compute_norm_stats.py
2.38 kB
| """ | |
| RockGlacierNet — compute per-band normalization stats for a built patch set. | |
| The training data_generator z-score normalizes each band. Its built-in | |
| GLOBAL_MEAN/STD were measured on the OLD glacier-centric crops and badly misfit the | |
| whole-Sikkim region patches (e.g. Elev std 282 vs actual ~1150, NDVI off by +3.7 sigma). | |
| This writes correct stats next to the patches; data_generator loads them automatically. | |
| python patch_dataset/compute_norm_stats.py --patch-size 128 | |
| Output: patch_dataset/patches_{size}/metadata/norm_stats.json | |
| """ | |
| import os | |
| import sys | |
| import json | |
| import glob | |
| import argparse | |
| import numpy as np | |
| import rasterio | |
| sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) | |
| import config as C | |
| def main(): | |
| ap = argparse.ArgumentParser() | |
| ap.add_argument("--patch-size", type=int, default=C.DEFAULT_PATCH) | |
| args = ap.parse_args() | |
| outdir = C.patches_dir(args.patch_size) | |
| feats = sorted(glob.glob(str(outdir / "train" / "features" / "*.tif"))) | |
| if not feats: | |
| sys.exit(f"No train features in {outdir}/train/features — build patches first.") | |
| n = C.NUM_BANDS | |
| # Welford-ish running sums over all pixels of all train patches. | |
| count = 0 | |
| s1 = np.zeros(n, dtype=np.float64) | |
| s2 = np.zeros(n, dtype=np.float64) | |
| for fp in feats: | |
| with rasterio.open(fp) as s: | |
| a = s.read().astype(np.float64) # (C, H, W) | |
| a = np.where(np.isfinite(a) & (a != C.NODATA_VALUE), a, 0.0) | |
| flat = a.reshape(n, -1) | |
| s1 += flat.sum(axis=1) | |
| s2 += (flat * flat).sum(axis=1) | |
| count += flat.shape[1] | |
| mean = s1 / count | |
| std = np.sqrt(np.maximum(s2 / count - mean * mean, 1e-12)) | |
| stats = {"band_names": C.BAND_NAMES, | |
| "mean": [round(float(x), 6) for x in mean], | |
| "std": [round(float(x), 6) for x in std], | |
| "num_train_patches": len(feats), | |
| "num_pixels": int(count)} | |
| out = outdir / "metadata" / "norm_stats.json" | |
| with open(out, "w") as f: | |
| json.dump(stats, f, indent=2) | |
| print(f"Computed over {len(feats)} train patches ({count:,} px/band)") | |
| print(f"{'band':7s} {'mean':>12s} {'std':>12s}") | |
| for nm, m, sd in zip(C.BAND_NAMES, stats["mean"], stats["std"]): | |
| print(f"{nm:7s} {m:12.4f} {sd:12.4f}") | |
| print(f"\nSaved -> {out}") | |
| if __name__ == "__main__": | |
| main() | |