Georeferencing растров

Геопривязка (Georeferencing) растров представляет собой процесс сопоставления пикселей изображения с реальными координатами на поверхности Земли. В результате обычное изображение превращается в пространственный слой, который может отображаться совместно с векторными объектами, спутниковыми снимками, картографическими подложками и другими геоданными.

В OpenLayers геопривязанные растры используются для решения различных задач:

  • отображение исторических карт;
  • наложение аэрофотоснимков;
  • работа со сканированными топографическими материалами;
  • отображение инженерных схем;
  • использование спутниковых изображений;
  • сравнение данных различных временных периодов.

Без геопривязки изображение остается обычным графическим файлом, положение которого относительно карты неизвестно.


Основные принципы геопривязки

Для отображения растра на карте необходимо определить:

  1. Координатную систему изображения.
  2. Координаты границ растра.
  3. Положение каждого угла изображения в пространстве.

Чаще всего геопривязанный растр содержит:

  • файл изображения (jpg, png, tif);
  • метаданные геопривязки;
  • информацию о системе координат.

Наиболее распространенные способы хранения геопривязки:

Формат Описание
GeoTIFF Геопривязка встроена в TIFF-файл
World File Отдельный файл (.jgw, .pgw, .tfw)
WMS Растр генерируется сервером
WMTS Тайловый геопривязанный растр
XYZ Tiles Набор тайлов с фиксированными координатами

Геопривязанные изображения через ImageStatic

Самый простой способ размещения геопривязанного изображения в OpenLayers — использование источника ImageStatic.

Ключевым параметром является imageExtent, определяющий пространственные границы изображения.

import Map from 'ol/Map';
import View from 'ol/View';

import ImageLayer from 'ol/layer/Image';
import Static from 'ol/source/ImageStatic';

const imageLayer = new ImageLayer({
  source: new Static({
    url: 'images/map.png',

    imageExtent: [
      418000,
      6152000,
      432000,
      6164000
    ]
  })
});

const map = new Map({
  target: 'map',
  layers: [imageLayer],
  view: new View({
    center: [425000, 6158000],
    zoom: 10
  })
});

Массив imageExtent задается в следующем порядке:

[minX, minY, maxX, maxY]

Где:

  • minX — западная граница;
  • minY — южная граница;
  • maxX — восточная граница;
  • maxY — северная граница.

OpenLayers автоматически растягивает изображение внутри указанного прямоугольника.


Указание системы координат

При работе с геопривязанными изображениями необходимо явно задавать проекцию.

Пример для Web Mercator:

import { get as getProjection } from 'ol/proj';

const imageLayer = new ImageLayer({
  source: new Static({
    url: 'map.png',
    projection: getProjection('EPSG:3857'),
    imageExtent: [
      -1000000,
      5000000,
      -900000,
      5100000
    ]
  })
});

Пример для географических координат:

projection: 'EPSG:4326'

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


Геопривязка исторической карты

Одной из наиболее распространенных задач является наложение исторических карт на современные данные.

Допустим, известны координаты углов старой карты:

Левый нижний угол:
55.7000, 37.5000

Правый верхний угол:
55.9000, 37.8000

Создание слоя:

const historicLayer = new ImageLayer({
  source: new Static({
    url: 'historic-map.jpg',
    projection: 'EPSG:4326',

    imageExtent: [
      37.5,
      55.7,
      37.8,
      55.9
    ]
  })
});

После добавления слоя историческая карта будет совмещена с современной подложкой.


Использование прозрачности

Для сравнения нескольких наборов данных часто применяется регулировка прозрачности.

const rasterLayer = new ImageLayer({
  opacity: 0.6,

  source: new Static({
    url: 'historic-map.jpg',
    projection: 'EPSG:4326',

    imageExtent: [
      37.5,
      55.7,
      37.8,
      55.9
    ]
  })
});

Значения прозрачности:

Значение Результат
0 Полностью прозрачный
0.5 Полупрозрачный
1 Полностью непрозрачный

Отображение нескольких геопривязанных растров

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

const raster1 = new ImageLayer({
  source: new Static({
    url: 'image1.png',
    imageExtent: [
      1000,
      1000,
      3000,
      3000
    ]
  })
});

const raster2 = new ImageLayer({
  source: new Static({
    url: 'image2.png',
    imageExtent: [
      2500,
      2000,
      4500,
      4000
    ]
  })
});

Добавление слоев:

const map = new Map({
  target: 'map',

  layers: [
    raster1,
    raster2
  ]
});

Порядок в массиве определяет порядок отрисовки.


Использование zIndex

Для управления взаимным перекрытием применяется свойство zIndex.

raster1.setZIndex(1);

raster2.setZIndex(10);

Чем выше значение, тем выше слой располагается в стеке отображения.


