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:
@@ -13,6 +13,9 @@ python -m src.main
|
|||||||
# UAV_VisLoc (81K images)
|
# UAV_VisLoc (81K images)
|
||||||
python scripts/run_uav_visloc.py
|
python scripts/run_uav_visloc.py
|
||||||
|
|
||||||
|
# GTA-UAV-LR (48K images, synthetic GTA V)
|
||||||
|
python scripts/run_gta_uav.py
|
||||||
|
|
||||||
# Тесты (143 шт, без GPU)
|
# Тесты (143 шт, без GPU)
|
||||||
python -m pytest src/tests/ -v
|
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`.
|
- **Формат выхода:** SafeTensors (zero-copy mmap, ~0.1ms чтение). Не NPY, не PNG, не `.pt`.
|
||||||
- **Структура директорий:** модальность = папка (`depth/`, `edge/`, `segm/`, `chm/`, `safetensors/`), не суффикс файла.
|
- **Структура директорий:** модальность = папка (`depth/`, `edge/`, `segm/`, `chm/`, `safetensors/`), не суффикс файла.
|
||||||
- **Стадии последовательно** — одна модель в GPU за раз (экономия VRAM).
|
- **Стадии последовательно** — одна модель в 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.
|
- **CHMv2 только FP32** — в FP16 NaN.
|
||||||
|
|
||||||
## Структура кода
|
## Структура кода
|
||||||
|
|||||||
22
README.md
22
README.md
@@ -10,10 +10,11 @@
|
|||||||
| **CHMv2** | DINOv3-ViTL16 (337M, FP32) | grayscale [256x256] | 31.7 img/s |
|
| **CHMv2** | DINOv3-ViTL16 (337M, FP32) | grayscale [256x256] | 31.7 img/s |
|
||||||
| **Consolidate** | SafeTensors (CPU) | `.safetensors` per image | ~5000 img/s |
|
| **Consolidate** | SafeTensors (CPU) | `.safetensors` per image | ~5000 img/s |
|
||||||
|
|
||||||
| Датасет | Изображения | Классы сегментации | Скрипт |
|
| Датасет | Изображения | Классы сегм. | Скрипт |
|
||||||
|:---|:---|:---|:---|
|
|:---|:---|:---|:---|
|
||||||
| **World-UAV** | 973K (486K DB + 486K query) | 11 | `python -m src.main` |
|
| **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` |
|
| **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
|
## Quick Start
|
||||||
|
|
||||||
@@ -24,6 +25,9 @@ python -m src.main
|
|||||||
# UAV_VisLoc
|
# UAV_VisLoc
|
||||||
python scripts/run_uav_visloc.py
|
python scripts/run_uav_visloc.py
|
||||||
|
|
||||||
|
# GTA-UAV-LR
|
||||||
|
python scripts/run_gta_uav.py
|
||||||
|
|
||||||
# Тесты (143 шт, без GPU)
|
# Тесты (143 шт, без GPU)
|
||||||
python -m pytest src/tests/ -v
|
python -m pytest src/tests/ -v
|
||||||
```
|
```
|
||||||
@@ -67,6 +71,7 @@ python -m pytest src/tests/ -v
|
|||||||
│ └── tests/ # 143 теста (pytest)
|
│ └── tests/ # 143 теста (pytest)
|
||||||
├── scripts/
|
├── scripts/
|
||||||
│ ├── run_uav_visloc.py # Запуск для UAV_VisLoc (16 классов)
|
│ ├── run_uav_visloc.py # Запуск для UAV_VisLoc (16 классов)
|
||||||
|
│ ├── run_gta_uav.py # Запуск для GTA-UAV-LR (14 классов)
|
||||||
│ └── migrate_layout.py # Миграция со старого prefix-формата
|
│ └── migrate_layout.py # Миграция со старого prefix-формата
|
||||||
└── docs/
|
└── docs/
|
||||||
├── segmentation_class_analysis.md # Анализ классов сегментации (11 классов)
|
├── segmentation_class_analysis.md # Анализ классов сегментации (11 классов)
|
||||||
@@ -135,6 +140,21 @@ UAV_VisLoc содержит больше сельских/прибрежных
|
|||||||
|
|
||||||
> Threshold снижен до 0.1 (vs 0.15 для World-UAV) — 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)
|
Подробный анализ выбора классов: [`docs/segmentation_class_analysis.md`](docs/segmentation_class_analysis.md)
|
||||||
|
|
||||||
### hardware.gin
|
### hardware.gin
|
||||||
|
|||||||
@@ -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)
|
- Инференс: ~1.8–2.2x медленнее (11 vs 5 text prompts)
|
||||||
|
|||||||
116
scripts/run_gta_uav.py
Normal file
116
scripts/run_gta_uav.py
Normal 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()
|
||||||
@@ -101,9 +101,11 @@ def discover_images(
|
|||||||
|
|
||||||
if source is not None:
|
if source is not None:
|
||||||
rel_parts = p.relative_to(root).parts
|
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
|
continue
|
||||||
if source == "db" and ("query" in rel_parts or "drone" in rel_parts):
|
if source == "db" and is_query:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
rel = p.relative_to(root)
|
rel = p.relative_to(root)
|
||||||
|
|||||||
Reference in New Issue
Block a user