Files
caption-test/CLAUDE.md
pikaliov 5da791801c Update docs: target-size 512, dataset verification results
- UAV-VisLoc processed at 512x512 (for segmentation/depth/normals)
- Dataset verified: 6744 drone, 74807 crops, median match 25.9m
- Known issue: 6 drones in route 06 outside satellite coverage
- Resize to model input size (224/256) in dataloader

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-18 02:41:31 +03:00

11 KiB
Raw Blame History

Caption Quality Test for Cross-View Geo-Localization

Архитектура системы (v2, 2026-04-17)

QUERY BRANCH (drone + caption):
  drone_img --> GeoRSCLIP ViT-B/32 (frozen) --> drone_feat [B,512]
  caption   --> GeoRSCLIP Text (partial unfreeze) --> text_feat [B,512]
                     |
              GatedFusion: q = sigma(alpha)*drone + (1-sigma(alpha))*text
                     |
              proj_query (Linear 512->512) --> L2-norm --> query [B,512]

GALLERY BRANCH (satellite only):
  sat_img --> GeoRSCLIP ViT-B/32 (frozen) --> sat_feat [B,512]
                     |
              proj_gallery (Linear 512->512) --> L2-norm --> gallery [B,512]

LOSS: InfoNCE(query, gallery) — symmetric, asymmetric weights (0.6 q->g, 0.4 g->q)
BASELINE: gate = 1.0 (text ignored)

Ключевые файлы

Файл Назначение
src/models/dual_encoder.py GeoRSCLIP + GatedFusion + projection heads
src/losses/multi_infonce.py InfoNCE с cosine temperature schedule
src/datasets/visloc_with_captions.py UAV-GeoLoc loader + template captions из path metadata
src/training/train.py Training loop, логирование loss/gate/tau
src/eval/evaluate.py R@K metrics, delta_r_at_1
scripts/compare_runs.py Markdown/JSON сравнение baseline vs caption runs
scripts/generate_captions.py Offline caption generation (template/VLM/hybrid)

Backbone: GeoRSCLIP ViT-B/32

  • Checkpoint: checkpoints/RS5M_ViT-B-32.pt (скачать с github.com/om-ai-lab/RS5M)
  • Image encoder: ViT-B/32, 224x224, 512-dim, ~86M params — frozen
  • Text encoder: CLIP text transformer, 77 tokens, 512-dim — partial unfreeze (last_block + text_projection)
  • Throughput: ~4000 img/s на RTX 4090 (AMP, batch 128)
  • Выбран вместо SigLIP 2 (ViT-SO400M, 384px, ~400M): в 7-10x быстрее, domain-specific (обучен на 5M RS-изображений), больше batch = больше негативов в InfoNCE

GatedFusion

  • query = sigma(alpha) * drone_feat + (1 - sigma(alpha)) * text_feat
  • alpha — один learnable scalar в logit-space
  • init_gate = 0.7 → начальный вес image = 70%, text = 30%
  • baseline_mode = True → gate = 1.0, text полностью игнорируется
  • Gate value логируется каждую эпоху для интерпретации вклада текста

Датасет: UAV-GeoLoc

  • Путь: /mnt/data1tb/cvgl_datasets/UAV-GeoLoc/
  • Train: 206,108 queries, 94,709 DB crops (140 scenes, Terrain split)
  • Val: 62,368 queries, 26,597 DB crops (40 scenes)
  • Test: 33,472 queries, 11,684 DB crops (20 scenes)
  • Структура: Terrain/{type}/{scene}/query/height{N}_rot{M}/footage/{file}.jpeg
  • Index: Index/train_query.txtquery_path 0 pos_crop1 pos_crop2 ...

Template captions (из path metadata)

Формат: "Aerial view at {height}m facing {heading} over {terrain} terrain near {scene}. Plan-view features: {features}."

Пример: "Aerial view at 100m facing northwest over volcanic terrain near KilaueaVolcano. Plan-view features: lava flows, crater edges, volcanic rock."

