Files
World-UAV-ds/analyze/analyze_crop_scheme.py
Pikaliov 4ff36ce188 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>
2026-05-09 12:44:49 +03:00

118 lines
4.0 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
Анализ схемы нарезки спутниковых снимков в датасете 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()