В этой статье я расскажу о том, как можно определить географическое местоположение объекта на фотографии, используя только длину тени и время съёмки. Мы рассмотрим конкретный пример - историческую фотографию 1963 года из Сайгона (ныне Хошимин), и напишем Python-скрипт для анализа возможных локаций.
Теория: как работают тени?
Представьте, что вы стоите рано утром на улице. Солнце только поднимается над горизонтом, и ваша тень очень длинная. К полудню солнце поднимается высоко в небо, и тень становится совсем короткой. А к вечеру тень снова удлиняется.
Давайте разберем эту геометрию подробнее. Вот простая схема:
Солнце •
/|
Угол высоты / |
солнца (θ) → / θ|
/ | Высота
/ | объекта (h)
/ |
/ |
--------+------+--------
Горизонт Длина
тени (s)
Что мы видим на этой схеме:
-
Солнце находится под углом θ к горизонту (это называется "угол высоты солнца")
-
У нас есть объект высотой h (например, человек или столб)
-
Этот объект отбрасывает тень длиной s
Связь между этими величинами описывается простой формулой:
длина_тени = высота_объекта / tan(угол_высоты_солнца)
Или математически:
s = h / tan(θ)
Что это значит на практике?
-
Когда солнце низко (маленький угол θ), тень длинная
-
Когда солнце высоко (большой угол θ), тень короткая
-
Отношение длины тени к высоте объекта (s/h) зависит только от угла высоты солнца
Алгоритм поиска места съёмки:
-
Берём конкретное время и дату фотографии
-
Для каждой точки на карте мира:
-
Вычисляем, под каким углом там было солнце в этот момент
-
Рассчитываем, какой длины должна была быть тень
-
Сравниваем с реальной тенью на фотографии
-
-
Точки, где расчётная длина совпадает с реальной - потенциальные места съёмки
В итоге на карте мы получим линию возможных локаций - все места, где в заданный момент времени тени имели именно такую длину.
Реализация алгоритма
Давайте разберем, как реализовать наш метод пошагово
Шаг 1: Создание координатной сетки
Сначала мы создаём сетку возможных координат на поверхности Земли. Мы используем шаг в 0.5 градуса как компромисс между точностью и скоростью вычислений:
lat_resolution = 0.5 # шаг по широте в градусах
lon_resolution = 0.5 # шаг по долготе в градусах
# Создаём массивы координат
# Широта от -60° до +85° (исключаем полярные регионы)
lats = np.arange(-60, 85, lat_resolution)
# Долгота от -180° до +180°
lons = np.arange(-180, 180, lon_resolution)
# Создаём сетку координат
lons_grid, lats_grid = np.meshgrid(lons, lats)
Шаг 2: Расчёт высоты солнца с помощью suncalc
Для расчёта положения солнца мы используем библиотеку suncalc. Это JavaScript библиотека, портированная на Python, которая вычисляет видимое положение солнца для любой точки на Земле в заданный момент времени. Она учитывает:
-
Орбиту Земли
-
Наклон земной оси
-
Точное время и дату
-
Географические координаты
Функция get_position
возвращает несколько параметров, но нас интересует прежде всего altitude
- угол высоты солнца над горизонтом в радианах.
Для каждой точки нашей сетки мы вычисляем этот угол:
sun_altitudes = np.zeros_like(lons_grid) # массив для хранения углов
for i in range(len(lats)):
for j in range(len(lons)):
# Получаем положение солнца для заданных координат и времени
pos = get_position(date_time, lons[j], lats[i])
# Сохраняем угол высоты солнца (в радианах)
sun_altitudes[i, j] = pos['altitude']
Шаг 3: Расчёт ожидаемой длины тени
Теперь, когда у нас есть углы высоты солнца для каждой точки на карте, мы можем рассчитать, какой длины должна быть тень в этой точке. Используя нашу формулу из теоретической части (s = h / tan(θ)), вычисляем ожидаемый размер тени для объекта известной высоты:
# Рассчитываем ожидаемую длину тени для каждой точки сетки
# object_height - высота объекта (например, человека на фото)
# sun_altitudes - массив углов высоты солнца в радианах
expected_shadow_lengths = object_height / np.tan(sun_altitudes)
# Сравниваем ожидаемую длину с реально измеренной на фотографии
# shadow_length - длина тени, измеренная на фотографии
relative_differences = np.abs((expected_shadow_lengths - shadow_length) / shadow_length)
Шаг 4: Визуализация
Результаты отображаются на карте мира, где цветом показано насколько хорошо совпадают расчётные и измеренные длины теней. Чем темнее цвет, тем лучше совпадение.
Практический пример: фотография из Сайгона
Рассмотрим историческую фотографию протестов в Сайгоне 1963 года. На фотографии видны люди и их тени, также присутствует вывеска на вьетнамском языке "TRUNG HOC TU THUC NGUYEN-KHUYEN".
Измерив в пикселях высоту человека и длину его тени (например, используя GIMP или Photoshop), получаем отношение примерно 160:75.
Зная дату (11 июня 1963 года) и предполагаемое время (6:30 UTC, что соответствует 14:30 по местному времени), мы можем запустить наш скрипт:
find_locations_from_shadow(
object_height=160,
shadow_length=75,
date_time=datetime(1963, 6, 11, 6, 30, tzinfo=timezone('UTC'))
)
Результаты анализа
Запустив скрипт, мы получаем карту возможных локаций. Как видно из визуализации, возможные места образуют дугу, проходящую через Юго-Восточную Азию. И действительно, Сайгон (современный Хошимин, координаты примерно 10.8°N, 106.7°E) находится именно на этой дуге.
Это подтверждает точность нашего метода и демонстрирует, как анализ теней может помочь в геолокации исторических фотографий.
Ограничения метода
-
Необходимо точное время съёмки
-
Объект должен отбрасывать чёткую тень
-
Поверхность должна быть ровной
-
Метод даёт не точку, а линию возможных локаций
Заключение
Метод геолокации по теням - мощный инструмент для анализа исторических фотографий. В сочетании с другими методами (анализ архитектуры, надписей, ландшафта) он может помочь точно определить место съёмки.
Полный исходный код проекта доступен на GitHub [https://github.com/HovhannesManushyan/SunTrack/blob/main/suntrack.py].
Благодарности
Этот проект основан на идеях и коде из проекта ShadowFinder. ShadowFinder - это открытый инструмент для геолокации изображений по теням, и я настоятельно рекомендую ознакомиться с оригинальным проектом.
Автор: H0fm4n