Разработчик нашёл остров по фото геометрией и CUDA, перебрав 80 миллионов кандидатов

OSINT-испытание gralhix #004, часть серии геолокационных головоломок, которую ведёт София Сантос (проект gralhix). Участникам показывают одну фотографию курорта на острове и просят по этому кадру ответить на три вопроса: как называется курорт, какие координаты у острова и в какую сторону света смотрела камера. Разработчик и OSINT-энтузиаст под ником yassa9 разобрал решение в открытом отчёте на своём сайте, сознательно отказавшись от очевидного пути, обратного поиска изображений через Google Lens, назвав это «потерей всего веселья», и прошёл задачу геометрией, статистическими фильтрами и вычислениями на GPU. Весь код, промежуточные данные и финальный отчёт выложены в открытом репозитории на GitHub.

Сначала, тупик с метаданными: exiftool показал, что фото, файл WEBP размером 736×515 пикселей без единого EXIF-тега, без GPS и без модели камеры. На снимке видно три участка суши: сам курортный островок (P0), остров справа (P1) и остров слева с горной вершиной (P2). Автор написал небольшой GUI на Python, чтобы вручную отметить эти три точки на фото и вычислить геометрию треугольника между ними, расстояния и углы, с допуском ±20% на неточность ручной разметки. Этот треугольник стал «отпечатком», который предстояло найти среди реальной суши Земли.

Базой для поиска стал набор контуров береговых линий OpenStreetMap land-polygons-split-4326 (882 МБ, всё покрытие суши Земли в системе координат WGS84). Кандидатов отсеивали цепочкой всё более дорогих фильтров. По оценке широты острова на фото решили, что он тропический, и оставили полосу от −30° до 30°, осталось 141 131 полигон. Фильтр плотности (не больше 10 соседних центроидов в радиусе 5 км, иначе это плотный архипелаг или рифовое поле) сократил список до 51 576 кандидатов. Кластеризация (не меньше 3 точек в радиусе 20 км друг от друга, иначе тройку не из чего составить) дала 23 500 кластеров. Каждый кластер урезали максимум до 60 точек стратифицированной выборкой по размеру острова и перебрали внутри все возможные тройки, получилось 80 690 777 кандидатных треугольников (один кластер даже из 60 точек сам по себе даёт 34 220 троек).

Сравнение с эталонным треугольником сделали на GPU: автор написал CUDA-ядро, где каждый поток обрабатывает одну тройку островов, сортирует их по площади, чтобы определить P0, определяет P1 и P2 по знаку векторного произведения (по направлению обхода), считает угол при P0 и отношение расстояний между сторонами, а затем проверяет, укладываются ли они в допуски эталонного отпечатка. На видеокарте NVIDIA GeForce RTX 3050 расчёт всех 80,7 миллиона троек занял 204,1 мс и задействовал 5169 МБ видеопамяти; маску совпадения прошли 158 784 тройки. После удаления дублей, одна и та же тройка могла попасть сразу в несколько пересекающихся кластеров, осталось 8 915 уникальных кандидатов.

Дальше кандидатов проверяли уже не перебором, а по смыслу снимка. Проверка на открытую воду, по одну сторону линии P0, P1 в реальности должна быть только вода, без другой суши в построенном рядом прямоугольнике, сократила список до 948. Проверка формы кораллового островка (компактность контура по индексу Полсби, Поппера не ниже 0,5 и хотя бы один мелкий рифовый фрагмент площадью до 0,05 км² в радиусе 1,5 км) оставила 213 кандидатов. Проверка овальности (соотношение сторон описанного прямоугольника от 1,05 до 2,2 и заполнение этого прямоугольника фигурой не меньше 0,75 от теоретического максимума для эллипса) сократила список до 137. Дальше в дело пошли спутниковые снимки: по данным Sentinel-2 через открытый каталог Earth Search (STAC API компании Element 84) для каждой точки посчитали вегетационный индекс NDVI, порог 0,6 (заметный растительный, пальмовый покров) прошли 66 островов. Последним фильтром стал рельеф: сам остров P0 должен быть низким и плоским (высота не больше 50 м), а в направлении, куда «смотрит» камера (сектор ±50° от вычисленного азимута, на расстоянии 2, 20 км), должен быть подъём высотой от 100 до 500 м, данные взяли из цифровой модели рельефа Copernicus DEM GLO-30 с разрешением 30 м. Этому условию соответствовали 26 кандидатов, в основном в Южной и Юго-Восточной Азии, Австралии и Океании, и один, у берегов Бразилии.

Финальные 26 кандидатов автор проверил вручную по спутниковым снимкам Google Maps, восьмой по счёту оказался верным. Курорт называется Oan, расположен в Микронезии, на координатах 7,363444° с. ш., 151,755750° в. д. (7°21′48,4″ с. ш., 151°45′20,7″ в. д.). Направление камеры вычислили по биссектрисе между азимутом на P1 и азимутом на P2: 324,97°, то есть северо-запад.

Все данные, на которых построен расчёт, открытые: контуры береговой линии, OpenStreetMap на лицензии ODbL 1.0, рельеф, Copernicus DEM GLO-30 (данные Евросоюза и Европейского космического агентства), снимки, обработанные данные Sentinel-2 через программу открытых данных AWS, границы стран, общедоступный набор Natural Earth. В начале материала автор отдельно подчёркивает: весь разбор, «подлинная работа человека», без использования генеративного ИИ.

