Refactor output to directory-based layout + migration script
Replace prefix-based naming (crop_12_4_depth.png) with directory-based
layout where modality is determined by folder (depth/crop_12_4.png).
New structure:
output_root/{modality}/{rel_parent}/{stem}.png (vis)
output_root/npy/{modality}/{rel_parent}/{stem}.npy (intermediate)
output_root/safetensors/{rel_parent}/{stem}.safetensors (training)
- Rewrite io_utils.py save functions: (output_root, rel_parent, stem)
- Update ImageRecord: output_root + rel_parent instead of output_dir
- Add path helpers: npy_path(), vis_path(), safetensors_path()
- Add scripts/migrate_layout.py for converting existing datasets
- Update all tests (143 passing)
- Update README with new layout docs
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
49
README.md
49
README.md
@@ -58,7 +58,9 @@ python -m pytest src/tests/ -v
|
||||
│ │ └── dataset.py # Discovery, filtering, PyTorch Dataset
|
||||
│ ├── conf/ # Gin-configurable dataclasses
|
||||
│ ├── utils/ # Profiler, benchmark, GPU utils
|
||||
│ └── tests/ # 141 тест (pytest)
|
||||
│ └── tests/ # 143 теста (pytest)
|
||||
├── scripts/
|
||||
│ └── migrate_layout.py # Миграция со старого prefix-формата
|
||||
└── docs/
|
||||
├── segmentation_class_analysis.md # Анализ классов сегментации (11 классов)
|
||||
├── segearth_ov3_architecture.md # Архитектура SegEarth-OV3 + SAM 3.1
|
||||
@@ -145,22 +147,24 @@ free_vram = total - reserved
|
||||
batch = round_down_pow2(free_vram / act_per_sample * 0.7)
|
||||
```
|
||||
|
||||
**Resume** проверяет существование `{stem}_{suffix}.png` (или `.npy`) для каждого изображения и `{stem}.safetensors` для этапа консолидации. Пайплайн можно прервать Ctrl+C и перезапустить -- готовые пропускаются.
|
||||
**Resume** проверяет существование файлов в соответствующих директориях модальностей. Пайплайн можно прервать Ctrl+C и перезапустить -- готовые пропускаются.
|
||||
|
||||
## Формат выхода
|
||||
|
||||
Структура директорий **зеркалит** исходный датасет. Исходные изображения не копируются:
|
||||
Модальность определяется **папкой**, а не суффиксом файла:
|
||||
|
||||
```
|
||||
World-UAV-aug/
|
||||
├── Rot/SouthernSuburbs/DB/img/
|
||||
│ ├── crop_12_4.safetensors # ВСЕ модальности (для обучения, zero-copy mmap)
|
||||
│ ├── crop_12_4_depth.png # grayscale визуализация
|
||||
│ ├── crop_12_4_edge.png # grayscale визуализация
|
||||
│ ├── crop_12_4_segm.png # RGB palette визуализация (11 классов)
|
||||
│ └── crop_12_4_chm.png # grayscale визуализация
|
||||
├── Country/...
|
||||
└── Terrain/...
|
||||
├── depth/Rot/SouthernSuburbs/DB/img/crop_12_4.png # vis
|
||||
├── edge/Rot/SouthernSuburbs/DB/img/crop_12_4.png # vis
|
||||
├── segm/Rot/SouthernSuburbs/DB/img/crop_12_4.png # vis (palette mode P)
|
||||
├── chm/Rot/SouthernSuburbs/DB/img/crop_12_4.png # vis
|
||||
├── npy/depth/Rot/SouthernSuburbs/DB/img/crop_12_4.npy # float16 intermediate
|
||||
├── npy/edge/...
|
||||
├── npy/segm/...
|
||||
├── npy/chm/...
|
||||
├── safetensors/Rot/SouthernSuburbs/DB/img/crop_12_4.safetensors # для обучения
|
||||
└── manifest.json
|
||||
```
|
||||
|
||||
### SafeTensors (рекомендуемый формат для обучения)
|
||||
@@ -213,10 +217,11 @@ World-UAV-aug/
|
||||
from safetensors.torch import load_file
|
||||
|
||||
stem = "crop_12_4"
|
||||
aug_dir = Path("World-UAV-aug/Rot/SouthernSuburbs/DB/img")
|
||||
aug_root = Path("World-UAV-aug")
|
||||
rel_parent = "Rot/SouthernSuburbs/DB/img"
|
||||
|
||||
# Zero-copy чтение всех модальностей за ~0.1ms
|
||||
data = load_file(aug_dir / f"{stem}.safetensors", device="cpu")
|
||||
data = load_file(aug_root / "safetensors" / rel_parent / f"{stem}.safetensors", device="cpu")
|
||||
|
||||
depth = data["depth"] # [1, 256, 256] float16, [0, 1]
|
||||
edge = data["edge"] # [1, 256, 256] float16, [0, 1]
|
||||
@@ -236,13 +241,25 @@ from PIL import Image
|
||||
import numpy as np
|
||||
|
||||
# Depth / Edge / CHM -- grayscale float [0, 1]
|
||||
depth = np.array(Image.open(aug_dir / f"{stem}_depth.png")) / 255.0 # [H, W]
|
||||
edge = np.array(Image.open(aug_dir / f"{stem}_edge.png")) / 255.0
|
||||
chm = np.array(Image.open(aug_dir / f"{stem}_chm.png")) / 255.0
|
||||
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
|
||||
```
|
||||
|
||||
> PNG визуализации квантуют float16 в uint8 (256 уровней). Для обучения используйте SafeTensors.
|
||||
|
||||
### Миграция со старого формата
|
||||
|
||||
Если данные сгенерированы в старом prefix-формате (`crop_12_4_depth.png`), мигрируйте:
|
||||
|
||||
```bash
|
||||
# Сначала проверить (dry-run)
|
||||
python scripts/migrate_layout.py /mnt/data1tb/cvgl_datasets/World-UAV-aug --dry-run
|
||||
|
||||
# Выполнить миграцию
|
||||
python scripts/migrate_layout.py /mnt/data1tb/cvgl_datasets/World-UAV-aug
|
||||
```
|
||||
|
||||
## Скачивание весов
|
||||
|
||||
Веса скачиваются один раз в `in/weights/` (~10 GB суммарно):
|
||||
|
||||
Reference in New Issue
Block a user