Геопривязанные изображения поверх OpenStreetMap

Наиболее частый сценарий — отображение растров поверх базовой карты.

import TileLayer from 'ol/layer/Tile';
import OSM from 'ol/source/OSM';

const osmLayer = new TileLayer({
  source: new OSM()
});

const rasterLayer = new ImageLayer({
  opacity: 0.7,

  source: new Static({
    url: 'overlay.png',

    imageExtent: [
      4120000,
      7480000,
      4140000,
      7500000
    ],

    projection: 'EPSG:3857'
  })
});

Создание карты:

const map = new Map({
  target: 'map',

  layers: [
    osmLayer,
    rasterLayer
  ]
});

Такой подход широко используется для наложения тематических данных на базовую картографическую подложку.


Работа с GeoTIFF

Формат GeoTIFF содержит встроенную информацию о пространственном положении изображения.

OpenLayers предоставляет специализированный источник GeoTIFF.

import GeoTIFF from 'ol/source/GeoTIFF';

const layer = new TileLayer({
  source: new GeoTIFF({
    sources: [
      {
        url: 'dem.tif'
      }
    ]
  })
});

Преимущества GeoTIFF:

  • автоматическое чтение геопривязки;
  • хранение координат внутри файла;
  • поддержка многоканальных данных;
  • работа с цифровыми моделями рельефа;
  • поддержка больших наборов растровых данных.

Геопривязка через World File

Многие изображения используют дополнительный файл геопривязки.

Примеры:

map.jpg
map.jgw

или

image.png
image.pgw

World File содержит:

размер пикселя по X
вращение
вращение
размер пикселя по Y
координата X
координата Y

Типичный пример:

1.000000
0.000000
0.000000
-1.000000
500000.000000
6200000.000000

OpenLayers напрямую не читает World File. Обычно координаты извлекаются сервером или внешним инструментом и затем передаются в imageExtent.


Получение extent из размеров изображения

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

Например:

Ширина: 5000 px
Высота: 3000 px

Левый нижний угол:
100000, 200000

Правый верхний угол:
105000, 203000

Extent будет:

[
  100000,
  200000,
  105000,
  203000
]

После этого изображение можно отобразить через ImageStatic.


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

Подход подходит только для изображений, которые:

  • имеют прямоугольную форму;
  • не требуют сложных трансформаций;
  • не содержат локальных деформаций;
  • уже прошли предварительную геопривязку.

Невозможно корректно обработать:

  • искривленные сканы;
  • деформированные исторические карты;
  • снимки с неравномерным масштабом;
  • изображения с ошибками привязки.

Для подобных случаев используются серверные ГИС-инструменты:

  • GDAL;
  • QGIS;
  • GeoServer;
  • MapServer.

Производительность при работе с большими растрами

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

Пример проблемного файла:

20000 × 20000 px

Такой растр может занимать сотни мегабайт памяти после декодирования.

Рекомендуемые методы оптимизации:

Использование тайлов

Вместо одного изображения:

large-image.jpg

используется набор тайлов:

0/0/0.png
0/0/1.png
1/0/0.png
...

Для этого применяются:

  • WMTS;
  • XYZ;
  • TileImage;
  • GeoServer Tile Cache.

Пирамиды масштабов

Создаются версии изображения различного разрешения:

Zoom 0 → 256×256
Zoom 1 → 512×512
Zoom 2 → 1024×1024
...

Загружается только необходимый уровень детализации.

Сжатие изображений

Для фотографий подходит:

JPEG

Для схем и карт:

PNG
WEBP

Контроль видимости геопривязанных растров

Слой можно включать и выключать программно.

rasterLayer.setVisible(false);

Включение:

rasterLayer.setVisible(true);

Проверка состояния:

const visible = rasterLayer.getVisible();

Подобный механизм используется в менеджерах слоев и тематических картах.


Определение границ растра

Любой слой имеет пространственный охват.

Получение extent:

const extent =
  rasterLayer
    .getSource()
    .getImageExtent();

Результат:

[
  minX,
  minY,
  maxX,
  maxY
]

Эти данные могут использоваться для автоматического масштабирования карты.

map.getView().fit(extent);

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


Типичный сценарий работы с геопривязанным изображением

Последовательность действий обычно выглядит следующим образом:

  1. Подготовка изображения в GIS-системе.
  2. Выполнение геопривязки.
  3. Определение координатной системы.
  4. Экспорт в GeoTIFF либо получение пространственных границ.
  5. Создание источника ImageStatic или GeoTIFF.
  6. Добавление слоя на карту.
  7. Настройка прозрачности и порядка отображения.
  8. Совмещение с базовыми картографическими сервисами.
  9. Масштабирование карты по extent растра.
  10. Оптимизация производительности для крупных наборов данных.

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