rockglacierNET / patch_dataset /collect_glacier.py
kabiriitb's picture
Upload folder using huggingface_hub
80e070e verified
Raw History Blame Contribute Delete
4.03 kB
"""
RockGlacierNet — Enlarged per-glacier collection ("best of both"). [patch_dataset/]
One crop per inventory polygon (max diversity: ~610 distinct positive examples),
each glacier centered with GLACIER_BUFFER_M of REAL surrounding terrain (not the
zero-padding the old dataset/ relied on). Reuses the bug-fixed download path from
collect_region (memory-light cloud-filtered composite, correct UTM terrain,
MemoryFile-safe download with sub-tiling fallback).
Outputs (nothing outside patch_dataset/):
patch_dataset/raw_glacier/features/feature_XXXX.tif (12-band, float32, 10 m, UTM45N)
patch_dataset/raw_glacier/masks/mask_XXXX.tif (1-band uint8, same grid)
Then:
python patch_dataset/build_patches.py --patch-size 128 \
--features-dir patch_dataset/raw_glacier/features \
--masks-dir patch_dataset/raw_glacier/masks
python patch_dataset/compute_norm_stats.py --patch-size 128
Run (env with ee+geemap+geopandas+rasterio):
python patch_dataset/collect_glacier.py # all polygons
python patch_dataset/collect_glacier.py --limit 5 # smoke test
All tunables live in patch_dataset/config.py.
"""
import os
import sys
import argparse
import numpy as np
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
import config as C
from collect_region import fetch_tile # robust, terrain-correct downloader
import ee
import geopandas as gpd
import rasterio
from rasterio.features import rasterize
def main():
ap = argparse.ArgumentParser(description="Enlarged per-glacier collection.")
ap.add_argument("--shapefile", default=str(C.SHAPEFILE_PATH))
ap.add_argument("--limit", type=int, default=None)
args = ap.parse_args()
try:
ee.Initialize(project=C.GEE_PROJECT)
except Exception:
ee.Authenticate(); ee.Initialize(project=C.GEE_PROJECT)
C.RAW_GLACIER_FEATURES_DIR.mkdir(parents=True, exist_ok=True)
C.RAW_GLACIER_MASKS_DIR.mkdir(parents=True, exist_ok=True)
gdf = gpd.read_file(args.shapefile).to_crs(C.TARGET_CRS)
n = len(gdf) if args.limit is None else min(args.limit, len(gdf))
print(f"{len(gdf)} polygons | processing {n} | buffer={C.GLACIER_BUFFER_M:.0f} m | scale={C.SCALE_M:.0f} m")
done = skip = fail = 0
for idx in range(n):
geom = gdf.geometry.iloc[idx]
if geom is None or geom.is_empty:
print(f" [{idx:04d}] empty geometry — skipped"); skip += 1; continue
fpath = C.RAW_GLACIER_FEATURES_DIR / f"feature_{idx:04d}.tif"
mpath = C.RAW_GLACIER_MASKS_DIR / f"mask_{idx:04d}.tif"
if fpath.exists() and mpath.exists():
skip += 1; continue
try:
b = geom.bounds
buf = C.GLACIER_BUFFER_M
bbox = (b[0] - buf, b[1] - buf, b[2] + buf, b[3] + buf)
arr, transform, crs = fetch_tile(bbox)
H, W = arr.shape[1], arr.shape[2]
with rasterio.open(fpath, "w", driver="GTiff", height=H, width=W,
count=arr.shape[0], dtype="float32",
crs=crs, transform=transform) as dst:
dst.write(arr.astype(np.float32))
mask = rasterize([(geom, 1)], out_shape=(H, W), transform=transform,
fill=0, dtype="uint8")
with rasterio.open(mpath, "w", driver="GTiff", height=H, width=W, count=1,
dtype="uint8", crs=crs, transform=transform, nodata=0) as dst:
dst.write(mask, 1)
done += 1
if done % 25 == 0 or idx == n - 1:
print(f" [{idx:04d}] done={done} skip={skip} fail={fail} (last {H}x{W}, fg={int(mask.sum())})")
except Exception as e:
fail += 1
print(f" [{idx:04d}] FAILED: {e}")
print(f"\nPer-glacier collection complete. done={done} skipped={skip} failed={fail}")
print(f"Features -> {C.RAW_GLACIER_FEATURES_DIR}")
print(f"Masks -> {C.RAW_GLACIER_MASKS_DIR}")
if __name__ == "__main__":
main()