Initial import: World-UAV prepro

Add dataloaders (v1/v2), analysis scripts, and documentation for working with UAV-GeoLoc (World-UAV).

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-05-09 12:44:49 +03:00
commit 4ff36ce188
72 changed files with 13594 additions and 0 deletions

View File

@@ -0,0 +1,117 @@
"""
Анализ схемы нарезки спутниковых снимков в датасете UAV-GeoLoc.
Скрипт определяет crop_size, stride и overlap для каждой сцены,
сопоставляя кропы с исходным merge.tif через попиксельное сравнение.
Результат: stride = crop_size // 2 (50% overlap) для всех сцен.
Naming: crop_X_Y.png — X по ширине (col), Y по высоте (row).
Позиция в merge.tif: merge[Y*stride : Y*stride+crop_size, X*stride : X*stride+crop_size]
"""
import glob
import os
import numpy as np
from PIL import Image
Image.MAX_IMAGE_PIXELS = None # некоторые merge.tif очень большие
def analyze_scene(scene_db_dir: str) -> dict:
"""Определяет параметры нарезки для одной сцены.
Args:
scene_db_dir: путь к папке DB сцены (содержит merge.tif и img/).
Returns:
dict с ключами: merge_size, crop_size, grid, stride, overlap.
"""
merge_path = os.path.join(scene_db_dir, "merge.tif")
img_dir = os.path.join(scene_db_dir, "img")
merge = np.array(Image.open(merge_path))
mh, mw = merge.shape[:2]
# Размер кропа
c00 = np.array(Image.open(os.path.join(img_dir, "crop_0_0.png")))
ch, cw = c00.shape[:2]
# Размер сетки
crops = os.listdir(img_dir)
xs, ys = [], []
for name in crops:
parts = name.replace("crop_", "").replace(".png", "").split("_")
xs.append(int(parts[0]))
ys.append(int(parts[1]))
grid_x, grid_y = max(xs) + 1, max(ys) + 1
# Проверяем что crop_0_0 начинается с (0, 0)
assert np.array_equal(c00, merge[0:ch, 0:cw, :3]), "crop_0_0 не совпадает с merge[0:ch, 0:cw]"
# Ищем stride по X: сдвигаем crop_1_0 вдоль ширины merge
c10 = np.array(Image.open(os.path.join(img_dir, "crop_1_0.png")))
stride_x = None
for s in range(1, cw + 1):
if s + cw <= mw and np.array_equal(c10, merge[0:ch, s:s + cw, :3]):
stride_x = s
break
assert stride_x is not None, "Не удалось найти stride по X"
# Ищем stride по Y: сдвигаем crop_0_1 вдоль высоты merge
c01 = np.array(Image.open(os.path.join(img_dir, "crop_0_1.png")))
stride_y = None
for s in range(1, ch + 1):
if s + ch <= mh and np.array_equal(c01, merge[s:s + ch, 0:cw, :3]):
stride_y = s
break
assert stride_y is not None, "Не удалось найти stride по Y"
return {
"merge_size": (mw, mh),
"crop_size": (cw, ch),
"grid": (grid_x, grid_y),
"stride": (stride_x, stride_y),
"overlap": (cw - stride_x, ch - stride_y),
}
def main():
base = os.path.dirname(os.path.abspath(__file__))
patterns = [
os.path.join(base, "Country", "*", "*", "*", "DB"),
os.path.join(base, "Terrain", "*", "*", "DB"),
]
scene_dirs = []
for pat in patterns:
scene_dirs.extend(sorted(glob.glob(pat)))
print(f"{'Scene':<50} {'merge WxH':>14} {'crop':>8} {'grid':>8} {'stride':>8} {'overlap':>8}")
print("-" * 100)
for scene_db in scene_dirs:
if not os.path.isfile(os.path.join(scene_db, "merge.tif")):
continue
# Короткое имя сцены
rel = os.path.relpath(scene_db, base)
name = rel.replace("/DB", "")
try:
info = analyze_scene(scene_db)
mw, mh = info["merge_size"]
cw, ch = info["crop_size"]
gx, gy = info["grid"]
sx, sy = info["stride"]
ox, oy = info["overlap"]
print(
f"{name:<50} {mw:>6}x{mh:<6} {cw:>3}x{ch:<4} {gx:>3}x{gy:<4} {sx:>3}x{sy:<4} {ox:>3}x{oy:<4}"
)
except Exception as e:
print(f"{name:<50} ERROR: {e}")
if __name__ == "__main__":
main()