В этой статье я расскажу о том, как можно определить географическое местоположение объекта на фотографии, используя только длину тени и время съёмки. Мы рассмотрим конкретный пример - историческую фотографию 1963 года из Сайгона (ныне Хошимин), и напишем Python-скрипт для анализа возможных локаций.

Теория: как работают тени?

Представьте, что вы стоите рано утром на улице. Солнце только поднимается над горизонтом, и ваша тень очень длинная. К полудню солнце поднимается высоко в небо, и тень становится совсем короткой. А к вечеру тень снова удлиняется.

Давайте разберем эту геометрию подробнее. Вот простая схема:

             Солнце •
                   /|
    Угол высоты   / |
    солнца (θ) → / θ|
                /   | Высота
               /    | объекта (h)
              /     |
             /      |
    --------+------+--------
    Горизонт    Длина
              тени (s)

Что мы видим на этой схеме:

  • Солнце находится под углом θ к горизонту (это называется "угол высоты солнца")

  • У нас есть объект высотой h (например, человек или столб)

  • Этот объект отбрасывает тень длиной s

Связь между этими величинами описывается простой формулой:

длина_тени = высота_объекта / tan(угол_высоты_солнца)

Или математически:

s = h / tan(θ)

Что это значит на практике?

  • Когда солнце низко (маленький угол θ), тень длинная

  • Когда солнце высоко (большой угол θ), тень короткая

  • Отношение длины тени к высоте объекта (s/h) зависит только от угла высоты солнца

Алгоритм поиска места съёмки:

  1. Берём конкретное время и дату фотографии

  2. Для каждой точки на карте мира:

    • Вычисляем, под каким углом там было солнце в этот момент

    • Рассчитываем, какой длины должна была быть тень

    • Сравниваем с реальной тенью на фотографии

  3. Точки, где расчётная длина совпадает с реальной - потенциальные места съёмки

В итоге на карте мы получим линию возможных локаций - все места, где в заданный момент времени тени имели именно такую длину.

Реализация алгоритма

Давайте разберем, как реализовать наш метод пошагово

Шаг 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) находится именно на этой дуге.

Ограничения метода

  1. Необходимо точное время съёмки

  2. Объект должен отбрасывать чёткую тень

  3. Поверхность должна быть ровной(То есть в расчетах могут быть ошибки из-за кривизны Земли, линзы и так далее. Чем точнее измерения, тем корректнее модель.)

  4. Метод даёт не точку, а линию возможных локаций

Заключение

Метод геолокации по теням - инструмент для анализа фотографий. В сочетании с другими методами (анализ архитектуры, надписей, ландшафта) он может помочь определить место съёмки.

Полный исходный код проекта доступен на GitHub [https://github.com/HovhannesManushyan/SunTrack/blob/main/suntrack.py].

Благодарности

Этот проект основан на идеях и коде из проекта ShadowFinder. ShadowFinder - это открытый инструмент для геолокации изображений по теням, и я настоятельно рекомендую ознакомиться с оригинальным проектом.

Комментарии (17)


  1. muxa_ru
    09.01.2025 16:48

    Измерив в пикселях высоту человека и длину его тени (например, используя GIMP или Photoshop), получаем отношение примерно 160:75.

    Высота тени в пикселях зависит не только от такого очевидного факта, как её непараллельность экрану, так и от менее очевидного факта возможной негоризонтальности и неровности поверхности, на которую она падает.

    То есть, тут тупо отсутствие понимание того, что такое геометрия/аксонометрия и как она работает.

    Зная дату (11 июня 1963 года) и предполагаемое время (6:30 UTC, что соответствует 14:30 по местному времени), мы можем запустить наш скрипт:

    Датировка фотографий это вообще отдельная тема и тут можно попытаться решить обратную задачу: зная место, попытаться определить время съёмки по падающим теням.

    Ну и, конечно же, нет вообще никакой гарантии того, что современный перевод времени будет работать для дат съёмки, потому что хз что там было с часовыми поясами и летним/зимним временем.

    И главная проблема из всего этого, то что могут найтись люди, которые будут считать это решение прям чем-то реальным и будут использовать на практике: автоматически массово атрибутировать фотографии, навешивать ярлыки "подделка"/"фейкньюс", подтверждать алиби или утверждать "исторические факты".

    А я потом сиди и выясняй, почему в интернете какая-то фотография висит с какой-то датой и координатами.


    1. H0fm4n Автор
      09.01.2025 16:48

      посмотрите заголовок «Ограничения метода». Метод требует вдумчивого использования, и его следует использовать не отдельно, а в сочетании с другими методами.


      1. muxa_ru
        09.01.2025 16:48

        Главное ограничение состоит в том, что не существует возможности определить длину тени, иначе как по лежащему рядом образцу известной длины.

        Просто исходный данных нет и всё. Работать не с чем.

        А то что нет никакой возможности установит точное время съёмок и проверить насколько ровная и горизонтальная поверхность, это уже мелочи. :)


        1. H0fm4n Автор
          09.01.2025 16:48

          Это, конечно, приближение, могут быть ошибки, которые приведут к смещению модели. Однако в сочетании с другими объектами на изображении этот метод может помочь определить примерное местоположение фотографии.


          1. muxa_ru
            09.01.2025 16:48

            примерное

            Есть оценка погрешности?


            1. H0fm4n Автор
              09.01.2025 16:48

              Нет, но это отличная идея для будущей работы. я экспериментировал с различными углами камеры и объектами, и область, которую я искал, всегда появлялась в пределах границ, но я могу представить, что метод также может дать сбой.


            1. 200sx_Pilot
              09.01.2025 16:48

              +/- два локтя по пятивёрстке.


  1. CBET_TbMbI
    09.01.2025 16:48

    Измерив в пикселях высоту человека и длину его тени (например, используя GIMP или Photoshop), получаем отношение примерно 160:75.

    Это работает только если и человек и его тень находятся в плоскости, перпендикулярной оси взгляда. Если тень расположена под углом, то нужно учитывать перспективу, что совсем не просто. Нужен алгоритм, определяющий длину теней (или хотя бы строящий концентрические круги на поверхности земли)

    Например тут, все шесть теней примерно одинаковой длины (1:1 к столбу). Но в пикселях они разные и зависят и двух углов: между плоскостью тени и линией взгляда, и между плоскостью земли и линией взгляда (от второго угла ещё и высота столба зависит).
    Например тут, все шесть теней примерно одинаковой длины (1:1 к столбу). Но в пикселях они разные и зависят и двух углов: между плоскостью тени и линией взгляда, и между плоскостью земли и линией взгляда (от второго угла ещё и высота столба зависит).

    Зная дату (11 июня 1963 года) и предполагаемое время (6:30 UTC, что соответствует 14:30 по местному времени), мы можем запустить наш скрипт:

    Ага-ага... Ещё бы понять, откуда взять это предполагаемое время. Для 99% фотографий, думаю, оно не известно. А если известно время, то и координаты, скорее всего, тоже.

    Как видно из визуализации, возможные места образуют дугу, проходящую через Юго-Восточную Азию. 

    Ага. А ещё через Китай, Монголию, Казахстан, Иран и Персидский залив. А с учётом погрешности определения длины тени, эта окружность превращается в круг с половину Азии.


    1. muxa_ru
      09.01.2025 16:48

      Добавьте сюда ещё неизвестную высоту расположения объектива, относительно точки схождения фигуры и отбрасываемой тени. :)


      1. H0fm4n Автор
        09.01.2025 16:48

        Я добавил больше примеров в скобках на случай, если у кого-то возникнут такие же вопросы.


    1. H0fm4n Автор
      09.01.2025 16:48

      посмотрите заголовок «Ограничения метода». Метод требует вдумчивого использования, и его следует использовать не отдельно, а в сочетании с другими методами


  1. kinall
    09.01.2025 16:48

    Это просто какой-то эталонный "программизм головного мозга". Особенно вот этот чудесный алгоритм:

    • Для каждой точки на карте мира:

      • Вычисляем, под каким углом там было солнце в этот момент

      • Рассчитываем, какой длины должна была быть тень

      • Сравниваем с реальной тенью на фотографии

    Вместо того, чтобы чуть-чуть подумать и решить прямую задачу (вычислить возвышение солнца, а по нему посчитать координаты), автор решает тысячи обратных задач, только потому, что ему попалось готовое решение, причём не разобравшись в исходной проблеме и не понимая её сути. Аплодирую стоя...


    1. H0fm4n Автор
      09.01.2025 16:48

      Цель этой статьи никогда не заключалась в поиске самого оптимального способа решения этой проблемы. Вы можете "немного подумать" и написать свою собственную статью на эту тему.


      1. H0fm4n Автор
        09.01.2025 16:48

        Я также предлагаю вам прочитать это https://wiki.c2.com/?PrematureOptimization, потому что в данном случае пространство поиска довольно мало, и для демонстрационных целей оптимизации не требовались.


  1. SquareRootOfZero
    09.01.2025 16:48

    "NGUYEN-KHUYEN" явно написал русский, которого достали все эти тамошние Нгуены... Автору стоило бы более другой пример подобрать, а то по таким надписям геолокация осуществляется куда точнее (где-то во Вьетнаме), чем, в итоге, вышло по теням (округлая зона на пол-континента).


    1. foreva
      09.01.2025 16:48

      ЯННП, но тем не менее, он существует ;-) https://vi.wikipedia.org/wiki/Nguyễn_Khuyến


      1. SquareRootOfZero
        09.01.2025 16:48

        Речь, разумеется, о редупликации.