From 75502b481ead972223b391c08ee0b54f0c658b9d Mon Sep 17 00:00:00 2001 From: pikaliov Date: Sat, 18 Apr 2026 04:10:57 +0300 Subject: [PATCH] Docs: clarify dense tensor maps format and training usage All modalities are stored as dense spatial tensor maps (not RGB renders): - depth/edge/chm: [1,H,W] float16 continuous values - segm: [1,H,W] uint8 dense class ID map (0-16) Add training code examples: one-hot encoding, per-class embedding, aux-encoder injection. Document why tensors over RGB renders (70% info loss + OOD for DINOv3). Co-Authored-By: Claude Opus 4.6 (1M context) --- CLAUDE.md | 4 ++-- README.md | 64 +++++++++++++++++++++++++++++++++---------------------- 2 files changed, 40 insertions(+), 28 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 92a119c..b88f889 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -30,7 +30,7 @@ python -m pytest src/tests/ -v ## Ключевые решения -- **Формат выхода:** SafeTensors (zero-copy mmap, ~0.1ms чтение). Не NPY, не PNG, не `.pt`. +- **Формат выхода:** SafeTensors с **dense tensor maps** (zero-copy mmap, ~0.1ms). Все модальности — прямые тензоры (float16/uint8), не RGB-рендеры. - **Структура директорий:** модальность = папка (`depth/`, `edge/`, `segm/`, `chm/`, `safetensors/`), не суффикс файла. - **Стадии последовательно** — одна модель в GPU за раз (экономия VRAM). - **Сегментация:** SegEarth-OV3 (SAM 3.1 + open-vocabulary prompts). **17 unified классов** для всех датасетов (единые ID для transfer learning). @@ -66,6 +66,6 @@ docs/ — документация - Не менять порядок/ID классов в `scripts/seg_classes.py` — все датасеты зависят от фиксированных ID. - Не использовать `.pt` (torch.save) для хранения тензоров — pickle, медленно. -- Не рендерить depth/seg в RGB colormap для обучения — OOD для DINOv3, потеря информации. +- Не рендерить depth/seg в RGB colormap для обучения — OOD для DINOv3, потеря ~70% информации. Использовать dense tensor maps из SafeTensors. - Не снижать threshold ниже 0.1 — увеличивает false positives без значимого улучшения recall. - Не менять `dark_water_std_thr` (0.18) — калибровано на GTA-UAV ocean (std 0.10-0.15). Ниже — не ловит, выше — false positives на normal images. diff --git a/README.md b/README.md index bfaf6f5..43835fc 100644 --- a/README.md +++ b/README.md @@ -198,10 +198,10 @@ World-UAV-aug/ | Ключ | Dtype | Shape | Описание | |:---|:---|:---|:---| -| `depth` | float16 | [1, H, W] | Карта глубины [0, 1] | -| `edge` | float16 | [1, H, W] | Границы (Sobel) [0, 1] | -| `chm` | float16 | [1, H, W] | Canopy height [0, 1] | -| `segm` | uint8 | [1, H, W] | Class IDs [0, 10] (World-UAV) / [0, 16] (unified) | +| `depth` | float16 | [1, H, W] | Dense depth map, непрерывная [0, 1], per-frame normalized | +| `edge` | float16 | [1, H, W] | Dense edge map (Sobel magnitude), [0, 1] | +| `chm` | float16 | [1, H, W] | Dense canopy height map, [0, 1], per-frame normalized | +| `segm` | uint8 | [1, H, W] | Dense class ID map, значения [0, 16] (17 unified классов) | Преимущества SafeTensors: - **Zero-copy mmap** -- тензор читается прямо с диска без копирования в RAM (~0.1ms) @@ -242,42 +242,54 @@ World-UAV-aug/ ## Использование для обучения +Все модальности хранятся как **dense tensor maps** — прямые тензоры, не RGB-рендеры. Это ключевое решение (см. [dialog_fusion_modalities](docs/segmentation_class_analysis.md)): тензоры сохраняют полную информацию без потерь при квантовании/colormapping и не являются OOD-входом для DINOv3. + ### SafeTensors (рекомендуемый способ) ```python from safetensors.torch import load_file - -stem = "crop_12_4" -aug_root = Path("World-UAV-aug") -rel_parent = "Rot/SouthernSuburbs/DB/img" +import torch.nn.functional as F # Zero-copy чтение всех модальностей за ~0.1ms -data = load_file(aug_root / "safetensors" / rel_parent / f"{stem}.safetensors", device="cpu") +data = load_file("World-UAV-aug/safetensors/Rot/.../crop_12_4.safetensors") -depth = data["depth"] # [1, 256, 256] float16, [0, 1] -edge = data["edge"] # [1, 256, 256] float16, [0, 1] -chm = data["chm"] # [1, 256, 256] float16, [0, 1] -segm = data["segm"] # [1, 256, 256] uint8, class IDs [0, 10] - -# Для Teacher NADEZHDA: segm -> one-hot -import torch.nn.functional as F -segm_onehot = F.one_hot(segm.long().squeeze(0), num_classes=17) # [H, W, 17] -segm_onehot = segm_onehot.permute(2, 0, 1).float() # [17, H, W] +# Все модальности — dense spatial maps, готовые для injection в backbone +depth = data["depth"] # [1, H, W] float16, непрерывная глубина [0, 1] +edge = data["edge"] # [1, H, W] float16, Sobel magnitude [0, 1] +chm = data["chm"] # [1, H, W] float16, canopy height [0, 1] +segm = data["segm"] # [1, H, W] uint8, dense class ID map [0, 16] ``` -### PNG fallback (для визуализации или legacy) +### Подача в Teacher NADEZHDA + +Каждая модальность подаётся в свой lightweight aux-encoder, затем через FiLM/Conv1x1 injection в DINOv3 patch tokens: ```python -from PIL import Image -import numpy as np +# Depth / Edge / CHM → [B, 1, H, W] float → Conv aux-encoder → FiLM injection +# Прямые тензоры, НЕ RGB-рендеры (turbo colormap = потеря 70% информации + OOD) +aux_depth = depth_encoder(depth.float()) # [1, H, W] → [C, H, W] +aux_edge = edge_encoder(edge.float()) +aux_chm = chm_encoder(chm.float()) -# Depth / Edge / CHM -- grayscale float [0, 1] -depth = np.array(Image.open(aug_root / "depth" / rel_parent / f"{stem}.png")) / 255.0 -edge = np.array(Image.open(aug_root / "edge" / rel_parent / f"{stem}.png")) / 255.0 -chm = np.array(Image.open(aug_root / "chm" / rel_parent / f"{stem}.png")) / 255.0 +# Segmentation → dense class ID map → per-class embedding → spatial feature map +# Вариант 1: one-hot → Conv +segm_onehot = F.one_hot(segm.long().squeeze(0), num_classes=17) # [H, W, 17] +segm_features = seg_conv(segm_onehot.permute(2, 0, 1).float()) # [17, H, W] → [C, H, W] + +# Вариант 2: learned per-class embedding (SegAuxEncoder) +# seg_emb = nn.Embedding(17, 32) +# segm_features = seg_emb(segm.long().squeeze(0)).permute(2, 0, 1) # [H, W] → [32, H, W] ``` -> PNG визуализации квантуют float16 в uint8 (256 уровней). Для обучения используйте SafeTensors. +### Почему тензоры, а не RGB-рендеры + +| Формат | Пример depth | Потеря информации | Для DINOv3 | +|---|---|---|---| +| `float16` тензор (хранится) | `[0.4231, 0.4235, ...]` | ~0% | Прямой вход в aux-encoder | +| `uint8` grayscale PNG | `[108, 108, ...]` | ~0.4% | Приемлемо | +| `turbo colormap` RGB PNG | `[R=50, G=180, B=220]` | **~70%** | **OOD** — DINOv3 обучен на натуральных RGB | + +> Для обучения **всегда** используйте SafeTensors. PNG визуализации — только для просмотра в Obsidian/файловом менеджере. ### Миграция со старого формата