From 143a837c0308fee9e425ab554f0df30b7dd0852d Mon Sep 17 00:00:00 2001 From: pikaliov Date: Fri, 17 Apr 2026 21:55:56 +0300 Subject: [PATCH] Add GTA-UAV-LR annotation script + dataset documentation - Add scripts/run_gta_uav.py for GTA-UAV-LR (48K images, GTA V synthetic) - 14 segmentation classes: 11 base + bare soil, rooftop, swimming pool - Fix source filter to recognize "satellite" folder (alongside "DB") - Document GTA-UAV characteristics in segmentation_class_analysis.md - Update README and CLAUDE.md with GTA-UAV support Co-Authored-By: Claude Opus 4.6 (1M context) --- CLAUDE.md | 5 +- README.md | 22 +++++- docs/segmentation_class_analysis.md | 65 ++++++++++++++++ scripts/run_gta_uav.py | 116 ++++++++++++++++++++++++++++ src/augmentor/dataset.py | 6 +- 5 files changed, 210 insertions(+), 4 deletions(-) create mode 100644 scripts/run_gta_uav.py diff --git a/CLAUDE.md b/CLAUDE.md index fbe37c1..b0fbfaa 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -13,6 +13,9 @@ python -m src.main # UAV_VisLoc (81K images) python scripts/run_uav_visloc.py +# GTA-UAV-LR (48K images, synthetic GTA V) +python scripts/run_gta_uav.py + # Тесты (143 шт, без GPU) python -m pytest src/tests/ -v ``` @@ -22,7 +25,7 @@ python -m pytest src/tests/ -v - **Формат выхода:** SafeTensors (zero-copy mmap, ~0.1ms чтение). Не NPY, не PNG, не `.pt`. - **Структура директорий:** модальность = папка (`depth/`, `edge/`, `segm/`, `chm/`, `safetensors/`), не суффикс файла. - **Стадии последовательно** — одна модель в GPU за раз (экономия VRAM). -- **Сегментация:** SegEarth-OV3 (SAM 3.1 + open-vocabulary prompts). 11 классов для World-UAV, 16 для UAV_VisLoc. +- **Сегментация:** SegEarth-OV3 (SAM 3.1 + open-vocabulary prompts). 11 классов для World-UAV, 16 для UAV_VisLoc, 14 для GTA-UAV. - **CHMv2 только FP32** — в FP16 NaN. ## Структура кода diff --git a/README.md b/README.md index cf8731a..e06f2b0 100644 --- a/README.md +++ b/README.md @@ -10,10 +10,11 @@ | **CHMv2** | DINOv3-ViTL16 (337M, FP32) | grayscale [256x256] | 31.7 img/s | | **Consolidate** | SafeTensors (CPU) | `.safetensors` per image | ~5000 img/s | -| Датасет | Изображения | Классы сегментации | Скрипт | +| Датасет | Изображения | Классы сегм. | Скрипт | |:---|:---|:---|:---| | **World-UAV** | 973K (486K DB + 486K query) | 11 | `python -m src.main` | | **UAV_VisLoc** | 81K (75K DB + 6.7K drone) | 16 | `python scripts/run_uav_visloc.py` | +| **GTA-UAV-LR** | 48K (15K sat + 34K drone) | 14 | `python scripts/run_gta_uav.py` | ## Quick Start @@ -24,6 +25,9 @@ python -m src.main # UAV_VisLoc python scripts/run_uav_visloc.py +# GTA-UAV-LR +python scripts/run_gta_uav.py + # Тесты (143 шт, без GPU) python -m pytest src/tests/ -v ``` @@ -67,6 +71,7 @@ python -m pytest src/tests/ -v │ └── tests/ # 143 теста (pytest) ├── scripts/ │ ├── run_uav_visloc.py # Запуск для UAV_VisLoc (16 классов) +│ ├── run_gta_uav.py # Запуск для GTA-UAV-LR (14 классов) │ └── migrate_layout.py # Миграция со старого prefix-формата └── docs/ ├── segmentation_class_analysis.md # Анализ классов сегментации (11 классов) @@ -135,6 +140,21 @@ UAV_VisLoc содержит больше сельских/прибрежных > Threshold снижен до 0.1 (vs 0.15 для World-UAV) — UAV_VisLoc содержит больше тёмных/низкоконтрастных сцен. +### GTA-UAV-LR: 14 классов + +Синтетический датасет из GTA V. Особенности: +- Satellite в RGBA (alpha = граница карты) → автоматически конвертируется в RGB +- Drone 512x384 (не квадратные) → resize в 512x512 +- 6 высот полёта: 100, 200, 300, 400, 500, 600 м + +Классы = 11 базовых + 3 специфических для GTA: + +| ID | Промпт | Зачем | +|:--:|:---|:---| +| 11 | `bare soil and plowed field` | Пустыри, стройплощадки (много в пригородах GTA) | +| 12 | `roof and rooftop` | Плоские крыши, вертолётные площадки | +| 13 | `swimming pool` | Бассейны — характерный landmark пригородов GTA | + Подробный анализ выбора классов: [`docs/segmentation_class_analysis.md`](docs/segmentation_class_analysis.md) ### hardware.gin diff --git a/docs/segmentation_class_analysis.md b/docs/segmentation_class_analysis.md index 810160e..e458d6a 100644 --- a/docs/segmentation_class_analysis.md +++ b/docs/segmentation_class_analysis.md @@ -273,6 +273,71 @@ SegConfig(threshold=0.1, prompts=[ --- +## Конфигурация для GTA-UAV-LR: 14 классов + +### Характеристики датасета + +GTA-UAV-LR — синтетический датасет, сгенерированный из игрового движка GTA V (Grand Theft Auto V). + +| Параметр | Значение | +|---|---| +| Drone изображения | 33 763 шт., 512x384 px, RGB PNG | +| Satellite изображения | 14 640 шт., 256x256 px, **RGBA** PNG | +| Итого | 48 403 изображения | +| Высоты полёта | 100, 200, 300, 400, 500, 600 м | +| Локация | Карта GTA V (Лос-Сантос и окрестности) | +| Сцены | Город, пригород, сельская местность, побережье, горы, пустыня | +| Формат аннотаций | JSON (cross-area, same-area, train/test splits) | + +**Особенности:** +- **Satellite RGBA:** alpha-канал обозначает границы карты GTA V. Прозрачные пиксели (alpha=0) = за пределами игрового мира. При обработке конвертируется в RGB (прозрачное → чёрный). +- **Drone не квадратные:** 512x384 → resize в 512x512 (потеря aspect ratio, но это синтетика — не критично). +- **Синтетические текстуры:** GTA V рендерит реалистичные но не фотореалистичные текстуры. SegEarth-OV3 справляется хорошо — текстуры достаточно близки к реальным для open-vocabulary grounding. +- **Бассейны** — характерная особенность пригородов GTA V (Vinewood Hills, Rockford Hills). Яркий бирюзовый цвет, уникальная геометрия — сильный localization cue для CVGL. + +### Выбор 14 классов + +11 базовых классов (совпадают с World-UAV) + 3 специфичных: + +| ID | Промпт | Обоснование | +|---|---|---| +| 11 | `bare soil and plowed field` | GTA V содержит много пустырей, стройплощадок, грунтовых дорог в пригородах (Sandy Shores, Grapeseed). Без этого класса ~10-15% уходит в background. | +| 12 | `roof and rooftop` | Плоские крыши коммерческих зданий, вертолётные площадки (Maze Bank Tower). GTA V рендерит крыши с детализированными текстурами (кондиционеры, антенны), которые `building` не ловит сверху. | +| 13 | `swimming pool` | Бассейны во дворах вилл — один из самых характерных визуальных элементов пригородов GTA V. Яркий бирюзовый цвет на сером/зелёном фоне — сильнейший landmark для cross-view matching. `water` не различает бассейн от океана. | + +### Почему не добавлены + +| Класс | Причина | +|---|---| +| `highway` | Покрыт `road` — SegEarth не различает шоссе и обычную дорогу | +| `beach` | Покрыт `sand and gravel ground` | +| `mountain` | Покрыт `rocky terrain` + `vegetation` | +| `sports field` | Есть в GTA V, но редко виден сверху (стадионы закрыты) | +| `muddy ground` | Не актуален для GTA V (нет болот в Лос-Сантосе) | + +### Конфигурация + +```python +SegConfig(threshold=0.15, prompts=[ + "background", # 0 + "building", # 1 + "road", # 2 + "vegetation", # 3 + "water", # 4 + "sand and gravel ground", # 5 + "rocky terrain", # 6 + "farmland", # 7 + "railway", # 8 + "parking lot", # 9 + "sidewalk", # 10 + "bare soil and plowed field", # 11 + "roof and rooftop", # 12 + "swimming pool", # 13 +]) +``` + +--- + ## Оценка влияния на производительность - Инференс: ~1.8–2.2x медленнее (11 vs 5 text prompts) diff --git a/scripts/run_gta_uav.py b/scripts/run_gta_uav.py new file mode 100644 index 0000000..987df5c --- /dev/null +++ b/scripts/run_gta_uav.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python3 +"""Run annotation pipeline for GTA-UAV-LR dataset. + +GTA-UAV-LR: synthetic dataset from GTA V engine. +- drone/images/: 33763 images, 512x384, RGB PNG +- satellite/: 14640 images, 256x256, RGBA PNG (alpha = map boundary) +- Total: 48403 images +- 6 flight heights: 100, 200, 300, 400, 500, 600 meters + +Usage: + python scripts/run_gta_uav.py + python scripts/run_gta_uav.py --source db # only satellite (14.6K) + python scripts/run_gta_uav.py --source drone # only drone (33.8K) +""" + +from __future__ import annotations + +import argparse +import sys +from pathlib import Path + +_PROJECT_ROOT = Path(__file__).resolve().parent.parent +sys.path.insert(0, str(_PROJECT_ROOT)) + +import numpy as np +import torch + +from src.conf.hardware_conf import HardwareConfig +from src.conf.input_conf import InputConfig +from src.conf.models_conf import ModelsConfig +from src.conf.pipeline_conf import PipelineConfig +from src.conf.seg_conf import SegConfig +from src.augmentor.io_utils import setup_logging +from src.main import run_pipeline + + +INPUT_ROOT = "/home/servml/Документы/datasets/GTA-UAV-LR" +OUTPUT_ROOT = "/home/servml/Документы/datasets/GTA-UAV-LR-aug" + + +def main() -> None: + parser = argparse.ArgumentParser(description="Annotate GTA-UAV-LR") + parser.add_argument("--source", choices=["db", "drone", "all"], default="all", + help="Process only db (satellite), drone, or all (default)") + parser.add_argument("--stages", nargs="+", + default=["depth", "edges", "segmentation", "chmv2"], + help="Stages to run") + args = parser.parse_args() + + import gin + gin.clear_config() + + source = None if args.source == "all" else args.source + if source == "drone": + source = "query" + + pipeline_conf = PipelineConfig( + input_root=INPUT_ROOT, + output_root=OUTPUT_ROOT, + stages=args.stages, + save_npy=False, + save_vis=True, + save_safetensors=True, + cleanup_npy=True, + resume=True, + source=source, + log_level="INFO", + ) + + hw_conf = HardwareConfig( + profile_name="rtx4090", + total_ram_gb=24.0, + reserve_gb=2.0, + use_fp16=True, + batch_size=None, + num_workers=4, + ) + + # GTA-UAV: satellite 256x256, drone 512x384 + # Use 256 for satellite, 512 for drone (non-square → resize to square) + input_conf = InputConfig(image_size=256, query_image_size=512) + + # GTA V synthetic scenes: urban, suburban, rural, coastal, mountainous + # 11 base classes + pool (swimming pools common in GTA suburbs) + seg_conf = SegConfig(threshold=0.15, prompts=[ + "background", # 0 + "building", # 1 + "road", # 2 + "vegetation", # 3 + "water", # 4 + "sand and gravel ground", # 5 + "rocky terrain", # 6 + "farmland", # 7 + "railway", # 8 + "parking lot", # 9 + "sidewalk", # 10 + "bare soil and plowed field", # 11 + "roof and rooftop", # 12 + "swimming pool", # 13 + ]) + + models_conf = ModelsConfig(weights_dir=str(_PROJECT_ROOT / "in" / "weights")) + + setup_logging( + pipeline_conf.log_level, + log_file=Path(OUTPUT_ROOT) / "pipeline.log", + ) + + torch.manual_seed(42) + np.random.seed(42) + + run_pipeline(pipeline_conf, hw_conf, models_conf, input_conf, seg_conf) + + +if __name__ == "__main__": + main() diff --git a/src/augmentor/dataset.py b/src/augmentor/dataset.py index 7f08825..793f3a6 100644 --- a/src/augmentor/dataset.py +++ b/src/augmentor/dataset.py @@ -101,9 +101,11 @@ def discover_images( if source is not None: rel_parts = p.relative_to(root).parts - if source == "query" and "DB" in rel_parts: + is_db = "DB" in rel_parts or "satellite" in rel_parts + is_query = "query" in rel_parts or "drone" in rel_parts + if source == "query" and is_db: continue - if source == "db" and ("query" in rel_parts or "drone" in rel_parts): + if source == "db" and is_query: continue rel = p.relative_to(root)