Как сделать мозаичное изображение пирамиды для листовки из негеографического источника
Предположим, у меня есть негеографическое изображение вместо обычной карты. Скажем, например, рентгеновское, МРТ или микроскопическое изображение, и я хотел бы использовать листовку, чтобы я мог увеличивать, уменьшать и размещать маркеры в некоторых заранее определенных точках.
Я читал пример с негеографических карт, но этот случай демонстрирует использование одного изображения вместо мозаики. Я бы предпочел плитки, так как мое изображение будет довольно большим. Есть ли что-то еще, что подойдет для случая, подобного описанному выше, пожалуйста? Я смотрю на растровые корды, но я еще не выяснил, работает ли это для любого растрового файла, это только для простых карт.
2 ответа
Вот мой опыт создания скользких карт из таких источников, как PDF-файлы, изображения с высоким разрешением или нескользкие карты. В любом случае я хотел написать статью об этом, поэтому пусть этот ответ будет наброском статьи, которую еще предстоит написать.
В качестве примера приведу карту европейских внутренних водных путей в формате PDF с векторной графикой и скользкую карту.
В принципе, самый разумный способ - сделать стандартный набор плиток и позволить Leaflet показать его. Т.е. производить плитки размером 256х256 для каждого из уровней масштабирования.
Вам не нужны огромные изображения в виде слоев, так как это будет слишком тяжело для браузера. Вы также не хотите изменять размеры в браузере, это приведет к низкому качеству.
К счастью, с помощью ImageMagick создавать плитки довольно просто. Вот как я это делаю.
Решите, сколько уровней масштабирования вы хотите
Сначала определите, сколько уровней масштабирования вы хотите. Это зависит от карты, из моего опыта вам нужно максимум 5-7 уровней масштабирования. Давайте возьмем 5 уровней масштабирования для примера. Чем больше уровней вы создадите, тем выше будут требования к оборудованию. Подход ниже, вероятно, не подходит для более чем 7-8 уровней масштабирования.
Рендеринг или изменение размера исходного изображения
Затем визуализируйте или измените размер изображения для каждого из уровней масштабирования. Вы должны создать изображения с одним из измерений, равным:
256
пиксель на уровне 0512
пиксель на уровне 11024
пиксель на уровне 22048
пиксель на уровне 34096
пиксель на уровне 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 и показывающая все опции.