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) <noreply@anthropic.com>
This commit is contained in:
pikaliov
2026-04-17 21:55:56 +03:00
parent 27eb315903
commit 143a837c03
5 changed files with 210 additions and 4 deletions

View File

@@ -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.
## Структура кода

View File

@@ -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

View File

@@ -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.82.2x медленнее (11 vs 5 text prompts)

116
scripts/run_gta_uav.py Normal file
View File

@@ -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()

View File

@@ -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)