Spaces:
Sleeping
Sleeping
Download scripts/build_prototypes.py from AthithyaLogan/SAMSpade: direct link, hf CLI and curl.
- Browser
- Download file 3.5 kB
-
https://huggingface.co/spaces/AthithyaLogan/SAMSpade/resolve/main/scripts/build_prototypes.py
- Command line
-
hf download hf://spaces/AthithyaLogan/SAMSpade/scripts/build_prototypes.py
-
curl -L -o build_prototypes.py https://huggingface.co/spaces/AthithyaLogan/SAMSpade/resolve/main/scripts/build_prototypes.py
3.5 kB
| """Build the global K-means prototype corpus from all 2022 construction tiles. | |
| Run this once after downloading tiles, before training. | |
| Usage:: | |
| python scripts/build_prototypes.py \\ | |
| --tiles data/tiles/ \\ | |
| --k 20 \\ | |
| --out checkpoints/prototypes.pt | |
| The script: | |
| 1. Loads every (tile_2022, mask_2022) pair from the tile directory. | |
| 2. Passes each tile through the frozen SAM2 image encoder. | |
| 3. Extracts foreground feature vectors (where mask > 0). | |
| 4. Runs KMeans(k) across all sites → k cluster centroids. | |
| 5. Saves as a dict: {"prototypes": Tensor[k, 256], "k": int, "inertia": float}. | |
| """ | |
| from __future__ import annotations | |
| import argparse | |
| import logging | |
| import sys | |
| from pathlib import Path | |
| sys.path.insert(0, str(Path(__file__).parent.parent)) | |
| import torch | |
| from omegaconf import OmegaConf | |
| from data.dataset import ConstructionChangeDataset | |
| from models.corpus_prototype import build_corpus_prototypes | |
| from models.detector import ConstructionChangeDetector | |
| logging.basicConfig( | |
| level=logging.INFO, | |
| format="%(asctime)s [%(levelname)s] %(message)s", | |
| ) | |
| logger = logging.getLogger(__name__) | |
| def parse_args() -> argparse.Namespace: | |
| p = argparse.ArgumentParser(description="Build SAM2 prototype corpus from 2022 tiles.") | |
| p.add_argument("--tiles", required=True, help="Root tile directory.") | |
| p.add_argument("--k", type=int, default=20, help="Number of prototype clusters.") | |
| p.add_argument("--out", required=True, help="Output path for prototypes.pt.") | |
| p.add_argument("--config", default="configs/base.yaml") | |
| p.add_argument("--max-fg", type=int, default=2000, help="Max foreground features sampled per site.") | |
| p.add_argument("--max-sites", type=int, default=None, help="Randomly sample this many sites (useful on CPU).") | |
| p.add_argument("--sam2-model", default=None, help="Override SAM2 HF model id (e.g. facebook/sam2.1-hiera-tiny).") | |
| return p.parse_args() | |
| def main() -> None: | |
| args = parse_args() | |
| cfg = OmegaConf.load(args.config) | |
| device = torch.device("cuda" if torch.cuda.is_available() else "cpu") | |
| logger.info("Device: %s", device) | |
| # Load dataset (no augmentation, train split = all) | |
| dataset = ConstructionChangeDataset( | |
| tile_dir=args.tiles, | |
| image_size=cfg.data.image_size, | |
| augment=False, | |
| min_fg_pixels=cfg.data.min_fg_pixels, | |
| ) | |
| logger.info("Dataset: %d samples", len(dataset)) | |
| # Subsample sites if requested (useful on CPU) | |
| if args.max_sites and args.max_sites < len(dataset): | |
| import random, torch.utils.data as tud | |
| indices = random.sample(range(len(dataset)), args.max_sites) | |
| dataset = tud.Subset(dataset, indices) | |
| logger.info("Subsampled to %d sites (--max-sites)", args.max_sites) | |
| # Build model and load SAM2 encoder | |
| sam2_id = args.sam2_model or cfg.model.sam2_hf_id | |
| logger.info("Loading SAM2: %s", sam2_id) | |
| model = ConstructionChangeDetector(k_prototypes=args.k) | |
| model.load_sam2(sam2_id) | |
| model.to(device) | |
| # Build prototypes | |
| Path(args.out).parent.mkdir(parents=True, exist_ok=True) | |
| prototypes = build_corpus_prototypes( | |
| image_encoder=model.image_encoder, | |
| dataset=dataset, | |
| k=args.k, | |
| max_fg_per_site=args.max_fg, | |
| device=device, | |
| output_path=args.out, | |
| ) | |
| logger.info("Prototypes shape: %s", prototypes.shape) | |
| logger.info("Saved to %s", args.out) | |
| if __name__ == "__main__": | |
| main() | |