Давайте воспользуемся пакетами exif and folium
Python
Большинство современных камер и мобильных телефонов с поддержкой GPS записывают информацию о геолокации при съемке фотографии, и эта информация сохраняется вместе со всеми другими метаданными.
Существует также множество веб-приложений, которые позволяют создавать различные визуализации с использованием этих метаданных. Но что, если вы, как и я, не доверяете свои фотографии сторонним сервисам с неизвестным уровнем безопасности данных? К счастью, большинство этих визуализаций относительно просто воспроизвести с помощью Python. В этом руководстве я покажу, как создать карту путешествия, используя фотоданные GPS.
Для этого проекта вам понадобится несколько пакетов, установленных в вашей среде Python. Мы будем использовать два основных пакета: exif
позволит нам извлекать метаданные из фотографий, а folium
мы будем использовать для создания карты и добавления маркеров местоположения. Наконец, мы также будем использовать карты цветов из matplotlib
, и pandas
и numpy
для манипуляций с данными.Чтобы установить все необходимые пакеты, просто выполните следующие действия. в вашем терминале:
pip install exif folium pandas numpy matplotlib
Начнем с импорта всех необходимых пакетов. В дополнение к перечисленным выше, мы также импортируем json
и Path
class из pathlib
library, оба из которых являются частью стандартной библиотеки.
Извлечение и подготовка метаданных для построения графика
Чтение метаданных с помощью exif
очень просто — нам просто нужно открыть файл в двоичном формате и создать из него объект Image
. Определим для этого функцию удобства:
В зависимости от устройства фотография может содержать десятки типов метаданных. Чтобы увидеть те, которые конкретно относятся к геолокации, мы можем загрузить одну фотографию и распечатать все категории метаданных, которые начинаются с «gps_».
Если в фотографию встроена информация о геолокации, вы должны увидеть следующий вывод:
gps_latitude_ref gps_latitude gps_longitude_ref gps_longitude gps_altitude_ref gps_altitude gps_timestamp gps_processing_method gps_datestamp
Некоторые из этих категорий относительно просты для понимания: gps_latitude, gps_longitude и gps_altitude хранят информацию о широте, долготе и высоте соответственно. Высота сохраняется как высота над уровнем моря, обычно в метрах. Широта и долгота хранятся в виде кортежей градусов, минут и угловых секунд.
Категории, оканчивающиеся на "_ref", содержат справочную информацию о том, как следует интерпретировать данные. В случае высоты он просто сообщает, что значение представляет собой высоту над уровнем моря, но для широты и долготы они содержат информацию об опорном полушарии, «E» или «W» для долготы и «N» или «S» для широты. Это важно при преобразовании необработанных данных в десятичный формат, поскольку стандартная запись имеет отрицательные координаты к западу от Гринвича и к югу от экватора.
Поскольку пакет folium, который мы будем использовать для построения графиков,не понимает координаты в градусах/минутах/секундах, нам нужно преобразовать широты и долготы в десятичное представление, и поскольку мы будем делать это довольно много раз, мы можем упростить жизнь и сделать код чище, определив функцию, которая будет принимать кортеж координат и опорное значение и возвращать его двоичное представление. Для этого переводим минуты и секунды в доли градуса путем деления на 60 и 3600 соответственно. Затем знак определяется на основе справочных данных:
Эта функция преобразует широту и долготу в десятичный формат, и нам не нужно ничего делать с высотами. При этом мы можем определить еще одну вспомогательную функцию, которая будет принимать объект exif.Image
и возвращать кортеж десятичных координат в формате (широта, долгота, высота).
Наконец, мы добавим еще одну функцию, которая будет рекурсивно проходить по всем подпапкам выбранной папки, считывать пространственную информацию из всех файлов изображений и возвращать словарь имен файлов и координат.
Теперь, когда это сделано, мы можем легко прочитать данные о местоположении из всех файлов в папке изображения:
Печать результирующего словаря должна привести к выводу, аналогичному моему:
print(json.dumps(res, indent=4)) Out: { "/media/pav/Storage/Photo/Phone/IMAG0036.jpg": { "latitude": -37.79912566666666, "longitude": 144.9850463611111, "altitude": 0.0, "timestamp": "2014:04:12 18:14:59"}, "/media/pav/Storage/Photo/Phone/IMAG0037.jpg": { "latitude": -37.79912566666666, "longitude": 144.9850463611111, "altitude": 0.0, "timestamp": "2014:04:12 18:15:36"}, ... }
График данных
Чтобы упростить будущие операции, мы можем преобразовать полученный словарь в pandas
DataFrame. Затем мы также преобразуем столбец меток времени в формат datetime
и сортируем значения по дате в порядке возрастания.
Чтобы покрасить наши точки данных, мы можем получить одну из цветовых карт, которые входят в состав пакета matplotlib
. В дополнение к этому нам также необходимо создать объект Normalize
. Этот объект будет присваивать числовые значения отдельным цветам в colourmap
от 0 до 1, и мы сможем вызывать любой цвет в colourspace
по его числовому значению. И для этого мы добавим столбец к нашему dataframe
, используя numpy.linspace()
.
Одна небольшая проблема заключается в том, что наши цвета будут в формате RGBA, но он не работает с folium
, поэтому нам также нужно будет преобразовать цвет в его шестнадцатеричное представление, что легко сделать:
Теперь давайте, наконец, пришло время визуализировать наши данные!
Основной частью пакета folium
является объект Map
, и простое создание экземпляра через folium.Map()
приведет к созданию карты всего мира.
Это нормально, но я предпочитаю, чтобы карта автоматически масштабировалась до уровня, на котором видны все маркеры. Мы можем добиться этого, используя метод fit_bounds()
результирующего объекта и предоставив координаты юго-западного и северо-восточного углов экстентов карты.
Мы можем рассчитать координаты юго-западного угла, взяв максимальную широту и минимальную долготу из наших данных. Точно так же координаты северо-восточного угла являются минимальной широтой и максимальной долготой. В приведенном ниже коде я также скорректировал ограничивающую рамку на 3 градуса в каждом направлении, чтобы данные аккуратно помещались в окне.
Итак, теперь, наконец, мы готовы создать карту, показывающую расположение фотографий, выделенных цветом по дате съемки.
В моем случае результат показывает кучу мест вокруг Виктории, Австралия, с фиолетовыми точками, представляющими более ранние фотографии, и более яркими красными и желтыми точками — более новые фотографии:
Заключение
Здесь мы коснулись лишь крошечной части всех возможностей, которые предлагают метаданные фотографий. С помощью этих данных вы можете создавать свои собственные базы данных фотографий, позволяющие легко классифицировать их и управлять ими. Вы также можете расширить использование данных геолокации, чтобы иметь возможность искать фотографии по местоположению в папках с изображениями, а также доступны многие другие вещи.
Полный код этого проекта можно загрузить с моего GitHub по следующему адресу: