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

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

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

2 ответа

Решение

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

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

В принципе, самый разумный способ - сделать стандартный набор плиток и позволить Leaflet показать его. Т.е. производить плитки размером 256х256 для каждого из уровней масштабирования.
Вам не нужны огромные изображения в виде слоев, так как это будет слишком тяжело для браузера. Вы также не хотите изменять размеры в браузере, это приведет к низкому качеству.

К счастью, с помощью ImageMagick создавать плитки довольно просто. Вот как я это делаю.

Решите, сколько уровней масштабирования вы хотите

Сначала определите, сколько уровней масштабирования вы хотите. Это зависит от карты, из моего опыта вам нужно максимум 5-7 уровней масштабирования. Давайте возьмем 5 уровней масштабирования для примера. Чем больше уровней вы создадите, тем выше будут требования к оборудованию. Подход ниже, вероятно, не подходит для более чем 7-8 уровней масштабирования.

Рендеринг или изменение размера исходного изображения

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

  • 256 пиксель на уровне 0
  • 512 пиксель на уровне 1
  • 1024 пиксель на уровне 2
  • 2048 пиксель на уровне 3
  • 4096 пиксель на уровне 4
  • и так далее.

Внимание: результатом этого шага являются огромные изображения. Уровень 5 будет около 10 МБ, уровень 6 около 20 МБ, уровень 7 около 40 МБ. Будьте осторожны, попробуйте открыть эти изображения в "нормальных" инструментах.

Изменение размера нормального изображения с высоким разрешением

Если ваш источник изображения высокого разрешения, просто используйте convert -resize либо с x*256* или же *256*x:

convert images\source.jpg -resize   x256 images\0.jpg
convert images\source.jpg -resize   x512 images\1.jpg
convert images\source.jpg -resize  x1024 images\2.jpg
convert images\source.jpg -resize  x2048 images\3.jpg
convert images\source.jpg -resize  x4096 images\4.jpg
convert images\source.jpg -resize  x8192 images\5.jpg

Если у вас есть несколько увеличенных изображений для разных уровней масштабирования (я думаю, это будет иметь место для сканирования МРТ), выберите исходное изображение с самым близким увеличением.

Работа с уже плиточными изображениями

В некоторых случаях исходные изображения уже нарезаются на плитки. Это типично для "старых" клиентов карт, которые вы хотите ускользнуть. Это пример, плитки называются vk-X-Y.jpg и режутся с некоторым перекрытием. В этом случае вы сначала должны обрезать изображения:

magick data\vk-0-0.jpg  -crop 522x373+0x0 images\t-0-0.jpg
magick data\vk-1-0.jpg  -crop 522x373+0x0 images\t-1-0.jpg
magick data\vk-2-0.jpg  -crop 522x373+0x0 images\t-2-0.jpg
magick data\vk-3-0.jpg  -crop 522x373+0x0 images\t-3-0.jpg
magick data\vk-4-0.jpg  -crop 522x373+0x0 images\t-4-0.jpg
magick data\vk-5-0.jpg  -crop 650x373+0x0 images\t-5-0.jpg
...

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

Затем, когда плитки обрезаны, добавьте их к большому изображению:

magick images\t-0-0.jpg images\t-1-0.jpg images\t-2-0.jpg images\t-3-0.jpg images\t-4-0.jpg images\t-5-0.jpg +append images\t-0.jpg
...
magick images\t-0.jpg images\t-1.jpg images\t-2.jpg images\t-3.jpg images\t-4.jpg images\t-5.jpg images\t-6.jpg images\t-7.jpg images\t-8.jpg images\t-9.jpg images\t-10.jpg -append images\t.jpg

Результатом этой операции обрезки и добавления является большое изображение карты в высоком разрешении. Измените размер к каждому из уровней, как описано выше.

Изменение размера PDF-файлов

При рендеринге PDF я предпочитаю изменять размер, используя density, Чтобы рассчитать плотность на уровень масштабирования (это команда Windows, измените для Linux соответственно):

identify -precision 16 -format "%%[fx:((256/max(w,h))*72)]\n%%[fx:((512/max(w,h))*72)]\n%%[fx:((1024/max(w,h))*72)]\n%%[fx:((2048/max(w,h))*72)]\n%%[fx:((4096/max(w,h))*72)]" source.pdf

Это дает вам что-то вроде:

21.89073634204276
43.78147268408551
87.56294536817103
175.1258907363421
350.2517814726841

Магия (4096/max(w,h))*72 Выражение простое: (целевой размер / исходный размер) * стандартный DPI.

Имея плотности визуализации изображений:

