# -*- coding: utf-8 -*- """Crop small geo-aligned ROI blocks from a georeferenced before/after pair. Prototypes the Wednesday ROI backend (windowed native crop + common-grid alignment) AND produces ready-made small test pairs under data/roi_test/. Usage: venv\\Scripts\\python scripts\\make_roi_test_blocks.py ROI blocks are fractional {x, y, w, h} in [0,1] of the images' geographic overlap, so they're resolution-independent (the same contract the real ROI feature will use). """ import sys from pathlib import Path import numpy as np from PIL import Image # Named test blocks (fractions of the geographic overlap). Tune as needed. BLOCKS = { "buildings": {"x": 0.34, "y": 0.66, "w": 0.16, "h": 0.16}, # the two new roofs "buildings_wide": {"x": 0.28, "y": 0.52, "w": 0.32, "h": 0.34}, # roofs + car row "parking": {"x": 0.30, "y": 0.10, "w": 0.24, "h": 0.22}, # cars only (nuisance) } def crop_block(before_path, after_path, roi, out_dir, name): import rasterio from rasterio.transform import from_origin from rasterio.warp import Resampling, reproject, transform_bounds with rasterio.open(before_path) as b, rasterio.open(after_path) as a: b_in_a = transform_bounds(b.crs, a.crs, *b.bounds) left = max(b_in_a[0], a.bounds.left) bottom = max(b_in_a[1], a.bounds.bottom) right = min(b_in_a[2], a.bounds.right) top = min(b_in_a[3], a.bounds.top) ow, oh = right - left, top - bottom # fractional ROI -> geographic sub-box (y measured from the top) gx0 = left + roi["x"] * ow gx1 = gx0 + roi["w"] * ow gy1 = top - roi["y"] * oh gy0 = gy1 - roi["h"] * oh res_x, res_y = a.res W = max(1, int(round((gx1 - gx0) / res_x))) H = max(1, int(round((gy1 - gy0) / res_y))) dst_tf = from_origin(gx0, gy1, res_x, res_y) def warp(src): out = np.zeros((3, H, W), dtype=np.uint8) for i in range(3): reproject( source=rasterio.band(src, i + 1), destination=out[i], src_transform=src.transform, src_crs=src.crs, dst_transform=dst_tf, dst_crs=a.crs, resampling=Resampling.bilinear, ) return np.ascontiguousarray(out.transpose(1, 2, 0)) bb, aa = warp(b), warp(a) out_dir.mkdir(parents=True, exist_ok=True) Image.fromarray(bb).save(out_dir / f"{name}_before.png") Image.fromarray(aa).save(out_dir / f"{name}_after.png") print(f" {name:16s} {W}x{H}px ({W*res_x:.1f}m x {H*res_y:.1f}m) " f"-> {out_dir / (name + '_{before,after}.png')}") return bb, aa def main(): if len(sys.argv) >= 3: before, after = Path(sys.argv[1]), Path(sys.argv[2]) else: before = Path(r"C:\Users\Priyanka\Downloads\1.tif") after = Path(r"C:\Users\Priyanka\Downloads\2.tif") out_dir = Path(__file__).resolve().parent.parent / "data" / "roi_test" print(f"source before: {before.name}\nsource after : {after.name}\nout: {out_dir}") for name, roi in BLOCKS.items(): crop_block(before, after, roi, out_dir, name) print("done") if __name__ == "__main__": main()