Идея спасти мир и при этом заработать немного шекелей витала у меня в голове уже давно. Имея неплохой накопленный опыт в области геоинформационных систем и защитивши в свое время диссертацию с их применением мне не хватало знаний разработчика. Окончив IT-курсы и получив доступ к «Святому Граалю знаний» я понял, – пора, и завертелось!
Летом 2024 года мы в составе команды «Arrow» одержали победу, заняв третье место в хакатоне «Лидеры цифровой трансформации» и вошли с нашим проектом в топ-100, став резидентами «Академии инноваторов» у нас появился свой стартапп.
Общая идея такова. Arrow - это платформа для анализа и обработки спутниковых снимков, использующая технологии машинного обучения и нейросетей для мониторинга окружающей среды, строительства и природопользования. Наш продукт помогает бизнесу и государственным структурам автоматизировать выявление экологических нарушений и незаконных построек, обеспечивая более точное и своевременное реагирование. Это в «розовом» будущем, а пока это только проект «Мобильное приложение для управления антропогенной нагрузкой на особо охраняемых природных территориях Камчатского края», занявшее призовое место, хотя и этот результат тоже когда-то был только в мечтах.
Я хочу открыть целый цикл статей в котором постараюсь осветить историю жизненного цикла нашего проекта «Arrow», которая будет писаться на ваших глазах. Здесь будет все: и фронт и бэк и мобильная разработка, будет и деплой в облако. В этих статьях, которые к стати буду писать не только я, но и ребята с моей команды, мы хотим осветить все начиная от создания MVP (минимально жизнеспособный продукт) и заканчивая выводом проекта в продакшн, анализ целевой аудитории и поиск первых клиентов, привлечение первых инвестиций, подбор команды, в общем все этапы через которые нам предстоит пройти для достижения своей цели, - получения интересного и востребованного продукта. Начнем же…
В современных реалиях блокировки доступа ко многим программным продуктам остро встает вопрос о переходе к использованию отечественных или, замещающих их и распространяемых открыто, ресурсам для построения элементов инфраструктуры пространственных данных.
Данная статья освещает практический подход для решения задачи построения Веб-ГИС приложения и сервисов на основе открытых ресурсов и на примере нашего проекта. Основное внимание в ней будет уделено созданию общей структуры проекта и освещению ресурсов на которых он функционирует.
Проект реализован с применением клиент-серверной архитектуры (рисунок 1). Серверная часть включает в себя СУБД для хранения векторных и растровых наборов данных, файловое хранилище растровых тайлов, сервер приложений Gunicorn, обслуживающий сам проект, и веб-сервер Nginx для взаимодействия, через протокол REST full с сервисами приложения, программ клиентов, которыми могут быть десктопные и (или) мобильные и (или) веб-браузеры. Таким образом, весь проект будет размещен в облаке
Технологический стек проекта включает в себя следующие свободно распространяемые ресурсы:
-
СУБД Postgresql с надстройкой PostGIS, которая предоставляет дополнительные возможности для работы с геопространственными данными, превращая базу данных в геореляционную;
-
Широко распространенный скриптовый язык программирования Python;
-
Не менее широко известный фреймворк, предназначенный для создания веб-приложений Django, взаимодействующий с СУБД с помощью технологии ORM (Object Relations Mapping). Эта технология позволяет работать с выбранной СУБД посредствам классов языка программирования, меняя лишь специальный драйвер, минуя при этом необходимость в написании SQL-запросов и, что самое главное, без изменения исходного программного кода приложения;
-
Для взаимодействия клиента с серверной частью предназначен Django REST фреймворк. DRF – одна из современных технологий создания API (программного интерфейса приложения), основным преимуществом которой является возможность организации совместной работы клиентских и серверных программ, написанных на различных языках программирования;
-
Библиотека GDAL содержит в себе полноценный функционал современных ГИС (геоинформационных систем) общего назначения, объединяя в себе две библиотеки – одноименную gdal, для работы с растровыми наборами данных и ogr, для работы с векторными форматами данных (shape, kml, geojson и др.). Активация этой библиотеки превращает фреймворк Django в GeoDjango;
-
- Для анализа спутниковых снимков (получаемых через API Sentinel Hub) применяются библиотеки Numpy и Pandas, дополнительно используется Jupiter Notebook, в том числе для работы со сверточной нейронной сетью U-Net для сегментации изображений;
-
Библиотека Leaflet (либо OpenLayer 3) посредствам java-скриптов и во взаимодействии с html-шаблонами и таблицами стилей CSS, визуализирует геоданные в окне веб-браузера и предоставляет пользователю элементы интерфейса для работы с серверным приложением;
-
В качестве карты-подложки применяется OSM-карта.
Создание проекта предполагает установку языка программирования, модуля для работы с виртуальными средами venv, пакетного менеджера pip, СУБД Postgrsql с расширением PostGIS, в качестве редактора кода я использую VSCode. В зависимости от операционной системы для установки всего этого добра используются различные менеджеры, например в MacOS это brew, в Ubuntu – apt, в Mandjaro pacman и т.д. Я работаю еще в Windows, но там использую стандартные .exe-шники. Тут и далее буду работать с Ubuntu, так как в дальнейшем при деплое на удаленном сервере
sudo apt install python3-venv python3-pip postgresql postgis
Далее создается база данных от имени пользователя postgres. Переключаемся на этого пользователя и заходим в утилиту psql.
sudo su postgres
psql
ALTER USER postgres WITH PASSWORD `admin`;
Теперь создаем базу данных.
CREATE DATABASE test;
Далее нужно активировать для этой базы данных расширение postgis. Подключаемся к базе.
c test
И активируем расширение.
CREATE EXTENSION postgis;
Со списком всех доступных расширений для работы с пространственными данными и для их активации рекомендую ознакомится со справкой на сайте PostGIS.
Выходим.
q
Переключаемся с пользователя «postgres» на пользователя операционной системы.
exit
Теперь при создании полей в моделях базы данных нам, помимо стандартных типов данных, также будет доступно поля данных с типом «геометрия».
Следующим шагом нам необходимо создать виртуальное окружение для размещения в нем нашего проекта и установить в него необходимые зависимости, главные из которых фреймворки django и djangorest, а также драйвер для работы с базой данных Postgresql – psycopg2-binary.
mkdir geodjango
Переключаемся на эту папку, это будет наша рабочая директория.Создаем папку для размещения проекта.
cd geodjango
Создаем окружение, где env – это названия окружения.
python –m venv env
И активируем его (для выхода из виртуального окружения необходимо запустить файл deactivate).
source env/bin/activate
Теперь установим в виртуальное окружение необходимые для работы проекта зависимости. Список этих зависимостей содержится в файле requirements.txt.
pip install –r requirements.txt
Можно проверить все ли необходимые зависимости установлены командой pip freeze (с их версиями).
Находясь в рабочей директории «geodjango», приступаем к созданию проекта и приложения в нем.
Создание проекта выполняется командой, где geodjango – это название проекта.
django-admin startproject geodjango
Создание приложения выполняется командой, где geoapp – это названия приложения.
python manage.py startapp geoapp
При создании проекта и приложения в нем с помощью фреймворка Django формируется первоначальная файловая структура. Каждый из этих файлов имеет свое строгое предназначение. Например, файл settings.py, в том числе, предназначен для подключения к предварительно созданной на основе шаблона PostGIS базе данных.
Для настройки подключения используется секция DATABASES.
DATABASES = {
'default': {
'ENGINE': 'django.contrib.gis.db.backends.postgis',
'NAME': 'test',
'USER': 'postgres',
'PASSWORD': 'admin',
'HOST': 'localhost',
'PORT': '5432',
}
}
Структура базы данных создается в файле models.py, где указываются необходимые модели (таблицы) с атрибутивными полями, хранящими данные определенных типов, а также поле для хранения геометрии пространственных объектов.
После создания моделей выполняется их миграция в базу данных и регистрация в файле admin.py для доступа к данным через специальную административную панель.
Каждое внесение изменений в модели базы данных требует создание миграций.
python manage.py makemigrations
Команда ниже создает модели в базе данных.
python manage.py migrate
Для взаимодействия с данными базы предназначен файл views.py. Он содержит функции и классы представлений, описывающих программную логику приложения.
Настройка взаимодействия клиента с этими представлениями осуществляется в результате процедуры роутинга – задания url-адресов доступа к тем или иным функциям, выполняемой в файле urls.py.
Функции генерируют контент, который рендерится в html-шаблоне, размещенном в папке templates, и визуализируется в окне веб-браузера с применением таблиц стилей CSS.
Если «обернуть» такие функции в специальный декоратор (или создать вместо функций классы наследующие атрибуты встроенных в Django классов джинериков и миксин, что является более современным подходом) они будут способны обрабатывать REST-запросы от клиента.
Такие запросы (или ответы на них) могут содержать тело данных, записываемых (или извлекаемых) в базу данных, через процедуры сериализации (преобразования объекта (словаря данных) в строку байтов для передачи по линиям связи), десериализации (обратно сериализации) и валидации (проверку данных на соответствие ожидаемой структуре).
Для понимания элементарный пример такого взаимодействия, реализованного в приложении, представлен ниже.
Пользователь выбирает элемент управления, размещенный в окне браузера. К этому элементу подключен java-скрипт формирования, например, некоторого условного POST-запроса.
// Добавляем маркер
function saveMarkerToDatabase(coordinates, markerName) {
fetch('https://swan-decent-shrew.ngrok-free.app/api/create_point/', {
// Задаем метод REST-запроса
method: 'POST',
// Формируем хедер запроса
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': getCookie('csrftoken'), // Добавляем CSRF-токен в заголовок запроса
},
// Формируем тело запроса
body: JSON.stringify({ name: markerName, location: 'SRID=4326;POINT(' + coordinates.lng + ' ' + coordinates.lat + ')' })
});
}
В момент клика мыши по определенному url на сервер отправляется этот запрос, содержащий в своем теле контент: имя события и данные локации в формате WKT (код системы координат и проекции и координаты точки). Такой запрос, кроме тела, должен содержать служебную информацию в своем заголовке, защищающую приложение от внешних атак – CSRF-токен.
Связанная с этим url функция, ее еще называют эндпоинтом, успешно отрабатывает о чем свидетельствует статус ответа 200, если не возникают какие-либо исключения.
Возвращаемым результатом этой функции - представления будет некий контент. Это может быть файл формата GeoJSON, содержащий значения каким-то образом обработанные и записанные (извлеченные, обновленные, удаленные) в базу данных, а также, помещенные по определенным ключам в самом GeoJSON.
Например, по ключу «объекты» во вложенный список помещается геометрия объекта вместе с ее типом и, по ключу «свойства», - параметры атрибутов пространственных объектов, в данном примере это название инцидента.
{ "context_point_trek": { "type": "FeatureCollection", "crs": { "type": "name", "properties": { "name": "EPSG:4326" } },
"features": [
{ "type": "Feature", "id": 1, "properties": { "name": "Точка: 1" }, "geometry": { "type": "Point", "coordinates": [ 158.839538, 53.572238 ] } },
{ "type": "Feature", "id": 2, "properties": { "name": "Точка: 2" }, "geometry": { "type": "Point", "coordinates": [ 158.83972, 53.572024 ] } }, (и так далее...)
Такой контент в виде переменных передается обратно в html-шаблон, где обрабатывается уже посредствам java-скриптов и стилизованно отображается в окне веб-браузера в виде слоев карты, таблиц, графиков, диаграмм и т.д., совместно с элементами пользовательского интерфейса (рисунок 3). Также такой контент может отдаваться в теле ответа на сформированный POST-запрос, для этого нужно лишь подкорректировать эндпоинт.
Для администрирования приложения, предназначается специальная панель Django, позволяющая создавать и удалять записи из базы данных пользователям, прошедшим процедуры идентификации и аутентификации (рисунок 4).
Для создания пользователя (на начальном этапе) используется команда
python manage.py createsuperuser
В дальнейшем, для регистрации новых пользователей приложения, этот функционал будет расширен.
Подытожить материал этой статьи хочется следующим. Логика веб-ГИС-приложения будет реализовывать инструменты получения спутниковых снимков с открытых ресурсов, например Sentinel Hub, и обработки полученных растров по специальным алгоритмам. Суть этой обработки заключается в комбинировании спектральных каналов спутниковых снимков и расчет спектральных индексов для решения задач на основе технологий машинного обучения: дешифрирования, классификации и кластеризации объектов и явлений местности. В дальнейшем также планируется внедрить в проект на основе этих наработок предобученные нейронные сети. Само собой это материалы для написания еще нескольких статей в дальнейшем. Будьте на связи, кому интересно подписывайтесь.
В общем такой подход позволит реализовать ряд сервисов, размещенных в облаке, доступ к которым будет осуществляться по подписке. Клиенты будут использовать такие сервисы для конструирования собственных приложений, на подобии Notion.
Также планируется, возможность организации целой инфраструктуры (как вы наверно уже поняли, в минимально работоспособном варианте это уже реализовано), когда на основе сервисов можно будет создавать панели мониторинга, например мест скопления твердых бытовых отходов, незаконных застроек, зон пожаров и гарей, затоплений и многого другого. Такие дашборды смогут конструировать сами пользователи на основе предварительно созданного инструментария на стороне фронта (карт, таблиц, графиков, диаграмм и др.). Своего рода nocode-приложения для неподготовленных пользователей, либо с элементами кодирования, для более подготовленных, путем использования нашего API. Кроме того, мы сами сможем обеспечить всю цепочку создания, развертывания и поддержки приложения под более конкретные запросы пользователей.
Еще одним элементом этой инфраструктуры, станет возможность не только мониторить обстановку, но и отдавать распоряжения и контролировать их исполнение различным службам реагирования (рисунок 5), путем реализации дополнительного связанного с базой данных мобильного приложения (Android, IOS, и др. наше приложение платформонезависимо, в этом его прелесть!).
Видеопрезентация полного цикла работы приложения доступна по ссылке.
Автор: dilmah949