Ключевые факты

  • OSINT-испытание gralhix #004 (София Сантос, проект gralhix) дало только фото курортного острова без метаданных и спросило: название курорта, координаты острова, направление камеры.
  • yassa9 построил геометрический «отпечаток», треугольник по расстояниям и углам между тремя островами на фото, и сверил его со 141 131 тропическим полигоном суши из набора береговых линий OpenStreetMap (882 МБ).
  • На CUDA-ядре, запущенном на видеокарте NVIDIA GeForce RTX 3050, за 204,1 мс перебрали 80 690 777 кандидатных троек островов; после серии проверок формы, вегетационного индекса NDVI (снимки Sentinel-2) и рельефа (Copernicus DEM) осталось 26 кандидатов.
  • Восьмой из 26 кандидатов, проверенных вручную по снимкам Google Maps, совпал: курорт Oan в Микронезии, координаты 7,363444° с. ш., 151,755750° в. д., камера направлена на северо-запад (азимут 324,97°).
  • Автор подчёркивает, что не пользовался ни ИИ, ни обратным поиском изображений (Google Lens), весь путь построен на геометрии, открытых геоданных и переборе на GPU.

Почему это важно

История интересна именно контрастом: вместо того чтобы отдать фото нейросети или сервису обратного поиска изображений, автор явно отказался от этого пути и решил геолокационную задачу голой геометрией, статистическими фильтрами и брутфорсом на GPU. Изображение-загадку без единого метаданного он свёл к числовой задаче, сравнению треугольника расстояний и углов со 141 131 полигоном реальной суши, и заставил видеокарту потребительского уровня перебрать 80,7 миллиона таких сравнений за 204,1 мс. Это наглядный пример того, что классические геометрические алгоритмы и параллельные вычисления на GPU остаются рабочей и быстрой альтернативой распознаванию образов там, где для точной геолокации по одному кадру не хватает данных для обучения модели или готового сервиса.

Кому это важно

В первую очередь, OSINT-исследователям и специалистам по гео-разведке, которые ищут воспроизводимые, не завязанные на закрытый ИИ-сервис методы определения места по фотографии. Во вторую, разработчикам, которые работают с CUDA, GPU-вычислениями и геоданными (GIS): пайплайн показывает, как сузить пространство поиска дешёвыми фильтрами перед дорогой геометрией и параллельным перебором. В третью, энтузиастам конкурентных гео-загадок (geoguessing) и авторам похожих OSINT-челленджей вроде gralhix. И отдельно, всем, кто задумывается о приватности своих фотографий: история показывает, что для точной геолокации по снимку не нужны ни EXIF, ни ИИ, если на кадре видна распознаваемая геометрия местности.

Как это применить

Пайплайн, это готовый рецепт, который можно повторить на других задачах геолокации по фото: 1) вручную выделить на снимке видимые ориентиры (острова, горы, линию берега) и посчитать относительные расстояния и углы между ними, «геометрический отпечаток»; 2) взять открытый набор геоданных нужного масштаба (в этом случае, контуры береговых линий OpenStreetMap, 882 МБ, лицензия ODbL 1.0) и сначала отсечь заведомо лишнее дешёвыми фильтрами, по широте, по локальной плотности, по кластеризации, прежде чем переходить к дорогой геометрии; 3) сам перебор кандидатов оформить как CUDA-ядро с одним потоком на кандидата, так 80,7 миллиона сравнений считаются за доли секунды даже на игровой видеокарте среднего уровня (RTX 3050); 4) отсеять уцелевших кандидатов независимыми проверками по открытым спутниковым данным, форма контура, вегетационный индекс NDVI по снимкам Sentinel-2 через каталог Earth Search (STAC API, без ключа доступа), рельеф по Copernicus DEM GLO-30; 5) финальный короткий список проверить вручную по спутниковым снимкам. Все использованные источники данных, бесплатные и открытые, код и данные проекта выложены на GitHub.

Можно ли доверять

Источник, личный технический блог одного автора (yassa9.github.io), без редакционной проверки, но с полной прозрачностью метода: код, промежуточные данные и итоговый отчёт открыты на GitHub, так что расчёт можно повторить самостоятельно. Автор явно указывает, что материал, «подлинная работа человека» без использования генеративного ИИ. При этом сам он неоднократно называет пороги фильтров (допуск отпечатка, плотность, компактность, соотношение сторон, NDVI, высоты рельефа) эвристическими, подобранными на глаз и методом проб и ошибок, а не статистически обоснованными. Финальный ответ, курорт Oan, подтверждён только собственной ручной проверкой автора по спутниковым снимкам Google Maps; независимого источника (сайта бронирования, новости, подтверждения от организатора челленджа Софии Сантос), который называл бы курорт по имени, в материале не приводится.

Риски и подводные камни

Эвристические пороги, подобранные методом проб и ошибок, а не статистически, источник и системной ошибки, и случайного успеха: слишком мягкий порог пропускает случайные геометрические совпадения (ложный остров с похожим треугольником), слишком строгий, может отбросить правильный ответ ещё на ранних, дешёвых фильтрах, до того как до него дойдёт очередь у GPU-перебора. Весь метод жёстко завязан на полноту исходного набора данных: если нужный островок плохо оцифрован или вовсе отсутствует в контурах OpenStreetMap, найти его невозможно в принципе, независимо от точности геометрии. Есть и более общий вывод для читателя: фотография, из которой полностью вычищены метаданные, всё равно поддаётся точной геолокации, если на ней видна хоть какая-то узнаваемая геометрия местности, и для этого не нужны ни ИИ-сервисы, ни закрытые базы данных, достаточно открытых геоданных и игровой видеокарты.

«Это подлинная работа человека, я не пользовался генерацией текста нейросетью.»

— yassa9, автор разбора gralhix #004