Metadata извлекается из пути:

  • Terrain/Volcano/KilaueaVolcano/query/height100_rot315/... → terrain=Volcano, scene=KilaueaVolcano, height=100, heading=northwest
  • 27 terrain типов с predefined features (Volcano, Mountain, Hill, Desert, Plain, ...)
  • Country subset: features = "buildings, roads, urban blocks, rooftops, intersections"

Конфигурации (gin)

Конфиг Gate init Описание
conf/balanced.gin 0.7 (30% text) Primary test
conf/baseline_no_text.gin 1.0 (no text) Reference baseline
conf/text_heavy.gin 0.3 (70% text) Stress test

Общие параметры: 10 epochs, batch 128, lr=1e-4, AMP, cosine LR schedule, eval every 2 epochs.

Запуск

# 1. Baseline (no text)
python -m src.training.train --config conf/baseline_no_text.gin

# 2. With captions (primary test)
python -m src.training.train --config conf/balanced.gin

# 3. Text-heavy (stress test)
python -m src.training.train --config conf/text_heavy.gin

# 4. Compare
python -m scripts.compare_runs \
    --baseline_report out/caption_test/baseline_no_text/eval_report.json \
    --full_report out/caption_test/balanced/eval_report.json \
    --output out/caption_test/comparison.md

Метрики и Decision rule

Primary metric: Delta R@1 (query -> gallery)

Delta R@1 Verdict
>= +3% PASS — captions informative, proceed to production
+1% to +3% MARGINAL — add VLM refinement, re-run
0 to +1% WEAK — redesign caption pipeline
< 0 HARMFUL — critical bug

Logged per epoch: loss, temperature (tau), gate value (sigma(alpha)), lr Eval metrics: R@1, R@5, R@10 для query->gallery и gallery->query

Бюджет времени (RTX 4090, 24 GB)

Фаза Время
Один training run (10 epochs, 206K queries, batch 128) ~15-30 мин
Full test (3 варианта) ~1-1.5 ч
Evaluation per run ~2-5 мин

Связанные проекты

Text Annotation Pipeline

  • Путь: /home/servml/Документы/pikaliov_obsidian/(Полякова ВЕ_Система для генерации текстовых описаний для БПЛА)/2_work/2_text_annotation/code/
  • VLM: Qwen3-VL-8B AWQ (1.68 s/img)
  • Scoring: SigLIP 2 (drone P3) + CLIP-RSICD (satellite P1+P2)
  • Формат описаний: 3 абзаца (P1 Inventory + P2 Spatial Map + P3 Fingerprint)
  • Метрики: FDR, FNR, NumAcc, LLaVA-Critic C1-C6

UAV-VisLoc Prepare

  • Путь: /home/servml/Документы/code/Yaroslav/UAV-VisLoc-prepare/scripts/prepare_dataset.py
  • Статус: выполнен (2026-04-17), данные в /home/servml/Документы/datasets/UAV_VisLoc_processed/ (25 GB)
  • Задача: нарезка satellite кропов 512x512, stride 256 + resize drone -> 512x512
  • Подробности: см. ниже

Датасеты (справочник)

UAV-VisLoc

  • Путь: /home/servml/Документы/datasets/UAV_VisLoc_dataset/
  • Структура: 11 маршрутов (папки 01-11), каждая содержит:
    • drone/ — drone-снимки (XX_NNNN.JPG)
    • satelliteXX.tif — спутниковая карта
    • XX.csv — GPS-метаданные drone (num, filename, date, lat, lon, height, Omega, Kappa, Phi1, Phi2)
  • Исключение: маршрут 09 — спутник разбит на 4 тайла (satellite09_01-01.tif и т.д.)
  • Satellite coordinates: satellite_ coordinates_range.csv — bbox каждой карты (LT_lat_map, LT_lon_map, RB_lat_map, RB_lon_map)
  • Splits: visloc_train.csv, visloc_test.csv — списки drone-снимков (TSV, full absolute paths)
  • Размеры: Drone 3976x2652 / 3000x2000 (6774 снимков), Satellite от 3000x170 до 43421x38408
  • GSD спутника: ~0.30 м/px (единый zoom level Google Earth для всех карт). GSD по долготе варьируется 0.23-0.27 м/px из-за косинусного эффекта широты (40°N vs 25°N), но это не разная высота съёмки. Кроп 512x512 покрывает ~154x154 м везде.