convert -verbose -density 21.89073634204276 source.pdf        images\0.png
convert -verbose -density 43.78147268408551 source.pdf        images\1.png
convert -verbose -density 87.56294536817103 source.pdf        images\2.png
convert -verbose -density 175.1258907363421 source.pdf        images\3.png
convert -verbose -density 350.2517814726841 source.pdf        images\4.png

На высоких уровнях это может занять много времени.

Обрезка изображений уровня в плитках

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

convert -verbose images\0.png -crop 256x256 +adjoin -background white -extent 256x256 -set filename:tile "%%[fx:floor(page.x/256)]_%%[fx:floor(page.y/256)]" +repage "tiles\0_%%[filename:tile].png"
convert -verbose images\1.png -crop 256x256 +adjoin -background white -extent 256x256 -set filename:tile "%%[fx:floor(page.x/256)]_%%[fx:floor(page.y/256)]" +repage "tiles\1_%%[filename:tile].png"
convert -verbose images\2.png -crop 256x256 +adjoin -background white -extent 256x256 -set filename:tile "%%[fx:floor(page.x/256)]_%%[fx:floor(page.y/256)]" +repage "tiles\2_%%[filename:tile].png"
convert -verbose images\3.png -crop 256x256 +adjoin -background white -extent 256x256 -set filename:tile "%%[fx:floor(page.x/256)]_%%[fx:floor(page.y/256)]" +repage "tiles\3_%%[filename:tile].png"
convert -verbose images\4.png -crop 256x256 +adjoin -background white -extent 256x256 -set filename:tile "%%[fx:floor(page.x/256)]_%%[fx:floor(page.y/256)]" +repage "tiles\4_%%[filename:tile].png"
convert -verbose images\5.png -crop 256x256 +adjoin -background white -extent 256x256 -set filename:tile "%%[fx:floor(page.x/256)]_%%[fx:floor(page.y/256)]" +repage "tiles\5_%%[filename:tile].png"

Это производит файлы как:

  • tiles/0_0_0.png
  • tiles/1_0_0.png
  • tiles/1_0_1.png
  • tiles/1_1_0.png
  • tiles/1_1_1.png
  • и т.п.

Это ваш статический предварительно отрендеренный набор плиток размером 256x256.

Настроить листовку

Теперь вам нужно только настроить Leaflet. Предполагая, что файлы плиток находятся в ../tiles каталог относительно HTML-файла, это просто:

L.tileLayer('../tiles/{z}_{x}_{y}.png', {
    maxZoom: 5,
    noWrap: true,                     
    attribution: 'Some Attribution'
}).addTo(map);

Если вы хотите установить правильную начальную точку обзора, увеличьте / переместите туда, куда вы хотите, откройте консоль JavaScript в ваших инструментах разработки и введите:

map.getCenter();
map.getZoom();

Затем используйте напечатанные параметры при инициализации карты:

var map = L.map('map').setView([-26.3525, -65.0390], 3);

Чтобы добавить маркер:

L.marker([-26.3525, -65.0390], {title: "Hi there!"}).addTo(map);

Маркер останется в том же положении, даже когда вы перемещаетесь или масштабируете.


Вот один из проектов в качестве примера:

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

Например, с помощью этой PDF-карты европейских внутренних водных путей (спасибо @lexicore!) Вы можете ввести:

vips dzsave European_inland_waterways_-_2012.pdf[dpi=600] xxx --layout google

и это сделает каталог под названием xxx содержащий все ваши плитки, готовые к загрузке на ваш сервер. Это займет около 15 секунд (в любом случае на этом ноутбуке).

Это быстро и требует мало памяти. Детали немного различаются в зависимости от формата файла, но для многих форматов он может декодировать входные данные, создавать все слои пирамиды и записывать выходные листы, все параллельно, без необходимости загружать все входное изображение в объем памяти. Я регулярно рисую пирамиды размером более 300000 x 300000 пикселей на скромном ноутбуке.

Он может использовать некоторые полезные типы файлов, а также обычные tiff, PNG, JPG и т. Д., Включая такие вещи, как SVG, FITS, DICOM и OpenSlide. Это может сделать пирамиды для глубокого увеличения и увеличения тоже.

Приятной особенностью для хостов Windows является возможность записи набора плиток в zip-файл, а не в файловую систему. Windows довольно медленно создает файлы - с большой пирамидой и небольшими плитками вы можете тратить почти 75% процессорного времени только на создание файла. Напишите вместо этого zip-файл, и вы увидите ускорение в 3 раза:

vips dzsave huge.tif xxx.zip --layout google

Плюс, конечно, zip проще загрузить на сервер.

В руководстве по libvips есть глава, рассказывающая о dzsave и показывающая все опции.

Другие вопросы по тегам