UAV-GeoLoc

  • Путь: /mnt/data1tb/cvgl_datasets/UAV-GeoLoc/
  • Подмножества: Country (171 scene), Terrain (200 scenes), Rot (1 scene)
  • Формат пар: positive.json, semi_positive.json, db_postion.txt
  • Index: train_query.txtquery_path label pos_crop1 pos_crop2 ...
  • Drone: синтетика Google Earth Studio 3D, 512x512, FOV 30deg, heights 100/125/150m
  • Satellite: кропы из merge.tif, доминирующий размер 200x200

Скрипт подготовки UAV-VisLoc

  • Путь: /home/servml/Документы/code/Yaroslav/UAV-VisLoc-prepare/scripts/prepare_dataset.py
  • Статус: выполнен (2026-04-17)

Запуск

python scripts/prepare_dataset.py \
    --src /home/servml/Документы/datasets/UAV_VisLoc_dataset \
    --dst /home/servml/Документы/datasets/UAV_VisLoc_processed \
    --crop-size 512 --stride 256 --target-size 512

Pipeline

  1. Resize drone -> 512x512 (JPEG, quality=95)
  2. Stitch satellite tiles для маршрута 09 (4 тайла -> 44800x33280)
  3. Нарезка satellite -> кропы 512x512, stride 256, сохранение без downscale (PNG)
  4. GPS для каждого кропа из bbox карты + позиция в grid
  5. Match drone->crop через vectorized haversine (positive = ближайший, semi-positive = +/-1 в grid)
  6. Metadata: positive.json, semi_positive.json, db_postion.txt (per route)
  7. Index: train_query.txt, test_query.txt, train_db.txt, test_db.txt, all_db.txt

Форматы выходных файлов (совместимость с UAV-GeoLoc)

Файл Формат
positive.json {frame_id: [crop_name]}, ключ = frame ID без route prefix ("0001")
semi_positive.json {frame_id: [crop1, crop2, ...]}, соседи +/-1 в grid
db_postion.txt tab-separated: name\tlon\tlat\tscale_lon\tscale_lat
train_query.txt route/drone/file.JPG 0 route/DB/img/crop1.png ...
train_db.txt / test_db.txt все кропы всех маршрутов (gallery одинаковая, split по query)

Результаты (target-size 512)

  • Drone: 6,744 images 512x512 (без маршрута 07: 30 excluded)
  • Satellite кропов: 74,807 (512x512, без downscale)
  • Размер на диске: 25 GB
  • Median distance drone->crop: 25.9m, P99: 45.7m
  • Память при генерации: до ~8.7 GB RAM (маршрут 09 stitched 44800x33280)
  • Разрешение 512 для downstream задач (сегментация, depth, normals); resize до 224/256 в dataloader

Ревью и исправления (2026-04-17)

  1. train_db.txt/test_db.txt содержали только matched кропы -> теперь все ~74K (полная gallery)
  2. db_position.txt -> db_postion.txt (совместимость с UAV-GeoLoc), добавлены scale_lon/scale_lat, tab-separator
  3. positive.json ключи были filename (01_0001.JPG) -> теперь frame_id (0001)
  4. Semi-positive поиск O(n) -> O(1) через dict lookup по (x,y) grid
  5. Удален мёртвый код (haversine_m, defaultdict import)

Известные ограничения

  • Нет val split (только train/test, как в оригинальном UAV-VisLoc)
  • 6 drone в маршруте 06 (06_0093-06_0098) за пределами спутниковой карты (distance >1000m)
  • Большие спутниковые карты загружаются целиком в RAM при генерации (до 8.7 GB для route 09)